Index: chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc |
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc |
index 4005cd637740de78e4b893536150352e6f725c0c..e9a40956f5ce54b5f1bea9dc5556bd7ab6dc2ea6 100644 |
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc |
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc |
@@ -13,6 +13,7 @@ |
#include "apps/ui/native_app_window.h" |
#include "base/base64.h" |
#include "base/bind.h" |
+#include "base/bind_helpers.h" |
#include "base/i18n/case_conversion.h" |
#include "base/i18n/rtl.h" |
#include "base/logging.h" |
@@ -26,6 +27,7 @@ |
#include "base/strings/utf_string_conversions.h" |
#include "base/time/time.h" |
#include "chrome/browser/autofill/personal_data_manager_factory.h" |
+#include "chrome/browser/autofill/validation_rules_storage_factory.h" |
#include "chrome/browser/browser_process.h" |
#include "chrome/browser/profiles/profile.h" |
#include "chrome/browser/ui/autofill/autofill_dialog_common.h" |
@@ -79,6 +81,10 @@ |
#include "grit/theme_resources.h" |
#include "grit/webkit_resources.h" |
#include "net/cert/cert_status_flags.h" |
+#include "third_party/libaddressinput/chromium/chrome_downloader_impl.h" |
+#include "third_party/libaddressinput/chromium/chrome_storage_impl.h" |
+#include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_data.h" |
+#include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_problem.h" |
#include "ui/base/base_window.h" |
#include "ui/base/l10n/l10n_util.h" |
#include "ui/base/models/combobox_model.h" |
@@ -88,6 +94,13 @@ |
#include "ui/gfx/image/image_skia_operations.h" |
#include "ui/gfx/skia_util.h" |
+using ::i18n::addressinput::AddressData; |
+using ::i18n::addressinput::AddressField; |
+using ::i18n::addressinput::AddressProblem; |
+using ::i18n::addressinput::AddressProblemFilter; |
+using ::i18n::addressinput::AddressProblems; |
+using ::i18n::addressinput::AddressValidator; |
+ |
namespace autofill { |
namespace { |
@@ -145,6 +158,28 @@ base::string16 NullGetInfo(const AutofillType& type) { |
return base::string16(); |
} |
+// Extract |type| from |inputs| using |section| to determine whether the info |
+// should be billing or shipping specific (for sections with address info). |
+base::string16 GetInfoFromInputs(const FieldValueMap& inputs, |
+ DialogSection section, |
+ const AutofillType& type) { |
+ ServerFieldType field_type = type.GetStorableType(); |
+ if (section != SECTION_SHIPPING) |
+ field_type = AutofillType::GetEquivalentBillingFieldType(field_type); |
+ |
+ base::string16 info; |
+ FieldValueMap::const_iterator it = inputs.find(field_type); |
+ if (it != inputs.end()) |
+ info = it->second; |
+ |
+ if (!info.empty() && type.html_type() == HTML_TYPE_COUNTRY_CODE) { |
+ info = base::ASCIIToUTF16(AutofillCountry::GetCountryCode( |
+ info, g_browser_process->GetApplicationLocale())); |
+ } |
+ |
+ return info; |
+} |
+ |
// Returns true if |input| should be used to fill a site-requested |field| which |
// is notated with a "shipping" tag, for use when the user has decided to use |
// the billing address as the shipping address. |
@@ -618,6 +653,17 @@ void AutofillDialogControllerImpl::Show() { |
if (account_chooser_model_->WalletIsSelected()) |
FetchWalletCookie(); |
+ if (i18ninput::Enabled()) { |
+ scoped_ptr< ::i18n::addressinput::Downloader> downloader( |
+ new autofill::ChromeDownloaderImpl(profile_->GetRequestContext())); |
+ validator_ = AddressValidator::Build( |
+ downloader.Pass(), |
+ ValidationRulesStorageFactory::CreateStorage(), |
+ this); |
+ GetValidator()->LoadRules( |
+ GetManager()->GetDefaultCountryCodeForNewAddress()); |
+ } |
+ |
// TODO(estade): don't show the dialog if the site didn't specify the right |
// fields. First we must figure out what the "right" fields are. |
SuggestionsUpdated(); |
@@ -1162,20 +1208,18 @@ void AutofillDialogControllerImpl::RestoreUserInputFromSnapshot( |
if (snapshot.empty()) |
return; |
- FieldMapWrapper wrapper(snapshot); |
for (size_t i = SECTION_MIN; i <= SECTION_MAX; ++i) { |
DialogSection section = static_cast<DialogSection>(i); |
if (!SectionIsActive(section)) |
continue; |
DetailInputs* inputs = MutableRequestedFieldsForSection(section); |
- wrapper.FillInputs(inputs); |
- |
for (size_t i = 0; i < inputs->size(); ++i) { |
- if (InputWasEdited((*inputs)[i].type, (*inputs)[i].initial_value)) { |
+ DetailInput* input = &(*inputs)[i]; |
+ input->initial_value = |
+ GetInfoFromInputs(snapshot, section, AutofillType(input->type)); |
+ if (InputWasEdited(input->type, input->initial_value)) |
SuggestionsMenuModelForSection(section)->SetCheckedItem(kAddNewItemKey); |
- break; |
- } |
} |
} |
} |
@@ -1648,7 +1692,16 @@ base::string16 AutofillDialogControllerImpl::InputValidityMessage( |
} |
} |
- switch (AutofillType(type).GetStorableType()) { |
+ AutofillType autofill_type(type); |
+ if (i18ninput::Enabled() && |
+ (autofill_type.group() == ADDRESS_HOME || |
+ autofill_type.group() == ADDRESS_BILLING)) { |
+ // TODO(dbeam): delete all US-specific address validation when |
+ // --enable-autofill-address-i18n is removed. |
+ return base::string16(); |
+ } |
+ |
+ switch (autofill_type.GetStorableType()) { |
case EMAIL_ADDRESS: |
if (!value.empty() && !IsValidEmailAddress(value)) { |
return l10n_util::GetStringUTF16( |
@@ -1699,8 +1752,9 @@ base::string16 AutofillDialogControllerImpl::InputValidityMessage( |
break; |
case ADDRESS_HOME_STATE: |
- if (!value.empty() && !autofill::IsValidState(value) && |
+ if (!value.empty() &&!autofill::IsValidState(value) && |
CountryCodeForSection(section) == "US") { |
+ DCHECK(!i18ninput::Enabled()); |
return l10n_util::GetStringUTF16( |
IDS_AUTOFILL_DIALOG_VALIDATION_INVALID_REGION); |
} |
@@ -1709,6 +1763,7 @@ base::string16 AutofillDialogControllerImpl::InputValidityMessage( |
case ADDRESS_HOME_ZIP: |
if (!value.empty() && !autofill::IsValidZip(value) && |
CountryCodeForSection(section) == "US") { |
+ DCHECK(!i18ninput::Enabled()); |
return l10n_util::GetStringUTF16( |
IDS_AUTOFILL_DIALOG_VALIDATION_INVALID_ZIP_CODE); |
} |
@@ -1745,10 +1800,41 @@ ValidityMessages AutofillDialogControllerImpl::InputsAreValid( |
DialogSection section, |
const FieldValueMap& inputs) { |
ValidityMessages messages; |
+ if (inputs.empty()) |
+ return messages; |
+ |
FieldValueMap field_values; |
+ |
+ if (i18ninput::Enabled() && section != SECTION_CC) { |
+ AddressData address_data; |
+ i18ninput::CreateAddressData( |
+ base::Bind(&GetInfoFromInputs, base::ConstRef(inputs), section), |
+ &address_data); |
+ |
+ AddressProblems problems; |
+ if (GetValidator()->ValidateAddress( |
+ address_data, |
+ AddressProblemFilter(), |
+ &problems) == AddressValidator::SUCCESS) { |
+ common::AddressType address_type = section == SECTION_SHIPPING ? |
+ common::ADDRESS_TYPE_SHIPPING : common::ADDRESS_TYPE_BILLING; |
+ for (size_t i = 0; i < problems.size(); ++i) { |
+ const AddressProblem& problem = problems[i]; |
+ bool sure = problem.type != AddressProblem::MISSING_REQUIRED_FIELD; |
+ base::string16 text = l10n_util::GetStringUTF16(problem.description_id); |
+ messages.Set(i18ninput::TypeForField(problem.field, address_type), |
+ ValidityMessage(text, sure)); |
+ } |
+ } else { |
+ // TODO(dbeam): disable submit button until able to successfully validate. |
+ } |
+ } |
+ |
for (FieldValueMap::const_iterator iter = inputs.begin(); |
iter != inputs.end(); ++iter) { |
const ServerFieldType type = iter->first; |
+ if (!messages.GetMessageOrDefault(type).text.empty()) |
+ continue; |
base::string16 text = InputValidityMessage(section, type, iter->second); |
@@ -1854,11 +1940,17 @@ void AutofillDialogControllerImpl::UserEditedOrActivatedInput( |
ScopedViewUpdates updates(view_.get()); |
if (type == ADDRESS_BILLING_COUNTRY || type == ADDRESS_HOME_COUNTRY) { |
+ DCHECK(i18ninput::Enabled()); |
+ |
const FieldValueMap snapshot = TakeUserInputSnapshot(); |
+ |
// Clobber the inputs because the view's already been updated. |
RebuildInputsForCountry(section, field_contents, true); |
RestoreUserInputFromSnapshot(snapshot); |
UpdateSection(section); |
+ |
+ GetValidator()->LoadRules(AutofillCountry::GetCountryCode( |
+ field_contents, g_browser_process->GetApplicationLocale())); |
} |
// The rest of this method applies only to textfields. If a combobox, bail. |
@@ -2575,7 +2667,6 @@ AutofillDialogControllerImpl::AutofillDialogControllerImpl( |
suggested_shipping_(this), |
cares_about_shipping_(true), |
popup_input_type_(UNKNOWN_TYPE), |
- weak_ptr_factory_(this), |
waiting_for_explicit_sign_in_response_(false), |
has_accepted_legal_documents_(false), |
is_submitting_(false), |
@@ -2583,7 +2674,8 @@ AutofillDialogControllerImpl::AutofillDialogControllerImpl( |
wallet_server_validation_recoverable_(true), |
data_was_passed_back_(false), |
was_ui_latency_logged_(false), |
- card_generated_animation_(2000, 60, this) { |
+ card_generated_animation_(2000, 60, this), |
+ weak_ptr_factory_(this) { |
// TODO(estade): remove duplicates from |form_structure|? |
DCHECK(!callback_.is_null()); |
} |
@@ -2596,6 +2688,10 @@ PersonalDataManager* AutofillDialogControllerImpl::GetManager() const { |
return PersonalDataManagerFactory::GetForProfile(profile_); |
} |
+AddressValidator* AutofillDialogControllerImpl::GetValidator() { |
+ return validator_.get(); |
+} |
+ |
const wallet::WalletClient* AutofillDialogControllerImpl::GetWalletClient() |
const { |
return const_cast<AutofillDialogControllerImpl*>(this)->GetWalletClient(); |
@@ -3073,15 +3169,19 @@ std::vector<ServerFieldType> AutofillDialogControllerImpl:: |
std::string AutofillDialogControllerImpl::CountryCodeForSection( |
DialogSection section) { |
+ base::string16 country; |
+ |
scoped_ptr<DataModelWrapper> wrapper = CreateWrapper(section); |
if (wrapper) { |
- return AutofillCountry::GetCountryCode( |
- wrapper->GetInfo(AutofillType(CountryTypeForSection(section))), |
- g_browser_process->GetApplicationLocale()); |
+ country = wrapper->GetInfo(AutofillType(CountryTypeForSection(section))); |
+ } else { |
+ FieldValueMap outputs; |
+ view_->GetUserInput(section, &outputs); |
+ country = outputs[CountryTypeForSection(section)]; |
} |
- CountryComboboxModel* model = CountryComboboxModelForSection(section); |
- return model ? model->GetDefaultCountryCode() : std::string(); |
+ return AutofillCountry::GetCountryCode( |
+ country, g_browser_process->GetApplicationLocale()); |
} |
bool AutofillDialogControllerImpl::RebuildInputsForCountry( |
@@ -3398,6 +3498,14 @@ void AutofillDialogControllerImpl::AnimationEnded( |
DoFinishSubmit(); |
} |
+void AutofillDialogControllerImpl::OnAddressValidationRulesLoaded( |
+ const std::string& country_code, |
+ bool success) { |
+ // TODO(dbeam): should we retry on failure? |
+ // TODO(dbeam): disable the submit button until rules are successfully loaded. |
+ // TODO(dbeam): ask |view_| to re-validate its contents if necessary. |
+} |
+ |
void AutofillDialogControllerImpl::DoFinishSubmit() { |
FillOutputForSection(SECTION_CC); |
FillOutputForSection(SECTION_BILLING); |