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
;
114 switch (components
[i
].length_hint
) {
115 case addressinput::AddressUiComponent::HINT_LONG
:
116 component
->is_long_field
= true;
118 case addressinput::AddressUiComponent::HINT_SHORT
:
119 component
->is_long_field
= false;
123 row
->row
.push_back(make_linked_ptr(component
.release()));
127 // Searches the |list| for the value at |index|. If this value is present in
128 // any of the rest of the list, then the item (at |index|) is removed. The
129 // comparison of phone number values is done on normalized versions of the phone
131 void RemoveDuplicatePhoneNumberAtIndex(
132 size_t index
, const std::string
& country_code
, base::ListValue
* list
) {
133 base::string16 new_value
;
134 if (!list
->GetString(index
, &new_value
)) {
135 NOTREACHED() << "List should have a value at index " << index
;
139 bool is_duplicate
= false;
140 std::string app_locale
= g_browser_process
->GetApplicationLocale();
141 for (size_t i
= 0; i
< list
->GetSize() && !is_duplicate
; ++i
) {
145 base::string16 existing_value
;
146 if (!list
->GetString(i
, &existing_value
)) {
147 NOTREACHED() << "List should have a value at index " << i
;
150 is_duplicate
= autofill::i18n::PhoneNumbersMatch(
151 new_value
, existing_value
, country_code
, app_locale
);
155 list
->Remove(index
, nullptr);
160 namespace extensions
{
162 ////////////////////////////////////////////////////////////////////////////////
163 // AutofillPrivateSaveAddressFunction
165 AutofillPrivateSaveAddressFunction::AutofillPrivateSaveAddressFunction()
166 : chrome_details_(this) {}
168 AutofillPrivateSaveAddressFunction::~AutofillPrivateSaveAddressFunction() {}
170 ExtensionFunction::ResponseAction
AutofillPrivateSaveAddressFunction::Run() {
171 scoped_ptr
<api::autofill_private::SaveAddress::Params
> parameters
=
172 api::autofill_private::SaveAddress::Params::Create(*args_
);
173 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
175 autofill::PersonalDataManager
* personal_data
=
176 autofill::PersonalDataManagerFactory::GetForProfile(
177 chrome_details_
.GetProfile());
178 if (!personal_data
|| !personal_data
->IsDataLoaded()) {
179 error_
= kErrorDataUnavailable
;
180 return RespondNow(NoArguments());
183 api::autofill_private::AddressEntry
* address
= ¶meters
->address
;
185 std::string guid
= address
->guid
? *address
->guid
: "";
186 autofill::AutofillProfile
profile(guid
, kSettingsOrigin
);
188 // Strings from JavaScript use UTF-8 encoding. This container is used as an
189 // intermediate container for functions which require UTF-16 strings.
190 std::vector
<base::string16
> string16Container
;
192 if (address
->full_names
) {
193 std::string full_name
;
194 if (!address
->full_names
->empty())
195 full_name
= address
->full_names
->at(0);
196 profile
.SetInfo(autofill::AutofillType(autofill::NAME_FULL
),
197 base::UTF8ToUTF16(full_name
),
198 g_browser_process
->GetApplicationLocale());
201 if (address
->company_name
) {
203 autofill::COMPANY_NAME
,
204 base::UTF8ToUTF16(*address
->company_name
));
207 if (address
->address_lines
) {
209 autofill::ADDRESS_HOME_STREET_ADDRESS
,
210 base::UTF8ToUTF16(*address
->address_lines
));
213 if (address
->address_level1
) {
215 autofill::ADDRESS_HOME_CITY
,
216 base::UTF8ToUTF16(*address
->address_level1
));
219 if (address
->address_level2
) {
221 autofill::ADDRESS_HOME_STATE
,
222 base::UTF8ToUTF16(*address
->address_level2
));
225 if (address
->address_level3
) {
227 autofill::ADDRESS_HOME_DEPENDENT_LOCALITY
,
228 base::UTF8ToUTF16(*address
->address_level3
));
231 if (address
->postal_code
) {
233 autofill::ADDRESS_HOME_ZIP
,
234 base::UTF8ToUTF16(*address
->postal_code
));
237 if (address
->sorting_code
) {
239 autofill::ADDRESS_HOME_SORTING_CODE
,
240 base::UTF8ToUTF16(*address
->sorting_code
));
243 if (address
->country_code
) {
245 autofill::ADDRESS_HOME_COUNTRY
,
246 base::UTF8ToUTF16(*address
->country_code
));
249 if (address
->phone_numbers
) {
251 if (!address
->phone_numbers
->empty())
252 phone
= address
->phone_numbers
->at(0);
253 profile
.SetRawInfo(autofill::PHONE_HOME_WHOLE_NUMBER
,
254 base::UTF8ToUTF16(phone
));
257 if (address
->email_addresses
) {
259 if (!address
->email_addresses
->empty())
260 email
= address
->email_addresses
->at(0);
261 profile
.SetRawInfo(autofill::EMAIL_ADDRESS
, base::UTF8ToUTF16(email
));
264 if (address
->language_code
)
265 profile
.set_language_code(*address
->language_code
);
267 if (!base::IsValidGUID(profile
.guid())) {
268 profile
.set_guid(base::GenerateGUID());
269 personal_data
->AddProfile(profile
);
271 personal_data
->UpdateProfile(profile
);
274 return RespondNow(NoArguments());
277 ////////////////////////////////////////////////////////////////////////////////
278 // AutofillPrivateGetAddressComponentsFunction
280 AutofillPrivateGetAddressComponentsFunction::
281 ~AutofillPrivateGetAddressComponentsFunction() {}
283 ExtensionFunction::ResponseAction
284 AutofillPrivateGetAddressComponentsFunction::Run() {
285 scoped_ptr
<api::autofill_private::GetAddressComponents::Params
> parameters
=
286 api::autofill_private::GetAddressComponents::Params::Create(*args_
);
287 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
289 autofill_private::AddressComponents components
;
290 PopulateAddressComponents(
291 parameters
->country_code
,
292 g_browser_process
->GetApplicationLocale(),
295 return RespondNow(OneArgument(components
.ToValue().release()));
298 ////////////////////////////////////////////////////////////////////////////////
299 // AutofillPrivateSaveCreditCardFunction
301 AutofillPrivateSaveCreditCardFunction::AutofillPrivateSaveCreditCardFunction()
302 : chrome_details_(this) {}
304 AutofillPrivateSaveCreditCardFunction::
305 ~AutofillPrivateSaveCreditCardFunction() {}
307 ExtensionFunction::ResponseAction
AutofillPrivateSaveCreditCardFunction::Run() {
308 scoped_ptr
<api::autofill_private::SaveCreditCard::Params
> parameters
=
309 api::autofill_private::SaveCreditCard::Params::Create(*args_
);
310 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
312 autofill::PersonalDataManager
* personal_data
=
313 autofill::PersonalDataManagerFactory::GetForProfile(
314 chrome_details_
.GetProfile());
315 if (!personal_data
|| !personal_data
->IsDataLoaded()) {
316 error_
= kErrorDataUnavailable
;
317 return RespondNow(NoArguments());
320 api::autofill_private::CreditCardEntry
* card
= ¶meters
->card
;
322 std::string guid
= card
->guid
? *card
->guid
: "";
323 autofill::CreditCard
credit_card(guid
, kSettingsOrigin
);
326 credit_card
.SetRawInfo(
327 autofill::CREDIT_CARD_NAME
,
328 base::UTF8ToUTF16(*card
->name
));
331 if (card
->card_number
) {
332 credit_card
.SetRawInfo(
333 autofill::CREDIT_CARD_NUMBER
,
334 base::UTF8ToUTF16(*card
->card_number
));
337 if (card
->expiration_month
) {
338 credit_card
.SetRawInfo(
339 autofill::CREDIT_CARD_EXP_MONTH
,
340 base::UTF8ToUTF16(*card
->expiration_month
));
343 if (card
->expiration_year
) {
344 credit_card
.SetRawInfo(
345 autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR
,
346 base::UTF8ToUTF16(*card
->expiration_year
));
349 if (!base::IsValidGUID(credit_card
.guid())) {
350 credit_card
.set_guid(base::GenerateGUID());
351 personal_data
->AddCreditCard(credit_card
);
353 personal_data
->UpdateCreditCard(credit_card
);
356 return RespondNow(NoArguments());
359 ////////////////////////////////////////////////////////////////////////////////
360 // AutofillPrivateRemoveEntryFunction
362 AutofillPrivateRemoveEntryFunction::AutofillPrivateRemoveEntryFunction()
363 : chrome_details_(this) {}
365 AutofillPrivateRemoveEntryFunction::~AutofillPrivateRemoveEntryFunction() {}
367 ExtensionFunction::ResponseAction
AutofillPrivateRemoveEntryFunction::Run() {
368 scoped_ptr
<api::autofill_private::RemoveEntry::Params
> parameters
=
369 api::autofill_private::RemoveEntry::Params::Create(*args_
);
370 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
372 autofill::PersonalDataManager
* personal_data
=
373 autofill::PersonalDataManagerFactory::GetForProfile(
374 chrome_details_
.GetProfile());
375 if (!personal_data
|| !personal_data
->IsDataLoaded()) {
376 error_
= kErrorDataUnavailable
;
377 return RespondNow(NoArguments());
380 personal_data
->RemoveByGUID(parameters
->guid
);
382 return RespondNow(NoArguments());
385 ////////////////////////////////////////////////////////////////////////////////
386 // AutofillPrivateValidatePhoneNumbersFunction
388 AutofillPrivateValidatePhoneNumbersFunction::
389 ~AutofillPrivateValidatePhoneNumbersFunction() {}
391 ExtensionFunction::ResponseAction
392 AutofillPrivateValidatePhoneNumbersFunction::Run() {
393 scoped_ptr
<api::autofill_private::ValidatePhoneNumbers::Params
> parameters
=
394 api::autofill_private::ValidatePhoneNumbers::Params::Create(*args_
);
395 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
397 api::autofill_private::ValidatePhoneParams
* params
= ¶meters
->params
;
399 // Extract the phone numbers into a ListValue.
400 scoped_ptr
<base::ListValue
> phoneNumbers(new base::ListValue
);
401 phoneNumbers
->AppendStrings(params
->phone_numbers
);
403 RemoveDuplicatePhoneNumberAtIndex(
404 params
->index_of_new_number
, params
->country_code
, phoneNumbers
.get());
406 return RespondNow(OneArgument(phoneNumbers
.Pass()));
409 ////////////////////////////////////////////////////////////////////////////////
410 // AutofillPrivateMaskCreditCardFunction
412 AutofillPrivateMaskCreditCardFunction::AutofillPrivateMaskCreditCardFunction()
413 : chrome_details_(this) {}
415 AutofillPrivateMaskCreditCardFunction::
416 ~AutofillPrivateMaskCreditCardFunction() {}
418 ExtensionFunction::ResponseAction
AutofillPrivateMaskCreditCardFunction::Run() {
419 scoped_ptr
<api::autofill_private::MaskCreditCard::Params
> parameters
=
420 api::autofill_private::MaskCreditCard::Params::Create(*args_
);
421 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
423 autofill::PersonalDataManager
* personal_data
=
424 autofill::PersonalDataManagerFactory::GetForProfile(
425 chrome_details_
.GetProfile());
426 if (!personal_data
|| !personal_data
->IsDataLoaded()) {
427 error_
= kErrorDataUnavailable
;
428 return RespondNow(NoArguments());
431 personal_data
->ResetFullServerCard(parameters
->guid
);
433 return RespondNow(NoArguments());
436 } // namespace extensions