1 // Copyright 2015 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.
5 #include "chrome/browser/extensions/api/autofill_private/autofill_private_api.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/values.h"
10 #include "chrome/browser/autofill/personal_data_manager_factory.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/common/extensions/api/autofill_private.h"
13 #include "chrome/grit/generated_resources.h"
14 #include "components/autofill/core/browser/autofill_profile.h"
15 #include "components/autofill/core/browser/personal_data_manager.h"
16 #include "extensions/browser/extension_function.h"
17 #include "extensions/browser/extension_function_registry.h"
18 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_ui.h"
19 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_ui_component.h"
20 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/localization.h"
21 #include "ui/base/l10n/l10n_util.h"
23 namespace autofill_private
= extensions::api::autofill_private
;
24 namespace addressinput
= i18n::addressinput
;
28 static const char kSettingsOrigin
[] = "Chrome settings";
29 static const char kErrorDataUnavailable
[] = "Autofill data unavailable.";
31 // Fills |components| with the address UI components that should be used to
32 // input an address for |country_code| when UI BCP 47 language code is
33 // |ui_language_code|.
34 void PopulateAddressComponents(
35 const std::string
& country_code
,
36 const std::string
& ui_language_code
,
37 autofill_private::AddressComponents
* address_components
) {
38 DCHECK(address_components
);
40 i18n::addressinput::Localization localization
;
41 localization
.SetGetter(l10n_util::GetStringUTF8
);
42 std::string best_address_language_code
;
43 std::vector
<addressinput::AddressUiComponent
> components
=
44 i18n::addressinput::BuildComponents(
48 &best_address_language_code
);
49 if (components
.empty()) {
50 static const char kDefaultCountryCode
[] = "US";
51 components
= i18n::addressinput::BuildComponents(
55 &best_address_language_code
);
57 address_components
->language_code
= best_address_language_code
;
58 DCHECK(!components
.empty());
60 autofill_private::AddressComponentRow
* row
= nullptr;
61 for (size_t i
= 0; i
< components
.size(); ++i
) {
63 components
[i
- 1].length_hint
==
64 addressinput::AddressUiComponent::HINT_LONG
||
65 components
[i
].length_hint
==
66 addressinput::AddressUiComponent::HINT_LONG
) {
67 row
= new autofill_private::AddressComponentRow
;
68 address_components
->components
.push_back(make_linked_ptr(row
));
71 scoped_ptr
<autofill_private::AddressComponent
>
72 component(new autofill_private::AddressComponent
);
73 component
->field_name
= components
[i
].name
;
75 switch (components
[i
].field
) {
76 case i18n::addressinput::COUNTRY
:
78 autofill_private::AddressField::ADDRESS_FIELD_COUNTRY_CODE
;
80 case i18n::addressinput::ADMIN_AREA
:
82 autofill_private::AddressField::ADDRESS_FIELD_ADDRESS_LEVEL_1
;
84 case i18n::addressinput::LOCALITY
:
86 autofill_private::AddressField::ADDRESS_FIELD_ADDRESS_LEVEL_2
;
88 case i18n::addressinput::DEPENDENT_LOCALITY
:
90 autofill_private::AddressField::ADDRESS_FIELD_ADDRESS_LEVEL_3
;
92 case i18n::addressinput::SORTING_CODE
:
94 autofill_private::AddressField::ADDRESS_FIELD_SORTING_CODE
;
96 case i18n::addressinput::POSTAL_CODE
:
98 autofill_private::AddressField::ADDRESS_FIELD_POSTAL_CODE
;
100 case i18n::addressinput::STREET_ADDRESS
:
102 autofill_private::AddressField::ADDRESS_FIELD_ADDRESS_LINES
;
104 case i18n::addressinput::ORGANIZATION
:
106 autofill_private::AddressField::ADDRESS_FIELD_COMPANY_NAME
;
108 case i18n::addressinput::RECIPIENT
:
110 autofill_private::AddressField::ADDRESS_FIELD_FULL_NAME
;
111 component
->placeholder
.reset(new std::string(
112 l10n_util::GetStringUTF8(IDS_AUTOFILL_FIELD_LABEL_ADD_NAME
)));
116 switch (components
[i
].length_hint
) {
117 case addressinput::AddressUiComponent::HINT_LONG
:
118 component
->is_long_field
= true;
120 case addressinput::AddressUiComponent::HINT_SHORT
:
121 component
->is_long_field
= false;
125 row
->row
.push_back(make_linked_ptr(component
.release()));
129 // Searches the |list| for the value at |index|. If this value is present in
130 // any of the rest of the list, then the item (at |index|) is removed. The
131 // comparison of phone number values is done on normalized versions of the phone
133 void RemoveDuplicatePhoneNumberAtIndex(
134 size_t index
, const std::string
& country_code
, base::ListValue
* list
) {
135 base::string16 new_value
;
136 if (!list
->GetString(index
, &new_value
)) {
137 NOTREACHED() << "List should have a value at index " << index
;
141 bool is_duplicate
= false;
142 std::string app_locale
= g_browser_process
->GetApplicationLocale();
143 for (size_t i
= 0; i
< list
->GetSize() && !is_duplicate
; ++i
) {
147 base::string16 existing_value
;
148 if (!list
->GetString(i
, &existing_value
)) {
149 NOTREACHED() << "List should have a value at index " << i
;
152 is_duplicate
= autofill::i18n::PhoneNumbersMatch(
153 new_value
, existing_value
, country_code
, app_locale
);
157 list
->Remove(index
, nullptr);
162 namespace extensions
{
164 ////////////////////////////////////////////////////////////////////////////////
165 // AutofillPrivateSaveAddressFunction
167 AutofillPrivateSaveAddressFunction::AutofillPrivateSaveAddressFunction()
168 : chrome_details_(this) {}
170 AutofillPrivateSaveAddressFunction::~AutofillPrivateSaveAddressFunction() {}
172 ExtensionFunction::ResponseAction
AutofillPrivateSaveAddressFunction::Run() {
173 scoped_ptr
<api::autofill_private::SaveAddress::Params
> parameters
=
174 api::autofill_private::SaveAddress::Params::Create(*args_
);
175 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
177 autofill::PersonalDataManager
* personal_data
=
178 autofill::PersonalDataManagerFactory::GetForProfile(
179 chrome_details_
.GetProfile());
180 if (!personal_data
|| !personal_data
->IsDataLoaded()) {
181 error_
= kErrorDataUnavailable
;
182 return RespondNow(NoArguments());
185 api::autofill_private::AddressEntry
* address
= ¶meters
->address
;
187 std::string guid
= address
->guid
? *address
->guid
: "";
188 autofill::AutofillProfile
profile(guid
, kSettingsOrigin
);
190 // Strings from JavaScript use UTF-8 encoding. This container is used as an
191 // intermediate container for functions which require UTF-16 strings.
192 std::vector
<base::string16
> string16Container
;
194 if (address
->full_names
) {
195 std::string full_name
;
196 if (!address
->full_names
->empty())
197 full_name
= address
->full_names
->at(0);
198 profile
.SetInfo(autofill::AutofillType(autofill::NAME_FULL
),
199 base::UTF8ToUTF16(full_name
),
200 g_browser_process
->GetApplicationLocale());
203 if (address
->company_name
) {
205 autofill::COMPANY_NAME
,
206 base::UTF8ToUTF16(*address
->company_name
));
209 if (address
->address_lines
) {
211 autofill::ADDRESS_HOME_STREET_ADDRESS
,
212 base::UTF8ToUTF16(*address
->address_lines
));
215 if (address
->address_level1
) {
217 autofill::ADDRESS_HOME_CITY
,
218 base::UTF8ToUTF16(*address
->address_level1
));
221 if (address
->address_level2
) {
223 autofill::ADDRESS_HOME_STATE
,
224 base::UTF8ToUTF16(*address
->address_level2
));
227 if (address
->address_level3
) {
229 autofill::ADDRESS_HOME_DEPENDENT_LOCALITY
,
230 base::UTF8ToUTF16(*address
->address_level3
));
233 if (address
->postal_code
) {
235 autofill::ADDRESS_HOME_ZIP
,
236 base::UTF8ToUTF16(*address
->postal_code
));
239 if (address
->sorting_code
) {
241 autofill::ADDRESS_HOME_SORTING_CODE
,
242 base::UTF8ToUTF16(*address
->sorting_code
));
245 if (address
->country_code
) {
247 autofill::ADDRESS_HOME_COUNTRY
,
248 base::UTF8ToUTF16(*address
->country_code
));
251 if (address
->phone_numbers
) {
253 if (!address
->phone_numbers
->empty())
254 phone
= address
->phone_numbers
->at(0);
255 profile
.SetRawInfo(autofill::PHONE_HOME_WHOLE_NUMBER
,
256 base::UTF8ToUTF16(phone
));
259 if (address
->email_addresses
) {
261 if (!address
->email_addresses
->empty())
262 email
= address
->email_addresses
->at(0);
263 profile
.SetRawInfo(autofill::EMAIL_ADDRESS
, base::UTF8ToUTF16(email
));
266 if (address
->language_code
)
267 profile
.set_language_code(*address
->language_code
);
269 if (!base::IsValidGUID(profile
.guid())) {
270 profile
.set_guid(base::GenerateGUID());
271 personal_data
->AddProfile(profile
);
273 personal_data
->UpdateProfile(profile
);
276 return RespondNow(NoArguments());
279 ////////////////////////////////////////////////////////////////////////////////
280 // AutofillPrivateGetAddressComponentsFunction
282 AutofillPrivateGetAddressComponentsFunction::
283 ~AutofillPrivateGetAddressComponentsFunction() {}
285 ExtensionFunction::ResponseAction
286 AutofillPrivateGetAddressComponentsFunction::Run() {
287 scoped_ptr
<api::autofill_private::GetAddressComponents::Params
> parameters
=
288 api::autofill_private::GetAddressComponents::Params::Create(*args_
);
289 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
291 autofill_private::AddressComponents components
;
292 PopulateAddressComponents(
293 parameters
->country_code
,
294 g_browser_process
->GetApplicationLocale(),
297 return RespondNow(OneArgument(components
.ToValue().release()));
300 ////////////////////////////////////////////////////////////////////////////////
301 // AutofillPrivateSaveCreditCardFunction
303 AutofillPrivateSaveCreditCardFunction::AutofillPrivateSaveCreditCardFunction()
304 : chrome_details_(this) {}
306 AutofillPrivateSaveCreditCardFunction::
307 ~AutofillPrivateSaveCreditCardFunction() {}
309 ExtensionFunction::ResponseAction
AutofillPrivateSaveCreditCardFunction::Run() {
310 scoped_ptr
<api::autofill_private::SaveCreditCard::Params
> parameters
=
311 api::autofill_private::SaveCreditCard::Params::Create(*args_
);
312 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
314 autofill::PersonalDataManager
* personal_data
=
315 autofill::PersonalDataManagerFactory::GetForProfile(
316 chrome_details_
.GetProfile());
317 if (!personal_data
|| !personal_data
->IsDataLoaded()) {
318 error_
= kErrorDataUnavailable
;
319 return RespondNow(NoArguments());
322 api::autofill_private::CreditCardEntry
* card
= ¶meters
->card
;
324 std::string guid
= card
->guid
? *card
->guid
: "";
325 autofill::CreditCard
credit_card(guid
, kSettingsOrigin
);
328 credit_card
.SetRawInfo(
329 autofill::CREDIT_CARD_NAME
,
330 base::UTF8ToUTF16(*card
->name
));
333 if (card
->card_number
) {
334 credit_card
.SetRawInfo(
335 autofill::CREDIT_CARD_NUMBER
,
336 base::UTF8ToUTF16(*card
->card_number
));
339 if (card
->expiration_month
) {
340 credit_card
.SetRawInfo(
341 autofill::CREDIT_CARD_EXP_MONTH
,
342 base::UTF8ToUTF16(*card
->expiration_month
));
345 if (card
->expiration_year
) {
346 credit_card
.SetRawInfo(
347 autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR
,
348 base::UTF8ToUTF16(*card
->expiration_year
));
351 if (!base::IsValidGUID(credit_card
.guid())) {
352 credit_card
.set_guid(base::GenerateGUID());
353 personal_data
->AddCreditCard(credit_card
);
355 personal_data
->UpdateCreditCard(credit_card
);
358 return RespondNow(NoArguments());
361 ////////////////////////////////////////////////////////////////////////////////
362 // AutofillPrivateRemoveEntryFunction
364 AutofillPrivateRemoveEntryFunction::AutofillPrivateRemoveEntryFunction()
365 : chrome_details_(this) {}
367 AutofillPrivateRemoveEntryFunction::~AutofillPrivateRemoveEntryFunction() {}
369 ExtensionFunction::ResponseAction
AutofillPrivateRemoveEntryFunction::Run() {
370 scoped_ptr
<api::autofill_private::RemoveEntry::Params
> parameters
=
371 api::autofill_private::RemoveEntry::Params::Create(*args_
);
372 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
374 autofill::PersonalDataManager
* personal_data
=
375 autofill::PersonalDataManagerFactory::GetForProfile(
376 chrome_details_
.GetProfile());
377 if (!personal_data
|| !personal_data
->IsDataLoaded()) {
378 error_
= kErrorDataUnavailable
;
379 return RespondNow(NoArguments());
382 personal_data
->RemoveByGUID(parameters
->guid
);
384 return RespondNow(NoArguments());
387 ////////////////////////////////////////////////////////////////////////////////
388 // AutofillPrivateValidatePhoneNumbersFunction
390 AutofillPrivateValidatePhoneNumbersFunction::
391 ~AutofillPrivateValidatePhoneNumbersFunction() {}
393 ExtensionFunction::ResponseAction
394 AutofillPrivateValidatePhoneNumbersFunction::Run() {
395 scoped_ptr
<api::autofill_private::ValidatePhoneNumbers::Params
> parameters
=
396 api::autofill_private::ValidatePhoneNumbers::Params::Create(*args_
);
397 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
399 api::autofill_private::ValidatePhoneParams
* params
= ¶meters
->params
;
401 // Extract the phone numbers into a ListValue.
402 scoped_ptr
<base::ListValue
> phoneNumbers(new base::ListValue
);
403 phoneNumbers
->AppendStrings(params
->phone_numbers
);
405 RemoveDuplicatePhoneNumberAtIndex(
406 params
->index_of_new_number
, params
->country_code
, phoneNumbers
.get());
408 return RespondNow(OneArgument(phoneNumbers
.Pass()));
411 ////////////////////////////////////////////////////////////////////////////////
412 // AutofillPrivateMaskCreditCardFunction
414 AutofillPrivateMaskCreditCardFunction::AutofillPrivateMaskCreditCardFunction()
415 : chrome_details_(this) {}
417 AutofillPrivateMaskCreditCardFunction::
418 ~AutofillPrivateMaskCreditCardFunction() {}
420 ExtensionFunction::ResponseAction
AutofillPrivateMaskCreditCardFunction::Run() {
421 scoped_ptr
<api::autofill_private::MaskCreditCard::Params
> parameters
=
422 api::autofill_private::MaskCreditCard::Params::Create(*args_
);
423 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
425 autofill::PersonalDataManager
* personal_data
=
426 autofill::PersonalDataManagerFactory::GetForProfile(
427 chrome_details_
.GetProfile());
428 if (!personal_data
|| !personal_data
->IsDataLoaded()) {
429 error_
= kErrorDataUnavailable
;
430 return RespondNow(NoArguments());
433 personal_data
->ResetFullServerCard(parameters
->guid
);
435 return RespondNow(NoArguments());
438 } // namespace extensions