summaryrefslogtreecommitdiff
path: root/chromium/components/autofill
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/autofill')
-rw-r--r--chromium/components/autofill/DEPS5
-rw-r--r--chromium/components/autofill/OWNERS2
-rw-r--r--chromium/components/autofill/android/BUILD.gn1
-rw-r--r--chromium/components/autofill/android/java/res/values/colors.xml11
-rw-r--r--chromium/components/autofill/android/java/res/values/dimens.xml9
-rw-r--r--chromium/components/autofill/content/browser/BUILD.gn1
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver.cc22
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver.h2
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver_factory.h1
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc27
-rw-r--r--chromium/components/autofill/content/browser/risk/fingerprint.cc5
-rw-r--r--chromium/components/autofill/content/browser/risk/fingerprint.h2
-rw-r--r--chromium/components/autofill/content/common/autofill_agent.mojom2
-rw-r--r--chromium/components/autofill/content/common/autofill_driver.mojom21
-rw-r--r--chromium/components/autofill/content/common/autofill_param_traits_macros.h2
-rw-r--r--chromium/components/autofill/content/common/autofill_types.mojom13
-rw-r--r--chromium/components/autofill/content/common/autofill_types.typemap1
-rw-r--r--chromium/components/autofill/content/common/autofill_types_struct_traits.cc43
-rw-r--r--chromium/components/autofill/content/common/autofill_types_struct_traits.h9
-rw-r--r--chromium/components/autofill/content/renderer/BUILD.gn4
-rw-r--r--chromium/components/autofill/content/renderer/DEPS8
-rw-r--r--chromium/components/autofill/content/renderer/autofill_agent.cc18
-rw-r--r--chromium/components/autofill/content/renderer/autofill_agent.h5
-rw-r--r--chromium/components/autofill/content/renderer/form_autofill_util.cc16
-rw-r--r--chromium/components/autofill/content/renderer/form_cache.h3
-rw-r--r--chromium/components/autofill/content/renderer/page_click_tracker.cc3
-rw-r--r--chromium/components/autofill/content/renderer/password_autofill_agent.cc60
-rw-r--r--chromium/components/autofill/content/renderer/password_autofill_agent.h6
-rw-r--r--chromium/components/autofill/content/renderer/password_form_conversion_utils.cc22
-rw-r--r--chromium/components/autofill/content/renderer/password_form_conversion_utils.h3
-rw-r--r--chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc40
-rw-r--r--chromium/components/autofill/content/renderer/password_generation_agent.cc1
-rw-r--r--chromium/components/autofill/content/renderer/password_generation_agent.h5
-rw-r--r--chromium/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc3
-rw-r--r--chromium/components/autofill/core/browser/BUILD.gn6
-rw-r--r--chromium/components/autofill/core/browser/address_field_unittest.cc69
-rw-r--r--chromium/components/autofill/core/browser/autofill_assistant.cc3
-rw-r--r--chromium/components/autofill/core/browser/autofill_client.h14
-rw-r--r--chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.h4
-rw-r--r--chromium/components/autofill/core/browser/autofill_data_model.h2
-rw-r--r--chromium/components/autofill/core/browser/autofill_data_util.cc1
-rw-r--r--chromium/components/autofill/core/browser/autofill_download_manager.cc4
-rw-r--r--chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc92
-rw-r--r--chromium/components/autofill/core/browser/autofill_experiments.cc110
-rw-r--r--chromium/components/autofill/core/browser/autofill_experiments.h49
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate.cc49
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate.h11
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc25
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager.cc122
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager.h5
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager_unittest.cc350
-rw-r--r--chromium/components/autofill/core/browser/autofill_merge_unittest.cc4
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics.cc26
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics.h16
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics_unittest.cc344
-rw-r--r--chromium/components/autofill/core/browser/autofill_popup_delegate.h3
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile.cc12
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile.h8
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_comparator.cc124
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_comparator_unittest.cc69
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_unittest.cc473
-rw-r--r--chromium/components/autofill/core/browser/autofill_scanner.cc24
-rw-r--r--chromium/components/autofill/core/browser/autofill_scanner.h12
-rw-r--r--chromium/components/autofill/core/browser/autofill_type.cc3
-rw-r--r--chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.cc24
-rw-r--r--chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.h19
-rw-r--r--chromium/components/autofill/core/browser/credit_card.cc22
-rw-r--r--chromium/components/autofill/core/browser/credit_card.h1
-rw-r--r--chromium/components/autofill/core/browser/credit_card_field_unittest.cc171
-rw-r--r--chromium/components/autofill/core/browser/credit_card_unittest.cc53
-rw-r--r--chromium/components/autofill/core/browser/field_types.h6
-rw-r--r--chromium/components/autofill/core/browser/form_field.cc31
-rw-r--r--chromium/components/autofill/core/browser/form_field.h2
-rw-r--r--chromium/components/autofill/core/browser/form_field_unittest.cc29
-rw-r--r--chromium/components/autofill/core/browser/form_structure.cc60
-rw-r--r--chromium/components/autofill/core/browser/form_structure.h20
-rw-r--r--chromium/components/autofill/core/browser/legal_message_line.h4
-rw-r--r--chromium/components/autofill/core/browser/name_field_unittest.cc104
-rw-r--r--chromium/components/autofill/core/browser/password_generator.cc2
-rw-r--r--chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc1
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_client.cc2
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager.cc117
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager.h32
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager_unittest.cc303
-rw-r--r--chromium/components/autofill/core/browser/phone_field_unittest.cc67
-rw-r--r--chromium/components/autofill/core/browser/popup_item_ids.h4
-rw-r--r--chromium/components/autofill/core/browser/proto/BUILD.gn1
-rw-r--r--chromium/components/autofill/core/browser/proto/autofill_sync.proto17
-rw-r--r--chromium/components/autofill/core/browser/suggestion.cc12
-rw-r--r--chromium/components/autofill/core/browser/suggestion.h1
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_client.cc11
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_client.h15
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_external_delegate.h2
-rw-r--r--chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl.cc42
-rw-r--r--chromium/components/autofill/core/browser/ui/card_unmask_prompt_view.h2
-rw-r--r--chromium/components/autofill/core/browser/validation.cc25
-rw-r--r--chromium/components/autofill/core/browser/validation.h8
-rw-r--r--chromium/components/autofill/core/browser/validation_unittest.cc58
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc477
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h95
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc524
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_syncable_service.cc2
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_data_type_controller.cc22
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_data_type_controller.h16
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_data_type_controller_unittest.cc1
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_entry.cc6
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_entry.h2
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_metadata_change_list.cc75
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_metadata_change_list.h55
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.cc25
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h17
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table.cc330
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table.h73
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc126
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc197
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h18
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc773
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc85
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h28
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service_unittest.cc165
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata.h14
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc31
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h20
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc22
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h6
-rw-r--r--chromium/components/autofill/core/common/autofill_regexes.cc8
-rw-r--r--chromium/components/autofill/core/common/password_form.cc5
-rw-r--r--chromium/components/autofill/core/common/password_form.h7
-rw-r--r--chromium/components/autofill/core/common/password_form_fill_data.cc4
-rw-r--r--chromium/components/autofill/core/common/save_password_progress_logger.cc14
-rw-r--r--chromium/components/autofill/core/common/save_password_progress_logger.h6
-rw-r--r--chromium/components/autofill/ios/browser/BUILD.gn1
-rw-r--r--chromium/components/autofill/ios/browser/autofill_driver_ios.h2
-rw-r--r--chromium/components/autofill/ios/browser/form_suggestion.h2
-rw-r--r--chromium/components/autofill/ios/browser/form_suggestion.mm2
135 files changed, 5061 insertions, 1873 deletions
diff --git a/chromium/components/autofill/DEPS b/chromium/components/autofill/DEPS
index bed4f0afd3c..6b6ca5cf0be 100644
--- a/chromium/components/autofill/DEPS
+++ b/chromium/components/autofill/DEPS
@@ -4,9 +4,14 @@ include_rules = [
"+grit", # For generated headers
"+jni",
"+net",
+ "+third_party/skia",
"+third_party/zlib/google",
"+ui",
+
# Autofill is a layered component; subdirectories must explicitly introduce
# the ability to use the content layer as appropriate.
"-components/autofill/content",
+
+ # This directory contains build flags and does not pull all of PPAPI in.
+ "+ppapi/features",
]
diff --git a/chromium/components/autofill/OWNERS b/chromium/components/autofill/OWNERS
index be52fd5be44..d52021494e9 100644
--- a/chromium/components/autofill/OWNERS
+++ b/chromium/components/autofill/OWNERS
@@ -1,6 +1,6 @@
estade@chromium.org
-isherman@chromium.org
mathp@chromium.org
+sebsg@chromium.org
vabr@chromium.org
# Owners for password autofill/generation only.
diff --git a/chromium/components/autofill/android/BUILD.gn b/chromium/components/autofill/android/BUILD.gn
index 54889a8605d..dab9ec22618 100644
--- a/chromium/components/autofill/android/BUILD.gn
+++ b/chromium/components/autofill/android/BUILD.gn
@@ -13,6 +13,7 @@ android_library("autofill_java") {
deps = [
":autofill_java_resources",
"//base:base_java",
+ "//third_party/android_tools:android_support_v7_appcompat_java",
"//ui/android:ui_java",
]
java_files = [
diff --git a/chromium/components/autofill/android/java/res/values/colors.xml b/chromium/components/autofill/android/java/res/values/colors.xml
new file mode 100644
index 00000000000..8b10dd3af7b
--- /dev/null
+++ b/chromium/components/autofill/android/java/res/values/colors.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2016 The Chromium Authors. All rights reserved.
+
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+-->
+<resources>
+ <!-- Text colors of warning messages for credit card and password forms. -->
+ <color name="http_bad_warning_message_text">#C53929</color>
+ <color name="insecure_context_payment_disabled_message_text">#646464</color>
+</resources>
diff --git a/chromium/components/autofill/android/java/res/values/dimens.xml b/chromium/components/autofill/android/java/res/values/dimens.xml
index ee949e47a0f..82d8c5e07c2 100644
--- a/chromium/components/autofill/android/java/res/values/dimens.xml
+++ b/chromium/components/autofill/android/java/res/values/dimens.xml
@@ -15,4 +15,13 @@
<dimen name="keyboard_accessory_height">48dp</dimen>
<dimen name="keyboard_accessory_padding">8dp</dimen>
<dimen name="keyboard_accessory_text_size">14sp</dimen>
+
+ <!--
+ Larger label and icon sizes for Form-Not-Secure experiment
+ (warning messages on credit card and password forms when users
+ are on HTTP sites).
+ -->
+ <dimen name="dropdown_item_larger_sublabel_font_size">18sp</dimen>
+ <dimen name="dropdown_large_icon_size">24dp</dimen>
+ <dimen name="dropdown_large_icon_margin">10dp</dimen>
</resources>
diff --git a/chromium/components/autofill/content/browser/BUILD.gn b/chromium/components/autofill/content/browser/BUILD.gn
index d8819209383..88576886284 100644
--- a/chromium/components/autofill/content/browser/BUILD.gn
+++ b/chromium/components/autofill/content/browser/BUILD.gn
@@ -37,6 +37,7 @@ static_library("browser") {
"//gpu/config",
"//mojo/common:common_base",
"//net",
+ "//ppapi/features",
"//services/service_manager/public/cpp",
"//sql",
"//third_party/icu",
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver.cc b/chromium/components/autofill/content/browser/content_autofill_driver.cc
index c0648785994..8eb8de071ae 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver.cc
+++ b/chromium/components/autofill/content/browser/content_autofill_driver.cc
@@ -159,15 +159,15 @@ void ContentAutofillDriver::PopupHidden() {
gfx::RectF ContentAutofillDriver::TransformBoundingBoxToViewportCoordinates(
const gfx::RectF& bounding_box) {
- gfx::Point orig_point(bounding_box.x(), bounding_box.y());
- gfx::Point transformed_point;
- transformed_point =
- render_frame_host_->GetView()->TransformPointToRootCoordSpace(orig_point);
+ content::RenderWidgetHostView* view = render_frame_host_->GetView();
+ if (!view)
+ return bounding_box;
- gfx::RectF new_box;
- new_box.SetRect(transformed_point.x(), transformed_point.y(),
- bounding_box.width(), bounding_box.height());
- return new_box;
+ gfx::Point orig_point(bounding_box.x(), bounding_box.y());
+ gfx::Point transformed_point =
+ view->TransformPointToRootCoordSpace(orig_point);
+ return gfx::RectF(transformed_point.x(), transformed_point.y(),
+ bounding_box.width(), bounding_box.height());
}
void ContentAutofillDriver::DidInteractWithCreditCardForm() {
@@ -216,10 +216,6 @@ void ContentAutofillDriver::HidePopup() {
autofill_manager_->OnHidePopup();
}
-void ContentAutofillDriver::PingAck() {
- autofill_external_delegate_.OnPingAck();
-}
-
void ContentAutofillDriver::FocusNoLongerOnForm() {
autofill_manager_->OnFocusNoLongerOnForm();
}
@@ -264,7 +260,7 @@ const mojom::AutofillAgentPtr& ContentAutofillDriver::GetAutofillAgent() {
// Here is a lazy binding, and will not reconnect after connection error.
if (!autofill_agent_) {
render_frame_host_->GetRemoteInterfaces()->GetInterface(
- mojo::GetProxy(&autofill_agent_));
+ mojo::MakeRequest(&autofill_agent_));
}
return autofill_agent_;
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver.h b/chromium/components/autofill/content/browser/content_autofill_driver.h
index e5740f57624..2fd226efc69 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver.h
+++ b/chromium/components/autofill/content/browser/content_autofill_driver.h
@@ -17,7 +17,6 @@
#include "mojo/public/cpp/bindings/binding.h"
namespace content {
-class BrowserContext;
class RenderFrameHost;
struct FrameNavigateParams;
struct LoadCommittedDetails;
@@ -84,7 +83,6 @@ class ContentAutofillDriver : public AutofillDriver,
const FormFieldData& field,
const gfx::RectF& bounding_box) override;
void HidePopup() override;
- void PingAck() override;
void FocusNoLongerOnForm() override;
void DidFillAutofillFormData(const FormData& form,
base::TimeTicks timestamp) override;
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver_factory.h b/chromium/components/autofill/content/browser/content_autofill_driver_factory.h
index 8bec3e5a051..2781ee4c1cf 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver_factory.h
+++ b/chromium/components/autofill/content/browser/content_autofill_driver_factory.h
@@ -20,7 +20,6 @@ class RenderFrameHost;
namespace autofill {
-class AutofillDriver;
class ContentAutofillDriver;
// Manages lifetime of ContentAutofillDriver. One Factory per WebContents
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc b/chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc
index 82dd2f6254a..3dbbd572f3c 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc
+++ b/chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc
@@ -137,6 +137,9 @@ class FakeAutofillAgent : public mojom::AutofillAgent {
return true;
}
+ // Mocked mojom::AutofillAgent methods:
+ MOCK_METHOD0(FirstUserGestureObservedInTab, void());
+
private:
void CallDone() {
if (!quit_closure_.is_null()) {
@@ -145,9 +148,7 @@ class FakeAutofillAgent : public mojom::AutofillAgent {
}
}
- // mojom::AutofillAgent methods:
- void FirstUserGestureObservedInTab() override {}
-
+ // mojom::AutofillAgent:
void FillForm(int32_t id, const FormData& form) override {
fill_form_id_ = id;
fill_form_form_ = form;
@@ -236,6 +237,11 @@ class MockAutofillManager : public AutofillManager {
MOCK_METHOD0(Reset, void());
};
+class MockAutofillClient : public TestAutofillClient {
+ public:
+ MOCK_METHOD0(OnFirstUserGestureObserved, void());
+};
+
class TestContentAutofillDriver : public ContentAutofillDriver {
public:
TestContentAutofillDriver(content::RenderFrameHost* rfh,
@@ -259,7 +265,7 @@ class ContentAutofillDriverTest : public content::RenderViewHostTestHarness {
void SetUp() override {
content::RenderViewHostTestHarness::SetUp();
- test_autofill_client_.reset(new TestAutofillClient());
+ test_autofill_client_.reset(new MockAutofillClient());
driver_.reset(new TestContentAutofillDriver(web_contents()->GetMainFrame(),
test_autofill_client_.get()));
@@ -279,7 +285,7 @@ class ContentAutofillDriverTest : public content::RenderViewHostTestHarness {
}
protected:
- std::unique_ptr<TestAutofillClient> test_autofill_client_;
+ std::unique_ptr<MockAutofillClient> test_autofill_client_;
std::unique_ptr<TestContentAutofillDriver> driver_;
FakeAutofillAgent fake_agent_;
@@ -479,4 +485,15 @@ TEST_F(ContentAutofillDriverTest, CreditCardFormInteractionOnHTTPS) {
content::SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP));
}
+TEST_F(ContentAutofillDriverTest, NotifyFirstUserGestureObservedInTab) {
+ driver_->NotifyFirstUserGestureObservedInTab();
+ EXPECT_CALL(fake_agent_, FirstUserGestureObservedInTab());
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(ContentAutofillDriverTest, FirstUserGestureObserved) {
+ EXPECT_CALL(*test_autofill_client_, OnFirstUserGestureObserved());
+ driver_->FirstUserGestureObserved();
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/content/browser/risk/fingerprint.cc b/chromium/components/autofill/content/browser/risk/fingerprint.cc
index acac2f15ad8..09041403ccc 100644
--- a/chromium/components/autofill/content/browser/risk/fingerprint.cc
+++ b/chromium/components/autofill/content/browser/risk/fingerprint.cc
@@ -41,6 +41,7 @@
#include "device/geolocation/geolocation_provider.h"
#include "device/geolocation/geoposition.h"
#include "gpu/config/gpu_info.h"
+#include "ppapi/features/features.h"
#include "third_party/WebKit/public/platform/WebRect.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
@@ -293,7 +294,7 @@ FingerprintDataLoader::FingerprintDataLoader(
gpu_data_manager_->RequestCompleteGpuInfoIfNeeded();
}
-#if defined(ENABLE_PLUGINS)
+#if BUILDFLAG(ENABLE_PLUGINS)
// Load plugin data.
content::PluginService::GetInstance()->GetPlugins(
base::Bind(&FingerprintDataLoader::OnGotPlugins,
@@ -325,7 +326,7 @@ void FingerprintDataLoader::OnGpuInfoUpdate() {
void FingerprintDataLoader::OnGotFonts(std::unique_ptr<base::ListValue> fonts) {
DCHECK(!fonts_);
- fonts_.reset(fonts.release());
+ fonts_ = std::move(fonts);
MaybeFillFingerprint();
}
diff --git a/chromium/components/autofill/content/browser/risk/fingerprint.h b/chromium/components/autofill/content/browser/risk/fingerprint.h
index ae1b7857a7a..870743d1a55 100644
--- a/chromium/components/autofill/content/browser/risk/fingerprint.h
+++ b/chromium/components/autofill/content/browser/risk/fingerprint.h
@@ -20,8 +20,6 @@
#include "base/callback_forward.h"
#include "components/autofill/core/browser/autofill_client.h"
-class PrefService;
-
namespace base {
class Time;
}
diff --git a/chromium/components/autofill/content/common/autofill_agent.mojom b/chromium/components/autofill/content/common/autofill_agent.mojom
index a2f40a9da67..7870cafc8b4 100644
--- a/chromium/components/autofill/content/common/autofill_agent.mojom
+++ b/chromium/components/autofill/content/common/autofill_agent.mojom
@@ -5,7 +5,7 @@
module autofill.mojom;
import "components/autofill/content/common/autofill_types.mojom";
-import "mojo/common/common_custom_types.mojom";
+import "mojo/common/string16.mojom";
// There is one instance of this interface per render frame in the render
// process.
diff --git a/chromium/components/autofill/content/common/autofill_driver.mojom b/chromium/components/autofill/content/common/autofill_driver.mojom
index 51278195f4b..ce08780300c 100644
--- a/chromium/components/autofill/content/common/autofill_driver.mojom
+++ b/chromium/components/autofill/content/common/autofill_driver.mojom
@@ -5,7 +5,9 @@
module autofill.mojom;
import "components/autofill/content/common/autofill_types.mojom";
-import "mojo/common/common_custom_types.mojom";
+import "mojo/common/string16.mojom";
+import "mojo/common/text_direction.mojom";
+import "mojo/common/time.mojom";
import "ui/gfx/geometry/mojo/geometry.mojom";
// There is one instance of this interface per render frame host in the browser
@@ -39,9 +41,6 @@ interface AutofillDriver {
// Instructs the browser to hide the Autofill popup if it is open.
HidePopup();
- // Sent immediately after the renderer receives a ping IPC.
- PingAck();
-
// Sent when the current form is no longer focused.
FocusNoLongerOnForm();
@@ -62,11 +61,6 @@ interface AutofillDriver {
// There is one instance of this interface per render frame host in the browser
// process.
interface PasswordManagerDriver {
- // A ping to the browser that PasswordAutofillAgent was constructed. As a
- // consequence, the browser sends SetLoggingState with the current
- // state of the logging activity.
- PasswordAutofillAgentConstructed();
-
// Notification that password forms have been seen that are candidates for
// filling/submitting by the password manager.
PasswordFormsParsed(array<PasswordForm> forms);
@@ -93,10 +87,17 @@ interface PasswordManagerDriver {
// Instructs the browser to show a popup with suggestions filled from data
// associated with |key|. The popup will use |text_direction| for displaying
// text.
- ShowPasswordSuggestions(int32 key, TextDirection text_direction,
+ ShowPasswordSuggestions(int32 key,
+ mojo.common.mojom.TextDirection text_direction,
mojo.common.mojom.String16 typed_username,
int32 options, gfx.mojom.RectF bounds);
+ // Instructs the browser to show a popup with a warning that the form
+ // is not secure. The popup will use |text_direction| for displaying
+ // text. This popup is shown when a password form on a non-secure page is
+ // autofilled on page load.
+ ShowNotSecureWarning(mojo.common.mojom.TextDirection text_direction,
+ gfx.mojom.RectF bounds);
// Instructs the browser to presave the form with generated password.
PresaveGeneratedPassword(PasswordForm password_form);
diff --git a/chromium/components/autofill/content/common/autofill_param_traits_macros.h b/chromium/components/autofill/content/common/autofill_param_traits_macros.h
index 1bced6ec0ab..edd3fcb8c05 100644
--- a/chromium/components/autofill/content/common/autofill_param_traits_macros.h
+++ b/chromium/components/autofill/content/common/autofill_param_traits_macros.h
@@ -21,7 +21,7 @@ IPC_ENUM_TRAITS_MAX_VALUE(autofill::FormFieldData::RoleAttribute,
autofill::FormFieldData::ROLE_ATTRIBUTE_OTHER)
IPC_ENUM_TRAITS_MAX_VALUE(base::i18n::TextDirection,
- base::i18n::TEXT_DIRECTION_NUM_DIRECTIONS - 1)
+ base::i18n::TEXT_DIRECTION_MAX)
IPC_STRUCT_TRAITS_BEGIN(autofill::FormFieldData)
IPC_STRUCT_TRAITS_MEMBER(label)
diff --git a/chromium/components/autofill/content/common/autofill_types.mojom b/chromium/components/autofill/content/common/autofill_types.mojom
index 91905f2d84d..ec56870ac77 100644
--- a/chromium/components/autofill/content/common/autofill_types.mojom
+++ b/chromium/components/autofill/content/common/autofill_types.mojom
@@ -4,7 +4,8 @@
module autofill.mojom;
-import "mojo/common/common_custom_types.mojom";
+import "mojo/common/text_direction.mojom";
+import "mojo/common/time.mojom";
import "url/mojo/origin.mojom";
import "url/mojo/url.mojom";
@@ -21,14 +22,6 @@ enum RoleAttribute {
ROLE_ATTRIBUTE_OTHER
};
-// base::i18n::TextDirection
-enum TextDirection {
- UNKNOWN_DIRECTION = 0,
- RIGHT_TO_LEFT = 1,
- LEFT_TO_RIGHT = 2,
- TEXT_DIRECTION_NUM_DIRECTIONS = 3
-};
-
// autofill::PasswordForm::GenerationUploadStatus
enum GenerationUploadStatus {
NO_SIGNAL_SENT,
@@ -84,7 +77,7 @@ struct FormFieldData {
bool is_focusable;
bool should_autocomplete;
RoleAttribute role;
- TextDirection text_direction;
+ mojo.common.mojom.TextDirection text_direction;
array<string> option_values;
array<string> option_contents;
diff --git a/chromium/components/autofill/content/common/autofill_types.typemap b/chromium/components/autofill/content/common/autofill_types.typemap
index 4511910b355..7072d03c967 100644
--- a/chromium/components/autofill/content/common/autofill_types.typemap
+++ b/chromium/components/autofill/content/common/autofill_types.typemap
@@ -42,6 +42,5 @@ type_mappings = [
"autofill.mojom.PasswordFormScheme=autofill::PasswordForm::Scheme",
"autofill.mojom.PasswordFormType=autofill::PasswordForm::Type",
"autofill.mojom.RoleAttribute=autofill::FormFieldData::RoleAttribute",
- "autofill.mojom.TextDirection=base::i18n::TextDirection",
"autofill.mojom.UsernamesCollectionKey=autofill::UsernamesCollectionKey",
]
diff --git a/chromium/components/autofill/content/common/autofill_types_struct_traits.cc b/chromium/components/autofill/content/common/autofill_types_struct_traits.cc
index 81e2fb478c6..c536b4abd48 100644
--- a/chromium/components/autofill/content/common/autofill_types_struct_traits.cc
+++ b/chromium/components/autofill/content/common/autofill_types_struct_traits.cc
@@ -6,6 +6,7 @@
#include "base/i18n/rtl.h"
#include "ipc/ipc_message_utils.h"
+#include "mojo/common/common_custom_types_struct_traits.h"
#include "url/mojo/origin_struct_traits.h"
#include "url/mojo/url_gurl_struct_traits.h"
@@ -83,48 +84,6 @@ bool EnumTraits<mojom::RoleAttribute, FormFieldData::RoleAttribute>::FromMojom(
}
// static
-mojom::TextDirection
-EnumTraits<mojom::TextDirection, base::i18n::TextDirection>::ToMojom(
- base::i18n::TextDirection input) {
- switch (input) {
- case base::i18n::TextDirection::UNKNOWN_DIRECTION:
- return mojom::TextDirection::UNKNOWN_DIRECTION;
- case base::i18n::TextDirection::RIGHT_TO_LEFT:
- return mojom::TextDirection::RIGHT_TO_LEFT;
- case base::i18n::TextDirection::LEFT_TO_RIGHT:
- return mojom::TextDirection::LEFT_TO_RIGHT;
- case base::i18n::TextDirection::TEXT_DIRECTION_NUM_DIRECTIONS:
- return mojom::TextDirection::TEXT_DIRECTION_NUM_DIRECTIONS;
- }
-
- NOTREACHED();
- return mojom::TextDirection::UNKNOWN_DIRECTION;
-}
-
-// static
-bool EnumTraits<mojom::TextDirection, base::i18n::TextDirection>::FromMojom(
- mojom::TextDirection input,
- base::i18n::TextDirection* output) {
- switch (input) {
- case mojom::TextDirection::UNKNOWN_DIRECTION:
- *output = base::i18n::TextDirection::UNKNOWN_DIRECTION;
- return true;
- case mojom::TextDirection::RIGHT_TO_LEFT:
- *output = base::i18n::TextDirection::RIGHT_TO_LEFT;
- return true;
- case mojom::TextDirection::LEFT_TO_RIGHT:
- *output = base::i18n::TextDirection::LEFT_TO_RIGHT;
- return true;
- case mojom::TextDirection::TEXT_DIRECTION_NUM_DIRECTIONS:
- *output = base::i18n::TextDirection::TEXT_DIRECTION_NUM_DIRECTIONS;
- return true;
- }
-
- NOTREACHED();
- return false;
-}
-
-// static
mojom::GenerationUploadStatus EnumTraits<mojom::GenerationUploadStatus,
PasswordForm::GenerationUploadStatus>::
ToMojom(PasswordForm::GenerationUploadStatus input) {
diff --git a/chromium/components/autofill/content/common/autofill_types_struct_traits.h b/chromium/components/autofill/content/common/autofill_types_struct_traits.h
index 8e2f74031ab..c623aa50b30 100644
--- a/chromium/components/autofill/content/common/autofill_types_struct_traits.h
+++ b/chromium/components/autofill/content/common/autofill_types_struct_traits.h
@@ -7,6 +7,7 @@
#include <utility>
+#include "base/i18n/rtl.h"
#include "base/strings/string16.h"
#include "components/autofill/content/common/autofill_types.mojom.h"
#include "components/autofill/core/common/form_data.h"
@@ -40,14 +41,6 @@ struct EnumTraits<autofill::mojom::RoleAttribute,
};
template <>
-struct EnumTraits<autofill::mojom::TextDirection, base::i18n::TextDirection> {
- static autofill::mojom::TextDirection ToMojom(
- base::i18n::TextDirection input);
- static bool FromMojom(autofill::mojom::TextDirection input,
- base::i18n::TextDirection* output);
-};
-
-template <>
struct EnumTraits<autofill::mojom::GenerationUploadStatus,
autofill::PasswordForm::GenerationUploadStatus> {
static autofill::mojom::GenerationUploadStatus ToMojom(
diff --git a/chromium/components/autofill/content/renderer/BUILD.gn b/chromium/components/autofill/content/renderer/BUILD.gn
index 5dd8086ea43..2ddd7715dc2 100644
--- a/chromium/components/autofill/content/renderer/BUILD.gn
+++ b/chromium/components/autofill/content/renderer/BUILD.gn
@@ -30,6 +30,10 @@ static_library("renderer") {
"//base:i18n",
"//components/autofill/content/common:mojo_interfaces",
"//components/autofill/core/common",
+
+ # TODO(elawrence): remove security_state/core when the Form-Not-Secure
+ # feature is fully launched. https://crbug.com/677295
+ "//components/security_state/core",
"//components/strings",
"//content/public/common",
"//content/public/renderer",
diff --git a/chromium/components/autofill/content/renderer/DEPS b/chromium/components/autofill/content/renderer/DEPS
index 0885896b9c9..83ce085fa2a 100644
--- a/chromium/components/autofill/content/renderer/DEPS
+++ b/chromium/components/autofill/content/renderer/DEPS
@@ -3,3 +3,11 @@ include_rules = [
"+content/public/renderer",
"+third_party/re2",
]
+
+specific_include_rules = {
+ # TODO(elawrence): remove this when the Form-Not-Secure feature is fully
+ # launched. https://crbug.com/677295
+ "password_autofill_agent\.cc" : [
+ "+components/security_state/core",
+ ],
+}
diff --git a/chromium/components/autofill/content/renderer/autofill_agent.cc b/chromium/components/autofill/content/renderer/autofill_agent.cc
index 49cf6727451..0aa8a423a75 100644
--- a/chromium/components/autofill/content/renderer/autofill_agent.cc
+++ b/chromium/components/autofill/content/renderer/autofill_agent.cc
@@ -300,10 +300,6 @@ void AutofillAgent::FocusChangeComplete() {
}
}
-void AutofillAgent::setIgnoreTextChanges(bool ignore) {
- ignore_text_changes_ = ignore;
-}
-
void AutofillAgent::FormControlElementClicked(
const WebFormControlElement& element,
bool was_focused) {
@@ -487,10 +483,6 @@ void AutofillAgent::PreviewForm(int32_t id, const FormData& form) {
GetAutofillDriver()->DidPreviewAutofillFormData();
}
-void AutofillAgent::OnPing() {
- GetAutofillDriver()->PingAck();
-}
-
void AutofillAgent::FieldTypePredictionsAvailable(
const std::vector<FormDataPredictions>& forms) {
for (const auto& form : forms) {
@@ -577,6 +569,14 @@ void AutofillAgent::ShowInitialPasswordAccountSuggestions(
ShowSuggestions(element, options);
}
+void AutofillAgent::ShowNotSecureWarning(
+ const blink::WebInputElement& element) {
+ if (is_generation_popup_possibly_visible_)
+ return;
+ password_autofill_agent_->ShowNotSecureWarning(element);
+ is_popup_possibly_visible_ = true;
+}
+
void AutofillAgent::OnSamePageNavigationCompleted() {
if (last_interacted_form_.isNull()) {
// If no last interacted form is available (i.e., there is no form tag),
@@ -783,7 +783,7 @@ void AutofillAgent::ajaxSucceeded() {
const mojom::AutofillDriverPtr& AutofillAgent::GetAutofillDriver() {
if (!autofill_driver_) {
render_frame()->GetRemoteInterfaces()->GetInterface(
- mojo::GetProxy(&autofill_driver_));
+ mojo::MakeRequest(&autofill_driver_));
}
return autofill_driver_;
diff --git a/chromium/components/autofill/content/renderer/autofill_agent.h b/chromium/components/autofill/content/renderer/autofill_agent.h
index e464af9575b..698e5c9fc70 100644
--- a/chromium/components/autofill/content/renderer/autofill_agent.h
+++ b/chromium/components/autofill/content/renderer/autofill_agent.h
@@ -83,6 +83,8 @@ class AutofillAgent : public content::RenderFrameObserver,
int32_t key,
const PasswordFormFillData& form_data) override;
+ void ShowNotSecureWarning(const blink::WebInputElement& element);
+
protected:
// blink::WebAutofillClient:
void didAssociateFormControlsDynamically() override;
@@ -182,14 +184,11 @@ class AutofillAgent : public content::RenderFrameObserver,
void textFieldDidReceiveKeyDown(
const blink::WebInputElement& element,
const blink::WebKeyboardEvent& event) override;
- void setIgnoreTextChanges(bool ignore) override;
void openTextDataListChooser(const blink::WebInputElement& element) override;
void dataListOptionsChanged(const blink::WebInputElement& element) override;
void firstUserGestureObserved() override;
void ajaxSucceeded() override;
- void OnPing();
-
// Called when a same-page navigation is detected.
void OnSamePageNavigationCompleted();
// Helper method which collects unowned elements (i.e., those not inside a
diff --git a/chromium/components/autofill/content/renderer/form_autofill_util.cc b/chromium/components/autofill/content/renderer/form_autofill_util.cc
index 2c5dc0975a7..8d690c2446a 100644
--- a/chromium/components/autofill/content/renderer/form_autofill_util.cc
+++ b/chromium/components/autofill/content/renderer/form_autofill_util.cc
@@ -5,11 +5,13 @@
#include "components/autofill/content/renderer/form_autofill_util.h"
#include <map>
+#include <memory>
#include <set>
+#include <vector>
#include "base/command_line.h"
#include "base/logging.h"
-#include "base/memory/scoped_vector.h"
+#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@@ -963,7 +965,7 @@ bool ExtractFieldsFromControlElements(
const WebVector<WebFormControlElement>& control_elements,
const FieldValueAndPropertiesMaskMap* field_value_and_properties_map,
ExtractMask extract_mask,
- ScopedVector<FormFieldData>* form_fields,
+ std::vector<std::unique_ptr<FormFieldData>>* form_fields,
std::vector<bool>* fields_extracted,
std::map<WebFormControlElement, FormFieldData*>* element_map) {
DCHECK(form_fields->empty());
@@ -981,7 +983,7 @@ bool ExtractFieldsFromControlElements(
WebFormControlElementToFormField(control_element,
field_value_and_properties_map,
extract_mask, form_field);
- form_fields->push_back(form_field);
+ form_fields->push_back(base::WrapUnique(form_field));
(*element_map)[control_element] = form_field;
(*fields_extracted)[i] = true;
@@ -1083,7 +1085,7 @@ bool FormOrFieldsetsToFormData(
// The extracted FormFields. We use pointers so we can store them in
// |element_map|.
- ScopedVector<FormFieldData> form_fields;
+ std::vector<std::unique_ptr<FormFieldData>> form_fields;
// A vector of bools that indicate whether each field in the form meets the
// requirements and thus will be in the resulting |form|.
@@ -1152,8 +1154,8 @@ bool FormOrFieldsetsToFormData(
}
// Copy the created FormFields into the resulting FormData object.
- for (const auto* iter : form_fields)
- form->fields.push_back(*iter);
+ for (const auto& field : form_fields)
+ form->fields.push_back(*field);
return true;
}
@@ -1617,6 +1619,8 @@ bool UnownedPasswordFormElementsAndFieldSetsToFormData(
bool FindFormAndFieldForFormControlElement(const WebFormControlElement& element,
FormData* form,
FormFieldData* field) {
+ DCHECK(!element.isNull());
+
if (!IsAutofillableElement(element))
return false;
diff --git a/chromium/components/autofill/content/renderer/form_cache.h b/chromium/components/autofill/content/renderer/form_cache.h
index 78bef2e6447..4afb3a66f9e 100644
--- a/chromium/components/autofill/content/renderer/form_cache.h
+++ b/chromium/components/autofill/content/renderer/form_cache.h
@@ -16,9 +16,6 @@
#include "components/autofill/core/common/form_data.h"
namespace blink {
-class WebDocument;
-class WebElement;
-class WebElementCollection;
class WebFormControlElement;
class WebFrame;
class WebInputElement;
diff --git a/chromium/components/autofill/content/renderer/page_click_tracker.cc b/chromium/components/autofill/content/renderer/page_click_tracker.cc
index da70ec2e851..0af746045e8 100644
--- a/chromium/components/autofill/content/renderer/page_click_tracker.cc
+++ b/chromium/components/autofill/content/renderer/page_click_tracker.cc
@@ -10,7 +10,6 @@
#include "components/autofill/core/common/autofill_util.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
-#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "third_party/WebKit/public/platform/WebPoint.h"
#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/WebKit/public/web/WebDocument.h"
@@ -25,8 +24,6 @@ using blink::WebElement;
using blink::WebFormControlElement;
using blink::WebGestureEvent;
using blink::WebInputElement;
-using blink::WebInputEvent;
-using blink::WebMouseEvent;
using blink::WebNode;
using blink::WebPoint;
using blink::WebSize;
diff --git a/chromium/components/autofill/content/renderer/password_autofill_agent.cc b/chromium/components/autofill/content/renderer/password_autofill_agent.cc
index 25edf2c8888..b17f17f0de1 100644
--- a/chromium/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/chromium/components/autofill/content/renderer/password_autofill_agent.cc
@@ -9,16 +9,17 @@
#include <memory>
#include <string>
#include <utility>
+#include <vector>
#include "base/bind.h"
#include "base/i18n/case_conversion.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/ptr_util.h"
-#include "base/memory/scoped_vector.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "components/autofill/content/renderer/form_autofill_util.h"
#include "components/autofill/content/renderer/password_form_conversion_utils.h"
@@ -27,6 +28,8 @@
#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/password_form_fill_data.h"
+#include "components/security_state/core/security_state.h"
+#include "content/public/common/origin_util.h"
#include "content/public/renderer/document_state.h"
#include "content/public/renderer/navigation_state.h"
#include "content/public/renderer/render_frame.h"
@@ -177,7 +180,8 @@ bool FindFormInputElement(
// fields.
const blink::WebInputElement input_element =
control_element.toConst<blink::WebInputElement>();
- if (input_element.isPasswordField() != is_password_field)
+ if (!input_element.isTextField() ||
+ input_element.isPasswordField() != is_password_field)
continue;
// For change password form with ambiguous or empty names keep only the
@@ -243,8 +247,6 @@ void FindFormElements(content::RenderFrame* render_frame,
DCHECK(results);
blink::WebDocument doc = render_frame->GetWebFrame()->document();
- if (!doc.isHTMLDocument())
- return;
if (data.origin != form_util::GetCanonicalOriginForDocument(doc))
return;
@@ -559,19 +561,6 @@ bool FillFormOnPasswordReceived(
field_value_and_properties_map, registration_callback, logger);
}
-// Takes a |map| with pointers as keys and linked_ptr as values, and returns
-// true if |key| is not NULL and |map| contains a non-NULL entry for |key|.
-// Makes sure not to create an entry as a side effect of using the operator [].
-template <class Key, class Value>
-bool ContainsNonNullEntryForNonNullKey(
- const std::map<Key*, linked_ptr<Value>>& map,
- Key* key) {
- if (!key)
- return false;
- auto it = map.find(key);
- return it != map.end() && it->second.get();
-}
-
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -586,7 +575,6 @@ PasswordAutofillAgent::PasswordAutofillAgent(content::RenderFrame* render_frame)
// PasswordAutofillAgent is guaranteed to outlive |render_frame|.
render_frame->GetInterfaceRegistry()->AddInterface(
base::Bind(&PasswordAutofillAgent::BindRequest, base::Unretained(this)));
- GetPasswordManagerDriver()->PasswordAutofillAgentConstructed();
}
PasswordAutofillAgent::~PasswordAutofillAgent() {
@@ -855,9 +843,23 @@ bool PasswordAutofillAgent::ShowSuggestions(
blink::WebInputElement username_element;
blink::WebInputElement password_element;
PasswordInfo* password_info;
+
if (!FindPasswordInfoForElement(element, &username_element, &password_element,
- &password_info))
+ &password_info)) {
+ // If we don't have a password stored, but the form is non-secure, warn
+ // the user about the non-secure form.
+ if ((element.isPasswordField() ||
+ HasAutocompleteAttributeValue(element, "username")) &&
+ security_state::IsHttpWarningInFormEnabled() &&
+ !content::IsOriginSecure(
+ url::Origin(
+ render_frame()->GetWebFrame()->top()->getSecurityOrigin())
+ .GetURL())) {
+ autofill_agent_->ShowNotSecureWarning(element);
+ return true;
+ }
return false;
+ }
// If autocomplete='off' is set on the form elements, no suggestion dialog
// should be shown. However, return |true| to indicate that this is a known
@@ -899,6 +901,16 @@ bool PasswordAutofillAgent::ShowSuggestions(
element.isPasswordField());
}
+void PasswordAutofillAgent::ShowNotSecureWarning(
+ const blink::WebInputElement& element) {
+ FormData form;
+ FormFieldData field;
+ form_util::FindFormAndFieldForFormControlElement(element, &form, &field);
+ GetPasswordManagerDriver()->ShowNotSecureWarning(
+ field.text_direction,
+ render_frame()->GetRenderView()->ElementBoundsInWindow(element));
+}
+
bool PasswordAutofillAgent::OriginCanAccessPasswordManager(
const blink::WebSecurityOrigin& origin) {
return origin.canAccessPasswordManager();
@@ -947,10 +959,6 @@ void PasswordAutofillAgent::SendPasswordForms(bool only_visible) {
}
blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
- // RenderFrameObserver::DidFinishLoad() can fire when Frame is
- // detaching. crbug.com/654654
- if (frame->isFrameDetachedForSpecialOneOffStopTheCrashingHackBug561873())
- return;
// Make sure that this security origin is allowed to use password manager.
blink::WebSecurityOrigin origin = frame->document().getSecurityOrigin();
@@ -1195,7 +1203,7 @@ void PasswordAutofillAgent::DidStartProvisionalLoad() {
*provisionally_saved_form_);
provisionally_saved_form_.reset();
} else {
- ScopedVector<PasswordForm> possible_submitted_forms;
+ std::vector<std::unique_ptr<PasswordForm>> possible_submitted_forms;
// Loop through the forms on the page looking for one that has been
// filled out. If one exists, try and save the credentials.
blink::WebVector<blink::WebFormElement> forms;
@@ -1218,7 +1226,7 @@ void PasswordAutofillAgent::DidStartProvisionalLoad() {
*render_frame()->GetWebFrame(), &field_value_and_properties_map_,
&form_predictions_));
- for (const PasswordForm* password_form : possible_submitted_forms) {
+ for (const auto& password_form : possible_submitted_forms) {
if (password_form && !password_form->username_value.empty() &&
FormContainsNonDefaultPasswordValue(*password_form)) {
password_forms_found = true;
@@ -1506,7 +1514,7 @@ const mojom::PasswordManagerDriverPtr&
PasswordAutofillAgent::GetPasswordManagerDriver() {
if (!password_manager_driver_) {
render_frame()->GetRemoteInterfaces()->GetInterface(
- mojo::GetProxy(&password_manager_driver_));
+ mojo::MakeRequest(&password_manager_driver_));
}
return password_manager_driver_;
diff --git a/chromium/components/autofill/content/renderer/password_autofill_agent.h b/chromium/components/autofill/content/renderer/password_autofill_agent.h
index 48f61a493f5..ce63053cce8 100644
--- a/chromium/components/autofill/content/renderer/password_autofill_agent.h
+++ b/chromium/components/autofill/content/renderer/password_autofill_agent.h
@@ -25,7 +25,6 @@
namespace blink {
class WebInputElement;
-class WebKeyboardEvent;
class WebSecurityOrigin;
}
@@ -95,6 +94,11 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
bool show_all,
bool generation_popup_showing);
+ // Shows an Autofill-style popup with a warning that the form is not secure.
+ // This UI is shown when a username or password field is autofilled or edited
+ // on a non-secure page.
+ void ShowNotSecureWarning(const blink::WebInputElement& element);
+
// Called when new form controls are inserted.
void OnDynamicFormsSeen();
diff --git a/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc b/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc
index d41ac97fbe3..3465657dd93 100644
--- a/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc
+++ b/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc
@@ -154,12 +154,16 @@ void ExcludeUsernameFromOtherUsernamesList(
}
// Helper to determine which password is the main (current) one, and which is
-// the new password (e.g., on a sign-up or change password form), if any.
+// the new password (e.g., on a sign-up or change password form), if any. If the
+// new password is found and there is another password field with the same user
+// input, the function also sets |confirmation_password| to this field.
bool LocateSpecificPasswords(std::vector<WebInputElement> passwords,
WebInputElement* current_password,
- WebInputElement* new_password) {
+ WebInputElement* new_password,
+ WebInputElement* confirmation_password) {
DCHECK(current_password && current_password->isNull());
DCHECK(new_password && new_password->isNull());
+ DCHECK(confirmation_password && confirmation_password->isNull());
// First, look for elements marked with either autocomplete='current-password'
// or 'new-password' -- if we find any, take the hint, and treat the first of
@@ -171,6 +175,9 @@ bool LocateSpecificPasswords(std::vector<WebInputElement> passwords,
} else if (HasAutocompleteAttributeValue(it, kAutocompleteNewPassword) &&
new_password->isNull()) {
*new_password = it;
+ } else if (!new_password->isNull() &&
+ (new_password->value() == it.value())) {
+ *confirmation_password = it;
}
}
@@ -197,6 +204,7 @@ bool LocateSpecificPasswords(std::vector<WebInputElement> passwords,
// password with a confirmation. This can be either a sign-up form or a
// password change form that does not ask for the old password.
*new_password = passwords[0];
+ *confirmation_password = passwords[1];
} else {
// Assume first is old password, second is new (no choice but to guess).
// This case also includes empty passwords in order to allow filling of
@@ -218,12 +226,14 @@ bool LocateSpecificPasswords(std::vector<WebInputElement> passwords,
// with 3 password fields, in which case we will assume this layout.
*current_password = passwords[0];
*new_password = passwords[1];
+ *confirmation_password = passwords[2];
} else if (passwords[0].value() == passwords[1].value()) {
// It is strange that the new password comes first, but trust more which
// fields are duplicated than the ordering of fields. Assume that
// any password fields after the new password contain sensitive
// information that isn't actually a password (security hint, SSN, etc.)
*new_password = passwords[0];
+ *confirmation_password = passwords[1];
} else {
// Three different passwords, or first and last match with middle
// different. No idea which is which, so no luck.
@@ -505,7 +515,9 @@ bool GetPasswordForm(
WebInputElement password;
WebInputElement new_password;
- if (!LocateSpecificPasswords(passwords, &password, &new_password))
+ WebInputElement confirmation_password;
+ if (!LocateSpecificPasswords(passwords, &password, &new_password,
+ &confirmation_password))
return false;
DCHECK_EQ(passwords.size(), last_text_input_before_password.size());
@@ -584,6 +596,10 @@ bool GetPasswordForm(
new_password.getAttribute("value") == new_password.value();
if (HasAutocompleteAttributeValue(new_password, kAutocompleteNewPassword))
password_form->new_password_marked_by_site = true;
+ if (!confirmation_password.isNull()) {
+ password_form->confirmation_password_element =
+ FieldName(confirmation_password, "anonymous_confirmation_password");
+ }
}
if (username_element.isNull()) {
diff --git a/chromium/components/autofill/content/renderer/password_form_conversion_utils.h b/chromium/components/autofill/content/renderer/password_form_conversion_utils.h
index 4101dcb9460..4c8cd645e46 100644
--- a/chromium/components/autofill/content/renderer/password_form_conversion_utils.h
+++ b/chromium/components/autofill/content/renderer/password_form_conversion_utils.h
@@ -15,7 +15,6 @@
#include "url/gurl.h"
namespace blink {
-class WebDocument;
class WebFormElement;
class WebFormControlElement;
class WebFrame;
@@ -24,8 +23,6 @@ class WebInputElement;
namespace autofill {
-struct FormData;
-struct FormFieldData;
struct PasswordForm;
// Tests whether the given form is a GAIA reauthentication form. The form is
diff --git a/chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc b/chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
index 5169e0bc376..08b1988e158 100644
--- a/chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
+++ b/chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
@@ -213,9 +213,8 @@ class MAYBE_PasswordFormConversionUtilsTest : public content::RenderViewTest {
FormStructure form_structure(form_data);
int field_index = 0;
- for (std::vector<AutofillField *>::const_iterator
- field = form_structure.begin();
- field != form_structure.end(); ++field, ++field_index) {
+ for (auto field = form_structure.begin(); field != form_structure.end();
+ ++field, ++field_index) {
if (predictions_positions.find(field_index) !=
predictions_positions.end()) {
(*predictions)[form_data][*(*field)] =
@@ -384,19 +383,20 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, IdentifyingTwoPasswordFields) {
const char* expected_password_value;
const char* expected_new_password_element;
const char* expected_new_password_value;
+ const char* expected_confirmation_element;
} cases[] = {
// Two non-empty fields with the same value should be treated as a new
// password field plus a confirmation field for the new password.
- {{"alpha", "alpha"}, "", "", "password1", "alpha"},
+ {{"alpha", "alpha"}, "", "", "password1", "alpha", "password2"},
// The same goes if the fields are yet empty: we speculate that we will
// identify them as new password fields once they are filled out, and we
// want to keep our abstract interpretation of the form less flaky.
- {{"", ""}, "password1", "", "password2", ""},
+ {{"", ""}, "password1", "", "password2", "", ""},
// Two different values should be treated as a password change form, one
// that also asks for the current password, but only once for the new.
- {{"alpha", ""}, "password1", "alpha", "password2", ""},
- {{"", "beta"}, "password1", "", "password2", "beta"},
- {{"alpha", "beta"}, "password1", "alpha", "password2", "beta"}};
+ {{"alpha", ""}, "password1", "alpha", "password2", "", ""},
+ {{"", "beta"}, "password1", "", "password2", "beta", ""},
+ {{"alpha", "beta"}, "password1", "alpha", "password2", "beta", ""}};
for (size_t i = 0; i < arraysize(cases); ++i) {
SCOPED_TRACE(testing::Message() << "Iteration " << i);
@@ -421,6 +421,8 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, IdentifyingTwoPasswordFields) {
password_form->new_password_element);
EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_value),
password_form->new_password_value);
+ EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_confirmation_element),
+ password_form->confirmation_password_element);
// Do a basic sanity check that we are still selecting the right username.
EXPECT_EQ(base::UTF8ToUTF16("username1"), password_form->username_element);
@@ -439,24 +441,30 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, IdentifyingThreePasswordFields) {
const char* expected_password_value;
const char* expected_new_password_element;
const char* expected_new_password_value;
+ const char* expected_confirmation_element;
} cases[] = {
// Two fields with the same value, and one different: we should treat this
// as a password change form with confirmation for the new password. Note
// that we only recognize (current + new + new) and (new + new + current)
// without autocomplete attributes.
- {{"alpha", "", ""}, "password1", "alpha", "password2", ""},
- {{"", "beta", "beta"}, "password1", "", "password2", "beta"},
- {{"alpha", "beta", "beta"}, "password1", "alpha", "password2", "beta"},
+ {{"alpha", "", ""}, "password1", "alpha", "password2", "", "password3"},
+ {{"", "beta", "beta"}, "password1", "", "password2", "beta", "password3"},
+ {{"alpha", "beta", "beta"},
+ "password1",
+ "alpha",
+ "password2",
+ "beta",
+ "password3"},
// If confirmed password comes first, assume that the third password
// field is related to security question, SSN, or credit card and ignore
// it.
- {{"beta", "beta", "alpha"}, "", "", "password1", "beta"},
+ {{"beta", "beta", "alpha"}, "", "", "password1", "beta", "password2"},
// If the fields are yet empty, we speculate that we will identify them as
// (current + new + new) once they are filled out, so we should classify
// them the same for now to keep our abstract interpretation less flaky.
- {{"", "", ""}, "password1", "", "password2", ""}};
- // Note: In all other cases, we give up and consider the form invalid.
- // This is tested in InvalidFormDueToConfusingPasswordFields.
+ {{"", "", ""}, "password1", "", "password2", "", "password3"}};
+ // Note: In all other cases, we give up and consider the form invalid.
+ // This is tested in InvalidFormDueToConfusingPasswordFields.
for (size_t i = 0; i < arraysize(cases); ++i) {
SCOPED_TRACE(testing::Message() << "Iteration " << i);
@@ -482,6 +490,8 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, IdentifyingThreePasswordFields) {
password_form->new_password_element);
EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_new_password_value),
password_form->new_password_value);
+ EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_confirmation_element),
+ password_form->confirmation_password_element);
// Do a basic sanity check that we are still selecting the right username.
EXPECT_EQ(base::UTF8ToUTF16("username1"), password_form->username_element);
diff --git a/chromium/components/autofill/content/renderer/password_generation_agent.cc b/chromium/components/autofill/content/renderer/password_generation_agent.cc
index a0a52834799..183b5f068c2 100644
--- a/chromium/components/autofill/content/renderer/password_generation_agent.cc
+++ b/chromium/components/autofill/content/renderer/password_generation_agent.cc
@@ -8,6 +8,7 @@
#include "base/command_line.h"
#include "base/logging.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "components/autofill/content/renderer/form_autofill_util.h"
#include "components/autofill/content/renderer/form_classifier.h"
#include "components/autofill/content/renderer/password_autofill_agent.h"
diff --git a/chromium/components/autofill/content/renderer/password_generation_agent.h b/chromium/components/autofill/content/renderer/password_generation_agent.h
index 2b73a4dc01d..694c5fc990c 100644
--- a/chromium/components/autofill/content/renderer/password_generation_agent.h
+++ b/chromium/components/autofill/content/renderer/password_generation_agent.h
@@ -21,13 +21,8 @@
#include "third_party/WebKit/public/web/WebInputElement.h"
#include "url/gurl.h"
-namespace blink {
-class WebDocument;
-}
-
namespace autofill {
-struct FormData;
struct PasswordForm;
struct PasswordFormGenerationData;
class PasswordAutofillAgent;
diff --git a/chromium/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc b/chromium/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc
index 7c0c27e21c9..85958d4f696 100644
--- a/chromium/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc
+++ b/chromium/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc
@@ -61,7 +61,8 @@ class FakeContentPasswordManagerDriver : public mojom::PasswordManagerDriver {
int options,
const gfx::RectF& bounds) override {}
- void PasswordAutofillAgentConstructed() override {}
+ void ShowNotSecureWarning(base::i18n::TextDirection text_direction,
+ const gfx::RectF& bounds) override {}
void RecordSavePasswordProgress(const std::string& log) override {
called_record_save_ = true;
diff --git a/chromium/components/autofill/core/browser/BUILD.gn b/chromium/components/autofill/core/browser/BUILD.gn
index 4e919e7d359..5281b7de472 100644
--- a/chromium/components/autofill/core/browser/BUILD.gn
+++ b/chromium/components/autofill/core/browser/BUILD.gn
@@ -117,6 +117,8 @@ static_library("browser") {
"ui/card_unmask_prompt_view.h",
"validation.cc",
"validation.h",
+ "webdata/autocomplete_sync_bridge.cc",
+ "webdata/autocomplete_sync_bridge.h",
"webdata/autocomplete_syncable_service.cc",
"webdata/autocomplete_syncable_service.h",
"webdata/autofill_change.cc",
@@ -125,6 +127,8 @@ static_library("browser") {
"webdata/autofill_data_type_controller.h",
"webdata/autofill_entry.cc",
"webdata/autofill_entry.h",
+ "webdata/autofill_metadata_change_list.cc",
+ "webdata/autofill_metadata_change_list.h",
"webdata/autofill_profile_data_type_controller.cc",
"webdata/autofill_profile_data_type_controller.h",
"webdata/autofill_profile_syncable_service.cc",
@@ -316,10 +320,12 @@ source_set("unit_tests") {
"phone_number_unittest.cc",
"ui/card_unmask_prompt_controller_impl_unittest.cc",
"validation_unittest.cc",
+ "webdata/autocomplete_sync_bridge_unittest.cc",
"webdata/autofill_data_type_controller_unittest.cc",
"webdata/autofill_profile_syncable_service_unittest.cc",
"webdata/autofill_table_unittest.cc",
"webdata/autofill_wallet_metadata_syncable_service_unittest.cc",
+ "webdata/autofill_wallet_syncable_service_unittest.cc",
"webdata/web_data_service_unittest.cc",
]
diff --git a/chromium/components/autofill/core/browser/address_field_unittest.cc b/chromium/components/autofill/core/browser/address_field_unittest.cc
index b3f4f92ca18..d959e8d7740 100644
--- a/chromium/components/autofill/core/browser/address_field_unittest.cc
+++ b/chromium/components/autofill/core/browser/address_field_unittest.cc
@@ -5,10 +5,10 @@
#include "components/autofill/core/browser/address_field.h"
#include <memory>
+#include <vector>
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/memory/scoped_vector.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_field.h"
@@ -25,7 +25,7 @@ class AddressFieldTest : public testing::Test {
AddressFieldTest() {}
protected:
- ScopedVector<AutofillField> list_;
+ std::vector<std::unique_ptr<AutofillField>> list_;
std::unique_ptr<AddressField> field_;
FieldCandidatesMap field_candidates_map_;
@@ -40,14 +40,14 @@ class AddressFieldTest : public testing::Test {
};
TEST_F(AddressFieldTest, Empty) {
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_EQ(nullptr, field_.get());
}
TEST_F(AddressFieldTest, NonParse) {
- list_.push_back(new AutofillField);
- AutofillScanner scanner(list_.get());
+ list_.push_back(base::MakeUnique<AutofillField>());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_EQ(nullptr, field_.get());
}
@@ -58,9 +58,10 @@ TEST_F(AddressFieldTest, ParseOneLineAddress) {
field.label = ASCIIToUTF16("Address");
field.name = ASCIIToUTF16("address");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("addr1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("addr1")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -76,13 +77,15 @@ TEST_F(AddressFieldTest, ParseTwoLineAddress) {
field.label = ASCIIToUTF16("Address");
field.name = ASCIIToUTF16("address");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("addr1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("addr1")));
field.label = base::string16();
field.name = ASCIIToUTF16("address2");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("addr2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("addr2")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -102,17 +105,20 @@ TEST_F(AddressFieldTest, ParseThreeLineAddress) {
field.label = ASCIIToUTF16("Address Line1");
field.name = ASCIIToUTF16("Address1");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("addr1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("addr1")));
field.label = ASCIIToUTF16("Address Line2");
field.name = ASCIIToUTF16("Address2");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("addr2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("addr2")));
field.label = ASCIIToUTF16("Address Line3");
field.name = ASCIIToUTF16("Address3");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("addr3")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("addr3")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -136,9 +142,9 @@ TEST_F(AddressFieldTest, ParseStreetAddressFromTextArea) {
field.label = ASCIIToUTF16("Address");
field.name = ASCIIToUTF16("address");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("addr")));
+ list_.push_back(base::MakeUnique<AutofillField>(field, ASCIIToUTF16("addr")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -154,9 +160,10 @@ TEST_F(AddressFieldTest, ParseCity) {
field.label = ASCIIToUTF16("City");
field.name = ASCIIToUTF16("city");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("city1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("city1")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -172,9 +179,10 @@ TEST_F(AddressFieldTest, ParseState) {
field.label = ASCIIToUTF16("State");
field.name = ASCIIToUTF16("state");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("state1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("state1")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -190,9 +198,9 @@ TEST_F(AddressFieldTest, ParseZip) {
field.label = ASCIIToUTF16("Zip");
field.name = ASCIIToUTF16("zip");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("zip1")));
+ list_.push_back(base::MakeUnique<AutofillField>(field, ASCIIToUTF16("zip1")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -208,13 +216,14 @@ TEST_F(AddressFieldTest, ParseStateAndZipOneLabel) {
field.label = ASCIIToUTF16("State/Province, Zip/Postal Code");
field.name = ASCIIToUTF16("state");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("state")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("state")));
field.label = ASCIIToUTF16("State/Province, Zip/Postal Code");
field.name = ASCIIToUTF16("zip");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("zip")));
+ list_.push_back(base::MakeUnique<AutofillField>(field, ASCIIToUTF16("zip")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -234,9 +243,10 @@ TEST_F(AddressFieldTest, ParseCountry) {
field.label = ASCIIToUTF16("Country");
field.name = ASCIIToUTF16("country");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("country1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("country1")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -253,9 +263,10 @@ TEST_F(AddressFieldTest, ParseCompany) {
field.label = ASCIIToUTF16("Company");
field.name = ASCIIToUTF16("company");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("company1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("company1")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
diff --git a/chromium/components/autofill/core/browser/autofill_assistant.cc b/chromium/components/autofill/core/browser/autofill_assistant.cc
index 4fccc2a7997..3e463b614bc 100644
--- a/chromium/components/autofill/core/browser/autofill_assistant.cc
+++ b/chromium/components/autofill/core/browser/autofill_assistant.cc
@@ -31,8 +31,7 @@ bool AutofillAssistant::CanShowCreditCardAssist(
!IsAutofillCreditCardAssistEnabled() ||
// Context of the page is not secure or target URL is valid but not
// secure.
- !(autofill_manager_->client()->IsContextSecure(
- form_structures.front()->source_url()) &&
+ !(autofill_manager_->client()->IsContextSecure() &&
(!form_structures.front()->target_url().is_valid() ||
!form_structures.front()->target_url().SchemeIs("http")))) {
return false;
diff --git a/chromium/components/autofill/core/browser/autofill_client.h b/chromium/components/autofill/core/browser/autofill_client.h
index 61b10177c41..3960f44fdbb 100644
--- a/chromium/components/autofill/core/browser/autofill_client.h
+++ b/chromium/components/autofill/core/browser/autofill_client.h
@@ -17,7 +17,6 @@
#include "ui/base/window_open_disposition.h"
#include "url/gurl.h"
-class GURL;
class IdentityProvider;
class PrefService;
@@ -26,12 +25,11 @@ class RenderFrameHost;
}
namespace gfx {
-class Rect;
class RectF;
}
namespace rappor {
-class RapporService;
+class RapporServiceImpl;
}
namespace syncer {
@@ -46,7 +44,6 @@ class CardUnmaskDelegate;
class CreditCard;
class FormStructure;
class PersonalDataManager;
-struct FormData;
struct Suggestion;
// A client interface that needs to be supplied to the Autofill component by the
@@ -105,8 +102,8 @@ class AutofillClient {
// Gets the IdentityProvider associated with the client (for OAuth2).
virtual IdentityProvider* GetIdentityProvider() = 0;
- // Gets the RapporService associated with the client (for metrics).
- virtual rappor::RapporService* GetRapporService() = 0;
+ // Gets the RapporServiceImpl associated with the client (for metrics).
+ virtual rappor::RapporServiceImpl* GetRapporServiceImpl() = 0;
// Causes the Autofill settings UI to be shown.
virtual void ShowAutofillSettings() = 0;
@@ -183,7 +180,7 @@ class AutofillClient {
virtual void OnFirstUserGestureObserved() = 0;
// If the context is secure.
- virtual bool IsContextSecure(const GURL& form_origin) = 0;
+ virtual bool IsContextSecure() = 0;
// Whether it is appropriate to show a signin promo for this user.
virtual bool ShouldShowSigninPromo() = 0;
@@ -191,6 +188,9 @@ class AutofillClient {
// Starts the signin flow. Should not be called if ShouldShowSigninPromo()
// returns false.
virtual void StartSigninFlow() = 0;
+
+ // Shows the explanation of http not secure warning message.
+ virtual void ShowHttpNotSecureExplanation() = 0;
};
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.h b/chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.h
index fe1cc199e0e..04e030694d5 100644
--- a/chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.h
+++ b/chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.h
@@ -13,10 +13,6 @@
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/infobars/core/confirm_infobar_delegate.h"
-namespace infobars {
-class InfoBarManager;
-}
-
namespace autofill {
class CreditCard;
diff --git a/chromium/components/autofill/core/browser/autofill_data_model.h b/chromium/components/autofill/core/browser/autofill_data_model.h
index ee055ff49b3..4cc373b7177 100644
--- a/chromium/components/autofill/core/browser/autofill_data_model.h
+++ b/chromium/components/autofill/core/browser/autofill_data_model.h
@@ -15,8 +15,6 @@
namespace autofill {
-class AutofillType;
-
// This class is an interface for the primary data models that back Autofill.
// The information in objects of this class is managed by the
// PersonalDataManager.
diff --git a/chromium/components/autofill/core/browser/autofill_data_util.cc b/chromium/components/autofill/core/browser/autofill_data_util.cc
index 5a09665034c..d931d7b0888 100644
--- a/chromium/components/autofill/core/browser/autofill_data_util.cc
+++ b/chromium/components/autofill/core/browser/autofill_data_util.cc
@@ -27,6 +27,7 @@ const PaymentRequestData kPaymentRequestData[]{
{"discoverCC", "discover", IDR_AUTOFILL_PR_DISCOVER},
{"jcbCC", "jcb", IDR_AUTOFILL_PR_JCB},
{"masterCardCC", "mastercard", IDR_AUTOFILL_PR_MASTERCARD},
+ {"mirCC", "mir", IDR_AUTOFILL_PR_MIR},
{"unionPayCC", "unionpay", IDR_AUTOFILL_PR_UNIONPAY},
{"visaCC", "visa", IDR_AUTOFILL_PR_VISA},
};
diff --git a/chromium/components/autofill/core/browser/autofill_download_manager.cc b/chromium/components/autofill/core/browser/autofill_download_manager.cc
index 331de998450..07084c52be4 100644
--- a/chromium/components/autofill/core/browser/autofill_download_manager.cc
+++ b/chromium/components/autofill/core/browser/autofill_download_manager.cc
@@ -247,8 +247,8 @@ bool AutofillDownloadManager::StartRequest(
net::LOAD_DO_NOT_SEND_COOKIES);
// Add Chrome experiment state to the request headers.
net::HttpRequestHeaders headers;
- // Note: It's fine to pass in |is_signed_in| false, which does not affect
- // transmission of experiment ids coming from the variations server.
+ // Note: It's OK to pass |is_signed_in| false if it's unknown, as it does
+ // not affect transmission of experiments coming from the variations server.
bool is_signed_in = false;
variations::AppendVariationHeaders(fetcher->GetOriginalURL(),
driver_->IsOffTheRecord(), false,
diff --git a/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc b/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc
index e9bfcb30cc9..73768ad2ace 100644
--- a/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc
@@ -9,7 +9,9 @@
#include <list>
#include <memory>
#include <utility>
+#include <vector>
+#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@@ -49,6 +51,14 @@ void FakeOnURLFetchComplete(net::TestURLFetcher* fetcher,
fetcher->delegate()->OnURLFetchComplete(fetcher);
}
+std::vector<FormStructure*> ToRawPointerVector(
+ const std::vector<std::unique_ptr<FormStructure>>& list) {
+ std::vector<FormStructure*> result;
+ for (const auto& item : list)
+ result.push_back(item.get());
+ return result;
+}
+
} // namespace
// This tests AutofillDownloadManager. AutofillDownloadManagerTest implements
@@ -166,9 +176,8 @@ TEST_F(AutofillDownloadManagerTest, QueryAndUploadTest) {
field.form_control_type = "submit";
form.fields.push_back(field);
- FormStructure* form_structure = new FormStructure(form);
- ScopedVector<FormStructure> form_structures;
- form_structures.push_back(form_structure);
+ std::vector<std::unique_ptr<FormStructure>> form_structures;
+ form_structures.push_back(base::MakeUnique<FormStructure>(form));
form.fields.clear();
@@ -192,8 +201,7 @@ TEST_F(AutofillDownloadManagerTest, QueryAndUploadTest) {
field.form_control_type = "submit";
form.fields.push_back(field);
- form_structure = new FormStructure(form);
- form_structures.push_back(form_structure);
+ form_structures.push_back(base::MakeUnique<FormStructure>(form));
form.fields.clear();
@@ -212,12 +220,12 @@ TEST_F(AutofillDownloadManagerTest, QueryAndUploadTest) {
field.form_control_type = "submit";
form.fields.push_back(field);
- form_structure = new FormStructure(form);
- form_structures.push_back(form_structure);
+ form_structures.push_back(base::MakeUnique<FormStructure>(form));
// Request with id 0.
base::HistogramTester histogram;
- EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures.get()));
+ EXPECT_TRUE(
+ download_manager_.StartQueryRequest(ToRawPointerVector(form_structures)));
histogram.ExpectUniqueSample("Autofill.ServerQueryResponse",
AutofillMetrics::QUERY_SENT, 1);
@@ -296,11 +304,11 @@ TEST_F(AutofillDownloadManagerTest, QueryAndUploadTest) {
field.name = ASCIIToUTF16("address2");
field.form_control_type = "text";
form.fields.push_back(field);
- form_structure = new FormStructure(form);
- form_structures.push_back(form_structure);
+ form_structures.push_back(base::MakeUnique<FormStructure>(form));
// Request with id 4, not successful.
- EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures.get()));
+ EXPECT_TRUE(
+ download_manager_.StartQueryRequest(ToRawPointerVector(form_structures)));
fetcher = factory.GetFetcherByID(4);
ASSERT_TRUE(fetcher);
histogram.ExpectUniqueSample("Autofill.ServerQueryResponse",
@@ -343,13 +351,13 @@ TEST_F(AutofillDownloadManagerTest, BackoffLogic_Query) {
field.form_control_type = "submit";
form.fields.push_back(field);
- FormStructure* form_structure = new FormStructure(form);
- ScopedVector<FormStructure> form_structures;
- form_structures.push_back(form_structure);
+ std::vector<std::unique_ptr<FormStructure>> form_structures;
+ form_structures.push_back(base::MakeUnique<FormStructure>(form));
// Request with id 0.
base::HistogramTester histogram;
- EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures.get()));
+ EXPECT_TRUE(
+ download_manager_.StartQueryRequest(ToRawPointerVector(form_structures)));
histogram.ExpectUniqueSample("Autofill.ServerQueryResponse",
AutofillMetrics::QUERY_SENT, 1);
@@ -403,7 +411,7 @@ TEST_F(AutofillDownloadManagerTest, BackoffLogic_Upload) {
field.form_control_type = "submit";
form.fields.push_back(field);
- std::unique_ptr<FormStructure> form_structure(new FormStructure(form));
+ auto form_structure = base::MakeUnique<FormStructure>(form);
// Request with id 0.
EXPECT_TRUE(download_manager_.StartUploadRequest(
@@ -452,7 +460,7 @@ TEST_F(AutofillDownloadManagerTest, QueryTooManyFieldsTest) {
// Create a query that contains too many fields for the server.
std::vector<FormData> forms(21);
- ScopedVector<FormStructure> form_structures;
+ std::vector<std::unique_ptr<FormStructure>> form_structures;
for (auto& form : forms) {
for (size_t i = 0; i < 5; ++i) {
FormFieldData field;
@@ -461,12 +469,12 @@ TEST_F(AutofillDownloadManagerTest, QueryTooManyFieldsTest) {
field.form_control_type = "text";
form.fields.push_back(field);
}
- FormStructure* form_structure = new FormStructure(form);
- form_structures.push_back(form_structure);
+ form_structures.push_back(base::MakeUnique<FormStructure>(form));
}
// Check whether the query is aborted.
- EXPECT_FALSE(download_manager_.StartQueryRequest(form_structures.get()));
+ EXPECT_FALSE(
+ download_manager_.StartQueryRequest(ToRawPointerVector(form_structures)));
}
TEST_F(AutofillDownloadManagerTest, QueryNotTooManyFieldsTest) {
@@ -476,7 +484,7 @@ TEST_F(AutofillDownloadManagerTest, QueryNotTooManyFieldsTest) {
// Create a query that contains a lot of fields, but not too many for the
// server.
std::vector<FormData> forms(25);
- ScopedVector<FormStructure> form_structures;
+ std::vector<std::unique_ptr<FormStructure>> form_structures;
for (auto& form : forms) {
for (size_t i = 0; i < 4; ++i) {
FormFieldData field;
@@ -485,12 +493,12 @@ TEST_F(AutofillDownloadManagerTest, QueryNotTooManyFieldsTest) {
field.form_control_type = "text";
form.fields.push_back(field);
}
- FormStructure* form_structure = new FormStructure(form);
- form_structures.push_back(form_structure);
+ form_structures.push_back(base::MakeUnique<FormStructure>(form));
}
// Check that the query is not aborted.
- EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures.get()));
+ EXPECT_TRUE(
+ download_manager_.StartQueryRequest(ToRawPointerVector(form_structures)));
}
TEST_F(AutofillDownloadManagerTest, CacheQueryTest) {
@@ -514,26 +522,23 @@ TEST_F(AutofillDownloadManagerTest, CacheQueryTest) {
field.name = ASCIIToUTF16("lastname");
form.fields.push_back(field);
- FormStructure* form_structure = new FormStructure(form);
- ScopedVector<FormStructure> form_structures0;
- form_structures0.push_back(form_structure);
+ std::vector<std::unique_ptr<FormStructure>> form_structures0;
+ form_structures0.push_back(base::MakeUnique<FormStructure>(form));
// Add a slightly different form, which should result in a different request.
field.label = ASCIIToUTF16("email");
field.name = ASCIIToUTF16("email");
form.fields.push_back(field);
- form_structure = new FormStructure(form);
- ScopedVector<FormStructure> form_structures1;
- form_structures1.push_back(form_structure);
+ std::vector<std::unique_ptr<FormStructure>> form_structures1;
+ form_structures1.push_back(base::MakeUnique<FormStructure>(form));
// Add another slightly different form, which should also result in a
// different request.
field.label = ASCIIToUTF16("email2");
field.name = ASCIIToUTF16("email2");
form.fields.push_back(field);
- form_structure = new FormStructure(form);
- ScopedVector<FormStructure> form_structures2;
- form_structures2.push_back(form_structure);
+ std::vector<std::unique_ptr<FormStructure>> form_structures2;
+ form_structures2.push_back(base::MakeUnique<FormStructure>(form));
// Limit cache to two forms.
LimitCache(2);
@@ -561,7 +566,8 @@ TEST_F(AutofillDownloadManagerTest, CacheQueryTest) {
base::HistogramTester histogram;
// Request with id 0.
- EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get()));
+ EXPECT_TRUE(download_manager_.StartQueryRequest(
+ ToRawPointerVector(form_structures0)));
histogram.ExpectUniqueSample("Autofill.ServerQueryResponse",
AutofillMetrics::QUERY_SENT, 1);
@@ -577,7 +583,8 @@ TEST_F(AutofillDownloadManagerTest, CacheQueryTest) {
responses_.clear();
// No actual request - should be a cache hit.
- EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get()));
+ EXPECT_TRUE(download_manager_.StartQueryRequest(
+ ToRawPointerVector(form_structures0)));
histogram.ExpectUniqueSample("Autofill.ServerQueryResponse",
AutofillMetrics::QUERY_SENT, 2);
// Data is available immediately from cache - no over-the-wire trip.
@@ -586,7 +593,8 @@ TEST_F(AutofillDownloadManagerTest, CacheQueryTest) {
responses_.clear();
// Request with id 1.
- EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures1.get()));
+ EXPECT_TRUE(download_manager_.StartQueryRequest(
+ ToRawPointerVector(form_structures1)));
histogram.ExpectUniqueSample("Autofill.ServerQueryResponse",
AutofillMetrics::QUERY_SENT, 3);
// No responses yet
@@ -601,7 +609,8 @@ TEST_F(AutofillDownloadManagerTest, CacheQueryTest) {
responses_.clear();
// Request with id 2.
- EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures2.get()));
+ EXPECT_TRUE(download_manager_.StartQueryRequest(
+ ToRawPointerVector(form_structures2)));
histogram.ExpectUniqueSample("Autofill.ServerQueryResponse",
AutofillMetrics::QUERY_SENT, 4);
@@ -614,11 +623,13 @@ TEST_F(AutofillDownloadManagerTest, CacheQueryTest) {
responses_.clear();
// No actual requests - should be a cache hit.
- EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures1.get()));
+ EXPECT_TRUE(download_manager_.StartQueryRequest(
+ ToRawPointerVector(form_structures1)));
histogram.ExpectUniqueSample("Autofill.ServerQueryResponse",
AutofillMetrics::QUERY_SENT, 5);
- EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures2.get()));
+ EXPECT_TRUE(download_manager_.StartQueryRequest(
+ ToRawPointerVector(form_structures2)));
histogram.ExpectUniqueSample("Autofill.ServerQueryResponse",
AutofillMetrics::QUERY_SENT, 6);
@@ -629,7 +640,8 @@ TEST_F(AutofillDownloadManagerTest, CacheQueryTest) {
// The first structure should've expired.
// Request with id 3.
- EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get()));
+ EXPECT_TRUE(download_manager_.StartQueryRequest(
+ ToRawPointerVector(form_structures0)));
histogram.ExpectUniqueSample("Autofill.ServerQueryResponse",
AutofillMetrics::QUERY_SENT, 7);
// No responses yet
diff --git a/chromium/components/autofill/core/browser/autofill_experiments.cc b/chromium/components/autofill/core/browser/autofill_experiments.cc
index e066d854f55..39472262445 100644
--- a/chromium/components/autofill/core/browser/autofill_experiments.cc
+++ b/chromium/components/autofill/core/browser/autofill_experiments.cc
@@ -7,16 +7,20 @@
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/metrics/field_trial.h"
+#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
+#include "components/autofill/core/browser/suggestion.h"
#include "components/autofill/core/common/autofill_pref_names.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/prefs/pref_service.h"
-#include "components/security_state/core/switches.h"
#include "components/sync/driver/sync_service.h"
#include "components/variations/variations_associated_data.h"
#include "google_apis/gaia/gaia_auth_util.h"
+#include "grit/components_strings.h"
+#include "ui/base/l10n/l10n_util.h"
namespace autofill {
@@ -24,11 +28,37 @@ const base::Feature kAutofillCreditCardAssist{
"AutofillCreditCardAssist", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kAutofillCreditCardSigninPromo{
"AutofillCreditCardSigninPromo", base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kAutofillProfileCleanup{"AutofillProfileCleanup",
- base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kAutofillScanCardholderName{
"AutofillScanCardholderName", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kAutofillCreditCardPopupLayout{
+ "AutofillCreditCardPopupLayout", base::FEATURE_DISABLED_BY_DEFAULT};
const char kCreditCardSigninPromoImpressionLimitParamKey[] = "impression_limit";
+const char kAutofillCreditCardPopupBackgroundColorKey[] = "background_color";
+const char kAutofillCreditCardPopupDividerColorKey[] = "dropdown_divider_color";
+const char kAutofillCreditCardPopupValueBoldKey[] = "is_value_bold";
+const char kAutofillCreditCardPopupIsValueAndLabelInSingleLineKey[] =
+ "is_value_and_label_in_single_line";
+const char kAutofillPopupDropdownItemHeightKey[] =
+ "dropdown_item_height";
+const char kAutofillCreditCardPopupIsIconAtStartKey[] =
+ "is_credit_card_icon_at_start";
+const char kAutofillPopupMarginKey[] = "margin";
+
+namespace {
+
+// Returns parameter value in |kAutofillCreditCardPopupLayout| feature, or 0 if
+// parameter is not specified.
+unsigned int GetCreditCardPopupParameterUintValue(
+ const std::string& param_name) {
+ unsigned int value;
+ const std::string param_value = variations::GetVariationParamValueByFeature(
+ kAutofillCreditCardPopupLayout, param_name);
+ if (!param_value.empty() && base::StringToUint(param_value, &value))
+ return value;
+ return 0;
+}
+
+} // namespace
bool IsAutofillEnabled(const PrefService* pref_service) {
return pref_service->GetBoolean(prefs::kAutofillEnabled);
@@ -40,10 +70,6 @@ bool IsInAutofillSuggestionsDisabledExperiment() {
return group_name == "Disabled";
}
-bool IsAutofillProfileCleanupEnabled() {
- return base::FeatureList::IsEnabled(kAutofillProfileCleanup);
-}
-
bool IsAutofillCreditCardSigninPromoEnabled() {
return base::FeatureList::IsEnabled(kAutofillCreditCardSigninPromo);
}
@@ -67,6 +93,64 @@ int GetCreditCardSigninPromoImpressionLimit() {
return 0;
}
+bool IsAutofillCreditCardPopupLayoutExperimentEnabled() {
+ return base::FeatureList::IsEnabled(kAutofillCreditCardPopupLayout);
+}
+
+// |GetCreditCardPopupParameterUintValue| returns 0 if experiment parameter is
+// not specified. 0 == |SK_ColorTRANSPARENT|.
+SkColor GetCreditCardPopupBackgroundColor() {
+ return GetCreditCardPopupParameterUintValue(
+ kAutofillCreditCardPopupBackgroundColorKey);
+}
+
+SkColor GetCreditCardPopupDividerColor() {
+ return GetCreditCardPopupParameterUintValue(
+ kAutofillCreditCardPopupDividerColorKey);
+}
+
+bool IsCreditCardPopupValueBold() {
+ const std::string param_value = variations::GetVariationParamValueByFeature(
+ kAutofillCreditCardPopupLayout, kAutofillCreditCardPopupValueBoldKey);
+ return param_value == "true";
+}
+
+unsigned int GetPopupDropdownItemHeight() {
+ return GetCreditCardPopupParameterUintValue(
+ kAutofillPopupDropdownItemHeightKey);
+}
+
+bool IsIconInCreditCardPopupAtStart() {
+ const std::string param_value = variations::GetVariationParamValueByFeature(
+ kAutofillCreditCardPopupLayout, kAutofillCreditCardPopupIsIconAtStartKey);
+ return param_value == "true";
+}
+
+// Modifies |suggestion| as follows if experiment to display value and label in
+// a single line is enabled.
+// Say, |value| is 'Visa ....1111' and |label| is '01/18' (expiration date).
+// Modifies |value| to 'Visa ....1111, exp 01/18' and clears |label|.
+void ModifyAutofillCreditCardSuggestion(Suggestion* suggestion) {
+ DCHECK(IsAutofillCreditCardPopupLayoutExperimentEnabled());
+ const std::string param_value = variations::GetVariationParamValueByFeature(
+ kAutofillCreditCardPopupLayout,
+ kAutofillCreditCardPopupIsValueAndLabelInSingleLineKey);
+ if (param_value == "true") {
+ const base::string16 format_string = l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE_LABEL_AND_ABBR);
+ if (!format_string.empty()) {
+ suggestion->value.append(l10n_util::GetStringFUTF16(
+ IDS_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE_LABEL_AND_ABBR,
+ suggestion->label));
+ }
+ suggestion->label.clear();
+ }
+}
+
+unsigned int GetPopupMargin() {
+ return GetCreditCardPopupParameterUintValue(kAutofillPopupMarginKey);
+}
+
bool OfferStoreUnmaskedCards() {
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
// The checkbox can be forced on with a flag, but by default we don't store
@@ -108,9 +192,9 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
// Users who have enabled a passphrase have chosen to not make their sync
// information accessible to Google. Since upload makes credit card data
// available to other Google systems, disable it for passphrase users.
- // We can't determine the passphrase state until the sync backend is
+ // We can't determine the passphrase state until the sync engine is
// initialized so disable upload if sync is not yet available.
- if (!sync_service->IsBackendInitialized() ||
+ if (!sync_service->IsEngineInitialized() ||
sync_service->IsUsingSecondaryPassphrase()) {
return false;
}
@@ -142,12 +226,4 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
return !group_name.empty() && group_name != "Disabled";
}
-bool IsCreditCardAutofillHttpWarningEnabled() {
- std::string choice =
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- security_state::switches::kMarkHttpAs);
- return choice == security_state::switches::
- kMarkHttpWithPasswordsOrCcWithChipAndFormWarning;
-}
-
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_experiments.h b/chromium/components/autofill/core/browser/autofill_experiments.h
index 9fe4fc0b556..4467e38d9b3 100644
--- a/chromium/components/autofill/core/browser/autofill_experiments.h
+++ b/chromium/components/autofill/core/browser/autofill_experiments.h
@@ -7,6 +7,9 @@
#include <string>
+#include "base/strings/string16.h"
+#include "third_party/skia/include/core/SkColor.h"
+
class PrefService;
namespace base {
@@ -19,11 +22,14 @@ class SyncService;
namespace autofill {
+struct Suggestion;
+
extern const base::Feature kAutofillCreditCardAssist;
extern const base::Feature kAutofillCreditCardSigninPromo;
-extern const base::Feature kAutofillProfileCleanup;
extern const base::Feature kAutofillScanCardholderName;
+extern const base::Feature kAutofillCreditCardPopupLayout;
extern const char kCreditCardSigninPromoImpressionLimitParamKey[];
+extern const char kAutofillCreditCardPopupSettingsSuggestionValueKey[];
// Returns true if autofill should be enabled. See also
// IsInAutofillSuggestionsDisabledExperiment below.
@@ -35,9 +41,6 @@ bool IsAutofillEnabled(const PrefService* pref_service);
// disables providing suggestions.
bool IsInAutofillSuggestionsDisabledExperiment();
-// Returns whether the Autofill profile cleanup feature is enabled.
-bool IsAutofillProfileCleanupEnabled();
-
// Returns whether the Autofill credit card signin promo should be shown.
bool IsAutofillCreditCardSigninPromoEnabled();
@@ -60,9 +63,41 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
const syncer::SyncService* sync_service,
const std::string& user_email);
-// Returns true if the http warning switch is on, which will display a warning
-// in the autofill dropdown when credit card fields are on an HTTP page.
-bool IsCreditCardAutofillHttpWarningEnabled();
+// Returns whether the new Autofill credit card popup layout experiment is
+// enabled.
+bool IsAutofillCreditCardPopupLayoutExperimentEnabled();
+
+// Returns the background color for credit card autofill popup, or
+// |SK_ColorTRANSPARENT| if the new credit card autofill popup layout experiment
+// is not enabled.
+SkColor GetCreditCardPopupBackgroundColor();
+
+// Returns the divider color for credit card autofill popup, or
+// |SK_ColorTRANSPARENT| if the new credit card autofill popup layout experiment
+// is not enabled.
+SkColor GetCreditCardPopupDividerColor();
+
+// Returns true if the credit card autofill popup suggestion value is displayed
+// in bold type face.
+bool IsCreditCardPopupValueBold();
+
+// Returns the dropdown item height for autofill popup, returning 0 if the
+// dropdown item height isn't configured in an experiment to tweak autofill
+// popup layout.
+unsigned int GetPopupDropdownItemHeight();
+
+// Returns true if the icon in the credit card autofill popup must be displayed
+// before the credit card value or any other suggestion text.
+bool IsIconInCreditCardPopupAtStart();
+
+// Modifies the suggestion value and label if the new credit card autofill popup
+// experiment is enabled to tweak the display of the value and label.
+void ModifyAutofillCreditCardSuggestion(struct Suggestion* suggestion);
+
+// Returns the margin for the icon, label and between icon and label. Returns 0
+// if the margin isn't configured in an experiment to tweak autofill popup
+// layout.
+unsigned int GetPopupMargin();
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_external_delegate.cc b/chromium/components/autofill/core/browser/autofill_external_delegate.cc
index 96a96c34879..e80c8ac5461 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate.cc
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate.cc
@@ -19,6 +19,7 @@
#include "build/build_config.h"
#include "components/autofill/core/browser/autocomplete_history_manager.h"
#include "components/autofill/core/browser/autofill_driver.h"
+#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/popup_item_ids.h"
@@ -31,9 +32,11 @@ namespace autofill {
namespace {
// Returns true if the suggestion entry is an Autofill warning message.
-// Warning message should display on top of suggestion list.
+// Warning messages should display on top of suggestion list.
bool IsAutofillWarningEntry(int frontend_id) {
- return frontend_id == POPUP_ITEM_ID_WARNING_MESSAGE;
+ return frontend_id ==
+ POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE ||
+ frontend_id == POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE;
}
} // anonymous namespace
@@ -46,6 +49,7 @@ AutofillExternalDelegate::AutofillExternalDelegate(AutofillManager* manager,
has_autofill_suggestions_(false),
has_shown_popup_for_current_edit_(false),
should_show_scan_credit_card_(false),
+ is_credit_card_popup_(false),
should_show_cc_signin_promo_(false),
has_shown_address_book_prompt(false),
weak_ptr_factory_(this) {
@@ -67,6 +71,8 @@ void AutofillExternalDelegate::OnQuery(int query_id,
element_bounds_ = element_bounds;
should_show_scan_credit_card_ =
manager_->ShouldShowScanCreditCard(query_form_, query_field_);
+ is_credit_card_popup_ =
+ manager_->IsCreditCardPopup(query_form_, query_field_);
should_show_cc_signin_promo_ =
manager_->ShouldShowCreditCardSigninPromo(query_form_, query_field_);
}
@@ -210,7 +216,8 @@ void AutofillExternalDelegate::DidAcceptSuggestion(const base::string16& value,
} else if (identifier == POPUP_ITEM_ID_CLEAR_FORM) {
// User selected 'Clear form'.
driver_->RendererShouldClearFilledForm();
- } else if (identifier == POPUP_ITEM_ID_PASSWORD_ENTRY) {
+ } else if (identifier == POPUP_ITEM_ID_PASSWORD_ENTRY ||
+ identifier == POPUP_ITEM_ID_USERNAME_ENTRY) {
NOTREACHED(); // Should be handled elsewhere.
} else if (identifier == POPUP_ITEM_ID_DATALIST_ENTRY) {
driver_->RendererShouldAcceptDataListSuggestion(value);
@@ -223,6 +230,9 @@ void AutofillExternalDelegate::DidAcceptSuggestion(const base::string16& value,
&AutofillExternalDelegate::OnCreditCardScanned, GetWeakPtr()));
} else if (identifier == POPUP_ITEM_ID_CREDIT_CARD_SIGNIN_PROMO) {
manager_->client()->StartSigninFlow();
+ } else if (identifier == POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE) {
+ AutofillMetrics::LogShowedHttpNotSecureExplanation();
+ manager_->client()->ShowHttpNotSecureExplanation();
} else {
if (identifier > 0) // Denotes an Autofill suggestion.
AutofillMetrics::LogAutofillSuggestionAcceptedIndex(position);
@@ -271,14 +281,12 @@ void AutofillExternalDelegate::ClearPreviewedForm() {
driver_->RendererShouldClearPreviewedForm();
}
-void AutofillExternalDelegate::Reset() {
- manager_->client()->HideAutofillPopup();
+bool AutofillExternalDelegate::IsCreditCardPopup() {
+ return is_credit_card_popup_;
}
-void AutofillExternalDelegate::OnPingAck() {
- // Reissue the most recent query, which will reopen the Autofill popup.
- manager_->OnQueryFormFieldAutofill(query_id_, query_form_, query_field_,
- element_bounds_);
+void AutofillExternalDelegate::Reset() {
+ manager_->client()->HideAutofillPopup();
}
base::WeakPtr<AutofillExternalDelegate> AutofillExternalDelegate::GetWeakPtr() {
@@ -293,7 +301,7 @@ void AutofillExternalDelegate::OnCreditCardScanned(const CreditCard& card) {
void AutofillExternalDelegate::FillAutofillFormData(int unique_id,
bool is_preview) {
// If the selected element is a warning we don't want to do anything.
- if (unique_id == POPUP_ITEM_ID_WARNING_MESSAGE)
+ if (IsAutofillWarningEntry(unique_id))
return;
AutofillDriver::RendererFormDataAction renderer_action = is_preview ?
@@ -327,8 +335,6 @@ void AutofillExternalDelegate::ApplyAutofillOptions(
if (query_field_.is_autofilled) {
base::string16 value =
l10n_util::GetStringUTF16(IDS_AUTOFILL_CLEAR_FORM_MENU_ITEM);
- // TODO(rouslan): Remove manual upper-casing when keyboard accessory becomes
- // default on Android.
if (IsKeyboardAccessoryEnabled())
value = base::i18n::ToUpper(value);
@@ -336,12 +342,9 @@ void AutofillExternalDelegate::ApplyAutofillOptions(
suggestions->back().frontend_id = POPUP_ITEM_ID_CLEAR_FORM;
}
- // Append the 'Chrome Autofill options' menu item;
- // TODO(rouslan): Switch on the platform in the GRD file when keyboard
- // accessory becomes default on Android.
- suggestions->push_back(Suggestion(l10n_util::GetStringUTF16(
- IsKeyboardAccessoryEnabled() ? IDS_AUTOFILL_OPTIONS_CONTENT_DESCRIPTION
- : IDS_AUTOFILL_OPTIONS_POPUP)));
+ // Append the 'Chrome Autofill options' menu item, or the menu item specified
+ // in the popup layout experiment.
+ suggestions->push_back(Suggestion(GetSettingsSuggestionValue()));
suggestions->back().frontend_id = POPUP_ITEM_ID_AUTOFILL_OPTIONS;
if (IsKeyboardAccessoryEnabled())
suggestions->back().icon = base::ASCIIToUTF16("settings");
@@ -384,4 +387,14 @@ void AutofillExternalDelegate::InsertDataListValues(
}
}
+base::string16 AutofillExternalDelegate::GetSettingsSuggestionValue()
+ const {
+ if (IsKeyboardAccessoryEnabled()) {
+ return l10n_util::GetStringUTF16(IDS_AUTOFILL_OPTIONS_CONTENT_DESCRIPTION);
+ }
+ return l10n_util::GetStringUTF16(is_credit_card_popup_ ?
+ IDS_AUTOFILL_CREDIT_CARD_OPTIONS_POPUP :
+ IDS_AUTOFILL_OPTIONS_POPUP);
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_external_delegate.h b/chromium/components/autofill/core/browser/autofill_external_delegate.h
index 5431b31fe6c..6a9807a0505 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate.h
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate.h
@@ -51,6 +51,9 @@ class AutofillExternalDelegate : public AutofillPopupDelegate {
base::string16* body) override;
bool RemoveSuggestion(const base::string16& value, int identifier) override;
void ClearPreviewedForm() override;
+ // Returns false for all popups prior to |onQuery|, true for credit card
+ // popups after call to |onQuery|.
+ bool IsCreditCardPopup() override;
// Records and associates a query_id with web form data. Called
// when the renderer posts an Autofill query to the browser. |bounds|
@@ -81,9 +84,6 @@ class AutofillExternalDelegate : public AutofillPopupDelegate {
// values or settings.
void Reset();
- // The renderer sent an IPC acknowledging an earlier ping IPC.
- void OnPingAck();
-
protected:
base::WeakPtr<AutofillExternalDelegate> GetWeakPtr();
@@ -118,6 +118,9 @@ class AutofillExternalDelegate : public AutofillPopupDelegate {
// version.
void InsertDataListValues(std::vector<Suggestion>* suggestions);
+ // Returns the text (i.e. |Suggestion| value) for Chrome autofill options.
+ base::string16 GetSettingsSuggestionValue() const;
+
AutofillManager* manager_; // weak.
// Provides driver-level context to the shared code of the component. Must
@@ -142,8 +145,8 @@ class AutofillExternalDelegate : public AutofillPopupDelegate {
// currently editing? Used to keep track of state for metrics logging.
bool has_shown_popup_for_current_edit_;
- // FIXME
bool should_show_scan_credit_card_;
+ bool is_credit_card_popup_;
// Whether the credit card signin promo should be shown to the user.
bool should_show_cc_signin_promo_;
diff --git a/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc b/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc
index 709c73444dd..97bd64b385c 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc
@@ -80,6 +80,8 @@ class MockAutofillClient : public TestAutofillClient {
MOCK_METHOD0(StartSigninFlow, void());
+ MOCK_METHOD0(ShowHttpNotSecureExplanation, void());
+
private:
DISALLOW_COPY_AND_ASSIGN(MockAutofillClient);
};
@@ -463,16 +465,15 @@ TEST_F(AutofillExternalDelegateUnitTest, AutofillWarnings) {
EXPECT_CALL(
autofill_client_,
ShowAutofillPopup(
- _,
- _,
- SuggestionVectorIdsAre(testing::ElementsAre(
- static_cast<int>(POPUP_ITEM_ID_WARNING_MESSAGE))),
+ _, _, SuggestionVectorIdsAre(testing::ElementsAre(static_cast<int>(
+ POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE))),
_));
// This should call ShowAutofillPopup.
std::vector<Suggestion> autofill_item;
autofill_item.push_back(Suggestion());
- autofill_item[0].frontend_id = POPUP_ITEM_ID_WARNING_MESSAGE;
+ autofill_item[0].frontend_id =
+ POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE;
external_delegate_->OnSuggestionsReturned(kQueryId, autofill_item);
}
@@ -493,9 +494,10 @@ TEST_F(AutofillExternalDelegateUnitTest,
// This should call ShowAutofillPopup.
std::vector<Suggestion> suggestions;
suggestions.push_back(Suggestion());
- suggestions[0].frontend_id = POPUP_ITEM_ID_WARNING_MESSAGE;
+ suggestions[0].frontend_id = POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE;
suggestions.push_back(Suggestion());
- suggestions[1].frontend_id = POPUP_ITEM_ID_WARNING_MESSAGE;
+ suggestions[1].frontend_id =
+ POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE;
suggestions.push_back(Suggestion());
suggestions[2].value = ASCIIToUTF16("Rick");
suggestions[2].frontend_id = POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY;
@@ -671,6 +673,15 @@ TEST_F(AutofillExternalDelegateUnitTest, SigninPromoMenuItem) {
base::string16(), POPUP_ITEM_ID_CREDIT_CARD_SIGNIN_PROMO, 0);
}
+// Test that autofill client will open the security indicator help center url
+// after the user accepted the http warning message suggestion item.
+TEST_F(AutofillExternalDelegateUnitTest, HttpWarningMessageItem) {
+ EXPECT_CALL(autofill_client_, ShowHttpNotSecureExplanation());
+ EXPECT_CALL(autofill_client_, HideAutofillPopup());
+ external_delegate_->DidAcceptSuggestion(
+ base::string16(), POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE, 0);
+}
+
MATCHER_P(CreditCardMatches, card, "") {
return !arg.Compare(card);
}
diff --git a/chromium/components/autofill/core/browser/autofill_manager.cc b/chromium/components/autofill/core/browser/autofill_manager.cc
index 7923e0bc9d5..977e67ae874 100644
--- a/chromium/components/autofill/core/browser/autofill_manager.cc
+++ b/chromium/components/autofill/core/browser/autofill_manager.cc
@@ -50,6 +50,7 @@
#include "components/autofill/core/browser/phone_number.h"
#include "components/autofill/core/browser/phone_number_i18n.h"
#include "components/autofill/core/browser/popup_item_ids.h"
+#include "components/autofill/core/browser/validation.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_data_validation.h"
#include "components/autofill/core/common/autofill_pref_names.h"
@@ -60,7 +61,9 @@
#include "components/autofill/core/common/password_form_fill_data.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
-#include "components/rappor/rappor_utils.h"
+#include "components/rappor/public/rappor_utils.h"
+#include "components/rappor/rappor_service_impl.h"
+#include "components/security_state/core/security_state.h"
#include "google_apis/gaia/identity_provider.h"
#include "grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"
@@ -183,6 +186,23 @@ bool IsCreditCardExpirationType(ServerFieldType type) {
type == CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR;
}
+// Create http bad warning message at the top of autofill popup list showing
+// "Payment not secure" when users are on http sites or broken https sites.
+Suggestion CreateHttpWarningMessageSuggestionItem(const GURL& source_url) {
+ Suggestion cc_field_http_warning_suggestion(
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_CREDIT_CARD_HTTP_WARNING_MESSAGE));
+ cc_field_http_warning_suggestion.frontend_id =
+ POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE;
+ cc_field_http_warning_suggestion.label =
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_HTTP_WARNING_LEARN_MORE);
+ cc_field_http_warning_suggestion.icon =
+ (source_url.is_valid() && source_url.SchemeIs("http"))
+ ? base::ASCIIToUTF16("httpWarning")
+ : base::ASCIIToUTF16("httpsInvalid");
+
+ return cc_field_http_warning_suggestion;
+}
+
} // namespace
AutofillManager::AutofillManager(
@@ -290,6 +310,12 @@ bool AutofillManager::ShouldShowScanCreditCard(const FormData& form,
return field.value.size() <= kShowScanCreditCardMaxValueLength;
}
+bool AutofillManager::IsCreditCardPopup(const FormData& form,
+ const FormFieldData& field) {
+ AutofillField* autofill_field = GetAutofillField(form, field);
+ return autofill_field && autofill_field->Type().group() == CREDIT_CARD;
+}
+
bool AutofillManager::ShouldShowCreditCardSigninPromo(
const FormData& form,
const FormFieldData& field) {
@@ -510,8 +536,6 @@ void AutofillManager::OnQueryFormFieldAutofill(int query_id,
if (!IsValidFormData(form) || !IsValidFormFieldData(field))
return;
- std::vector<Suggestion> suggestions;
-
gfx::RectF transformed_box =
driver_->TransformBoundingBoxToViewportCoordinates(bounding_box);
external_delegate_->OnQuery(query_id, form, field, transformed_box);
@@ -526,9 +550,12 @@ void AutofillManager::OnQueryFormFieldAutofill(int query_id,
// Don't send suggestions or track forms that should not be parsed.
form_structure->ShouldBeParsed();
- // Logging interactions of forms that are autofillable.
+ bool is_filling_credit_card = false;
+
+ // Log interactions of forms that are autofillable.
if (got_autofillable_form) {
if (autofill_field->Type().group() == CREDIT_CARD) {
+ is_filling_credit_card = true;
driver_->DidInteractWithCreditCardForm();
credit_card_form_event_logger_->OnDidInteractWithAutofillableForm();
} else {
@@ -536,11 +563,18 @@ void AutofillManager::OnQueryFormFieldAutofill(int query_id,
}
}
+ std::vector<Suggestion> suggestions;
+ const bool is_context_secure =
+ !form_structure ||
+ (client_->IsContextSecure() &&
+ (!form_structure->target_url().is_valid() ||
+ !form_structure->target_url().SchemeIs("http")));
+ const bool is_http_warning_enabled =
+ security_state::IsHttpWarningInFormEnabled();
+
if (is_autofill_possible &&
driver_->RendererIsAvailable() &&
got_autofillable_form) {
- AutofillType type = autofill_field->Type();
- bool is_filling_credit_card = (type.group() == CREDIT_CARD);
// On desktop, don't return non credit card related suggestions for forms or
// fields that have the "autocomplete" attribute set to off.
if (IsDesktopPlatform() && !is_filling_credit_card &&
@@ -548,16 +582,13 @@ void AutofillManager::OnQueryFormFieldAutofill(int query_id,
return;
}
if (is_filling_credit_card) {
- suggestions = GetCreditCardSuggestions(field, type);
+ suggestions = GetCreditCardSuggestions(field, autofill_field->Type());
} else {
suggestions =
GetProfileSuggestions(*form_structure, field, *autofill_field);
}
+
if (!suggestions.empty()) {
- bool is_context_secure =
- client_->IsContextSecure(form_structure->source_url()) &&
- (!form_structure->target_url().is_valid() ||
- !form_structure->target_url().SchemeIs("http"));
if (is_filling_credit_card)
AutofillMetrics::LogIsQueriedCreditCardFormSecure(is_context_secure);
@@ -566,26 +597,18 @@ void AutofillManager::OnQueryFormFieldAutofill(int query_id,
// IsContextSecure).
if (is_filling_credit_card && !is_context_secure) {
// Replace the suggestion content with a warning message explaining why
- // Autofill is disabled for a website.
+ // Autofill is disabled for a website. The string is different if the
+ // credit card autofill HTTP warning experiment is enabled.
Suggestion warning_suggestion(l10n_util::GetStringUTF16(
- IDS_AUTOFILL_WARNING_INSECURE_CONNECTION));
- warning_suggestion.frontend_id = POPUP_ITEM_ID_WARNING_MESSAGE;
+ is_http_warning_enabled
+ ? IDS_AUTOFILL_WARNING_PAYMENT_DISABLED
+ : IDS_AUTOFILL_WARNING_INSECURE_CONNECTION));
+ warning_suggestion.frontend_id =
+ POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE;
suggestions.assign(1, warning_suggestion);
-
- // On top of the explanation message, first show a "Payment not secure"
- // message.
- if (IsCreditCardAutofillHttpWarningEnabled()) {
- Suggestion cc_field_http_warning_suggestion(l10n_util::GetStringUTF16(
- IDS_AUTOFILL_CREDIT_CARD_HTTP_WARNING_MESSAGE));
- cc_field_http_warning_suggestion.frontend_id =
- POPUP_ITEM_ID_WARNING_MESSAGE;
- suggestions.insert(suggestions.begin(),
- cc_field_http_warning_suggestion);
- }
} else {
- bool section_is_autofilled =
- SectionIsAutofilled(*form_structure, form,
- autofill_field->section());
+ bool section_is_autofilled = SectionIsAutofilled(
+ *form_structure, form, autofill_field->section());
if (section_is_autofilled) {
// If the relevant section is auto-filled and the renderer is querying
// for suggestions, then the user is editing the value of a field.
@@ -617,6 +640,21 @@ void AutofillManager::OnQueryFormFieldAutofill(int query_id,
}
}
+ // Show a "Payment not secure" message.
+ if (!is_context_secure && is_filling_credit_card && is_http_warning_enabled) {
+#if !defined(OS_ANDROID)
+ if (!suggestions.empty()) {
+ suggestions.insert(suggestions.begin(), Suggestion());
+ suggestions.front().frontend_id = POPUP_ITEM_ID_SEPARATOR;
+ }
+#endif
+
+ suggestions.insert(
+ suggestions.begin(),
+ CreateHttpWarningMessageSuggestionItem(
+ form_structure ? form_structure->source_url() : GURL::EmptyGURL()));
+ }
+
// If there are no Autofill suggestions, consider showing Autocomplete
// suggestions. We will not show Autocomplete suggestions for a field that
// specifies autocomplete=off (or an unrecognized type), a field for which we
@@ -948,7 +986,7 @@ void AutofillManager::OnLoadedServerPredictions(
// Parse and store the server predictions.
FormStructure::ParseQueryResponse(std::move(response), queried_forms,
- client_->GetRapporService());
+ client_->GetRapporServiceImpl());
// Will log quality metrics for each FormStructure based on the presence of
// autocomplete attributes, if available.
@@ -1091,7 +1129,7 @@ void AutofillManager::ImportFormData(const FormStructure& submitted_form) {
recently_autofilled_forms_.push_back(
std::map<std::string, base::string16>());
auto& map = recently_autofilled_forms_.back();
- for (const auto* field : submitted_form) {
+ for (const auto& field : submitted_form) {
AutofillType type = field->Type();
// Even though this is for development only, mask full credit card #'s.
if (type.GetStorableType() == CREDIT_CARD_NUMBER &&
@@ -1131,10 +1169,10 @@ void AutofillManager::ImportFormData(const FormStructure& submitted_form) {
// their card. If no CVC is present, do nothing. We could fall back to a
// local save but we believe that sometimes offering upload and sometimes
// offering local save is a confusing user experience.
- int cvc;
- for (const AutofillField* field : submitted_form) {
+ for (const auto& field : submitted_form) {
if (field->Type().GetStorableType() == CREDIT_CARD_VERIFICATION_CODE &&
- base::StringToInt(field->value, &cvc)) {
+ IsValidCreditCardSecurityCode(field->value,
+ upload_request_.card.type())) {
upload_request_.cvc = field->value;
break;
}
@@ -1268,8 +1306,8 @@ bool AutofillManager::GetProfilesForCreditCardUpload(
void AutofillManager::CollectRapportSample(const GURL& source_url,
const char* metric_name) const {
- if (source_url.is_valid() && client_->GetRapporService()) {
- rappor::SampleDomainAndRegistryFromGURL(client_->GetRapporService(),
+ if (source_url.is_valid() && client_->GetRapporServiceImpl()) {
+ rappor::SampleDomainAndRegistryFromGURL(client_->GetRapporServiceImpl(),
metric_name, source_url);
}
}
@@ -1284,9 +1322,10 @@ void AutofillManager::UploadFormDataAsyncCallback(
const TimeTicks& interaction_time,
const TimeTicks& submission_time,
bool observed_submission) {
- submitted_form->LogQualityMetrics(
- load_time, interaction_time, submission_time, client_->GetRapporService(),
- did_show_suggestions_, observed_submission);
+ submitted_form->LogQualityMetrics(load_time, interaction_time,
+ submission_time,
+ client_->GetRapporServiceImpl(),
+ did_show_suggestions_, observed_submission);
if (submitted_form->ShouldBeCrowdsourced())
UploadFormData(*submitted_form, observed_submission);
@@ -1400,6 +1439,8 @@ bool AutofillManager::RefreshDataModels() {
is_server_data_available);
credit_card_form_event_logger_->set_is_local_data_available(
is_local_data_available);
+ credit_card_form_event_logger_->set_is_context_secure(
+ client_->IsContextSecure());
}
{
bool is_server_data_available = false;
@@ -1647,9 +1688,9 @@ bool AutofillManager::GetCachedFormAndField(const FormData& form,
// Find the AutofillField that corresponds to |field|.
*autofill_field = NULL;
- for (AutofillField* current : **form_structure) {
+ for (const auto& current : **form_structure) {
if (current->SameFieldAs(field)) {
- *autofill_field = current;
+ *autofill_field = current.get();
break;
}
}
@@ -1769,6 +1810,7 @@ std::vector<Suggestion> AutofillManager::GetCreditCardSuggestions(
for (size_t i = 0; i < suggestions.size(); i++) {
suggestions[i].frontend_id =
MakeFrontendID(suggestions[i].backend_id, std::string());
+ suggestions[i].is_value_bold = IsCreditCardPopupValueBold();
}
return suggestions;
}
diff --git a/chromium/components/autofill/core/browser/autofill_manager.h b/chromium/components/autofill/core/browser/autofill_manager.h
index f3d3e2f762e..ce8608f03db 100644
--- a/chromium/components/autofill/core/browser/autofill_manager.h
+++ b/chromium/components/autofill/core/browser/autofill_manager.h
@@ -44,7 +44,6 @@
#endif
namespace gfx {
-class Rect;
class RectF;
}
@@ -97,6 +96,10 @@ class AutofillManager : public AutofillDownloadManager::Observer,
virtual bool ShouldShowScanCreditCard(const FormData& form,
const FormFieldData& field);
+ // Whether the |field| belongs to CREDIT_CARD |FieldTypeGroup|.
+ virtual bool IsCreditCardPopup(const FormData& form,
+ const FormFieldData& field);
+
// Whether we should show the signin promo, based on the triggered |field|
// inside the |form|.
virtual bool ShouldShowCreditCardSigninPromo(const FormData& form,
diff --git a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc b/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
index eea68f0a4b9..38264eda18c 100644
--- a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -49,7 +49,7 @@
#include "components/autofill/core/common/form_field_data.h"
#include "components/prefs/pref_service.h"
#include "components/rappor/test_rappor_service.h"
-#include "components/security_state/core/switches.h"
+#include "components/security_state/core/security_state.h"
#include "components/variations/variations_associated_data.h"
#include "grit/components_strings.h"
#include "net/url_request/url_request_test_util.h"
@@ -72,6 +72,13 @@ namespace {
const int kDefaultPageID = 137;
+const std::string kUTF8MidlineEllipsis =
+ " "
+ "\xE2\x80\xA2\xE2\x80\x86"
+ "\xE2\x80\xA2\xE2\x80\x86"
+ "\xE2\x80\xA2\xE2\x80\x86"
+ "\xE2\x80\xA2\xE2\x80\x86";
+
class MockAutofillClient : public TestAutofillClient {
public:
MockAutofillClient() {}
@@ -688,7 +695,7 @@ class TestAutofillExternalDelegate : public AutofillExternalDelegate {
EXPECT_TRUE(on_suggestions_returned_seen_);
EXPECT_EQ(expected_page_id, query_id_);
- ASSERT_EQ(expected_num_suggestions, suggestions_.size());
+ ASSERT_LE(expected_num_suggestions, suggestions_.size());
for (size_t i = 0; i < expected_num_suggestions; ++i) {
SCOPED_TRACE(base::StringPrintf("i: %" PRIuS, i));
EXPECT_EQ(expected_suggestions[i].value, suggestions_[i].value);
@@ -697,6 +704,7 @@ class TestAutofillExternalDelegate : public AutofillExternalDelegate {
EXPECT_EQ(expected_suggestions[i].frontend_id,
suggestions_[i].frontend_id);
}
+ ASSERT_EQ(expected_num_suggestions, suggestions_.size());
}
// Wrappers around the above GetSuggestions call that take a hardcoded number
@@ -1012,10 +1020,8 @@ class AutofillManagerTest : public testing::Test {
}
void SetHttpWarningEnabled() {
- base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
- security_state::switches::kMarkHttpAs,
- security_state::switches::
- kMarkHttpWithPasswordsOrCcWithChipAndFormWarning);
+ scoped_feature_list_.InitAndEnableFeature(
+ security_state::kHttpFormWarningFeature);
}
protected:
@@ -1265,6 +1271,24 @@ TEST_F(AutofillManagerTest, GetProfileSuggestions_EmptyValue) {
Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 2));
}
+// Test that the HttpWarning does not appear on non-payment forms.
+TEST_F(AutofillManagerTest, GetProfileSuggestions_EmptyValueNotSecure) {
+ SetHttpWarningEnabled();
+ // Set up our form data.
+ FormData form;
+ test::CreateTestAddressFormData(&form);
+ std::vector<FormData> forms(1, form);
+ FormsSeen(forms);
+
+ const FormFieldData& field = form.fields[0];
+ GetAutofillSuggestions(form, field);
+
+ // Test that we sent the right values to the external delegate.
+ external_delegate_->CheckSuggestions(
+ kDefaultPageID, Suggestion("Charles", "123 Apple St.", "", 1),
+ Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 2));
+}
+
// Test that we return only matching address profile suggestions when the
// selected form field has been partially filled out.
TEST_F(AutofillManagerTest, GetProfileSuggestions_MatchCharacter) {
@@ -1439,14 +1463,11 @@ TEST_F(AutofillManagerTest, GetCreditCardSuggestions_EmptyValue) {
// Test that we sent the right values to the external delegate.
external_delegate_->CheckSuggestions(
- kDefaultPageID, Suggestion("Visa\xC2\xA0\xE2\x8B\xAF"
- "3456",
+ kDefaultPageID, Suggestion("Visa" + kUTF8MidlineEllipsis + "3456",
"04/99", kVisaCard,
autofill_manager_->GetPackedCreditCardID(4)),
- Suggestion("MasterCard\xC2\xA0\xE2\x8B\xAF"
- "8765",
- "10/98", kMasterCard,
- autofill_manager_->GetPackedCreditCardID(5)));
+ Suggestion("MasterCard" + kUTF8MidlineEllipsis + "8765", "10/98",
+ kMasterCard, autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we return all credit card profile suggestions when the triggering
@@ -1464,14 +1485,11 @@ TEST_F(AutofillManagerTest, GetCreditCardSuggestions_Whitespace) {
// Test that we sent the right values to the external delegate.
external_delegate_->CheckSuggestions(
- kDefaultPageID, Suggestion("Visa\xC2\xA0\xE2\x8B\xAF"
- "3456",
+ kDefaultPageID, Suggestion("Visa" + kUTF8MidlineEllipsis + "3456",
"04/99", kVisaCard,
autofill_manager_->GetPackedCreditCardID(4)),
- Suggestion("MasterCard\xC2\xA0\xE2\x8B\xAF"
- "8765",
- "10/98", kMasterCard,
- autofill_manager_->GetPackedCreditCardID(5)));
+ Suggestion("MasterCard" + kUTF8MidlineEllipsis + "8765", "10/98",
+ kMasterCard, autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we return all credit card profile suggestions when the triggering
@@ -1489,14 +1507,11 @@ TEST_F(AutofillManagerTest, GetCreditCardSuggestions_StopCharsOnly) {
// Test that we sent the right values to the external delegate.
external_delegate_->CheckSuggestions(
- kDefaultPageID, Suggestion("Visa\xC2\xA0\xE2\x8B\xAF"
- "3456",
+ kDefaultPageID, Suggestion("Visa" + kUTF8MidlineEllipsis + "3456",
"04/99", kVisaCard,
autofill_manager_->GetPackedCreditCardID(4)),
- Suggestion("MasterCard\xC2\xA0\xE2\x8B\xAF"
- "8765",
- "10/98", kMasterCard,
- autofill_manager_->GetPackedCreditCardID(5)));
+ Suggestion("MasterCard" + kUTF8MidlineEllipsis + "8765", "10/98",
+ kMasterCard, autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we return all credit card profile suggestions when the triggering
@@ -1523,8 +1538,7 @@ TEST_F(AutofillManagerTest, GetCreditCardSuggestions_StopCharsWithInput) {
// Test that we sent the right value to the external delegate.
external_delegate_->CheckSuggestions(
- kDefaultPageID, Suggestion("MasterCard\xC2\xA0\xE2\x8B\xAF"
- "3123",
+ kDefaultPageID, Suggestion("MasterCard" + kUTF8MidlineEllipsis + "3123",
"08/17", kMasterCard,
autofill_manager_->GetPackedCreditCardID(7)));
}
@@ -1544,8 +1558,7 @@ TEST_F(AutofillManagerTest, GetCreditCardSuggestions_MatchCharacter) {
// Test that we sent the right values to the external delegate.
external_delegate_->CheckSuggestions(
- kDefaultPageID, Suggestion("Visa\xC2\xA0\xE2\x8B\xAF"
- "3456",
+ kDefaultPageID, Suggestion("Visa" + kUTF8MidlineEllipsis + "3456",
"04/99", kVisaCard,
autofill_manager_->GetPackedCreditCardID(4)));
}
@@ -1563,15 +1576,13 @@ TEST_F(AutofillManagerTest, GetCreditCardSuggestions_NonCCNumber) {
GetAutofillSuggestions(form, field);
#if defined(OS_ANDROID)
- static const char* kVisaSuggestion =
- "Visa\xC2\xA0\xE2\x8B\xAF"
- "3456";
- static const char* kMcSuggestion =
- "MasterCard\xC2\xA0\xE2\x8B\xAF"
- "8765";
+ static const std::string kVisaSuggestion =
+ "Visa" + kUTF8MidlineEllipsis + "3456";
+ static const std::string kMcSuggestion =
+ "MasterCard" + kUTF8MidlineEllipsis + "8765";
#else
- static const char* kVisaSuggestion = "*3456";
- static const char* kMcSuggestion = "*8765";
+ static const std::string kVisaSuggestion = "*3456";
+ static const std::string kMcSuggestion = "*8765";
#endif
// Test that we sent the right values to the external delegate.
@@ -1629,16 +1640,26 @@ TEST_F(AutofillManagerTest,
kDefaultPageID,
Suggestion(l10n_util::GetStringUTF8(
IDS_AUTOFILL_CREDIT_CARD_HTTP_WARNING_MESSAGE),
- "", "", -1),
+ l10n_util::GetStringUTF8(IDS_AUTOFILL_HTTP_WARNING_LEARN_MORE),
+ "httpWarning", POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE),
+#if !defined(OS_ANDROID)
+ Suggestion("", "", "", POPUP_ITEM_ID_SEPARATOR),
+#endif
Suggestion(
- l10n_util::GetStringUTF8(IDS_AUTOFILL_WARNING_INSECURE_CONNECTION),
- "", "", -1));
+ l10n_util::GetStringUTF8(IDS_AUTOFILL_WARNING_PAYMENT_DISABLED), "",
+ "", POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE));
- // Clear the test credit cards and try again -- we shouldn't return a warning.
+ // Clear the test credit cards and try again -- we should still show the
+ // warning.
personal_data_.ClearCreditCards();
GetAutofillSuggestions(form, field);
- // Autocomplete suggestions are queried, but not Autofill.
- EXPECT_FALSE(external_delegate_->on_suggestions_returned_seen());
+ // Test that we sent the right values to the external delegate.
+ external_delegate_->CheckSuggestions(
+ kDefaultPageID,
+ Suggestion(l10n_util::GetStringUTF8(
+ IDS_AUTOFILL_CREDIT_CARD_HTTP_WARNING_MESSAGE),
+ l10n_util::GetStringUTF8(IDS_AUTOFILL_HTTP_WARNING_LEARN_MORE),
+ "httpWarning", POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE));
}
// Test that we don't show the extra "Payment not secure" warning when the page
@@ -1658,14 +1679,11 @@ TEST_F(AutofillManagerTest,
// Test that we sent the right values to the external delegate.
external_delegate_->CheckSuggestions(
- kDefaultPageID, Suggestion("Visa\xC2\xA0\xE2\x8B\xAF"
- "3456",
+ kDefaultPageID, Suggestion("Visa" + kUTF8MidlineEllipsis + "3456",
"04/99", kVisaCard,
autofill_manager_->GetPackedCreditCardID(4)),
- Suggestion("MasterCard\xC2\xA0\xE2\x8B\xAF"
- "8765",
- "10/98", kMasterCard,
- autofill_manager_->GetPackedCreditCardID(5)));
+ Suggestion("MasterCard" + kUTF8MidlineEllipsis + "8765", "10/98",
+ kMasterCard, autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we will eventually return the credit card signin promo when there
@@ -1749,14 +1767,11 @@ TEST_F(AutofillManagerTest,
// Test that we sent the right values to the external delegate.
external_delegate_->CheckSuggestions(
- kDefaultPageID, Suggestion("Visa\xC2\xA0\xE2\x8B\xAF"
- "3456",
+ kDefaultPageID, Suggestion("Visa" + kUTF8MidlineEllipsis + "3456",
"04/99", kVisaCard,
autofill_manager_->GetPackedCreditCardID(4)),
- Suggestion("MasterCard\xC2\xA0\xE2\x8B\xAF"
- "8765",
- "10/98", kMasterCard,
- autofill_manager_->GetPackedCreditCardID(5)));
+ Suggestion("MasterCard" + kUTF8MidlineEllipsis + "8765", "10/98",
+ kMasterCard, autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we return credit card suggestions for secure pages that have a
@@ -1776,14 +1791,11 @@ TEST_F(AutofillManagerTest,
// Test that we sent the right values to the external delegate.
external_delegate_->CheckSuggestions(
- kDefaultPageID, Suggestion("Visa\xC2\xA0\xE2\x8B\xAF"
- "3456",
+ kDefaultPageID, Suggestion("Visa" + kUTF8MidlineEllipsis + "3456",
"04/99", kVisaCard,
autofill_manager_->GetPackedCreditCardID(4)),
- Suggestion("MasterCard\xC2\xA0\xE2\x8B\xAF"
- "8765",
- "10/98", kMasterCard,
- autofill_manager_->GetPackedCreditCardID(5)));
+ Suggestion("MasterCard" + kUTF8MidlineEllipsis + "8765", "10/98",
+ kMasterCard, autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we return all credit card suggestions in the case that two cards
@@ -1810,18 +1822,13 @@ TEST_F(AutofillManagerTest, GetCreditCardSuggestions_RepeatedObfuscatedNumber) {
// Test that we sent the right values to the external delegate.
external_delegate_->CheckSuggestions(
- kDefaultPageID, Suggestion("Visa\xC2\xA0\xE2\x8B\xAF"
- "3456",
+ kDefaultPageID, Suggestion("Visa" + kUTF8MidlineEllipsis + "3456",
"04/99", kVisaCard,
autofill_manager_->GetPackedCreditCardID(4)),
- Suggestion("MasterCard\xC2\xA0\xE2\x8B\xAF"
- "8765",
- "10/98", kMasterCard,
- autofill_manager_->GetPackedCreditCardID(5)),
- Suggestion("MasterCard\xC2\xA0\xE2\x8B\xAF"
- "3456",
- "05/99", kMasterCard,
- autofill_manager_->GetPackedCreditCardID(7)));
+ Suggestion("MasterCard" + kUTF8MidlineEllipsis + "8765", "10/98",
+ kMasterCard, autofill_manager_->GetPackedCreditCardID(5)),
+ Suggestion("MasterCard" + kUTF8MidlineEllipsis + "3456", "05/99",
+ kMasterCard, autofill_manager_->GetPackedCreditCardID(7)));
}
// Test that we return profile and credit card suggestions for combined forms.
@@ -1847,14 +1854,11 @@ TEST_F(AutofillManagerTest, GetAddressAndCreditCardSuggestions) {
// Test that we sent the credit card suggestions to the external delegate.
external_delegate_->CheckSuggestions(
- kPageID2, Suggestion("Visa\xC2\xA0\xE2\x8B\xAF"
- "3456",
+ kPageID2, Suggestion("Visa" + kUTF8MidlineEllipsis + "3456",
"04/99", kVisaCard,
autofill_manager_->GetPackedCreditCardID(4)),
- Suggestion("MasterCard\xC2\xA0\xE2\x8B\xAF"
- "8765",
- "10/98", kMasterCard,
- autofill_manager_->GetPackedCreditCardID(5)));
+ Suggestion("MasterCard" + kUTF8MidlineEllipsis + "8765", "10/98",
+ kMasterCard, autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that for non-https forms with both address and credit card fields, we
@@ -3667,17 +3671,38 @@ TEST_F(AutofillManagerTest, FormSubmittedWithDefaultValues) {
}
// Tests that credit card data are saved for forms on https
-TEST_F(AutofillManagerTest, ImportFormDataCreditCardHTTPS) {
+// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
+#if defined(OS_ANDROID)
+#define MAYBE_ImportFormDataCreditCardHTTPS \
+ DISABLED_ImportFormDataCreditCardHTTPS
+#else
+#define MAYBE_ImportFormDataCreditCardHTTPS ImportFormDataCreditCardHTTPS
+#endif
+TEST_F(AutofillManagerTest, MAYBE_ImportFormDataCreditCardHTTPS) {
TestSaveCreditCards(true);
}
// Tests that credit card data are saved for forms on http
-TEST_F(AutofillManagerTest, ImportFormDataCreditCardHTTP) {
+// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
+#if defined(OS_ANDROID)
+#define MAYBE_ImportFormDataCreditCardHTTP DISABLED_ImportFormDataCreditCardHTTP
+#else
+#define MAYBE_ImportFormDataCreditCardHTTP ImportFormDataCreditCardHTTP
+#endif
+TEST_F(AutofillManagerTest, MAYBE_ImportFormDataCreditCardHTTP) {
TestSaveCreditCards(false);
}
// Tests that credit card data are saved when autocomplete=off for CC field.
-TEST_F(AutofillManagerTest, CreditCardSavedWhenAutocompleteOff) {
+// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
+#if defined(OS_ANDROID)
+#define MAYBE_CreditCardSavedWhenAutocompleteOff \
+ DISABLED_CreditCardSavedWhenAutocompleteOff
+#else
+#define MAYBE_CreditCardSavedWhenAutocompleteOff \
+ CreditCardSavedWhenAutocompleteOff
+#endif
+TEST_F(AutofillManagerTest, MAYBE_CreditCardSavedWhenAutocompleteOff) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, false, false);
@@ -4376,8 +4401,7 @@ TEST_F(AutofillManagerTest,
GetAutofillSuggestions(form, number_field);
external_delegate_->CheckSuggestions(
- kDefaultPageID, Suggestion("Visa\xC2\xA0\xE2\x8B\xAF"
- "3456",
+ kDefaultPageID, Suggestion("Visa" + kUTF8MidlineEllipsis + "3456",
"04/99", kVisaCard,
autofill_manager_->GetPackedCreditCardID(4)));
}
@@ -4466,7 +4490,13 @@ TEST_F(AutofillManagerTest, FillInUpdatedExpirationDate) {
"4012888888881881");
}
-TEST_F(AutofillManagerTest, UploadCreditCard) {
+// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
+#if defined(OS_ANDROID)
+#define MAYBE_UploadCreditCard DISABLED_UploadCreditCard
+#else
+#define MAYBE_UploadCreditCard UploadCreditCard
+#endif
+TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard) {
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -4500,7 +4530,13 @@ TEST_F(AutofillManagerTest, UploadCreditCard) {
AutofillMetrics::UPLOAD_OFFERED, 1);
}
-TEST_F(AutofillManagerTest, UploadCreditCard_FeatureNotEnabled) {
+// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
+#if defined(OS_ANDROID)
+#define MAYBE_UploadCreditCard_FeatureNotEnabled DISABLED_UploadCreditCard_FeatureNotEnabled
+#else
+#define MAYBE_UploadCreditCard_FeatureNotEnabled UploadCreditCard_FeatureNotEnabled
+#endif
+TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_FeatureNotEnabled) {
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(false);
@@ -4535,7 +4571,13 @@ TEST_F(AutofillManagerTest, UploadCreditCard_FeatureNotEnabled) {
histogram_tester.ExpectTotalCount("Autofill.CardUploadDecisionExpanded", 0);
}
-TEST_F(AutofillManagerTest, UploadCreditCard_CvcUnavailable) {
+// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
+#if defined(OS_ANDROID)
+#define MAYBE_UploadCreditCard_CvcUnavailable DISABLED_UploadCreditCard_CvcUnavailable
+#else
+#define MAYBE_UploadCreditCard_CvcUnavailable UploadCreditCard_CvcUnavailable
+#endif
+TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_CvcUnavailable) {
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -4571,7 +4613,60 @@ TEST_F(AutofillManagerTest, UploadCreditCard_CvcUnavailable) {
"Autofill.CardUploadDecisionExpanded",
AutofillMetrics::UPLOAD_NOT_OFFERED_NO_CVC, 1);
- rappor::TestRapporService* rappor_service =
+ rappor::TestRapporServiceImpl* rappor_service =
+ autofill_client_.test_rappor_service();
+ EXPECT_EQ(1, rappor_service->GetReportsCount());
+ std::string sample;
+ rappor::RapporType type;
+ EXPECT_TRUE(rappor_service->GetRecordedSampleForMetric(
+ "Autofill.CardUploadNotOfferedNoCvc", &sample, &type));
+ EXPECT_EQ("myform.com", sample);
+ EXPECT_EQ(rappor::ETLD_PLUS_ONE_RAPPOR_TYPE, type);
+}
+
+// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
+#if defined(OS_ANDROID)
+#define MAYBE_UploadCreditCard_CvcInvalidLength DISABLED_UploadCreditCard_CvcInvalidLength
+#else
+#define MAYBE_UploadCreditCard_CvcInvalidLength UploadCreditCard_CvcInvalidLength
+#endif
+TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_CvcInvalidLength) {
+ personal_data_.ClearAutofillProfiles();
+ autofill_manager_->set_credit_card_upload_enabled(true);
+
+ // Create, fill and submit an address form in order to establish a recent
+ // profile which can be selected for the upload request.
+ FormData address_form;
+ test::CreateTestAddressFormData(&address_form);
+ FormsSeen(std::vector<FormData>(1, address_form));
+ ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form);
+ FormSubmitted(address_form);
+
+ // Set up our credit card form data.
+ FormData credit_card_form;
+ CreateTestCreditCardFormData(&credit_card_form, true, false);
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+
+ // Edit the data, and submit.
+ credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
+ credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
+ credit_card_form.fields[2].value = ASCIIToUTF16("11");
+ credit_card_form.fields[3].value = ASCIIToUTF16("2017");
+ credit_card_form.fields[4].value = ASCIIToUTF16("1234");
+
+ base::HistogramTester histogram_tester;
+
+ // Neither a local save nor an upload should happen in this case.
+ EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
+ FormSubmitted(credit_card_form);
+ EXPECT_FALSE(autofill_manager_->credit_card_was_uploaded());
+
+ // Verify that the correct histogram entry (and only that) was logged.
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.CardUploadDecisionExpanded",
+ AutofillMetrics::UPLOAD_NOT_OFFERED_NO_CVC, 1);
+
+ rappor::TestRapporServiceImpl* rappor_service =
autofill_client_.test_rappor_service();
EXPECT_EQ(1, rappor_service->GetReportsCount());
std::string sample;
@@ -4582,7 +4677,13 @@ TEST_F(AutofillManagerTest, UploadCreditCard_CvcUnavailable) {
EXPECT_EQ(rappor::ETLD_PLUS_ONE_RAPPOR_TYPE, type);
}
-TEST_F(AutofillManagerTest, UploadCreditCard_MultipleCvcFields) {
+// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
+#if defined(OS_ANDROID)
+#define MAYBE_UploadCreditCard_MultipleCvcFields DISABLED_UploadCreditCard_MultipleCvcFields
+#else
+#define MAYBE_UploadCreditCard_MultipleCvcFields UploadCreditCard_MultipleCvcFields
+#endif
+TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_MultipleCvcFields) {
autofill_manager_->set_credit_card_upload_enabled(true);
// Remove the profiles that were created in the TestPersonalDataManager
@@ -4641,7 +4742,13 @@ TEST_F(AutofillManagerTest, UploadCreditCard_MultipleCvcFields) {
AutofillMetrics::UPLOAD_OFFERED, 1);
}
-TEST_F(AutofillManagerTest, UploadCreditCard_NoProfileAvailable) {
+// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
+#if defined(OS_ANDROID)
+#define MAYBE_UploadCreditCard_NoProfileAvailable DISABLED_UploadCreditCard_NoProfileAvailable
+#else
+#define MAYBE_UploadCreditCard_NoProfileAvailable UploadCreditCard_NoProfileAvailable
+#endif
+TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NoProfileAvailable) {
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -4671,7 +4778,7 @@ TEST_F(AutofillManagerTest, UploadCreditCard_NoProfileAvailable) {
"Autofill.CardUploadDecisionExpanded",
AutofillMetrics::UPLOAD_NOT_OFFERED_NO_ADDRESS, 1);
- rappor::TestRapporService* rappor_service =
+ rappor::TestRapporServiceImpl* rappor_service =
autofill_client_.test_rappor_service();
EXPECT_EQ(1, rappor_service->GetReportsCount());
std::string sample;
@@ -4682,7 +4789,13 @@ TEST_F(AutofillManagerTest, UploadCreditCard_NoProfileAvailable) {
EXPECT_EQ(rappor::ETLD_PLUS_ONE_RAPPOR_TYPE, type);
}
-TEST_F(AutofillManagerTest, UploadCreditCard_NoNameAvailable) {
+// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
+#if defined(OS_ANDROID)
+#define MAYBE_UploadCreditCard_NoNameAvailable DISABLED_UploadCreditCard_NoNameAvailable
+#else
+#define MAYBE_UploadCreditCard_NoNameAvailable UploadCreditCard_NoNameAvailable
+#endif
+TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NoNameAvailable) {
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -4718,7 +4831,7 @@ TEST_F(AutofillManagerTest, UploadCreditCard_NoNameAvailable) {
"Autofill.CardUploadDecisionExpanded",
AutofillMetrics::UPLOAD_NOT_OFFERED_NO_NAME, 1);
- rappor::TestRapporService* rappor_service =
+ rappor::TestRapporServiceImpl* rappor_service =
autofill_client_.test_rappor_service();
EXPECT_EQ(1, rappor_service->GetReportsCount());
std::string sample;
@@ -4729,7 +4842,13 @@ TEST_F(AutofillManagerTest, UploadCreditCard_NoNameAvailable) {
EXPECT_EQ(rappor::ETLD_PLUS_ONE_RAPPOR_TYPE, type);
}
-TEST_F(AutofillManagerTest, UploadCreditCard_ZipCodesConflict) {
+// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
+#if defined(OS_ANDROID)
+#define MAYBE_UploadCreditCard_ZipCodesConflict DISABLED_UploadCreditCard_ZipCodesConflict
+#else
+#define MAYBE_UploadCreditCard_ZipCodesConflict UploadCreditCard_ZipCodesConflict
+#endif
+TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_ZipCodesConflict) {
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -4774,7 +4893,13 @@ TEST_F(AutofillManagerTest, UploadCreditCard_ZipCodesConflict) {
AutofillMetrics::UPLOAD_NOT_OFFERED_CONFLICTING_ZIPS, 1);
}
-TEST_F(AutofillManagerTest, UploadCreditCard_ZipCodesHavePrefixMatch) {
+// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
+#if defined(OS_ANDROID)
+#define MAYBE_UploadCreditCard_ZipCodesHavePrefixMatch DISABLED_UploadCreditCard_ZipCodesHavePrefixMatch
+#else
+#define MAYBE_UploadCreditCard_ZipCodesHavePrefixMatch UploadCreditCard_ZipCodesHavePrefixMatch
+#endif
+TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_ZipCodesHavePrefixMatch) {
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -4819,7 +4944,13 @@ TEST_F(AutofillManagerTest, UploadCreditCard_ZipCodesHavePrefixMatch) {
AutofillMetrics::UPLOAD_OFFERED, 1);
}
-TEST_F(AutofillManagerTest, UploadCreditCard_NoZipCodeAvailable) {
+// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
+#if defined(OS_ANDROID)
+#define MAYBE_UploadCreditCard_NoZipCodeAvailable DISABLED_UploadCreditCard_NoZipCodeAvailable
+#else
+#define MAYBE_UploadCreditCard_NoZipCodeAvailable UploadCreditCard_NoZipCodeAvailable
+#endif
+TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NoZipCodeAvailable) {
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -4863,7 +4994,13 @@ TEST_F(AutofillManagerTest, UploadCreditCard_NoZipCodeAvailable) {
AutofillMetrics::UPLOAD_NOT_OFFERED_NO_ZIP_CODE, 1);
}
-TEST_F(AutofillManagerTest, UploadCreditCard_NamesMatchLoosely) {
+// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
+#if defined(OS_ANDROID)
+#define MAYBE_UploadCreditCard_NamesMatchLoosely DISABLED_UploadCreditCard_NamesMatchLoosely
+#else
+#define MAYBE_UploadCreditCard_NamesMatchLoosely UploadCreditCard_NamesMatchLoosely
+#endif
+TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NamesMatchLoosely) {
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -4911,7 +5048,13 @@ TEST_F(AutofillManagerTest, UploadCreditCard_NamesMatchLoosely) {
AutofillMetrics::UPLOAD_OFFERED, 1);
}
-TEST_F(AutofillManagerTest, UploadCreditCard_NamesHaveToMatch) {
+// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
+#if defined(OS_ANDROID)
+#define MAYBE_UploadCreditCard_NamesHaveToMatch DISABLED_UploadCreditCard_NamesHaveToMatch
+#else
+#define MAYBE_UploadCreditCard_NamesHaveToMatch UploadCreditCard_NamesHaveToMatch
+#endif
+TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NamesHaveToMatch) {
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -4955,7 +5098,7 @@ TEST_F(AutofillManagerTest, UploadCreditCard_NamesHaveToMatch) {
"Autofill.CardUploadDecisionExpanded",
AutofillMetrics::UPLOAD_NOT_OFFERED_CONFLICTING_NAMES, 1);
- rappor::TestRapporService* rappor_service =
+ rappor::TestRapporServiceImpl* rappor_service =
autofill_client_.test_rappor_service();
EXPECT_EQ(1, rappor_service->GetReportsCount());
std::string sample;
@@ -4966,7 +5109,13 @@ TEST_F(AutofillManagerTest, UploadCreditCard_NamesHaveToMatch) {
EXPECT_EQ(rappor::ETLD_PLUS_ONE_RAPPOR_TYPE, type);
}
-TEST_F(AutofillManagerTest, UploadCreditCard_UploadDetailsFails) {
+// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
+#if defined(OS_ANDROID)
+#define MAYBE_UploadCreditCard_UploadDetailsFails DISABLED_UploadCreditCard_UploadDetailsFails
+#else
+#define MAYBE_UploadCreditCard_UploadDetailsFails UploadCreditCard_UploadDetailsFails
+#endif
+TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_UploadDetailsFails) {
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -5089,11 +5238,10 @@ TEST_F(AutofillManagerTest, DisplayCreditCardSuggestionsWithMatchingTokens) {
GetAutofillSuggestions(form, field);
#if defined(OS_ANDROID)
- static const char* kVisaSuggestion =
- "Visa\xC2\xA0\xE2\x8B\xAF"
- "3456";
+ static const std::string kVisaSuggestion =
+ "Visa" + kUTF8MidlineEllipsis + "3456";
#else
- static const char* kVisaSuggestion = "*3456";
+ static const std::string kVisaSuggestion = "*3456";
#endif
external_delegate_->CheckSuggestions(
diff --git a/chromium/components/autofill/core/browser/autofill_merge_unittest.cc b/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
index f38ffaf95f2..a4aceaab132 100644
--- a/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
@@ -8,7 +8,6 @@
#include <memory>
#include <vector>
-#include "base/feature_list.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/macros.h"
@@ -17,7 +16,6 @@
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_feature_list.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/autofill_type.h"
@@ -186,7 +184,6 @@ class AutofillMergeTest : public DataDrivenTest,
PersonalDataManagerMock personal_data_;
private:
- base::test::ScopedFeatureList scoped_feature_list_;
std::map<std::string, ServerFieldType> string_to_field_type_map_;
DISALLOW_COPY_AND_ASSIGN(AutofillMergeTest);
@@ -205,7 +202,6 @@ AutofillMergeTest::~AutofillMergeTest() {
void AutofillMergeTest::SetUp() {
test::DisableSystemServices(nullptr);
- scoped_feature_list_.InitAndEnableFeature(kAutofillProfileCleanup);
}
void AutofillMergeTest::TearDown() {
diff --git a/chromium/components/autofill/core/browser/autofill_metrics.cc b/chromium/components/autofill/core/browser/autofill_metrics.cc
index e655f7fe66f..66a7bfcc967 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics.cc
+++ b/chromium/components/autofill/core/browser/autofill_metrics.cc
@@ -675,10 +675,17 @@ void AutofillMetrics::LogIsQueriedCreditCardFormSecure(bool is_secure) {
UMA_HISTOGRAM_BOOLEAN("Autofill.QueriedCreditCardFormIsSecure", is_secure);
}
+// static
+void AutofillMetrics::LogShowedHttpNotSecureExplanation() {
+ base::RecordAction(
+ base::UserMetricsAction("Autofill_ShowedHttpNotSecureExplanation"));
+}
+
AutofillMetrics::FormEventLogger::FormEventLogger(bool is_for_credit_card)
: is_for_credit_card_(is_for_credit_card),
is_server_data_available_(false),
is_local_data_available_(false),
+ is_context_secure_(false),
has_logged_interacted_(false),
has_logged_suggestions_shown_(false),
has_logged_masked_server_card_suggestion_selected_(false),
@@ -686,8 +693,7 @@ AutofillMetrics::FormEventLogger::FormEventLogger(bool is_for_credit_card)
has_logged_will_submit_(false),
has_logged_submitted_(false),
logged_suggestion_filled_was_server_data_(false),
- logged_suggestion_filled_was_masked_server_card_(false) {
-}
+ logged_suggestion_filled_was_masked_server_card_(false) {}
void AutofillMetrics::FormEventLogger::OnDidInteractWithAutofillableForm() {
if (!has_logged_interacted_) {
@@ -814,6 +820,10 @@ void AutofillMetrics::FormEventLogger::OnWillSubmitForm() {
Log(AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE);
}
+ if (has_logged_suggestions_shown_) {
+ Log(AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE);
+ }
+
base::RecordAction(base::UserMetricsAction("Autofill_OnWillSubmitForm"));
}
@@ -837,6 +847,10 @@ void AutofillMetrics::FormEventLogger::OnFormSubmitted() {
} else {
Log(AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE);
}
+
+ if (has_logged_suggestions_shown_) {
+ Log(AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE);
+ }
}
void AutofillMetrics::FormEventLogger::Log(FormEvent event) const {
@@ -848,6 +862,14 @@ void AutofillMetrics::FormEventLogger::Log(FormEvent event) const {
name += "Address";
LogUMAHistogramEnumeration(name, event, NUM_FORM_EVENTS);
+ // Log again in a different histogram for credit card forms on nonsecure
+ // pages, so that form interactions on nonsecure pages can be analyzed on
+ // their own.
+ if (is_for_credit_card_ && !is_context_secure_) {
+ LogUMAHistogramEnumeration(name + ".OnNonsecurePage", event,
+ NUM_FORM_EVENTS);
+ }
+
// Logging again in a different histogram for segmentation purposes.
// TODO(waltercacau): Re-evaluate if we still need such fine grained
// segmentation. http://crbug.com/454018
diff --git a/chromium/components/autofill/core/browser/autofill_metrics.h b/chromium/components/autofill/core/browser/autofill_metrics.h
index b8e569baf69..6fe8a34ebc3 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics.h
+++ b/chromium/components/autofill/core/browser/autofill_metrics.h
@@ -383,6 +383,13 @@ class AutofillMetrics {
FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE,
FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE,
FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
+ // A dropdown with suggestions was shown and a form was submitted after
+ // that.
+ FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE,
+ // A dropdown with suggestions was shown and a form is about to be
+ // submitted. If the submission is not interrupted by JavaScript, the "form
+ // submitted" event above will also be logged.
+ FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE,
NUM_FORM_EVENTS,
};
@@ -656,6 +663,10 @@ class AutofillMetrics {
// context.
static void LogIsQueriedCreditCardFormSecure(bool is_secure);
+ // This should be called when the user selects the Form-Not-Secure warning
+ // suggestion to show an explanation of the warning.
+ static void LogShowedHttpNotSecureExplanation();
+
// Utility to autofill form events in the relevant histograms depending on
// the presence of server and/or local data.
class FormEventLogger {
@@ -670,6 +681,10 @@ class AutofillMetrics {
is_local_data_available_ = is_local_data_available;
}
+ inline void set_is_context_secure(bool is_context_secure) {
+ is_context_secure_ = is_context_secure;
+ }
+
void OnDidInteractWithAutofillableForm();
void OnDidPollSuggestions(const FormFieldData& field);
@@ -694,6 +709,7 @@ class AutofillMetrics {
bool is_for_credit_card_;
bool is_server_data_available_;
bool is_local_data_available_;
+ bool is_context_secure_;
bool has_logged_interacted_;
bool has_logged_suggestions_shown_;
bool has_logged_masked_server_card_suggestion_selected_;
diff --git a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
index 681b131a408..f9799f5e8af 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -22,6 +22,7 @@
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/payments/payments_client.h"
#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/popup_item_ids.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
@@ -42,7 +43,7 @@
using base::ASCIIToUTF16;
using base::Bucket;
using base::TimeTicks;
-using rappor::TestRapporService;
+using rappor::TestRapporServiceImpl;
using ::testing::ElementsAre;
namespace autofill {
@@ -1885,6 +1886,7 @@ TEST_F(AutofillMetricsTest, QueriedCreditCardFormIsSecure) {
form.name = ASCIIToUTF16("TestForm");
form.origin = GURL("http://example.com/form.html");
form.action = GURL("http://example.com/submit.html");
+ autofill_client_.set_form_origin(form.origin);
FormFieldData field;
std::vector<ServerFieldType> field_types;
@@ -1918,6 +1920,7 @@ TEST_F(AutofillMetricsTest, QueriedCreditCardFormIsSecure) {
autofill_manager_->Reset();
form.origin = GURL("https://example.com/form.html");
form.action = GURL("https://example.com/submit.html");
+ autofill_client_.set_form_origin(form.origin);
autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulate an Autofill query on a credit card field (HTTPS form).
@@ -2413,6 +2416,24 @@ TEST_F(AutofillMetricsTest, CreditCardSubmittedFormEvents) {
autofill_manager_->AddSeenForm(form, field_types, field_types);
{
+ // Simulating submission with suggestion shown.
+ base::HistogramTester histogram_tester;
+ autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
+ autofill_manager_->SubmitForm(form, TimeTicks::Now());
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1);
+ }
+
+ // Reset the autofill manager state.
+ autofill_manager_->Reset();
+ autofill_manager_->AddSeenForm(form, field_types, field_types);
+
+ {
// Simulating submission with filled local data.
base::HistogramTester histogram_tester;
autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
@@ -2496,6 +2517,9 @@ TEST_F(AutofillMetricsTest, CreditCardSubmittedFormEvents) {
AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
@@ -2510,6 +2534,9 @@ TEST_F(AutofillMetricsTest, CreditCardSubmittedFormEvents) {
AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
@@ -2526,27 +2553,45 @@ TEST_F(AutofillMetricsTest, CreditCardSubmittedFormEvents) {
autofill_manager_->AddSeenForm(form, field_types, field_types);
{
- // Simulating submission without previous interaction.
+ // Simulating submission with suggestion shown but without previous
+ // interaction.
base::HistogramTester histogram_tester;
+ autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
autofill_manager_->SubmitForm(form, TimeTicks::Now());
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+ AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+ AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0);
+ AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
+ AutofillMetrics::
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
+ 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
+ 0);
}
}
@@ -2600,6 +2645,24 @@ TEST_F(AutofillMetricsTest, CreditCardWillSubmitFormEvents) {
autofill_manager_->AddSeenForm(form, field_types, field_types);
{
+ // Simulating submission with suggestion shown.
+ base::HistogramTester histogram_tester;
+ autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
+ autofill_manager_->WillSubmitForm(form, TimeTicks::Now());
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
+ }
+
+ // Reset the autofill manager state.
+ autofill_manager_->Reset();
+ autofill_manager_->AddSeenForm(form, field_types, field_types);
+
+ {
// Simulating submission with filled local data.
base::HistogramTester histogram_tester;
autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
@@ -2683,6 +2746,9 @@ TEST_F(AutofillMetricsTest, CreditCardWillSubmitFormEvents) {
AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
@@ -2697,6 +2763,9 @@ TEST_F(AutofillMetricsTest, CreditCardWillSubmitFormEvents) {
AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
@@ -2713,27 +2782,45 @@ TEST_F(AutofillMetricsTest, CreditCardWillSubmitFormEvents) {
autofill_manager_->AddSeenForm(form, field_types, field_types);
{
- // Simulating submission without previous interaction.
+ // Simulating submission with suggestion shown but without previous
+ // interaction.
base::HistogramTester histogram_tester;
+ autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
autofill_manager_->WillSubmitForm(form, TimeTicks::Now());
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+ AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+ AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0);
+ AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
+ AutofillMetrics::
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
+ 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
- AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
+ 0);
}
}
@@ -2991,6 +3078,24 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
autofill_manager_->AddSeenForm(form, field_types, field_types);
{
+ // Simulating submission with suggestion shown.
+ base::HistogramTester histogram_tester;
+ autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
+ autofill_manager_->SubmitForm(form, TimeTicks::Now());
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1);
+ }
+
+ // Reset the autofill manager state.
+ autofill_manager_->Reset();
+ autofill_manager_->AddSeenForm(form, field_types, field_types);
+
+ {
// Simulating submission with filled local data.
base::HistogramTester histogram_tester;
autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
@@ -3043,6 +3148,9 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
@@ -3052,6 +3160,9 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
@@ -3063,11 +3174,16 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
autofill_manager_->AddSeenForm(form, field_types, field_types);
{
- // Simulating submission without previous interaction.
+ // Simulating submission with suggestion show but without previous
+ // interaction.
base::HistogramTester histogram_tester;
+ autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
autofill_manager_->SubmitForm(form, TimeTicks::Now());
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
@@ -3077,6 +3193,14 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
+ AutofillMetrics::
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
+ 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
@@ -3084,6 +3208,11 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
+ AutofillMetrics::
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
+ 0);
}
}
@@ -3135,6 +3264,24 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
autofill_manager_->AddSeenForm(form, field_types, field_types);
{
+ // Simulating submission with suggestion shown.
+ base::HistogramTester histogram_tester;
+ autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
+ autofill_manager_->WillSubmitForm(form, TimeTicks::Now());
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
+ }
+
+ // Reset the autofill manager state.
+ autofill_manager_->Reset();
+ autofill_manager_->AddSeenForm(form, field_types, field_types);
+
+ {
// Simulating submission with filled local data.
base::HistogramTester histogram_tester;
autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
@@ -3184,9 +3331,26 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
autofill_manager_->WillSubmitForm(form, TimeTicks::Now());
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
+ AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
+ AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
+ AutofillMetrics::
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
+ 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
@@ -3194,6 +3358,11 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
+ AutofillMetrics::
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
+ 0);
}
// Reset the autofill manager state.
@@ -3201,11 +3370,16 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
autofill_manager_->AddSeenForm(form, field_types, field_types);
{
- // Simulating submission without previous interaction.
+ // Simulating submission with suggestion shown but without previous
+ // interaction.
base::HistogramTester histogram_tester;
+ autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
autofill_manager_->WillSubmitForm(form, TimeTicks::Now());
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
@@ -3215,6 +3389,14 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
+ AutofillMetrics::
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
+ 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
@@ -3222,6 +3404,11 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
+ AutofillMetrics::
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
+ 0);
}
}
@@ -4035,7 +4222,7 @@ class AutofillMetricsParseQueryResponseTest : public testing::Test {
}
protected:
- TestRapporService rappor_service_;
+ TestRapporServiceImpl rappor_service_;
std::vector<std::unique_ptr<FormStructure>> owned_forms_;
std::vector<FormStructure*> forms_;
};
@@ -4139,4 +4326,125 @@ TEST_F(AutofillMetricsParseQueryResponseTest, PartialNoServerData) {
EXPECT_EQ(0, rappor_service_.GetReportsCount());
}
+// Test that the Form-Not-Secure warning user action is recorded.
+TEST_F(AutofillMetricsTest, ShowHttpNotSecureExplanationUserAction) {
+ base::UserActionTester user_action_tester;
+ external_delegate_->DidAcceptSuggestion(
+ ASCIIToUTF16("Test"), POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE, 0);
+ EXPECT_EQ(1, user_action_tester.GetActionCount(
+ "Autofill_ShowedHttpNotSecureExplanation"));
+}
+
+// Tests that credit card form submissions are logged specially when the form is
+// on a non-secure page.
+TEST_F(AutofillMetricsTest, NonsecureCreditCardForm) {
+ personal_data_->RecreateCreditCards(
+ true /* include_local_credit_card */,
+ false /* include_masked_server_credit_card */,
+ false /* include_full_server_credit_card */);
+
+ // Set up our form data.
+ FormData form;
+ form.name = ASCIIToUTF16("TestForm");
+ form.origin = GURL("http://example.com/form.html");
+ form.action = GURL("http://example.com/submit.html");
+ autofill_client_.set_form_origin(form.origin);
+
+ FormFieldData field;
+ std::vector<ServerFieldType> field_types;
+ test::CreateTestFormField("Name on card", "cc-name", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_NAME_FULL);
+ test::CreateTestFormField("Credit card", "card", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_NUMBER);
+ test::CreateTestFormField("Month", "card_month", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_EXP_MONTH);
+
+ // Simulate having seen this form on page load.
+ // |form_structure| will be owned by |autofill_manager_|.
+ autofill_manager_->AddSeenForm(form, field_types, field_types);
+
+ // Simulate an Autofill query on a credit card field.
+ {
+ base::UserActionTester user_action_tester;
+ autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
+ EXPECT_EQ(1, user_action_tester.GetActionCount(
+ "Autofill_PolledCreditCardSuggestions"));
+ }
+
+ // Simulate submitting the credit card form.
+ {
+ base::HistogramTester histograms;
+ autofill_manager_->SubmitForm(form, TimeTicks::Now());
+ histograms.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard.OnNonsecurePage",
+ AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1);
+ histograms.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1);
+ histograms.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard.WithOnlyLocalData",
+ AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1);
+ }
+}
+
+// Tests that credit card form submissions are *not* logged specially when the
+// form is *not* on a non-secure page.
+TEST_F(AutofillMetricsTest,
+ NonsecureCreditCardFormMetricsNotRecordedOnSecurePage) {
+ personal_data_->RecreateCreditCards(
+ true /* include_local_credit_card */,
+ false /* include_masked_server_credit_card */,
+ false /* include_full_server_credit_card */);
+
+ // Set up our form data.
+ FormData form;
+ form.name = ASCIIToUTF16("TestForm");
+ form.origin = GURL("https://example.com/form.html");
+ form.action = GURL("http://example.com/submit.html");
+
+ FormFieldData field;
+ std::vector<ServerFieldType> field_types;
+ test::CreateTestFormField("Name on card", "cc-name", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_NAME_FULL);
+ test::CreateTestFormField("Credit card", "card", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_NUMBER);
+ test::CreateTestFormField("Month", "card_month", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_EXP_MONTH);
+
+ // Simulate having seen this form on page load.
+ // |form_structure| will be owned by |autofill_manager_|.
+ autofill_manager_->AddSeenForm(form, field_types, field_types);
+
+ // Simulate an Autofill query on a credit card field.
+ {
+ base::UserActionTester user_action_tester;
+ autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
+ EXPECT_EQ(1, user_action_tester.GetActionCount(
+ "Autofill_PolledCreditCardSuggestions"));
+ }
+
+ // Simulate submitting the credit card form.
+ {
+ base::HistogramTester histograms;
+ autofill_manager_->SubmitForm(form, TimeTicks::Now());
+ histograms.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
+ histograms.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1);
+ // Check that the nonsecure histogram was not recorded. ExpectBucketCount()
+ // can't be used here because it expects the histogram to exist.
+ EXPECT_EQ(
+ 0, histograms.GetTotalCountsForPrefix("Autofill.FormEvents.CreditCard")
+ ["Autofill.FormEvents.CreditCard.OnNonsecurePage"]);
+ }
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_popup_delegate.h b/chromium/components/autofill/core/browser/autofill_popup_delegate.h
index 99a66758a30..5a864242755 100644
--- a/chromium/components/autofill/core/browser/autofill_popup_delegate.h
+++ b/chromium/components/autofill/core/browser/autofill_popup_delegate.h
@@ -43,6 +43,9 @@ class AutofillPopupDelegate {
// Informs the delegate that the Autofill previewed form should be cleared.
virtual void ClearPreviewedForm() = 0;
+
+ // Returns true if popup is for credit card.
+ virtual bool IsCreditCardPopup() = 0;
};
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_profile.cc b/chromium/components/autofill/core/browser/autofill_profile.cc
index 469111e4ce6..9630d5b188b 100644
--- a/chromium/components/autofill/core/browser/autofill_profile.cc
+++ b/chromium/components/autofill/core/browser/autofill_profile.cc
@@ -195,22 +195,23 @@ AutofillProfile::AutofillProfile(const std::string& guid,
const std::string& origin)
: AutofillDataModel(guid, origin),
record_type_(LOCAL_PROFILE),
- phone_number_(this) {
-}
+ phone_number_(this),
+ has_converted_(false) {}
AutofillProfile::AutofillProfile(RecordType type, const std::string& server_id)
: AutofillDataModel(base::GenerateGUID(), std::string()),
record_type_(type),
phone_number_(this),
- server_id_(server_id) {
+ server_id_(server_id),
+ has_converted_(false) {
DCHECK(type == SERVER_PROFILE);
}
AutofillProfile::AutofillProfile()
: AutofillDataModel(base::GenerateGUID(), std::string()),
record_type_(LOCAL_PROFILE),
- phone_number_(this) {
-}
+ phone_number_(this),
+ has_converted_(false) {}
AutofillProfile::AutofillProfile(const AutofillProfile& profile)
: AutofillDataModel(std::string(), std::string()), phone_number_(this) {
@@ -243,6 +244,7 @@ AutofillProfile& AutofillProfile::operator=(const AutofillProfile& profile) {
set_language_code(profile.language_code());
server_id_ = profile.server_id();
+ has_converted_ = profile.has_converted();
return *this;
}
diff --git a/chromium/components/autofill/core/browser/autofill_profile.h b/chromium/components/autofill/core/browser/autofill_profile.h
index 00be04e8592..ae7b521385d 100644
--- a/chromium/components/autofill/core/browser/autofill_profile.h
+++ b/chromium/components/autofill/core/browser/autofill_profile.h
@@ -178,6 +178,10 @@ class AutofillProfile : public AutofillDataModel {
// use.
void RecordAndLogUse();
+ // Valid only when type() == SERVER_PROFILE.
+ bool has_converted() const { return has_converted_; }
+ void set_has_converted(bool has_converted) { has_converted_ = has_converted; }
+
private:
typedef std::vector<const FormGroup*> FormGroupList;
@@ -221,6 +225,10 @@ class AutofillProfile : public AutofillDataModel {
// ID used for identifying this profile. Only set for SERVER_PROFILEs. This is
// a hash of the contents.
std::string server_id_;
+
+ // Only useful for SERVER_PROFILEs. Whether this server profile has been
+ // converted to a local profile.
+ bool has_converted_;
};
// So we can compare AutofillProfiles with EXPECT_EQ().
diff --git a/chromium/components/autofill/core/browser/autofill_profile_comparator.cc b/chromium/components/autofill/core/browser/autofill_profile_comparator.cc
index edfe2450d67..c3e8709549b 100644
--- a/chromium/components/autofill/core/browser/autofill_profile_comparator.cc
+++ b/chromium/components/autofill/core/browser/autofill_profile_comparator.cc
@@ -316,7 +316,7 @@ bool AutofillProfileComparator::MergeCompanyNames(
switch (result) {
case DIFFERENT_TOKENS:
default:
- NOTREACHED();
+ NOTREACHED() << "Unexpected mismatch: '" << c1 << "' vs '" << c2 << "'";
return false;
case S1_CONTAINS_S2:
best = &c1;
@@ -501,13 +501,72 @@ bool AutofillProfileComparator::MergeAddresses(const AutofillProfile& p1,
break;
case DIFFERENT_TOKENS:
default:
- // The addresses aren't mergeable and we shouldn't be doing any of
+ // The cities aren't mergeable and we shouldn't be doing any of
+ // this.
+ NOTREACHED() << "Unexpected mismatch: '" << city1 << "' vs '" << city2
+ << "'";
+ return false;
+ }
+ }
+
+ // One of the dependend localities is empty or one of the localities has a
+ // subset of tokens from the other. Pick the locality name with more tokens;
+ // this is usually the most explicit one.
+ const AutofillType kDependentLocality(ADDRESS_HOME_DEPENDENT_LOCALITY);
+ const base::string16& locality1 = p1.GetInfo(kDependentLocality, app_locale_);
+ const base::string16& locality2 = p2.GetInfo(kDependentLocality, app_locale_);
+ if (locality1.empty()) {
+ address->SetInfo(kDependentLocality, locality2, app_locale_);
+ } else if (locality2.empty()) {
+ address->SetInfo(kDependentLocality, locality1, app_locale_);
+ } else {
+ // Prefer the one with more tokens, making sure to apply address
+ // normalization and rewriting before doing the comparison.
+ CompareTokensResult result =
+ CompareTokens(rewriter.Rewrite(NormalizeForComparison(locality1)),
+ rewriter.Rewrite(NormalizeForComparison(locality2)));
+ switch (result) {
+ case SAME_TOKENS:
+ // They have the same set of unique tokens. Let's pick the more recently
+ // used one.
+ address->SetInfo(
+ kDependentLocality,
+ (p2.use_date() > p1.use_date() ? locality2 : locality1),
+ app_locale_);
+ break;
+ case S1_CONTAINS_S2:
+ // locality1 has more unique tokens than locality2.
+ address->SetInfo(kDependentLocality, locality1, app_locale_);
+ break;
+ case S2_CONTAINS_S1:
+ // locality2 has more unique tokens than locality1.
+ address->SetInfo(kDependentLocality, locality2, app_locale_);
+ break;
+ case DIFFERENT_TOKENS:
+ default:
+ // The localities aren't mergeable and we shouldn't be doing any of
// this.
- NOTREACHED();
+ NOTREACHED() << "Unexpected mismatch: '" << locality1 << "' vs '"
+ << locality2 << "'";
return false;
}
}
+ // One of the sorting codes is empty, they are the same, or one is a substring
+ // of the other. We prefer the most recently used sorting code.
+ const AutofillType kSortingCode(ADDRESS_HOME_SORTING_CODE);
+ const base::string16& sorting1 = p1.GetInfo(kSortingCode, app_locale_);
+ const base::string16& sorting2 = p2.GetInfo(kSortingCode, app_locale_);
+ if (sorting1.empty()) {
+ address->SetInfo(kSortingCode, sorting2, app_locale_);
+ } else if (sorting2.empty()) {
+ address->SetInfo(kSortingCode, sorting1, app_locale_);
+ } else {
+ address->SetInfo(kSortingCode,
+ (p2.use_date() > p1.use_date() ? sorting2 : sorting1),
+ app_locale_);
+ }
+
// One of the addresses is empty or one of the addresses has a subset of
// tokens from the other. Prefer the more verbosely expressed one.
const AutofillType kStreetAddress(ADDRESS_HOME_STREET_ADDRESS);
@@ -554,7 +613,8 @@ bool AutofillProfileComparator::MergeAddresses(const AutofillProfile& p1,
default:
// The addresses aren't mergeable and we shouldn't be doing any of
// this.
- NOTREACHED();
+ NOTREACHED() << "Unexpected mismatch: '" << address1 << "' vs '"
+ << address2 << "'";
return false;
}
}
@@ -771,17 +831,17 @@ bool AutofillProfileComparator::HaveMergeablePhoneNumbers(
// Parse and compare the phone numbers.
PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance();
switch (phone_util->IsNumberMatchWithTwoStrings(phone_1, phone_2)) {
- case PhoneNumberUtil::INVALID_NUMBER:
- case PhoneNumberUtil::NO_MATCH:
- return false;
case PhoneNumberUtil::SHORT_NSN_MATCH:
case PhoneNumberUtil::NSN_MATCH:
case PhoneNumberUtil::EXACT_MATCH:
return true;
+ case PhoneNumberUtil::INVALID_NUMBER:
+ case PhoneNumberUtil::NO_MATCH:
+ return false;
+ default:
+ NOTREACHED();
+ return false;
}
-
- NOTREACHED();
- return false;
}
bool AutofillProfileComparator::HaveMergeableAddresses(
@@ -797,10 +857,6 @@ bool AutofillProfileComparator::HaveMergeableAddresses(
return false;
}
- // TODO(rogerm): Lookup the normalization rules for the (common) country of
- // the address. The rules should be applied post NormalizeForComparison to
- // the state, city, and address bag of words comparisons.
-
// Zip
// ----
// If the addresses are definitely not in the same zip/area code then we're
@@ -816,6 +872,8 @@ bool AutofillProfileComparator::HaveMergeableAddresses(
return false;
}
+ // Use the token rewrite rules for the (common) country of the address to
+ // transform equivalent substrings to a representative token for comparison.
AddressRewriter rewriter =
AddressRewriter::ForCountryCode(country1.empty() ? country2 : country1);
@@ -845,14 +903,44 @@ bool AutofillProfileComparator::HaveMergeableAddresses(
// TODO(rogerm): If the match is between non-empty zip codes then we can infer
// that the two city strings are intended to have the same meaning. This
// handles the cases where we have a city vs one of its suburbs.
- const base::string16& city1 = rewriter.Rewrite(NormalizeForComparison(
- p1.GetInfo(AutofillType(ADDRESS_HOME_CITY), app_locale_)));
- const base::string16& city2 = rewriter.Rewrite(NormalizeForComparison(
- p2.GetInfo(AutofillType(ADDRESS_HOME_CITY), app_locale_)));
+ const AutofillType kCity(ADDRESS_HOME_CITY);
+ const base::string16& city1 =
+ rewriter.Rewrite(NormalizeForComparison(p1.GetInfo(kCity, app_locale_)));
+ const base::string16& city2 =
+ rewriter.Rewrite(NormalizeForComparison(p2.GetInfo(kCity, app_locale_)));
if (CompareTokens(city1, city2) == DIFFERENT_TOKENS) {
return false;
}
+ // Dependent Locality
+ // -------------------
+ // Heuristic: Dependent Localities are mergeable if one is a (possibly empty)
+ // bag of words subset of the other.
+ const AutofillType kDependentLocality(ADDRESS_HOME_DEPENDENT_LOCALITY);
+ const base::string16& locality1 = rewriter.Rewrite(
+ NormalizeForComparison(p1.GetInfo(kDependentLocality, app_locale_)));
+ const base::string16& locality2 = rewriter.Rewrite(
+ NormalizeForComparison(p2.GetInfo(kDependentLocality, app_locale_)));
+ if (CompareTokens(locality1, locality2) == DIFFERENT_TOKENS) {
+ return false;
+ }
+
+ // Sorting Code
+ // -------------
+ // Heuristic: Sorting codes are mergeable if one is empty or one is a
+ // substring of the other, post normalization and whitespace removed. This
+ // is similar to postal/zip codes.
+ const AutofillType kSortingCode(ADDRESS_HOME_SORTING_CODE);
+ const base::string16& sorting1 = NormalizeForComparison(
+ p1.GetInfo(kSortingCode, app_locale_), DISCARD_WHITESPACE);
+ const base::string16& sorting2 = NormalizeForComparison(
+ p2.GetInfo(kSortingCode, app_locale_), DISCARD_WHITESPACE);
+ if (!sorting1.empty() && !sorting2.empty() &&
+ sorting1.find(sorting2) == base::string16::npos &&
+ sorting2.find(sorting1) == base::string16::npos) {
+ return false;
+ }
+
// Address
// --------
// Heuristic: Street addresses are mergeable if one is a (possibly empty) bag
diff --git a/chromium/components/autofill/core/browser/autofill_profile_comparator_unittest.cc b/chromium/components/autofill/core/browser/autofill_profile_comparator_unittest.cc
index bcd0274eb66..36da4fdf765 100644
--- a/chromium/components/autofill/core/browser/autofill_profile_comparator_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_profile_comparator_unittest.cc
@@ -16,9 +16,11 @@
// Field Type Constants
using autofill::ADDRESS_HOME_CITY;
using autofill::ADDRESS_HOME_COUNTRY;
+using autofill::ADDRESS_HOME_DEPENDENT_LOCALITY;
using autofill::ADDRESS_HOME_LINE1;
using autofill::ADDRESS_HOME_LINE2;
using autofill::ADDRESS_HOME_LINE3;
+using autofill::ADDRESS_HOME_SORTING_CODE;
using autofill::ADDRESS_HOME_STATE;
using autofill::ADDRESS_HOME_STREET_ADDRESS;
using autofill::ADDRESS_HOME_ZIP;
@@ -239,6 +241,13 @@ class AutofillProfileComparatorTest : public ::testing::Test {
EXPECT_EQ(
expected.GetInfo(AutofillType(ADDRESS_HOME_STREET_ADDRESS), kLocale),
actual.GetInfo(AutofillType(ADDRESS_HOME_STREET_ADDRESS), kLocale));
+ EXPECT_EQ(
+ expected.GetInfo(AutofillType(ADDRESS_HOME_DEPENDENT_LOCALITY),
+ kLocale),
+ actual.GetInfo(AutofillType(ADDRESS_HOME_DEPENDENT_LOCALITY), kLocale));
+ EXPECT_EQ(
+ expected.GetInfo(AutofillType(ADDRESS_HOME_SORTING_CODE), kLocale),
+ actual.GetInfo(AutofillType(ADDRESS_HOME_SORTING_CODE), kLocale));
EXPECT_EQ(expected.GetInfo(AutofillType(ADDRESS_HOME_CITY), kLocale),
actual.GetInfo(AutofillType(ADDRESS_HOME_CITY), kLocale));
EXPECT_EQ(expected.GetInfo(AutofillType(ADDRESS_HOME_STATE), kLocale),
@@ -518,10 +527,14 @@ TEST_F(AutofillProfileComparatorTest, HaveMergeableAddresses) {
AutofillProfile empty = CreateProfileWithAddress("", "", "", "", "", "");
AutofillProfile p1 = CreateProfileWithAddress(
"1 Some Street", "Unit 3", "Carver", "CA - California", "90210", "US");
+ p1.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY, UTF8ToUTF16("Some String"));
+ p1.SetRawInfo(ADDRESS_HOME_SORTING_CODE, UTF8ToUTF16("64205 Biarritz CEDEX"));
+
AutofillProfile p2 = CreateProfileWithAddress(
"Unit 3", "1 Some Street", "Suburb", "california", "90 210-3214", "");
AutofillProfile p3 = CreateProfileWithAddress("1 Some Street #3", "",
"Carver City", "ca", "", "us");
+
AutofillProfile differentCountry =
CopyAndModify(p1, {{ADDRESS_HOME_COUNTRY, "CA"}});
AutofillProfile differentZip =
@@ -533,6 +546,10 @@ TEST_F(AutofillProfileComparatorTest, HaveMergeableAddresses) {
AutofillProfile differentAddress =
CopyAndModify(p1, {{ADDRESS_HOME_LINE1, "17 Park Lane"},
{ADDRESS_HOME_LINE2, "Suite 150"}});
+ AutofillProfile differentLocality =
+ CopyAndModify(p1, {{ADDRESS_HOME_DEPENDENT_LOCALITY, "Funky Chicken"}});
+ AutofillProfile differentSortingCode =
+ CopyAndModify(p1, {{ADDRESS_HOME_SORTING_CODE, "98000 Monaco"}});
EXPECT_TRUE(comparator_.HaveMergeableAddresses(p1, empty));
EXPECT_TRUE(comparator_.HaveMergeableAddresses(empty, p2));
@@ -553,6 +570,8 @@ TEST_F(AutofillProfileComparatorTest, HaveMergeableAddresses) {
EXPECT_FALSE(comparator_.HaveMergeableAddresses(p1, differentState));
EXPECT_FALSE(comparator_.HaveMergeableAddresses(p1, differentCity));
EXPECT_FALSE(comparator_.HaveMergeableAddresses(p1, differentAddress));
+ EXPECT_FALSE(comparator_.HaveMergeableAddresses(p1, differentLocality));
+ EXPECT_FALSE(comparator_.HaveMergeableAddresses(p1, differentSortingCode));
}
TEST_F(AutofillProfileComparatorTest, AreMergeable) {
@@ -902,7 +921,6 @@ TEST_F(AutofillProfileComparatorTest, MergePhoneNumbers_Intl) {
}
TEST_F(AutofillProfileComparatorTest, MergeAddresses) {
- AutofillProfile empty;
AutofillProfile p1 = CreateProfileWithAddress(
"1 Some Street", "Unit 3", "Carver", "CA - California", "90210", "US");
AutofillProfile p2 = CreateProfileWithAddress(
@@ -919,8 +937,25 @@ TEST_F(AutofillProfileComparatorTest, MergeAddresses) {
MergeAddressesAndExpect(p1, p2, expected);
}
+TEST_F(AutofillProfileComparatorTest, MergeAddressesMostUniqueTokens) {
+ AutofillProfile p1 = CreateProfileWithAddress(
+ "1 Some Street", "Unit 3", "Carver", "CA - California", "90210", "US");
+ AutofillProfile p2 = CreateProfileWithAddress(
+ "1 Some Other Street", "Unit 3", "Carver City", "ca", "90210-1234", "us");
+
+ Address expected;
+ expected.SetRawInfo(ADDRESS_HOME_LINE1, UTF8ToUTF16("1 Some Other Street"));
+ expected.SetRawInfo(ADDRESS_HOME_LINE2, UTF8ToUTF16("Unit 3"));
+ expected.SetRawInfo(ADDRESS_HOME_CITY, UTF8ToUTF16("Carver City"));
+ expected.SetRawInfo(ADDRESS_HOME_STATE, UTF8ToUTF16("ca"));
+ expected.SetRawInfo(ADDRESS_HOME_ZIP, UTF8ToUTF16("90210-1234"));
+ expected.SetRawInfo(ADDRESS_HOME_COUNTRY, UTF8ToUTF16("US"));
+
+ MergeAddressesAndExpect(p1, p2, expected);
+ MergeAddressesAndExpect(p2, p1, expected);
+}
+
TEST_F(AutofillProfileComparatorTest, MergeAddressesWithRewrite) {
- AutofillProfile empty;
AutofillProfile p1 = CreateProfileWithAddress(
"6543 CH BACON", "APP 3", "MONTRÉAL", "QUÉBEC", "HHH999", "ca");
AutofillProfile p2 = CreateProfileWithAddress(
@@ -936,4 +971,34 @@ TEST_F(AutofillProfileComparatorTest, MergeAddressesWithRewrite) {
expected.SetRawInfo(ADDRESS_HOME_COUNTRY, UTF8ToUTF16("CA"));
MergeAddressesAndExpect(p1, p2, expected);
+ MergeAddressesAndExpect(p2, p1, expected);
+}
+
+TEST_F(AutofillProfileComparatorTest,
+ MergeAddressesDependendLocalityAndSortingCode) {
+ AutofillProfile p1 = CreateProfileWithAddress(
+ "6543 CH BACON", "APP 3", "MONTRÉAL", "QUÉBEC", "HHH999", "ca");
+ p1.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY, UTF8ToUTF16("Some String"));
+ p1.SetRawInfo(ADDRESS_HOME_SORTING_CODE, UTF8ToUTF16("64205 Biarritz CEDEX"));
+ AutofillProfile p2 = CreateProfileWithAddress(
+ "6543, Bacon Rd", "", "Montreal", "QC", "hhh 999", "CA");
+ p2.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY,
+ UTF8ToUTF16("Some Other String"));
+ p2.SetRawInfo(ADDRESS_HOME_SORTING_CODE, UTF8ToUTF16("64205 Biarritz"));
+ p2.set_use_date(p1.use_date() + base::TimeDelta::FromMinutes(1));
+
+ Address expected;
+ expected.SetRawInfo(ADDRESS_HOME_LINE1, UTF8ToUTF16("6543 CH BACON"));
+ expected.SetRawInfo(ADDRESS_HOME_LINE2, UTF8ToUTF16("APP 3"));
+ expected.SetRawInfo(ADDRESS_HOME_CITY, UTF8ToUTF16("Montreal"));
+ expected.SetRawInfo(ADDRESS_HOME_STATE, UTF8ToUTF16("QC"));
+ expected.SetRawInfo(ADDRESS_HOME_ZIP, UTF8ToUTF16("hhh 999"));
+ expected.SetRawInfo(ADDRESS_HOME_COUNTRY, UTF8ToUTF16("CA"));
+ expected.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY,
+ UTF8ToUTF16("Some Other String"));
+ expected.SetRawInfo(ADDRESS_HOME_SORTING_CODE,
+ UTF8ToUTF16("64205 Biarritz")); // Preferred by use date.
+
+ MergeAddressesAndExpect(p1, p2, expected);
+ MergeAddressesAndExpect(p2, p1, expected);
}
diff --git a/chromium/components/autofill/core/browser/autofill_profile_unittest.cc b/chromium/components/autofill/core/browser/autofill_profile_unittest.cc
index d50ddecf7ee..c54f2ae61c4 100644
--- a/chromium/components/autofill/core/browser/autofill_profile_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_profile_unittest.cc
@@ -7,11 +7,12 @@
#include <stddef.h>
#include <memory>
+#include <vector>
#include "base/format_macros.h"
#include "base/guid.h"
#include "base/macros.h"
-#include "base/memory/scoped_vector.h"
+#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/strings/stringprintf.h"
@@ -79,6 +80,14 @@ void SetupTestProfile(AutofillProfile& profile) {
"Hollywood", "CA", "91601", "US", "12345678910");
}
+std::vector<AutofillProfile*> ToRawPointerVector(
+ const std::vector<std::unique_ptr<AutofillProfile>>& list) {
+ std::vector<AutofillProfile*> result;
+ for (const auto& item : list)
+ result.push_back(item.get());
+ return result;
+}
+
} // namespace
// Tests different possibilities for summary string generation.
@@ -186,62 +195,32 @@ TEST(AutofillProfileTest, PreviewSummaryString) {
}
TEST(AutofillProfileTest, AdjustInferredLabels) {
- ScopedVector<AutofillProfile> profiles;
- profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), "https://www.example.com/"));
- test::SetProfileInfo(
- profiles[0],
- "John",
- "",
- "Doe",
- "johndoe@hades.com",
- "Underworld",
- "666 Erebus St.",
- "",
- "Elysium", "CA",
- "91111",
- "US",
- "16502111111");
- profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), "http://www.example.com/"));
- test::SetProfileInfo(
- profiles[1],
- "Jane",
- "",
- "Doe",
- "janedoe@tertium.com",
- "Pluto Inc.",
- "123 Letha Shore.",
- "",
- "Dis", "CA",
- "91222",
- "US",
- "12345678910");
+ std::vector<std::unique_ptr<AutofillProfile>> profiles;
+ profiles.push_back(base::MakeUnique<AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com/"));
+ test::SetProfileInfo(profiles[0].get(), "John", "", "Doe",
+ "johndoe@hades.com", "Underworld", "666 Erebus St.", "",
+ "Elysium", "CA", "91111", "US", "16502111111");
+ profiles.push_back(base::MakeUnique<AutofillProfile>(
+ base::GenerateGUID(), "http://www.example.com/"));
+ test::SetProfileInfo(profiles[1].get(), "Jane", "", "Doe",
+ "janedoe@tertium.com", "Pluto Inc.", "123 Letha Shore.",
+ "", "Dis", "CA", "91222", "US", "12345678910");
std::vector<base::string16> labels;
- AutofillProfile::CreateDifferentiatingLabels(
- profiles.get(), "en-US", &labels);
+ AutofillProfile::CreateDifferentiatingLabels(ToRawPointerVector(profiles),
+ "en-US", &labels);
ASSERT_EQ(2U, labels.size());
EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St."), labels[0]);
EXPECT_EQ(ASCIIToUTF16("Jane Doe, 123 Letha Shore."), labels[1]);
profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), kSettingsOrigin));
- test::SetProfileInfo(
- profiles[2],
- "John",
- "",
- "Doe",
- "johndoe@tertium.com",
- "Underworld",
- "666 Erebus St.",
- "",
- "Elysium", "CA",
- "91111",
- "US",
- "16502111111");
+ base::MakeUnique<AutofillProfile>(base::GenerateGUID(), kSettingsOrigin));
+ test::SetProfileInfo(profiles[2].get(), "John", "", "Doe",
+ "johndoe@tertium.com", "Underworld", "666 Erebus St.",
+ "", "Elysium", "CA", "91111", "US", "16502111111");
labels.clear();
- AutofillProfile::CreateDifferentiatingLabels(
- profiles.get(), "en-US", &labels);
+ AutofillProfile::CreateDifferentiatingLabels(ToRawPointerVector(profiles),
+ "en-US", &labels);
// Profile 0 and 2 inferred label now includes an e-mail.
ASSERT_EQ(3U, labels.size());
@@ -254,24 +233,15 @@ TEST(AutofillProfileTest, AdjustInferredLabels) {
profiles.resize(2);
profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), std::string()));
- test::SetProfileInfo(
- profiles[2],
- "John",
- "",
- "Doe",
- "johndoe@hades.com",
- "Underworld",
- "666 Erebus St.",
- "",
- "Elysium", "CO", // State is different
- "91111",
- "US",
- "16502111111");
+ base::MakeUnique<AutofillProfile>(base::GenerateGUID(), std::string()));
+ test::SetProfileInfo(profiles[2].get(), "John", "", "Doe",
+ "johndoe@hades.com", "Underworld", "666 Erebus St.", "",
+ "Elysium", "CO", // State is different
+ "91111", "US", "16502111111");
labels.clear();
- AutofillProfile::CreateDifferentiatingLabels(
- profiles.get(), "en-US", &labels);
+ AutofillProfile::CreateDifferentiatingLabels(ToRawPointerVector(profiles),
+ "en-US", &labels);
// Profile 0 and 2 inferred label now includes a state.
ASSERT_EQ(3U, labels.size());
@@ -279,25 +249,17 @@ TEST(AutofillProfileTest, AdjustInferredLabels) {
EXPECT_EQ(ASCIIToUTF16("Jane Doe, 123 Letha Shore."), labels[1]);
EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., CO"), labels[2]);
- profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), "https://www.example.com/"));
- test::SetProfileInfo(
- profiles[3],
- "John",
- "",
- "Doe",
- "johndoe@hades.com",
- "Underworld",
- "666 Erebus St.",
- "",
- "Elysium", "CO", // State is different for some.
- "91111",
- "US",
- "16504444444"); // Phone is different for some.
+ profiles.push_back(base::MakeUnique<AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com/"));
+ test::SetProfileInfo(profiles[3].get(), "John", "", "Doe",
+ "johndoe@hades.com", "Underworld", "666 Erebus St.", "",
+ "Elysium", "CO", // State is different for some.
+ "91111", "US",
+ "16504444444"); // Phone is different for some.
labels.clear();
- AutofillProfile::CreateDifferentiatingLabels(
- profiles.get(), "en-US", &labels);
+ AutofillProfile::CreateDifferentiatingLabels(ToRawPointerVector(profiles),
+ "en-US", &labels);
ASSERT_EQ(4U, labels.size());
EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., CA"), labels[0]);
EXPECT_EQ(ASCIIToUTF16("Jane Doe, 123 Letha Shore."), labels[1]);
@@ -308,25 +270,18 @@ TEST(AutofillProfileTest, AdjustInferredLabels) {
EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., CO, 16504444444"),
labels[3]);
- profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), "https://www.example.com/"));
- test::SetProfileInfo(
- profiles[4],
- "John",
- "",
- "Doe",
- "johndoe@styx.com", // E-Mail is different for some.
- "Underworld",
- "666 Erebus St.",
- "",
- "Elysium", "CO", // State is different for some.
- "91111",
- "US",
- "16504444444"); // Phone is different for some.
+ profiles.push_back(base::MakeUnique<AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com/"));
+ test::SetProfileInfo(profiles[4].get(), "John", "", "Doe",
+ "johndoe@styx.com", // E-Mail is different for some.
+ "Underworld", "666 Erebus St.", "", "Elysium",
+ "CO", // State is different for some.
+ "91111", "US",
+ "16504444444"); // Phone is different for some.
labels.clear();
- AutofillProfile::CreateDifferentiatingLabels(
- profiles.get(), "en-US", &labels);
+ AutofillProfile::CreateDifferentiatingLabels(ToRawPointerVector(profiles),
+ "en-US", &labels);
ASSERT_EQ(5U, labels.size());
EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., CA"), labels[0]);
EXPECT_EQ(ASCIIToUTF16("Jane Doe, 123 Letha Shore."), labels[1]);
@@ -341,21 +296,13 @@ TEST(AutofillProfileTest, AdjustInferredLabels) {
}
TEST(AutofillProfileTest, CreateInferredLabelsI18n_CH) {
- ScopedVector<AutofillProfile> profiles;
- profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), "https://www.example.com/"));
- test::SetProfileInfo(profiles.back(),
- "H.",
- "R.",
- "Giger",
- "hrgiger@beispiel.com",
- "Beispiel Inc",
- "Brandschenkestrasse 110",
- "",
- "Zurich", "",
- "8002",
- "CH",
- "+41 44-668-1800");
+ std::vector<std::unique_ptr<AutofillProfile>> profiles;
+ profiles.push_back(base::MakeUnique<AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com/"));
+ test::SetProfileInfo(profiles.back().get(), "H.", "R.", "Giger",
+ "hrgiger@beispiel.com", "Beispiel Inc",
+ "Brandschenkestrasse 110", "", "Zurich", "", "8002",
+ "CH", "+41 44-668-1800");
profiles.back()->set_language_code("de_CH");
static const char* kExpectedLabels[] = {
"",
@@ -374,8 +321,8 @@ TEST(AutofillProfileTest, CreateInferredLabelsI18n_CH) {
std::vector<base::string16> labels;
for (size_t i = 0; i < arraysize(kExpectedLabels); ++i) {
- AutofillProfile::CreateInferredLabels(
- profiles.get(), NULL, UNKNOWN_TYPE, i, "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles), NULL,
+ UNKNOWN_TYPE, i, "en-US", &labels);
ASSERT_FALSE(labels.empty());
EXPECT_EQ(UTF8ToUTF16(kExpectedLabels[i]), labels.back());
}
@@ -383,21 +330,12 @@ TEST(AutofillProfileTest, CreateInferredLabelsI18n_CH) {
TEST(AutofillProfileTest, CreateInferredLabelsI18n_FR) {
- ScopedVector<AutofillProfile> profiles;
- profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), "https://www.example.com/"));
- test::SetProfileInfo(profiles.back(),
- "Antoine",
- "",
- "de Saint-Exupéry",
- "antoine@exemple.com",
- "Exemple Inc",
- "8 Rue de Londres",
- "",
- "Paris", "",
- "75009",
- "FR",
- "+33 (0) 1 42 68 53 00");
+ std::vector<std::unique_ptr<AutofillProfile>> profiles;
+ profiles.push_back(base::MakeUnique<AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com/"));
+ test::SetProfileInfo(profiles.back().get(), "Antoine", "", "de Saint-Exupéry",
+ "antoine@exemple.com", "Exemple Inc", "8 Rue de Londres",
+ "", "Paris", "", "75009", "FR", "+33 (0) 1 42 68 53 00");
profiles.back()->set_language_code("fr_FR");
profiles.back()->SetInfo(
AutofillType(ADDRESS_HOME_SORTING_CODE), UTF8ToUTF16("CEDEX"), "en-US");
@@ -422,29 +360,21 @@ TEST(AutofillProfileTest, CreateInferredLabelsI18n_FR) {
std::vector<base::string16> labels;
for (size_t i = 0; i < arraysize(kExpectedLabels); ++i) {
- AutofillProfile::CreateInferredLabels(
- profiles.get(), NULL, UNKNOWN_TYPE, i, "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles), NULL,
+ UNKNOWN_TYPE, i, "en-US", &labels);
ASSERT_FALSE(labels.empty());
EXPECT_EQ(UTF8ToUTF16(kExpectedLabels[i]), labels.back());
}
}
TEST(AutofillProfileTest, CreateInferredLabelsI18n_KR) {
- ScopedVector<AutofillProfile> profiles;
- profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), "https://www.example.com/"));
- test::SetProfileInfo(profiles.back(),
- "Park",
- "",
- "Jae-sang",
- "park@yeleul.com",
- "Yeleul Inc",
- "Gangnam Finance Center",
- "152 Teheran-ro",
- "Gangnam-Gu", "Seoul",
- "135-984",
- "KR",
- "+82-2-531-9000");
+ std::vector<std::unique_ptr<AutofillProfile>> profiles;
+ profiles.push_back(base::MakeUnique<AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com/"));
+ test::SetProfileInfo(profiles.back().get(), "Park", "", "Jae-sang",
+ "park@yeleul.com", "Yeleul Inc",
+ "Gangnam Finance Center", "152 Teheran-ro", "Gangnam-Gu",
+ "Seoul", "135-984", "KR", "+82-2-531-9000");
profiles.back()->set_language_code("ko_Latn");
profiles.back()->SetInfo(AutofillType(ADDRESS_HOME_DEPENDENT_LOCALITY),
UTF8ToUTF16("Yeoksam-Dong"),
@@ -475,29 +405,21 @@ TEST(AutofillProfileTest, CreateInferredLabelsI18n_KR) {
std::vector<base::string16> labels;
for (size_t i = 0; i < arraysize(kExpectedLabels); ++i) {
- AutofillProfile::CreateInferredLabels(
- profiles.get(), NULL, UNKNOWN_TYPE, i, "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles), NULL,
+ UNKNOWN_TYPE, i, "en-US", &labels);
ASSERT_FALSE(labels.empty());
EXPECT_EQ(UTF8ToUTF16(kExpectedLabels[i]), labels.back());
}
}
TEST(AutofillProfileTest, CreateInferredLabelsI18n_JP_Latn) {
- ScopedVector<AutofillProfile> profiles;
- profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), "https://www.example.com/"));
- test::SetProfileInfo(profiles.back(),
- "Miku",
- "",
- "Hatsune",
- "miku@rei.com",
- "Rei Inc",
- "Roppongi Hills Mori Tower",
- "6-10-1 Roppongi",
- "Minato-ku", "Tokyo",
- "106-6126",
- "JP",
- "+81-3-6384-9000");
+ std::vector<std::unique_ptr<AutofillProfile>> profiles;
+ profiles.push_back(base::MakeUnique<AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com/"));
+ test::SetProfileInfo(profiles.back().get(), "Miku", "", "Hatsune",
+ "miku@rei.com", "Rei Inc", "Roppongi Hills Mori Tower",
+ "6-10-1 Roppongi", "Minato-ku", "Tokyo", "106-6126",
+ "JP", "+81-3-6384-9000");
profiles.back()->set_language_code("ja_Latn");
static const char* kExpectedLabels[] = {
"",
@@ -521,28 +443,20 @@ TEST(AutofillProfileTest, CreateInferredLabelsI18n_JP_Latn) {
std::vector<base::string16> labels;
for (size_t i = 0; i < arraysize(kExpectedLabels); ++i) {
- AutofillProfile::CreateInferredLabels(
- profiles.get(), NULL, UNKNOWN_TYPE, i, "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles), NULL,
+ UNKNOWN_TYPE, i, "en-US", &labels);
ASSERT_FALSE(labels.empty());
EXPECT_EQ(UTF8ToUTF16(kExpectedLabels[i]), labels.back());
}
}
TEST(AutofillProfileTest, CreateInferredLabelsI18n_JP_ja) {
- ScopedVector<AutofillProfile> profiles;
- profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), "https://www.example.com/"));
- test::SetProfileInfo(profiles.back(),
- "ミク",
- "",
- "初音",
- "miku@rei.com",
- "例",
- "六本木ヒルズ森タワー",
- "六本木 6-10-1",
- "港区", "東京都",
- "106-6126",
- "JP",
+ std::vector<std::unique_ptr<AutofillProfile>> profiles;
+ profiles.push_back(base::MakeUnique<AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com/"));
+ test::SetProfileInfo(profiles.back().get(), "ミク", "", "初音",
+ "miku@rei.com", "例", "六本木ヒルズ森タワー",
+ "六本木 6-10-1", "港区", "東京都", "106-6126", "JP",
"03-6384-9000");
profiles.back()->set_language_code("ja_JP");
static const char* kExpectedLabels[] = {
@@ -563,53 +477,35 @@ TEST(AutofillProfileTest, CreateInferredLabelsI18n_JP_ja) {
std::vector<base::string16> labels;
for (size_t i = 0; i < arraysize(kExpectedLabels); ++i) {
- AutofillProfile::CreateInferredLabels(
- profiles.get(), NULL, UNKNOWN_TYPE, i, "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles), NULL,
+ UNKNOWN_TYPE, i, "en-US", &labels);
ASSERT_FALSE(labels.empty());
EXPECT_EQ(UTF8ToUTF16(kExpectedLabels[i]), labels.back());
}
}
TEST(AutofillProfileTest, CreateInferredLabels) {
- ScopedVector<AutofillProfile> profiles;
- profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), "https://www.example.com/"));
- test::SetProfileInfo(profiles[0],
- "John",
- "",
- "Doe",
- "johndoe@hades.com",
- "Underworld",
- "666 Erebus St.",
- "",
- "Elysium", "CA",
- "91111",
- "US",
- "16502111111");
- profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), "https://www.example.com/"));
- test::SetProfileInfo(profiles[1],
- "Jane",
- "",
- "Doe",
- "janedoe@tertium.com",
- "Pluto Inc.",
- "123 Letha Shore.",
- "",
- "Dis", "CA",
- "91222",
- "US",
- "12345678910");
+ std::vector<std::unique_ptr<AutofillProfile>> profiles;
+ profiles.push_back(base::MakeUnique<AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com/"));
+ test::SetProfileInfo(profiles[0].get(), "John", "", "Doe",
+ "johndoe@hades.com", "Underworld", "666 Erebus St.", "",
+ "Elysium", "CA", "91111", "US", "16502111111");
+ profiles.push_back(base::MakeUnique<AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com/"));
+ test::SetProfileInfo(profiles[1].get(), "Jane", "", "Doe",
+ "janedoe@tertium.com", "Pluto Inc.", "123 Letha Shore.",
+ "", "Dis", "CA", "91222", "US", "12345678910");
std::vector<base::string16> labels;
// Two fields at least - no filter.
- AutofillProfile::CreateInferredLabels(profiles.get(), NULL, UNKNOWN_TYPE, 2,
- "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles), NULL,
+ UNKNOWN_TYPE, 2, "en-US", &labels);
EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St."), labels[0]);
EXPECT_EQ(ASCIIToUTF16("Jane Doe, 123 Letha Shore."), labels[1]);
// Three fields at least - no filter.
- AutofillProfile::CreateInferredLabels(profiles.get(), NULL, UNKNOWN_TYPE, 3,
- "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles), NULL,
+ UNKNOWN_TYPE, 3, "en-US", &labels);
EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., Elysium"),
labels[0]);
EXPECT_EQ(ASCIIToUTF16("Jane Doe, 123 Letha Shore., Dis"),
@@ -621,21 +517,24 @@ TEST(AutofillProfileTest, CreateInferredLabels) {
suggested_fields.push_back(ADDRESS_HOME_ZIP);
// Two fields at least, from suggested fields - no filter.
- AutofillProfile::CreateInferredLabels(profiles.get(), &suggested_fields,
- UNKNOWN_TYPE, 2, "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles),
+ &suggested_fields, UNKNOWN_TYPE, 2,
+ "en-US", &labels);
EXPECT_EQ(ASCIIToUTF16("Elysium 91111"), labels[0]);
EXPECT_EQ(ASCIIToUTF16("Dis 91222"), labels[1]);
// Three fields at least, from suggested fields - no filter.
- AutofillProfile::CreateInferredLabels(profiles.get(), &suggested_fields,
- UNKNOWN_TYPE, 3, "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles),
+ &suggested_fields, UNKNOWN_TYPE, 3,
+ "en-US", &labels);
EXPECT_EQ(ASCIIToUTF16("Elysium, CA 91111"), labels[0]);
EXPECT_EQ(ASCIIToUTF16("Dis, CA 91222"), labels[1]);
// Three fields at least, from suggested fields - but filter reduces available
// fields to two.
- AutofillProfile::CreateInferredLabels(profiles.get(), &suggested_fields,
- ADDRESS_HOME_ZIP, 3, "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles),
+ &suggested_fields, ADDRESS_HOME_ZIP, 3,
+ "en-US", &labels);
EXPECT_EQ(ASCIIToUTF16("Elysium, CA"), labels[0]);
EXPECT_EQ(ASCIIToUTF16("Dis, CA"), labels[1]);
@@ -643,15 +542,17 @@ TEST(AutofillProfileTest, CreateInferredLabels) {
// In our implementation we always display NAME_FULL for all NAME* fields...
suggested_fields.push_back(NAME_MIDDLE);
// One field at least, from suggested fields - no filter.
- AutofillProfile::CreateInferredLabels(profiles.get(), &suggested_fields,
- UNKNOWN_TYPE, 1, "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles),
+ &suggested_fields, UNKNOWN_TYPE, 1,
+ "en-US", &labels);
EXPECT_EQ(ASCIIToUTF16("John Doe"), labels[0]);
EXPECT_EQ(ASCIIToUTF16("Jane Doe"), labels[1]);
// One field at least, from suggested fields - filter the same as suggested
// field.
- AutofillProfile::CreateInferredLabels(profiles.get(), &suggested_fields,
- NAME_MIDDLE, 1, "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles),
+ &suggested_fields, NAME_MIDDLE, 1,
+ "en-US", &labels);
EXPECT_EQ(base::string16(), labels[0]);
EXPECT_EQ(base::string16(), labels[1]);
@@ -659,8 +560,9 @@ TEST(AutofillProfileTest, CreateInferredLabels) {
// In our implementation we always display NAME_FULL for NAME_MIDDLE_INITIAL
suggested_fields.push_back(NAME_MIDDLE_INITIAL);
// One field at least, from suggested fields - no filter.
- AutofillProfile::CreateInferredLabels(profiles.get(), &suggested_fields,
- UNKNOWN_TYPE, 1, "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles),
+ &suggested_fields, UNKNOWN_TYPE, 1,
+ "en-US", &labels);
EXPECT_EQ(ASCIIToUTF16("John Doe"), labels[0]);
EXPECT_EQ(ASCIIToUTF16("Jane Doe"), labels[1]);
@@ -670,13 +572,14 @@ TEST(AutofillProfileTest, CreateInferredLabels) {
suggested_fields.push_back(UNKNOWN_TYPE);
suggested_fields.push_back(NAME_FULL);
suggested_fields.push_back(ADDRESS_HOME_LINE1);
- AutofillProfile::CreateInferredLabels(profiles.get(), &suggested_fields,
- NAME_FULL, 1, "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles),
+ &suggested_fields, NAME_FULL, 1,
+ "en-US", &labels);
EXPECT_EQ(base::string16(ASCIIToUTF16("666 Erebus St.")), labels[0]);
EXPECT_EQ(base::string16(ASCIIToUTF16("123 Letha Shore.")), labels[1]);
// No suggested fields, but non-unknown excluded field.
- AutofillProfile::CreateInferredLabels(profiles.get(), NULL,
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles), NULL,
NAME_FULL, 1, "en-US", &labels);
EXPECT_EQ(base::string16(ASCIIToUTF16("666 Erebus St.")), labels[0]);
EXPECT_EQ(base::string16(ASCIIToUTF16("123 Letha Shore.")), labels[1]);
@@ -685,17 +588,16 @@ TEST(AutofillProfileTest, CreateInferredLabels) {
// Test that we fall back to using the full name if there are no other
// distinguishing fields, but only if it makes sense given the suggested fields.
TEST(AutofillProfileTest, CreateInferredLabelsFallsBackToFullName) {
- ScopedVector<AutofillProfile> profiles;
- profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), "https://www.example.com/"));
- test::SetProfileInfo(profiles[0],
- "John", "", "Doe", "doe@example.com", "",
- "88 Nowhere Ave.", "", "", "", "", "", "");
- profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), "https://www.example.com/"));
- test::SetProfileInfo(profiles[1],
- "Johnny", "K", "Doe", "doe@example.com", "",
- "88 Nowhere Ave.", "", "", "", "", "", "");
+ std::vector<std::unique_ptr<AutofillProfile>> profiles;
+ profiles.push_back(base::MakeUnique<AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com/"));
+ test::SetProfileInfo(profiles[0].get(), "John", "", "Doe", "doe@example.com",
+ "", "88 Nowhere Ave.", "", "", "", "", "", "");
+ profiles.push_back(base::MakeUnique<AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com/"));
+ test::SetProfileInfo(profiles[1].get(), "Johnny", "K", "Doe",
+ "doe@example.com", "", "88 Nowhere Ave.", "", "", "", "",
+ "", "");
// If the only name field in the suggested fields is the excluded field, we
// should not fall back to the full name as a distinguishing field.
@@ -704,16 +606,18 @@ TEST(AutofillProfileTest, CreateInferredLabelsFallsBackToFullName) {
suggested_fields.push_back(ADDRESS_HOME_LINE1);
suggested_fields.push_back(EMAIL_ADDRESS);
std::vector<base::string16> labels;
- AutofillProfile::CreateInferredLabels(profiles.get(), &suggested_fields,
- NAME_LAST, 1, "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles),
+ &suggested_fields, NAME_LAST, 1,
+ "en-US", &labels);
ASSERT_EQ(2U, labels.size());
EXPECT_EQ(ASCIIToUTF16("88 Nowhere Ave."), labels[0]);
EXPECT_EQ(ASCIIToUTF16("88 Nowhere Ave."), labels[1]);
// Otherwise, we should.
suggested_fields.push_back(NAME_FIRST);
- AutofillProfile::CreateInferredLabels(profiles.get(), &suggested_fields,
- NAME_LAST, 1, "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles),
+ &suggested_fields, NAME_LAST, 1,
+ "en-US", &labels);
ASSERT_EQ(2U, labels.size());
EXPECT_EQ(ASCIIToUTF16("88 Nowhere Ave., John Doe"), labels[0]);
EXPECT_EQ(ASCIIToUTF16("88 Nowhere Ave., Johnny K Doe"), labels[1]);
@@ -721,17 +625,15 @@ TEST(AutofillProfileTest, CreateInferredLabelsFallsBackToFullName) {
// Test that we do not show duplicate fields in the labels.
TEST(AutofillProfileTest, CreateInferredLabelsNoDuplicatedFields) {
- ScopedVector<AutofillProfile> profiles;
- profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), "https://www.example.com/"));
- test::SetProfileInfo(profiles[0],
- "John", "", "Doe", "doe@example.com", "",
- "88 Nowhere Ave.", "", "", "", "", "", "");
- profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), "https://www.example.com/"));
- test::SetProfileInfo(profiles[1],
- "John", "", "Doe", "dojo@example.com", "",
- "88 Nowhere Ave.", "", "", "", "", "", "");
+ std::vector<std::unique_ptr<AutofillProfile>> profiles;
+ profiles.push_back(base::MakeUnique<AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com/"));
+ test::SetProfileInfo(profiles[0].get(), "John", "", "Doe", "doe@example.com",
+ "", "88 Nowhere Ave.", "", "", "", "", "", "");
+ profiles.push_back(base::MakeUnique<AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com/"));
+ test::SetProfileInfo(profiles[1].get(), "John", "", "Doe", "dojo@example.com",
+ "", "88 Nowhere Ave.", "", "", "", "", "", "");
// If the only name field in the suggested fields is the excluded field, we
// should not fall back to the full name as a distinguishing field.
@@ -740,8 +642,9 @@ TEST(AutofillProfileTest, CreateInferredLabelsNoDuplicatedFields) {
suggested_fields.push_back(ADDRESS_BILLING_LINE1);
suggested_fields.push_back(EMAIL_ADDRESS);
std::vector<base::string16> labels;
- AutofillProfile::CreateInferredLabels(profiles.get(), &suggested_fields,
- UNKNOWN_TYPE, 2, "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles),
+ &suggested_fields, UNKNOWN_TYPE, 2,
+ "en-US", &labels);
ASSERT_EQ(2U, labels.size());
EXPECT_EQ(ASCIIToUTF16("88 Nowhere Ave., doe@example.com"), labels[0]);
EXPECT_EQ(ASCIIToUTF16("88 Nowhere Ave., dojo@example.com"), labels[1]);
@@ -749,26 +652,24 @@ TEST(AutofillProfileTest, CreateInferredLabelsNoDuplicatedFields) {
// Make sure that empty fields are not treated as distinguishing fields.
TEST(AutofillProfileTest, CreateInferredLabelsSkipsEmptyFields) {
- ScopedVector<AutofillProfile> profiles;
- profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), "https://www.example.com/"));
- test::SetProfileInfo(profiles[0],
- "John", "", "Doe", "doe@example.com",
+ std::vector<std::unique_ptr<AutofillProfile>> profiles;
+ profiles.push_back(base::MakeUnique<AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com/"));
+ test::SetProfileInfo(profiles[0].get(), "John", "", "Doe", "doe@example.com",
"Gogole", "", "", "", "", "", "", "");
- profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), "https://www.example.com/"));
- test::SetProfileInfo(profiles[1],
- "John", "", "Doe", "doe@example.com",
+ profiles.push_back(base::MakeUnique<AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com/"));
+ test::SetProfileInfo(profiles[1].get(), "John", "", "Doe", "doe@example.com",
"Ggoole", "", "", "", "", "", "", "");
- profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), "https://www.example.com/"));
- test::SetProfileInfo(profiles[2],
- "John", "", "Doe", "john.doe@example.com",
- "Goolge", "", "", "", "", "", "", "");
+ profiles.push_back(base::MakeUnique<AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com/"));
+ test::SetProfileInfo(profiles[2].get(), "John", "", "Doe",
+ "john.doe@example.com", "Goolge", "", "", "", "", "", "",
+ "");
std::vector<base::string16> labels;
- AutofillProfile::CreateInferredLabels(profiles.get(), NULL, UNKNOWN_TYPE, 3,
- "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles), NULL,
+ UNKNOWN_TYPE, 3, "en-US", &labels);
ASSERT_EQ(3U, labels.size());
EXPECT_EQ(ASCIIToUTF16("John Doe, doe@example.com, Gogole"), labels[0]);
EXPECT_EQ(ASCIIToUTF16("John Doe, doe@example.com, Ggoole"), labels[1]);
@@ -777,8 +678,8 @@ TEST(AutofillProfileTest, CreateInferredLabelsSkipsEmptyFields) {
// A field must have a non-empty value for each profile to be considered a
// distinguishing field.
profiles[1]->SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("88 Nowhere Ave."));
- AutofillProfile::CreateInferredLabels(profiles.get(), NULL, UNKNOWN_TYPE, 1,
- "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles), NULL,
+ UNKNOWN_TYPE, 1, "en-US", &labels);
ASSERT_EQ(3U, labels.size());
EXPECT_EQ(ASCIIToUTF16("John Doe, doe@example.com, Gogole"), labels[0]);
EXPECT_EQ(ASCIIToUTF16("John Doe, 88 Nowhere Ave., doe@example.com, Ggoole"),
@@ -788,12 +689,11 @@ TEST(AutofillProfileTest, CreateInferredLabelsSkipsEmptyFields) {
// Test that labels that would otherwise have multiline values are flattened.
TEST(AutofillProfileTest, CreateInferredLabelsFlattensMultiLineValues) {
- ScopedVector<AutofillProfile> profiles;
- profiles.push_back(
- new AutofillProfile(base::GenerateGUID(), "https://www.example.com/"));
- test::SetProfileInfo(profiles[0],
- "John", "", "Doe", "doe@example.com", "",
- "88 Nowhere Ave.", "Apt. 42", "", "", "", "", "");
+ std::vector<std::unique_ptr<AutofillProfile>> profiles;
+ profiles.push_back(base::MakeUnique<AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com/"));
+ test::SetProfileInfo(profiles[0].get(), "John", "", "Doe", "doe@example.com",
+ "", "88 Nowhere Ave.", "Apt. 42", "", "", "", "", "");
// If the only name field in the suggested fields is the excluded field, we
// should not fall back to the full name as a distinguishing field.
@@ -801,8 +701,9 @@ TEST(AutofillProfileTest, CreateInferredLabelsFlattensMultiLineValues) {
suggested_fields.push_back(NAME_FULL);
suggested_fields.push_back(ADDRESS_HOME_STREET_ADDRESS);
std::vector<base::string16> labels;
- AutofillProfile::CreateInferredLabels(profiles.get(), &suggested_fields,
- NAME_FULL, 1, "en-US", &labels);
+ AutofillProfile::CreateInferredLabels(ToRawPointerVector(profiles),
+ &suggested_fields, NAME_FULL, 1,
+ "en-US", &labels);
ASSERT_EQ(1U, labels.size());
EXPECT_EQ(ASCIIToUTF16("88 Nowhere Ave., Apt. 42"), labels[0]);
}
diff --git a/chromium/components/autofill/core/browser/autofill_scanner.cc b/chromium/components/autofill/core/browser/autofill_scanner.cc
index 47a8c4c989e..857a7b8987f 100644
--- a/chromium/components/autofill/core/browser/autofill_scanner.cc
+++ b/chromium/components/autofill/core/browser/autofill_scanner.cc
@@ -9,11 +9,16 @@
namespace autofill {
-AutofillScanner::AutofillScanner(const std::vector<AutofillField*>& fields)
- : cursor_(fields.begin()),
- saved_cursor_(fields.begin()),
- begin_(fields.begin()),
- end_(fields.end()) {
+AutofillScanner::AutofillScanner(const std::vector<AutofillField*>& fields) {
+ Init(fields);
+}
+
+AutofillScanner::AutofillScanner(
+ const std::vector<std::unique_ptr<AutofillField>>& fields) {
+ for (const auto& field : fields)
+ non_owning_.push_back(field.get());
+
+ Init(non_owning_);
}
AutofillScanner::~AutofillScanner() {
@@ -27,7 +32,7 @@ void AutofillScanner::Advance() {
AutofillField* AutofillScanner::Cursor() const {
if (IsEnd()) {
NOTREACHED();
- return NULL;
+ return nullptr;
}
return *cursor_;
@@ -54,4 +59,11 @@ size_t AutofillScanner::SaveCursor() {
return static_cast<size_t>(cursor_ - begin_);
}
+void AutofillScanner::Init(const std::vector<AutofillField*>& fields) {
+ cursor_ = fields.begin();
+ saved_cursor_ = fields.begin();
+ begin_ = fields.begin();
+ end_ = fields.end();
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_scanner.h b/chromium/components/autofill/core/browser/autofill_scanner.h
index f30d5abcbc3..88b84e6fd94 100644
--- a/chromium/components/autofill/core/browser/autofill_scanner.h
+++ b/chromium/components/autofill/core/browser/autofill_scanner.h
@@ -7,6 +7,7 @@
#include <stddef.h>
+#include <memory>
#include <vector>
#include "base/macros.h"
@@ -20,6 +21,8 @@ class AutofillField;
class AutofillScanner {
public:
explicit AutofillScanner(const std::vector<AutofillField*>& fields);
+ explicit AutofillScanner(
+ const std::vector<std::unique_ptr<AutofillField>>& fields);
~AutofillScanner();
// Advances the cursor by one step, if possible.
@@ -43,6 +46,8 @@ class AutofillScanner {
size_t SaveCursor();
private:
+ void Init(const std::vector<AutofillField*>& fields);
+
// Indicates the current position in the stream, represented as a vector.
std::vector<AutofillField*>::const_iterator cursor_;
@@ -50,10 +55,13 @@ class AutofillScanner {
std::vector<AutofillField*>::const_iterator saved_cursor_;
// The beginning pointer for the stream.
- const std::vector<AutofillField*>::const_iterator begin_;
+ std::vector<AutofillField*>::const_iterator begin_;
// The past-the-end pointer for the stream.
- const std::vector<AutofillField*>::const_iterator end_;
+ std::vector<AutofillField*>::const_iterator end_;
+
+ // The storage of non-owning pointers, used for the unique_ptr constructor.
+ std::vector<AutofillField*> non_owning_;
DISALLOW_COPY_AND_ASSIGN(AutofillScanner);
};
diff --git a/chromium/components/autofill/core/browser/autofill_type.cc b/chromium/components/autofill/core/browser/autofill_type.cc
index 47081994a9d..8dc9dbc85ad 100644
--- a/chromium/components/autofill/core/browser/autofill_type.cc
+++ b/chromium/components/autofill/core/browser/autofill_type.cc
@@ -126,6 +126,7 @@ FieldTypeGroup AutofillType::group() const {
case PROBABLY_NEW_PASSWORD:
case NOT_NEW_PASSWORD:
case PROBABLY_ACCOUNT_CREATION_PASSWORD:
+ case CONFIRMATION_PASSWORD:
return PASSWORD_FIELD;
case NO_SERVER_DATA:
@@ -757,6 +758,8 @@ std::string AutofillType::ServerFieldTypeToString(ServerFieldType type) {
return "NOT_NEW_PASSWORD";
case PROBABLY_ACCOUNT_CREATION_PASSWORD:
return "PROBABLY_ACCOUNT_CREATION_PASSWORD";
+ case CONFIRMATION_PASSWORD:
+ return "CONFIRMATION_PASSWORD";
case MAX_VALID_FIELD_TYPE:
return std::string();
diff --git a/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.cc b/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.cc
index 61bf8140a6c..ecdcce20fa0 100644
--- a/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.cc
+++ b/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.cc
@@ -4,6 +4,8 @@
#include "components/autofill/core/browser/autofill_wallet_data_type_controller.h"
+#include <utility>
+
#include "base/bind.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
@@ -18,13 +20,15 @@ namespace browser_sync {
AutofillWalletDataTypeController::AutofillWalletDataTypeController(
syncer::ModelType type,
- const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
+ scoped_refptr<base::SingleThreadTaskRunner> db_thread,
const base::Closure& dump_stack,
syncer::SyncClient* sync_client,
const scoped_refptr<autofill::AutofillWebDataService>& web_data_service)
- : NonUIDataTypeController(type, dump_stack, sync_client),
- db_thread_(db_thread),
- sync_client_(sync_client),
+ : AsyncDirectoryTypeController(type,
+ dump_stack,
+ sync_client,
+ syncer::GROUP_DB,
+ std::move(db_thread)),
callback_registered_(false),
web_data_service_(web_data_service),
currently_enabled_(IsEnabled()) {
@@ -39,18 +43,6 @@ AutofillWalletDataTypeController::AutofillWalletDataTypeController(
AutofillWalletDataTypeController::~AutofillWalletDataTypeController() {}
-syncer::ModelSafeGroup AutofillWalletDataTypeController::model_safe_group()
- const {
- return syncer::GROUP_DB;
-}
-
-bool AutofillWalletDataTypeController::PostTaskOnBackendThread(
- const tracked_objects::Location& from_here,
- const base::Closure& task) {
- DCHECK(CalledOnValidThread());
- return db_thread_->PostTask(from_here, task);
-}
-
bool AutofillWalletDataTypeController::StartModels() {
DCHECK(CalledOnValidThread());
DCHECK_EQ(state(), MODEL_STARTING);
diff --git a/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.h b/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.h
index e483e0b304f..cffe8628f57 100644
--- a/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.h
+++ b/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.h
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "components/prefs/pref_change_registrar.h"
-#include "components/sync/driver/non_ui_data_type_controller.h"
+#include "components/sync/driver/async_directory_type_controller.h"
namespace autofill {
class AutofillWebDataService;
@@ -17,25 +17,20 @@ namespace browser_sync {
// Controls syncing of either AUTOFILL_WALLET or AUTOFILL_WALLET_METADATA.
class AutofillWalletDataTypeController
- : public syncer::NonUIDataTypeController {
+ : public syncer::AsyncDirectoryTypeController {
public:
// |type| should be either AUTOFILL_WALLET or AUTOFILL_WALLET_METADATA.
// |dump_stack| is called when an unrecoverable error occurs.
AutofillWalletDataTypeController(
syncer::ModelType type,
- const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
+ scoped_refptr<base::SingleThreadTaskRunner> db_thread,
const base::Closure& dump_stack,
syncer::SyncClient* sync_client,
const scoped_refptr<autofill::AutofillWebDataService>& web_data_service);
~AutofillWalletDataTypeController() override;
- // NonUIDataTypeController implementation.
- syncer::ModelSafeGroup model_safe_group() const override;
-
private:
- // NonUIDataTypeController implementation.
- bool PostTaskOnBackendThread(const tracked_objects::Location& from_here,
- const base::Closure& task) override;
+ // AsyncDirectoryTypeController implementation.
bool StartModels() override;
void StopModels() override;
bool ReadyForStart() const override;
@@ -46,12 +41,6 @@ class AutofillWalletDataTypeController
// Returns true if the prefs are set such that wallet sync should be enabled.
bool IsEnabled();
- // A reference to the DB thread's task runner.
- const scoped_refptr<base::SingleThreadTaskRunner> db_thread_;
-
- // A pointer to the sync client.
- syncer::SyncClient* const sync_client_;
-
// Whether the database loaded callback has been registered.
bool callback_registered_;
diff --git a/chromium/components/autofill/core/browser/credit_card.cc b/chromium/components/autofill/core/browser/credit_card.cc
index 75a34c75a26..3b402eae9e8 100644
--- a/chromium/components/autofill/core/browser/credit_card.cc
+++ b/chromium/components/autofill/core/browser/credit_card.cc
@@ -39,12 +39,15 @@ using base::ASCIIToUTF16;
namespace autofill {
-const base::char16 kMidlineEllipsis[] = { 0x22ef, 0 };
+const base::char16 kMidlineEllipsis[] = { 0x0020, 0x0020,
+ 0x2022, 0x2006,
+ 0x2022, 0x2006,
+ 0x2022, 0x2006,
+ 0x2022, 0x2006, 0 };
namespace {
const base::char16 kCreditCardObfuscationSymbol = '*';
-const base::char16 kNonBreakingSpace[] = { 0x00a0, 0 };
bool ConvertYear(const base::string16& year, int* num) {
// If the |year| is empty, clear the stored value.
@@ -72,6 +75,8 @@ base::string16 TypeForFill(const std::string& type) {
return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_JCB);
if (type == kMasterCard)
return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_MASTERCARD);
+ if (type == kMirCard)
+ return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_MIR);
if (type == kUnionPay)
return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_UNION_PAY);
if (type == kVisaCard)
@@ -130,13 +135,15 @@ int CreditCard::IconResourceId(const std::string& type) {
if (type == kAmericanExpressCard)
return IDR_AUTOFILL_CC_AMEX;
if (type == kDinersCard)
- return IDR_AUTOFILL_CC_GENERIC;
+ return IDR_AUTOFILL_CC_DINERS;
if (type == kDiscoverCard)
return IDR_AUTOFILL_CC_DISCOVER;
if (type == kJCBCard)
- return IDR_AUTOFILL_CC_GENERIC;
+ return IDR_AUTOFILL_CC_JCB;
if (type == kMasterCard)
return IDR_AUTOFILL_CC_MASTERCARD;
+ if (type == kMirCard)
+ return IDR_AUTOFILL_CC_MIR;
if (type == kUnionPay)
return IDR_AUTOFILL_CC_GENERIC;
if (type == kVisaCard)
@@ -188,6 +195,9 @@ const char* CreditCard::GetCreditCardType(const base::string16& number) {
if (!base::StringToInt(number.substr(0, 2), &first_two_digits))
return kGenericCard;
+ if (first_two_digits == 22)
+ return kMirCard;
+
if (first_two_digits == 34 || first_two_digits == 37)
return kAmericanExpressCard;
@@ -492,8 +502,7 @@ base::string16 CreditCard::TypeAndLastFourDigits() const {
return type;
// TODO(estade): i18n?
- return type + base::string16(kNonBreakingSpace) +
- base::string16(kMidlineEllipsis) + digits;
+ return type + base::string16(kMidlineEllipsis) + digits;
}
base::string16 CreditCard::AbbreviatedExpirationDateForDisplay() const {
@@ -865,6 +874,7 @@ const char kDiscoverCard[] = "discoverCC";
const char kGenericCard[] = "genericCC";
const char kJCBCard[] = "jcbCC";
const char kMasterCard[] = "masterCardCC";
+const char kMirCard[] = "mirCC";
const char kUnionPay[] = "unionPayCC";
const char kVisaCard[] = "visaCC";
diff --git a/chromium/components/autofill/core/browser/credit_card.h b/chromium/components/autofill/core/browser/credit_card.h
index 1e4efd12f37..d0a8a6eee7e 100644
--- a/chromium/components/autofill/core/browser/credit_card.h
+++ b/chromium/components/autofill/core/browser/credit_card.h
@@ -266,6 +266,7 @@ extern const char kDiscoverCard[];
extern const char kGenericCard[];
extern const char kJCBCard[];
extern const char kMasterCard[];
+extern const char kMirCard[];
extern const char kUnionPay[];
extern const char kVisaCard[];
diff --git a/chromium/components/autofill/core/browser/credit_card_field_unittest.cc b/chromium/components/autofill/core/browser/credit_card_field_unittest.cc
index b6cf5757216..5b44a651d9c 100644
--- a/chromium/components/autofill/core/browser/credit_card_field_unittest.cc
+++ b/chromium/components/autofill/core/browser/credit_card_field_unittest.cc
@@ -5,10 +5,10 @@
#include "components/autofill/core/browser/credit_card_field.h"
#include <memory>
+#include <vector>
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/memory/scoped_vector.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_scanner.h"
@@ -25,14 +25,14 @@ class CreditCardFieldTest : public testing::Test {
~CreditCardFieldTest() override {}
protected:
- ScopedVector<AutofillField> list_;
+ std::vector<std::unique_ptr<AutofillField>> list_;
std::unique_ptr<const CreditCardField> field_;
FieldCandidatesMap field_candidates_map_;
// Parses the contents of |list_| as a form, and stores the result into
// |field_|.
void Parse() {
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
std::unique_ptr<FormField> field = CreditCardField::Parse(&scanner);
field_ = base::WrapUnique(static_cast<CreditCardField*>(field.release()));
}
@@ -40,7 +40,7 @@ class CreditCardFieldTest : public testing::Test {
void MultipleParses() {
std::unique_ptr<FormField> field;
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
while (!scanner.IsEnd()) {
field = CreditCardField::Parse(&scanner);
field_ = base::WrapUnique(static_cast<CreditCardField*>(field.release()));
@@ -68,7 +68,7 @@ TEST_F(CreditCardFieldTest, Empty) {
}
TEST_F(CreditCardFieldTest, NonParse) {
- list_.push_back(new AutofillField);
+ list_.push_back(base::MakeUnique<AutofillField>());
Parse();
ASSERT_EQ(nullptr, field_.get());
}
@@ -79,11 +79,13 @@ TEST_F(CreditCardFieldTest, ParseCreditCardNoNumber) {
field.label = ASCIIToUTF16("Exp Month");
field.name = ASCIIToUTF16("ccmonth");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("month1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("month1")));
field.label = ASCIIToUTF16("Exp Year");
field.name = ASCIIToUTF16("ccyear");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("year2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("year2")));
Parse();
ASSERT_EQ(nullptr, field_.get());
@@ -95,7 +97,8 @@ TEST_F(CreditCardFieldTest, ParseCreditCardNoDate) {
field.label = ASCIIToUTF16("Card Number");
field.name = ASCIIToUTF16("card_number");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("number1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("number1")));
Parse();
ASSERT_EQ(nullptr, field_.get());
@@ -107,15 +110,18 @@ TEST_F(CreditCardFieldTest, ParseMiniumCreditCard) {
field.label = ASCIIToUTF16("Card Number");
field.name = ASCIIToUTF16("card_number");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("number1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("number1")));
field.label = ASCIIToUTF16("Exp Month");
field.name = ASCIIToUTF16("ccmonth");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("month2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("month2")));
field.label = ASCIIToUTF16("Exp Year");
field.name = ASCIIToUTF16("ccyear");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("year3")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("year3")));
Parse();
ASSERT_NE(nullptr, field_.get());
@@ -140,30 +146,32 @@ TEST_F(CreditCardFieldTest, ParseFullCreditCard) {
field.label = ASCIIToUTF16("Name on Card");
field.name = ASCIIToUTF16("name_on_card");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name")));
+ list_.push_back(base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name")));
field.label = ASCIIToUTF16("Card Number");
field.name = ASCIIToUTF16("card_number");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("number")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("number")));
field.label = ASCIIToUTF16("Exp Month");
field.name = ASCIIToUTF16("ccmonth");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("month")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("month")));
field.label = ASCIIToUTF16("Exp Year");
field.name = ASCIIToUTF16("ccyear");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("year")));
+ list_.push_back(base::MakeUnique<AutofillField>(field, ASCIIToUTF16("year")));
field.label = ASCIIToUTF16("Verification");
field.name = ASCIIToUTF16("verification");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("cvc")));
+ list_.push_back(base::MakeUnique<AutofillField>(field, ASCIIToUTF16("cvc")));
field.form_control_type = "select-one";
field.label = ASCIIToUTF16("Card Type");
field.name = ASCIIToUTF16("card_type");
field.option_contents.push_back(ASCIIToUTF16("visa"));
field.option_values.push_back(ASCIIToUTF16("visa"));
- list_.push_back(new AutofillField(field, ASCIIToUTF16("type")));
+ list_.push_back(base::MakeUnique<AutofillField>(field, ASCIIToUTF16("type")));
Parse();
ASSERT_NE(nullptr, field_.get());
@@ -200,19 +208,23 @@ TEST_F(CreditCardFieldTest, ParseExpMonthYear) {
field.label = ASCIIToUTF16("Name on Card");
field.name = ASCIIToUTF16("name_on_card");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name1")));
field.label = ASCIIToUTF16("Card Number");
field.name = ASCIIToUTF16("card_number");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("number2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("number2")));
field.label = ASCIIToUTF16("ExpDate Month / Year");
field.name = ASCIIToUTF16("ExpDate");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("month3")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("month3")));
field.label = ASCIIToUTF16("ExpDate Month / Year");
field.name = ASCIIToUTF16("ExpDate");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("year4")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("year4")));
Parse();
ASSERT_NE(nullptr, field_.get());
@@ -241,19 +253,23 @@ TEST_F(CreditCardFieldTest, ParseExpMonthYear2) {
field.label = ASCIIToUTF16("Name on Card");
field.name = ASCIIToUTF16("name_on_card");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name1")));
field.label = ASCIIToUTF16("Card Number");
field.name = ASCIIToUTF16("card_number");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("number2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("number2")));
field.label = ASCIIToUTF16("Expiration date Month / Year");
field.name = ASCIIToUTF16("ExpDate");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("month3")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("month3")));
field.label = ASCIIToUTF16("Expiration date Month / Year");
field.name = ASCIIToUTF16("ExpDate");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("year4")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("year4")));
Parse();
ASSERT_NE(nullptr, field_.get());
@@ -343,18 +359,21 @@ TEST_F(CreditCardFieldTest, ParseExpField) {
field.label = ASCIIToUTF16("Name on Card");
field.name = ASCIIToUTF16("name_on_card");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name1")));
field.label = ASCIIToUTF16("Card Number");
field.name = ASCIIToUTF16("card_number");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("num2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("num2")));
field.label = ASCIIToUTF16(test_case.label);
if (test_case.max_length != 0) {
field.max_length = test_case.max_length;
}
field.name = ASCIIToUTF16("cc_exp");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("exp3")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("exp3")));
Parse();
@@ -397,7 +416,8 @@ TEST_F(CreditCardFieldTest, ParseCreditCardHolderNameWithCCFullName) {
field.label = ASCIIToUTF16("Name");
field.name = ASCIIToUTF16("ccfullname");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name1")));
Parse();
ASSERT_NE(nullptr, field_.get());
@@ -415,12 +435,14 @@ TEST_F(CreditCardFieldTest, ParseMonthControl) {
field.form_control_type = "text";
field.label = ASCIIToUTF16("Card number:");
field.name = ASCIIToUTF16("ccnumber");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("number1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("number1")));
field.form_control_type = "month";
field.label = ASCIIToUTF16("Expiration date:");
field.name = ASCIIToUTF16("ccexp");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("date2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("date2")));
Parse();
ASSERT_NE(nullptr, field_.get());
@@ -443,15 +465,17 @@ TEST_F(CreditCardFieldTest, ParseCreditCardExpYear_2DigitMaxLength) {
field.label = ASCIIToUTF16("Card Number");
field.name = ASCIIToUTF16("card_number");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("number")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("number")));
field.label = ASCIIToUTF16("Expiration Date");
field.name = ASCIIToUTF16("ccmonth");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("month")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("month")));
field.name = ASCIIToUTF16("ccyear");
field.max_length = 2;
- list_.push_back(new AutofillField(field, ASCIIToUTF16("year")));
+ list_.push_back(base::MakeUnique<AutofillField>(field, ASCIIToUTF16("year")));
Parse();
ASSERT_NE(nullptr, field_.get());
@@ -477,17 +501,20 @@ TEST_F(CreditCardFieldTest, ParseCreditCardNumberWithSplit) {
field.label = ASCIIToUTF16("Card Number");
field.name = ASCIIToUTF16("card_number_q1");
field.max_length = 4;
- list_.push_back(new AutofillField(field, ASCIIToUTF16("number1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("number1")));
field.label = ASCIIToUTF16("Card Number");
field.name = ASCIIToUTF16("card_number_q2");
field.max_length = 4;
- list_.push_back(new AutofillField(field, ASCIIToUTF16("number2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("number2")));
field.label = ASCIIToUTF16("Card Number");
field.name = ASCIIToUTF16("card_number_q3");
field.max_length = 4;
- list_.push_back(new AutofillField(field, ASCIIToUTF16("number3")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("number3")));
// For last credit card number input field it simply ignores the |max_length|
// attribute. So even having a very big number, does not conside it an invalid
@@ -495,15 +522,18 @@ TEST_F(CreditCardFieldTest, ParseCreditCardNumberWithSplit) {
field.label = ASCIIToUTF16("Card Number");
field.name = ASCIIToUTF16("card_number_q4");
field.max_length = 20;
- list_.push_back(new AutofillField(field, ASCIIToUTF16("number4")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("number4")));
field.label = ASCIIToUTF16("Exp Month");
field.name = ASCIIToUTF16("ccmonth");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("month5")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("month5")));
field.label = ASCIIToUTF16("Exp Year");
field.name = ASCIIToUTF16("ccyear");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("year6")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("year6")));
Parse();
ASSERT_NE(nullptr, field_.get());
@@ -549,23 +579,28 @@ TEST_F(CreditCardFieldTest, ParseMultipleCreditCardNumbers) {
field.label = ASCIIToUTF16("Name on Card");
field.name = ASCIIToUTF16("name_on_card");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name1")));
field.label = ASCIIToUTF16("Card Number");
field.name = ASCIIToUTF16("card_number");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("number2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("number2")));
field.label = ASCIIToUTF16("Confirm Card Number");
field.name = ASCIIToUTF16("confirm_card_number");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("number3")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("number3")));
field.label = ASCIIToUTF16("Exp Month");
field.name = ASCIIToUTF16("ccmonth");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("month4")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("month4")));
field.label = ASCIIToUTF16("Exp Year");
field.name = ASCIIToUTF16("ccyear");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("year5")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("year5")));
Parse();
ASSERT_NE(nullptr, field_.get());
@@ -599,23 +634,28 @@ TEST_F(CreditCardFieldTest, ParseFirstAndLastNames) {
field.label = ASCIIToUTF16("First Name on Card");
field.name = ASCIIToUTF16("cc-fname");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name1")));
field.label = ASCIIToUTF16("Last Name");
field.name = ASCIIToUTF16("cc-lname");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name2")));
field.label = ASCIIToUTF16("Card Number");
field.name = ASCIIToUTF16("card_number");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("number3")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("number3")));
field.label = ASCIIToUTF16("Exp Month");
field.name = ASCIIToUTF16("ccmonth");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("month4")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("month4")));
field.label = ASCIIToUTF16("Exp Year");
field.name = ASCIIToUTF16("ccyear");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("year5")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("year5")));
Parse();
ASSERT_NE(nullptr, field_.get());
@@ -649,27 +689,29 @@ TEST_F(CreditCardFieldTest, ParseConsecutiveCvc) {
field.label = ASCIIToUTF16("Name on Card");
field.name = ASCIIToUTF16("name_on_card");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name")));
+ list_.push_back(base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name")));
field.label = ASCIIToUTF16("Card Number");
field.name = ASCIIToUTF16("card_number");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("number")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("number")));
field.label = ASCIIToUTF16("Exp Month");
field.name = ASCIIToUTF16("ccmonth");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("month")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("month")));
field.label = ASCIIToUTF16("Exp Year");
field.name = ASCIIToUTF16("ccyear");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("year")));
+ list_.push_back(base::MakeUnique<AutofillField>(field, ASCIIToUTF16("year")));
field.label = ASCIIToUTF16("Verification");
field.name = ASCIIToUTF16("verification");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("cvc")));
+ list_.push_back(base::MakeUnique<AutofillField>(field, ASCIIToUTF16("cvc")));
field.label = ASCIIToUTF16("Verification");
field.name = ASCIIToUTF16("verification");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("cvc2")));
+ list_.push_back(base::MakeUnique<AutofillField>(field, ASCIIToUTF16("cvc2")));
MultipleParses();
@@ -705,31 +747,34 @@ TEST_F(CreditCardFieldTest, ParseNonConsecutiveCvc) {
field.label = ASCIIToUTF16("Name on Card");
field.name = ASCIIToUTF16("name_on_card");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name")));
+ list_.push_back(base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name")));
field.label = ASCIIToUTF16("Card Number");
field.name = ASCIIToUTF16("card_number");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("number")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("number")));
field.label = ASCIIToUTF16("Exp Month");
field.name = ASCIIToUTF16("ccmonth");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("month")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("month")));
field.label = ASCIIToUTF16("Exp Year");
field.name = ASCIIToUTF16("ccyear");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("year")));
+ list_.push_back(base::MakeUnique<AutofillField>(field, ASCIIToUTF16("year")));
field.label = ASCIIToUTF16("Verification");
field.name = ASCIIToUTF16("verification");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("cvc")));
+ list_.push_back(base::MakeUnique<AutofillField>(field, ASCIIToUTF16("cvc")));
field.label = ASCIIToUTF16("Unknown");
field.name = ASCIIToUTF16("unknown");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("unknown")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("unknown")));
field.label = ASCIIToUTF16("Verification");
field.name = ASCIIToUTF16("verification");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("cvc2")));
+ list_.push_back(base::MakeUnique<AutofillField>(field, ASCIIToUTF16("cvc2")));
MultipleParses();
diff --git a/chromium/components/autofill/core/browser/credit_card_unittest.cc b/chromium/components/autofill/core/browser/credit_card_unittest.cc
index 3f481ee956d..de26d8e56d3 100644
--- a/chromium/components/autofill/core/browser/credit_card_unittest.cc
+++ b/chromium/components/autofill/core/browser/credit_card_unittest.cc
@@ -59,6 +59,13 @@ const char* const kInvalidNumbers[] = {
"3056 9309 0259 04aa", /* non-digit characters */
};
+const std::string kUTF8MidlineEllipsis =
+ " "
+ "\xE2\x80\xA2\xE2\x80\x86"
+ "\xE2\x80\xA2\xE2\x80\x86"
+ "\xE2\x80\xA2\xE2\x80\x86"
+ "\xE2\x80\xA2\xE2\x80\x86";
+
} // namespace
// Tests credit card summary string generation. This test simulates a variety
@@ -93,14 +100,10 @@ TEST(CreditCardTest, PreviewSummaryAndTypeAndLastFourDigitsStrings) {
test::SetCreditCardInfo(
&credit_card2, "John Dillinger", "5105 1051 0510 5100", "", "2010");
base::string16 summary2 = credit_card2.Label();
- EXPECT_EQ(UTF8ToUTF16(
- "MasterCard\xC2\xA0\xE2\x8B\xAF"
- "5100"),
+ EXPECT_EQ(UTF8ToUTF16("MasterCard" + kUTF8MidlineEllipsis + "5100"),
summary2);
base::string16 obfuscated2 = credit_card2.TypeAndLastFourDigits();
- EXPECT_EQ(UTF8ToUTF16(
- "MasterCard\xC2\xA0\xE2\x8B\xAF"
- "5100"),
+ EXPECT_EQ(UTF8ToUTF16("MasterCard" + kUTF8MidlineEllipsis + "5100"),
obfuscated2);
// Case 3: No year.
@@ -108,14 +111,10 @@ TEST(CreditCardTest, PreviewSummaryAndTypeAndLastFourDigitsStrings) {
test::SetCreditCardInfo(
&credit_card3, "John Dillinger", "5105 1051 0510 5100", "01", "");
base::string16 summary3 = credit_card3.Label();
- EXPECT_EQ(UTF8ToUTF16(
- "MasterCard\xC2\xA0\xE2\x8B\xAF"
- "5100"),
+ EXPECT_EQ(UTF8ToUTF16("MasterCard" + kUTF8MidlineEllipsis + "5100"),
summary3);
base::string16 obfuscated3 = credit_card3.TypeAndLastFourDigits();
- EXPECT_EQ(UTF8ToUTF16(
- "MasterCard\xC2\xA0\xE2\x8B\xAF"
- "5100"),
+ EXPECT_EQ(UTF8ToUTF16("MasterCard" + kUTF8MidlineEllipsis + "5100"),
obfuscated3);
// Case 4: Have everything.
@@ -123,14 +122,10 @@ TEST(CreditCardTest, PreviewSummaryAndTypeAndLastFourDigitsStrings) {
test::SetCreditCardInfo(
&credit_card4, "John Dillinger", "5105 1051 0510 5100", "01", "2010");
base::string16 summary4 = credit_card4.Label();
- EXPECT_EQ(UTF8ToUTF16(
- "MasterCard\xC2\xA0\xE2\x8B\xAF"
- "5100, 01/2010"),
+ EXPECT_EQ(UTF8ToUTF16("MasterCard" + kUTF8MidlineEllipsis + "5100, 01/2010"),
summary4);
base::string16 obfuscated4 = credit_card4.TypeAndLastFourDigits();
- EXPECT_EQ(UTF8ToUTF16(
- "MasterCard\xC2\xA0\xE2\x8B\xAF"
- "5100"),
+ EXPECT_EQ(UTF8ToUTF16("MasterCard" + kUTF8MidlineEllipsis + "5100"),
obfuscated4);
// Case 5: Very long credit card
@@ -140,14 +135,10 @@ TEST(CreditCardTest, PreviewSummaryAndTypeAndLastFourDigitsStrings) {
"John Dillinger",
"0123456789 0123456789 0123456789 5105 1051 0510 5100", "01", "2010");
base::string16 summary5 = credit_card5.Label();
- EXPECT_EQ(UTF8ToUTF16(
- "Card\xC2\xA0\xE2\x8B\xAF"
- "5100, 01/2010"),
+ EXPECT_EQ(UTF8ToUTF16("Card" + kUTF8MidlineEllipsis + "5100, 01/2010"),
summary5);
base::string16 obfuscated5 = credit_card5.TypeAndLastFourDigits();
- EXPECT_EQ(UTF8ToUTF16(
- "Card\xC2\xA0\xE2\x8B\xAF"
- "5100"),
+ EXPECT_EQ(UTF8ToUTF16("Card" + kUTF8MidlineEllipsis + "5100"),
obfuscated5);
}
@@ -378,14 +369,16 @@ TEST(CreditCardTest, Compare) {
TEST(CreditCardTest, IconResourceId) {
EXPECT_EQ(IDR_AUTOFILL_CC_AMEX,
CreditCard::IconResourceId(kAmericanExpressCard));
- EXPECT_EQ(IDR_AUTOFILL_CC_GENERIC,
+ EXPECT_EQ(IDR_AUTOFILL_CC_DINERS,
CreditCard::IconResourceId(kDinersCard));
EXPECT_EQ(IDR_AUTOFILL_CC_DISCOVER,
CreditCard::IconResourceId(kDiscoverCard));
- EXPECT_EQ(IDR_AUTOFILL_CC_GENERIC,
+ EXPECT_EQ(IDR_AUTOFILL_CC_JCB,
CreditCard::IconResourceId(kJCBCard));
EXPECT_EQ(IDR_AUTOFILL_CC_MASTERCARD,
CreditCard::IconResourceId(kMasterCard));
+ EXPECT_EQ(IDR_AUTOFILL_CC_MIR,
+ CreditCard::IconResourceId(kMirCard));
EXPECT_EQ(IDR_AUTOFILL_CC_VISA,
CreditCard::IconResourceId(kVisaCard));
}
@@ -659,6 +652,9 @@ TEST(CreditCardTest, GetCreditCardType) {
{ "6247130048162403", kUnionPay, true },
{ "6247130048162403", kUnionPay, true },
{ "622384452162063648", kUnionPay, true },
+ { "2204883716636153", kMirCard, true },
+ { "2200111234567898", kMirCard, true },
+ { "2200481349288130", kMirCard, true },
// Empty string
{ std::string(), kGenericCard, false },
@@ -670,13 +666,16 @@ TEST(CreditCardTest, GetCreditCardType) {
// Fails Luhn check.
{ "4111111111111112", kVisaCard, false },
{ "6247130048162413", kUnionPay, false },
+ { "2204883716636154", kMirCard, false },
// Invalid length.
{ "3434343434343434", kAmericanExpressCard, false },
{ "411111111111116", kVisaCard, false },
+ { "220011123456783", kMirCard, false },
// Issuer Identification Numbers (IINs) that Chrome recognizes.
{ "4", kVisaCard, false },
+ { "22", kMirCard, false },
{ "34", kAmericanExpressCard, false },
{ "37", kAmericanExpressCard, false },
{ "300", kDinersCard, false },
@@ -708,6 +707,7 @@ TEST(CreditCardTest, GetCreditCardType) {
{ "62", kUnionPay, false },
// Not enough data to determine an IIN uniquely.
+ { "2", kGenericCard, false },
{ "3", kGenericCard, false },
{ "30", kGenericCard, false },
{ "309", kGenericCard, false },
@@ -721,7 +721,6 @@ TEST(CreditCardTest, GetCreditCardType) {
// Unknown IINs.
{ "0", kGenericCard, false },
{ "1", kGenericCard, false },
- { "2", kGenericCard, false },
{ "306", kGenericCard, false },
{ "307", kGenericCard, false },
{ "308", kGenericCard, false },
diff --git a/chromium/components/autofill/core/browser/field_types.h b/chromium/components/autofill/core/browser/field_types.h
index 7dee4279e2e..6c2aa807752 100644
--- a/chromium/components/autofill/core/browser/field_types.h
+++ b/chromium/components/autofill/core/browser/field_types.h
@@ -159,9 +159,13 @@ enum ServerFieldType {
// for local heuristics.
PROBABLY_ACCOUNT_CREATION_PASSWORD = 94,
+ // The confirmation password field in account creation or change password
+ // forms.
+ CONFIRMATION_PASSWORD = 95,
+
// No new types can be added without a corresponding change to the Autofill
// server.
- MAX_VALID_FIELD_TYPE = 95,
+ MAX_VALID_FIELD_TYPE = 96,
};
// The list of all HTML autocomplete field type hints supported by Chrome.
diff --git a/chromium/components/autofill/core/browser/form_field.cc b/chromium/components/autofill/core/browser/form_field.cc
index 3d31c0bd59f..a1997ebbb36 100644
--- a/chromium/components/autofill/core/browser/form_field.cc
+++ b/chromium/components/autofill/core/browser/form_field.cc
@@ -27,19 +27,6 @@
#include "components/autofill/core/common/autofill_util.h"
namespace autofill {
-namespace {
-
-bool ShouldBeProcessed(const AutofillField* field) {
- // Ignore checkable fields as they interfere with parsers assuming context.
- // Eg., while parsing address, "Is PO box" checkbox after ADDRESS_LINE1
- // interferes with correctly understanding ADDRESS_LINE2.
- // Ignore fields marked as presentational. See
- // http://www.w3.org/TR/wai-aria/roles#presentation
- return !(IsCheckable(field->check_status) ||
- field->role == FormFieldData::ROLE_ATTRIBUTE_PRESENTATION);
-}
-
-} // namespace
// There's an implicit precedence determined by the values assigned here. Email
// is currently the most important followed by Phone, Address, Credit Card and
@@ -52,12 +39,22 @@ const float FormField::kBaseNameParserScore = 1.0f;
// static
FieldCandidatesMap FormField::ParseFormFields(
- const std::vector<AutofillField*>& fields,
+ const std::vector<std::unique_ptr<AutofillField>>& fields,
bool is_form_tag) {
// Set up a working copy of the fields to be processed.
std::vector<AutofillField*> processed_fields;
- std::copy_if(fields.begin(), fields.end(),
- std::back_inserter(processed_fields), ShouldBeProcessed);
+ for (const auto& field : fields) {
+ // Ignore checkable fields as they interfere with parsers assuming context.
+ // Eg., while parsing address, "Is PO box" checkbox after ADDRESS_LINE1
+ // interferes with correctly understanding ADDRESS_LINE2.
+ // Ignore fields marked as presentational. See
+ // http://www.w3.org/TR/wai-aria/roles#presentation
+ if (IsCheckable(field->check_status) ||
+ field->role == FormFieldData::ROLE_ATTRIBUTE_PRESENTATION) {
+ continue;
+ }
+ processed_fields.push_back(field.get());
+ }
FieldCandidatesMap field_candidates;
@@ -175,7 +172,7 @@ void FormField::ParseFormFieldsPass(ParseFunction parse,
FieldCandidatesMap* field_candidates) {
AutofillScanner scanner(fields);
while (!scanner.IsEnd()) {
- std::unique_ptr<FormField> form_field(parse(&scanner));
+ std::unique_ptr<FormField> form_field = parse(&scanner);
if (form_field == nullptr) {
scanner.Advance();
} else {
diff --git a/chromium/components/autofill/core/browser/form_field.h b/chromium/components/autofill/core/browser/form_field.h
index 2d7dcd7dbf4..3ec73b4cf3a 100644
--- a/chromium/components/autofill/core/browser/form_field.h
+++ b/chromium/components/autofill/core/browser/form_field.h
@@ -30,7 +30,7 @@ class FormField {
// Each field has a derived unique name that is used as the key into the
// returned FieldCandidatesMap.
static FieldCandidatesMap ParseFormFields(
- const std::vector<AutofillField*>& fields,
+ const std::vector<std::unique_ptr<AutofillField>>& fields,
bool is_form_tag);
protected:
diff --git a/chromium/components/autofill/core/browser/form_field_unittest.cc b/chromium/components/autofill/core/browser/form_field_unittest.cc
index 71e5e12d476..8962409833c 100644
--- a/chromium/components/autofill/core/browser/form_field_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_field_unittest.cc
@@ -2,7 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/memory/scoped_vector.h"
+#include <memory>
+#include <vector>
+
+#include "base/memory/ptr_util.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_field.h"
@@ -124,32 +127,36 @@ TEST(FormFieldTest, Match) {
// Test that we ignore checkable elements.
TEST(FormFieldTest, ParseFormFields) {
- ScopedVector<AutofillField> fields;
+ std::vector<std::unique_ptr<AutofillField>> fields;
FormFieldData field_data;
field_data.form_control_type = "text";
field_data.label = ASCIIToUTF16("Address line1");
- fields.push_back(new AutofillField(field_data, field_data.label));
+ fields.push_back(
+ base::MakeUnique<AutofillField>(field_data, field_data.label));
field_data.check_status = FormFieldData::CHECKABLE_BUT_UNCHECKED;
field_data.label = ASCIIToUTF16("Is PO Box");
- fields.push_back(new AutofillField(field_data, field_data.label));
+ fields.push_back(
+ base::MakeUnique<AutofillField>(field_data, field_data.label));
// reset |is_checkable| to false.
field_data.check_status = FormFieldData::NOT_CHECKABLE;
field_data.label = ASCIIToUTF16("Address line2");
- fields.push_back(new AutofillField(field_data, field_data.label));
+ fields.push_back(
+ base::MakeUnique<AutofillField>(field_data, field_data.label));
// Does not parse since there are only 2 recognized fields.
- ASSERT_TRUE(FormField::ParseFormFields(fields.get(), true).empty());
+ ASSERT_TRUE(FormField::ParseFormFields(fields, true).empty());
field_data.label = ASCIIToUTF16("City");
- fields.push_back(new AutofillField(field_data, field_data.label));
+ fields.push_back(
+ base::MakeUnique<AutofillField>(field_data, field_data.label));
// Checkable element shouldn't interfere with inference of Address line2.
const FieldCandidatesMap field_candidates_map =
- FormField::ParseFormFields(fields.get(), true);
+ FormField::ParseFormFields(fields, true);
ASSERT_EQ(3U, field_candidates_map.size());
EXPECT_EQ(ADDRESS_HOME_LINE1,
@@ -170,11 +177,11 @@ TEST(FormFieldTest, ParseFormFieldsImmutableForm) {
field_data.form_control_type = "text";
field_data.name = ASCIIToUTF16("business_email_address");
- ScopedVector<AutofillField> fields;
- fields.push_back(new AutofillField(field_data, unique_name));
+ std::vector<std::unique_ptr<AutofillField>> fields;
+ fields.push_back(base::MakeUnique<AutofillField>(field_data, unique_name));
const FieldCandidatesMap field_candidates_map =
- FormField::ParseFormFields(fields.get(), true);
+ FormField::ParseFormFields(fields, true);
// The input form should not be modified.
EXPECT_EQ(1U, fields.size());
diff --git a/chromium/components/autofill/core/browser/form_structure.cc b/chromium/components/autofill/core/browser/form_structure.cc
index cf4ae5c7b15..278cc7b6de3 100644
--- a/chromium/components/autofill/core/browser/form_structure.cc
+++ b/chromium/components/autofill/core/browser/form_structure.cc
@@ -13,6 +13,7 @@
#include "base/command_line.h"
#include "base/i18n/case_conversion.h"
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial.h"
#include "base/sha1.h"
#include "base/strings/string_number_conversions.h"
@@ -33,8 +34,8 @@
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/form_field_data_predictions.h"
#include "components/autofill/core/common/signatures_util.h"
-#include "components/rappor/rappor_service.h"
-#include "components/rappor/rappor_utils.h"
+#include "components/rappor/public/rappor_utils.h"
+#include "components/rappor/rappor_service_impl.h"
namespace autofill {
namespace {
@@ -321,7 +322,7 @@ FormStructure::FormStructure(const FormData& form)
base::string16 unique_name =
field.name + base::ASCIIToUTF16("_") +
base::SizeTToString16(++unique_names[field.name]);
- fields_.push_back(new AutofillField(field, unique_name));
+ fields_.push_back(base::MakeUnique<AutofillField>(field, unique_name));
}
form_signature_ = autofill::CalculateFormSignature(form);
@@ -345,8 +346,8 @@ void FormStructure::DetermineHeuristicTypes() {
if (active_field_count() >= kRequiredFieldsForPredictionRoutines &&
(is_form_tag_ || is_formless_checkout_)) {
const FieldCandidatesMap field_type_map =
- FormField::ParseFormFields(fields_.get(), is_form_tag_);
- for (AutofillField* field : fields_) {
+ FormField::ParseFormFields(fields_, is_form_tag_);
+ for (const auto& field : fields_) {
const auto iter = field_type_map.find(field->unique_name());
if (iter != field_type_map.end())
field->set_heuristic_type(iter->second.BestHeuristicType());
@@ -379,7 +380,7 @@ bool FormStructure::EncodeUploadRequest(
// Verify that |available_field_types| agrees with the possible field types we
// are uploading.
- for (const AutofillField* field : *this) {
+ for (const auto& field : *this) {
for (const auto& type : field->possible_types()) {
DCHECK(type == UNKNOWN_TYPE || type == EMPTY_TYPE ||
available_field_types.count(type));
@@ -442,9 +443,10 @@ bool FormStructure::EncodeQueryRequest(
}
// static
-void FormStructure::ParseQueryResponse(std::string payload,
- const std::vector<FormStructure*>& forms,
- rappor::RapporService* rappor_service) {
+void FormStructure::ParseQueryResponse(
+ std::string payload,
+ const std::vector<FormStructure*>& forms,
+ rappor::RapporServiceImpl* rappor_service) {
AutofillMetrics::LogServerQueryMetric(
AutofillMetrics::QUERY_RESPONSE_RECEIVED);
@@ -467,7 +469,7 @@ void FormStructure::ParseQueryResponse(std::string payload,
response.upload_required() ? UPLOAD_REQUIRED : UPLOAD_NOT_REQUIRED;
bool query_response_has_no_server_data = true;
- for (AutofillField* field : form->fields_) {
+ for (auto& field : form->fields_) {
if (form->ShouldSkipField(*field))
continue;
@@ -532,7 +534,7 @@ std::vector<FormDataPredictions> FormStructure::GetFieldTypePredictions(
form.data.is_form_tag = form_structure->is_form_tag_;
form.signature = form_structure->FormSignatureAsStr();
- for (const AutofillField* field : form_structure->fields_) {
+ for (const auto& field : form_structure->fields_) {
form.data.fields.push_back(FormFieldData(*field));
FormFieldDataPredictions annotated_field;
@@ -573,7 +575,7 @@ bool FormStructure::IsAutofillable() const {
bool FormStructure::IsCompleteCreditCardForm() const {
bool found_cc_number = false;
bool found_cc_expiration = false;
- for (const AutofillField* field : fields_) {
+ for (const auto& field : fields_) {
ServerFieldType type = field->Type().GetStorableType();
if (!found_cc_expiration && IsCreditCardExpirationType(type)) {
found_cc_expiration = true;
@@ -588,7 +590,7 @@ bool FormStructure::IsCompleteCreditCardForm() const {
void FormStructure::UpdateAutofillCount() {
autofill_count_ = 0;
- for (const AutofillField* field : *this) {
+ for (const auto& field : *this) {
if (field && field->IsFieldFillable())
++autofill_count_;
}
@@ -609,7 +611,7 @@ bool FormStructure::ShouldBeParsed() const {
return false;
bool has_text_field = false;
- for (const AutofillField* it : *this) {
+ for (const auto& it : *this) {
has_text_field |= it->form_control_type != "select-one";
}
@@ -626,11 +628,11 @@ void FormStructure::UpdateFromCache(const FormStructure& cached_form) {
// Map from field signatures to cached fields.
std::map<std::string, const AutofillField*> cached_fields;
for (size_t i = 0; i < cached_form.field_count(); ++i) {
- const AutofillField* field = cached_form.field(i);
+ const auto& field = cached_form.field(i);
cached_fields[field->FieldSignatureAsStr()] = field;
}
- for (AutofillField* field : *this) {
+ for (auto& field : *this) {
std::map<std::string, const AutofillField*>::const_iterator cached_field =
cached_fields.find(field->FieldSignatureAsStr());
if (cached_field != cached_fields.end()) {
@@ -669,7 +671,7 @@ void FormStructure::UpdateFromCache(const FormStructure& cached_form) {
void FormStructure::LogQualityMetrics(const base::TimeTicks& load_time,
const base::TimeTicks& interaction_time,
const base::TimeTicks& submission_time,
- rappor::RapporService* rappor_service,
+ rappor::RapporServiceImpl* rappor_service,
bool did_show_suggestions,
bool observed_submission) const {
size_t num_detected_field_types = 0;
@@ -679,7 +681,7 @@ void FormStructure::LogQualityMetrics(const base::TimeTicks& load_time,
bool did_autofill_all_possible_fields = true;
bool did_autofill_some_possible_fields = false;
for (size_t i = 0; i < field_count(); ++i) {
- const AutofillField* field = this->field(i);
+ const auto& field = this->field(i);
// No further logging for password fields. Those are primarily related to a
// different feature code path, and so make more sense to track outside of
@@ -845,7 +847,7 @@ void FormStructure::LogQualityMetrics(const base::TimeTicks& load_time,
}
void FormStructure::LogQualityMetricsBasedOnAutocomplete() const {
- for (const AutofillField* field : fields_) {
+ for (const auto& field : fields_) {
if (field->html_type() != HTML_TYPE_UNSPECIFIED &&
field->html_type() != HTML_TYPE_UNRECOGNIZED) {
// The type inferred by the autocomplete attribute.
@@ -886,7 +888,7 @@ void FormStructure::ParseFieldTypesFromAutocompleteAttributes() {
has_author_specified_types_ = false;
has_author_specified_sections_ = false;
- for (AutofillField* field : fields_) {
+ for (const auto& field : fields_) {
// To prevent potential section name collisions, add a default suffix for
// other fields. Without this, 'autocomplete' attribute values
// "section--shipping street-address" and "shipping street-address" would be
@@ -1006,7 +1008,7 @@ bool FormStructure::FillFields(
std::set<base::string16> FormStructure::PossibleValues(ServerFieldType type) {
std::set<base::string16> values;
AutofillType target_type(type);
- for (const AutofillField* field : fields_) {
+ for (const auto& field : fields_) {
if (field->Type().GetStorableType() != target_type.GetStorableType() ||
field->Type().group() != target_type.group()) {
continue;
@@ -1034,7 +1036,7 @@ std::set<base::string16> FormStructure::PossibleValues(ServerFieldType type) {
base::string16 FormStructure::GetUniqueValue(HtmlFieldType type) const {
base::string16 value;
- for (const AutofillField* field : fields_) {
+ for (const auto& field : fields_) {
if (field->html_type() != type)
continue;
@@ -1056,7 +1058,7 @@ const AutofillField* FormStructure::field(size_t index) const {
return NULL;
}
- return fields_[index];
+ return fields_[index].get();
}
AutofillField* FormStructure::field(size_t index) {
@@ -1107,7 +1109,7 @@ void FormStructure::EncodeFormForQuery(
DCHECK(!IsMalformed());
query_form->set_signature(form_signature());
- for (const AutofillField* field : fields_) {
+ for (const auto& field : fields_) {
if (ShouldSkipField(*field))
continue;
@@ -1128,7 +1130,7 @@ void FormStructure::EncodeFormForQuery(
void FormStructure::EncodeFormForUpload(AutofillUploadContents* upload) const {
DCHECK(!IsMalformed());
- for (const AutofillField* field : fields_) {
+ for (const auto& field : fields_) {
// Don't upload checkable fields.
if (IsCheckable(field->check_status))
continue;
@@ -1196,7 +1198,7 @@ void FormStructure::IdentifySections(bool has_author_specified_sections) {
std::set<ServerFieldType> seen_types;
ServerFieldType previous_type = UNKNOWN_TYPE;
- for (AutofillField* field : fields_) {
+ for (const auto& field : fields_) {
const ServerFieldType current_type = field->Type().GetStorableType();
bool already_saw_current_type = seen_types.count(current_type) > 0;
@@ -1250,7 +1252,7 @@ void FormStructure::IdentifySections(bool has_author_specified_sections) {
// Ensure that credit card and address fields are in separate sections.
// This simplifies the section-aware logic in autofill_manager.cc.
- for (AutofillField* field : fields_) {
+ for (const auto& field : fields_) {
FieldTypeGroup field_type_group = field->Type().group();
if (field_type_group == CREDIT_CARD)
field->set_section(field->section() + "-cc");
@@ -1272,7 +1274,7 @@ void FormStructure::ProcessExtractedFields() {
// Find the longest common prefix within all the field names.
std::vector<base::string16> names;
names.reserve(field_count());
- for (const AutofillField* field : *this)
+ for (const auto& field : *this)
names.push_back(field->name);
const base::string16 longest_prefix = FindLongestCommonPrefix(names);
@@ -1280,7 +1282,7 @@ void FormStructure::ProcessExtractedFields() {
return;
// The name without the prefix will be used for heuristics parsing.
- for (AutofillField* field : *this) {
+ for (auto& field : *this) {
if (field->name.size() > longest_prefix.size()) {
field->set_parseable_name(
field->name.substr(longest_prefix.size(), field->name.size()));
diff --git a/chromium/components/autofill/core/browser/form_structure.h b/chromium/components/autofill/core/browser/form_structure.h
index e359a8f1f93..09c4ee13b89 100644
--- a/chromium/components/autofill/core/browser/form_structure.h
+++ b/chromium/components/autofill/core/browser/form_structure.h
@@ -7,6 +7,7 @@
#include <stddef.h>
+#include <memory>
#include <set>
#include <string>
#include <vector>
@@ -14,7 +15,6 @@
#include "base/callback.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/memory/scoped_vector.h"
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
#include "components/autofill/core/browser/autofill_field.h"
@@ -23,8 +23,6 @@
#include "components/autofill/core/browser/proto/server.pb.h"
#include "url/gurl.h"
-class XmlWriter;
-
enum UploadRequired {
UPLOAD_NOT_REQUIRED,
UPLOAD_REQUIRED,
@@ -35,12 +33,8 @@ namespace base {
class TimeTicks;
}
-namespace buzz {
-class XmlElement;
-}
-
namespace rappor {
-class RapporService;
+class RapporServiceImpl;
}
namespace autofill {
@@ -81,7 +75,7 @@ class FormStructure {
// |rappor_service| may be null.
static void ParseQueryResponse(std::string response,
const std::vector<FormStructure*>& forms,
- rappor::RapporService* rappor_service);
+ rappor::RapporServiceImpl* rappor_service);
// Returns predictions using the details from the given |form_structures| and
// their fields' predicted types.
@@ -135,7 +129,7 @@ class FormStructure {
void LogQualityMetrics(const base::TimeTicks& load_time,
const base::TimeTicks& interaction_time,
const base::TimeTicks& submission_time,
- rappor::RapporService* rappor_service,
+ rappor::RapporServiceImpl* rappor_service,
bool did_show_suggestions,
bool observed_submission) const;
@@ -194,10 +188,10 @@ class FormStructure {
size_t autofill_count() const { return autofill_count_; }
// Used for iterating over the fields.
- std::vector<AutofillField*>::const_iterator begin() const {
+ std::vector<std::unique_ptr<AutofillField>>::const_iterator begin() const {
return fields_.begin();
}
- std::vector<AutofillField*>::const_iterator end() const {
+ std::vector<std::unique_ptr<AutofillField>>::const_iterator end() const {
return fields_.end();
}
@@ -280,7 +274,7 @@ class FormStructure {
size_t autofill_count_;
// A vector of all the input fields in the form.
- ScopedVector<AutofillField> fields_;
+ std::vector<std::unique_ptr<AutofillField>> fields_;
// The number of fields that are part of the form signature and that are
// included in queries to the Autofill server.
diff --git a/chromium/components/autofill/core/browser/legal_message_line.h b/chromium/components/autofill/core/browser/legal_message_line.h
index 681173c9d58..50955f9569c 100644
--- a/chromium/components/autofill/core/browser/legal_message_line.h
+++ b/chromium/components/autofill/core/browser/legal_message_line.h
@@ -63,9 +63,7 @@ class LegalMessageLine {
// expand correctly.
// 3. "${" anywhere in the template string is invalid.
// 4. "\n" embedded anywhere in the template string, or an empty template
- // string, can be used to separate paragraphs. It is not possible to create
- // a completely blank line by using two consecutive newlines (they will be
- // treated as a single newline by views::StyledLabel).
+ // string, can be used to separate paragraphs.
static bool Parse(const base::DictionaryValue& legal_message,
LegalMessageLines* out);
diff --git a/chromium/components/autofill/core/browser/name_field_unittest.cc b/chromium/components/autofill/core/browser/name_field_unittest.cc
index a76c15f62b6..584becf107c 100644
--- a/chromium/components/autofill/core/browser/name_field_unittest.cc
+++ b/chromium/components/autofill/core/browser/name_field_unittest.cc
@@ -5,10 +5,10 @@
#include "components/autofill/core/browser/name_field.h"
#include <memory>
+#include <vector>
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/memory/scoped_vector.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_scanner.h"
@@ -24,7 +24,7 @@ class NameFieldTest : public testing::Test {
NameFieldTest() {}
protected:
- ScopedVector<AutofillField> list_;
+ std::vector<std::unique_ptr<AutofillField>> list_;
std::unique_ptr<NameField> field_;
FieldCandidatesMap field_candidates_map_;
@@ -44,17 +44,20 @@ TEST_F(NameFieldTest, FirstMiddleLast) {
field.label = ASCIIToUTF16("First Name");
field.name = ASCIIToUTF16("First");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name1")));
field.label = ASCIIToUTF16("Middle Name");
field.name = ASCIIToUTF16("Middle");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name2")));
field.label = ASCIIToUTF16("Last Name");
field.name = ASCIIToUTF16("Last");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name3")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name3")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -78,17 +81,20 @@ TEST_F(NameFieldTest, FirstMiddleLast2) {
field.label = base::string16();
field.name = ASCIIToUTF16("firstName");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name1")));
field.label = base::string16();
field.name = ASCIIToUTF16("middleName");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name2")));
field.label = base::string16();
field.name = ASCIIToUTF16("lastName");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name3")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name3")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -112,13 +118,15 @@ TEST_F(NameFieldTest, FirstLast) {
field.label = base::string16();
field.name = ASCIIToUTF16("first_name");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name1")));
field.label = base::string16();
field.name = ASCIIToUTF16("last_name");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name2")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -138,13 +146,15 @@ TEST_F(NameFieldTest, FirstLast2) {
field.label = ASCIIToUTF16("Name");
field.name = ASCIIToUTF16("first_name");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name1")));
field.label = ASCIIToUTF16("Name");
field.name = ASCIIToUTF16("last_name");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name2")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -164,17 +174,20 @@ TEST_F(NameFieldTest, FirstLastMiddleWithSpaces) {
field.label = ASCIIToUTF16("First Name");
field.name = ASCIIToUTF16("first_name");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name1")));
field.label = ASCIIToUTF16("Middle Name");
field.name = ASCIIToUTF16("middle_name");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name2")));
field.label = ASCIIToUTF16("Last Name");
field.name = ASCIIToUTF16("last_name");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name3")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name3")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -198,13 +211,15 @@ TEST_F(NameFieldTest, FirstLastEmpty) {
field.label = ASCIIToUTF16("Name");
field.name = ASCIIToUTF16("first_name");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name1")));
- field.label = base::string16();
+ field.label = base::string16();
field.name = ASCIIToUTF16("last_name");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name2")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -224,17 +239,20 @@ TEST_F(NameFieldTest, FirstMiddleLastEmpty) {
field.label = ASCIIToUTF16("Name");
field.name = ASCIIToUTF16("first_name");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name1")));
field.label = base::string16();
field.name = ASCIIToUTF16("middle_name");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name2")));
field.label = base::string16();
field.name = ASCIIToUTF16("last_name");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name3")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name3")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -258,17 +276,20 @@ TEST_F(NameFieldTest, MiddleInitial) {
field.label = ASCIIToUTF16("First Name");
field.name = ASCIIToUTF16("first_name");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name1")));
field.label = ASCIIToUTF16("MI");
field.name = ASCIIToUTF16("middle_name");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name2")));
field.label = ASCIIToUTF16("Last Name");
field.name = ASCIIToUTF16("last_name");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name3")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name3")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -292,13 +313,15 @@ TEST_F(NameFieldTest, MiddleInitialNoLastName) {
field.label = ASCIIToUTF16("First Name");
field.name = ASCIIToUTF16("first_name");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name1")));
field.label = ASCIIToUTF16("MI");
field.name = ASCIIToUTF16("middle_name");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name2")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_EQ(nullptr, field_.get());
}
@@ -311,17 +334,20 @@ TEST_F(NameFieldTest, MiddleInitialAtEnd) {
field.label = base::string16();
field.name = ASCIIToUTF16("XXXnameXXXfirst");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name1")));
field.label = base::string16();
field.name = ASCIIToUTF16("XXXnameXXXmi");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name2")));
field.label = base::string16();
field.name = ASCIIToUTF16("XXXnameXXXlast");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("name3")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("name3")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
diff --git a/chromium/components/autofill/core/browser/password_generator.cc b/chromium/components/autofill/core/browser/password_generator.cc
index 86877fb647b..def06733a3e 100644
--- a/chromium/components/autofill/core/browser/password_generator.cc
+++ b/chromium/components/autofill/core/browser/password_generator.cc
@@ -55,7 +55,7 @@ bool VerifyPassword(const std::string& password) {
namespace autofill {
-const int PasswordGenerator::kDefaultPasswordLength = 12;
+const int PasswordGenerator::kDefaultPasswordLength = 15;
void ForceFixPassword(std::string* password) {
for (char& it : *password) {
diff --git a/chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc b/chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc
index 6fa6a66d947..480f71c8aa4 100644
--- a/chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc
@@ -9,6 +9,7 @@
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/stringprintf.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/credit_card.h"
diff --git a/chromium/components/autofill/core/browser/payments/payments_client.cc b/chromium/components/autofill/core/browser/payments/payments_client.cc
index 32b2cca0857..5fbeca35005 100644
--- a/chromium/components/autofill/core/browser/payments/payments_client.cc
+++ b/chromium/components/autofill/core/browser/payments/payments_client.cc
@@ -458,7 +458,7 @@ void PaymentsClient::OnURLFetchComplete(const net::URLFetcher* source) {
std::string error_code;
std::unique_ptr<base::Value> message_value = base::JSONReader::Read(data);
if (message_value.get() &&
- message_value->IsType(base::Value::TYPE_DICTIONARY)) {
+ message_value->IsType(base::Value::Type::DICTIONARY)) {
response_dict.reset(
static_cast<base::DictionaryValue*>(message_value.release()));
response_dict->GetString("error.code", &error_code);
diff --git a/chromium/components/autofill/core/browser/personal_data_manager.cc b/chromium/components/autofill/core/browser/personal_data_manager.cc
index 73ba1d35179..88096ec268a 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager.cc
+++ b/chromium/components/autofill/core/browser/personal_data_manager.cc
@@ -292,7 +292,15 @@ void PersonalDataManager::Init(scoped_refptr<AutofillWebDataService> database,
LoadCreditCards();
database_->AddObserver(this);
- is_autofill_profile_dedupe_pending_ = IsAutofillProfileCleanupEnabled();
+
+ // Check if profile cleanup has already been performed this major version.
+ is_autofill_profile_cleanup_pending_ =
+ pref_service_->GetInteger(prefs::kAutofillLastVersionDeduped) >=
+ atoi(version_info::GetVersionNumber().c_str());
+ DVLOG(1) << "Autofill profile cleanup "
+ << (is_autofill_profile_cleanup_pending_ ? "needs to be"
+ : "has already been")
+ << " performed for this version";
}
PersonalDataManager::~PersonalDataManager() {
@@ -309,7 +317,7 @@ void PersonalDataManager::OnSyncServiceInitialized(
syncer::SyncService* sync_service) {
// We want to know when, if at all, we need to run autofill profile de-
// duplication: now or after waiting until sync has started.
- if (!is_autofill_profile_dedupe_pending_) {
+ if (!is_autofill_profile_cleanup_pending_) {
// De-duplication isn't enabled.
return;
}
@@ -419,7 +427,8 @@ void PersonalDataManager::AutofillMultipleChanged() {
}
void PersonalDataManager::SyncStarted(syncer::ModelType model_type) {
- if (model_type == syncer::AUTOFILL_PROFILE) {
+ if (model_type == syncer::AUTOFILL_PROFILE &&
+ is_autofill_profile_cleanup_pending_) {
// This runs as a one-time fix, tracked in syncable prefs. If it has already
// run, it is a NOP (other than checking the pref).
ApplyProfileUseDatesFix();
@@ -472,7 +481,7 @@ void PersonalDataManager::RecordUseOf(const AutofillDataModel& data_model) {
if (credit_card->record_type() == CreditCard::LOCAL_CARD)
database_->UpdateCreditCard(*credit_card);
else
- database_->UpdateServerCardUsageStats(*credit_card);
+ database_->UpdateServerCardMetadata(*credit_card);
Refresh();
return;
@@ -485,7 +494,7 @@ void PersonalDataManager::RecordUseOf(const AutofillDataModel& data_model) {
if (profile->record_type() == AutofillProfile::LOCAL_PROFILE)
database_->UpdateAutofillProfile(*profile);
else if (profile->record_type() == AutofillProfile::SERVER_PROFILE)
- database_->UpdateServerAddressUsageStats(*profile);
+ database_->UpdateServerAddressMetadata(*profile);
Refresh();
}
@@ -636,29 +645,14 @@ void PersonalDataManager::UpdateServerCreditCard(
Refresh();
}
-void PersonalDataManager::UpdateServerCardBillingAddress(
+void PersonalDataManager::UpdateServerCardMetadata(
const CreditCard& credit_card) {
DCHECK_NE(CreditCard::LOCAL_CARD, credit_card.record_type());
- if (!database_.get())
- return;
-
- CreditCard* existing_credit_card = nullptr;
- for (auto& server_card : server_credit_cards_) {
- if (credit_card.server_id() == server_card->server_id()) {
- existing_credit_card = server_card.get();
- break;
- }
- }
- if (!existing_credit_card
- || existing_credit_card->billing_address_id() ==
- credit_card.billing_address_id()) {
+ if (is_off_the_record_ || !database_.get())
return;
- }
- existing_credit_card->set_billing_address_id(
- credit_card.billing_address_id());
- database_->UpdateServerCardBillingAddress(*existing_credit_card);
+ database_->UpdateServerCardMetadata(credit_card);
Refresh();
}
@@ -1011,7 +1005,8 @@ std::string PersonalDataManager::MergeProfile(
std::string guid = new_profile.guid();
// If we have already saved this address, merge in any missing values.
- // Only merge with the first match.
+ // Only merge with the first match. Merging the new profile into the existing
+ // one preserves the validity of credit card's billing address reference.
AutofillProfileComparator comparator(app_locale);
for (const auto& existing_profile : *existing_profiles) {
if (!matching_profile_found &&
@@ -1372,7 +1367,7 @@ bool PersonalDataManager::ImportAddressProfiles(const FormStructure& form) {
// Relevant sections for address fields.
std::set<std::string> sections;
- for (const AutofillField* field : form) {
+ for (const auto& field : form) {
if (field->Type().group() != CREDIT_CARD)
sections.insert(field->section());
}
@@ -1409,7 +1404,7 @@ bool PersonalDataManager::ImportAddressProfileForSection(
std::set<ServerFieldType> types_seen;
// Go through each |form| field and attempt to constitute a valid profile.
- for (const AutofillField* field : form) {
+ for (const auto& field : form) {
// Reject fields that are not within the specified |section|.
if (field->section() != section)
continue;
@@ -1489,7 +1484,7 @@ bool PersonalDataManager::ImportCreditCard(
candidate_credit_card.set_origin(form.source_url().spec());
std::set<ServerFieldType> types_seen;
- for (const AutofillField* field : form) {
+ for (const auto& field : form) {
base::string16 value;
base::TrimWhitespace(field->value, base::TRIM_ALL, &value);
@@ -1625,6 +1620,8 @@ std::vector<Suggestion> PersonalDataManager::GetSuggestionsForCards(
suggestion->value = credit_card->TypeAndLastFourDigits();
suggestion->label = credit_card->GetInfo(
AutofillType(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR), app_locale_);
+ if (IsAutofillCreditCardPopupLayoutExperimentEnabled())
+ ModifyAutofillCreditCardSuggestion(suggestion);
} else if (credit_card->number().empty()) {
if (type.GetStorableType() != CREDIT_CARD_NAME_FULL) {
suggestion->label = credit_card->GetInfo(
@@ -1678,11 +1675,10 @@ void PersonalDataManager::ApplyProfileUseDatesFix() {
}
bool PersonalDataManager::ApplyDedupingRoutine() {
- if (!is_autofill_profile_dedupe_pending_)
+ if (!is_autofill_profile_cleanup_pending_)
return false;
- DCHECK(IsAutofillProfileCleanupEnabled());
- is_autofill_profile_dedupe_pending_ = false;
+ is_autofill_profile_cleanup_pending_ = false;
// No need to de-duplicate if there are less than two profiles.
if (web_profiles_.size() < 2) {
@@ -1703,9 +1699,13 @@ bool PersonalDataManager::ApplyDedupingRoutine() {
std::unordered_set<AutofillProfile*> profiles_to_delete;
profiles_to_delete.reserve(web_profiles_.size());
- DedupeProfiles(&web_profiles_, &profiles_to_delete);
+ // Create the map used to update credit card's billing addresses after the
+ // dedupe.
+ std::unordered_map<std::string, std::string> guids_merge_map;
+
+ DedupeProfiles(&web_profiles_, &profiles_to_delete, &guids_merge_map);
- // Apply the changes to the database.
+ // Apply the profile changes to the database.
for (const auto& profile : web_profiles_) {
// If the profile was set to be deleted, remove it from the database.
if (profiles_to_delete.count(profile.get())) {
@@ -1716,6 +1716,8 @@ bool PersonalDataManager::ApplyDedupingRoutine() {
}
}
+ UpdateCardsBillingAddressReference(guids_merge_map);
+
// Set the pref to the current major version.
pref_service_->SetInteger(prefs::kAutofillLastVersionDeduped,
current_major_version);
@@ -1728,7 +1730,8 @@ bool PersonalDataManager::ApplyDedupingRoutine() {
void PersonalDataManager::DedupeProfiles(
std::vector<std::unique_ptr<AutofillProfile>>* existing_profiles,
- std::unordered_set<AutofillProfile*>* profiles_to_delete) {
+ std::unordered_set<AutofillProfile*>* profiles_to_delete,
+ std::unordered_map<std::string, std::string>* guids_merge_map) {
AutofillMetrics::LogNumberOfProfilesConsideredForDedupe(
existing_profiles->size());
@@ -1782,6 +1785,11 @@ void PersonalDataManager::DedupeProfiles(
// and will not accept updates from profile_to_merge.
if (existing_profile->SaveAdditionalInfo(*profile_to_merge,
app_locale_)) {
+ // Keep track that a credit card using |profile_to_merge|'s GUID as its
+ // billing address id should replace it by |existing_profile|'s GUID.
+ guids_merge_map->insert(std::pair<std::string, std::string>(
+ profile_to_merge->guid(), existing_profile->guid()));
+
// Since |profile_to_merge| was a duplicate of |existing_profile|
// and was merged successfully, it can now be deleted.
profiles_to_delete->insert(profile_to_merge);
@@ -1801,4 +1809,47 @@ void PersonalDataManager::DedupeProfiles(
profiles_to_delete->size());
}
+void PersonalDataManager::UpdateCardsBillingAddressReference(
+ const std::unordered_map<std::string, std::string>& guids_merge_map) {
+ /* Here is an example of what the graph might look like.
+
+ A -> B
+ \
+ -> E
+ /
+ C -> D
+ */
+
+ for (auto& credit_card : local_credit_cards_) {
+ // If the credit card is not associated with a billing address, skip it.
+ if (credit_card->billing_address_id().empty())
+ break;
+
+ // If the billing address profile associated with the card has been merged,
+ // replace it by the id of the profile in which it was merged. Repeat the
+ // process until the billing address has not been merged into another one.
+ std::unordered_map<std::string, std::string>::size_type nb_guid_changes = 0;
+ bool was_modified = false;
+ auto it = guids_merge_map.find(credit_card->billing_address_id());
+ while (it != guids_merge_map.end()) {
+ was_modified = true;
+ credit_card->set_billing_address_id(it->second);
+ it = guids_merge_map.find(credit_card->billing_address_id());
+
+ // Out of abundance of caution.
+ if (nb_guid_changes > guids_merge_map.size()) {
+ NOTREACHED();
+ // Cancel the changes for that card.
+ was_modified = false;
+ break;
+ }
+ }
+
+ // If the card was modified, apply the changes to the database.
+ if (was_modified) {
+ database_->UpdateCreditCard(*credit_card);
+ }
+ }
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/personal_data_manager.h b/chromium/components/autofill/core/browser/personal_data_manager.h
index 89508f3a350..165862f6217 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager.h
+++ b/chromium/components/autofill/core/browser/personal_data_manager.h
@@ -9,6 +9,7 @@
#include <memory>
#include <set>
#include <string>
+#include <unordered_map>
#include <unordered_set>
#include <vector>
@@ -151,9 +152,9 @@ class PersonalDataManager : public KeyedService,
// status can be changed. Looks up the card by server ID.
virtual void UpdateServerCreditCard(const CreditCard& credit_card);
- // Updates the billing address for the server |credit_card|. Looks up the card
- // by GUID.
- void UpdateServerCardBillingAddress(const CreditCard& credit_card);
+ // Updates the use stats and billing address id for the server |credit_card|.
+ // Looks up the card by server_id.
+ void UpdateServerCardMetadata(const CreditCard& credit_card);
// Resets the card for |guid| to the masked state.
void ResetFullServerCard(const std::string& guid);
@@ -288,10 +289,16 @@ class PersonalDataManager : public KeyedService,
FRIEND_TEST_ALL_PREFIXES(AutofillMetricsTest, AutofillIsEnabledAtStartup);
FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest,
DedupeProfiles_ProfilesToDelete);
+ FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest,
+ DedupeProfiles_GuidsMergeMap);
+ FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest,
+ UpdateCardsBillingAddressReference);
FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest, ApplyProfileUseDatesFix);
FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest,
ApplyProfileUseDatesFix_NotAppliedTwice);
FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest,
+ ApplyDedupingRoutine_CardsBillingAddressIdUpdated);
+ FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest,
ApplyDedupingRoutine_MergedProfileValues);
FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest,
ApplyDedupingRoutine_VerifiedProfileFirst);
@@ -472,20 +479,28 @@ class PersonalDataManager : public KeyedService,
// Applies the deduping routine once per major version if the feature is
// enabled. Calls DedupeProfiles with the content of |web_profiles_| as a
// parameter. Removes the profiles to delete from the database and updates the
- // others. Returns true if the routine was run.
+ // others. Also updates the credit cards' billing address references. Returns
+ // true if the routine was run.
bool ApplyDedupingRoutine();
// Goes through all the |existing_profiles| and merges all similar unverified
// profiles together. Also discards unverified profiles that are similar to a
// verified profile. All the profiles except the results of the merges will be
// added to |profile_guids_to_delete|. This routine should be run once per
- // major version.
+ // major version. Records all the merges into the |guids_merge_map|.
//
// This method should only be called by ApplyDedupingRoutine. It is split for
// testing purposes.
void DedupeProfiles(
std::vector<std::unique_ptr<AutofillProfile>>* existing_profiles,
- std::unordered_set<AutofillProfile*>* profile_guids_to_delete);
+ std::unordered_set<AutofillProfile*>* profile_guids_to_delete,
+ std::unordered_map<std::string, std::string>* guids_merge_map);
+
+ // Updates the credit cards' billing address reference based on the merges
+ // that happened during the dedupe, as defined in |guids_merge_map|. Also
+ // updates the cards entries in the database.
+ void UpdateCardsBillingAddressReference(
+ const std::unordered_map<std::string, std::string>& guids_merge_map);
const std::string app_locale_;
@@ -523,9 +538,8 @@ class PersonalDataManager : public KeyedService,
// An observer to listen for changes to prefs::kAutofillWalletImportEnabled.
std::unique_ptr<BooleanPrefMember> wallet_enabled_pref_;
- // Set to true if autofill profile deduplication is enabled and needs to be
- // performed on the next data refresh.
- bool is_autofill_profile_dedupe_pending_ = false;
+ // True if autofill profile cleanup needs to be performed.
+ bool is_autofill_profile_cleanup_pending_ = false;
#if defined(OS_ANDROID)
// The context for the request to be used to fetch libaddressinput's address
diff --git a/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc b/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
index 49bee42bf2c..18bb0aebdd4 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -15,7 +15,6 @@
#include <vector>
#include "base/command_line.h"
-#include "base/feature_list.h"
#include "base/files/scoped_temp_dir.h"
#include "base/guid.h"
#include "base/memory/ptr_util.h"
@@ -24,7 +23,6 @@
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/histogram_tester.h"
-#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -61,6 +59,13 @@ namespace {
enum UserMode { USER_MODE_NORMAL, USER_MODE_INCOGNITO };
+const std::string kUTF8MidlineEllipsis =
+ " "
+ "\xE2\x80\xA2\xE2\x80\x86"
+ "\xE2\x80\xA2\xE2\x80\x86"
+ "\xE2\x80\xA2\xE2\x80\x86"
+ "\xE2\x80\xA2\xE2\x80\x86";
+
ACTION(QuitMainMessageLoop) {
base::MessageLoop::current()->QuitWhenIdle();
}
@@ -143,7 +148,6 @@ class PersonalDataManagerTest : public testing::Test {
// There are no field trials enabled by default.
field_trial_list_.reset();
- scoped_feature_list_.reset();
// Reset the deduping pref to its default value.
personal_data_->pref_service_->SetInteger(
@@ -197,9 +201,7 @@ class PersonalDataManagerTest : public testing::Test {
}
void EnableAutofillProfileCleanup() {
- scoped_feature_list_.reset(new base::test::ScopedFeatureList);
- scoped_feature_list_->InitAndEnableFeature(kAutofillProfileCleanup);
- personal_data_->is_autofill_profile_dedupe_pending_ = true;
+ personal_data_->is_autofill_profile_cleanup_pending_ = true;
}
void SetupReferenceProfile() {
@@ -364,7 +366,6 @@ class PersonalDataManagerTest : public testing::Test {
std::unique_ptr<base::FieldTrialList> field_trial_list_;
scoped_refptr<base::FieldTrial> field_trial_;
- std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_;
};
TEST_F(PersonalDataManagerTest, AddProfile) {
@@ -3697,8 +3698,7 @@ TEST_F(PersonalDataManagerTest, GetCreditCardSuggestions_NumberMissing) {
AutofillType(CREDIT_CARD_NUMBER),
/* field_contents= */ base::string16());
ASSERT_EQ(1U, suggestions.size());
- EXPECT_EQ(UTF8ToUTF16("Amex\xC2\xA0\xE2\x8B\xAF"
- "8555"),
+ EXPECT_EQ(UTF8ToUTF16("Amex" + kUTF8MidlineEllipsis + "8555"),
suggestions[0].value);
EXPECT_EQ(ASCIIToUTF16("04/99"), suggestions[0].label);
}
@@ -3761,17 +3761,13 @@ TEST_F(PersonalDataManagerTest, GetCreditCardSuggestions_ServerDuplicates) {
suggestions = personal_data_->GetCreditCardSuggestions(
AutofillType(CREDIT_CARD_NUMBER), /* field_contents= */ base::string16());
ASSERT_EQ(4U, suggestions.size());
- EXPECT_EQ(UTF8ToUTF16("Visa\xC2\xA0\xE2\x8B\xAF"
- "9012"),
+ EXPECT_EQ(UTF8ToUTF16("Visa" + kUTF8MidlineEllipsis + "9012"),
suggestions[0].value);
- EXPECT_EQ(UTF8ToUTF16("Amex\xC2\xA0\xE2\x8B\xAF"
- "8555"),
+ EXPECT_EQ(UTF8ToUTF16("Amex" + kUTF8MidlineEllipsis + "8555"),
suggestions[1].value);
- EXPECT_EQ(UTF8ToUTF16("MasterCard\xC2\xA0\xE2\x8B\xAF"
- "2109"),
+ EXPECT_EQ(UTF8ToUTF16("MasterCard" + kUTF8MidlineEllipsis + "2109"),
suggestions[2].value);
- EXPECT_EQ(UTF8ToUTF16("Visa\xC2\xA0\xE2\x8B\xAF"
- "2109"),
+ EXPECT_EQ(UTF8ToUTF16("Visa" + kUTF8MidlineEllipsis + "2109"),
suggestions[3].value);
}
@@ -4672,8 +4668,10 @@ TEST_F(PersonalDataManagerTest, DedupeProfiles_ProfilesToDelete) {
EnableAutofillProfileCleanup();
base::HistogramTester histogram_tester;
+ std::unordered_map<std::string, std::string> guids_merge_map;
std::unordered_set<AutofillProfile*> profiles_to_delete;
- personal_data_->DedupeProfiles(&existing_profiles, &profiles_to_delete);
+ personal_data_->DedupeProfiles(&existing_profiles, &profiles_to_delete,
+ &guids_merge_map);
// 5 profiles were considered for dedupe.
histogram_tester.ExpectUniqueSample(
"Autofill.NumberOfProfilesConsideredForDedupe", 5, 1);
@@ -4696,6 +4694,272 @@ TEST_F(PersonalDataManagerTest, DedupeProfiles_ProfilesToDelete) {
EXPECT_EQ(5U, existing_profiles.size());
}
+// Tests that DedupeProfiles sets the correct merge mapping for billing address
+// id references.
+TEST_F(PersonalDataManagerTest, DedupeProfiles_GuidsMergeMap) {
+ // Create the profile for which to find duplicates. It has the highest
+ // frecency.
+ AutofillProfile* profile1 =
+ new AutofillProfile(base::GenerateGUID(), "https://www.example.com");
+ test::SetProfileInfo(profile1, "Homer", "Jay", "Simpson",
+ "homer.simpson@abc.com", "", "742. Evergreen Terrace",
+ "", "Springfield", "IL", "91601", "US", "12345678910");
+ profile1->set_use_count(9);
+
+ // Create a different profile that should not be deduped (different address).
+ AutofillProfile* profile2 =
+ new AutofillProfile(base::GenerateGUID(), "https://www.example.com");
+ test::SetProfileInfo(profile2, "Homer", "Jay", "Simpson",
+ "homer.simpson@abc.com", "Fox", "1234 Other Street", "",
+ "Springfield", "IL", "91601", "US", "12345678910");
+ profile2->set_use_count(7);
+
+ // Create a profile similar to profile1 which should be deduped.
+ AutofillProfile* profile3 =
+ new AutofillProfile(base::GenerateGUID(), "https://www.example.com");
+ test::SetProfileInfo(profile3, "Homer", "Jay", "Simpson",
+ "homer.simpson@abc.com", "", "742 Evergreen Terrace", "",
+ "Springfield", "IL", "91601", "US", "12345678910");
+ profile3->set_use_count(5);
+
+ // Create another different profile that should not be deduped (different
+ // name).
+ AutofillProfile* profile4 =
+ new AutofillProfile(base::GenerateGUID(), "https://www.example.com");
+ test::SetProfileInfo(profile4, "Marjorie", "Jacqueline", "Simpson",
+ "homer.simpson@abc.com", "Fox", "742 Evergreen Terrace",
+ "", "Springfield", "IL", "91601", "US", "12345678910");
+ profile4->set_use_count(3);
+
+ // Create another profile similar to profile1. Since that one has the lowest
+ // frecency, the result of the merge should be in this profile at the end of
+ // the test.
+ AutofillProfile* profile5 =
+ new AutofillProfile(base::GenerateGUID(), "https://www.example.com");
+ test::SetProfileInfo(profile5, "Homer", "Jay", "Simpson",
+ "homer.simpson@abc.com", "Fox", "742 Evergreen Terrace.",
+ "", "Springfield", "IL", "91601", "US", "12345678910");
+ profile5->set_use_count(1);
+
+ // Add the profiles.
+ std::vector<std::unique_ptr<AutofillProfile>> existing_profiles;
+ existing_profiles.push_back(base::WrapUnique(profile1));
+ existing_profiles.push_back(base::WrapUnique(profile2));
+ existing_profiles.push_back(base::WrapUnique(profile3));
+ existing_profiles.push_back(base::WrapUnique(profile4));
+ existing_profiles.push_back(base::WrapUnique(profile5));
+
+ // Enable the profile cleanup.
+ EnableAutofillProfileCleanup();
+
+ std::unordered_map<std::string, std::string> guids_merge_map;
+ std::unordered_set<AutofillProfile*> profiles_to_delete;
+ personal_data_->DedupeProfiles(&existing_profiles, &profiles_to_delete,
+ &guids_merge_map);
+
+ // The two profile merges should be recorded in the map.
+ EXPECT_EQ(2U, guids_merge_map.size());
+
+ // Profile 1 was merged into profile 3.
+ ASSERT_TRUE(guids_merge_map.count(profile1->guid()));
+ EXPECT_TRUE(guids_merge_map.at(profile1->guid()) == profile3->guid());
+
+ // Profile 3 was merged into profile 5.
+ ASSERT_TRUE(guids_merge_map.count(profile3->guid()));
+ EXPECT_TRUE(guids_merge_map.at(profile3->guid()) == profile5->guid());
+}
+
+// Tests that UpdateCardsBillingAddressReference sets the correct billing
+// address id as specified in the map.
+TEST_F(PersonalDataManagerTest, UpdateCardsBillingAddressReference) {
+ /* The merges will be as follow:
+
+ A -> B F (not merged)
+ \
+ -> E
+ /
+ C -> D
+ */
+
+ std::unordered_map<std::string, std::string> guids_merge_map;
+ guids_merge_map.insert(std::pair<std::string, std::string>("A", "B"));
+ guids_merge_map.insert(std::pair<std::string, std::string>("C", "D"));
+ guids_merge_map.insert(std::pair<std::string, std::string>("B", "E"));
+ guids_merge_map.insert(std::pair<std::string, std::string>("D", "E"));
+
+ // Create cards that use A, D, E and F as their billing address id.
+ CreditCard* credit_card1 =
+ new CreditCard(base::GenerateGUID(), "https://www.example.com");
+ credit_card1->set_billing_address_id("A");
+ CreditCard* credit_card2 =
+ new CreditCard(base::GenerateGUID(), "https://www.example.com");
+ credit_card2->set_billing_address_id("D");
+ CreditCard* credit_card3 =
+ new CreditCard(base::GenerateGUID(), "https://www.example.com");
+ credit_card3->set_billing_address_id("E");
+ CreditCard* credit_card4 =
+ new CreditCard(base::GenerateGUID(), "https://www.example.com");
+ credit_card4->set_billing_address_id("F");
+
+ // Add the credit cards to the database.
+ personal_data_->local_credit_cards_.push_back(base::WrapUnique(credit_card1));
+ personal_data_->local_credit_cards_.push_back(base::WrapUnique(credit_card2));
+ personal_data_->local_credit_cards_.push_back(base::WrapUnique(credit_card3));
+ personal_data_->local_credit_cards_.push_back(base::WrapUnique(credit_card4));
+
+ personal_data_->UpdateCardsBillingAddressReference(guids_merge_map);
+
+ // The first card's billing address should now be E.
+ EXPECT_EQ("E", credit_card1->billing_address_id());
+ // The second card's billing address should now be E.
+ EXPECT_EQ("E", credit_card2->billing_address_id());
+ // The third card's billing address should still be E.
+ EXPECT_EQ("E", credit_card3->billing_address_id());
+ // The fourth card's billing address should still be F.
+ EXPECT_EQ("F", credit_card4->billing_address_id());
+}
+
+// Tests that ApplyDedupingRoutine updates the credit cards' billing address id
+// based on the deduped profiles.
+TEST_F(PersonalDataManagerTest,
+ ApplyDedupingRoutine_CardsBillingAddressIdUpdated) {
+ // A set of 6 profiles will be created. They should merge in this way:
+ // 1 -> 2 -> 3
+ // 4 -> 5
+ // 6
+ // Set their frencency score so that profile 3 has a higher score than 5, and
+ // 5 has a higher score than 6. This will ensure a deterministic order when
+ // verifying results.
+
+ // Create a set of 3 profiles to be merged together.
+ // Create a profile with a higher frecency score.
+ AutofillProfile profile1(base::GenerateGUID(), "https://www.example.com");
+ test::SetProfileInfo(&profile1, "Homer", "J", "Simpson",
+ "homer.simpson@abc.com", "", "742. Evergreen Terrace",
+ "", "Springfield", "IL", "91601", "US", "");
+ profile1.set_use_count(12);
+ profile1.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
+
+ // Create a profile with a medium frecency score.
+ AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
+ test::SetProfileInfo(&profile2, "Homer", "Jay", "Simpson",
+ "homer.simpson@abc.com", "", "742 Evergreen Terrace", "",
+ "Springfield", "IL", "91601", "", "12345678910");
+ profile2.set_use_count(5);
+ profile2.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(3));
+
+ // Create a profile with a lower frecency score.
+ AutofillProfile profile3(base::GenerateGUID(), "https://www.example.com");
+ test::SetProfileInfo(&profile3, "Homer", "J", "Simpson",
+ "homer.simpson@abc.com", "Fox", "742 Evergreen Terrace.",
+ "", "Springfield", "IL", "91601", "", "");
+ profile3.set_use_count(3);
+ profile3.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(5));
+
+ // Create a set of two profiles to be merged together.
+ // Create a profile with a higher frecency score.
+ AutofillProfile profile4(base::GenerateGUID(), "https://www.example.com");
+ test::SetProfileInfo(&profile4, "Marge", "B", "Simpson",
+ "marge.simpson@abc.com", "", "742. Evergreen Terrace",
+ "", "Springfield", "IL", "91601", "US", "");
+ profile4.set_use_count(11);
+ profile4.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
+
+ // Create a profile with a lower frecency score.
+ AutofillProfile profile5(base::GenerateGUID(), "https://www.example.com");
+ test::SetProfileInfo(&profile5, "Marge", "B", "Simpson",
+ "marge.simpson@abc.com", "Fox", "742 Evergreen Terrace.",
+ "", "Springfield", "IL", "91601", "", "");
+ profile5.set_use_count(5);
+ profile5.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(3));
+
+ // Create a unique profile.
+ AutofillProfile profile6(base::GenerateGUID(), "https://www.example.com");
+ test::SetProfileInfo(&profile6, "Bart", "J", "Simpson",
+ "bart.simpson@abc.com", "Fox", "742 Evergreen Terrace.",
+ "", "Springfield", "IL", "91601", "", "");
+ profile6.set_use_count(10);
+ profile6.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
+
+ // Add three credit cards. Give them a frecency score so that they are
+ // suggested in order (1, 2, 3). This will ensure a deterministic order for
+ // verifying results.
+ CreditCard credit_card1(base::GenerateGUID(), "https://www.example.com");
+ test::SetCreditCardInfo(&credit_card1, "Clyde Barrow",
+ "347666888555" /* American Express */, "04", "2999");
+ credit_card1.set_use_count(10);
+
+ CreditCard credit_card2(base::GenerateGUID(), "https://www.example.com");
+ test::SetCreditCardInfo(&credit_card2, "John Dillinger",
+ "423456789012" /* Visa */, "01", "2999");
+ credit_card2.set_use_count(5);
+
+ CreditCard credit_card3(base::GenerateGUID(), "https://www.example.com");
+ test::SetCreditCardInfo(&credit_card3, "Bonnie Parker",
+ "518765432109" /* Mastercard */, "12", "2999");
+ credit_card3.set_use_count(1);
+
+ // Associate the first card with profile1.
+ credit_card1.set_billing_address_id(profile1.guid());
+ // Associate the second card with profile4.
+ credit_card2.set_billing_address_id(profile4.guid());
+ // Associate the third card with profile6.
+ credit_card3.set_billing_address_id(profile6.guid());
+
+ personal_data_->AddProfile(profile1);
+ personal_data_->AddProfile(profile2);
+ personal_data_->AddProfile(profile3);
+ personal_data_->AddProfile(profile4);
+ personal_data_->AddProfile(profile5);
+ personal_data_->AddProfile(profile6);
+ personal_data_->AddCreditCard(credit_card1);
+ personal_data_->AddCreditCard(credit_card2);
+ personal_data_->AddCreditCard(credit_card3);
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .WillOnce(QuitMainMessageLoop());
+ base::RunLoop().Run();
+
+ // Make sure the 6 profiles and 3 credit cards were saved.
+ EXPECT_EQ(6U, personal_data_->GetProfiles().size());
+ EXPECT_EQ(3U, personal_data_->GetCreditCards().size());
+
+ // Enable the profile cleanup now. Otherwise it would be triggered by the
+ // calls to AddProfile.
+ EnableAutofillProfileCleanup();
+
+ EXPECT_TRUE(personal_data_->ApplyDedupingRoutine());
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .WillOnce(QuitMainMessageLoop());
+ base::RunLoop().Run();
+
+ // Get the profiles and cards sorted by frecency to have a deterministic
+ // order.
+ std::vector<AutofillProfile*> profiles =
+ personal_data_->GetProfilesToSuggest();
+ std::vector<CreditCard*> credit_cards =
+ personal_data_->GetCreditCardsToSuggest();
+
+ // |profile1| should have been merged into |profile2| which should then have
+ // been merged into |profile3|. |profile4| should have been merged into
+ // |profile5| and |profile6| should not have merged. Therefore there should be
+ // 3 profile left.
+ ASSERT_EQ(3U, profiles.size());
+
+ // Make sure the remaining profiles are the expected ones.
+ EXPECT_EQ(profile3.guid(), profiles[0]->guid());
+ EXPECT_EQ(profile5.guid(), profiles[1]->guid());
+ EXPECT_EQ(profile6.guid(), profiles[2]->guid());
+
+ // |credit_card1|'s billing address should now be profile 3.
+ EXPECT_EQ(profile3.guid(), credit_cards[0]->billing_address_id());
+
+ // |credit_card2|'s billing address should now be profile 5.
+ EXPECT_EQ(profile5.guid(), credit_cards[1]->billing_address_id());
+
+ // |credit_card3|'s billing address should still be profile 6.
+ EXPECT_EQ(profile6.guid(), credit_cards[2]->billing_address_id());
+}
+
// Tests that ApplyDedupingRoutine merges the profile values correctly, i.e.
// never lose information and keep the syntax of the profile with the higher
// frecency score.
@@ -5363,9 +5627,6 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_OncePerVersion) {
"homer.simpson@abc.com", "Fox", "742 Evergreen Terrace.",
"", "Springfield", "IL", "91601", "", "");
- // Disable the profile cleanup before adding |profile3|.
- scoped_feature_list_.reset();
-
personal_data_->AddProfile(profile3);
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
diff --git a/chromium/components/autofill/core/browser/phone_field_unittest.cc b/chromium/components/autofill/core/browser/phone_field_unittest.cc
index f270cbfa104..868bb69675f 100644
--- a/chromium/components/autofill/core/browser/phone_field_unittest.cc
+++ b/chromium/components/autofill/core/browser/phone_field_unittest.cc
@@ -7,10 +7,10 @@
#include <stddef.h>
#include <memory>
+#include <vector>
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/memory/scoped_vector.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_field.h"
@@ -56,7 +56,7 @@ class PhoneFieldTest : public testing::Test {
EXPECT_EQ(expected_type, it->second.BestHeuristicType()) << name;
}
- ScopedVector<AutofillField> list_;
+ std::vector<std::unique_ptr<AutofillField>> list_;
std::unique_ptr<PhoneField> field_;
FieldCandidatesMap field_candidates_map_;
@@ -65,14 +65,14 @@ class PhoneFieldTest : public testing::Test {
};
TEST_F(PhoneFieldTest, Empty) {
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_EQ(nullptr, field_.get());
}
TEST_F(PhoneFieldTest, NonParse) {
- list_.push_back(new AutofillField);
- AutofillScanner scanner(list_.get());
+ list_.push_back(base::MakeUnique<AutofillField>());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_EQ(nullptr, field_.get());
}
@@ -86,9 +86,10 @@ TEST_F(PhoneFieldTest, ParseOneLinePhone) {
field.form_control_type = field_type;
field.label = ASCIIToUTF16("Phone");
field.name = ASCIIToUTF16("phone");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("phone1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("phone1")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -105,13 +106,15 @@ TEST_F(PhoneFieldTest, ParseTwoLinePhone) {
field.form_control_type = field_type;
field.label = ASCIIToUTF16("Area Code");
field.name = ASCIIToUTF16("area code");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("areacode1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("areacode1")));
field.label = ASCIIToUTF16("Phone");
field.name = ASCIIToUTF16("phone");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("phone2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("phone2")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -135,24 +138,28 @@ TEST_F(PhoneFieldTest, ThreePartPhoneNumber) {
field.label = ASCIIToUTF16("Phone:");
field.name = ASCIIToUTF16("dayphone1");
field.max_length = 0;
- list_.push_back(new AutofillField(field, ASCIIToUTF16("areacode1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("areacode1")));
field.label = ASCIIToUTF16("-");
field.name = ASCIIToUTF16("dayphone2");
field.max_length = 3;
- list_.push_back(new AutofillField(field, ASCIIToUTF16("prefix2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("prefix2")));
field.label = ASCIIToUTF16("-");
field.name = ASCIIToUTF16("dayphone3");
field.max_length = 4;
- list_.push_back(new AutofillField(field, ASCIIToUTF16("suffix3")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("suffix3")));
field.label = ASCIIToUTF16("ext.:");
field.name = ASCIIToUTF16("dayphone4");
field.max_length = 0;
- list_.push_back(new AutofillField(field, ASCIIToUTF16("ext4")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("ext4")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -175,17 +182,20 @@ TEST_F(PhoneFieldTest, ThreePartPhoneNumberPrefixSuffix) {
field.form_control_type = field_type;
field.label = ASCIIToUTF16("Phone:");
field.name = ASCIIToUTF16("area");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("areacode1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("areacode1")));
field.label = base::string16();
field.name = ASCIIToUTF16("prefix");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("prefix2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("prefix2")));
field.label = base::string16();
field.name = ASCIIToUTF16("suffix");
- list_.push_back(new AutofillField(field, ASCIIToUTF16("suffix3")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("suffix3")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -205,19 +215,22 @@ TEST_F(PhoneFieldTest, ThreePartPhoneNumberPrefixSuffix2) {
field.label = ASCIIToUTF16("(");
field.name = ASCIIToUTF16("phone1");
field.max_length = 3;
- list_.push_back(new AutofillField(field, ASCIIToUTF16("phone1")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("phone1")));
field.label = ASCIIToUTF16(")");
field.name = ASCIIToUTF16("phone2");
field.max_length = 3;
- list_.push_back(new AutofillField(field, ASCIIToUTF16("phone2")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("phone2")));
field.label = base::string16();
field.name = ASCIIToUTF16("phone3");
field.max_length = 4;
- list_.push_back(new AutofillField(field, ASCIIToUTF16("phone3")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("phone3")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
@@ -239,14 +252,16 @@ TEST_F(PhoneFieldTest, CountryAndCityAndPhoneNumber) {
field.label = ASCIIToUTF16("Phone Number");
field.name = ASCIIToUTF16("CountryCode");
field.max_length = 3;
- list_.push_back(new AutofillField(field, ASCIIToUTF16("country")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("country")));
field.label = ASCIIToUTF16("Phone Number");
field.name = ASCIIToUTF16("PhoneNumber");
field.max_length = 10;
- list_.push_back(new AutofillField(field, ASCIIToUTF16("phone")));
+ list_.push_back(
+ base::MakeUnique<AutofillField>(field, ASCIIToUTF16("phone")));
- AutofillScanner scanner(list_.get());
+ AutofillScanner scanner(list_);
field_ = Parse(&scanner);
ASSERT_NE(nullptr, field_.get());
field_->AddClassifications(&field_candidates_map_);
diff --git a/chromium/components/autofill/core/browser/popup_item_ids.h b/chromium/components/autofill/core/browser/popup_item_ids.h
index 29be19cb622..7821315f611 100644
--- a/chromium/components/autofill/core/browser/popup_item_ids.h
+++ b/chromium/components/autofill/core/browser/popup_item_ids.h
@@ -11,7 +11,7 @@ namespace autofill {
enum PopupItemId {
POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY = 0,
- POPUP_ITEM_ID_WARNING_MESSAGE = -1,
+ POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE = -1,
POPUP_ITEM_ID_PASSWORD_ENTRY = -2,
POPUP_ITEM_ID_SEPARATOR = -3,
POPUP_ITEM_ID_CLEAR_FORM = -4,
@@ -20,6 +20,8 @@ enum PopupItemId {
POPUP_ITEM_ID_SCAN_CREDIT_CARD = -7,
POPUP_ITEM_ID_TITLE = -8,
POPUP_ITEM_ID_CREDIT_CARD_SIGNIN_PROMO = -9,
+ POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE = -10,
+ POPUP_ITEM_ID_USERNAME_ENTRY = -11,
};
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/proto/BUILD.gn b/chromium/components/autofill/core/browser/proto/BUILD.gn
index ad52e78646b..2a8069f6378 100644
--- a/chromium/components/autofill/core/browser/proto/BUILD.gn
+++ b/chromium/components/autofill/core/browser/proto/BUILD.gn
@@ -6,6 +6,7 @@ import("//third_party/protobuf/proto_library.gni")
proto_library("proto") {
sources = [
+ "autofill_sync.proto",
"server.proto",
]
}
diff --git a/chromium/components/autofill/core/browser/proto/autofill_sync.proto b/chromium/components/autofill/core/browser/proto/autofill_sync.proto
new file mode 100644
index 00000000000..613bdbac022
--- /dev/null
+++ b/chromium/components/autofill/core/browser/proto/autofill_sync.proto
@@ -0,0 +1,17 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package autofill;
+
+// Used to convert between autofill::AutofillKey and a std::string that can be
+// passed to sync as storage key to uniquely identify an entity of ModelType
+// syncer::AUTOFILL.
+message AutofillSyncStorageKey {
+ optional string name = 1;
+ optional string value = 2;
+}
diff --git a/chromium/components/autofill/core/browser/suggestion.cc b/chromium/components/autofill/core/browser/suggestion.cc
index 22d4ac7c89c..754ede930f8 100644
--- a/chromium/components/autofill/core/browser/suggestion.cc
+++ b/chromium/components/autofill/core/browser/suggestion.cc
@@ -10,7 +10,8 @@ namespace autofill {
Suggestion::Suggestion()
: frontend_id(0),
- match(PREFIX_MATCH) {
+ match(PREFIX_MATCH),
+ is_value_bold(false) {
}
Suggestion::Suggestion(const Suggestion& other)
@@ -19,13 +20,15 @@ Suggestion::Suggestion(const Suggestion& other)
value(other.value),
label(other.label),
icon(other.icon),
- match(other.match) {
+ match(other.match),
+ is_value_bold(other.is_value_bold) {
}
Suggestion::Suggestion(const base::string16& v)
: frontend_id(0),
value(v),
- match(PREFIX_MATCH) {
+ match(PREFIX_MATCH),
+ is_value_bold(false) {
}
Suggestion::Suggestion(const std::string& v,
@@ -36,7 +39,8 @@ Suggestion::Suggestion(const std::string& v,
value(base::UTF8ToUTF16(v)),
label(base::UTF8ToUTF16(l)),
icon(base::UTF8ToUTF16(i)),
- match(PREFIX_MATCH) {
+ match(PREFIX_MATCH),
+ is_value_bold(false) {
}
Suggestion::~Suggestion() {
diff --git a/chromium/components/autofill/core/browser/suggestion.h b/chromium/components/autofill/core/browser/suggestion.h
index 930ab230f2d..63522debfec 100644
--- a/chromium/components/autofill/core/browser/suggestion.h
+++ b/chromium/components/autofill/core/browser/suggestion.h
@@ -47,6 +47,7 @@ struct Suggestion {
base::string16 label;
base::string16 icon;
MatchMode match;
+ bool is_value_bold; // true if |value| should be displayed in bold type face.
};
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/test_autofill_client.cc b/chromium/components/autofill/core/browser/test_autofill_client.cc
index 5913dedf3bf..7df6c300ce4 100644
--- a/chromium/components/autofill/core/browser/test_autofill_client.cc
+++ b/chromium/components/autofill/core/browser/test_autofill_client.cc
@@ -11,7 +11,8 @@ namespace autofill {
TestAutofillClient::TestAutofillClient()
: token_service_(new FakeOAuth2TokenService()),
identity_provider_(new FakeIdentityProvider(token_service_.get())),
- rappor_service_(new rappor::TestRapporService()) {}
+ rappor_service_(new rappor::TestRapporServiceImpl()),
+ form_origin_(GURL("https://example.test")) {}
TestAutofillClient::~TestAutofillClient() {
}
@@ -36,7 +37,7 @@ IdentityProvider* TestAutofillClient::GetIdentityProvider() {
return identity_provider_.get();
}
-rappor::RapporService* TestAutofillClient::GetRapporService() {
+rappor::RapporServiceImpl* TestAutofillClient::GetRapporServiceImpl() {
return rappor_service_.get();
}
@@ -115,9 +116,9 @@ void TestAutofillClient::DidFillOrPreviewField(
void TestAutofillClient::OnFirstUserGestureObserved() {
}
-bool TestAutofillClient::IsContextSecure(const GURL& form_origin) {
+bool TestAutofillClient::IsContextSecure() {
// Simplified secure context check for tests.
- return form_origin.SchemeIs("https");
+ return form_origin_.SchemeIs("https");
}
bool TestAutofillClient::ShouldShowSigninPromo() {
@@ -126,4 +127,6 @@ bool TestAutofillClient::ShouldShowSigninPromo() {
void TestAutofillClient::StartSigninFlow() {}
+void TestAutofillClient::ShowHttpNotSecureExplanation() {}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/test_autofill_client.h b/chromium/components/autofill/core/browser/test_autofill_client.h
index 013a9030d53..72cdd8c3f57 100644
--- a/chromium/components/autofill/core/browser/test_autofill_client.h
+++ b/chromium/components/autofill/core/browser/test_autofill_client.h
@@ -33,7 +33,7 @@ class TestAutofillClient : public AutofillClient {
PrefService* GetPrefs() override;
syncer::SyncService* GetSyncService() override;
IdentityProvider* GetIdentityProvider() override;
- rappor::RapporService* GetRapporService() override;
+ rappor::RapporServiceImpl* GetRapporServiceImpl() override;
void ShowAutofillSettings() override;
void ShowUnmaskPrompt(const CreditCard& card,
UnmaskCardReason reason,
@@ -67,24 +67,31 @@ class TestAutofillClient : public AutofillClient {
void DidFillOrPreviewField(const base::string16& autofilled_value,
const base::string16& profile_full_name) override;
void OnFirstUserGestureObserved() override;
- bool IsContextSecure(const GURL& form_origin) override;
+ // By default, TestAutofillClient will report that the context is
+ // secure. This can be adjusted by calling set_form_origin() with an
+ // http:// URL.
+ bool IsContextSecure() override;
bool ShouldShowSigninPromo() override;
void StartSigninFlow() override;
+ void ShowHttpNotSecureExplanation() override;
void SetPrefs(std::unique_ptr<PrefService> prefs) {
prefs_ = std::move(prefs);
}
- rappor::TestRapporService* test_rappor_service() {
+ rappor::TestRapporServiceImpl* test_rappor_service() {
return rappor_service_.get();
}
+ void set_form_origin(const GURL& url) { form_origin_ = url; }
+
private:
// NULL by default.
std::unique_ptr<PrefService> prefs_;
std::unique_ptr<FakeOAuth2TokenService> token_service_;
std::unique_ptr<FakeIdentityProvider> identity_provider_;
- std::unique_ptr<rappor::TestRapporService> rappor_service_;
+ std::unique_ptr<rappor::TestRapporServiceImpl> rappor_service_;
+ GURL form_origin_;
DISALLOW_COPY_AND_ASSIGN(TestAutofillClient);
};
diff --git a/chromium/components/autofill/core/browser/test_autofill_external_delegate.h b/chromium/components/autofill/core/browser/test_autofill_external_delegate.h
index cc7bf73ee44..9da419394b0 100644
--- a/chromium/components/autofill/core/browser/test_autofill_external_delegate.h
+++ b/chromium/components/autofill/core/browser/test_autofill_external_delegate.h
@@ -9,8 +9,6 @@
namespace autofill {
-class AutofillManager;
-
// Calls the required functions on the given external delegate to cause the
// delegate to display a popup.
void GenerateTestAutofillPopup(
diff --git a/chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl.cc b/chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl.cc
index a922b5a2c75..435e00caf82 100644
--- a/chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl.cc
+++ b/chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl.cc
@@ -15,6 +15,7 @@
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/ui/card_unmask_prompt_view.h"
+#include "components/autofill/core/browser/validation.h"
#include "components/autofill/core/common/autofill_pref_names.h"
#include "components/prefs/pref_service.h"
#include "grit/components_scaled_resources.h"
@@ -83,7 +84,7 @@ void CardUnmaskPromptControllerImpl::OnVerificationResult(
case AutofillClient::TRY_AGAIN_FAILURE: {
error_message = l10n_util::GetStringUTF16(
- IDS_AUTOFILL_CARD_UNMASK_PROMPT_ERROR_TRY_AGAIN);
+ IDS_AUTOFILL_CARD_UNMASK_PROMPT_ERROR_TRY_AGAIN_CVC);
break;
}
@@ -219,15 +220,11 @@ base::string16 CardUnmaskPromptControllerImpl::GetWindowTitle() const {
// The iOS UI has less room for the title so it shows a shorter string.
return l10n_util::GetStringUTF16(IDS_AUTOFILL_CARD_UNMASK_PROMPT_TITLE);
#else
- int ids;
- if (reason_ == AutofillClient::UNMASK_FOR_AUTOFILL &&
- ShouldRequestExpirationDate()) {
- ids = IDS_AUTOFILL_CARD_UNMASK_PROMPT_UPDATE_TITLE;
- }
- else {
- ids = IDS_AUTOFILL_CARD_UNMASK_PROMPT_TITLE;
- }
- return l10n_util::GetStringFUTF16(ids, card_.TypeAndLastFourDigits());
+ return l10n_util::GetStringFUTF16(
+ ShouldRequestExpirationDate()
+ ? IDS_AUTOFILL_CARD_UNMASK_PROMPT_EXPIRED_TITLE
+ : IDS_AUTOFILL_CARD_UNMASK_PROMPT_TITLE,
+ card_.TypeAndLastFourDigits());
#endif
}
@@ -283,10 +280,7 @@ bool CardUnmaskPromptControllerImpl::InputCvcIsValid(
const base::string16& input_text) const {
base::string16 trimmed_text;
base::TrimWhitespace(input_text, base::TRIM_ALL, &trimmed_text);
- size_t input_size = card_.type() == kAmericanExpressCard ? 4 : 3;
- return trimmed_text.size() == input_size &&
- base::ContainsOnlyChars(trimmed_text,
- base::ASCIIToUTF16("0123456789"));
+ return IsValidCreditCardSecurityCode(trimmed_text, card_.type());
}
bool CardUnmaskPromptControllerImpl::InputExpirationIsValid(
@@ -303,23 +297,15 @@ bool CardUnmaskPromptControllerImpl::InputExpirationIsValid(
return false;
}
- if (month_value < 1 || month_value > 12)
- return false;
-
- base::Time::Exploded now;
- base::Time::Now().LocalExplode(&now);
-
// Convert 2 digit year to 4 digit year.
- if (year_value < 100)
+ if (year_value < 100) {
+ base::Time::Exploded now;
+ base::Time::Now().LocalExplode(&now);
year_value += (now.year / 100) * 100;
+ }
- if (year_value < now.year)
- return false;
-
- if (year_value > now.year)
- return true;
-
- return month_value >= now.month;
+ return IsValidCreditCardExpirationDate(year_value, month_value,
+ base::Time::Now());
}
base::TimeDelta CardUnmaskPromptControllerImpl::GetSuccessMessageDuration()
diff --git a/chromium/components/autofill/core/browser/ui/card_unmask_prompt_view.h b/chromium/components/autofill/core/browser/ui/card_unmask_prompt_view.h
index dbedeab35a2..a234739f1c5 100644
--- a/chromium/components/autofill/core/browser/ui/card_unmask_prompt_view.h
+++ b/chromium/components/autofill/core/browser/ui/card_unmask_prompt_view.h
@@ -10,8 +10,6 @@
namespace autofill {
-class CardUnmaskPromptController;
-
// The cross-platform UI interface which prompts the user to unlock a masked
// Wallet instrument (credit card). This object is responsible for its own
// lifetime.
diff --git a/chromium/components/autofill/core/browser/validation.cc b/chromium/components/autofill/core/browser/validation.cc
index b0f0a2a72bc..15a96e6ab22 100644
--- a/chromium/components/autofill/core/browser/validation.cc
+++ b/chromium/components/autofill/core/browser/validation.cc
@@ -43,6 +43,7 @@ bool IsValidCreditCardNumber(const base::string16& text) {
// defined sizes.
// [1] http://www.merriampark.com/anatomycc.htm
// [2] http://en.wikipedia.org/wiki/Bank_card_number
+ // CardEditor.isCardNumberLengthMaxium() needs to be kept in sync.
const char* const type = CreditCard::GetCreditCardType(text);
if (type == kAmericanExpressCard && number.size() != 15)
return false;
@@ -54,6 +55,8 @@ bool IsValidCreditCardNumber(const base::string16& text) {
return false;
if (type == kMasterCard && number.size() != 16)
return false;
+ if (type == kMirCard && number.size() != 16)
+ return false;
if (type == kUnionPay && (number.size() < 16 || number.size() > 19))
return false;
if (type == kVisaCard && number.size() != 13 && number.size() != 16)
@@ -84,25 +87,11 @@ bool IsValidCreditCardNumber(const base::string16& text) {
return (sum % 10) == 0;
}
-bool IsValidCreditCardSecurityCode(const base::string16& text) {
- if (text.size() < 3U || text.size() > 4U)
- return false;
-
- for (const base::char16& it : text) {
- if (!base::IsAsciiDigit(it))
- return false;
- }
- return true;
-}
-
bool IsValidCreditCardSecurityCode(const base::string16& code,
- const base::string16& number) {
- const char* const type = CreditCard::GetCreditCardType(number);
- size_t required_length = 3;
- if (type == kAmericanExpressCard)
- required_length = 4;
-
- return code.length() == required_length;
+ const base::StringPiece card_type) {
+ size_t required_length = card_type == kAmericanExpressCard ? 4 : 3;
+ return code.length() == required_length &&
+ base::ContainsOnlyChars(code, base::ASCIIToUTF16("0123456789"));
}
bool IsValidEmailAddress(const base::string16& text) {
diff --git a/chromium/components/autofill/core/browser/validation.h b/chromium/components/autofill/core/browser/validation.h
index aaaedcd23b8..a09ae75cbb3 100644
--- a/chromium/components/autofill/core/browser/validation.h
+++ b/chromium/components/autofill/core/browser/validation.h
@@ -6,6 +6,7 @@
#define COMPONENTS_AUTOFILL_CORE_BROWSER_VALIDATION_H_
#include "base/strings/string16.h"
+#include "base/strings/string_piece.h"
namespace base {
class Time;
@@ -23,13 +24,10 @@ bool IsValidCreditCardExpirationDate(int year,
// Uses the Luhn formula to validate the number.
bool IsValidCreditCardNumber(const base::string16& text);
-// Returns true if |text| looks like a valid credit card security code.
-bool IsValidCreditCardSecurityCode(const base::string16& text);
-
// Returns true if |code| looks like a valid credit card security code
-// for the type of credit card designated by |number|.
+// for the given credit card type.
bool IsValidCreditCardSecurityCode(const base::string16& code,
- const base::string16& number);
+ const base::StringPiece card_type);
// Returns true if |text| looks like a valid e-mail address.
bool IsValidEmailAddress(const base::string16& text);
diff --git a/chromium/components/autofill/core/browser/validation_unittest.cc b/chromium/components/autofill/core/browser/validation_unittest.cc
index c7b880b0a17..798f53462bd 100644
--- a/chromium/components/autofill/core/browser/validation_unittest.cc
+++ b/chromium/components/autofill/core/browser/validation_unittest.cc
@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
+#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/validation.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -25,6 +26,11 @@ struct IntExpirationDate {
const int month;
};
+struct SecurityCodeCardTypePair {
+ const char* security_code;
+ const char* card_type;
+};
+
// From https://www.paypalobjects.com/en_US/vhelp/paypalmanager_help/credit_card_numbers.htm
const char* const kValidNumbers[] = {
"378282246310005",
@@ -64,14 +70,16 @@ const IntExpirationDate kInvalidCreditCardIntExpirationDate[] = {
{ 2015, 13 }, // Not a real month.
{ 2015, 0 }, // Zero is legal in the CC class but is not a valid date.
};
-const char* const kValidCreditCardSecurityCode[] = {
- "323", // 3-digit CSC.
- "3234", // 4-digit CSC.
+const SecurityCodeCardTypePair kValidSecurityCodeCardTypePairs[] = {
+ { "323", kGenericCard }, // 3-digit CSC.
+ { "3234", kAmericanExpressCard }, // 4-digit CSC.
};
-const char* const kInvalidCreditCardSecurityCode[] = {
- "32", // CSC too short.
- "12345", // CSC too long.
- "asd", // non-numeric CSC.
+const SecurityCodeCardTypePair kInvalidSecurityCodeCardTypePairs[] = {
+ { "32", kGenericCard }, // CSC too short.
+ { "323", kAmericanExpressCard }, // CSC too short.
+ { "3234", kGenericCard }, // CSC too long.
+ { "12345", kAmericanExpressCard }, // CSC too long.
+ { "asd", kGenericCard }, // non-numeric CSC.
};
const char* const kValidEmailAddress[] = {
"user@example",
@@ -85,10 +93,6 @@ const char* const kInvalidEmailAddress[] = {
"user@",
"user@=example.com"
};
-const char kAmericanExpressCard[] = "341111111111111";
-const char kVisaCard[] = "4111111111111111";
-const char kAmericanExpressCVC[] = "1234";
-const char kVisaCVC[] = "123";
} // namespace
TEST(AutofillValidation, IsValidCreditCardNumber) {
@@ -117,14 +121,19 @@ TEST(AutofillValidation, IsValidCreditCardIntExpirationDate) {
EXPECT_TRUE(!IsValidCreditCardExpirationDate(data.year, data.month, now));
}
}
+
TEST(AutofillValidation, IsValidCreditCardSecurityCode) {
- for (const char* valid_code : kValidCreditCardSecurityCode) {
- SCOPED_TRACE(valid_code);
- EXPECT_TRUE(IsValidCreditCardSecurityCode(ASCIIToUTF16(valid_code)));
+ for (const auto data : kValidSecurityCodeCardTypePairs) {
+ SCOPED_TRACE(data.security_code);
+ SCOPED_TRACE(data.card_type);
+ EXPECT_TRUE(IsValidCreditCardSecurityCode(ASCIIToUTF16(data.security_code),
+ data.card_type));
}
- for (const char* invalid_code : kInvalidCreditCardSecurityCode) {
- SCOPED_TRACE(invalid_code);
- EXPECT_FALSE(IsValidCreditCardSecurityCode(ASCIIToUTF16(invalid_code)));
+ for (const auto data : kInvalidSecurityCodeCardTypePairs) {
+ SCOPED_TRACE(data.security_code);
+ SCOPED_TRACE(data.card_type);
+ EXPECT_FALSE(IsValidCreditCardSecurityCode(ASCIIToUTF16(data.security_code),
+ data.card_type));
}
}
@@ -139,19 +148,4 @@ TEST(AutofillValidation, IsValidEmailAddress) {
}
}
-TEST(AutofillValidation, IsValidCreditCardSecurityCodeWithNumber) {
- EXPECT_TRUE(IsValidCreditCardSecurityCode(
- ASCIIToUTF16(kAmericanExpressCVC), ASCIIToUTF16(kAmericanExpressCard)));
- EXPECT_TRUE(IsValidCreditCardSecurityCode(
- ASCIIToUTF16(kVisaCVC), ASCIIToUTF16(kVisaCard)));
- EXPECT_FALSE(IsValidCreditCardSecurityCode(
- ASCIIToUTF16(kVisaCVC), ASCIIToUTF16(kAmericanExpressCard)));
- EXPECT_FALSE(IsValidCreditCardSecurityCode(
- ASCIIToUTF16(kAmericanExpressCVC), ASCIIToUTF16(kVisaCard)));
- EXPECT_TRUE(IsValidCreditCardSecurityCode(
- ASCIIToUTF16(kVisaCVC), ASCIIToUTF16(kInvalidNumbers[0])));
- EXPECT_FALSE(IsValidCreditCardSecurityCode(
- ASCIIToUTF16(kAmericanExpressCVC), ASCIIToUTF16(kInvalidNumbers[0])));
-}
-
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc
new file mode 100644
index 00000000000..0bf47d314ba
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc
@@ -0,0 +1,477 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/webdata/autocomplete_sync_bridge.h"
+
+#include <algorithm>
+#include <set>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/debug/dump_without_crashing.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/proto/autofill_sync.pb.h"
+#include "components/autofill/core/browser/webdata/autofill_metadata_change_list.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.h"
+#include "components/sync/model/entity_data.h"
+#include "components/sync/model/model_type_change_processor.h"
+#include "components/sync/model/mutable_data_batch.h"
+#include "net/base/escape.h"
+
+using base::Optional;
+using base::Time;
+using base::debug::DumpWithoutCrashing;
+using sync_pb::AutofillSpecifics;
+using syncer::EntityChange;
+using syncer::EntityChangeList;
+using syncer::EntityData;
+using syncer::EntityDataMap;
+using syncer::MetadataChangeList;
+using syncer::ModelError;
+using syncer::ModelTypeChangeProcessor;
+using syncer::MutableDataBatch;
+
+namespace autofill {
+
+namespace {
+
+const char kAutocompleteEntryNamespaceTag[] = "autofill_entry|";
+const char kAutocompleteTagDelimiter[] = "|";
+
+// Simplify checking for optional errors and returning only when present.
+#define RETURN_IF_ERROR(x) \
+ if (Optional<ModelError> ret_val = x) { \
+ return ret_val; \
+ }
+
+void* UserDataKey() {
+ // Use the address of a static that COMDAT folding won't ever collide
+ // with something else.
+ static int user_data_key = 0;
+ return reinterpret_cast<void*>(&user_data_key);
+}
+
+std::unique_ptr<EntityData> CreateEntityData(const AutofillEntry& entry) {
+ auto entity_data = base::MakeUnique<EntityData>();
+ entity_data->non_unique_name = base::UTF16ToUTF8(entry.key().name());
+ AutofillSpecifics* autofill = entity_data->specifics.mutable_autofill();
+ autofill->set_name(base::UTF16ToUTF8(entry.key().name()));
+ autofill->set_value(base::UTF16ToUTF8(entry.key().value()));
+ autofill->add_usage_timestamp(entry.date_created().ToInternalValue());
+ if (entry.date_created() != entry.date_last_used())
+ autofill->add_usage_timestamp(entry.date_last_used().ToInternalValue());
+ return entity_data;
+}
+
+std::string BuildSerializedStorageKey(const std::string& name,
+ const std::string& value) {
+ AutofillSyncStorageKey proto;
+ proto.set_name(name);
+ proto.set_value(value);
+ return proto.SerializeAsString();
+}
+
+std::string GetStorageKeyFromModel(const AutofillKey& key) {
+ return BuildSerializedStorageKey(base::UTF16ToUTF8(key.name()),
+ base::UTF16ToUTF8(key.value()));
+}
+
+AutofillEntry MergeEntryDates(const AutofillEntry& entry1,
+ const AutofillEntry& entry2) {
+ DCHECK(entry1.key() == entry2.key());
+ return AutofillEntry(
+ entry1.key(), std::min(entry1.date_created(), entry2.date_created()),
+ std::max(entry1.date_last_used(), entry2.date_last_used()));
+}
+
+bool ParseStorageKey(const std::string& storage_key, AutofillKey* out_key) {
+ AutofillSyncStorageKey proto;
+ if (proto.ParseFromString(storage_key)) {
+ *out_key = AutofillKey(base::UTF8ToUTF16(proto.name()),
+ base::UTF8ToUTF16((proto.value())));
+ return true;
+ } else {
+ return false;
+ }
+}
+
+AutofillEntry CreateAutofillEntry(const AutofillSpecifics& autofill_specifics) {
+ AutofillKey key(base::UTF8ToUTF16(autofill_specifics.name()),
+ base::UTF8ToUTF16(autofill_specifics.value()));
+ Time date_created, date_last_used;
+ const google::protobuf::RepeatedField<int64_t>& timestamps =
+ autofill_specifics.usage_timestamp();
+ if (!timestamps.empty()) {
+ auto iter_pair = std::minmax_element(timestamps.begin(), timestamps.end());
+ date_created = Time::FromInternalValue(*iter_pair.first);
+ date_last_used = Time::FromInternalValue(*iter_pair.second);
+ }
+ return AutofillEntry(key, date_created, date_last_used);
+}
+
+// This is used to respond to ApplySyncChanges() and MergeSyncData(). Attempts
+// to lazily load local data, and then react to sync data by maintaining
+// internal state until flush calls are made, at which point the applicable
+// modification should be sent towards local and sync directions.
+class SyncDifferenceTracker {
+ public:
+ explicit SyncDifferenceTracker(AutofillTable* table) : table_(table) {}
+
+ Optional<ModelError> IncorporateRemoteSpecifics(
+ const std::string& storage_key,
+ const AutofillSpecifics& specifics) {
+ if (!specifics.has_value()) {
+ // A long time ago autofill had a different format, and it's possible we
+ // could encounter some of that legacy data. It is not useful to us,
+ // because an autofill entry with no value will not place any text in a
+ // form for the user. So drop all of these on the floor.
+ DVLOG(1) << "Dropping old-style autofill profile change.";
+ return {};
+ }
+
+ const AutofillEntry remote = CreateAutofillEntry(specifics);
+ DCHECK_EQ(storage_key, GetStorageKeyFromModel(remote.key()));
+
+ Optional<AutofillEntry> local;
+ if (!ReadEntry(remote.key(), &local)) {
+ return ModelError(FROM_HERE, "Failed reading from WebDatabase.");
+ } else if (!local) {
+ save_to_local_.push_back(remote);
+ } else if (remote != local.value()) {
+ if (specifics.usage_timestamp().empty()) {
+ // Skip merging if there are no timestamps. We don't want to wipe out
+ // a local value of |date_created| if the remote copy is oddly formed.
+ save_to_sync_.push_back(local.value());
+ } else {
+ const AutofillEntry merged = MergeEntryDates(local.value(), remote);
+ save_to_local_.push_back(merged);
+ save_to_sync_.push_back(merged);
+ }
+ unique_to_local_.erase(local.value());
+ }
+ return {};
+ }
+
+ Optional<ModelError> IncorporateRemoteDelete(const std::string& storage_key) {
+ AutofillKey key;
+ if (!ParseStorageKey(storage_key, &key)) {
+ return ModelError(FROM_HERE, "Failed parsing storage key.");
+ }
+ delete_from_local_.insert(key);
+ return {};
+ }
+
+ Optional<ModelError> FlushToLocal(AutofillWebDataBackend* web_data_backend) {
+ for (const AutofillKey& key : delete_from_local_) {
+ if (!table_->RemoveFormElement(key.name(), key.value())) {
+ return ModelError(FROM_HERE, "Failed deleting from WebDatabase");
+ }
+ }
+ if (!table_->UpdateAutofillEntries(save_to_local_)) {
+ return ModelError(FROM_HERE, "Failed updating WebDatabase");
+ }
+ if (!delete_from_local_.empty() || !save_to_local_.empty()) {
+ web_data_backend->NotifyOfMultipleAutofillChanges();
+ }
+ return {};
+ }
+
+ Optional<ModelError> FlushToSync(
+ bool include_local_only,
+ std::unique_ptr<MetadataChangeList> metadata_change_list,
+ ModelTypeChangeProcessor* change_processor) {
+ for (const AutofillEntry& entry : save_to_sync_) {
+ change_processor->Put(GetStorageKeyFromModel(entry.key()),
+ CreateEntityData(entry),
+ metadata_change_list.get());
+ }
+ if (include_local_only) {
+ if (!InitializeIfNeeded()) {
+ return ModelError(FROM_HERE, "Failed reading from WebDatabase.");
+ }
+ for (const AutofillEntry& entry : unique_to_local_) {
+ // This should never be true because only ApplySyncChanges should be
+ // calling IncorporateRemoteDelete, while only MergeSyncData should be
+ // passing in true for |include_local_only|. If this requirement
+ // changes, this DCHECK can change to act as a filter.
+ DCHECK(delete_from_local_.find(entry.key()) ==
+ delete_from_local_.end());
+ change_processor->Put(GetStorageKeyFromModel(entry.key()),
+ CreateEntityData(entry),
+ metadata_change_list.get());
+ }
+ }
+ return static_cast<AutofillMetadataChangeList*>(metadata_change_list.get())
+ ->TakeError();
+ }
+
+ private:
+ // There are three major outcomes of this method.
+ // 1. An error is encountered reading from the db, false is returned.
+ // 2. The entry is not found, |entry| will not be touched.
+ // 3. The entry is found, |entry| will be set.
+ bool ReadEntry(const AutofillKey& key, Optional<AutofillEntry>* entry) {
+ if (!InitializeIfNeeded()) {
+ return false;
+ }
+ auto iter = unique_to_local_.find(AutofillEntry(key, Time(), Time()));
+ if (iter != unique_to_local_.end()) {
+ *entry = *iter;
+ }
+ return true;
+ }
+
+ bool InitializeIfNeeded() {
+ if (initialized_) {
+ return true;
+ }
+
+ std::vector<AutofillEntry> vector;
+ if (!table_->GetAllAutofillEntries(&vector)) {
+ return false;
+ }
+
+ unique_to_local_ = std::set<AutofillEntry>(vector.begin(), vector.end());
+ initialized_ = true;
+ return true;
+ }
+
+ AutofillTable* table_;
+
+ // This class attempts to lazily load data from |table_|. This field tracks
+ // if that has happened or not yet. To facilitate this, the first usage of
+ // |unique_to_local_| should typically be done through ReadEntry().
+ bool initialized_ = false;
+
+ // Important to note that because AutofillEntry's operator < simply compares
+ // contained AutofillKeys, this acts as a map<AutofillKey, AutofillEntry>.
+ // Shouldn't be accessed until either ReadEntry() or InitializeIfNeeded() is
+ // called, afterward it will start with all the local data. As sync data is
+ // encountered entries are removed from here, leaving only entries that exist
+ // solely on the local client.
+ std::set<AutofillEntry> unique_to_local_;
+
+ std::set<AutofillKey> delete_from_local_;
+ std::vector<AutofillEntry> save_to_local_;
+
+ // Contains merged data for entries that existed on both sync and local sides
+ // and need to be saved back to sync.
+ std::vector<AutofillEntry> save_to_sync_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyncDifferenceTracker);
+};
+
+} // namespace
+
+// static
+void AutocompleteSyncBridge::CreateForWebDataServiceAndBackend(
+ AutofillWebDataService* web_data_service,
+ AutofillWebDataBackend* web_data_backend) {
+ web_data_service->GetDBUserData()->SetUserData(
+ UserDataKey(),
+ new AutocompleteSyncBridge(
+ web_data_backend,
+ base::BindRepeating(
+ &ModelTypeChangeProcessor::Create,
+ base::BindRepeating(base::IgnoreResult(&DumpWithoutCrashing)))));
+}
+
+// static
+AutocompleteSyncBridge* AutocompleteSyncBridge::FromWebDataService(
+ AutofillWebDataService* web_data_service) {
+ return static_cast<AutocompleteSyncBridge*>(
+ web_data_service->GetDBUserData()->GetUserData(UserDataKey()));
+}
+
+AutocompleteSyncBridge::AutocompleteSyncBridge(
+ AutofillWebDataBackend* backend,
+ const ChangeProcessorFactory& change_processor_factory)
+ : ModelTypeSyncBridge(change_processor_factory, syncer::AUTOFILL),
+ web_data_backend_(backend),
+ scoped_observer_(this) {
+ DCHECK(web_data_backend_);
+
+ scoped_observer_.Add(web_data_backend_);
+
+ LoadMetadata();
+}
+
+AutocompleteSyncBridge::~AutocompleteSyncBridge() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+std::unique_ptr<MetadataChangeList>
+AutocompleteSyncBridge::CreateMetadataChangeList() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return base::MakeUnique<AutofillMetadataChangeList>(GetAutofillTable(),
+ syncer::AUTOFILL);
+}
+
+Optional<syncer::ModelError> AutocompleteSyncBridge::MergeSyncData(
+ std::unique_ptr<MetadataChangeList> metadata_change_list,
+ EntityDataMap entity_data_map) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // TODO(skym, crbug.com/680218): Uncomment and add unit tests.
+ /*SyncDifferenceTracker tracker(GetAutofillTable());
+ for (auto kv : entity_data_map) {
+ DCHECK(kv.second->specifics.has_autofill());
+ RETURN_IF_ERROR(tracker.IncorporateRemoteSpecifics(
+ kv.first, kv.second->specifics.autofill()));
+ }
+
+ RETURN_IF_ERROR(tracker.FlushToLocal(web_data_backend_));
+ RETURN_IF_ERROR(tracker.FlushToSync(true, std::move(metadata_change_list),
+ change_processor()));
+ web_data_backend_->RemoveExpiredFormElements();
+ web_data_backend_->NotifyThatSyncHasStarted(syncer::AUTOFILL);*/
+ return {};
+}
+
+Optional<ModelError> AutocompleteSyncBridge::ApplySyncChanges(
+ std::unique_ptr<MetadataChangeList> metadata_change_list,
+ EntityChangeList entity_changes) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ SyncDifferenceTracker tracker(GetAutofillTable());
+ for (const EntityChange& change : entity_changes) {
+ if (change.type() == EntityChange::ACTION_DELETE) {
+ RETURN_IF_ERROR(tracker.IncorporateRemoteDelete(change.storage_key()));
+ } else {
+ DCHECK(change.data().specifics.has_autofill());
+ RETURN_IF_ERROR(tracker.IncorporateRemoteSpecifics(
+ change.storage_key(), change.data().specifics.autofill()));
+ }
+ }
+
+ RETURN_IF_ERROR(tracker.FlushToLocal(web_data_backend_));
+ RETURN_IF_ERROR(tracker.FlushToSync(false, std::move(metadata_change_list),
+ change_processor()));
+ web_data_backend_->RemoveExpiredFormElements();
+ return {};
+}
+
+void AutocompleteSyncBridge::AutocompleteSyncBridge::GetData(
+ StorageKeyList storage_keys,
+ DataCallback callback) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ std::vector<AutofillEntry> entries;
+ if (!GetAutofillTable()->GetAllAutofillEntries(&entries)) {
+ change_processor()->ReportError(FROM_HERE,
+ "Failed to load entries from table.");
+ return;
+ }
+
+ std::unordered_set<std::string> keys_set(storage_keys.begin(),
+ storage_keys.end());
+ auto batch = base::MakeUnique<MutableDataBatch>();
+ for (const AutofillEntry& entry : entries) {
+ std::string key = GetStorageKeyFromModel(entry.key());
+ if (keys_set.find(key) != keys_set.end()) {
+ batch->Put(key, CreateEntityData(entry));
+ }
+ }
+ callback.Run(std::move(batch));
+}
+
+void AutocompleteSyncBridge::GetAllData(DataCallback callback) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ std::vector<AutofillEntry> entries;
+ if (!GetAutofillTable()->GetAllAutofillEntries(&entries)) {
+ change_processor()->ReportError(FROM_HERE,
+ "Failed to load entries from table.");
+ return;
+ }
+
+ auto batch = base::MakeUnique<MutableDataBatch>();
+ for (const AutofillEntry& entry : entries) {
+ batch->Put(GetStorageKeyFromModel(entry.key()), CreateEntityData(entry));
+ }
+ callback.Run(std::move(batch));
+}
+
+void AutocompleteSyncBridge::ActOnLocalChanges(
+ const AutofillChangeList& changes) {
+ if (!change_processor()->IsTrackingMetadata()) {
+ return;
+ }
+
+ auto metadata_change_list = base::MakeUnique<AutofillMetadataChangeList>(
+ GetAutofillTable(), syncer::AUTOFILL);
+ for (const auto& change : changes) {
+ const std::string storage_key = GetStorageKeyFromModel(change.key());
+ switch (change.type()) {
+ case AutofillChange::ADD:
+ case AutofillChange::UPDATE: {
+ base::Time date_created, date_last_used;
+ bool success = GetAutofillTable()->GetAutofillTimestamps(
+ change.key().name(), change.key().value(), &date_created,
+ &date_last_used);
+ if (!success) {
+ change_processor()->ReportError(
+ FROM_HERE, "Failed reading autofill entry from WebDatabase.");
+ return;
+ }
+
+ const AutofillEntry entry(change.key(), date_created, date_last_used);
+ change_processor()->Put(storage_key, CreateEntityData(entry),
+ metadata_change_list.get());
+ break;
+ }
+ case AutofillChange::REMOVE: {
+ change_processor()->Delete(storage_key, metadata_change_list.get());
+ break;
+ }
+ }
+ }
+
+ if (Optional<ModelError> error = metadata_change_list->TakeError())
+ change_processor()->ReportError(error.value());
+}
+
+void AutocompleteSyncBridge::LoadMetadata() {
+ auto batch = base::MakeUnique<syncer::MetadataBatch>();
+ if (!GetAutofillTable()->GetAllSyncMetadata(syncer::AUTOFILL, batch.get())) {
+ change_processor()->ReportError(
+ FROM_HERE, "Failed reading autofill metadata from WebDatabase.");
+ return;
+ }
+ change_processor()->ModelReadyToSync(std::move(batch));
+}
+
+std::string AutocompleteSyncBridge::GetClientTag(
+ const EntityData& entity_data) {
+ DCHECK(entity_data.specifics.has_autofill());
+ const AutofillSpecifics specifics = entity_data.specifics.autofill();
+ return std::string(kAutocompleteEntryNamespaceTag) +
+ net::EscapePath(specifics.name()) +
+ std::string(kAutocompleteTagDelimiter) +
+ net::EscapePath(specifics.value());
+}
+
+std::string AutocompleteSyncBridge::GetStorageKey(
+ const EntityData& entity_data) {
+ DCHECK(entity_data.specifics.has_autofill());
+ const AutofillSpecifics specifics = entity_data.specifics.autofill();
+ return BuildSerializedStorageKey(specifics.name(), specifics.value());
+}
+
+// AutofillWebDataServiceObserverOnDBThread implementation.
+void AutocompleteSyncBridge::AutofillEntriesChanged(
+ const AutofillChangeList& changes) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ ActOnLocalChanges(changes);
+}
+
+AutofillTable* AutocompleteSyncBridge::GetAutofillTable() const {
+ return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase());
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h
new file mode 100644
index 00000000000..cd350bec322
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h
@@ -0,0 +1,95 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOCOMPLETE_SYNC_BRIDGE_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOCOMPLETE_SYNC_BRIDGE_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "base/optional.h"
+#include "base/scoped_observer.h"
+#include "base/supports_user_data.h"
+#include "base/threading/non_thread_safe.h"
+#include "components/autofill/core/browser/webdata/autofill_change.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h"
+#include "components/sync/model/metadata_change_list.h"
+#include "components/sync/model/model_error.h"
+#include "components/sync/model/model_type_sync_bridge.h"
+
+namespace autofill {
+
+class AutofillTable;
+class AutofillWebDataBackend;
+class AutofillWebDataService;
+
+class AutocompleteSyncBridge : public base::SupportsUserData::Data,
+ public syncer::ModelTypeSyncBridge,
+ public AutofillWebDataServiceObserverOnDBThread {
+ public:
+ AutocompleteSyncBridge();
+ AutocompleteSyncBridge(
+ AutofillWebDataBackend* backend,
+ const ChangeProcessorFactory& change_processor_factory);
+ ~AutocompleteSyncBridge() override;
+
+ static void CreateForWebDataServiceAndBackend(
+ AutofillWebDataService* web_data_service,
+ AutofillWebDataBackend* web_data_backend);
+
+ static AutocompleteSyncBridge* FromWebDataService(
+ AutofillWebDataService* web_data_service);
+
+ // syncer::ModelTypeSyncBridge implementation.
+ std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
+ override;
+ base::Optional<syncer::ModelError> MergeSyncData(
+ std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+ syncer::EntityDataMap entity_data_map) override;
+ base::Optional<syncer::ModelError> ApplySyncChanges(
+ std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+ syncer::EntityChangeList entity_changes) override;
+ void GetData(StorageKeyList storage_keys, DataCallback callback) override;
+ void GetAllData(DataCallback callback) override;
+ // Generate a tag that uniquely identifies |entity_data| across all data
+ // types. This is used to identify the entity on the server. The format, which
+ // must remain the same for server compatibility, is:
+ // "autofill_entry|$name|$value" where $name and $value are escaped.
+ std::string GetClientTag(const syncer::EntityData& entity_data) override;
+ // Generate a string key uniquely identifying |entity_data| in the context of
+ // local storage. The format, which should stay the same, is $name|$value"
+ // where $name and $value are escaped.
+ std::string GetStorageKey(const syncer::EntityData& entity_data) override;
+
+ // AutofillWebDataServiceObserverOnDBThread implementation.
+ void AutofillEntriesChanged(const AutofillChangeList& changes) override;
+
+ private:
+ // Returns the table associated with the |web_data_backend_|.
+ AutofillTable* GetAutofillTable() const;
+
+ // Respond to local autofill entries changing by notifying sync of the
+ // changes.
+ void ActOnLocalChanges(const AutofillChangeList& changes);
+
+ // Synchronously load sync metadata from the autofill table and pass it to the
+ // processor so that it can start tracking changes.
+ void LoadMetadata();
+
+ base::ThreadChecker thread_checker_;
+
+ // AutocompleteSyncBridge is owned by |web_data_backend_| through
+ // SupportsUserData, so it's guaranteed to outlive |this|.
+ AutofillWebDataBackend* const web_data_backend_;
+
+ ScopedObserver<AutofillWebDataBackend, AutocompleteSyncBridge>
+ scoped_observer_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutocompleteSyncBridge);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOCOMPLETE_SYNC_BRIDGE_H_
diff --git a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc
new file mode 100644
index 00000000000..b12d0ef223f
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc
@@ -0,0 +1,524 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/webdata/autocomplete_sync_bridge.h"
+
+#include <algorithm>
+#include <map>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "components/autofill/core/browser/webdata/autofill_entry.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_backend_impl.h"
+#include "components/sync/model/data_batch.h"
+#include "components/sync/model/metadata_batch.h"
+#include "components/sync/model/model_error.h"
+#include "components/sync/model/recording_model_type_change_processor.h"
+#include "components/webdata/common/web_database.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::UTF8ToUTF16;
+using base::ScopedTempDir;
+using base::Time;
+using base::TimeDelta;
+using sync_pb::AutofillSpecifics;
+using sync_pb::EntitySpecifics;
+using syncer::DataBatch;
+using syncer::EntityData;
+using syncer::EntityDataPtr;
+using syncer::EntityChange;
+using syncer::EntityChangeList;
+using syncer::FakeModelTypeChangeProcessor;
+using syncer::KeyAndData;
+using syncer::ModelError;
+using syncer::ModelType;
+using syncer::ModelTypeChangeProcessor;
+using syncer::ModelTypeSyncBridge;
+
+namespace autofill {
+
+namespace {
+
+const char kNameFormat[] = "name %d";
+const char kValueFormat[] = "value %d";
+
+void VerifyEqual(const AutofillSpecifics& s1, const AutofillSpecifics& s2) {
+ // Instead of just comparing serialized strings, manually check fields to show
+ // differences on failure.
+ EXPECT_EQ(s1.name(), s2.name());
+ EXPECT_EQ(s1.value(), s2.value());
+ EXPECT_EQ(s1.usage_timestamp().size(), s2.usage_timestamp().size());
+ int size = std::min(s1.usage_timestamp().size(), s2.usage_timestamp().size());
+ for (int i = 0; i < size; ++i) {
+ EXPECT_EQ(s1.usage_timestamp(i), s2.usage_timestamp(i))
+ << "Values differ at index " << i;
+ }
+ // Neither should have any profile data, so we don't have to compare it.
+ EXPECT_FALSE(s1.has_profile());
+ EXPECT_FALSE(s2.has_profile());
+}
+
+void VerifyDataBatch(std::map<std::string, AutofillSpecifics> expected,
+ std::unique_ptr<DataBatch> batch) {
+ while (batch->HasNext()) {
+ const KeyAndData& pair = batch->Next();
+ auto iter = expected.find(pair.first);
+ ASSERT_NE(iter, expected.end());
+ VerifyEqual(iter->second, pair.second->specifics.autofill());
+ // Removing allows us to verify we don't see the same item multiple times,
+ // and that we saw everything we expected.
+ expected.erase(iter);
+ }
+ EXPECT_TRUE(expected.empty());
+}
+
+AutofillEntry CreateAutofillEntry(const AutofillSpecifics& autofill_specifics) {
+ AutofillKey key(UTF8ToUTF16(autofill_specifics.name()),
+ UTF8ToUTF16(autofill_specifics.value()));
+ Time date_created, date_last_used;
+ const google::protobuf::RepeatedField<int64_t>& timestamps =
+ autofill_specifics.usage_timestamp();
+ if (!timestamps.empty()) {
+ date_created = Time::FromInternalValue(*timestamps.begin());
+ date_last_used = Time::FromInternalValue(*timestamps.rbegin());
+ }
+ return AutofillEntry(key, date_created, date_last_used);
+}
+
+EntityDataPtr SpecificsToEntity(const AutofillSpecifics& specifics) {
+ EntityData data;
+ data.client_tag_hash = "ignored";
+ *data.specifics.mutable_autofill() = specifics;
+ return data.PassToPtr();
+}
+
+class FakeAutofillBackend : public AutofillWebDataBackend {
+ public:
+ FakeAutofillBackend() {}
+ ~FakeAutofillBackend() override {}
+ WebDatabase* GetDatabase() override { return db_; }
+ void AddObserver(
+ autofill::AutofillWebDataServiceObserverOnDBThread* observer) override {}
+ void RemoveObserver(
+ autofill::AutofillWebDataServiceObserverOnDBThread* observer) override {}
+ void RemoveExpiredFormElements() override {}
+ void NotifyOfMultipleAutofillChanges() override {}
+ void NotifyThatSyncHasStarted(ModelType model_type) override {}
+ void SetWebDatabase(WebDatabase* db) { db_ = db; }
+
+ private:
+ WebDatabase* db_;
+};
+
+} // namespace
+
+class AutocompleteSyncBridgeTest : public testing::Test {
+ public:
+ AutocompleteSyncBridgeTest() {
+ if (temp_dir_.CreateUniqueTempDir()) {
+ db_.AddTable(&table_);
+ db_.Init(temp_dir_.GetPath().AppendASCII("SyncTestWebDatabase"));
+ backend_.SetWebDatabase(&db_);
+
+ sync_pb::ModelTypeState model_type_state;
+ model_type_state.set_initial_sync_done(true);
+ table_.UpdateModelTypeState(syncer::AUTOFILL, model_type_state);
+
+ bridge_.reset(new AutocompleteSyncBridge(
+ &backend_,
+ base::Bind(
+ &AutocompleteSyncBridgeTest::CreateModelTypeChangeProcessor,
+ base::Unretained(this))));
+ }
+ }
+ ~AutocompleteSyncBridgeTest() override {}
+
+ void SaveSpecificsToTable(
+ const std::vector<AutofillSpecifics>& specifics_list) {
+ std::vector<AutofillEntry> new_entries;
+ for (const auto& specifics : specifics_list) {
+ new_entries.push_back(CreateAutofillEntry(specifics));
+ }
+ table_.UpdateAutofillEntries(new_entries);
+ }
+
+ AutofillSpecifics CreateSpecifics(const std::string& name,
+ const std::string& value,
+ const std::vector<int>& timestamps) {
+ AutofillSpecifics specifics;
+ specifics.set_name(name);
+ specifics.set_value(value);
+ for (int timestamp : timestamps) {
+ specifics.add_usage_timestamp(
+ Time::FromTimeT(timestamp).ToInternalValue());
+ }
+ return specifics;
+ }
+
+ AutofillSpecifics CreateSpecifics(int suffix,
+ const std::vector<int>& timestamps) {
+ return CreateSpecifics(base::StringPrintf(kNameFormat, suffix),
+ base::StringPrintf(kValueFormat, suffix),
+ timestamps);
+ }
+
+ AutofillSpecifics CreateSpecifics(int suffix) {
+ return CreateSpecifics(suffix, std::vector<int>{0});
+ }
+
+ std::string GetStorageKey(const AutofillSpecifics& specifics) {
+ std::string key =
+ bridge()->GetStorageKey(SpecificsToEntity(specifics).value());
+ EXPECT_FALSE(key.empty());
+ return key;
+ }
+
+ EntityChangeList EntityAddList(
+ const std::vector<AutofillSpecifics>& specifics_vector) {
+ EntityChangeList changes;
+ for (const auto& specifics : specifics_vector) {
+ changes.push_back(EntityChange::CreateAdd(GetStorageKey(specifics),
+ SpecificsToEntity(specifics)));
+ }
+ return changes;
+ }
+
+ void VerifyApplyChanges(const std::vector<EntityChange>& changes) {
+ const auto error = bridge()->ApplySyncChanges(
+ bridge()->CreateMetadataChangeList(), changes);
+ EXPECT_FALSE(error);
+ }
+
+ void VerifyApplyAdds(const std::vector<AutofillSpecifics>& specifics) {
+ VerifyApplyChanges(EntityAddList(specifics));
+ }
+
+ std::map<std::string, AutofillSpecifics> ExpectedMap(
+ const std::vector<AutofillSpecifics>& specifics_vector) {
+ std::map<std::string, AutofillSpecifics> map;
+ for (const auto& specifics : specifics_vector) {
+ map[GetStorageKey(specifics)] = specifics;
+ }
+ return map;
+ }
+
+ void VerifyAllData(const std::vector<AutofillSpecifics>& expected) {
+ bridge()->GetAllData(base::Bind(&VerifyDataBatch, ExpectedMap(expected)));
+ }
+
+ void VerifyProcessorRecordedPut(const AutofillSpecifics& specifics,
+ int position = 0) {
+ const std::string storage_key = GetStorageKey(specifics);
+ auto recorded_specifics_iterator =
+ processor()->put_multimap().find(storage_key);
+
+ EXPECT_NE(processor()->put_multimap().end(), recorded_specifics_iterator);
+ while (position > 0) {
+ recorded_specifics_iterator++;
+ EXPECT_NE(processor()->put_multimap().end(), recorded_specifics_iterator);
+ position--;
+ }
+
+ AutofillSpecifics recorded_specifics =
+ recorded_specifics_iterator->second->specifics.autofill();
+ VerifyEqual(recorded_specifics, specifics);
+ }
+
+ AutocompleteSyncBridge* bridge() { return bridge_.get(); }
+
+ syncer::RecordingModelTypeChangeProcessor* processor() { return processor_; }
+
+ AutofillTable* table() { return &table_; }
+
+ private:
+ std::unique_ptr<syncer::ModelTypeChangeProcessor>
+ CreateModelTypeChangeProcessor(syncer::ModelType type,
+ syncer::ModelTypeSyncBridge* bridge) {
+ auto processor =
+ base::MakeUnique<syncer::RecordingModelTypeChangeProcessor>();
+ processor_ = processor.get();
+ return std::move(processor);
+ }
+
+ ScopedTempDir temp_dir_;
+ base::MessageLoop message_loop_;
+ FakeAutofillBackend backend_;
+ AutofillTable table_;
+ WebDatabase db_;
+ std::unique_ptr<AutocompleteSyncBridge> bridge_;
+ // A non-owning pointer to the processor given to the bridge. Will be null
+ // before being given to the bridge, to make ownership easier.
+ syncer::RecordingModelTypeChangeProcessor* processor_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(AutocompleteSyncBridgeTest);
+};
+
+TEST_F(AutocompleteSyncBridgeTest, GetClientTag) {
+ // TODO(skym, crbug.com/675991): Implementation.
+}
+
+TEST_F(AutocompleteSyncBridgeTest, GetStorageKey) {
+ std::string key = GetStorageKey(CreateSpecifics(1));
+ EXPECT_EQ(key, GetStorageKey(CreateSpecifics(1)));
+ EXPECT_NE(key, GetStorageKey(CreateSpecifics(2)));
+}
+
+// Timestamps should not affect storage keys.
+TEST_F(AutocompleteSyncBridgeTest, GetStorageKeyTimestamp) {
+ AutofillSpecifics specifics = CreateSpecifics(1);
+ std::string key = GetStorageKey(specifics);
+
+ specifics.add_usage_timestamp(1);
+ EXPECT_EQ(key, GetStorageKey(specifics));
+
+ specifics.add_usage_timestamp(0);
+ EXPECT_EQ(key, GetStorageKey(specifics));
+
+ specifics.add_usage_timestamp(-1);
+ EXPECT_EQ(key, GetStorageKey(specifics));
+}
+
+// Verify that the \0 character is respected as a difference.
+TEST_F(AutocompleteSyncBridgeTest, GetStorageKeyNull) {
+ AutofillSpecifics specifics;
+ std::string key = GetStorageKey(specifics);
+
+ specifics.set_value(std::string("\0", 1));
+ EXPECT_NE(key, GetStorageKey(specifics));
+}
+
+// The storage key should never accidentally change for existing data. This
+// would cause lookups to fail and either lose or duplicate user data. It should
+// be possible for the model type to migrate storage key formats, but doing so
+// would need to be done very carefully.
+TEST_F(AutocompleteSyncBridgeTest, GetStorageKeyFixed) {
+ EXPECT_EQ("\n\x6name 1\x12\avalue 1", GetStorageKey(CreateSpecifics(1)));
+ EXPECT_EQ("\n\x6name 2\x12\avalue 2", GetStorageKey(CreateSpecifics(2)));
+ // This literal contains the null terminating character, which causes
+ // std::string to stop copying early if we don't tell it how much to read.
+ EXPECT_EQ(std::string("\n\0\x12\0", 4), GetStorageKey(AutofillSpecifics()));
+ AutofillSpecifics specifics;
+ specifics.set_name("\xEC\xA4\x91");
+ specifics.set_value("\xD0\x80");
+ EXPECT_EQ("\n\x3\xEC\xA4\x91\x12\x2\xD0\x80", GetStorageKey(specifics));
+}
+
+TEST_F(AutocompleteSyncBridgeTest, GetData) {
+ const AutofillSpecifics specifics1 = CreateSpecifics(1);
+ const AutofillSpecifics specifics2 = CreateSpecifics(2);
+ const AutofillSpecifics specifics3 = CreateSpecifics(3);
+ SaveSpecificsToTable({specifics1, specifics2, specifics3});
+ bridge()->GetData(
+ {GetStorageKey(specifics1), GetStorageKey(specifics3)},
+ base::Bind(&VerifyDataBatch, ExpectedMap({specifics1, specifics3})));
+}
+
+TEST_F(AutocompleteSyncBridgeTest, GetDataNotExist) {
+ const AutofillSpecifics specifics1 = CreateSpecifics(1);
+ const AutofillSpecifics specifics2 = CreateSpecifics(2);
+ const AutofillSpecifics specifics3 = CreateSpecifics(3);
+ SaveSpecificsToTable({specifics1, specifics2});
+ bridge()->GetData(
+ {GetStorageKey(specifics1), GetStorageKey(specifics2),
+ GetStorageKey(specifics3)},
+ base::Bind(&VerifyDataBatch, ExpectedMap({specifics1, specifics2})));
+}
+
+TEST_F(AutocompleteSyncBridgeTest, GetAllData) {
+ const AutofillSpecifics specifics1 = CreateSpecifics(1);
+ const AutofillSpecifics specifics2 = CreateSpecifics(2);
+ const AutofillSpecifics specifics3 = CreateSpecifics(3);
+ SaveSpecificsToTable({specifics1, specifics2, specifics3});
+ VerifyAllData({specifics1, specifics2, specifics3});
+}
+
+TEST_F(AutocompleteSyncBridgeTest, ApplySyncChangesEmpty) {
+ // TODO(skym, crbug.com/672619): Ideally would like to verify that the db is
+ // not accessed.
+ VerifyApplyAdds(std::vector<AutofillSpecifics>());
+}
+
+TEST_F(AutocompleteSyncBridgeTest, ApplySyncChangesSimple) {
+ AutofillSpecifics specifics1 = CreateSpecifics(1);
+ AutofillSpecifics specifics2 = CreateSpecifics(2);
+ ASSERT_NE(specifics1.SerializeAsString(), specifics2.SerializeAsString());
+ ASSERT_NE(GetStorageKey(specifics1), GetStorageKey(specifics2));
+
+ VerifyApplyAdds({specifics1, specifics2});
+ VerifyAllData({specifics1, specifics2});
+
+ VerifyApplyChanges({EntityChange::CreateDelete(GetStorageKey(specifics1))});
+ VerifyAllData({specifics2});
+}
+
+// Should be resilient to deleting and updating non-existent things, and adding
+// existing ones.
+TEST_F(AutocompleteSyncBridgeTest, ApplySyncChangesWrongChangeType) {
+ AutofillSpecifics specifics = CreateSpecifics(1, {1});
+ VerifyApplyChanges({EntityChange::CreateDelete(GetStorageKey(specifics))});
+ VerifyAllData(std::vector<AutofillSpecifics>());
+
+ VerifyApplyChanges({EntityChange::CreateUpdate(
+ GetStorageKey(specifics), SpecificsToEntity(specifics))});
+ VerifyAllData({specifics});
+
+ specifics.add_usage_timestamp(Time::FromTimeT(2).ToInternalValue());
+ VerifyApplyAdds({specifics});
+ VerifyAllData({specifics});
+}
+
+// The format in the table has a fixed 2 timestamp format. Round tripping is
+// lossy and the middle value should be thrown out.
+TEST_F(AutocompleteSyncBridgeTest, ApplySyncChangesThreeTimestamps) {
+ VerifyApplyAdds({CreateSpecifics(1, {1, 2, 3})});
+ VerifyAllData({CreateSpecifics(1, {1, 3})});
+}
+
+// The correct format of timestamps is that the first should be smaller and the
+// second should be larger. Bad foreign data should be repaired.
+TEST_F(AutocompleteSyncBridgeTest, ApplySyncChangesWrongOrder) {
+ VerifyApplyAdds({CreateSpecifics(1, {3, 2})});
+ VerifyAllData({CreateSpecifics(1, {2, 3})});
+}
+
+// In a minor attempt to save bandwidth, we only send one of the two timestamps
+// when they share a value.
+TEST_F(AutocompleteSyncBridgeTest, ApplySyncChangesRepeatedTime) {
+ VerifyApplyAdds({CreateSpecifics(1, {2, 2})});
+ VerifyAllData({CreateSpecifics(1, {2})});
+}
+
+// Again, the format in the table is lossy, and cannot distinguish between no
+// time, and valid time zero.
+TEST_F(AutocompleteSyncBridgeTest, ApplySyncChangesNoTime) {
+ VerifyApplyAdds({CreateSpecifics(1, std::vector<int>())});
+ VerifyAllData({CreateSpecifics(1, {0})});
+}
+
+// If has_value() returns false, then the specifics are determined to be old
+// style and ignored.
+TEST_F(AutocompleteSyncBridgeTest, ApplySyncChangesNoValue) {
+ AutofillSpecifics input = CreateSpecifics(1, {2, 3});
+ input.clear_value();
+ VerifyApplyAdds({input});
+ VerifyAllData(std::vector<AutofillSpecifics>());
+}
+
+// Should be treated the same as an empty string name. This inconsistency is
+// being perpetuated from the previous sync integration.
+TEST_F(AutocompleteSyncBridgeTest, ApplySyncChangesNoName) {
+ AutofillSpecifics input = CreateSpecifics(1, {2, 3});
+ input.clear_name();
+ VerifyApplyAdds({input});
+ VerifyAllData({input});
+}
+
+// UTF-8 characters should not be dropped when round tripping, including middle
+// of string \0 characters.
+TEST_F(AutocompleteSyncBridgeTest, ApplySyncChangesUTF) {
+ const AutofillSpecifics specifics =
+ CreateSpecifics(std::string("\n\0\x12\0", 4), "\xEC\xA4\x91", {1});
+ VerifyApplyAdds({specifics});
+ VerifyAllData({specifics});
+}
+
+// Timestamps should always use the oldest creation time, and the most recent
+// usage time.
+TEST_F(AutocompleteSyncBridgeTest, ApplySyncChangesMinMaxTimestamps) {
+ const AutofillSpecifics initial = CreateSpecifics(1, {3, 6});
+ VerifyApplyAdds({initial});
+ VerifyAllData({initial});
+
+ VerifyApplyAdds({CreateSpecifics(1, {2, 5})});
+ VerifyAllData({CreateSpecifics(1, {2, 6})});
+
+ VerifyApplyAdds({CreateSpecifics(1, {4, 7})});
+ VerifyAllData({CreateSpecifics(1, {2, 7})});
+}
+
+// An error should be generated when parsing the storage key happens. This
+// should never happen in practice because storage keys should be generated at
+// runtime by the bridge and not loaded from disk.
+TEST_F(AutocompleteSyncBridgeTest, ApplySyncChangesBadStorageKey) {
+ const auto error = bridge()->ApplySyncChanges(
+ bridge()->CreateMetadataChangeList(),
+ {EntityChange::CreateDelete("bogus storage key")});
+ EXPECT_TRUE(error);
+}
+
+TEST_F(AutocompleteSyncBridgeTest, ApplySyncChangesDatabaseFailure) {
+ // TODO(skym, crbug.com/672619): Should have tests that get false back when
+ // making db calls and verify the errors are propagated up.
+}
+
+TEST_F(AutocompleteSyncBridgeTest, LocalEntriesAdded) {
+ const AutofillSpecifics added_specifics1 = CreateSpecifics(1, {2, 3});
+ const AutofillSpecifics added_specifics2 = CreateSpecifics(2, {2, 3});
+
+ const AutofillEntry added_entry1 = CreateAutofillEntry(added_specifics1);
+ const AutofillEntry added_entry2 = CreateAutofillEntry(added_specifics2);
+
+ table()->UpdateAutofillEntries({added_entry1, added_entry2});
+
+ bridge()->AutofillEntriesChanged(
+ {AutofillChange(AutofillChange::ADD, added_entry1.key()),
+ AutofillChange(AutofillChange::ADD, added_entry2.key())});
+
+ EXPECT_EQ(2u, processor()->put_multimap().size());
+
+ VerifyProcessorRecordedPut(added_specifics1);
+ VerifyProcessorRecordedPut(added_specifics2);
+}
+
+TEST_F(AutocompleteSyncBridgeTest, LocalEntryAddedThenUpdated) {
+ const AutofillSpecifics added_specifics = CreateSpecifics(1, {2, 3});
+ const AutofillEntry added_entry = CreateAutofillEntry(added_specifics);
+ table()->UpdateAutofillEntries({added_entry});
+
+ bridge()->AutofillEntriesChanged(
+ {AutofillChange(AutofillChange::ADD, added_entry.key())});
+
+ EXPECT_EQ(1u, processor()->put_multimap().size());
+
+ VerifyProcessorRecordedPut(added_specifics);
+
+ const AutofillSpecifics updated_specifics = CreateSpecifics(1, {2, 4});
+ const AutofillEntry updated_entry = CreateAutofillEntry(updated_specifics);
+ table()->UpdateAutofillEntries({updated_entry});
+
+ bridge()->AutofillEntriesChanged(
+ {AutofillChange(AutofillChange::UPDATE, updated_entry.key())});
+
+ VerifyProcessorRecordedPut(updated_specifics, 1);
+}
+
+TEST_F(AutocompleteSyncBridgeTest, LocalEntryDeleted) {
+ const AutofillSpecifics deleted_specifics = CreateSpecifics(1, {2, 3});
+ const AutofillEntry deleted_entry = CreateAutofillEntry(deleted_specifics);
+ const std::string storage_key = GetStorageKey(deleted_specifics);
+
+ bridge()->AutofillEntriesChanged(
+ {AutofillChange(AutofillChange::REMOVE, deleted_entry.key())});
+
+ EXPECT_EQ(1u, processor()->delete_set().size());
+ EXPECT_NE(processor()->delete_set().end(),
+ processor()->delete_set().find(storage_key));
+}
+
+TEST_F(AutocompleteSyncBridgeTest, LoadMetadataCalled) {
+ EXPECT_NE(processor()->metadata(), nullptr);
+ EXPECT_TRUE(processor()->metadata()->GetModelTypeState().initial_sync_done());
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autocomplete_syncable_service.cc b/chromium/components/autofill/core/browser/webdata/autocomplete_syncable_service.cc
index 76fb7fbdbcc..aff312184ea 100644
--- a/chromium/components/autofill/core/browser/webdata/autocomplete_syncable_service.cc
+++ b/chromium/components/autofill/core/browser/webdata/autocomplete_syncable_service.cc
@@ -317,7 +317,7 @@ void AutocompleteSyncableService::CreateOrUpdateEntry(
if (it == loaded_data->end()) {
// New entry.
base::Time date_created, date_last_used;
- if (timestamps.size() > 0) {
+ if (!timestamps.empty()) {
date_created = base::Time::FromInternalValue(*timestamps.begin());
date_last_used = base::Time::FromInternalValue(*timestamps.rbegin());
}
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_data_type_controller.cc b/chromium/components/autofill/core/browser/webdata/autofill_data_type_controller.cc
index d1399bfc3a2..fc3beeae20d 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_data_type_controller.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_data_type_controller.cc
@@ -4,6 +4,8 @@
#include "components/autofill/core/browser/webdata/autofill_data_type_controller.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/metrics/histogram.h"
#include "components/autofill/core/browser/webdata/autocomplete_syncable_service.h"
@@ -14,18 +16,17 @@
namespace browser_sync {
AutofillDataTypeController::AutofillDataTypeController(
- const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
+ scoped_refptr<base::SingleThreadTaskRunner> db_thread,
const base::Closure& dump_stack,
syncer::SyncClient* sync_client,
const scoped_refptr<autofill::AutofillWebDataService>& web_data_service)
- : NonUIDataTypeController(syncer::AUTOFILL, dump_stack, sync_client),
- db_thread_(db_thread),
+ : AsyncDirectoryTypeController(syncer::AUTOFILL,
+ dump_stack,
+ sync_client,
+ syncer::GROUP_DB,
+ std::move(db_thread)),
web_data_service_(web_data_service) {}
-syncer::ModelSafeGroup AutofillDataTypeController::model_safe_group() const {
- return syncer::GROUP_DB;
-}
-
void AutofillDataTypeController::WebDatabaseLoaded() {
DCHECK(CalledOnValidThread());
DCHECK_EQ(MODEL_STARTING, state());
@@ -37,13 +38,6 @@ AutofillDataTypeController::~AutofillDataTypeController() {
DCHECK(CalledOnValidThread());
}
-bool AutofillDataTypeController::PostTaskOnBackendThread(
- const tracked_objects::Location& from_here,
- const base::Closure& task) {
- DCHECK(CalledOnValidThread());
- return db_thread_->PostTask(from_here, task);
-}
-
bool AutofillDataTypeController::StartModels() {
DCHECK(CalledOnValidThread());
DCHECK_EQ(MODEL_STARTING, state());
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_data_type_controller.h b/chromium/components/autofill/core/browser/webdata/autofill_data_type_controller.h
index 90559399957..bccdbf7d9f7 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_data_type_controller.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_data_type_controller.h
@@ -11,7 +11,7 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "components/sync/driver/non_ui_data_type_controller.h"
+#include "components/sync/driver/async_directory_type_controller.h"
namespace autofill {
class AutofillWebDataService;
@@ -20,23 +20,18 @@ class AutofillWebDataService;
namespace browser_sync {
// A class that manages the startup and shutdown of autofill sync.
-class AutofillDataTypeController : public syncer::NonUIDataTypeController {
+class AutofillDataTypeController : public syncer::AsyncDirectoryTypeController {
public:
// |dump_stack| is called when an unrecoverable error occurs.
AutofillDataTypeController(
- const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
+ scoped_refptr<base::SingleThreadTaskRunner> db_thread,
const base::Closure& dump_stack,
syncer::SyncClient* sync_client,
const scoped_refptr<autofill::AutofillWebDataService>& web_data_service);
~AutofillDataTypeController() override;
- // NonUIDataTypeController implementation.
- syncer::ModelSafeGroup model_safe_group() const override;
-
protected:
- // NonUIDataTypeController implementation.
- bool PostTaskOnBackendThread(const tracked_objects::Location& from_here,
- const base::Closure& task) override;
+ // AsyncDirectoryTypeController implementation.
bool StartModels() override;
private:
@@ -47,9 +42,6 @@ class AutofillDataTypeController : public syncer::NonUIDataTypeController {
// Callback once WebDatabase has loaded.
void WebDatabaseLoaded();
- // A reference to the DB thread's task runner.
- const scoped_refptr<base::SingleThreadTaskRunner> db_thread_;
-
// A reference to the AutofillWebDataService for this controller.
scoped_refptr<autofill::AutofillWebDataService> web_data_service_;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_data_type_controller_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_data_type_controller_unittest.cc
index b0ac2cd33df..90aa68b77d8 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_data_type_controller_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_data_type_controller_unittest.cc
@@ -10,6 +10,7 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_entry.cc b/chromium/components/autofill/core/browser/webdata/autofill_entry.cc
index 83fd639bbbd..58494a7c93e 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_entry.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_entry.cc
@@ -38,6 +38,8 @@ bool AutofillKey::operator<(const AutofillKey& key) const {
return std::tie(name_, value_) < std::tie(key.name(), key.value());
}
+AutofillEntry::AutofillEntry() {}
+
AutofillEntry::AutofillEntry(const AutofillKey& key,
const base::Time& date_created,
const base::Time& date_last_used)
@@ -53,6 +55,10 @@ bool AutofillEntry::operator==(const AutofillEntry& entry) const {
date_last_used() == entry.date_last_used();
}
+bool AutofillEntry::operator!=(const AutofillEntry& entry) const {
+ return !(*this == entry);
+}
+
bool AutofillEntry::operator<(const AutofillEntry& entry) const {
return key_ < entry.key();
}
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_entry.h b/chromium/components/autofill/core/browser/webdata/autofill_entry.h
index 1edc4010dd5..4a934dd4510 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_entry.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_entry.h
@@ -31,6 +31,7 @@ class AutofillKey {
class AutofillEntry {
public:
+ AutofillEntry();
AutofillEntry(const AutofillKey& key,
const base::Time& date_created,
const base::Time& date_last_used);
@@ -41,6 +42,7 @@ class AutofillEntry {
const base::Time& date_last_used() const { return date_last_used_; }
bool operator==(const AutofillEntry& entry) const;
+ bool operator!=(const AutofillEntry& entry) const;
bool operator<(const AutofillEntry& entry) const;
private:
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_metadata_change_list.cc b/chromium/components/autofill/core/browser/webdata/autofill_metadata_change_list.cc
new file mode 100644
index 00000000000..24876e4a0cf
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autofill_metadata_change_list.cc
@@ -0,0 +1,75 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/webdata/autofill_metadata_change_list.h"
+
+#include "base/location.h"
+
+using base::Optional;
+using syncer::ModelError;
+
+namespace autofill {
+
+AutofillMetadataChangeList::AutofillMetadataChangeList(AutofillTable* table,
+ syncer::ModelType type)
+ : table_(table), type_(type) {
+ DCHECK(table_);
+ // This should be changed as new autofill types are converted to USS.
+ DCHECK_EQ(syncer::AUTOFILL, type_);
+}
+
+AutofillMetadataChangeList::~AutofillMetadataChangeList() {
+ DCHECK(!error_);
+}
+
+void AutofillMetadataChangeList::UpdateModelTypeState(
+ const sync_pb::ModelTypeState& model_type_state) {
+ if (error_) {
+ return;
+ }
+
+ if (!table_->UpdateModelTypeState(type_, model_type_state)) {
+ error_ = ModelError(FROM_HERE, "Failed to update ModelTypeState.");
+ }
+}
+
+void AutofillMetadataChangeList::ClearModelTypeState() {
+ if (error_) {
+ return;
+ }
+
+ if (!table_->ClearModelTypeState(type_)) {
+ error_ = ModelError(FROM_HERE, "Failed to clear ModelTypeState.");
+ }
+}
+
+void AutofillMetadataChangeList::UpdateMetadata(
+ const std::string& storage_key,
+ const sync_pb::EntityMetadata& metadata) {
+ if (error_) {
+ return;
+ }
+
+ if (!table_->UpdateSyncMetadata(type_, storage_key, metadata)) {
+ error_ = ModelError(FROM_HERE, "Failed to update entity metadata.");
+ }
+}
+
+void AutofillMetadataChangeList::ClearMetadata(const std::string& storage_key) {
+ if (error_) {
+ return;
+ }
+
+ if (!table_->ClearSyncMetadata(type_, storage_key)) {
+ error_ = ModelError(FROM_HERE, "Failed to clear entity metadata.");
+ }
+}
+
+Optional<ModelError> AutofillMetadataChangeList::TakeError() {
+ Optional<ModelError> temp = error_;
+ error_.reset();
+ return temp;
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_metadata_change_list.h b/chromium/components/autofill/core/browser/webdata/autofill_metadata_change_list.h
new file mode 100644
index 00000000000..e924e2070a6
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autofill_metadata_change_list.h
@@ -0,0 +1,55 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_METADATA_CHANGE_LIST_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_METADATA_CHANGE_LIST_H_
+
+#include <string>
+
+#include "base/optional.h"
+#include "components/autofill/core/browser/webdata/autofill_table.h"
+#include "components/sync/base/model_type.h"
+#include "components/sync/model/metadata_change_list.h"
+#include "components/sync/model/model_error.h"
+#include "components/sync/model/sync_error.h"
+#include "components/sync/protocol/entity_metadata.pb.h"
+#include "components/sync/protocol/model_type_state.pb.h"
+
+namespace autofill {
+
+// A thin wrapper around an AutofillTable that implements sync's
+// MetadataChangeList interface. Changes are passed directly into the table and
+// not stored inside this object. Since the table calls can fail, |TakeError()|
+// must be called before this object is destroyed to check whether any
+// operations failed.
+class AutofillMetadataChangeList : public syncer::MetadataChangeList {
+ public:
+ AutofillMetadataChangeList(AutofillTable* table, syncer::ModelType type);
+ ~AutofillMetadataChangeList() override;
+
+ // syncer::MetadataChangeList implementation.
+ void UpdateModelTypeState(
+ const sync_pb::ModelTypeState& model_type_state) override;
+ void ClearModelTypeState() override;
+ void UpdateMetadata(const std::string& storage_key,
+ const sync_pb::EntityMetadata& metadata) override;
+ void ClearMetadata(const std::string& storage_key) override;
+
+ // Returns the value of |error_| and unsets it.
+ base::Optional<syncer::ModelError> TakeError();
+
+ private:
+ // The autofill table to store metadata in; always outlives |this|.
+ AutofillTable* table_;
+
+ // The sync model type for this metadata.
+ syncer::ModelType type_;
+
+ // The first error encountered by this object, if any.
+ base::Optional<syncer::ModelError> error_;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_METADATA_CHANGE_LIST_H_
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.cc b/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.cc
index 9d0f57057d8..f883c970e26 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.cc
@@ -4,6 +4,8 @@
#include "components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/metrics/histogram.h"
#include "components/autofill/core/browser/personal_data_manager.h"
@@ -17,23 +19,19 @@ using autofill::AutofillWebDataService;
namespace browser_sync {
AutofillProfileDataTypeController::AutofillProfileDataTypeController(
- const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
+ scoped_refptr<base::SingleThreadTaskRunner> db_thread,
const base::Closure& dump_stack,
syncer::SyncClient* sync_client,
const scoped_refptr<autofill::AutofillWebDataService>& web_data_service)
- : NonUIDataTypeController(syncer::AUTOFILL_PROFILE,
- dump_stack,
- sync_client),
- db_thread_(db_thread),
+ : AsyncDirectoryTypeController(syncer::AUTOFILL_PROFILE,
+ dump_stack,
+ sync_client,
+ syncer::GROUP_DB,
+ std::move(db_thread)),
sync_client_(sync_client),
web_data_service_(web_data_service),
callback_registered_(false) {}
-syncer::ModelSafeGroup AutofillProfileDataTypeController::model_safe_group()
- const {
- return syncer::GROUP_DB;
-}
-
void AutofillProfileDataTypeController::WebDatabaseLoaded() {
DCHECK(CalledOnValidThread());
OnModelLoaded();
@@ -60,13 +58,6 @@ void AutofillProfileDataTypeController::OnPersonalDataChanged() {
AutofillProfileDataTypeController::~AutofillProfileDataTypeController() {}
-bool AutofillProfileDataTypeController::PostTaskOnBackendThread(
- const tracked_objects::Location& from_here,
- const base::Closure& task) {
- DCHECK(CalledOnValidThread());
- return db_thread_->PostTask(from_here, task);
-}
-
bool AutofillProfileDataTypeController::StartModels() {
DCHECK(CalledOnValidThread());
DCHECK_EQ(state(), MODEL_STARTING);
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h b/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h
index cf68f4af67d..6dd5fd55893 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h
@@ -10,38 +10,32 @@
#include "base/memory/ref_counted.h"
#include "base/scoped_observer.h"
#include "components/autofill/core/browser/personal_data_manager_observer.h"
-#include "components/sync/driver/non_ui_data_type_controller.h"
+#include "components/sync/driver/async_directory_type_controller.h"
namespace autofill {
class AutofillWebDataService;
-class PersonalDataManager;
} // namespace autofill
namespace browser_sync {
// Controls syncing of the AUTOFILL_PROFILE data type.
class AutofillProfileDataTypeController
- : public syncer::NonUIDataTypeController,
+ : public syncer::AsyncDirectoryTypeController,
public autofill::PersonalDataManagerObserver {
public:
// |dump_stack| is called when an unrecoverable error occurs.
AutofillProfileDataTypeController(
- const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
+ scoped_refptr<base::SingleThreadTaskRunner> db_thread,
const base::Closure& dump_stack,
syncer::SyncClient* sync_client,
const scoped_refptr<autofill::AutofillWebDataService>& web_data_service);
~AutofillProfileDataTypeController() override;
- // NonUIDataTypeController:
- syncer::ModelSafeGroup model_safe_group() const override;
-
// PersonalDataManagerObserver:
void OnPersonalDataChanged() override;
protected:
- // NonUIDataTypeController:
- bool PostTaskOnBackendThread(const tracked_objects::Location& from_here,
- const base::Closure& task) override;
+ // AsyncDirectoryTypeController:
bool StartModels() override;
void StopModels() override;
@@ -49,9 +43,6 @@ class AutofillProfileDataTypeController
// Callback to notify that WebDatabase has loaded.
void WebDatabaseLoaded();
- // A reference to the DB thread's task runner.
- const scoped_refptr<base::SingleThreadTaskRunner> db_thread_;
-
// A pointer to the sync client.
syncer::SyncClient* const sync_client_;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table.cc b/chromium/components/autofill/core/browser/webdata/autofill_table.cc
index 88867361266..503eb0fa9e7 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table.cc
@@ -35,6 +35,10 @@
#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/os_crypt/os_crypt.h"
+#include "components/sync/base/model_type.h"
+#include "components/sync/model/metadata_batch.h"
+#include "components/sync/protocol/entity_metadata.pb.h"
+#include "components/sync/protocol/model_type_state.pb.h"
#include "components/webdata/common/web_database.h"
#include "sql/statement.h"
#include "sql/transaction.h"
@@ -416,7 +420,8 @@ bool AutofillTable::CreateTablesIfNecessary() {
InitProfilePhonesTable() && InitProfileTrashTable() &&
InitMaskedCreditCardsTable() && InitUnmaskedCreditCardsTable() &&
InitServerCardMetadataTable() && InitServerAddressesTable() &&
- InitServerAddressMetadataTable());
+ InitServerAddressMetadataTable() && InitAutofillSyncMetadataTable() &&
+ InitModelTypeStateTable());
}
bool AutofillTable::IsSyncable() {
@@ -463,6 +468,12 @@ bool AutofillTable::MigrateToVersion(int version,
case 67:
*update_compatible_version = false;
return MigrateToVersion67AddMaskedCardBillingAddress();
+ case 70:
+ *update_compatible_version = false;
+ return MigrateToVersion70AddSyncMetadata();
+ case 71:
+ *update_compatible_version = true;
+ return MigrateToVersion71AddHasConvertedAndBillingAddressIdMetadata();
}
return true;
}
@@ -934,7 +945,7 @@ bool AutofillTable::GetAutofillProfiles(
}
bool AutofillTable::GetServerProfiles(
- std::vector<std::unique_ptr<AutofillProfile>>* profiles) {
+ std::vector<std::unique_ptr<AutofillProfile>>* profiles) const {
profiles->clear();
sql::Statement s(db_->GetUniqueStatement(
@@ -1197,22 +1208,22 @@ bool AutofillTable::GetCreditCards(
}
bool AutofillTable::GetServerCreditCards(
- std::vector<std::unique_ptr<CreditCard>>* credit_cards) {
+ std::vector<std::unique_ptr<CreditCard>>* credit_cards) const {
credit_cards->clear();
sql::Statement s(db_->GetUniqueStatement(
"SELECT "
- "card_number_encrypted, " // 0
- "last_four," // 1
- "masked.id," // 2
- "metadata.use_count," // 3
- "metadata.use_date," // 4
- "type," // 5
- "status," // 6
- "name_on_card," // 7
- "exp_month," // 8
- "exp_year," // 9
- "billing_address_id " // 10
+ "card_number_encrypted, " // 0
+ "last_four," // 1
+ "masked.id," // 2
+ "metadata.use_count," // 3
+ "metadata.use_date," // 4
+ "type," // 5
+ "status," // 6
+ "name_on_card," // 7
+ "exp_month," // 8
+ "exp_year," // 9
+ "metadata.billing_address_id " // 10
"FROM masked_credit_cards masked "
"LEFT OUTER JOIN unmasked_credit_cards USING (id) "
"LEFT OUTER JOIN server_card_metadata metadata USING (id)"));
@@ -1271,17 +1282,16 @@ void AutofillTable::SetServerCreditCards(
"DELETE FROM masked_credit_cards"));
masked_delete.Run();
- sql::Statement masked_insert(db_->GetUniqueStatement(
- "INSERT INTO masked_credit_cards("
- "id," // 0
- "type," // 1
- "status," // 2
- "name_on_card," // 3
- "last_four," // 4
- "exp_month," // 5
- "exp_year," // 6
- "billing_address_id) " // 7
- "VALUES (?,?,?,?,?,?,?,?)"));
+ sql::Statement masked_insert(
+ db_->GetUniqueStatement("INSERT INTO masked_credit_cards("
+ "id," // 0
+ "type," // 1
+ "status," // 2
+ "name_on_card," // 3
+ "last_four," // 4
+ "exp_month," // 5
+ "exp_year)" // 6
+ "VALUES (?,?,?,?,?,?,?)"));
for (const CreditCard& card : credit_cards) {
DCHECK_EQ(CreditCard::MASKED_SERVER_CARD, card.record_type());
@@ -1294,13 +1304,12 @@ void AutofillTable::SetServerCreditCards(
masked_insert.BindString16(5, card.GetRawInfo(CREDIT_CARD_EXP_MONTH));
masked_insert.BindString16(6,
card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
- masked_insert.BindString(7, card.billing_address_id());
masked_insert.Run();
masked_insert.Reset(true);
// Save the use count and use date of the card.
- UpdateServerCardUsageStats(card);
+ UpdateServerCardMetadata(card);
}
// Delete all items in the unmasked table that aren't in the new set.
@@ -1341,7 +1350,7 @@ bool AutofillTable::UnmaskServerCreditCard(const CreditCard& masked,
unmasked.set_record_type(CreditCard::FULL_SERVER_CARD);
unmasked.SetNumber(full_number);
unmasked.RecordAndLogUse();
- UpdateServerCardUsageStats(unmasked);
+ UpdateServerCardMetadata(unmasked);
return db_->GetLastChangeCount() > 0;
}
@@ -1354,8 +1363,7 @@ bool AutofillTable::MaskServerCreditCard(const std::string& id) {
return db_->GetLastChangeCount() > 0;
}
-bool AutofillTable::UpdateServerCardUsageStats(
- const CreditCard& credit_card) {
+bool AutofillTable::UpdateServerCardMetadata(const CreditCard& credit_card) {
DCHECK_NE(CreditCard::LOCAL_CARD, credit_card.record_type());
sql::Transaction transaction(db_);
if (!transaction.Begin())
@@ -1366,12 +1374,14 @@ bool AutofillTable::UpdateServerCardUsageStats(
remove.BindString(0, credit_card.server_id());
remove.Run();
- sql::Statement s(db_->GetUniqueStatement(
- "INSERT INTO server_card_metadata(use_count, use_date, id)"
- "VALUES (?,?,?)"));
+ sql::Statement s(
+ db_->GetUniqueStatement("INSERT INTO server_card_metadata(use_count, "
+ "use_date, billing_address_id, id)"
+ "VALUES (?,?,?,?)"));
s.BindInt64(0, credit_card.use_count());
s.BindInt64(1, credit_card.use_date().ToInternalValue());
- s.BindString(2, credit_card.server_id());
+ s.BindString(2, credit_card.billing_address_id());
+ s.BindString(3, credit_card.server_id());
s.Run();
transaction.Commit();
@@ -1379,7 +1389,9 @@ bool AutofillTable::UpdateServerCardUsageStats(
return db_->GetLastChangeCount() > 0;
}
-bool AutofillTable::UpdateServerAddressUsageStats(
+// TODO(crbug.com/680182): Record the address conversion status when a server
+// address gets converted.
+bool AutofillTable::UpdateServerAddressMetadata(
const AutofillProfile& profile) {
DCHECK_EQ(AutofillProfile::SERVER_PROFILE, profile.record_type());
@@ -1392,12 +1404,14 @@ bool AutofillTable::UpdateServerAddressUsageStats(
remove.BindString(0, profile.server_id());
remove.Run();
- sql::Statement s(db_->GetUniqueStatement(
- "INSERT INTO server_address_metadata(use_count, use_date, id)"
- "VALUES (?,?,?)"));
+ sql::Statement s(
+ db_->GetUniqueStatement("INSERT INTO server_address_metadata(use_count, "
+ "use_date, has_converted, id)"
+ "VALUES (?,?,?,?)"));
s.BindInt64(0, profile.use_count());
s.BindInt64(1, profile.use_date().ToInternalValue());
- s.BindString(2, profile.server_id());
+ s.BindBool(2, false);
+ s.BindString(3, profile.server_id());
s.Run();
transaction.Commit();
@@ -1405,21 +1419,6 @@ bool AutofillTable::UpdateServerAddressUsageStats(
return db_->GetLastChangeCount() > 0;
}
-bool AutofillTable::UpdateServerCardBillingAddress(
- const CreditCard& credit_card) {
- DCHECK_NE(CreditCard::LOCAL_CARD, credit_card.record_type());
-
- sql::Statement update(db_->GetUniqueStatement(
- "UPDATE masked_credit_cards SET billing_address_id = ? "
- "WHERE id = ?"));
- update.BindString(0, credit_card.billing_address_id());
- update.BindString(1, credit_card.server_id());
- if (!update.Run())
- return false;
-
- return db_->GetLastChangeCount() > 0;
-}
-
bool AutofillTable::ClearAllServerData() {
sql::Transaction transaction(db_);
if (!transaction.Begin())
@@ -1680,6 +1679,122 @@ bool AutofillTable::IsAutofillGUIDInTrash(const std::string& guid) {
return s.Step();
}
+bool AutofillTable::GetAllSyncMetadata(syncer::ModelType model_type,
+ syncer::MetadataBatch* metadata_batch) {
+ DCHECK_EQ(model_type, syncer::AUTOFILL)
+ << "Only the AUTOFILL model type is supported";
+ syncer::EntityMetadataMap metadata_records;
+ if (GetAllSyncEntityMetadata(model_type, &metadata_records)) {
+ for (const auto& pair : metadata_records) {
+ // todo(pnoland): add batch transfer of metadata map
+ metadata_batch->AddMetadata(pair.first, pair.second);
+ }
+ } else {
+ return false;
+ }
+
+ sync_pb::ModelTypeState model_type_state;
+ if (GetModelTypeState(model_type, &model_type_state)) {
+ metadata_batch->SetModelTypeState(model_type_state);
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+bool AutofillTable::GetAllSyncEntityMetadata(
+ syncer::ModelType model_type,
+ syncer::EntityMetadataMap* metadata_records) {
+ DCHECK_EQ(model_type, syncer::AUTOFILL)
+ << "Only the AUTOFILL model type is supported";
+
+ sql::Statement s(db_->GetUniqueStatement(
+ "SELECT storage_key, value FROM autofill_sync_metadata"));
+
+ while (s.Step()) {
+ std::string storage_key = s.ColumnString(0);
+ std::string serialized_metadata = s.ColumnString(1);
+ sync_pb::EntityMetadata metadata_record;
+ if (metadata_record.ParseFromString(serialized_metadata)) {
+ metadata_records->insert(std::make_pair(storage_key, metadata_record));
+ } else {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool AutofillTable::UpdateSyncMetadata(
+ syncer::ModelType model_type,
+ const std::string& storage_key,
+ const sync_pb::EntityMetadata& metadata) {
+ DCHECK_EQ(model_type, syncer::AUTOFILL)
+ << "Only the AUTOFILL model type is supported";
+
+ sql::Statement s(
+ db_->GetUniqueStatement("INSERT OR REPLACE INTO autofill_sync_metadata "
+ "(storage_key, value) VALUES(?, ?)"));
+ s.BindString(0, storage_key);
+ s.BindString(1, metadata.SerializeAsString());
+
+ return s.Run();
+}
+
+bool AutofillTable::ClearSyncMetadata(syncer::ModelType model_type,
+ const std::string& storage_key) {
+ DCHECK_EQ(model_type, syncer::AUTOFILL)
+ << "Only the AUTOFILL model type is supported";
+
+ sql::Statement s(db_->GetUniqueStatement(
+ "DELETE FROM autofill_sync_metadata WHERE storage_key=?"));
+ s.BindString(0, storage_key);
+
+ return s.Run();
+}
+
+bool AutofillTable::GetModelTypeState(syncer::ModelType model_type,
+ sync_pb::ModelTypeState* state) {
+ DCHECK_EQ(model_type, syncer::AUTOFILL)
+ << "Only the AUTOFILL model type is supported";
+
+ sql::Statement s(db_->GetUniqueStatement(
+ "SELECT value FROM autofill_model_type_state WHERE id=1"));
+
+ if (!s.Step()) {
+ return false;
+ }
+
+ std::string serialized_state = s.ColumnString(0);
+ return state->ParseFromString(serialized_state);
+}
+
+bool AutofillTable::UpdateModelTypeState(
+ syncer::ModelType model_type,
+ const sync_pb::ModelTypeState& model_type_state) {
+ DCHECK_EQ(model_type, syncer::AUTOFILL)
+ << "Only the AUTOFILL model type is supported";
+
+ // Hardcode the id to force a collision, ensuring that there remains only a
+ // single entry.
+ sql::Statement s(db_->GetUniqueStatement(
+ "INSERT OR REPLACE INTO autofill_model_type_state (id, value) "
+ "VALUES(1,?)"));
+ s.BindString(0, model_type_state.SerializeAsString());
+
+ return s.Run();
+}
+
+bool AutofillTable::ClearModelTypeState(syncer::ModelType model_type) {
+ DCHECK_EQ(model_type, syncer::AUTOFILL)
+ << "Only the AUTOFILL model type is supported";
+
+ sql::Statement s(db_->GetUniqueStatement(
+ "DELETE FROM autofill_model_type_state WHERE id=1"));
+
+ return s.Run();
+}
+
bool AutofillTable::InitMainTable() {
if (!db_->DoesTableExist("autofill")) {
if (!db_->Execute("CREATE TABLE autofill ("
@@ -1804,8 +1919,7 @@ bool AutofillTable::InitMaskedCreditCardsTable() {
"type VARCHAR,"
"last_four VARCHAR,"
"exp_month INTEGER DEFAULT 0,"
- "exp_year INTEGER DEFAULT 0, "
- "billing_address_id VARCHAR)")) {
+ "exp_year INTEGER DEFAULT 0)")) {
NOTREACHED();
return false;
}
@@ -1833,7 +1947,8 @@ bool AutofillTable::InitServerCardMetadataTable() {
if (!db_->Execute("CREATE TABLE server_card_metadata ("
"id VARCHAR NOT NULL,"
"use_count INTEGER NOT NULL DEFAULT 0, "
- "use_date INTEGER NOT NULL DEFAULT 0)")) {
+ "use_date INTEGER NOT NULL DEFAULT 0, "
+ "billing_address_id VARCHAR)")) {
NOTREACHED();
return false;
}
@@ -1871,7 +1986,31 @@ bool AutofillTable::InitServerAddressMetadataTable() {
if (!db_->Execute("CREATE TABLE server_address_metadata ("
"id VARCHAR NOT NULL,"
"use_count INTEGER NOT NULL DEFAULT 0, "
- "use_date INTEGER NOT NULL DEFAULT 0)")) {
+ "use_date INTEGER NOT NULL DEFAULT 0, "
+ "has_converted BOOL NOT NULL DEFAULT FALSE)")) {
+ NOTREACHED();
+ return false;
+ }
+ }
+ return true;
+}
+
+bool AutofillTable::InitAutofillSyncMetadataTable() {
+ if (!db_->DoesTableExist("autofill_sync_metadata")) {
+ if (!db_->Execute("CREATE TABLE autofill_sync_metadata ("
+ "storage_key VARCHAR PRIMARY KEY NOT NULL,"
+ "value BLOB)")) {
+ NOTREACHED();
+ return false;
+ }
+ }
+ return true;
+}
+
+bool AutofillTable::InitModelTypeStateTable() {
+ if (!db_->DoesTableExist("autofill_model_type_state")) {
+ if (!db_->Execute("CREATE TABLE autofill_model_type_state (id INTEGER "
+ "PRIMARY KEY, value BLOB)")) {
NOTREACHED();
return false;
}
@@ -2315,4 +2454,77 @@ bool AutofillTable::MigrateToVersion67AddMaskedCardBillingAddress() {
"ALTER TABLE masked_credit_cards ADD COLUMN billing_address_id VARCHAR");
}
-} // namespace autofill
+bool AutofillTable::MigrateToVersion70AddSyncMetadata() {
+ if (!db_->Execute("CREATE TABLE autofill_sync_metadata ("
+ "storage_key VARCHAR PRIMARY KEY NOT NULL,"
+ "value BLOB)")) {
+ return false;
+ }
+ return db_->Execute(
+ "CREATE TABLE autofill_model_type_state (id INTEGER PRIMARY KEY, value "
+ "BLOB)");
+}
+
+bool AutofillTable::
+ MigrateToVersion71AddHasConvertedAndBillingAddressIdMetadata() {
+ sql::Transaction transaction(db_);
+ if (!transaction.Begin())
+ return false;
+
+ // Add the new has_converted column to the server_address_metadata table.
+ if (!db_->DoesColumnExist("server_address_metadata", "has_converted") &&
+ !db_->Execute("ALTER TABLE server_address_metadata ADD COLUMN "
+ "has_converted BOOL NOT NULL DEFAULT FALSE")) {
+ return false;
+ }
+
+ // Add the new billing_address_id column to the server_card_metadata table.
+ if (!db_->DoesColumnExist("server_card_metadata", "billing_address_id") &&
+ !db_->Execute("ALTER TABLE server_card_metadata ADD COLUMN "
+ "billing_address_id VARCHAR")) {
+ return false;
+ }
+
+ // Copy over the billing_address_id from the masked_server_cards to
+ // server_card_metadata.
+ if (!db_->Execute("UPDATE server_card_metadata "
+ "SET billing_address_id = "
+ "(SELECT billing_address_id "
+ "FROM masked_credit_cards "
+ "WHERE id = server_card_metadata.id)")) {
+ return false;
+ }
+
+ // Remove the billing_address_id column from the masked_credit_cards table.
+ // Create a temporary table that is a copy of masked_credit_cards but without
+ // the billing_address_id column.
+ if (db_->DoesTableExist("masked_credit_cards_temp") ||
+ !db_->Execute("CREATE TABLE masked_credit_cards_temp ("
+ "id VARCHAR,"
+ "status VARCHAR,"
+ "name_on_card VARCHAR,"
+ "type VARCHAR,"
+ "last_four VARCHAR,"
+ "exp_month INTEGER DEFAULT 0,"
+ "exp_year INTEGER DEFAULT 0)")) {
+ return false;
+ }
+ // Copy over the data from the original masked_credit_cards table.
+ if (!db_->Execute("INSERT INTO masked_credit_cards_temp "
+ "SELECT id, status, name_on_card, type, last_four, "
+ "exp_month, exp_year "
+ "FROM masked_credit_cards")) {
+ return false;
+ }
+ // Delete the existing table and replace it with the contents of the
+ // temporary table.
+ if (!db_->Execute("DROP TABLE masked_credit_cards") ||
+ !db_->Execute("ALTER TABLE masked_credit_cards_temp "
+ "RENAME TO masked_credit_cards")) {
+ return false;
+ }
+
+ return transaction.Commit();
+}
+
+} // namespace autofill \ No newline at end of file
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table.h b/chromium/components/autofill/core/browser/webdata/autofill_table.h
index a8eceb0ae1b..2f5fff15431 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table.h
@@ -13,6 +13,8 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/strings/string16.h"
+#include "components/sync/base/model_type.h"
+#include "components/sync/model/metadata_batch.h"
#include "components/webdata/common/web_database_table.h"
class WebDatabase;
@@ -21,6 +23,11 @@ namespace base {
class Time;
}
+namespace sync_pb {
+class EntityMetadata;
+class ModelTypeState;
+}
+
namespace autofill {
class AutofillChange;
@@ -160,10 +167,6 @@ struct FormFieldData;
// with locally stored cards and generating descriptions.
// exp_month Expiration month: 1-12
// exp_year Four-digit year: 2017
-// billing_address_id The guid string that identifies the local profile which
-// is the billing address for this card. Can be null in the
-// database, but always returned as an empty string in
-// CreditCard. Added in version 67.
//
// unmasked_credit_cards
// When a masked credit credit card is unmasked and the
@@ -175,6 +178,7 @@ struct FormFieldData;
// Full card number, encrypted.
// use_count DEPRECATED in version 65. See server_card_metadata.
// use_date DEPRECATED in version 65. See server_card_metadata.
+// TODO(crbug.com/682326): Remove deprecated columns.
// unmask_date The date this card was unmasked in units of
// Time::ToInternalValue. Added in version 64.
//
@@ -188,6 +192,10 @@ struct FormFieldData;
// a form.
// use_date The date this card was last used to fill a form,
// in internal t.
+// billing_address_id The string that identifies the profile which is the
+// billing address for this card. Can be null in the
+// database, but always returned as an empty string in
+// CreditCard. Added in version 71.
//
// server_addresses This table contains Autofill address data synced from
// the wallet server. It's basically the same as the
@@ -228,6 +236,21 @@ struct FormFieldData;
// a form.
// use_date The date this address was last used to fill a form,
// in internal t.
+// has_converted Whether this server address has been converted to a
+// local autofill profile.
+//
+// autofill_sync_metadata
+// Sync-specific metadata for autofill records.
+//
+// storage_key A string that uniquely identifies the metadata record
+// as well as the corresponding autofill record.
+// value The serialized EntityMetadata record.
+//
+// autofill_model_type_state
+// Single row table that contains the sync ModelTypeState
+// for the autofill model type.
+//
+// value The serialized ModelTypeState record.
class AutofillTable : public WebDatabaseTable {
public:
@@ -320,7 +343,7 @@ class AutofillTable : public WebDatabaseTable {
virtual bool GetAutofillProfiles(
std::vector<std::unique_ptr<AutofillProfile>>* profiles);
virtual bool GetServerProfiles(
- std::vector<std::unique_ptr<AutofillProfile>>* profiles);
+ std::vector<std::unique_ptr<AutofillProfile>>* profiles) const;
// Sets the server profiles. All old profiles are deleted and replaced with
// the given ones.
@@ -343,7 +366,7 @@ class AutofillTable : public WebDatabaseTable {
virtual bool GetCreditCards(
std::vector<std::unique_ptr<CreditCard>>* credit_cards);
virtual bool GetServerCreditCards(
- std::vector<std::unique_ptr<CreditCard>>* credit_cards);
+ std::vector<std::unique_ptr<CreditCard>>* credit_cards) const;
// Replaces all server credit cards with the given vector. Unmasked cards
// present in the new list will be preserved (even if the input is MASKED).
@@ -356,10 +379,8 @@ class AutofillTable : public WebDatabaseTable {
const base::string16& full_number);
bool MaskServerCreditCard(const std::string& id);
- bool UpdateServerCardUsageStats(const CreditCard& credit_card);
- bool UpdateServerAddressUsageStats(const AutofillProfile& profile);
-
- bool UpdateServerCardBillingAddress(const CreditCard& credit_card);
+ bool UpdateServerCardMetadata(const CreditCard& credit_card);
+ bool UpdateServerAddressMetadata(const AutofillProfile& profile);
// 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"
@@ -403,6 +424,28 @@ class AutofillTable : public WebDatabaseTable {
// Clear all profiles.
bool ClearAutofillProfiles();
+ // Read all the stored metadata for |model_type| and fill |metadata_batch|
+ // with it.
+ bool GetAllSyncMetadata(syncer::ModelType model_type,
+ syncer::MetadataBatch* metadata_batch);
+
+ // Update the metadata row for |model_type|, keyed by |storage_key|, to
+ // contain the contents of |metadata|.
+ bool UpdateSyncMetadata(syncer::ModelType model_type,
+ const std::string& storage_key,
+ const sync_pb::EntityMetadata& metadata);
+
+ // Remove the metadata row of type |model_type| keyed by |storage|key|.
+ bool ClearSyncMetadata(syncer::ModelType model_type,
+ const std::string& storage_key);
+
+ // Update the stored sync state for the |model_type|.
+ bool UpdateModelTypeState(syncer::ModelType model_type,
+ const sync_pb::ModelTypeState& model_type_state);
+
+ // Clear the stored sync state for |model_type|.
+ bool ClearModelTypeState(syncer::ModelType model_type);
+
// 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
@@ -419,6 +462,8 @@ class AutofillTable : public WebDatabaseTable {
bool MigrateToVersion65AddServerMetadataTables();
bool MigrateToVersion66AddCardBillingAddress();
bool MigrateToVersion67AddMaskedCardBillingAddress();
+ bool MigrateToVersion70AddSyncMetadata();
+ bool MigrateToVersion71AddHasConvertedAndBillingAddressIdMetadata();
// Max data length saved in the table, AKA the maximum length allowed for
// form data.
@@ -474,6 +519,12 @@ class AutofillTable : public WebDatabaseTable {
std::vector<AutofillChange>* changes,
base::Time time);
+ bool GetAllSyncEntityMetadata(syncer::ModelType model_type,
+ syncer::EntityMetadataMap* metadata_records);
+
+ bool GetModelTypeState(syncer::ModelType model_type,
+ sync_pb::ModelTypeState* state);
+
// Insert a single AutofillEntry into the autofill table.
bool InsertAutofillEntry(const AutofillEntry& entry);
@@ -496,6 +547,8 @@ class AutofillTable : public WebDatabaseTable {
bool InitServerCardMetadataTable();
bool InitServerAddressesTable();
bool InitServerAddressMetadataTable();
+ bool InitAutofillSyncMetadataTable();
+ bool InitModelTypeStateTable();
DISALLOW_COPY_AND_ASSIGN(AutofillTable);
};
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc
index 18277b1f121..e8da2b12843 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc
@@ -35,6 +35,8 @@
#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/os_crypt/os_crypt_mocker.h"
+#include "components/sync/protocol/entity_metadata.pb.h"
+#include "components/sync/protocol/model_type_state.pb.h"
#include "components/webdata/common/web_database.h"
#include "sql/statement.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -1716,7 +1718,7 @@ TEST_F(AutofillTableTest, SetServerCardModify) {
outputs.clear();
}
-TEST_F(AutofillTableTest, SetServerCardUpdateUsageStats) {
+TEST_F(AutofillTableTest, SetServerCardUpdateUsageStatsAndBillingAddress) {
// Add a masked card.
CreditCard masked_card(CreditCard::MASKED_SERVER_CARD, "a123");
masked_card.SetRawInfo(CREDIT_CARD_NAME_FULL,
@@ -1724,6 +1726,7 @@ TEST_F(AutofillTableTest, SetServerCardUpdateUsageStats) {
masked_card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("1"));
masked_card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2020"));
masked_card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("1111"));
+ masked_card.set_billing_address_id("1");
masked_card.SetTypeForMaskedCard(kVisaCard);
std::vector<CreditCard> inputs;
@@ -1744,13 +1747,15 @@ TEST_F(AutofillTableTest, SetServerCardUpdateUsageStats) {
// Update the usage stats; make sure they're reflected in GetServerProfiles.
inputs.back().set_use_count(4U);
inputs.back().set_use_date(base::Time());
- table_->UpdateServerCardUsageStats(inputs.back());
+ inputs.back().set_billing_address_id("2");
+ table_->UpdateServerCardMetadata(inputs.back());
table_->GetServerCreditCards(&outputs);
ASSERT_EQ(1u, outputs.size());
EXPECT_EQ(masked_card.server_id(), outputs[0]->server_id());
EXPECT_EQ(4U, outputs[0]->use_count());
EXPECT_EQ(base::Time(), outputs[0]->use_date());
EXPECT_EQ(base::Time(), outputs[0]->modification_date());
+ EXPECT_EQ("2", outputs[0]->billing_address_id());
outputs.clear();
// Setting the cards again shouldn't delete the usage stats.
@@ -1761,6 +1766,7 @@ TEST_F(AutofillTableTest, SetServerCardUpdateUsageStats) {
EXPECT_EQ(4U, outputs[0]->use_count());
EXPECT_EQ(base::Time(), outputs[0]->use_date());
EXPECT_EQ(base::Time(), outputs[0]->modification_date());
+ EXPECT_EQ("2", outputs[0]->billing_address_id());
outputs.clear();
// Set a card list where the card is missing --- this should clear metadata.
@@ -1777,36 +1783,10 @@ TEST_F(AutofillTableTest, SetServerCardUpdateUsageStats) {
EXPECT_EQ(1U, outputs[0]->use_count());
EXPECT_NE(base::Time(), outputs[0]->use_date());
EXPECT_EQ(base::Time(), outputs[0]->modification_date());
+ EXPECT_EQ("1", outputs[0]->billing_address_id());
outputs.clear();
}
-TEST_F(AutofillTableTest, UpdateServerCardBillingAddress) {
- // Add a masked card.
- CreditCard masked_card(CreditCard::MASKED_SERVER_CARD, "a123");
- masked_card.SetRawInfo(CREDIT_CARD_NAME_FULL,
- ASCIIToUTF16("Paul F. Tompkins"));
- masked_card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("1"));
- masked_card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2020"));
- masked_card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("1111"));
- masked_card.set_billing_address_id("billing-address-id-1");
- masked_card.SetTypeForMaskedCard(kVisaCard);
- test::SetServerCreditCards(table_.get(),
- std::vector<CreditCard>(1, masked_card));
- std::vector<std::unique_ptr<CreditCard>> outputs;
- table_->GetServerCreditCards(&outputs);
- ASSERT_EQ(1u, outputs.size());
-
- EXPECT_EQ("billing-address-id-1", outputs[0]->billing_address_id());
-
- masked_card.set_billing_address_id("billing-address-id-2");
- table_->UpdateServerCardBillingAddress(masked_card);
- outputs.clear();
- table_->GetServerCreditCards(&outputs);
- ASSERT_EQ(1u, outputs.size());
-
- EXPECT_EQ("billing-address-id-2", outputs[0]->billing_address_id());
-}
-
TEST_F(AutofillTableTest, SetServerProfile) {
AutofillProfile one(AutofillProfile::SERVER_PROFILE, "a123");
std::vector<AutofillProfile> inputs;
@@ -1853,7 +1833,7 @@ TEST_F(AutofillTableTest, SetServerProfileUpdateUsageStats) {
// Update the usage stats; make sure they're reflected in GetServerProfiles.
inputs.back().set_use_count(4U);
inputs.back().set_use_date(base::Time::Now());
- table_->UpdateServerAddressUsageStats(inputs.back());
+ table_->UpdateServerAddressMetadata(inputs.back());
table_->GetServerProfiles(&outputs);
ASSERT_EQ(1u, outputs.size());
EXPECT_EQ(one.server_id(), outputs[0]->server_id());
@@ -2016,4 +1996,90 @@ TEST_F(AutofillTableTest, GetFormValuesForElementName_SubstringMatchEnabled) {
}
}
+TEST_F(AutofillTableTest, GetAllSyncMetadata) {
+ sync_pb::EntityMetadata metadata;
+ std::string storage_key = "storage_key";
+ std::string storage_key2 = "storage_key2";
+ metadata.set_sequence_number(1);
+
+ EXPECT_TRUE(
+ table_->UpdateSyncMetadata(syncer::AUTOFILL, storage_key, metadata));
+
+ sync_pb::ModelTypeState model_type_state;
+ model_type_state.set_initial_sync_done(true);
+
+ EXPECT_TRUE(table_->UpdateModelTypeState(syncer::AUTOFILL, model_type_state));
+
+ metadata.set_sequence_number(2);
+ EXPECT_TRUE(
+ table_->UpdateSyncMetadata(syncer::AUTOFILL, storage_key2, metadata));
+
+ syncer::MetadataBatch metadata_batch;
+ EXPECT_TRUE(table_->GetAllSyncMetadata(syncer::AUTOFILL, &metadata_batch));
+
+ EXPECT_TRUE(metadata_batch.GetModelTypeState().initial_sync_done());
+
+ syncer::EntityMetadataMap metadata_records = metadata_batch.TakeAllMetadata();
+
+ EXPECT_EQ(metadata_records.size(), 2u);
+ EXPECT_EQ(metadata_records[storage_key].sequence_number(), 1);
+ EXPECT_EQ(metadata_records[storage_key2].sequence_number(), 2);
+
+ // Now check that a model type state update replaces the old value
+ model_type_state.set_initial_sync_done(false);
+ EXPECT_TRUE(table_->UpdateModelTypeState(syncer::AUTOFILL, model_type_state));
+
+ EXPECT_TRUE(table_->GetAllSyncMetadata(syncer::AUTOFILL, &metadata_batch));
+ EXPECT_FALSE(metadata_batch.GetModelTypeState().initial_sync_done());
+}
+
+TEST_F(AutofillTableTest, WriteThenDeleteSyncMetadata) {
+ sync_pb::EntityMetadata metadata;
+ syncer::MetadataBatch metadata_batch;
+ std::string storage_key = "storage_key";
+ sync_pb::ModelTypeState model_type_state;
+
+ model_type_state.set_initial_sync_done(true);
+
+ metadata.set_client_tag_hash("client_hash");
+
+ // Write the data into the store.
+ EXPECT_TRUE(
+ table_->UpdateSyncMetadata(syncer::AUTOFILL, storage_key, metadata));
+ EXPECT_TRUE(table_->UpdateModelTypeState(syncer::AUTOFILL, model_type_state));
+ // Delete the data we just wrote.
+ EXPECT_TRUE(table_->ClearSyncMetadata(syncer::AUTOFILL, storage_key));
+ // It shouldn't be there any more.
+ EXPECT_TRUE(table_->GetAllSyncMetadata(syncer::AUTOFILL, &metadata_batch));
+
+ syncer::EntityMetadataMap metadata_records = metadata_batch.TakeAllMetadata();
+ EXPECT_EQ(metadata_records.size(), 0u);
+
+ // Now delete the model type state.
+ EXPECT_TRUE(table_->ClearModelTypeState(syncer::AUTOFILL));
+ EXPECT_FALSE(table_->GetAllSyncMetadata(syncer::AUTOFILL, &metadata_batch));
+}
+
+TEST_F(AutofillTableTest, CorruptSyncMetadata) {
+ syncer::MetadataBatch metadata_batch;
+ sync_pb::ModelTypeState state;
+ std::string storage_key = "storage_key";
+
+ sql::Statement s(db_->GetSQLConnection()->GetUniqueStatement(
+ "INSERT OR REPLACE INTO autofill_sync_metadata "
+ "(storage_key, value) VALUES(?, ?)"));
+ s.BindString(0, storage_key);
+ s.BindString(1, "unparseable");
+
+ sql::Statement s2(db_->GetSQLConnection()->GetUniqueStatement(
+ "INSERT OR REPLACE INTO autofill_model_type_state "
+ "(rowid, value) VALUES(1, ?)"));
+ s2.BindString(0, "unparseable");
+
+ EXPECT_TRUE(s.Run());
+ EXPECT_TRUE(s2.Run());
+
+ EXPECT_FALSE(table_->GetAllSyncMetadata(syncer::AUTOFILL, &metadata_batch));
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
index 3706d27701e..326ddc4ee15 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
@@ -10,7 +10,6 @@
#include "base/base64.h"
#include "base/bind.h"
-#include "base/containers/scoped_ptr_hash_map.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
@@ -41,29 +40,42 @@ void* UserDataKey() {
return reinterpret_cast<void*>(&user_data_key);
}
-// Returns syncable metadata for the |local| profile or credit card.
+// Sets the common syncable |metadata| for the |local_data_model|.
+void SetCommonMetadata(sync_pb::WalletMetadataSpecifics::Type type,
+ const std::string& server_id,
+ const AutofillDataModel& local_data_model,
+ sync_pb::WalletMetadataSpecifics* metadata) {
+ metadata->set_type(type);
+ metadata->set_id(server_id);
+ metadata->set_use_count(local_data_model.use_count());
+ metadata->set_use_date(local_data_model.use_date().ToInternalValue());
+}
+
+// Returns syncable metadata for the |local_profile|.
syncer::SyncData BuildSyncData(sync_pb::WalletMetadataSpecifics::Type type,
const std::string& server_id,
- const AutofillDataModel& local) {
+ const AutofillProfile& local_profile) {
sync_pb::EntitySpecifics entity;
sync_pb::WalletMetadataSpecifics* metadata = entity.mutable_wallet_metadata();
- metadata->set_type(type);
- metadata->set_id(server_id);
- metadata->set_use_count(local.use_count());
- metadata->set_use_date(local.use_date().ToInternalValue());
-
- std::string sync_tag;
- switch (type) {
- case sync_pb::WalletMetadataSpecifics::ADDRESS:
- sync_tag = "address-" + server_id;
- break;
- case sync_pb::WalletMetadataSpecifics::CARD:
- sync_tag = "card-" + server_id;
- break;
- case sync_pb::WalletMetadataSpecifics::UNKNOWN:
- NOTREACHED();
- break;
- }
+ SetCommonMetadata(type, server_id, local_profile, metadata);
+ metadata->set_address_has_converted(local_profile.has_converted());
+ std::string sync_tag = "address-" + server_id;
+
+ return syncer::SyncData::CreateLocalData(sync_tag, sync_tag, entity);
+}
+
+// Returns syncable metadata for the |local_card|.
+syncer::SyncData BuildSyncData(sync_pb::WalletMetadataSpecifics::Type type,
+ const std::string& server_id,
+ const CreditCard& local_card) {
+ sync_pb::EntitySpecifics entity;
+ sync_pb::WalletMetadataSpecifics* metadata = entity.mutable_wallet_metadata();
+ SetCommonMetadata(type, server_id, local_card, metadata);
+ // The strings must be in valid UTF-8 to sync.
+ std::string billing_address_id;
+ base::Base64Encode(local_card.billing_address_id(), &billing_address_id);
+ metadata->set_card_billing_address_id(billing_address_id);
+ std::string sync_tag = "card-" + server_id;
return syncer::SyncData::CreateLocalData(sync_tag, sync_tag, entity);
}
@@ -73,11 +85,12 @@ template <class DataType>
void UndeleteMetadataIfExisting(
const std::string& server_id,
const sync_pb::WalletMetadataSpecifics::Type& metadata_type,
- base::ScopedPtrHashMap<std::string, std::unique_ptr<DataType>>* locals,
+ std::unordered_map<std::string, std::unique_ptr<DataType>>* locals,
syncer::SyncChangeList* changes_to_sync) {
const auto& it = locals->find(server_id);
if (it != locals->end()) {
- std::unique_ptr<DataType> local_metadata = locals->take_and_erase(it);
+ std::unique_ptr<DataType> local_metadata = std::move(it->second);
+ locals->erase(it);
changes_to_sync->push_back(syncer::SyncChange(
FROM_HERE, syncer::SyncChange::ACTION_ADD,
BuildSyncData(metadata_type, server_id, *local_metadata)));
@@ -142,6 +155,89 @@ void ApplyChangesToCache(const syncer::SyncChangeList& changes,
}
}
+// Merges the metadata of the remote and local versions of the data model.
+void MergeCommonMetadata(
+ const sync_pb::WalletMetadataSpecifics& remote_metadata,
+ AutofillDataModel* local_model,
+ bool* is_remote_outdated,
+ bool* is_local_modified) {
+ size_t remote_use_count =
+ base::checked_cast<size_t>(remote_metadata.use_count());
+ if (local_model->use_count() < remote_use_count) {
+ local_model->set_use_count(remote_use_count);
+ *is_local_modified = true;
+ } else if (local_model->use_count() > remote_use_count) {
+ *is_remote_outdated = true;
+ }
+
+ base::Time remote_use_date =
+ base::Time::FromInternalValue(remote_metadata.use_date());
+ if (local_model->use_date() < remote_use_date) {
+ local_model->set_use_date(remote_use_date);
+ *is_local_modified = true;
+ } else if (local_model->use_date() > remote_use_date) {
+ *is_remote_outdated = true;
+ }
+}
+
+// Merges the metadata of the remote and local versions of the profile.
+void MergeMetadata(const sync_pb::WalletMetadataSpecifics& remote_metadata,
+ AutofillProfile* local_profile,
+ bool* is_remote_outdated,
+ bool* is_local_modified) {
+ // Merge the has_converted status.
+ if (local_profile->has_converted() !=
+ remote_metadata.address_has_converted()) {
+ if (!local_profile->has_converted()) {
+ local_profile->set_has_converted(true);
+ *is_local_modified = true;
+ } else {
+ *is_remote_outdated = true;
+ }
+ }
+
+ // Merge the use_count and use_date.
+ MergeCommonMetadata(remote_metadata, local_profile, is_remote_outdated,
+ is_local_modified);
+}
+
+// Merges the metadata of the remote and local versions of the credit card.
+void MergeMetadata(const sync_pb::WalletMetadataSpecifics& remote_metadata,
+ CreditCard* local_card,
+ bool* is_remote_outdated,
+ bool* is_local_modified) {
+ // Merge the billing_address_id. Do this before updating the use_count
+ // because it may be used to determine what id to keep.
+ std::string remote_billing_address_id;
+ base::Base64Decode(remote_metadata.card_billing_address_id(),
+ &remote_billing_address_id);
+
+ if (local_card->billing_address_id() != remote_billing_address_id) {
+ // If one of the values is empty, update it with the non empty value.
+ if (local_card->billing_address_id().empty()) {
+ local_card->set_billing_address_id(remote_billing_address_id);
+ *is_local_modified = true;
+ } else if (remote_billing_address_id.empty()) {
+ *is_remote_outdated = true;
+ } else {
+ // The cards have a different non-empty billing address id. Keep the
+ // billing address id of the most recently used card.
+ base::Time remote_use_date =
+ base::Time::FromInternalValue(remote_metadata.use_date());
+ if (local_card->use_date() < remote_use_date) {
+ local_card->set_billing_address_id(remote_billing_address_id);
+ *is_local_modified = true;
+ } else {
+ *is_remote_outdated = true;
+ }
+ }
+ }
+
+ // Merge the use_count and use_date.
+ MergeCommonMetadata(remote_metadata, local_card, is_remote_outdated,
+ is_local_modified);
+}
+
// Merges |remote| metadata into a collection of metadata |locals|. Returns true
// if the corresponding local metadata was found.
//
@@ -151,7 +247,7 @@ template <class DataType>
bool MergeRemote(
const syncer::SyncData& remote,
const base::Callback<bool(const DataType&)>& updater,
- base::ScopedPtrHashMap<std::string, std::unique_ptr<DataType>>* locals,
+ std::unordered_map<std::string, std::unique_ptr<DataType>>* locals,
syncer::SyncChangeList* changes_to_sync) {
DCHECK(locals);
DCHECK(changes_to_sync);
@@ -162,27 +258,13 @@ bool MergeRemote(
if (it == locals->end())
return false;
- std::unique_ptr<DataType> local_metadata = locals->take_and_erase(it);
+ std::unique_ptr<DataType> local_metadata = std::move(it->second);
+ locals->erase(it);
- size_t remote_use_count =
- base::checked_cast<size_t>(remote_metadata.use_count());
bool is_local_modified = false;
bool is_remote_outdated = false;
- if (local_metadata->use_count() < remote_use_count) {
- local_metadata->set_use_count(remote_use_count);
- is_local_modified = true;
- } else if (local_metadata->use_count() > remote_use_count) {
- is_remote_outdated = true;
- }
-
- base::Time remote_use_date =
- base::Time::FromInternalValue(remote_metadata.use_date());
- if (local_metadata->use_date() < remote_use_date) {
- local_metadata->set_use_date(remote_use_date);
- is_local_modified = true;
- } else if (local_metadata->use_date() > remote_use_date) {
- is_remote_outdated = true;
- }
+ MergeMetadata(remote_metadata, local_metadata.get(), &is_remote_outdated,
+ &is_local_modified);
if (is_remote_outdated) {
changes_to_sync->push_back(syncer::SyncChange(
@@ -247,9 +329,8 @@ syncer::SyncDataList AutofillWalletMetadataSyncableService::GetAllSyncData(
DCHECK_EQ(syncer::AUTOFILL_WALLET_METADATA, type);
syncer::SyncDataList data_list;
- base::ScopedPtrHashMap<std::string, std::unique_ptr<AutofillProfile>>
- profiles;
- base::ScopedPtrHashMap<std::string, std::unique_ptr<CreditCard>> cards;
+ std::unordered_map<std::string, std::unique_ptr<AutofillProfile>> profiles;
+ std::unordered_map<std::string, std::unique_ptr<CreditCard>> cards;
if (GetLocalData(&profiles, &cards)) {
for (const auto& it : profiles) {
data_list.push_back(BuildSyncData(
@@ -272,9 +353,8 @@ syncer::SyncError AutofillWalletMetadataSyncableService::ProcessSyncChanges(
ApplyChangesToCache(changes_from_sync, &cache_);
- base::ScopedPtrHashMap<std::string, std::unique_ptr<AutofillProfile>>
- profiles;
- base::ScopedPtrHashMap<std::string, std::unique_ptr<CreditCard>> cards;
+ std::unordered_map<std::string, std::unique_ptr<AutofillProfile>> profiles;
+ std::unordered_map<std::string, std::unique_ptr<CreditCard>> cards;
GetLocalData(&profiles, &cards);
// base::Unretained is used because the callbacks are invoked synchronously.
@@ -399,17 +479,15 @@ AutofillWalletMetadataSyncableService::AutofillWalletMetadataSyncableService(
}
bool AutofillWalletMetadataSyncableService::GetLocalData(
- base::ScopedPtrHashMap<std::string, std::unique_ptr<AutofillProfile>>*
- profiles,
- base::ScopedPtrHashMap<std::string, std::unique_ptr<CreditCard>>* cards)
- const {
+ std::unordered_map<std::string, std::unique_ptr<AutofillProfile>>* profiles,
+ std::unordered_map<std::string, std::unique_ptr<CreditCard>>* cards) const {
std::vector<std::unique_ptr<AutofillProfile>> profile_list;
bool success =
AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase())
->GetServerProfiles(&profile_list);
while (!profile_list.empty()) {
auto server_id = GetServerId(*profile_list.front());
- profiles->add(server_id, std::move(profile_list.front()));
+ (*profiles)[server_id] = std::move(profile_list.front());
profile_list.erase(profile_list.begin());
}
@@ -418,7 +496,7 @@ bool AutofillWalletMetadataSyncableService::GetLocalData(
->GetServerCreditCards(&card_list);
while (!card_list.empty()) {
auto server_id = GetServerId(*card_list.front());
- cards->add(server_id, std::move(card_list.front()));
+ (*cards)[server_id] = std::move(card_list.front());
card_list.erase(card_list.begin());
}
@@ -428,13 +506,13 @@ bool AutofillWalletMetadataSyncableService::GetLocalData(
bool AutofillWalletMetadataSyncableService::UpdateAddressStats(
const AutofillProfile& profile) {
return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase())
- ->UpdateServerAddressUsageStats(profile);
+ ->UpdateServerAddressMetadata(profile);
}
bool AutofillWalletMetadataSyncableService::UpdateCardStats(
const CreditCard& credit_card) {
return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase())
- ->UpdateServerCardUsageStats(credit_card);
+ ->UpdateServerCardMetadata(credit_card);
}
syncer::SyncError
@@ -447,9 +525,8 @@ AutofillWalletMetadataSyncableService::SendChangesToSyncServer(
syncer::SyncMergeResult AutofillWalletMetadataSyncableService::MergeData(
const syncer::SyncDataList& sync_data) {
- base::ScopedPtrHashMap<std::string, std::unique_ptr<AutofillProfile>>
- profiles;
- base::ScopedPtrHashMap<std::string, std::unique_ptr<CreditCard>> cards;
+ std::unordered_map<std::string, std::unique_ptr<AutofillProfile>> profiles;
+ std::unordered_map<std::string, std::unique_ptr<CreditCard>> cards;
GetLocalData(&profiles, &cards);
syncer::SyncMergeResult result(syncer::AUTOFILL_WALLET_METADATA);
@@ -518,16 +595,18 @@ syncer::SyncMergeResult AutofillWalletMetadataSyncableService::MergeData(
return result;
}
+template <class DataType>
void AutofillWalletMetadataSyncableService::AutofillDataModelChanged(
const std::string& server_id,
const sync_pb::WalletMetadataSpecifics::Type& type,
- const AutofillDataModel& local) {
+ const DataType& local) {
auto it = FindServerIdAndTypeInCache(server_id, type, &cache_);
if (it == cache_.end())
return;
const sync_pb::WalletMetadataSpecifics& remote =
it->GetSpecifics().wallet_metadata();
+
if (base::checked_cast<size_t>(remote.use_count()) < local.use_count() &&
base::Time::FromInternalValue(remote.use_date()) < local.use_date()) {
SendChangesToSyncServer(syncer::SyncChangeList(
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h
index 4987768f7e7..23edced9e32 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h
@@ -7,6 +7,7 @@
#include <memory>
#include <string>
+#include <unordered_map>
#include "base/callback_forward.h"
#include "base/macros.h"
@@ -20,14 +21,8 @@
#include "components/sync/model/syncable_service.h"
#include "components/sync/protocol/autofill_specifics.pb.h"
-namespace base {
-template <typename, typename>
-class ScopedPtrHashMap;
-}
-
namespace syncer {
class SyncChangeProcessor;
-class SyncData;
class SyncErrorFactory;
}
@@ -37,7 +32,6 @@ class Location;
namespace autofill {
-class AutofillDataModel;
class AutofillProfile;
class AutofillWebDataBackend;
class AutofillWebDataService;
@@ -97,9 +91,9 @@ class AutofillWalletMetadataSyncableService
// to server profiles and server cards read from disk. This data contains the
// usage stats. Returns true on success.
virtual bool GetLocalData(
- base::ScopedPtrHashMap<std::string, std::unique_ptr<AutofillProfile>>*
+ std::unordered_map<std::string, std::unique_ptr<AutofillProfile>>*
profiles,
- base::ScopedPtrHashMap<std::string, std::unique_ptr<CreditCard>>* cards)
+ std::unordered_map<std::string, std::unique_ptr<CreditCard>>* cards)
const;
// Updates the stats for |profile| stored on disk. Does not trigger
@@ -128,11 +122,13 @@ class AutofillWalletMetadataSyncableService
// is not present locally.
syncer::SyncMergeResult MergeData(const syncer::SyncDataList& sync_data);
- // Sends updates to the sync server.
+ // Sends the autofill data model updates to the sync server if the local
+ // version is more recent. Used for both profiles and credit cards.
+ template <class DataType>
void AutofillDataModelChanged(
const std::string& server_id,
const sync_pb::WalletMetadataSpecifics::Type& type,
- const AutofillDataModel& local);
+ const DataType& local);
base::ThreadChecker thread_checker_;
AutofillWebDataBackend* web_data_backend_; // Weak ref.
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc
index 70438328595..89439d7184c 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc
@@ -11,7 +11,6 @@
#include <vector>
#include "base/base64.h"
-#include "base/containers/scoped_ptr_hash_map.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
@@ -65,13 +64,13 @@ ACTION_P2(GetCopiesOf, profiles, cards) {
for (const auto& profile : *profiles) {
std::string utf8_server_id;
base::Base64Encode(profile.server_id(), &utf8_server_id);
- arg0->add(utf8_server_id, base::WrapUnique(new AutofillProfile(profile)));
+ (*arg0)[utf8_server_id] = base::MakeUnique<AutofillProfile>(profile);
}
for (const auto& card : *cards) {
std::string utf8_server_id;
base::Base64Encode(card.server_id(), &utf8_server_id);
- arg1->add(utf8_server_id, base::WrapUnique(new CreditCard(card)));
+ (*arg1)[utf8_server_id] = base::MakeUnique<CreditCard>(card);
}
}
@@ -121,9 +120,8 @@ class MockService : public AutofillWalletMetadataSyncableService {
private:
MOCK_CONST_METHOD2(
GetLocalData,
- bool(base::ScopedPtrHashMap<std::string,
- std::unique_ptr<AutofillProfile>>*,
- base::ScopedPtrHashMap<std::string, std::unique_ptr<CreditCard>>*));
+ bool(std::unordered_map<std::string, std::unique_ptr<AutofillProfile>>*,
+ std::unordered_map<std::string, std::unique_ptr<CreditCard>>*));
syncer::SyncError SendChangesToSyncServerConcrete(
const syncer::SyncChangeList& changes) {
@@ -185,28 +183,33 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest, NoMetadataToReturn) {
AutofillProfile BuildAddress(const std::string& server_id,
int64_t use_count,
- int64_t use_date) {
+ int64_t use_date,
+ bool has_converted) {
AutofillProfile profile(AutofillProfile::SERVER_PROFILE, server_id);
profile.set_use_count(use_count);
profile.set_use_date(base::Time::FromInternalValue(use_date));
+ profile.set_has_converted(has_converted);
return profile;
}
CreditCard BuildCard(const std::string& server_id,
int64_t use_count,
- int64_t use_date) {
+ int64_t use_date,
+ const std::string& billing_address_id) {
CreditCard card(CreditCard::MASKED_SERVER_CARD, server_id);
card.set_use_count(use_count);
card.set_use_date(base::Time::FromInternalValue(use_date));
+ card.set_billing_address_id(billing_address_id);
return card;
}
-MATCHER_P5(SyncDataMatches,
+MATCHER_P6(SyncAddressDataMatches,
sync_tag,
metadata_type,
server_id,
use_count,
use_date,
+ has_converted,
"") {
return arg.IsValid() &&
syncer::AUTOFILL_WALLET_METADATA == arg.GetDataType() &&
@@ -214,22 +217,43 @@ MATCHER_P5(SyncDataMatches,
metadata_type == arg.GetSpecifics().wallet_metadata().type() &&
server_id == arg.GetSpecifics().wallet_metadata().id() &&
use_count == arg.GetSpecifics().wallet_metadata().use_count() &&
- use_date == arg.GetSpecifics().wallet_metadata().use_date();
+ use_date == arg.GetSpecifics().wallet_metadata().use_date() &&
+ has_converted ==
+ arg.GetSpecifics().wallet_metadata().address_has_converted();
+}
+
+MATCHER_P6(SyncCardDataMatches,
+ sync_tag,
+ metadata_type,
+ server_id,
+ use_count,
+ use_date,
+ billing_address_id,
+ "") {
+ return arg.IsValid() &&
+ syncer::AUTOFILL_WALLET_METADATA == arg.GetDataType() &&
+ sync_tag == syncer::SyncDataLocal(arg).GetTag() &&
+ metadata_type == arg.GetSpecifics().wallet_metadata().type() &&
+ server_id == arg.GetSpecifics().wallet_metadata().id() &&
+ use_count == arg.GetSpecifics().wallet_metadata().use_count() &&
+ use_date == arg.GetSpecifics().wallet_metadata().use_date() &&
+ billing_address_id ==
+ arg.GetSpecifics().wallet_metadata().card_billing_address_id();
}
// Verify that all metadata from disk is sent to the sync server.
TEST_F(AutofillWalletMetadataSyncableServiceTest, ReturnAllMetadata) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4));
-
- EXPECT_THAT(
- local_.GetAllSyncData(syncer::AUTOFILL_WALLET_METADATA),
- UnorderedElementsAre(
- SyncDataMatches(kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8,
- 1, 2),
- SyncDataMatches(kCard1SyncTag, sync_pb::WalletMetadataSpecifics::CARD,
- kCard1Utf8, 3, 4)));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+
+ EXPECT_THAT(local_.GetAllSyncData(syncer::AUTOFILL_WALLET_METADATA),
+ UnorderedElementsAre(
+ SyncAddressDataMatches(
+ kAddr1SyncTag, sync_pb::WalletMetadataSpecifics::ADDRESS,
+ kAddr1Utf8, 1, 2, true),
+ SyncCardDataMatches(kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD,
+ kCard1Utf8, 3, 4, kAddr1Utf8)));
}
void MergeMetadata(MockService* local, MockService* remote) {
@@ -272,8 +296,8 @@ MATCHER_P2(SyncChangeMatches, change_type, sync_tag, "") {
// Verify that remote data without local counterpart is deleted during the
// initial merge.
TEST_F(AutofillWalletMetadataSyncableServiceTest, DeleteFromServerOnMerge) {
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
@@ -287,37 +311,53 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest, DeleteFromServerOnMerge) {
MergeMetadata(&local_, &remote_);
}
-MATCHER_P6(SyncChangeAndDataMatch,
+MATCHER_P7(SyncAddressChangeAndDataMatch,
+ change_type,
+ sync_tag,
+ metadata_type,
+ server_id,
+ use_count,
+ use_date,
+ has_converted,
+ "") {
+ return Value(arg, SyncChangeMatches(change_type, sync_tag)) &&
+ Value(arg.sync_data(),
+ SyncAddressDataMatches(sync_tag, metadata_type, server_id,
+ use_count, use_date, has_converted));
+}
+
+MATCHER_P7(SyncCardChangeAndDataMatch,
change_type,
sync_tag,
metadata_type,
server_id,
use_count,
use_date,
+ billing_address_id,
"") {
return Value(arg, SyncChangeMatches(change_type, sync_tag)) &&
Value(arg.sync_data(),
- SyncDataMatches(sync_tag, metadata_type, server_id, use_count,
- use_date));
+ SyncCardDataMatches(sync_tag, metadata_type, server_id,
+ use_count, use_date, billing_address_id));
}
// Verify that local data is sent to the sync server during the initial merge,
// if the server does not have the data already.
TEST_F(AutofillWalletMetadataSyncableServiceTest, AddToServerOnMerge) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(
- local_,
- SendChangesToSyncServer(UnorderedElementsAre(
- SyncChangeAndDataMatch(syncer::SyncChange::ACTION_ADD, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS,
- kAddr1Utf8, 1, 2),
- SyncChangeAndDataMatch(syncer::SyncChange::ACTION_ADD, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard1Utf8, 3, 4))));
+ EXPECT_CALL(local_, SendChangesToSyncServer(UnorderedElementsAre(
+ SyncAddressChangeAndDataMatch(
+ syncer::SyncChange::ACTION_ADD, kAddr1SyncTag,
+ sync_pb::WalletMetadataSpecifics::ADDRESS,
+ kAddr1Utf8, 1, 2, true),
+ SyncCardChangeAndDataMatch(
+ syncer::SyncChange::ACTION_ADD, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD,
+ kCard1Utf8, 3, 4, kAddr1Utf8))));
MergeMetadata(&local_, &remote_);
}
@@ -326,10 +366,10 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest, AddToServerOnMerge) {
// local and remote data are identical during the initial merge.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
IgnoreIdenticalValuesOnMerge) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
@@ -338,24 +378,43 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
MergeMetadata(&local_, &remote_);
}
-MATCHER_P3(AutofillMetadataMatches, server_id, use_count, use_date, "") {
+MATCHER_P4(AutofillAddressMetadataMatches,
+ server_id,
+ use_count,
+ use_date,
+ has_converted,
+ "") {
+ return arg.server_id() == server_id &&
+ arg.use_count() == base::checked_cast<size_t>(use_count) &&
+ arg.use_date() == base::Time::FromInternalValue(use_date) &&
+ arg.has_converted() == has_converted;
+}
+
+MATCHER_P4(AutofillCardMetadataMatches,
+ server_id,
+ use_count,
+ use_date,
+ billing_address_id,
+ "") {
return arg.server_id() == server_id &&
arg.use_count() == base::checked_cast<size_t>(use_count) &&
- arg.use_date() == base::Time::FromInternalValue(use_date);
+ arg.use_date() == base::Time::FromInternalValue(use_date) &&
+ arg.billing_address_id() == billing_address_id;
}
// Verify that remote data with higher values of use count and last use date is
// saved to disk during the initial merge.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
SaveHigherValuesLocallyOnMerge) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 10, 20));
- remote_.UpdateCardStats(BuildCard(kCard1, 30, 40));
-
- EXPECT_CALL(local_,
- UpdateAddressStats(AutofillMetadataMatches(kAddr1, 10, 20)));
- EXPECT_CALL(local_, UpdateCardStats(AutofillMetadataMatches(kCard1, 30, 40)));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 10, 20, true));
+ remote_.UpdateCardStats(BuildCard(kCard1, 30, 40, kAddr1));
+
+ EXPECT_CALL(local_, UpdateAddressStats(AutofillAddressMetadataMatches(
+ kAddr1, 10, 20, true)));
+ EXPECT_CALL(local_, UpdateCardStats(
+ AutofillCardMetadataMatches(kCard1, 30, 40, kAddr1)));
EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
MergeMetadata(&local_, &remote_);
@@ -365,22 +424,22 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// sent to the sync server during the initial merge.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
SendHigherValuesToServerOnMerge) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 10, 20));
- local_.UpdateCardStats(BuildCard(kCard1, 30, 40));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 10, 20, true));
+ local_.UpdateCardStats(BuildCard(kCard1, 30, 40, kAddr1));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr2));
EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(
- local_,
- SendChangesToSyncServer(UnorderedElementsAre(
- SyncChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 10, 20),
- SyncChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 30, 40))));
+ EXPECT_CALL(local_, SendChangesToSyncServer(UnorderedElementsAre(
+ SyncAddressChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
+ sync_pb::WalletMetadataSpecifics::ADDRESS,
+ kAddr1Utf8, 10, 20, true),
+ SyncCardChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD,
+ kCard1Utf8, 30, 40, kAddr1Utf8))));
MergeMetadata(&local_, &remote_);
}
@@ -389,13 +448,13 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// local metadata is updated.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
DontSendLowerValueToServerOnSingleChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
- AutofillProfile address = BuildAddress(kAddr1, 0, 0);
- CreditCard card = BuildCard(kCard1, 0, 0);
+ AutofillProfile address = BuildAddress(kAddr1, 0, 0, false);
+ CreditCard card = BuildCard(kCard1, 0, 0, kAddr2);
EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
@@ -409,24 +468,24 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// metadata is updated.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
SendHigherValuesToServerOnLocalSingleChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
- AutofillProfile address = BuildAddress(kAddr1, 10, 20);
- CreditCard card = BuildCard(kCard1, 30, 40);
+ AutofillProfile address = BuildAddress(kAddr1, 10, 20, true);
+ CreditCard card = BuildCard(kCard1, 30, 40, kAddr2);
- EXPECT_CALL(
- local_,
- SendChangesToSyncServer(ElementsAre(SyncChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 10, 20))));
- EXPECT_CALL(
- local_,
- SendChangesToSyncServer(ElementsAre(SyncChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 30, 40))));
+ EXPECT_CALL(local_,
+ SendChangesToSyncServer(ElementsAre(SyncAddressChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
+ sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 10, 20,
+ true))));
+ EXPECT_CALL(local_,
+ SendChangesToSyncServer(ElementsAre(SyncCardChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 30, 40,
+ kAddr2Utf8))));
local_.AutofillProfileChanged(AutofillProfileChange(
AutofillProfileChange::UPDATE, address.guid(), &address));
@@ -439,13 +498,13 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// instead.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
DontAddToServerOnSingleChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
- AutofillProfile address = BuildAddress(kAddr2, 5, 6);
- CreditCard card = BuildCard(kCard2, 7, 8);
+ AutofillProfile address = BuildAddress(kAddr2, 5, 6, false);
+ CreditCard card = BuildCard(kCard2, 7, 8, kAddr2);
EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
@@ -458,24 +517,24 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// Verify that new metadata is sent to the sync server when multiple metadata
// values change at once.
TEST_F(AutofillWalletMetadataSyncableServiceTest, AddToServerOnMultiChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
// These methods do not trigger notifications or sync:
- local_.UpdateAddressStats(BuildAddress(kAddr2, 5, 6));
- local_.UpdateCardStats(BuildCard(kCard2, 7, 8));
-
- EXPECT_CALL(
- local_,
- SendChangesToSyncServer(UnorderedElementsAre(
- SyncChangeAndDataMatch(syncer::SyncChange::ACTION_ADD, kAddr2SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS,
- kAddr2Utf8, 5, 6),
- SyncChangeAndDataMatch(syncer::SyncChange::ACTION_ADD, kCard2SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard2Utf8, 7, 8))));
+ local_.UpdateAddressStats(BuildAddress(kAddr2, 5, 6, true));
+ local_.UpdateCardStats(BuildCard(kCard2, 7, 8, kAddr2));
+
+ EXPECT_CALL(local_, SendChangesToSyncServer(UnorderedElementsAre(
+ SyncAddressChangeAndDataMatch(
+ syncer::SyncChange::ACTION_ADD, kAddr2SyncTag,
+ sync_pb::WalletMetadataSpecifics::ADDRESS,
+ kAddr2Utf8, 5, 6, true),
+ SyncCardChangeAndDataMatch(
+ syncer::SyncChange::ACTION_ADD, kCard2SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD,
+ kCard2Utf8, 7, 8, kAddr2Utf8))));
local_.AutofillMultipleChanged();
}
@@ -484,24 +543,24 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest, AddToServerOnMultiChange) {
// when multiple metadata values change at once.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
UpdateToHigherValueOnServerOnMultiChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
// These methods do not trigger notifications or sync:
- local_.UpdateAddressStats(BuildAddress(kAddr1, 5, 6));
- local_.UpdateCardStats(BuildCard(kCard1, 7, 8));
-
- EXPECT_CALL(
- local_,
- SendChangesToSyncServer(UnorderedElementsAre(
- SyncChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 5, 6),
- SyncChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 7, 8))));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 5, 6, true));
+ local_.UpdateCardStats(BuildCard(kCard1, 7, 8, kAddr2));
+
+ EXPECT_CALL(local_, SendChangesToSyncServer(UnorderedElementsAre(
+ SyncAddressChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
+ sync_pb::WalletMetadataSpecifics::ADDRESS,
+ kAddr1Utf8, 5, 6, true),
+ SyncCardChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD,
+ kCard1Utf8, 7, 8, kAddr2Utf8))));
local_.AutofillMultipleChanged();
}
@@ -510,14 +569,14 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// when multiple metadata values change at once.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
DontUpdateToLowerValueOnServerOnMultiChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
// These methods do not trigger notifications or sync:
- local_.UpdateAddressStats(BuildAddress(kAddr1, 0, 0));
- local_.UpdateCardStats(BuildCard(kCard1, 0, 0));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 0, 0, false));
+ local_.UpdateCardStats(BuildCard(kCard1, 0, 0, kAddr2));
EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
@@ -528,10 +587,10 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// multiple metadata values change at once.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
DeleteFromServerOnMultiChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
// This method dooes not trigger notifications or sync:
local_.ClearServerData();
@@ -549,10 +608,10 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// Verify that empty sync change from the sync server does not trigger writing
// to disk or sending any data to the sync server.
TEST_F(AutofillWalletMetadataSyncableServiceTest, EmptySyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
@@ -562,18 +621,49 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest, EmptySyncChange) {
local_.ProcessSyncChanges(FROM_HERE, syncer::SyncChangeList());
}
-syncer::SyncChange BuildChange(
+void BuildBasicChange(syncer::SyncChange::SyncChangeType change_type,
+ const std::string& sync_tag,
+ sync_pb::WalletMetadataSpecifics::Type metadata_type,
+ const std::string& server_id,
+ int64_t use_count,
+ int64_t use_date,
+ sync_pb::EntitySpecifics* entity) {
+ entity->mutable_wallet_metadata()->set_type(metadata_type);
+ entity->mutable_wallet_metadata()->set_id(server_id);
+ entity->mutable_wallet_metadata()->set_use_count(use_count);
+ entity->mutable_wallet_metadata()->set_use_date(use_date);
+}
+
+syncer::SyncChange BuildAddressChange(
+ syncer::SyncChange::SyncChangeType change_type,
+ const std::string& sync_tag,
+ sync_pb::WalletMetadataSpecifics::Type metadata_type,
+ const std::string& server_id,
+ int64_t use_count,
+ int64_t use_date,
+ bool has_converted) {
+ sync_pb::EntitySpecifics entity;
+ BuildBasicChange(change_type, sync_tag, metadata_type, server_id, use_count,
+ use_date, &entity);
+ entity.mutable_wallet_metadata()->set_address_has_converted(has_converted);
+ return syncer::SyncChange(
+ FROM_HERE, change_type,
+ syncer::SyncData::CreateLocalData(sync_tag, sync_tag, entity));
+}
+
+syncer::SyncChange BuildCardChange(
syncer::SyncChange::SyncChangeType change_type,
const std::string& sync_tag,
sync_pb::WalletMetadataSpecifics::Type metadata_type,
const std::string& server_id,
int64_t use_count,
- int64_t use_date) {
+ int64_t use_date,
+ const std::string& billing_address_id) {
sync_pb::EntitySpecifics entity;
- entity.mutable_wallet_metadata()->set_type(metadata_type);
- entity.mutable_wallet_metadata()->set_id(server_id);
- entity.mutable_wallet_metadata()->set_use_count(use_count);
- entity.mutable_wallet_metadata()->set_use_date(use_date);
+ BuildBasicChange(change_type, sync_tag, metadata_type, server_id, use_count,
+ use_date, &entity);
+ entity.mutable_wallet_metadata()->set_card_billing_address_id(
+ billing_address_id);
return syncer::SyncChange(
FROM_HERE, change_type,
syncer::SyncData::CreateLocalData(sync_tag, sync_tag, entity));
@@ -584,18 +674,18 @@ syncer::SyncChange BuildChange(
// server.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
IgnoreNewMetadataFromServerOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
syncer::SyncChangeList changes;
- changes.push_back(BuildChange(syncer::SyncChange::ACTION_ADD, kAddr2SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS,
- kAddr2Utf8, 5, 6));
- changes.push_back(BuildChange(syncer::SyncChange::ACTION_ADD, kCard2SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard2Utf8, 7, 8));
+ changes.push_back(BuildAddressChange(
+ syncer::SyncChange::ACTION_ADD, kAddr2SyncTag,
+ sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr2Utf8, 5, 6, true));
+ changes.push_back(BuildCardChange(
+ syncer::SyncChange::ACTION_ADD, kCard2SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD, kCard2Utf8, 7, 8, kAddr2Utf8));
EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
@@ -608,22 +698,23 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// disk when processing on-going sync changes.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
SaveHigherValuesFromServerOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
syncer::SyncChangeList changes;
- changes.push_back(BuildChange(
+ changes.push_back(BuildAddressChange(
syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 10, 20));
- changes.push_back(
- BuildChange(syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 30, 40));
-
- EXPECT_CALL(local_,
- UpdateAddressStats(AutofillMetadataMatches(kAddr1, 10, 20)));
- EXPECT_CALL(local_, UpdateCardStats(AutofillMetadataMatches(kCard1, 30, 40)));
+ sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 10, 20, true));
+ changes.push_back(BuildCardChange(
+ syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 30, 40, kAddr2Utf8));
+
+ EXPECT_CALL(local_, UpdateAddressStats(AutofillAddressMetadataMatches(
+ kAddr1, 10, 20, true)));
+ EXPECT_CALL(local_, UpdateCardStats(
+ AutofillCardMetadataMatches(kCard1, 30, 40, kAddr2)));
EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
local_.ProcessSyncChanges(FROM_HERE, changes);
@@ -633,30 +724,30 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// processing on-going sync changes.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
SendHigherValuesToServerOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
syncer::SyncChangeList changes;
- changes.push_back(
- BuildChange(syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 0, 0));
- changes.push_back(
- BuildChange(syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 0, 0));
+ changes.push_back(BuildAddressChange(
+ syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
+ sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 0, 0, false));
+ changes.push_back(BuildCardChange(
+ syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 0, 0, kAddr2Utf8));
EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(
- local_,
- SendChangesToSyncServer(UnorderedElementsAre(
- SyncChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 1, 2),
- SyncChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 3, 4))));
+ EXPECT_CALL(local_, SendChangesToSyncServer(UnorderedElementsAre(
+ SyncAddressChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
+ sync_pb::WalletMetadataSpecifics::ADDRESS,
+ kAddr1Utf8, 1, 2, true),
+ SyncCardChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD,
+ kCard1Utf8, 3, 4, kAddr1Utf8))));
local_.ProcessSyncChanges(FROM_HERE, changes);
}
@@ -664,30 +755,30 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// Verify that addition of known metadata is treated the same as an update.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
TreatAdditionOfKnownMetadataAsUpdateOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
syncer::SyncChangeList changes;
- changes.push_back(BuildChange(syncer::SyncChange::ACTION_ADD, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS,
- kAddr1Utf8, 0, 0));
- changes.push_back(BuildChange(syncer::SyncChange::ACTION_ADD, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard1Utf8, 0, 0));
+ changes.push_back(BuildAddressChange(
+ syncer::SyncChange::ACTION_ADD, kAddr1SyncTag,
+ sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 0, 0, false));
+ changes.push_back(BuildCardChange(
+ syncer::SyncChange::ACTION_ADD, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 0, 0, kAddr2Utf8));
EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(
- local_,
- SendChangesToSyncServer(UnorderedElementsAre(
- SyncChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 1, 2),
- SyncChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 3, 4))));
+ EXPECT_CALL(local_, SendChangesToSyncServer(UnorderedElementsAre(
+ SyncAddressChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
+ sync_pb::WalletMetadataSpecifics::ADDRESS,
+ kAddr1Utf8, 1, 2, true),
+ SyncCardChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD,
+ kCard1Utf8, 3, 4, kAddr1Utf8))));
local_.ProcessSyncChanges(FROM_HERE, changes);
}
@@ -696,18 +787,18 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// no disk writes and no messages sent to the server.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
IgnoreUpdateOfUnknownMetadataOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
syncer::SyncChangeList changes;
- changes.push_back(
- BuildChange(syncer::SyncChange::ACTION_UPDATE, kAddr2SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr2Utf8, 0, 0));
- changes.push_back(
- BuildChange(syncer::SyncChange::ACTION_UPDATE, kCard2SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard2Utf8, 0, 0));
+ changes.push_back(BuildAddressChange(
+ syncer::SyncChange::ACTION_UPDATE, kAddr2SyncTag,
+ sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr2Utf8, 0, 0, false));
+ changes.push_back(BuildCardChange(
+ syncer::SyncChange::ACTION_UPDATE, kCard2SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD, kCard2Utf8, 0, 0, kAddr2Utf8));
EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
@@ -720,18 +811,18 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// ignored. There should be no disk writes and no messages sent to the server.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
IgnoreDeleteOfUnknownMetadataOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
syncer::SyncChangeList changes;
- changes.push_back(
- BuildChange(syncer::SyncChange::ACTION_DELETE, kAddr2SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr2Utf8, 0, 0));
- changes.push_back(
- BuildChange(syncer::SyncChange::ACTION_DELETE, kCard2SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard2Utf8, 0, 0));
+ changes.push_back(BuildAddressChange(
+ syncer::SyncChange::ACTION_DELETE, kAddr2SyncTag,
+ sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr2Utf8, 0, 0, false));
+ changes.push_back(BuildCardChange(
+ syncer::SyncChange::ACTION_DELETE, kCard2SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD, kCard2Utf8, 0, 0, kAddr2Utf8));
EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
@@ -744,30 +835,30 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// trigger an undelete message sent to the server.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
UndeleteExistingMetadataOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
syncer::SyncChangeList changes;
- changes.push_back(
- BuildChange(syncer::SyncChange::ACTION_DELETE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 0, 0));
- changes.push_back(
- BuildChange(syncer::SyncChange::ACTION_DELETE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 0, 0));
+ changes.push_back(BuildAddressChange(
+ syncer::SyncChange::ACTION_DELETE, kAddr1SyncTag,
+ sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 0, 0, false));
+ changes.push_back(BuildCardChange(
+ syncer::SyncChange::ACTION_DELETE, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 0, 0, kAddr2Utf8));
EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(
- local_,
- SendChangesToSyncServer(UnorderedElementsAre(
- SyncChangeAndDataMatch(syncer::SyncChange::ACTION_ADD, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS,
- kAddr1Utf8, 1, 2),
- SyncChangeAndDataMatch(syncer::SyncChange::ACTION_ADD, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard1Utf8, 3, 4))));
+ EXPECT_CALL(local_, SendChangesToSyncServer(UnorderedElementsAre(
+ SyncAddressChangeAndDataMatch(
+ syncer::SyncChange::ACTION_ADD, kAddr1SyncTag,
+ sync_pb::WalletMetadataSpecifics::ADDRESS,
+ kAddr1Utf8, 1, 2, true),
+ SyncCardChangeAndDataMatch(
+ syncer::SyncChange::ACTION_ADD, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD,
+ kCard1Utf8, 3, 4, kAddr1Utf8))));
local_.ProcessSyncChanges(FROM_HERE, changes);
}
@@ -776,22 +867,22 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// data, which is used to avoid calling the expensive GetAllSyncData() function.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
CacheIsUpToDateAfterSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- local_.UpdateAddressStats(BuildAddress(kAddr2, 3, 4));
- local_.UpdateCardStats(BuildCard(kCard1, 5, 6));
- local_.UpdateCardStats(BuildCard(kCard2, 7, 8));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateAddressStats(BuildAddress(kAddr2, 3, 4));
- remote_.UpdateCardStats(BuildCard(kCard1, 5, 6));
- remote_.UpdateCardStats(BuildCard(kCard2, 7, 8));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateAddressStats(BuildAddress(kAddr2, 3, 4, false));
+ local_.UpdateCardStats(BuildCard(kCard1, 5, 6, kAddr1));
+ local_.UpdateCardStats(BuildCard(kCard2, 7, 8, kAddr2));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateAddressStats(BuildAddress(kAddr2, 3, 4, false));
+ remote_.UpdateCardStats(BuildCard(kCard1, 5, 6, kAddr1));
+ remote_.UpdateCardStats(BuildCard(kCard2, 7, 8, kAddr2));
MergeMetadata(&local_, &remote_);
syncer::SyncChangeList changes;
- changes.push_back(BuildChange(
+ changes.push_back(BuildAddressChange(
syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 10, 20));
- changes.push_back(
- BuildChange(syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 50, 60));
+ sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 10, 20, false));
+ changes.push_back(BuildCardChange(
+ syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 50, 60, kAddr1Utf8));
local_.ProcessSyncChanges(FROM_HERE, changes);
// This method dooes not trigger notifications or sync:
local_.ClearServerData();
@@ -812,23 +903,24 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// values to the sync server.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
SaveHigherValuesLocallyOnLateDataArrival) {
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
+ remote_.UpdateCardStats(BuildCard(kCard1, 5, 6, kAddr1));
MergeMetadata(&local_, &remote_);
syncer::SyncChangeList changes;
- changes.push_back(
- BuildChange(syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 5, 6));
- changes.push_back(
- BuildChange(syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 7, 8));
+ changes.push_back(BuildAddressChange(
+ syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
+ sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 5, 6, true));
+ changes.push_back(BuildCardChange(
+ syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 7, 8, kAddr2Utf8));
local_.ProcessSyncChanges(FROM_HERE, changes);
- local_.UpdateAddressStats(BuildAddress(kAddr1, 0, 0));
- local_.UpdateCardStats(BuildCard(kCard1, 0, 0));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 0, 0, true));
+ local_.UpdateCardStats(BuildCard(kCard1, 0, 0, kAddr2));
- EXPECT_CALL(local_,
- UpdateAddressStats(AutofillMetadataMatches(kAddr1, 5, 6)));
- EXPECT_CALL(local_, UpdateCardStats(AutofillMetadataMatches(kCard1, 7, 8)));
+ EXPECT_CALL(local_, UpdateAddressStats(
+ AutofillAddressMetadataMatches(kAddr1, 5, 6, true)));
+ EXPECT_CALL(local_, UpdateCardStats(
+ AutofillCardMetadataMatches(kCard1, 7, 8, kAddr2)));
EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
local_.AutofillMultipleChanged();
@@ -839,42 +931,133 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// once the data finally arrives.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
SaveHigherValuesLocallyOnLateDataArrivalAfterPartialUpdates) {
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2));
- remote_.UpdateAddressStats(BuildAddress(kAddr2, 3, 4));
- remote_.UpdateCardStats(BuildCard(kCard1, 5, 6));
- remote_.UpdateCardStats(BuildCard(kCard2, 7, 8));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
+ remote_.UpdateAddressStats(BuildAddress(kAddr2, 3, 4, false));
+ remote_.UpdateCardStats(BuildCard(kCard1, 5, 6, kAddr1));
+ remote_.UpdateCardStats(BuildCard(kCard2, 7, 8, kAddr1));
MergeMetadata(&local_, &remote_);
syncer::SyncChangeList changes;
- changes.push_back(BuildChange(
+ changes.push_back(BuildAddressChange(
syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 9, 10));
- changes.push_back(
- BuildChange(syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 11, 12));
- changes.push_back(BuildChange(
+ sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 9, 10, false));
+ changes.push_back(BuildCardChange(
+ syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 11, 12, kAddr2Utf8));
+ changes.push_back(BuildAddressChange(
syncer::SyncChange::ACTION_UPDATE, kAddr2SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr2Utf8, 13, 14));
- changes.push_back(
- BuildChange(syncer::SyncChange::ACTION_UPDATE, kCard2SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard2Utf8, 15, 16));
+ sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr2Utf8, 13, 14, true));
+ changes.push_back(BuildCardChange(
+ syncer::SyncChange::ACTION_UPDATE, kCard2SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD, kCard2Utf8, 15, 16, kAddr1Utf8));
local_.ProcessSyncChanges(FROM_HERE, changes);
changes.resize(2);
local_.ProcessSyncChanges(FROM_HERE, changes);
- local_.UpdateAddressStats(BuildAddress(kAddr1, 0, 0));
- local_.UpdateAddressStats(BuildAddress(kAddr2, 0, 0));
- local_.UpdateCardStats(BuildCard(kCard1, 0, 0));
- local_.UpdateCardStats(BuildCard(kCard2, 0, 0));
-
- EXPECT_CALL(local_,
- UpdateAddressStats(AutofillMetadataMatches(kAddr1, 9, 10)));
- EXPECT_CALL(local_, UpdateCardStats(AutofillMetadataMatches(kCard1, 11, 12)));
- EXPECT_CALL(local_,
- UpdateAddressStats(AutofillMetadataMatches(kAddr2, 13, 14)));
- EXPECT_CALL(local_, UpdateCardStats(AutofillMetadataMatches(kCard2, 15, 16)));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 0, 0, false));
+ local_.UpdateAddressStats(BuildAddress(kAddr2, 0, 0, false));
+ local_.UpdateCardStats(BuildCard(kCard1, 0, 0, kAddr1));
+ local_.UpdateCardStats(BuildCard(kCard2, 0, 0, kAddr2));
+
+ EXPECT_CALL(local_, UpdateAddressStats(AutofillAddressMetadataMatches(
+ kAddr1, 9, 10, false)));
+ EXPECT_CALL(local_, UpdateCardStats(
+ AutofillCardMetadataMatches(kCard1, 11, 12, kAddr2)));
+ EXPECT_CALL(local_, UpdateAddressStats(AutofillAddressMetadataMatches(
+ kAddr2, 13, 14, true)));
+ EXPECT_CALL(local_, UpdateCardStats(
+ AutofillCardMetadataMatches(kCard2, 15, 16, kAddr1)));
EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
local_.AutofillMultipleChanged();
}
+// Verify that the merge logic keeps the best data on a field by field basis.
+// Make sure that if the better data is split across the local and server
+// version, both are updated with the merge results.
+TEST_F(AutofillWalletMetadataSyncableServiceTest, SaveHigherValues_Mixed1) {
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 20, true));
+ local_.UpdateCardStats(BuildCard(kCard1, 30, 4, ""));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 10, 2, false));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 40, kAddr1));
+
+ EXPECT_CALL(local_, UpdateAddressStats(AutofillAddressMetadataMatches(
+ kAddr1, 10, 20, true)));
+ EXPECT_CALL(local_, UpdateCardStats(
+ AutofillCardMetadataMatches(kCard1, 30, 40, kAddr1)));
+ EXPECT_CALL(local_, SendChangesToSyncServer(UnorderedElementsAre(
+ SyncAddressChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
+ sync_pb::WalletMetadataSpecifics::ADDRESS,
+ kAddr1Utf8, 10, 20, true),
+ SyncCardChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD,
+ kCard1Utf8, 30, 40, kAddr1Utf8))));
+
+ MergeMetadata(&local_, &remote_);
+}
+
+// Verify that the merge logic keeps the best data on a field by field basis.
+// Make sure that if the better data is split across the local and server
+// version, both are updated with the merge results.
+// Same as SaveHigherValues_Mixed1 but with the higher values moved from local
+// to server and vice versa.
+TEST_F(AutofillWalletMetadataSyncableServiceTest, SaveHigherValues_Mixed2) {
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 10, 2, false));
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 40, kAddr1));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 20, true));
+ remote_.UpdateCardStats(BuildCard(kCard1, 30, 4, ""));
+
+ EXPECT_CALL(local_, UpdateAddressStats(AutofillAddressMetadataMatches(
+ kAddr1, 10, 20, true)));
+ EXPECT_CALL(local_, UpdateCardStats(
+ AutofillCardMetadataMatches(kCard1, 30, 40, kAddr1)));
+ EXPECT_CALL(local_, SendChangesToSyncServer(UnorderedElementsAre(
+ SyncAddressChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
+ sync_pb::WalletMetadataSpecifics::ADDRESS,
+ kAddr1Utf8, 10, 20, true),
+ SyncCardChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD,
+ kCard1Utf8, 30, 40, kAddr1Utf8))));
+
+ MergeMetadata(&local_, &remote_);
+}
+
+// Verify that if both local and server have a different non empty billing
+// address id, the one with the most recent (bigger) use date is kept.
+TEST_F(AutofillWalletMetadataSyncableServiceTest,
+ SaveHigherValues_DifferentBillingAddressId_LocalMostRecent) {
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 40, kAddr1));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr2));
+
+ // The value from the local should be kept because it has a more recent use
+ // date.
+ EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
+ EXPECT_CALL(local_, SendChangesToSyncServer(
+ UnorderedElementsAre(SyncCardChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD,
+ kCard1Utf8, 3, 40, kAddr1Utf8))));
+
+ MergeMetadata(&local_, &remote_);
+}
+
+// Verify that if both local and server have a different non empty billing
+// address id, the one with the most recent (bigger) use date is kept.
+TEST_F(AutofillWalletMetadataSyncableServiceTest,
+ SaveHigherValues_DifferentBillingAddressId_RemoteMostRecent) {
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 40, kAddr2));
+
+ // The value from the remote should be kept because it has a more recent use
+ // date.
+ EXPECT_CALL(local_, UpdateCardStats(
+ AutofillCardMetadataMatches(kCard1, 3, 40, kAddr2)));
+ EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
+
+ MergeMetadata(&local_, &remote_);
+}
+
} // namespace
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
index de80ecd1728..8ad43337b41 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
@@ -12,8 +12,6 @@
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/autofill_profile.h"
-#include "components/autofill/core/browser/credit_card.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.h"
@@ -24,6 +22,10 @@ namespace autofill {
namespace {
+// The length of the GUIDs used for local autofill data. It is different than
+// the length used for server autofill data.
+const int kLocalGuidSize = 36;
+
void* UserDataKey() {
// Use the address of a static so that COMDAT folding won't ever fold
// with something else.
@@ -75,6 +77,7 @@ CreditCard CardFromSpecifics(const sync_pb::WalletMaskedCreditCard& card) {
base::UTF8ToUTF16(card.name_on_card()));
result.SetExpirationMonth(card.exp_month());
result.SetExpirationYear(card.exp_year());
+ result.set_billing_address_id(card.billing_address_id());
return result;
}
@@ -118,25 +121,6 @@ AutofillProfile ProfileFromSpecifics(
return profile;
}
-// Searches for CreditCards with identical server IDs and copies the billing
-// address ID from the existing cards on disk into the new cards from server.
-// The credit card's IDs do not change over time.
-void CopyBillingAddressesFromDisk(AutofillTable* table,
- std::vector<CreditCard>* cards_from_server) {
- std::vector<std::unique_ptr<CreditCard>> cards_on_disk;
- table->GetServerCreditCards(&cards_on_disk);
-
- // The reasons behind brute-force search are explained in SetDataIfChanged.
- for (const auto& saved_card : cards_on_disk) {
- for (CreditCard& server_card : *cards_from_server) {
- if (saved_card->server_id() == server_card.server_id()) {
- server_card.set_billing_address_id(saved_card->billing_address_id());
- break;
- }
- }
- }
-}
-
// This function handles conditionally updating the AutofillTable with either
// a set of CreditCards or AutocompleteProfiles only when the existing data
// doesn't match.
@@ -154,7 +138,7 @@ template <class Data>
bool SetDataIfChanged(
AutofillTable* table,
const std::vector<Data>& data,
- bool (AutofillTable::*getter)(std::vector<std::unique_ptr<Data>>*),
+ bool (AutofillTable::*getter)(std::vector<std::unique_ptr<Data>>*) const,
void (AutofillTable::*setter)(const std::vector<Data>&),
size_t* prev_item_count) {
std::vector<std::unique_ptr<Data>> existing_data;
@@ -270,10 +254,12 @@ void AutofillWalletSyncableService::InjectStartSyncFlare(
flare_ = flare;
}
-syncer::SyncMergeResult AutofillWalletSyncableService::SetSyncData(
- const syncer::SyncDataList& data_list) {
- std::vector<CreditCard> wallet_cards;
- std::vector<AutofillProfile> wallet_addresses;
+// static
+void AutofillWalletSyncableService::PopulateWalletCardsAndAddresses(
+ const syncer::SyncDataList& data_list,
+ std::vector<CreditCard>* wallet_cards,
+ std::vector<AutofillProfile>* wallet_addresses) {
+ std::map<std::string, std::string> ids;
for (const syncer::SyncData& data : data_list) {
DCHECK_EQ(syncer::AUTOFILL_WALLET_DATA, data.GetDataType());
@@ -281,23 +267,64 @@ syncer::SyncMergeResult AutofillWalletSyncableService::SetSyncData(
data.GetSpecifics().autofill_wallet();
if (autofill_specifics.type() ==
sync_pb::AutofillWalletSpecifics::MASKED_CREDIT_CARD) {
- wallet_cards.push_back(
+ wallet_cards->push_back(
CardFromSpecifics(autofill_specifics.masked_card()));
} else {
DCHECK_EQ(sync_pb::AutofillWalletSpecifics::POSTAL_ADDRESS,
autofill_specifics.type());
- wallet_addresses.push_back(
+ wallet_addresses->push_back(
ProfileFromSpecifics(autofill_specifics.address()));
+
+ // Map the sync billing address id to the profile's id.
+ ids[autofill_specifics.address().id()] =
+ wallet_addresses->back().server_id();
}
}
+ // Set the billing address of the wallet cards to the id of the appropriate
+ // profile.
+ for (CreditCard& card : *wallet_cards) {
+ auto it = ids.find(card.billing_address_id());
+ if (it != ids.end())
+ card.set_billing_address_id(it->second);
+ }
+}
+
+// static
+void AutofillWalletSyncableService::CopyRelevantBillingAddressesFromDisk(
+ const AutofillTable& table,
+ std::vector<CreditCard>* cards_from_server) {
+ std::vector<std::unique_ptr<CreditCard>> cards_on_disk;
+ table.GetServerCreditCards(&cards_on_disk);
+
+ // The reasons behind brute-force search are explained in SetDataIfChanged.
+ for (const auto& saved_card : cards_on_disk) {
+ for (CreditCard& server_card : *cards_from_server) {
+ if (saved_card->server_id() == server_card.server_id()) {
+ // Keep the billing address id of the saved cards only if it points to
+ // a local address.
+ if (saved_card->billing_address_id().length() == kLocalGuidSize) {
+ server_card.set_billing_address_id(saved_card->billing_address_id());
+ break;
+ }
+ }
+ }
+ }
+}
+
+syncer::SyncMergeResult AutofillWalletSyncableService::SetSyncData(
+ const syncer::SyncDataList& data_list) {
+ std::vector<CreditCard> wallet_cards;
+ std::vector<AutofillProfile> wallet_addresses;
+ PopulateWalletCardsAndAddresses(data_list, &wallet_cards, &wallet_addresses);
+
// Users can set billing address of the server credit card locally, but that
// information does not propagate to either Chrome Sync or Google Payments
// server. To preserve user's preferred billing address, copy the billing
// addresses from disk into |wallet_cards|.
AutofillTable* table =
AutofillTable::FromWebDatabase(webdata_backend_->GetDatabase());
- CopyBillingAddressesFromDisk(table, &wallet_cards);
+ CopyRelevantBillingAddressesFromDisk(*table, &wallet_cards);
// In the common case, the database won't have changed. Committing an update
// to the database will require at least one DB page write and will schedule
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h
index eb4b9e044ef..03f13116409 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h
@@ -8,10 +8,13 @@
#include "base/macros.h"
#include "base/supports_user_data.h"
#include "base/threading/thread_checker.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/credit_card.h"
#include "components/sync/model/syncable_service.h"
namespace autofill {
+class AutofillTable;
class AutofillWebDataBackend;
class AutofillWebDataService;
@@ -58,8 +61,33 @@ class AutofillWalletSyncableService
const std::string& app_locale);
private:
+ FRIEND_TEST_ALL_PREFIXES(
+ AutofillWalletSyncableServiceTest,
+ CopyRelevantBillingAddressesFromDisk_KeepLocalAddresses);
+ FRIEND_TEST_ALL_PREFIXES(
+ AutofillWalletSyncableServiceTest,
+ CopyRelevantBillingAddressesFromDisk_OverwriteOtherAddresses);
+ FRIEND_TEST_ALL_PREFIXES(
+ AutofillWalletSyncableServiceTest,
+ PopulateWalletCardsAndAddresses_BillingAddressIdTransfer);
+
syncer::SyncMergeResult SetSyncData(const syncer::SyncDataList& data_list);
+ // Populates the wallet cards and addresses from the sync data and uses the
+ // sync data to link the card to its billing address.
+ static void PopulateWalletCardsAndAddresses(
+ const syncer::SyncDataList& data_list,
+ std::vector<CreditCard>* wallet_cards,
+ std::vector<AutofillProfile>* wallet_addresses);
+
+ // Finds the copies of the same credit card from the server and on disk and
+ // overwrites the server version with the billing id saved on disk if it
+ // refers to a local autofill profile. The credit card's IDs do not change
+ // over time.
+ static void CopyRelevantBillingAddressesFromDisk(
+ const AutofillTable& table,
+ std::vector<CreditCard>* cards_from_server);
+
base::ThreadChecker thread_checker_;
AutofillWebDataBackend* webdata_backend_; // Weak ref.
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service_unittest.cc
new file mode 100644
index 00000000000..9561a8b1c9b
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service_unittest.cc
@@ -0,0 +1,165 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h"
+
+#include <vector>
+
+#include "base/memory/ptr_util.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/webdata/autofill_table.h"
+#include "components/sync/protocol/autofill_specifics.pb.h"
+#include "components/sync/protocol/sync.pb.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+namespace {
+
+syncer::SyncData CreateSyncDataForWalletCreditCard(
+ const std::string& id,
+ const std::string& billing_address_id) {
+ sync_pb::EntitySpecifics specifics;
+
+ sync_pb::AutofillWalletSpecifics* wallet_specifics =
+ specifics.mutable_autofill_wallet();
+ wallet_specifics->set_type(
+ sync_pb::AutofillWalletSpecifics_WalletInfoType::
+ AutofillWalletSpecifics_WalletInfoType_MASKED_CREDIT_CARD);
+
+ sync_pb::WalletMaskedCreditCard* card_specifics =
+ wallet_specifics->mutable_masked_card();
+ card_specifics->set_id(id);
+ card_specifics->set_billing_address_id(billing_address_id);
+ return syncer::SyncData::CreateLocalData(id, id, specifics);
+}
+
+syncer::SyncData CreateSyncDataForWalletAddress(const std::string& id) {
+ sync_pb::EntitySpecifics specifics;
+
+ sync_pb::AutofillWalletSpecifics* wallet_specifics =
+ specifics.mutable_autofill_wallet();
+ wallet_specifics->set_type(
+ sync_pb::AutofillWalletSpecifics_WalletInfoType::
+ AutofillWalletSpecifics_WalletInfoType_POSTAL_ADDRESS);
+
+ sync_pb::WalletPostalAddress* address_specifics =
+ wallet_specifics->mutable_address();
+ address_specifics->set_id(id);
+ return syncer::SyncData::CreateLocalData(id, id, specifics);
+}
+
+class TestAutofillTable : public AutofillTable {
+ public:
+ explicit TestAutofillTable(std::vector<CreditCard> cards_on_disk)
+ : cards_on_disk_(cards_on_disk) {}
+
+ ~TestAutofillTable() override {}
+
+ bool GetServerCreditCards(
+ std::vector<std::unique_ptr<CreditCard>>* cards) const override {
+ for (const auto& card_on_disk : cards_on_disk_)
+ cards->push_back(base::MakeUnique<CreditCard>(card_on_disk));
+ return true;
+ }
+
+ private:
+ std::vector<CreditCard> cards_on_disk_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestAutofillTable);
+};
+
+} // anonymous namespace
+
+// Verify that the link between a card and its billing address from sync is
+// present in the generated Autofill objects.
+TEST(AutofillWalletSyncableServiceTest,
+ PopulateWalletCardsAndAddresses_BillingAddressIdTransfer) {
+ std::vector<CreditCard> wallet_cards;
+ std::vector<AutofillProfile> wallet_addresses;
+ syncer::SyncDataList data_list;
+
+ // Create a Sync data for a card and its billing address.
+ data_list.push_back(CreateSyncDataForWalletAddress("1" /* id */));
+ data_list.push_back(CreateSyncDataForWalletCreditCard(
+ "card1" /* id */, "1" /* billing_address_id */));
+
+ AutofillWalletSyncableService::PopulateWalletCardsAndAddresses(
+ data_list, &wallet_cards, &wallet_addresses);
+
+ ASSERT_EQ(1U, wallet_cards.size());
+ ASSERT_EQ(1U, wallet_addresses.size());
+
+ // Make sure the card's billing address id is equal to the address' server id.
+ EXPECT_EQ(wallet_addresses.back().server_id(),
+ wallet_cards.back().billing_address_id());
+}
+
+// Verify that the billing address id from the card saved on disk is kept if it
+// is a local profile guid.
+TEST(AutofillWalletSyncableServiceTest,
+ CopyRelevantBillingAddressesFromDisk_KeepLocalAddresses) {
+ std::vector<CreditCard> cards_on_disk;
+ std::vector<CreditCard> wallet_cards;
+
+ // Create a local profile to be used as a billing address.
+ AutofillProfile billing_address;
+
+ // Create a card on disk that refers to that local profile as its billing
+ // address.
+ cards_on_disk.push_back(CreditCard());
+ cards_on_disk.back().set_billing_address_id(billing_address.guid());
+
+ // Create a card pulled from wallet with the same id, but a different billing
+ // address id.
+ wallet_cards.push_back(CreditCard(cards_on_disk.back()));
+ wallet_cards.back().set_billing_address_id("1234");
+
+ // Setup the TestAutofillTable with the cards_on_disk.
+ TestAutofillTable table(cards_on_disk);
+
+ AutofillWalletSyncableService::CopyRelevantBillingAddressesFromDisk(
+ table, &wallet_cards);
+
+ ASSERT_EQ(1U, wallet_cards.size());
+
+ // Make sure the wallet card replace its billind address id for the one that
+ // was saved on disk.
+ EXPECT_EQ(cards_on_disk.back().billing_address_id(),
+ wallet_cards.back().billing_address_id());
+}
+
+// Verify that the billing address id from the card saved on disk is overwritten
+// if it does not refer to a local profile.
+TEST(AutofillWalletSyncableServiceTest,
+ CopyRelevantBillingAddressesFromDisk_OverwriteOtherAddresses) {
+ std::string old_billing_id = "1234";
+ std::string new_billing_id = "9876";
+ std::vector<CreditCard> cards_on_disk;
+ std::vector<CreditCard> wallet_cards;
+
+ // Create a card on disk that does not refer to a local profile (which have 36
+ // chars ids).
+ cards_on_disk.push_back(CreditCard());
+ cards_on_disk.back().set_billing_address_id(old_billing_id);
+
+ // Create a card pulled from wallet with the same id, but a different billing
+ // address id.
+ wallet_cards.push_back(CreditCard(cards_on_disk.back()));
+ wallet_cards.back().set_billing_address_id(new_billing_id);
+
+ // Setup the TestAutofillTable with the cards_on_disk.
+ TestAutofillTable table(cards_on_disk);
+
+ AutofillWalletSyncableService::CopyRelevantBillingAddressesFromDisk(
+ table, &wallet_cards);
+
+ ASSERT_EQ(1U, wallet_cards.size());
+
+ // Make sure the local address billing id that was saved on disk did not
+ // replace the new one.
+ EXPECT_EQ(new_billing_id, wallet_cards.back().billing_address_id());
+}
+
+} // namespace autofill \ No newline at end of file
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_webdata.h b/chromium/components/autofill/core/browser/webdata/autofill_webdata.h
index 3cdd07322a9..eb573874b12 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_webdata.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata.h
@@ -17,7 +17,6 @@ class Time;
} // namespace base
-class Profile;
class WebDataServiceConsumer;
namespace autofill {
@@ -110,16 +109,11 @@ class AutofillWebData {
const base::string16& full_number) = 0;
virtual void MaskServerCreditCard(const std::string& id) = 0;
- // Updates the use count and last use date for a server card (masked or not).
- virtual void UpdateServerCardUsageStats(const CreditCard& credit_card) = 0;
+ // Updates the metadata for a server card (masked or not).
+ virtual void UpdateServerCardMetadata(const CreditCard& credit_card) = 0;
- // Updates the use count and last use date for a server address.
- virtual void UpdateServerAddressUsageStats(const AutofillProfile& profile)
- = 0;
-
- // Updates the billing address for a server card (masked or not).
- virtual void UpdateServerCardBillingAddress(const CreditCard& credit_card)
- = 0;
+ // Updates the metadata for a server address.
+ virtual void UpdateServerAddressMetadata(const AutofillProfile& profile) = 0;
// Removes Autofill records from the database.
virtual void RemoveAutofillDataModifiedBetween(
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc b/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
index ccda7ac2eca..2129da0abdd 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
@@ -29,14 +29,12 @@ AutofillWebDataBackendImpl::AutofillWebDataBackendImpl(
scoped_refptr<base::SingleThreadTaskRunner> db_thread,
const base::Closure& on_changed_callback,
const base::Callback<void(syncer::ModelType)>& on_sync_started_callback)
- : base::RefCountedDeleteOnMessageLoop<AutofillWebDataBackendImpl>(
- db_thread),
+ : base::RefCountedDeleteOnSequence<AutofillWebDataBackendImpl>(db_thread),
ui_thread_(ui_thread),
db_thread_(db_thread),
web_database_backend_(web_database_backend),
on_changed_callback_(on_changed_callback),
- on_sync_started_callback_(on_sync_started_callback) {
-}
+ on_sync_started_callback_(on_sync_started_callback) {}
void AutofillWebDataBackendImpl::AddObserver(
AutofillWebDataServiceObserverOnDBThread* observer) {
@@ -372,11 +370,11 @@ WebDatabase::State
return WebDatabase::COMMIT_NOT_NEEDED;
}
-WebDatabase::State AutofillWebDataBackendImpl::UpdateServerCardUsageStats(
+WebDatabase::State AutofillWebDataBackendImpl::UpdateServerCardMetadata(
const CreditCard& card,
WebDatabase* db) {
DCHECK(db_thread_->BelongsToCurrentThread());
- if (!AutofillTable::FromWebDatabase(db)->UpdateServerCardUsageStats(card))
+ if (!AutofillTable::FromWebDatabase(db)->UpdateServerCardMetadata(card))
return WebDatabase::COMMIT_NOT_NEEDED;
for (auto& db_observer : db_observer_list_) {
@@ -387,11 +385,11 @@ WebDatabase::State AutofillWebDataBackendImpl::UpdateServerCardUsageStats(
return WebDatabase::COMMIT_NEEDED;
}
-WebDatabase::State AutofillWebDataBackendImpl::UpdateServerAddressUsageStats(
+WebDatabase::State AutofillWebDataBackendImpl::UpdateServerAddressMetadata(
const AutofillProfile& profile,
WebDatabase* db) {
DCHECK(db_thread_->BelongsToCurrentThread());
- if (!AutofillTable::FromWebDatabase(db)->UpdateServerAddressUsageStats(
+ if (!AutofillTable::FromWebDatabase(db)->UpdateServerAddressMetadata(
profile)) {
return WebDatabase::COMMIT_NOT_NEEDED;
}
@@ -404,23 +402,6 @@ WebDatabase::State AutofillWebDataBackendImpl::UpdateServerAddressUsageStats(
return WebDatabase::COMMIT_NEEDED;
}
-WebDatabase::State AutofillWebDataBackendImpl::UpdateServerCardBillingAddress(
- const CreditCard& card,
- WebDatabase* db) {
- DCHECK(db_thread_->BelongsToCurrentThread());
- if (!AutofillTable::FromWebDatabase(db)->UpdateServerCardBillingAddress(
- card)) {
- return WebDatabase::COMMIT_NOT_NEEDED;
- }
-
- for (auto& db_observer : db_observer_list_) {
- db_observer.CreditCardChanged(
- CreditCardChange(CreditCardChange::UPDATE, card.guid(), &card));
- }
-
- return WebDatabase::COMMIT_NEEDED;
-}
-
WebDatabase::State AutofillWebDataBackendImpl::ClearAllServerData(
WebDatabase* db) {
DCHECK(db_thread_->BelongsToCurrentThread());
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h b/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
index 516e4d14151..9badefeb70c 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/ref_counted_delete_on_message_loop.h"
+#include "base/memory/ref_counted_delete_on_sequence.h"
#include "base/observer_list.h"
#include "base/supports_user_data.h"
#include "components/autofill/core/browser/webdata/autofill_webdata.h"
@@ -39,7 +39,7 @@ class CreditCard;
// WebDataService.
// This class is destroyed on the DB thread.
class AutofillWebDataBackendImpl
- : public base::RefCountedDeleteOnMessageLoop<AutofillWebDataBackendImpl>,
+ : public base::RefCountedDeleteOnSequence<AutofillWebDataBackendImpl>,
public AutofillWebDataBackend {
public:
// |web_database_backend| is used to access the WebDatabase directly for
@@ -152,17 +152,11 @@ class AutofillWebDataBackendImpl
WebDatabase::State MaskServerCreditCard(const std::string& id,
WebDatabase* db);
- WebDatabase::State UpdateServerCardUsageStats(
- const CreditCard& credit_card,
- WebDatabase* db);
-
- WebDatabase::State UpdateServerAddressUsageStats(
- const AutofillProfile& profile,
- WebDatabase* db);
+ WebDatabase::State UpdateServerCardMetadata(const CreditCard& credit_card,
+ WebDatabase* db);
- WebDatabase::State UpdateServerCardBillingAddress(
- const CreditCard& card,
- WebDatabase* db);
+ WebDatabase::State UpdateServerAddressMetadata(const AutofillProfile& profile,
+ WebDatabase* db);
WebDatabase::State ClearAllServerData(WebDatabase* db);
@@ -184,7 +178,7 @@ class AutofillWebDataBackendImpl
~AutofillWebDataBackendImpl() override;
private:
- friend class base::RefCountedDeleteOnMessageLoop<AutofillWebDataBackendImpl>;
+ friend class base::RefCountedDeleteOnSequence<AutofillWebDataBackendImpl>;
friend class base::DeleteHelper<AutofillWebDataBackendImpl>;
// This makes the destructor public, and thus allows us to aggregate
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc b/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc
index 22377e9e3af..d8d072f0d43 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc
@@ -212,28 +212,18 @@ void AutofillWebDataService::ClearAllServerData() {
autofill_backend_));
}
-void AutofillWebDataService::UpdateServerCardUsageStats(
+void AutofillWebDataService::UpdateServerCardMetadata(
const CreditCard& credit_card) {
wdbs_->ScheduleDBTask(
- FROM_HERE,
- Bind(&AutofillWebDataBackendImpl::UpdateServerCardUsageStats,
- autofill_backend_, credit_card));
+ FROM_HERE, Bind(&AutofillWebDataBackendImpl::UpdateServerCardMetadata,
+ autofill_backend_, credit_card));
}
-void AutofillWebDataService::UpdateServerAddressUsageStats(
+void AutofillWebDataService::UpdateServerAddressMetadata(
const AutofillProfile& profile) {
wdbs_->ScheduleDBTask(
- FROM_HERE,
- Bind(&AutofillWebDataBackendImpl::UpdateServerAddressUsageStats,
- autofill_backend_, profile));
-}
-
-void AutofillWebDataService::UpdateServerCardBillingAddress(
- const CreditCard& credit_card) {
- wdbs_->ScheduleDBTask(
- FROM_HERE,
- Bind(&AutofillWebDataBackendImpl::UpdateServerCardBillingAddress,
- autofill_backend_, credit_card));
+ FROM_HERE, Bind(&AutofillWebDataBackendImpl::UpdateServerAddressMetadata,
+ autofill_backend_, profile));
}
void AutofillWebDataService::RemoveAutofillDataModifiedBetween(
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h b/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h
index ab0ac2c86e5..dfc35afca5f 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h
@@ -28,7 +28,6 @@ class SingleThreadTaskRunner;
namespace autofill {
-class AutofillChange;
class AutofillEntry;
class AutofillProfile;
class AutofillWebDataBackend;
@@ -98,9 +97,8 @@ class AutofillWebDataService : public AutofillWebData,
void ClearAllServerData();
- void UpdateServerCardUsageStats(const CreditCard& credit_card) override;
- void UpdateServerAddressUsageStats(const AutofillProfile& profile) override;
- void UpdateServerCardBillingAddress(const CreditCard& credit_card) override;
+ void UpdateServerCardMetadata(const CreditCard& credit_card) override;
+ void UpdateServerAddressMetadata(const AutofillProfile& profile) override;
void RemoveAutofillDataModifiedBetween(const base::Time& delete_begin,
const base::Time& delete_end) override;
diff --git a/chromium/components/autofill/core/common/autofill_regexes.cc b/chromium/components/autofill/core/common/autofill_regexes.cc
index dc3dd58e04b..c9fa5222ac1 100644
--- a/chromium/components/autofill/core/common/autofill_regexes.cc
+++ b/chromium/components/autofill/core/common/autofill_regexes.cc
@@ -5,9 +5,9 @@
#include "components/autofill/core/common/autofill_regexes.h"
#include <memory>
+#include <unordered_map>
#include <utility>
-#include "base/containers/scoped_ptr_hash_map.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
@@ -30,7 +30,7 @@ class AutofillRegexes {
friend struct base::DefaultSingletonTraits<AutofillRegexes>;
// Maps patterns to their corresponding regex matchers.
- base::ScopedPtrHashMap<base::string16, std::unique_ptr<icu::RegexMatcher>>
+ std::unordered_map<base::string16, std::unique_ptr<icu::RegexMatcher>>
matchers_;
DISALLOW_COPY_AND_ASSIGN(AutofillRegexes);
@@ -57,11 +57,11 @@ icu::RegexMatcher* AutofillRegexes::GetMatcher(const base::string16& pattern) {
new icu::RegexMatcher(icu_pattern, UREGEX_CASE_INSENSITIVE, status));
DCHECK(U_SUCCESS(status));
- auto result = matchers_.add(pattern, std::move(matcher));
+ auto result = matchers_.insert(std::make_pair(pattern, std::move(matcher)));
DCHECK(result.second);
it = result.first;
}
- return it->second;
+ return it->second.get();
}
} // namespace
diff --git a/chromium/components/autofill/core/common/password_form.cc b/chromium/components/autofill/core/common/password_form.cc
index 17db56672b2..3969e1ff4e4 100644
--- a/chromium/components/autofill/core/common/password_form.cc
+++ b/chromium/components/autofill/core/common/password_form.cc
@@ -145,8 +145,9 @@ bool ArePasswordFormUniqueKeyEqual(const PasswordForm& left,
left.password_element == right.password_element);
}
-bool LessThanUniqueKey::operator()(const PasswordForm* left,
- const PasswordForm* right) const {
+bool LessThanUniqueKey::operator()(
+ const std::unique_ptr<PasswordForm>& left,
+ const std::unique_ptr<PasswordForm>& right) const {
int result = left->signon_realm.compare(right->signon_realm);
if (result)
return result < 0;
diff --git a/chromium/components/autofill/core/common/password_form.h b/chromium/components/autofill/core/common/password_form.h
index c70da901fc9..74716230236 100644
--- a/chromium/components/autofill/core/common/password_form.h
+++ b/chromium/components/autofill/core/common/password_form.h
@@ -165,6 +165,10 @@ struct PasswordForm {
// element corresponding to the new password. Optional, and not persisted.
base::string16 new_password_element;
+ // The confirmation password element. Optional, only set on form parsing, and
+ // not persisted.
+ base::string16 confirmation_password_element;
+
// The new password. Optional, and not persisted.
base::string16 new_password_value;
@@ -293,7 +297,8 @@ bool ArePasswordFormUniqueKeyEqual(const PasswordForm& left,
// A comparator for the unique key.
struct LessThanUniqueKey {
- bool operator()(const PasswordForm* left, const PasswordForm* right) const;
+ bool operator()(const std::unique_ptr<PasswordForm>& left,
+ const std::unique_ptr<PasswordForm>& right) const;
};
// For testing.
diff --git a/chromium/components/autofill/core/common/password_form_fill_data.cc b/chromium/components/autofill/core/common/password_form_fill_data.cc
index b4d5fd047bc..9b1383046e0 100644
--- a/chromium/components/autofill/core/common/password_form_fill_data.cc
+++ b/chromium/components/autofill/core/common/password_form_fill_data.cc
@@ -22,9 +22,7 @@ bool UsernamesCollectionKey::operator<(
}
PasswordFormFillData::PasswordFormFillData()
- : wait_for_username(false),
- is_possible_change_password_form(false) {
-}
+ : wait_for_username(false), is_possible_change_password_form(false) {}
PasswordFormFillData::PasswordFormFillData(const PasswordFormFillData& other) =
default;
diff --git a/chromium/components/autofill/core/common/save_password_progress_logger.cc b/chromium/components/autofill/core/common/save_password_progress_logger.cc
index b2dd78b63c8..93d1bc6c500 100644
--- a/chromium/components/autofill/core/common/save_password_progress_logger.cc
+++ b/chromium/components/autofill/core/common/save_password_progress_logger.cc
@@ -266,6 +266,8 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "Invalid form";
case SavePasswordProgressLogger::STRING_SYNC_CREDENTIAL:
return "Credential is used for syncing passwords";
+ case STRING_BLOCK_PASSWORD_SAME_ORIGIN_INSECURE_SCHEME:
+ return "Blocked password due to same origin but insecure scheme";
case SavePasswordProgressLogger::STRING_PROVISIONALLY_SAVED_FORM:
return "provisionally_saved_form";
case SavePasswordProgressLogger::STRING_IGNORE_POSSIBLE_USERNAMES:
@@ -318,11 +320,11 @@ std::string SavePasswordProgressLogger::GetStringFromID(
case SavePasswordProgressLogger::STRING_BEST_SCORE:
return "best_score";
case SavePasswordProgressLogger::STRING_ON_GET_STORE_RESULTS_METHOD:
- return "PasswordFormManager::OnGetPasswordStoreResults";
+ return "FormFetcherImpl::OnGetPasswordStoreResults";
case SavePasswordProgressLogger::STRING_NUMBER_RESULTS:
return "Number of results from the password store";
- case SavePasswordProgressLogger::STRING_FETCH_LOGINS_METHOD:
- return "PasswordFormManager::FetchMatchingLoginsFromPasswordStore";
+ case SavePasswordProgressLogger::STRING_FETCH_METHOD:
+ return "FormFetcherImpl::Fetch";
case SavePasswordProgressLogger::STRING_NO_STORE:
return "PasswordStore is not available";
case SavePasswordProgressLogger::STRING_CREATE_LOGIN_MANAGERS_METHOD:
@@ -346,8 +348,8 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "PasswordFormManager::ProcessFrame";
case SavePasswordProgressLogger::STRING_FORM_SIGNATURE:
return "Signature of form";
- case SavePasswordProgressLogger::STRING_FORM_MANAGER_STATE:
- return "PasswordFormManager::state_";
+ case SavePasswordProgressLogger::STRING_FORM_FETCHER_STATE:
+ return "FormFetcherImpl::state_";
case SavePasswordProgressLogger::STRING_ADDING_SIGNATURE:
return "Adding manager for form";
case SavePasswordProgressLogger::STRING_UNOWNED_INPUTS_VISIBLE:
@@ -388,6 +390,8 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "Server predictions";
case SavePasswordProgressLogger::STRING_FORM_VOTES:
return "Form votes";
+ case SavePasswordProgressLogger::STRING_REUSE_FOUND:
+ return "Password reused from ";
case SavePasswordProgressLogger::STRING_INVALID:
return "INVALID";
// Intentionally no default: clause here -- all IDs need to get covered.
diff --git a/chromium/components/autofill/core/common/save_password_progress_logger.h b/chromium/components/autofill/core/common/save_password_progress_logger.h
index d8c9fe1ac08..de8a08232b4 100644
--- a/chromium/components/autofill/core/common/save_password_progress_logger.h
+++ b/chromium/components/autofill/core/common/save_password_progress_logger.h
@@ -90,6 +90,7 @@ class SavePasswordProgressLogger {
STRING_FORM_BLACKLISTED,
STRING_INVALID_FORM,
STRING_SYNC_CREDENTIAL,
+ STRING_BLOCK_PASSWORD_SAME_ORIGIN_INSECURE_SCHEME,
STRING_PROVISIONALLY_SAVED_FORM,
STRING_IGNORE_POSSIBLE_USERNAMES,
STRING_ON_PASSWORD_FORMS_RENDERED_METHOD,
@@ -116,7 +117,7 @@ class SavePasswordProgressLogger {
STRING_BEST_SCORE,
STRING_ON_GET_STORE_RESULTS_METHOD,
STRING_NUMBER_RESULTS,
- STRING_FETCH_LOGINS_METHOD,
+ STRING_FETCH_METHOD,
STRING_NO_STORE,
STRING_CREATE_LOGIN_MANAGERS_METHOD,
STRING_OLD_NUMBER_LOGIN_MANAGERS,
@@ -129,7 +130,7 @@ class SavePasswordProgressLogger {
STRING_PROCESS_FRAME_METHOD,
STRING_FORM_SIGNATURE,
STRING_ADDING_SIGNATURE,
- STRING_FORM_MANAGER_STATE,
+ STRING_FORM_FETCHER_STATE,
STRING_UNOWNED_INPUTS_VISIBLE,
STRING_ON_FILL_PASSWORD_FORM_METHOD,
STRING_ON_SHOW_INITIAL_PASSWORD_ACCOUNT_SUGGESTIONS,
@@ -148,6 +149,7 @@ class SavePasswordProgressLogger {
STRING_FIELDS,
STRING_SERVER_PREDICTIONS,
STRING_FORM_VOTES,
+ STRING_REUSE_FOUND,
STRING_INVALID, // Represents a string returned in a case of an error.
STRING_MAX = STRING_INVALID
};
diff --git a/chromium/components/autofill/ios/browser/BUILD.gn b/chromium/components/autofill/ios/browser/BUILD.gn
index 91dbed34da0..c16d7d83090 100644
--- a/chromium/components/autofill/ios/browser/BUILD.gn
+++ b/chromium/components/autofill/ios/browser/BUILD.gn
@@ -27,7 +27,6 @@ source_set("browser") {
"//base",
"//components/autofill/core/browser",
"//components/autofill/core/common",
- "//ios/public/provider/web",
"//ios/web",
"//ui/gfx/geometry",
]
diff --git a/chromium/components/autofill/ios/browser/autofill_driver_ios.h b/chromium/components/autofill/ios/browser/autofill_driver_ios.h
index 2da12651251..c6678f31c49 100644
--- a/chromium/components/autofill/ios/browser/autofill_driver_ios.h
+++ b/chromium/components/autofill/ios/browser/autofill_driver_ios.h
@@ -21,8 +21,6 @@ class WebState;
namespace autofill {
-class AutofillManagerDelegate;
-
// Class that drives autofill flow on iOS. There is one instance per
// WebContents.
class AutofillDriverIOS : public AutofillDriver,
diff --git a/chromium/components/autofill/ios/browser/form_suggestion.h b/chromium/components/autofill/ios/browser/form_suggestion.h
index 7fd9df1ddbd..8fb6689d694 100644
--- a/chromium/components/autofill/ios/browser/form_suggestion.h
+++ b/chromium/components/autofill/ios/browser/form_suggestion.h
@@ -7,8 +7,6 @@
#import <Foundation/Foundation.h>
-#include "base/mac/objc_property_releaser.h"
-
// Represents a user-selectable suggestion for a single field within a form
// on a web page.
@interface FormSuggestion : NSObject
diff --git a/chromium/components/autofill/ios/browser/form_suggestion.mm b/chromium/components/autofill/ios/browser/form_suggestion.mm
index 709bb63b4ce..f4bb40c37c3 100644
--- a/chromium/components/autofill/ios/browser/form_suggestion.mm
+++ b/chromium/components/autofill/ios/browser/form_suggestion.mm
@@ -4,6 +4,8 @@
#import "components/autofill/ios/browser/form_suggestion.h"
+#include "base/mac/objc_property_releaser.h"
+
@interface FormSuggestion ()
// Local initializer for a FormSuggestion.
- (id)initWithValue:(NSString*)value