1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/autofill/core/browser/form_data_importer.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <algorithm>
11 #include <limits>
12 #include <map>
13 #include <memory>
14 #include <set>
15 #include <utility>
16
17 #include "base/bind.h"
18 #include "base/strings/string16.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "build/build_config.h"
22 #include "components/autofill/core/browser/address_profiles/address_profile_save_manager.h"
23 #include "components/autofill/core/browser/autofill_client.h"
24 #include "components/autofill/core/browser/autofill_metrics.h"
25 #include "components/autofill/core/browser/autofill_type.h"
26 #include "components/autofill/core/browser/data_model/autofill_profile.h"
27 #include "components/autofill/core/browser/data_model/autofill_structured_address_name.h"
28 #include "components/autofill/core/browser/data_model/credit_card.h"
29 #include "components/autofill/core/browser/data_model/phone_number.h"
30 #include "components/autofill/core/browser/form_structure.h"
31 #include "components/autofill/core/browser/geo/autofill_country.h"
32 #include "components/autofill/core/browser/geo/phone_number_i18n.h"
33 #include "components/autofill/core/browser/logging/log_manager.h"
34 #include "components/autofill/core/browser/personal_data_manager.h"
35 #include "components/autofill/core/browser/validation.h"
36 #include "components/autofill/core/common/autofill_features.h"
37 #include "components/autofill/core/common/autofill_internals/log_message.h"
38 #include "components/autofill/core/common/autofill_internals/logging_scope.h"
39 #include "components/autofill/core/common/autofill_payments_features.h"
40 #include "components/autofill/core/common/autofill_util.h"
41 #include "components/variations/service/variations_field_trial_creator.h"
42 #include "components/variations/service/variations_service.h"
43
44 namespace autofill {
45
46 using structured_address::VerificationStatus;
47
48 namespace {
49
50 using AddressImportRequirement =
51 AutofillMetrics::AddressProfileImportRequirementMetric;
52
53 // Return true if the |field_type| and |value| are valid within the context
54 // of importing a form.
IsValidFieldTypeAndValue(const std::set<ServerFieldType> & types_seen,ServerFieldType field_type,const base::string16 & value,LogBuffer * import_log_buffer)55 bool IsValidFieldTypeAndValue(const std::set<ServerFieldType>& types_seen,
56 ServerFieldType field_type,
57 const base::string16& value,
58 LogBuffer* import_log_buffer) {
59 // Abandon the import if two fields of the same type are encountered.
60 // This indicates ambiguous data or miscategorization of types.
61 // Make an exception for PHONE_HOME_NUMBER however as both prefix and
62 // suffix are stored against this type, and for EMAIL_ADDRESS because it is
63 // common to see second 'confirm email address' fields on forms.
64 if (types_seen.count(field_type) && field_type != PHONE_HOME_NUMBER &&
65 field_type != EMAIL_ADDRESS) {
66 if (import_log_buffer) {
67 *import_log_buffer << LogMessage::kImportAddressProfileFromFormFailed
68 << "Multiple fields of type "
69 << AutofillType(field_type).ToString() << "."
70 << CTag{};
71 }
72 return false;
73 }
74 // Abandon the import if an email address value shows up in a field that is
75 // not an email address.
76 if (field_type != EMAIL_ADDRESS && IsValidEmailAddress(value)) {
77 if (import_log_buffer) {
78 *import_log_buffer << LogMessage::kImportAddressProfileFromFormFailed
79 << "Email address found in field of different type: "
80 << AutofillType(field_type).ToString() << CTag{};
81 }
82 return false;
83 }
84
85 return true;
86 }
87
88 // Returns true if minimum requirements for import of a given |profile| have
89 // been met. An address submitted via a form must have at least the fields
90 // required as determined by its country code.
91 // No verification of validity of the contents is performed. This is an
92 // existence check only.
IsMinimumAddress(const AutofillProfile & profile,const std::string & variation_country_code,const std::string & app_locale,LogBuffer * import_log_buffer)93 bool IsMinimumAddress(const AutofillProfile& profile,
94 const std::string& variation_country_code,
95 const std::string& app_locale,
96 LogBuffer* import_log_buffer) {
97 // Try to acquire the country code form the filled form.
98 std::string country_code =
99 base::UTF16ToASCII(profile.GetRawInfo(ADDRESS_HOME_COUNTRY));
100
101 if (import_log_buffer && !country_code.empty()) {
102 *import_log_buffer << LogMessage::kImportAddressProfileFromFormCountrySource
103 << "Country entry in form." << CTag{};
104 }
105
106 // As a fallback, use the finch state to get a country code.
107 if (country_code.empty() && !variation_country_code.empty()) {
108 country_code = variation_country_code;
109 if (import_log_buffer && !country_code.empty()) {
110 *import_log_buffer
111 << LogMessage::kImportAddressProfileFromFormCountrySource
112 << "Variations service." << CTag{};
113 }
114 }
115
116 // As the last resort, derive the country code from the app_locale.
117 if (country_code.empty()) {
118 country_code = AutofillCountry::CountryCodeForLocale(app_locale);
119 if (import_log_buffer && !country_code.empty()) {
120 *import_log_buffer
121 << LogMessage::kImportAddressProfileFromFormCountrySource
122 << "App locale." << CTag{};
123 }
124 }
125
126 AutofillCountry country(country_code, app_locale);
127
128 // Include the details of the country to the log.
129 if (import_log_buffer)
130 *import_log_buffer << country;
131
132 // Check the |ADDRESS_HOME_LINE1| requirement.
133 bool is_line1_missing = false;
134 if (country.requires_line1() &&
135 profile.GetRawInfo(ADDRESS_HOME_LINE1).empty() &&
136 profile.GetRawInfo(ADDRESS_HOME_STREET_NAME).empty()) {
137 if (import_log_buffer) {
138 *import_log_buffer << LogMessage::kImportAddressProfileFromFormFailed
139 << "Missing required ADDRESS_HOME_LINE1." << CTag{};
140 }
141 is_line1_missing = true;
142 }
143
144 // Check the |ADDRESS_HOME_CITY| requirement.
145 bool is_city_missing = false;
146 if (country.requires_city() &&
147 profile.GetRawInfo(ADDRESS_HOME_CITY).empty()) {
148 if (import_log_buffer) {
149 *import_log_buffer << LogMessage::kImportAddressProfileFromFormFailed
150 << "Missing required ADDRESS_HOME_CITY." << CTag{};
151 }
152 is_city_missing = true;
153 }
154
155 // Check the |ADDRESS_HOME_STATE| requirement.
156 bool is_state_missing = false;
157 if (country.requires_state() &&
158 profile.GetRawInfo(ADDRESS_HOME_STATE).empty()) {
159 if (import_log_buffer) {
160 *import_log_buffer << LogMessage::kImportAddressProfileFromFormFailed
161 << "Missing required ADDRESS_HOME_STATE." << CTag{};
162 }
163 is_state_missing = true;
164 }
165
166 // Check the |ADDRESS_HOME_ZIP| requirement.
167 bool is_zip_missing = false;
168 if (country.requires_zip() && profile.GetRawInfo(ADDRESS_HOME_ZIP).empty()) {
169 if (import_log_buffer) {
170 *import_log_buffer << LogMessage::kImportAddressProfileFromFormFailed
171 << "Missing required ADDRESS_HOME_ZIP." << CTag{};
172 }
173 is_zip_missing = true;
174 }
175
176 bool is_zip_or_state_requirement_violated = false;
177 if (country.requires_zip_or_state() &&
178 profile.GetRawInfo(ADDRESS_HOME_ZIP).empty() &&
179 profile.GetRawInfo(ADDRESS_HOME_STATE).empty()) {
180 if (import_log_buffer) {
181 *import_log_buffer
182 << LogMessage::kImportAddressProfileFromFormFailed
183 << "Missing required ADDRESS_HOME_ZIP or ADDRESS_HOME_STATE."
184 << CTag{};
185 }
186 is_zip_or_state_requirement_violated = true;
187 }
188
189 // Collect metrics regarding the requirements.
190 AutofillMetrics::LogAddressFormImportRequirementMetric(
191 is_line1_missing ? AddressImportRequirement::LINE1_REQUIREMENT_VIOLATED
192 : AddressImportRequirement::LINE1_REQUIREMENT_FULFILLED);
193
194 AutofillMetrics::LogAddressFormImportRequirementMetric(
195 is_city_missing ? AddressImportRequirement::CITY_REQUIREMENT_VIOLATED
196 : AddressImportRequirement::CITY_REQUIREMENT_FULFILLED);
197
198 AutofillMetrics::LogAddressFormImportRequirementMetric(
199 is_state_missing ? AddressImportRequirement::STATE_REQUIREMENT_VIOLATED
200 : AddressImportRequirement::STATE_REQUIREMENT_FULFILLED);
201
202 AutofillMetrics::LogAddressFormImportRequirementMetric(
203 is_zip_missing ? AddressImportRequirement::ZIP_REQUIREMENT_VIOLATED
204 : AddressImportRequirement::ZIP_REQUIREMENT_FULFILLED);
205
206 AutofillMetrics::LogAddressFormImportRequirementMetric(
207 is_zip_or_state_requirement_violated
208 ? AddressImportRequirement::ZIP_OR_STATE_REQUIREMENT_VIOLATED
209 : AddressImportRequirement::ZIP_OR_STATE_REQUIREMENT_FULFILLED);
210
211 AutofillMetrics::LogAddressFormImportCountrySpecificFieldRequirementsMetric(
212 is_zip_missing, is_state_missing, is_city_missing, is_line1_missing);
213
214 // Return true if all requirements are fulfilled.
215 return !(is_line1_missing || is_city_missing || is_state_missing ||
216 is_zip_missing || is_zip_or_state_requirement_violated);
217 }
218
219 } // namespace
220
FormDataImporter(AutofillClient * client,payments::PaymentsClient * payments_client,PersonalDataManager * personal_data_manager,const std::string & app_locale)221 FormDataImporter::FormDataImporter(AutofillClient* client,
222 payments::PaymentsClient* payments_client,
223 PersonalDataManager* personal_data_manager,
224 const std::string& app_locale)
225 : client_(client),
226 credit_card_save_manager_(
227 std::make_unique<CreditCardSaveManager>(client,
228 payments_client,
229 app_locale,
230 personal_data_manager)),
231 address_profile_save_manager_(
232 std::make_unique<AddressProfileSaveManager>(personal_data_manager)),
233 #if !defined(OS_ANDROID) && !defined(OS_IOS)
234 local_card_migration_manager_(
235 std::make_unique<LocalCardMigrationManager>(client,
236 payments_client,
237 app_locale,
238 personal_data_manager)),
239 upi_vpa_save_manager_(
240 std::make_unique<UpiVpaSaveManager>(client, personal_data_manager)),
241 #endif // #if !defined(OS_ANDROID) && !defined(OS_IOS)
242 personal_data_manager_(personal_data_manager),
243 app_locale_(app_locale) {
244 }
245
~FormDataImporter()246 FormDataImporter::~FormDataImporter() {}
247
ImportFormData(const FormStructure & submitted_form,bool profile_autofill_enabled,bool credit_card_autofill_enabled)248 void FormDataImporter::ImportFormData(const FormStructure& submitted_form,
249 bool profile_autofill_enabled,
250 bool credit_card_autofill_enabled) {
251 std::unique_ptr<CreditCard> imported_credit_card;
252 base::Optional<std::string> detected_upi_id;
253
254 bool is_credit_card_upstream_enabled =
255 credit_card_save_manager_->IsCreditCardUploadEnabled();
256 // ImportFormData will set the |imported_credit_card_record_type_|. If the
257 // imported card is invalid or already a server card, or if
258 // |credit_card_save_manager_| does not allow uploading,
259 // |imported_credit_card| will be nullptr.
260 ImportFormData(submitted_form, profile_autofill_enabled,
261 credit_card_autofill_enabled,
262 /*should_return_local_card=*/is_credit_card_upstream_enabled,
263 &imported_credit_card, &detected_upi_id);
264
265 #if !defined(OS_ANDROID) && !defined(OS_IOS)
266 if (detected_upi_id && credit_card_autofill_enabled &&
267 base::FeatureList::IsEnabled(features::kAutofillSaveAndFillVPA)) {
268 upi_vpa_save_manager_->OfferLocalSave(*detected_upi_id);
269 }
270 #endif // #if !defined(OS_ANDROID) && !defined(OS_IOS)
271
272 // If no card was successfully imported from the form, return.
273 if (imported_credit_card_record_type_ ==
274 ImportedCreditCardRecordType::NO_CARD) {
275 return;
276 }
277 // Do not offer upload save for google domain.
278 if (net::HasGoogleHost(submitted_form.main_frame_origin().GetURL()) &&
279 is_credit_card_upstream_enabled) {
280 return;
281 }
282
283 #if !defined(OS_ANDROID) && !defined(OS_IOS)
284 // A credit card was successfully imported, but it's possible it is already a
285 // local or server card. First, check to see if we should offer local card
286 // migration in this case, as local cards could go either way.
287 if (local_card_migration_manager_ &&
288 local_card_migration_manager_->ShouldOfferLocalCardMigration(
289 imported_credit_card.get(), imported_credit_card_record_type_)) {
290 local_card_migration_manager_->AttemptToOfferLocalCardMigration(
291 /*is_from_settings_page=*/false);
292 return;
293 }
294 #endif // #if !defined(OS_ANDROID) && !defined(OS_IOS)
295
296 // Local card migration will not be offered. If we do not have a new card to
297 // save (or a local card to upload save), return.
298 if (!imported_credit_card)
299 return;
300
301 // We have a card to save; decide what type of save flow to display.
302 if (is_credit_card_upstream_enabled) {
303 // Attempt to offer upload save. Because we pass
304 // |credit_card_upstream_enabled| to ImportFormData, this block can be
305 // reached on observing either a new card or one already stored locally
306 // which doesn't match an existing server card. If Google Payments declines
307 // allowing upload, |credit_card_save_manager_| is tasked with deciding if
308 // we should fall back to local save or not.
309 DCHECK(imported_credit_card_record_type_ ==
310 ImportedCreditCardRecordType::LOCAL_CARD ||
311 imported_credit_card_record_type_ ==
312 ImportedCreditCardRecordType::NEW_CARD);
313 credit_card_save_manager_->AttemptToOfferCardUploadSave(
314 submitted_form, from_dynamic_change_form_, has_non_focusable_field_,
315 *imported_credit_card,
316 /*uploading_local_card=*/imported_credit_card_record_type_ ==
317 ImportedCreditCardRecordType::LOCAL_CARD);
318 } else {
319 // If upload save is not allowed, new cards should be saved locally.
320 DCHECK(imported_credit_card_record_type_ ==
321 ImportedCreditCardRecordType::NEW_CARD);
322 credit_card_save_manager_->AttemptToOfferCardLocalSave(
323 from_dynamic_change_form_, has_non_focusable_field_,
324 *imported_credit_card);
325 }
326 }
327
ExtractCreditCardFromForm(const FormStructure & form)328 CreditCard FormDataImporter::ExtractCreditCardFromForm(
329 const FormStructure& form) {
330 bool has_duplicate_field_type;
331 return ExtractCreditCardFromForm(form, &has_duplicate_field_type);
332 }
333
334 // static
IsValidLearnableProfile(const AutofillProfile & profile,const std::string & variation_country_code,const std::string & app_locale,LogBuffer * import_log_buffer)335 bool FormDataImporter::IsValidLearnableProfile(
336 const AutofillProfile& profile,
337 const std::string& variation_country_code,
338 const std::string& app_locale,
339 LogBuffer* import_log_buffer) {
340 // Check if the imported address qualifies as a minimum address.
341 bool is_not_minimum_address = false;
342 if (!IsMinimumAddress(profile, variation_country_code, app_locale,
343 import_log_buffer)) {
344 is_not_minimum_address = true;
345 }
346
347 // Check that the email address is valid if it is supplied.
348 bool is_email_invalid = false;
349 base::string16 email = profile.GetRawInfo(EMAIL_ADDRESS);
350 if (!email.empty() && !IsValidEmailAddress(email)) {
351 if (import_log_buffer) {
352 *import_log_buffer << LogMessage::kImportAddressProfileFromFormFailed
353 << "Invalid email address." << CTag{};
354 }
355 is_email_invalid = true;
356 }
357
358 // Reject profiles with an invalid |HOME_ADDRESS_STATE| entry.
359 bool is_state_invalid = false;
360 if (profile.IsPresentButInvalid(ADDRESS_HOME_STATE)) {
361 if (import_log_buffer)
362 *import_log_buffer
363 << LogMessage::kImportAddressProfileFromFormFailed
364 << "Invalid state as of AutofillProfile::IsPresentButInvalid()."
365 << CTag{};
366 is_state_invalid = true;
367 }
368
369 // Reject profiles with an invalid |HOME_ADDRESS_ZIP| entry.
370 bool is_zip_invalid = false;
371 if (profile.IsPresentButInvalid(ADDRESS_HOME_ZIP)) {
372 if (import_log_buffer)
373 *import_log_buffer
374 << LogMessage::kImportAddressProfileFromFormFailed
375 << "Invalid ZIP as of AutofillProfile::IsPresentButInvalid()."
376 << CTag{};
377 is_zip_invalid = true;
378 }
379
380 // Collect metrics.
381 AutofillMetrics::LogAddressFormImportRequirementMetric(
382 is_email_invalid
383 ? AddressImportRequirement::EMAIL_VALID_REQUIREMENT_VIOLATED
384 : AddressImportRequirement::EMAIL_VALID_REQUIREMENT_FULFILLED);
385
386 AutofillMetrics::LogAddressFormImportRequirementMetric(
387 is_state_invalid
388 ? AddressImportRequirement::STATE_VALID_REQUIREMENT_VIOLATED
389 : AddressImportRequirement::STATE_VALID_REQUIREMENT_FULFILLED);
390
391 AutofillMetrics::LogAddressFormImportRequirementMetric(
392 is_zip_invalid
393 ? AddressImportRequirement::ZIP_VALID_REQUIREMENT_VIOLATED
394 : AddressImportRequirement::ZIP_VALID_REQUIREMENT_FULFILLED);
395
396 // Return true if none of the requirements is violated.
397 return !(is_not_minimum_address || is_email_invalid || is_state_invalid ||
398 is_zip_invalid);
399 }
400
ImportFormData(const FormStructure & submitted_form,bool profile_autofill_enabled,bool credit_card_autofill_enabled,bool should_return_local_card,std::unique_ptr<CreditCard> * imported_credit_card,base::Optional<std::string> * imported_upi_id)401 bool FormDataImporter::ImportFormData(
402 const FormStructure& submitted_form,
403 bool profile_autofill_enabled,
404 bool credit_card_autofill_enabled,
405 bool should_return_local_card,
406 std::unique_ptr<CreditCard>* imported_credit_card,
407 base::Optional<std::string>* imported_upi_id) {
408 // We try the same |form| for both credit card and address import/update.
409 // - ImportCreditCard may update an existing card, or fill
410 // |imported_credit_card| with an extracted card. See .h for details of
411 // |should_return_local_card|.
412 // Reset |imported_credit_card_record_type_| every time we import data from
413 // form no matter whether ImportCreditCard() is called or not.
414 imported_credit_card_record_type_ = ImportedCreditCardRecordType::NO_CARD;
415 bool cc_import = false;
416 if (credit_card_autofill_enabled) {
417 cc_import = ImportCreditCard(submitted_form, should_return_local_card,
418 imported_credit_card);
419 *imported_upi_id = ImportUpiId(submitted_form);
420 }
421 // - ImportAddressProfiles may eventually save or update one or more address
422 // profiles.
423 bool address_import = false;
424 if (profile_autofill_enabled) {
425 address_import = ImportAddressProfiles(submitted_form);
426 }
427
428 if (cc_import || address_import || imported_upi_id->has_value())
429 return true;
430
431 personal_data_manager_->MarkObserversInsufficientFormDataForImport();
432 return false;
433 }
434
ImportAddressProfiles(const FormStructure & form)435 bool FormDataImporter::ImportAddressProfiles(const FormStructure& form) {
436 // Create a buffer to collect logging output for the autofill-internals.
437 LogBuffer import_log_buffer;
438 import_log_buffer << LoggingScope::kAddressProfileFormImport;
439 // Print the full form into the logging scope.
440 import_log_buffer << LogMessage::kImportAddressProfileFromForm << form
441 << CTag{};
442
443 // We save a maximum of 2 profiles per submitted form (e.g. for shipping and
444 // billing).
445 static const size_t kMaxNumAddressProfilesSaved = 2;
446 size_t num_saved_profiles = 0;
447
448 if (!form.field_count()) {
449 import_log_buffer << LogMessage::kImportAddressProfileFromFormFailed
450 << "Form is empty." << CTag{};
451 } else {
452 // Relevant sections for address fields.
453 std::set<std::string> sections;
454 for (const auto& field : form) {
455 if (field->Type().group() != CREDIT_CARD)
456 sections.insert(field->section);
457 }
458
459 for (const std::string& section : sections) {
460 if (num_saved_profiles == kMaxNumAddressProfilesSaved)
461 break;
462 // Log the output from a section in a separate div for readability.
463 import_log_buffer << Tag{"div"}
464 << Attrib{"class", "profile_import_from_form_section"};
465 import_log_buffer << LogMessage::kImportAddressProfileFromFormSection
466 << section << CTag{};
467 // Try to import an address profile from the form fields of this section.
468 if (ImportAddressProfileForSection(form, section, &import_log_buffer))
469 num_saved_profiles++;
470 // And close the div of the section import log.
471 import_log_buffer << CTag{"div"};
472 }
473 // Run the import on the union of the section if the import was not
474 // successful and if there is more than one section.
475 if (num_saved_profiles > 0) {
476 AutofillMetrics::LogAddressFormImportStatustMetric(
477 AutofillMetrics::AddressProfileImportStatusMetric::REGULAR_IMPORT);
478 } else if (sections.size() > 1) {
479 // Try to import by combining all sections.
480 if (ImportAddressProfileForSection(form, "", &import_log_buffer)) {
481 num_saved_profiles++;
482 AutofillMetrics::LogAddressFormImportStatustMetric(
483 AutofillMetrics::AddressProfileImportStatusMetric::
484 SECTION_UNION_IMPORT);
485 }
486 }
487 if (num_saved_profiles == 0) {
488 AutofillMetrics::LogAddressFormImportStatustMetric(
489 AutofillMetrics::AddressProfileImportStatusMetric::NO_IMPORT);
490 }
491 }
492 import_log_buffer << LogMessage::kImportAddressProfileFromFormNumberOfImports
493 << num_saved_profiles << CTag{};
494
495 // Write log buffer to autofill-internals.
496 LogManager* log_manager = client_->GetLogManager();
497 if (log_manager)
498 log_manager->Log() << std::move(import_log_buffer);
499
500 return num_saved_profiles > 0;
501 }
502
ImportAddressProfileForSection(const FormStructure & form,const std::string & section,LogBuffer * import_log_buffer)503 bool FormDataImporter::ImportAddressProfileForSection(
504 const FormStructure& form,
505 const std::string& section,
506 LogBuffer* import_log_buffer) {
507 // The candidate for profile import. There are many ways for the candidate to
508 // be rejected (see everywhere this function returns false).
509 AutofillProfile candidate_profile;
510
511 // We only set complete phone, so aggregate phone parts in these vars and set
512 // complete at the end.
513 PhoneNumber::PhoneCombineHelper combined_phone;
514
515 // Used to detect and discard address forms with multiple fields of the same
516 // type.
517 std::set<ServerFieldType> types_seen;
518
519 // Tracks if the form section contains multiple distinct email addresses.
520 bool has_multiple_distinct_email_addresses = false;
521
522 // Tracks if the form section contains an invalid types.
523 bool has_invalid_field_types = false;
524
525 // Tracks if the form section contains an invalid phone number.
526 bool has_invalid_phone_number = false;
527
528 // Tracks if the form section contains an invalid country.
529 bool has_invalid_country = false;
530
531 // Go through each |form| field and attempt to constitute a valid profile.
532 for (const auto& field : form) {
533 // Reject fields that are not within the specified |section|.
534 // If section is empty, use all fields.
535 if (field->section != section && !section.empty())
536 continue;
537
538 base::string16 value;
539 base::TrimWhitespace(field->value, base::TRIM_ALL, &value);
540
541 // If we don't know the type of the field, or the user hasn't entered any
542 // information into the field, then skip it.
543 if (!field->IsFieldFillable() || value.empty())
544 continue;
545
546 AutofillType field_type = field->Type();
547
548 // Credit card fields are handled by ImportCreditCard().
549 if (field_type.group() == CREDIT_CARD)
550 continue;
551
552 // There can be multiple email fields (e.g. in the case of 'confirm email'
553 // fields) but they must all contain the same value, else the profile is
554 // invalid.
555 ServerFieldType server_field_type = field_type.GetStorableType();
556 if (server_field_type == EMAIL_ADDRESS &&
557 types_seen.count(server_field_type) &&
558 candidate_profile.GetRawInfo(EMAIL_ADDRESS) != value) {
559 if (import_log_buffer) {
560 *import_log_buffer << LogMessage::kImportAddressProfileFromFormFailed
561 << "Multiple different email addresses present."
562 << CTag{};
563 }
564 has_multiple_distinct_email_addresses = true;
565 }
566
567 // If the field type and |value| don't pass basic validity checks then
568 // abandon the import.
569 if (!IsValidFieldTypeAndValue(types_seen, server_field_type, value,
570 import_log_buffer))
571 has_invalid_field_types = true;
572 types_seen.insert(server_field_type);
573
574 // We need to store phone data in the variables, before building the whole
575 // number at the end. If |value| is not from a phone field, home.SetInfo()
576 // returns false and data is stored directly in |candidate_profile|.
577 if (!combined_phone.SetInfo(field_type, value)) {
578 candidate_profile.SetInfoWithVerificationStatus(
579 field_type, value, app_locale_, VerificationStatus::kObserved);
580 }
581
582 // Reject profiles with invalid country information.
583 if (server_field_type == ADDRESS_HOME_COUNTRY &&
584 candidate_profile.GetRawInfo(ADDRESS_HOME_COUNTRY).empty()) {
585 // The country code was not successfully determined from the value in
586 // the country field. This can be caused by a localization that does not
587 // match the |app_locale|. Try setting the value again using the
588 // language of the page. Note, there should be a locale associated with
589 // every language code.
590 std::string page_language;
591 const translate::LanguageState* language_state =
592 client_->GetLanguageState();
593 if (language_state)
594 page_language = language_state->original_language();
595 // Retry to set the country of there is known page language.
596 if (!page_language.empty()) {
597 candidate_profile.SetInfoWithVerificationStatus(
598 field_type, value, page_language, VerificationStatus::kObserved);
599 }
600 // Check if the country code was still not determined correctly.
601 if (candidate_profile.GetRawInfo(ADDRESS_HOME_COUNTRY).empty()) {
602 if (import_log_buffer) {
603 *import_log_buffer << LogMessage::kImportAddressProfileFromFormFailed
604 << "Missing country." << CTag{};
605 }
606 has_invalid_country = true;
607 }
608 }
609 }
610
611 // Construct the phone number. Reject the whole profile if the number is
612 // invalid.
613 if (!combined_phone.IsEmpty()) {
614 base::string16 constructed_number;
615 if (!combined_phone.ParseNumber(candidate_profile, app_locale_,
616 &constructed_number) ||
617 !candidate_profile.SetInfoWithVerificationStatus(
618 AutofillType(PHONE_HOME_WHOLE_NUMBER), constructed_number,
619 app_locale_, VerificationStatus::kObserved)) {
620 if (import_log_buffer) {
621 *import_log_buffer << LogMessage::kImportAddressProfileFromFormFailed
622 << "Invalid phone number." << CTag{};
623 }
624 has_invalid_phone_number = true;
625 }
626 }
627
628 // Reject the profile if minimum address and validation requirements are not
629 // met.
630 const std::string variation_country_code =
631 client_->GetVariationConfigCountryCode();
632 bool is_invalid_learnable_profile =
633 !IsValidLearnableProfile(candidate_profile, variation_country_code,
634 app_locale_, import_log_buffer);
635
636 // Do not import a profile if any of the requirements is violated.
637 bool all_fullfilled =
638 !(has_multiple_distinct_email_addresses || has_invalid_field_types ||
639 has_invalid_country || has_invalid_phone_number ||
640 is_invalid_learnable_profile);
641
642 // Collect metrics regarding the requirements for an address profile import.
643 AutofillMetrics::LogAddressFormImportRequirementMetric(
644 has_multiple_distinct_email_addresses
645 ? AddressImportRequirement::EMAIL_ADDRESS_UNIQUE_REQUIREMENT_VIOLATED
646 : AddressImportRequirement::
647 EMAIL_ADDRESS_UNIQUE_REQUIREMENT_FULFILLED);
648
649 AutofillMetrics::LogAddressFormImportRequirementMetric(
650 has_invalid_field_types
651 ? AddressImportRequirement::
652 NO_INVALID_FIELD_TYPES_REQUIREMENT_VIOLATED
653 : AddressImportRequirement::
654 NO_INVALID_FIELD_TYPES_REQUIREMENT_FULFILLED);
655
656 AutofillMetrics::LogAddressFormImportRequirementMetric(
657 has_invalid_phone_number
658 ? AddressImportRequirement::PHONE_VALID_REQUIREMENT_VIOLATED
659 : AddressImportRequirement::PHONE_VALID_REQUIREMENT_FULFILLED);
660
661 AutofillMetrics::LogAddressFormImportRequirementMetric(
662 has_invalid_country
663 ? AddressImportRequirement::COUNTRY_VALID_REQUIREMENT_VIOLATED
664 : AddressImportRequirement::COUNTRY_VALID_REQUIREMENT_FULFILLED);
665
666 AutofillMetrics::LogAddressFormImportRequirementMetric(
667 all_fullfilled ? AddressImportRequirement::OVERALL_REQUIREMENT_FULFILLED
668 : AddressImportRequirement::OVERALL_REQUIREMENT_VIOLATED);
669
670 if (!all_fullfilled)
671 return false;
672
673 if (!candidate_profile.FinalizeAfterImport())
674 return false;
675
676 std::string guid =
677 address_profile_save_manager_->SaveProfile(candidate_profile);
678
679 return !guid.empty();
680 }
681
ImportCreditCard(const FormStructure & form,bool should_return_local_card,std::unique_ptr<CreditCard> * imported_credit_card)682 bool FormDataImporter::ImportCreditCard(
683 const FormStructure& form,
684 bool should_return_local_card,
685 std::unique_ptr<CreditCard>* imported_credit_card) {
686 DCHECK(!*imported_credit_card);
687
688 // The candidate for credit card import. There are many ways for the candidate
689 // to be rejected (see everywhere this function returns false, below).
690 bool has_duplicate_field_type;
691 CreditCard candidate_credit_card =
692 ExtractCreditCardFromForm(form, &has_duplicate_field_type);
693
694 // If we've seen the same credit card field type twice in the same form,
695 // abort credit card import/update.
696 if (has_duplicate_field_type)
697 return false;
698
699 if (candidate_credit_card.IsValid()) {
700 AutofillMetrics::LogSubmittedCardStateMetric(
701 AutofillMetrics::HAS_CARD_NUMBER_AND_EXPIRATION_DATE);
702 } else {
703 if (candidate_credit_card.HasValidCardNumber()) {
704 AutofillMetrics::LogSubmittedCardStateMetric(
705 AutofillMetrics::HAS_CARD_NUMBER_ONLY);
706 }
707 if (candidate_credit_card.HasValidExpirationDate()) {
708 AutofillMetrics::LogSubmittedCardStateMetric(
709 AutofillMetrics::HAS_EXPIRATION_DATE_ONLY);
710 }
711 }
712
713 // Cards with invalid expiration dates can be uploaded due to the existence of
714 // the expiration date fix flow. However, cards with invalid card numbers must
715 // still be ignored.
716 if (!candidate_credit_card.HasValidCardNumber()) {
717 return false;
718 }
719
720 // Can import one valid card per form. Start by treating it as NEW_CARD, but
721 // overwrite this type if we discover it is already a local or server card.
722 imported_credit_card_record_type_ = ImportedCreditCardRecordType::NEW_CARD;
723
724 // Attempt to merge with an existing credit card. Don't present a prompt if we
725 // have already saved this card number, unless |should_return_local_card| is
726 // true which indicates that upload is enabled. In this case, it's useful to
727 // present the upload prompt to the user to promote the card from a local card
728 // to a synced server card, provided we don't have a masked server card with
729 // the same |TypeAndLastFourDigits|.
730 for (const CreditCard* card : personal_data_manager_->GetLocalCreditCards()) {
731 // Make a local copy so that the data in |local_credit_cards_| isn't
732 // modified directly by the UpdateFromImportedCard() call.
733 CreditCard card_copy(*card);
734 if (card_copy.UpdateFromImportedCard(candidate_credit_card, app_locale_)) {
735 personal_data_manager_->UpdateCreditCard(card_copy);
736 // Mark that the credit card imported from the submitted form is
737 // already a local card.
738 imported_credit_card_record_type_ =
739 ImportedCreditCardRecordType::LOCAL_CARD;
740
741 // If the card is a local card and it has a nickname stored in the local
742 // database, copy the nickname to the |candidate_credit_card| so that the
743 // nickname also shows in the Upstream bubble.
744 candidate_credit_card.SetNickname(card_copy.nickname());
745
746 // If we should not return the local card, return that we merged it,
747 // without setting |imported_credit_card|.
748 if (!should_return_local_card)
749 return true;
750
751 break;
752 }
753 }
754
755 // Also don't offer to save if we already have this stored as a server
756 // card. We only check the number because if the new card has the same number
757 // as the server card, upload is guaranteed to fail. There's no mechanism for
758 // entries with the same number but different names or expiration dates as
759 // there is for local cards.
760 for (const CreditCard* card :
761 personal_data_manager_->GetServerCreditCards()) {
762 if ((card->record_type() == CreditCard::MASKED_SERVER_CARD &&
763 card->LastFourDigits() == candidate_credit_card.LastFourDigits()) ||
764 (card->record_type() == CreditCard::FULL_SERVER_CARD &&
765 candidate_credit_card.HasSameNumberAs(*card))) {
766 // Don't update card if the expiration date is missing
767 if (candidate_credit_card.expiration_month() == 0 ||
768 candidate_credit_card.expiration_year() == 0) {
769 return false;
770 }
771 // Mark that the imported credit card is a server card.
772 imported_credit_card_record_type_ =
773 ImportedCreditCardRecordType::SERVER_CARD;
774 // Record metric on whether expiration dates matched.
775 if (candidate_credit_card.expiration_month() ==
776 card->expiration_month() &&
777 candidate_credit_card.expiration_year() == card->expiration_year()) {
778 AutofillMetrics::LogSubmittedServerCardExpirationStatusMetric(
779 card->record_type() == CreditCard::FULL_SERVER_CARD
780 ? AutofillMetrics::FULL_SERVER_CARD_EXPIRATION_DATE_MATCHED
781 : AutofillMetrics::MASKED_SERVER_CARD_EXPIRATION_DATE_MATCHED);
782 } else {
783 AutofillMetrics::LogSubmittedServerCardExpirationStatusMetric(
784 card->record_type() == CreditCard::FULL_SERVER_CARD
785 ? AutofillMetrics::
786 FULL_SERVER_CARD_EXPIRATION_DATE_DID_NOT_MATCH
787 : AutofillMetrics::
788 MASKED_SERVER_CARD_EXPIRATION_DATE_DID_NOT_MATCH);
789 }
790 return false;
791 }
792 }
793 *imported_credit_card = std::make_unique<CreditCard>(candidate_credit_card);
794 return true;
795 }
796
ExtractCreditCardFromForm(const FormStructure & form,bool * has_duplicate_field_type)797 CreditCard FormDataImporter::ExtractCreditCardFromForm(
798 const FormStructure& form,
799 bool* has_duplicate_field_type) {
800 *has_duplicate_field_type = false;
801 has_non_focusable_field_ = false;
802 from_dynamic_change_form_ = false;
803
804 CreditCard candidate_credit_card;
805
806 std::set<ServerFieldType> types_seen;
807 for (const auto& field : form) {
808 base::string16 value;
809 base::TrimWhitespace(field->value, base::TRIM_ALL, &value);
810
811 // If we don't know the type of the field, or the user hasn't entered any
812 // information into the field, then skip it.
813 if (!field->IsFieldFillable() || value.empty())
814 continue;
815
816 AutofillType field_type = field->Type();
817 // Field was not identified as a credit card field.
818 if (field_type.group() != CREDIT_CARD)
819 continue;
820
821 if (form.value_from_dynamic_change_form())
822 from_dynamic_change_form_ = true;
823 if (!field->is_focusable)
824 has_non_focusable_field_ = true;
825
826 // If we've seen the same credit card field type twice in the same form,
827 // set |has_duplicate_field_type| to true.
828 ServerFieldType server_field_type = field_type.GetStorableType();
829 if (types_seen.count(server_field_type)) {
830 *has_duplicate_field_type = true;
831 } else {
832 types_seen.insert(server_field_type);
833 }
834 // If |field| is an HTML5 month input, handle it as a special case.
835 if (base::LowerCaseEqualsASCII(field->form_control_type, "month")) {
836 DCHECK_EQ(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, server_field_type);
837 candidate_credit_card.SetInfoForMonthInputType(value);
838 continue;
839 }
840
841 // CreditCard handles storing the |value| according to |field_type|.
842 bool saved = candidate_credit_card.SetInfo(field_type, value, app_locale_);
843
844 // Saving with the option text (here |value|) may fail for the expiration
845 // month. Attempt to save with the option value. First find the index of the
846 // option text in the select options and try the corresponding value.
847 if (!saved && server_field_type == CREDIT_CARD_EXP_MONTH) {
848 for (size_t i = 0; i < field->option_contents.size(); ++i) {
849 if (value == field->option_contents[i]) {
850 candidate_credit_card.SetInfo(field_type, field->option_values[i],
851 app_locale_);
852 break;
853 }
854 }
855 }
856 }
857
858 return candidate_credit_card;
859 }
860
ImportUpiId(const FormStructure & form)861 base::Optional<std::string> FormDataImporter::ImportUpiId(
862 const FormStructure& form) {
863 for (const auto& field : form) {
864 if (IsUPIVirtualPaymentAddress(field->value))
865 return base::UTF16ToUTF8(field->value);
866 }
867 return base::nullopt;
868 }
869
870 } // namespace autofill
871