Home | History | Annotate | Download | only in autofill
      1 // Copyright 2013 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 "chrome/browser/ui/autofill/autofill_dialog_controller_impl.h"
      6 
      7 #include <algorithm>
      8 #include <map>
      9 #include <string>
     10 
     11 #include "base/base64.h"
     12 #include "base/bind.h"
     13 #include "base/bind_helpers.h"
     14 #include "base/i18n/case_conversion.h"
     15 #include "base/i18n/rtl.h"
     16 #include "base/logging.h"
     17 #include "base/prefs/pref_registry_simple.h"
     18 #include "base/prefs/pref_service.h"
     19 #include "base/prefs/scoped_user_pref_update.h"
     20 #include "base/rand_util.h"
     21 #include "base/strings/string_number_conversions.h"
     22 #include "base/strings/string_split.h"
     23 #include "base/strings/utf_string_conversions.h"
     24 #include "base/time/time.h"
     25 #include "chrome/browser/apps/app_window_registry_util.h"
     26 #include "chrome/browser/autofill/personal_data_manager_factory.h"
     27 #include "chrome/browser/autofill/validation_rules_storage_factory.h"
     28 #include "chrome/browser/browser_process.h"
     29 #include "chrome/browser/profiles/profile.h"
     30 #include "chrome/browser/ui/autofill/autofill_dialog_common.h"
     31 #include "chrome/browser/ui/autofill/autofill_dialog_i18n_input.h"
     32 #include "chrome/browser/ui/autofill/autofill_dialog_view.h"
     33 #include "chrome/browser/ui/autofill/data_model_wrapper.h"
     34 #include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
     35 #include "chrome/browser/ui/autofill/new_credit_card_bubble_controller.h"
     36 #include "chrome/browser/ui/browser.h"
     37 #include "chrome/browser/ui/browser_finder.h"
     38 #include "chrome/browser/ui/browser_navigator.h"
     39 #include "chrome/browser/ui/browser_window.h"
     40 #include "chrome/common/chrome_content_client.h"
     41 #include "chrome/common/chrome_version_info.h"
     42 #include "chrome/common/pref_names.h"
     43 #include "chrome/common/render_messages.h"
     44 #include "chrome/common/url_constants.h"
     45 #include "chrome/grit/chromium_strings.h"
     46 #include "chrome/grit/generated_resources.h"
     47 #include "components/autofill/content/browser/risk/fingerprint.h"
     48 #include "components/autofill/content/browser/risk/proto/fingerprint.pb.h"
     49 #include "components/autofill/content/browser/wallet/form_field_error.h"
     50 #include "components/autofill/content/browser/wallet/full_wallet.h"
     51 #include "components/autofill/content/browser/wallet/gaia_account.h"
     52 #include "components/autofill/content/browser/wallet/instrument.h"
     53 #include "components/autofill/content/browser/wallet/wallet_address.h"
     54 #include "components/autofill/content/browser/wallet/wallet_items.h"
     55 #include "components/autofill/content/browser/wallet/wallet_service_url.h"
     56 #include "components/autofill/content/browser/wallet/wallet_signin_helper.h"
     57 #include "components/autofill/core/browser/address_i18n.h"
     58 #include "components/autofill/core/browser/autofill_country.h"
     59 #include "components/autofill/core/browser/autofill_data_model.h"
     60 #include "components/autofill/core/browser/autofill_manager.h"
     61 #include "components/autofill/core/browser/autofill_type.h"
     62 #include "components/autofill/core/browser/personal_data_manager.h"
     63 #include "components/autofill/core/browser/phone_number_i18n.h"
     64 #include "components/autofill/core/browser/validation.h"
     65 #include "components/autofill/core/common/autofill_pref_names.h"
     66 #include "components/autofill/core/common/form_data.h"
     67 #include "components/metrics/metrics_service.h"
     68 #include "components/pref_registry/pref_registry_syncable.h"
     69 #include "content/public/browser/browser_thread.h"
     70 #include "content/public/browser/geolocation_provider.h"
     71 #include "content/public/browser/navigation_controller.h"
     72 #include "content/public/browser/navigation_details.h"
     73 #include "content/public/browser/navigation_entry.h"
     74 #include "content/public/browser/notification_service.h"
     75 #include "content/public/browser/notification_types.h"
     76 #include "content/public/browser/render_view_host.h"
     77 #include "content/public/browser/web_contents.h"
     78 #include "content/public/common/url_constants.h"
     79 #include "extensions/browser/app_window/app_window.h"
     80 #include "extensions/browser/app_window/native_app_window.h"
     81 #include "grit/components_scaled_resources.h"
     82 #include "grit/components_strings.h"
     83 #include "grit/platform_locale_settings.h"
     84 #include "grit/theme_resources.h"
     85 #include "net/cert/cert_status_flags.h"
     86 #include "third_party/libaddressinput/chromium/chrome_metadata_source.h"
     87 #include "third_party/libaddressinput/chromium/chrome_storage_impl.h"
     88 #include "third_party/libaddressinput/messages.h"
     89 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
     90 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_field.h"
     91 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_problem.h"
     92 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/localization.h"
     93 #include "ui/base/base_window.h"
     94 #include "ui/base/l10n/l10n_util.h"
     95 #include "ui/base/models/combobox_model.h"
     96 #include "ui/base/resource/resource_bundle.h"
     97 #include "ui/gfx/canvas.h"
     98 #include "ui/gfx/image/image_skia_operations.h"
     99 #include "ui/gfx/skia_util.h"
    100 
    101 using ::i18n::addressinput::AddressData;
    102 using ::i18n::addressinput::AddressField;
    103 using ::i18n::addressinput::AddressProblem;
    104 using ::i18n::addressinput::ADMIN_AREA;
    105 using ::i18n::addressinput::DEPENDENT_LOCALITY;
    106 using ::i18n::addressinput::FieldProblemMap;
    107 using ::i18n::addressinput::Localization;
    108 using ::i18n::addressinput::MISSING_REQUIRED_FIELD;
    109 
    110 namespace autofill {
    111 
    112 namespace {
    113 
    114 const char kAddNewItemKey[] = "add-new-item";
    115 const char kManageItemsKey[] = "manage-items";
    116 const char kSameAsBillingKey[] = "same-as-billing";
    117 
    118 // URLs for Wallet error messages.
    119 const char kBuyerLegalAddressStatusUrl[] =
    120     "https://wallet.google.com/manage/settings";
    121 const char kKnowYourCustomerStatusUrl[] = "https://wallet.google.com/kyc";
    122 
    123 // Keys for the kAutofillDialogAutofillDefault pref dictionary (do not change
    124 // these values).
    125 const char kGuidPrefKey[] = "guid";
    126 
    127 // This string is stored along with saved addresses and credit cards in the
    128 // WebDB, and hence should not be modified, so that it remains consistent over
    129 // time.
    130 const char kAutofillDialogOrigin[] = "Chrome Autofill dialog";
    131 
    132 // HSL shift to gray out an image.
    133 const color_utils::HSL kGrayImageShift = {-1, 0, 0.8};
    134 
    135 // Limit Wallet items refresh rate to at most once per minute.
    136 const int64 kWalletItemsRefreshRateSeconds = 60;
    137 
    138 // The number of milliseconds to delay enabling the submit button after showing
    139 // the dialog. This delay prevents users from accidentally clicking the submit
    140 // button on startup.
    141 const int kSubmitButtonDelayMs = 1000;
    142 
    143 // A helper class to make sure an AutofillDialogView knows when a series of
    144 // updates is incoming.
    145 class ScopedViewUpdates {
    146  public:
    147   explicit ScopedViewUpdates(AutofillDialogView* view) : view_(view) {
    148     if (view_)
    149       view_->UpdatesStarted();
    150   }
    151 
    152   ~ScopedViewUpdates() {
    153     if (view_)
    154       view_->UpdatesFinished();
    155   }
    156 
    157  private:
    158   AutofillDialogView* view_;
    159 
    160   DISALLOW_COPY_AND_ASSIGN(ScopedViewUpdates);
    161 };
    162 
    163 base::string16 NullGetInfo(const AutofillType& type) {
    164   return base::string16();
    165 }
    166 
    167 // Extract |type| from |inputs| using |section| to determine whether the info
    168 // should be billing or shipping specific (for sections with address info).
    169 base::string16 GetInfoFromInputs(const FieldValueMap& inputs,
    170                                  DialogSection section,
    171                                  const AutofillType& type) {
    172   ServerFieldType field_type = type.GetStorableType();
    173   if (section != SECTION_SHIPPING)
    174     field_type = AutofillType::GetEquivalentBillingFieldType(field_type);
    175 
    176   base::string16 info;
    177   FieldValueMap::const_iterator it = inputs.find(field_type);
    178   if (it != inputs.end())
    179     info = it->second;
    180 
    181   if (!info.empty() && type.html_type() == HTML_TYPE_COUNTRY_CODE) {
    182     info = base::ASCIIToUTF16(AutofillCountry::GetCountryCode(
    183         info, g_browser_process->GetApplicationLocale()));
    184   }
    185 
    186   return info;
    187 }
    188 
    189 // Returns true if |input| should be used to fill a site-requested |field| which
    190 // is notated with a "shipping" tag, for use when the user has decided to use
    191 // the billing address as the shipping address.
    192 bool ServerTypeMatchesShippingField(ServerFieldType type,
    193                                     const AutofillField& field) {
    194   // Equivalent billing field type is used to support UseBillingAsShipping
    195   // usecase.
    196   return common::ServerTypeEncompassesFieldType(
    197       type,
    198       AutofillType(AutofillType::GetEquivalentBillingFieldType(
    199           field.Type().GetStorableType())));
    200 }
    201 
    202 // Initializes |form_group| from user-entered data.
    203 void FillFormGroupFromOutputs(const FieldValueMap& detail_outputs,
    204                               FormGroup* form_group) {
    205   for (FieldValueMap::const_iterator iter = detail_outputs.begin();
    206        iter != detail_outputs.end(); ++iter) {
    207     ServerFieldType type = iter->first;
    208     if (!iter->second.empty()) {
    209       form_group->SetInfo(AutofillType(type),
    210                           iter->second,
    211                           g_browser_process->GetApplicationLocale());
    212     }
    213   }
    214 }
    215 
    216 // Get billing info from |output| and put it into |card|, |cvc|, and |profile|.
    217 // These outparams are required because |card|/|profile| accept different types
    218 // of raw info, and CreditCard doesn't save CVCs.
    219 void GetBillingInfoFromOutputs(const FieldValueMap& output,
    220                                CreditCard* card,
    221                                base::string16* cvc,
    222                                AutofillProfile* profile) {
    223   for (FieldValueMap::const_iterator it = output.begin();
    224        it != output.end(); ++it) {
    225     const ServerFieldType type = it->first;
    226     base::string16 trimmed;
    227     base::TrimWhitespace(it->second, base::TRIM_ALL, &trimmed);
    228 
    229     // Special case CVC as CreditCard just swallows it.
    230     if (type == CREDIT_CARD_VERIFICATION_CODE) {
    231       if (cvc)
    232         cvc->assign(trimmed);
    233     } else if (common::IsCreditCardType(type)) {
    234       card->SetRawInfo(type, trimmed);
    235     } else {
    236       // Copy the credit card name to |profile| in addition to |card| as
    237       // wallet::Instrument requires a recipient name for its billing address.
    238       if (card && type == NAME_FULL)
    239         card->SetRawInfo(CREDIT_CARD_NAME, trimmed);
    240 
    241       if (profile) {
    242         profile->SetInfo(AutofillType(AutofillType(type).GetStorableType()),
    243                          trimmed,
    244                          g_browser_process->GetApplicationLocale());
    245       }
    246     }
    247   }
    248 }
    249 
    250 // Returns the containing window for the given |web_contents|. The containing
    251 // window might be a browser window for a Chrome tab, or it might be an app
    252 // window for a platform app.
    253 ui::BaseWindow* GetBaseWindowForWebContents(
    254     content::WebContents* web_contents) {
    255   Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
    256   if (browser)
    257     return browser->window();
    258 
    259   gfx::NativeWindow native_window = web_contents->GetTopLevelNativeWindow();
    260   extensions::AppWindow* app_window =
    261       AppWindowRegistryUtil::GetAppWindowForNativeWindowAnyProfile(
    262           native_window);
    263   return app_window->GetBaseWindow();
    264 }
    265 
    266 // Returns a string descriptor for a DialogSection, for use with prefs (do not
    267 // change these values).
    268 std::string SectionToPrefString(DialogSection section) {
    269   switch (section) {
    270     case SECTION_CC:
    271       return "cc";
    272 
    273     case SECTION_BILLING:
    274       return "billing";
    275 
    276     case SECTION_CC_BILLING:
    277       // The SECTION_CC_BILLING section isn't active when using Autofill.
    278       NOTREACHED();
    279       return std::string();
    280 
    281     case SECTION_SHIPPING:
    282       return "shipping";
    283   }
    284 
    285   NOTREACHED();
    286   return std::string();
    287 }
    288 
    289 // Check if a given MaskedInstrument is allowed for the purchase.
    290 bool IsInstrumentAllowed(
    291     const wallet::WalletItems::MaskedInstrument& instrument) {
    292   switch (instrument.status()) {
    293     case wallet::WalletItems::MaskedInstrument::VALID:
    294     case wallet::WalletItems::MaskedInstrument::PENDING:
    295     case wallet::WalletItems::MaskedInstrument::EXPIRED:
    296     case wallet::WalletItems::MaskedInstrument::BILLING_INCOMPLETE:
    297       return true;
    298     default:
    299       return false;
    300   }
    301 }
    302 
    303 // Loops through |addresses_| comparing to |address| ignoring ID. If a match
    304 // is not found, NULL is returned.
    305 const wallet::Address* FindDuplicateAddress(
    306     const std::vector<wallet::Address*>& addresses,
    307     const wallet::Address& address) {
    308   for (size_t i = 0; i < addresses.size(); ++i) {
    309     if (addresses[i]->EqualsIgnoreID(address))
    310       return addresses[i];
    311   }
    312   return NULL;
    313 }
    314 
    315 bool IsCardHolderNameValidForWallet(const base::string16& name) {
    316   base::string16 whitespace_collapsed_name =
    317       base::CollapseWhitespace(name, true);
    318   std::vector<base::string16> split_name;
    319   base::SplitString(whitespace_collapsed_name, ' ', &split_name);
    320   return split_name.size() >= 2;
    321 }
    322 
    323 DialogSection SectionFromLocation(wallet::FormFieldError::Location location) {
    324   switch (location) {
    325     case wallet::FormFieldError::PAYMENT_INSTRUMENT:
    326     case wallet::FormFieldError::LEGAL_ADDRESS:
    327       return SECTION_CC_BILLING;
    328 
    329     case wallet::FormFieldError::SHIPPING_ADDRESS:
    330       return SECTION_SHIPPING;
    331 
    332     case wallet::FormFieldError::UNKNOWN_LOCATION:
    333       NOTREACHED();
    334       return SECTION_MAX;
    335   }
    336 
    337   NOTREACHED();
    338   return SECTION_MAX;
    339 }
    340 
    341 scoped_ptr<DialogNotification> GetWalletError(
    342     wallet::WalletClient::ErrorType error_type) {
    343   base::string16 text;
    344   GURL url;
    345 
    346   switch (error_type) {
    347     case wallet::WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS:
    348       text = l10n_util::GetStringUTF16(
    349           IDS_AUTOFILL_WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS);
    350       url = GURL(kKnowYourCustomerStatusUrl);
    351       break;
    352 
    353     case wallet::WalletClient::BUYER_LEGAL_ADDRESS_NOT_SUPPORTED:
    354       text = l10n_util::GetStringUTF16(
    355           IDS_AUTOFILL_WALLET_BUYER_COUNTRY_NOT_SUPPORTED);
    356       url = GURL(kBuyerLegalAddressStatusUrl);
    357       break;
    358 
    359     default:
    360       // The notification will not have a link; it's handled in the next
    361       // switch statement.
    362       break;
    363   }
    364 
    365   if (!text.empty()) {
    366     scoped_ptr<DialogNotification> notification(new DialogNotification(
    367         DialogNotification::WALLET_ERROR,
    368         text));
    369     notification->set_link_url(url);
    370     return notification.Pass();
    371   }
    372 
    373   int error_ids = 0;
    374   int error_code = 0;
    375 
    376   switch (error_type) {
    377     case wallet::WalletClient::UNSUPPORTED_MERCHANT:
    378       error_ids = IDS_AUTOFILL_WALLET_UNSUPPORTED_MERCHANT;
    379       break;
    380 
    381     case wallet::WalletClient::BAD_REQUEST:
    382       error_ids = IDS_AUTOFILL_WALLET_UPGRADE_CHROME_ERROR;
    383       error_code = 71;
    384       break;
    385 
    386     case wallet::WalletClient::INVALID_PARAMS:
    387       error_ids = IDS_AUTOFILL_WALLET_BAD_TRANSACTION_AMOUNT;
    388       error_code = 76;
    389       break;
    390 
    391     case wallet::WalletClient::BUYER_ACCOUNT_ERROR:
    392       error_ids = IDS_AUTOFILL_WALLET_BUYER_ACCOUNT_ERROR;
    393       error_code = 12;
    394       break;
    395 
    396     case wallet::WalletClient::UNSUPPORTED_API_VERSION:
    397       error_ids = IDS_AUTOFILL_WALLET_UPGRADE_CHROME_ERROR;
    398       error_code = 43;
    399       break;
    400 
    401     case wallet::WalletClient::SERVICE_UNAVAILABLE:
    402       error_ids = IDS_AUTOFILL_WALLET_SERVICE_UNAVAILABLE_ERROR;
    403       error_code = 61;
    404       break;
    405 
    406     case wallet::WalletClient::INTERNAL_ERROR:
    407       error_ids = IDS_AUTOFILL_WALLET_UPGRADE_CHROME_ERROR;
    408       error_code = 62;
    409       break;
    410 
    411     case wallet::WalletClient::MALFORMED_RESPONSE:
    412       error_ids = IDS_AUTOFILL_WALLET_UNKNOWN_ERROR;
    413       error_code = 72;
    414       break;
    415 
    416     case wallet::WalletClient::NETWORK_ERROR:
    417       error_ids = IDS_AUTOFILL_WALLET_UNKNOWN_ERROR;
    418       error_code = 73;
    419       break;
    420 
    421     case wallet::WalletClient::UNKNOWN_ERROR:
    422       error_ids = IDS_AUTOFILL_WALLET_UNKNOWN_ERROR;
    423       error_code = 74;
    424       break;
    425 
    426     case wallet::WalletClient::UNSUPPORTED_USER_AGENT_OR_API_KEY:
    427       error_ids = IDS_AUTOFILL_WALLET_UNSUPPORTED_AGENT_OR_API_KEY;
    428       error_code = 75;
    429       break;
    430 
    431     case wallet::WalletClient::SPENDING_LIMIT_EXCEEDED:
    432       error_ids = IDS_AUTOFILL_WALLET_BAD_TRANSACTION_AMOUNT;
    433       break;
    434 
    435     // Handled in the prior switch().
    436     case wallet::WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS:
    437     case wallet::WalletClient::BUYER_LEGAL_ADDRESS_NOT_SUPPORTED:
    438       NOTREACHED();
    439       break;
    440   }
    441 
    442   DCHECK_NE(0, error_ids);
    443 
    444   // The other error types are strings of the form "XXX. You can pay without
    445   // wallet."
    446   scoped_ptr<DialogNotification> notification(new DialogNotification(
    447       DialogNotification::WALLET_ERROR,
    448       l10n_util::GetStringFUTF16(IDS_AUTOFILL_DIALOG_COMPLETE_WITHOUT_WALLET,
    449                                  l10n_util::GetStringUTF16(error_ids))));
    450 
    451   if (error_code) {
    452     notification->set_tooltip_text(
    453         l10n_util::GetStringFUTF16(IDS_AUTOFILL_WALLET_ERROR_CODE_TOOLTIP,
    454                                    base::IntToString16(error_code)));
    455   }
    456 
    457   return notification.Pass();
    458 }
    459 
    460 // Returns the ID of the address or instrument that should be selected in the
    461 // UI, given that the |default_id| is currently the default ID on the Wallet
    462 // server, |previous_default_id| was the default ID prior to re-fetching the
    463 // Wallet data, and |previously_selected_id| was the ID of the item selected in
    464 // the dialog prior to re-fetching the Wallet data.
    465 std::string GetIdToSelect(const std::string& default_id,
    466                           const std::string& previous_default_id,
    467                           const std::string& previously_selected_id) {
    468   // If the default ID changed since the last fetch of the Wallet data, select
    469   // it rather than the previously selected item, as the user's intention in
    470   // changing the default was probably to use it.
    471   if (default_id != previous_default_id)
    472     return default_id;
    473 
    474   // Otherwise, prefer the previously selected item, if there was one.
    475   return !previously_selected_id.empty() ? previously_selected_id : default_id;
    476 }
    477 
    478 // Generate a random card number in a user displayable format.
    479 base::string16 GenerateRandomCardNumber() {
    480   std::string card_number;
    481   for (size_t i = 0; i < 4; ++i) {
    482     int part = base::RandInt(0, 10000);
    483     base::StringAppendF(&card_number, "%04d ", part);
    484   }
    485   return base::ASCIIToUTF16(card_number);
    486 }
    487 
    488 gfx::Image CreditCardIconForType(const std::string& credit_card_type) {
    489   const int input_card_idr = CreditCard::IconResourceId(credit_card_type);
    490   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
    491   gfx::Image result = rb.GetImageNamed(input_card_idr);
    492   if (input_card_idr == IDR_AUTOFILL_CC_GENERIC) {
    493     // When the credit card type is unknown, no image should be shown. However,
    494     // to simplify the view code on Mac, save space for the credit card image by
    495     // returning a transparent image of the appropriate size. Not all credit
    496     // card images are the same size, but none is larger than the Visa icon.
    497     result = gfx::Image(gfx::ImageSkiaOperations::CreateTransparentImage(
    498         rb.GetImageNamed(IDR_AUTOFILL_CC_VISA).AsImageSkia(), 0));
    499   }
    500   return result;
    501 }
    502 
    503 gfx::Image CvcIconForCreditCardType(const base::string16& credit_card_type) {
    504   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
    505   if (credit_card_type == l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_AMEX))
    506     return rb.GetImageNamed(IDR_CREDIT_CARD_CVC_HINT_AMEX);
    507 
    508   return rb.GetImageNamed(IDR_CREDIT_CARD_CVC_HINT);
    509 }
    510 
    511 ServerFieldType CountryTypeForSection(DialogSection section) {
    512   return section == SECTION_SHIPPING ? ADDRESS_HOME_COUNTRY :
    513                                        ADDRESS_BILLING_COUNTRY;
    514 }
    515 
    516 // Attempts to canonicalize the administrative area name in |profile| using the
    517 // rules in |validator|.
    518 void CanonicalizeState(const AddressValidator* validator,
    519                        AutofillProfile* profile) {
    520   base::string16 administrative_area;
    521   scoped_ptr<AddressData> address_data =
    522       i18n::CreateAddressDataFromAutofillProfile(
    523           *profile, g_browser_process->GetApplicationLocale());
    524 
    525   validator->CanonicalizeAdministrativeArea(address_data.get());
    526   administrative_area = base::UTF8ToUTF16(address_data->administrative_area);
    527 
    528   profile->SetInfo(AutofillType(ADDRESS_HOME_STATE),
    529                    administrative_area,
    530                    g_browser_process->GetApplicationLocale());
    531 }
    532 
    533 ValidityMessage GetPhoneValidityMessage(const base::string16& country_name,
    534                                         const base::string16& number) {
    535   std::string region = AutofillCountry::GetCountryCode(
    536       country_name,
    537       g_browser_process->GetApplicationLocale());
    538   i18n::PhoneObject phone_object(number, region);
    539   ValidityMessage phone_message(base::string16(), true);
    540 
    541   // Check if the phone number is invalid. Allow valid international
    542   // numbers that don't match the address's country only if they have an
    543   // international calling code.
    544   if (!phone_object.IsValidNumber() ||
    545       (phone_object.country_code().empty() &&
    546        phone_object.region() != region)) {
    547     phone_message.text = l10n_util::GetStringUTF16(
    548         IDS_AUTOFILL_DIALOG_VALIDATION_INVALID_PHONE_NUMBER);
    549   }
    550 
    551   return phone_message;
    552 }
    553 
    554 // Constructs |inputs| from template data for a given |dialog_section|.
    555 // |country_country| specifies the country code that the inputs should be built
    556 // for. Sets the |language_code| to be used for address formatting, if
    557 // internationalized address input is enabled. The |language_code| parameter can
    558 // be NULL.
    559 void BuildInputsForSection(DialogSection dialog_section,
    560                            const std::string& country_code,
    561                            DetailInputs* inputs,
    562                            std::string* language_code) {
    563   using l10n_util::GetStringUTF16;
    564 
    565   const DetailInput kCCInputs[] = {
    566     { DetailInput::LONG,
    567       CREDIT_CARD_NUMBER,
    568       GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_CARD_NUMBER) },
    569     { DetailInput::SHORT,
    570       CREDIT_CARD_EXP_MONTH,
    571       GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_MONTH) },
    572     { DetailInput::SHORT,
    573       CREDIT_CARD_EXP_4_DIGIT_YEAR,
    574       GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_YEAR) },
    575     { DetailInput::SHORT_EOL,
    576       CREDIT_CARD_VERIFICATION_CODE,
    577       GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC),
    578       1.5 },
    579   };
    580 
    581   const DetailInput kBillingPhoneInputs[] = {
    582     { DetailInput::LONG,
    583       PHONE_BILLING_WHOLE_NUMBER,
    584       GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_PHONE_NUMBER) },
    585   };
    586 
    587   const DetailInput kEmailInputs[] = {
    588     { DetailInput::LONG,
    589       EMAIL_ADDRESS,
    590       GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_EMAIL) },
    591   };
    592 
    593   const DetailInput kShippingPhoneInputs[] = {
    594     { DetailInput::LONG,
    595       PHONE_HOME_WHOLE_NUMBER,
    596       GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_PHONE_NUMBER) },
    597   };
    598 
    599   switch (dialog_section) {
    600     case SECTION_CC: {
    601       common::BuildInputs(kCCInputs, arraysize(kCCInputs), inputs);
    602       break;
    603     }
    604 
    605     case SECTION_BILLING: {
    606       i18ninput::BuildAddressInputs(common::ADDRESS_TYPE_BILLING,
    607                                     country_code, inputs, language_code);
    608       common::BuildInputs(kBillingPhoneInputs, arraysize(kBillingPhoneInputs),
    609                           inputs);
    610       common::BuildInputs(kEmailInputs, arraysize(kEmailInputs), inputs);
    611       break;
    612     }
    613 
    614     case SECTION_CC_BILLING: {
    615       common::BuildInputs(kCCInputs, arraysize(kCCInputs), inputs);
    616 
    617       // Wallet only supports US billing addresses.
    618       const std::string hardcoded_country_code = "US";
    619       i18ninput::BuildAddressInputs(common::ADDRESS_TYPE_BILLING,
    620                                     hardcoded_country_code,
    621                                     inputs,
    622                                     language_code);
    623       DCHECK_EQ(inputs->back().type, ADDRESS_BILLING_COUNTRY);
    624       inputs->back().length = DetailInput::NONE;
    625       const std::string& app_locale =
    626           g_browser_process->GetApplicationLocale();
    627       inputs->back().initial_value =
    628           AutofillCountry(hardcoded_country_code, app_locale).name();
    629 
    630       common::BuildInputs(kBillingPhoneInputs, arraysize(kBillingPhoneInputs),
    631                           inputs);
    632       break;
    633     }
    634 
    635     case SECTION_SHIPPING: {
    636       i18ninput::BuildAddressInputs(common::ADDRESS_TYPE_SHIPPING,
    637                                     country_code, inputs, language_code);
    638       common::BuildInputs(kShippingPhoneInputs, arraysize(kShippingPhoneInputs),
    639                           inputs);
    640       break;
    641     }
    642   }
    643 }
    644 
    645 }  // namespace
    646 
    647 AutofillDialogViewDelegate::~AutofillDialogViewDelegate() {}
    648 
    649 AutofillDialogControllerImpl::~AutofillDialogControllerImpl() {
    650   if (popup_controller_)
    651     popup_controller_->Hide();
    652 
    653   GetMetricLogger().LogDialogInitialUserState(initial_user_state_);
    654 }
    655 
    656 // Checks the country code against the values the form structure enumerates.
    657 bool AutofillCountryFilter(
    658     const std::set<base::string16>& form_structure_values,
    659     const std::string& country_code) {
    660   if (!form_structure_values.empty() &&
    661       !form_structure_values.count(base::ASCIIToUTF16(country_code))) {
    662     return false;
    663   }
    664 
    665   return true;
    666 }
    667 
    668 // Checks the country code against the values the form structure enumerates and
    669 // against the ones Wallet allows.
    670 bool WalletCountryFilter(
    671     const std::set<base::string16>& form_structure_values,
    672     const std::set<std::string>& wallet_allowed_values,
    673     const std::string& country_code) {
    674   if ((!form_structure_values.empty() &&
    675        !form_structure_values.count(base::ASCIIToUTF16(country_code))) ||
    676       (!wallet_allowed_values.empty() &&
    677        !wallet_allowed_values.count(country_code))) {
    678     return false;
    679   }
    680 
    681   return true;
    682 }
    683 
    684 // static
    685 base::WeakPtr<AutofillDialogControllerImpl>
    686 AutofillDialogControllerImpl::Create(
    687     content::WebContents* contents,
    688     const FormData& form_structure,
    689     const GURL& source_url,
    690     const AutofillClient::ResultCallback& callback) {
    691   // AutofillDialogControllerImpl owns itself.
    692   AutofillDialogControllerImpl* autofill_dialog_controller =
    693       new AutofillDialogControllerImpl(contents,
    694                                        form_structure,
    695                                        source_url,
    696                                        callback);
    697   return autofill_dialog_controller->weak_ptr_factory_.GetWeakPtr();
    698 }
    699 
    700 // static
    701 void AutofillDialogController::RegisterPrefs(PrefRegistrySimple* registry) {
    702   registry->RegisterListPref(::prefs::kAutofillDialogWalletLocationAcceptance);
    703 }
    704 
    705 // static
    706 void AutofillDialogController::RegisterProfilePrefs(
    707     user_prefs::PrefRegistrySyncable* registry) {
    708   registry->RegisterBooleanPref(
    709       ::prefs::kAutofillDialogPayWithoutWallet,
    710       false,
    711       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
    712   registry->RegisterDictionaryPref(
    713       ::prefs::kAutofillDialogAutofillDefault,
    714       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
    715   registry->RegisterBooleanPref(
    716       ::prefs::kAutofillDialogSaveData,
    717       true,
    718       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
    719   registry->RegisterBooleanPref(
    720       ::prefs::kAutofillDialogWalletShippingSameAsBilling,
    721       false,
    722       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
    723 }
    724 
    725 // static
    726 base::WeakPtr<AutofillDialogController> AutofillDialogController::Create(
    727     content::WebContents* contents,
    728     const FormData& form_structure,
    729     const GURL& source_url,
    730     const AutofillClient::ResultCallback& callback) {
    731   return AutofillDialogControllerImpl::Create(contents,
    732                                               form_structure,
    733                                               source_url,
    734                                               callback);
    735 }
    736 
    737 void AutofillDialogControllerImpl::Show() {
    738   dialog_shown_timestamp_ = base::Time::Now();
    739 
    740   // Determine what field types should be included in the dialog.
    741   bool has_types = false;
    742   bool has_sections = false;
    743   form_structure_.ParseFieldTypesFromAutocompleteAttributes(
    744       &has_types, &has_sections);
    745 
    746   // Fail if the author didn't specify autocomplete types.
    747   if (!has_types) {
    748     callback_.Run(
    749         AutofillClient::AutocompleteResultErrorDisabled,
    750         base::ASCIIToUTF16("Form is missing autocomplete attributes."),
    751         NULL);
    752     delete this;
    753     return;
    754   }
    755 
    756   // Fail if the author didn't ask for at least some kind of credit card
    757   // information.
    758   bool has_credit_card_field = false;
    759   for (size_t i = 0; i < form_structure_.field_count(); ++i) {
    760     AutofillType type = form_structure_.field(i)->Type();
    761     if (type.html_type() != HTML_TYPE_UNKNOWN && type.group() == CREDIT_CARD) {
    762       has_credit_card_field = true;
    763       break;
    764     }
    765   }
    766 
    767   if (!has_credit_card_field) {
    768     callback_.Run(AutofillClient::AutocompleteResultErrorDisabled,
    769                   base::ASCIIToUTF16(
    770                       "Form is not a payment form (must contain "
    771                       "some autocomplete=\"cc-*\" fields). "),
    772                   NULL);
    773     delete this;
    774     return;
    775   }
    776 
    777   billing_country_combobox_model_.reset(new CountryComboboxModel());
    778   billing_country_combobox_model_->SetCountries(
    779       *GetManager(),
    780       base::Bind(AutofillCountryFilter,
    781                  form_structure_.PossibleValues(ADDRESS_BILLING_COUNTRY)));
    782   shipping_country_combobox_model_.reset(new CountryComboboxModel());
    783   acceptable_shipping_countries_ =
    784       form_structure_.PossibleValues(ADDRESS_HOME_COUNTRY);
    785   shipping_country_combobox_model_->SetCountries(
    786       *GetManager(),
    787       base::Bind(AutofillCountryFilter,
    788                  base::ConstRef(acceptable_shipping_countries_)));
    789 
    790   // If the form has a country <select> but none of the options are valid, bail.
    791   if (billing_country_combobox_model_->GetItemCount() == 0 ||
    792       shipping_country_combobox_model_->GetItemCount() == 0) {
    793     callback_.Run(AutofillClient::AutocompleteResultErrorDisabled,
    794                   base::ASCIIToUTF16("No valid/supported country options"
    795                                      " found."),
    796                   NULL);
    797     delete this;
    798     return;
    799   }
    800 
    801   // Log any relevant UI metrics and security exceptions.
    802   GetMetricLogger().LogDialogUiEvent(AutofillMetrics::DIALOG_UI_SHOWN);
    803 
    804   GetMetricLogger().LogDialogSecurityMetric(
    805       AutofillMetrics::SECURITY_METRIC_DIALOG_SHOWN);
    806 
    807   // The Autofill dialog is shown in response to a message from the renderer and
    808   // as such, it can only be made in the context of the current document. A call
    809   // to GetActiveEntry would return a pending entry, if there was one, which
    810   // would be a security bug. Therefore, we use the last committed URL for the
    811   // access checks.
    812   const GURL& current_url = web_contents()->GetLastCommittedURL();
    813   invoked_from_same_origin_ =
    814       current_url.GetOrigin() == source_url_.GetOrigin();
    815 
    816   if (!invoked_from_same_origin_) {
    817     GetMetricLogger().LogDialogSecurityMetric(
    818         AutofillMetrics::SECURITY_METRIC_CROSS_ORIGIN_FRAME);
    819   }
    820 
    821   for (size_t i = SECTION_MIN; i <= SECTION_MAX; ++i) {
    822     DialogSection section = static_cast<DialogSection>(i);
    823 
    824     std::string country_code;
    825     CountryComboboxModel* model = CountryComboboxModelForSection(section);
    826     if (model)
    827       country_code = model->GetDefaultCountryCode();
    828 
    829     DetailInputs* inputs = MutableRequestedFieldsForSection(section);
    830     BuildInputsForSection(
    831         section, country_code, inputs,
    832         MutableAddressLanguageCodeForSection(section));
    833   }
    834 
    835   // Test whether we need to show the shipping section. If filling that section
    836   // would be a no-op, don't show it.
    837   cares_about_shipping_ = form_structure_.FillFields(
    838       RequestedTypesForSection(SECTION_SHIPPING),
    839       base::Bind(common::ServerTypeMatchesField, SECTION_SHIPPING),
    840       base::Bind(NullGetInfo),
    841       std::string(),
    842       g_browser_process->GetApplicationLocale());
    843 
    844   transaction_amount_ = form_structure_.GetUniqueValue(
    845       HTML_TYPE_TRANSACTION_AMOUNT);
    846   transaction_currency_ = form_structure_.GetUniqueValue(
    847       HTML_TYPE_TRANSACTION_CURRENCY);
    848 
    849   account_chooser_model_.reset(
    850       new AccountChooserModel(this,
    851                               profile_,
    852                               !ShouldShowAccountChooser(),
    853                               metric_logger_));
    854 
    855   acceptable_cc_types_ = form_structure_.PossibleValues(CREDIT_CARD_TYPE);
    856   // Wallet generates MC virtual cards, so we have to disable it if MC is not
    857   // allowed.
    858   if (ShouldDisallowCcType(CreditCard::TypeForDisplay(kMasterCard)))
    859     DisableWallet(wallet::WalletClient::UNSUPPORTED_MERCHANT);
    860 
    861   if (account_chooser_model_->WalletIsSelected())
    862     FetchWalletCookie();
    863 
    864   validator_.reset(new AddressValidator(
    865       scoped_ptr< ::i18n::addressinput::Source>(
    866           new autofill::ChromeMetadataSource(I18N_ADDRESS_VALIDATION_DATA_URL,
    867                                              profile_->GetRequestContext())),
    868       ValidationRulesStorageFactory::CreateStorage(),
    869       this));
    870 
    871   SuggestionsUpdated();
    872   SubmitButtonDelayBegin();
    873   view_.reset(CreateView());
    874   view_->Show();
    875   GetManager()->AddObserver(this);
    876 
    877   if (!account_chooser_model_->WalletIsSelected())
    878     LogDialogLatencyToShow();
    879 }
    880 
    881 void AutofillDialogControllerImpl::Hide() {
    882   if (view_)
    883     view_->Hide();
    884 }
    885 
    886 void AutofillDialogControllerImpl::TabActivated() {
    887   // If the user switched away from this tab and then switched back, reload the
    888   // Wallet items, in case they've changed.
    889   int64 seconds_elapsed_since_last_refresh =
    890       (base::TimeTicks::Now() - last_wallet_items_fetch_timestamp_).InSeconds();
    891   if (IsPayingWithWallet() && wallet_items_ &&
    892       seconds_elapsed_since_last_refresh >= kWalletItemsRefreshRateSeconds) {
    893     GetWalletItems();
    894   }
    895 }
    896 
    897 ////////////////////////////////////////////////////////////////////////////////
    898 // AutofillDialogViewDelegate implementation.
    899 
    900 base::string16 AutofillDialogControllerImpl::DialogTitle() const {
    901   if (ShouldShowSpinner())
    902     return base::string16();
    903 
    904   return l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_TITLE);
    905 }
    906 
    907 base::string16 AutofillDialogControllerImpl::AccountChooserText() const {
    908   if (!account_chooser_model_->WalletIsSelected())
    909     return l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_PAYING_WITHOUT_WALLET);
    910 
    911   if (SignedInState() == SIGNED_IN)
    912     return account_chooser_model_->GetActiveWalletAccountName();
    913 
    914   // In this case, the account chooser should be showing the signin link.
    915   return base::string16();
    916 }
    917 
    918 base::string16 AutofillDialogControllerImpl::SignInLinkText() const {
    919   int ids = SignedInState() == NOT_CHECKED ?
    920       IDS_AUTOFILL_DIALOG_USE_WALLET_LINK :
    921       ShouldShowSignInWebView() ? IDS_AUTOFILL_DIALOG_CANCEL_SIGN_IN :
    922                                   IDS_AUTOFILL_DIALOG_SIGN_IN;
    923 
    924   return l10n_util::GetStringUTF16(ids);
    925 }
    926 
    927 base::string16 AutofillDialogControllerImpl::SpinnerText() const {
    928   return l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_LOADING);
    929 }
    930 
    931 base::string16 AutofillDialogControllerImpl::EditSuggestionText() const {
    932   return l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_EDIT);
    933 }
    934 
    935 base::string16 AutofillDialogControllerImpl::CancelButtonText() const {
    936   return l10n_util::GetStringUTF16(IDS_CANCEL);
    937 }
    938 
    939 base::string16 AutofillDialogControllerImpl::ConfirmButtonText() const {
    940   return l10n_util::GetStringUTF16(IsSubmitPausedOn(wallet::VERIFY_CVV) ?
    941       IDS_AUTOFILL_DIALOG_VERIFY_BUTTON : IDS_AUTOFILL_DIALOG_SUBMIT_BUTTON);
    942 }
    943 
    944 base::string16 AutofillDialogControllerImpl::SaveLocallyText() const {
    945   return l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_SAVE_LOCALLY_CHECKBOX);
    946 }
    947 
    948 base::string16 AutofillDialogControllerImpl::SaveLocallyTooltip() const {
    949   return l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_SAVE_LOCALLY_TOOLTIP);
    950 }
    951 
    952 base::string16 AutofillDialogControllerImpl::LegalDocumentsText() {
    953   if (!IsPayingWithWallet() || ShouldShowSignInWebView())
    954     return base::string16();
    955 
    956   return legal_documents_text_;
    957 }
    958 
    959 bool AutofillDialogControllerImpl::ShouldShowSpinner() const {
    960   return SignedInState() == REQUIRES_RESPONSE ||
    961          SignedInState() == REQUIRES_PASSIVE_SIGN_IN;
    962 }
    963 
    964 bool AutofillDialogControllerImpl::ShouldShowAccountChooser() const {
    965   return !ShouldShowSpinner() && GetManager()->IsCountryOfInterest("US");
    966 }
    967 
    968 bool AutofillDialogControllerImpl::ShouldShowSignInWebView() const {
    969   return !signin_registrar_.IsEmpty();
    970 }
    971 
    972 GURL AutofillDialogControllerImpl::SignInUrl() const {
    973   return wallet::GetSignInUrl();
    974 }
    975 
    976 bool AutofillDialogControllerImpl::ShouldOfferToSaveInChrome() const {
    977   return IsAutofillEnabled() &&
    978       !IsPayingWithWallet() &&
    979       !profile_->IsOffTheRecord() &&
    980       IsManuallyEditingAnySection() &&
    981       !ShouldShowSpinner();
    982 }
    983 
    984 bool AutofillDialogControllerImpl::ShouldSaveInChrome() const {
    985   return profile_->GetPrefs()->GetBoolean(::prefs::kAutofillDialogSaveData);
    986 }
    987 
    988 int AutofillDialogControllerImpl::GetDialogButtons() const {
    989   if (waiting_for_explicit_sign_in_response_)
    990     return ui::DIALOG_BUTTON_NONE;
    991 
    992   if (ShouldShowSpinner() && !handling_use_wallet_link_click_)
    993     return ui::DIALOG_BUTTON_CANCEL;
    994 
    995   return ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL;
    996 }
    997 
    998 bool AutofillDialogControllerImpl::IsDialogButtonEnabled(
    999     ui::DialogButton button) const {
   1000   if (button == ui::DIALOG_BUTTON_OK) {
   1001     if (IsSubmitPausedOn(wallet::VERIFY_CVV))
   1002       return true;
   1003 
   1004     if (ShouldShowSpinner() || is_submitting_)
   1005       return false;
   1006 
   1007     if (submit_button_delay_timer_.IsRunning())
   1008       return false;
   1009 
   1010     return true;
   1011   }
   1012 
   1013   DCHECK_EQ(ui::DIALOG_BUTTON_CANCEL, button);
   1014   return !is_submitting_ || IsSubmitPausedOn(wallet::VERIFY_CVV);
   1015 }
   1016 
   1017 DialogOverlayState AutofillDialogControllerImpl::GetDialogOverlay() {
   1018   bool show_wallet_interstitial = IsPayingWithWallet() && is_submitting_ &&
   1019       !(full_wallet_ && !full_wallet_->required_actions().empty());
   1020   if (!show_wallet_interstitial) {
   1021     card_scrambling_delay_.Stop();
   1022     card_scrambling_refresher_.Stop();
   1023     return DialogOverlayState();
   1024   }
   1025 
   1026   ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
   1027   DialogOverlayState state;
   1028   state.string.font_list = rb->GetFontList(ui::ResourceBundle::MediumFont);
   1029 
   1030   const SkColor start_top_color = SkColorSetRGB(0xD6, 0xD6, 0xD6);
   1031   const SkColor start_bottom_color = SkColorSetRGB(0x98, 0x98, 0x98);
   1032   const SkColor final_top_color = SkColorSetRGB(0x52, 0x9F, 0xF8);
   1033   const SkColor final_bottom_color = SkColorSetRGB(0x22, 0x75, 0xE5);
   1034 
   1035   if (full_wallet_ && full_wallet_->required_actions().empty()) {
   1036     card_scrambling_delay_.Stop();
   1037     card_scrambling_refresher_.Stop();
   1038 
   1039     base::string16 cc_number = base::ASCIIToUTF16(full_wallet_->GetPan());
   1040     DCHECK_GE(cc_number.size(), 4U);
   1041     state.image = GetGeneratedCardImage(
   1042         base::ASCIIToUTF16("XXXX XXXX XXXX ") +
   1043             cc_number.substr(cc_number.size() - 4),
   1044         full_wallet_->billing_address()->recipient_name(),
   1045         color_utils::AlphaBlend(
   1046             final_top_color,
   1047             start_top_color,
   1048             255 * card_generated_animation_.GetCurrentValue()),
   1049         color_utils::AlphaBlend(
   1050             final_bottom_color,
   1051             start_bottom_color,
   1052             255 * card_generated_animation_.GetCurrentValue()));
   1053 
   1054     state.string.text = l10n_util::GetStringUTF16(
   1055         IDS_AUTOFILL_DIALOG_CARD_GENERATION_DONE);
   1056   } else {
   1057     // Start the refresher if it isn't running. Wait one second before pumping
   1058     // updates to the view.
   1059     if (!card_scrambling_delay_.IsRunning() &&
   1060         !card_scrambling_refresher_.IsRunning()) {
   1061       scrambled_card_number_ = GenerateRandomCardNumber();
   1062       card_scrambling_delay_.Start(
   1063           FROM_HERE,
   1064           base::TimeDelta::FromSeconds(1),
   1065           this,
   1066           &AutofillDialogControllerImpl::StartCardScramblingRefresher);
   1067     }
   1068 
   1069     DCHECK(!scrambled_card_number_.empty());
   1070     state.image = GetGeneratedCardImage(
   1071         scrambled_card_number_,
   1072         submitted_cardholder_name_,
   1073         start_top_color,
   1074         start_bottom_color);
   1075 
   1076     // "Submitting" waiting page.
   1077     state.string.text = l10n_util::GetStringUTF16(
   1078         IDS_AUTOFILL_DIALOG_CARD_GENERATION_IN_PROGRESS);
   1079   }
   1080 
   1081   return state;
   1082 }
   1083 
   1084 const std::vector<gfx::Range>& AutofillDialogControllerImpl::
   1085     LegalDocumentLinks() {
   1086   return legal_document_link_ranges_;
   1087 }
   1088 
   1089 bool AutofillDialogControllerImpl::SectionIsActive(DialogSection section)
   1090     const {
   1091   if (IsSubmitPausedOn(wallet::VERIFY_CVV))
   1092     return section == SECTION_CC_BILLING;
   1093 
   1094   if (!FormStructureCaresAboutSection(section))
   1095     return false;
   1096 
   1097   if (IsPayingWithWallet())
   1098     return section == SECTION_CC_BILLING || section == SECTION_SHIPPING;
   1099 
   1100   return section != SECTION_CC_BILLING;
   1101 }
   1102 
   1103 void AutofillDialogControllerImpl::GetWalletItems() {
   1104   ScopedViewUpdates updates(view_.get());
   1105 
   1106   wallet_items_requested_ = true;
   1107   wallet::WalletClient* wallet_client = GetWalletClient();
   1108   wallet_client->CancelRequest();
   1109 
   1110   previously_selected_instrument_id_.clear();
   1111   previously_selected_shipping_address_id_.clear();
   1112   if (wallet_items_) {
   1113     previous_default_instrument_id_ = wallet_items_->default_instrument_id();
   1114     previous_default_shipping_address_id_ = wallet_items_->default_address_id();
   1115 
   1116     const wallet::WalletItems::MaskedInstrument* instrument =
   1117         ActiveInstrument();
   1118     if (instrument)
   1119       previously_selected_instrument_id_ = instrument->object_id();
   1120 
   1121     const wallet::Address* address = ActiveShippingAddress();
   1122     if (address)
   1123       previously_selected_shipping_address_id_ = address->object_id();
   1124   }
   1125 
   1126   last_wallet_items_fetch_timestamp_ = base::TimeTicks::Now();
   1127   passive_failed_ = false;
   1128   wallet_items_.reset();
   1129 
   1130   // The "Loading..." page should be showing now, which should cause the
   1131   // account chooser to hide.
   1132   view_->UpdateAccountChooser();
   1133   wallet_client->GetWalletItems(transaction_amount_, transaction_currency_);
   1134 }
   1135 
   1136 void AutofillDialogControllerImpl::HideSignIn() {
   1137   ScopedViewUpdates updates(view_.get());
   1138   signin_registrar_.RemoveAll();
   1139   view_->HideSignIn();
   1140   view_->UpdateAccountChooser();
   1141 }
   1142 
   1143 AutofillDialogControllerImpl::DialogSignedInState
   1144     AutofillDialogControllerImpl::SignedInState() const {
   1145   if (wallet_error_notification_)
   1146     return SIGN_IN_DISABLED;
   1147 
   1148   if (signin_helper_ || (wallet_items_requested_ && !wallet_items_))
   1149     return REQUIRES_RESPONSE;
   1150 
   1151   if (!wallet_items_requested_)
   1152     return NOT_CHECKED;
   1153 
   1154   if (wallet_items_->HasRequiredAction(wallet::GAIA_AUTH) ||
   1155       passive_failed_) {
   1156     return REQUIRES_SIGN_IN;
   1157   }
   1158 
   1159   if (wallet_items_->HasRequiredAction(wallet::PASSIVE_GAIA_AUTH))
   1160     return REQUIRES_PASSIVE_SIGN_IN;
   1161 
   1162   return SIGNED_IN;
   1163 }
   1164 
   1165 void AutofillDialogControllerImpl::SignedInStateUpdated() {
   1166   if (!ShouldShowSpinner())
   1167     waiting_for_explicit_sign_in_response_ = false;
   1168 
   1169   switch (SignedInState()) {
   1170     case SIGNED_IN:
   1171       LogDialogLatencyToShow();
   1172       break;
   1173 
   1174     case REQUIRES_SIGN_IN:
   1175       if (handling_use_wallet_link_click_)
   1176         SignInLinkClicked();
   1177       // Fall through.
   1178     case SIGN_IN_DISABLED:
   1179       // Switch to the local account and refresh the dialog.
   1180       signin_helper_.reset();
   1181       OnWalletSigninError();
   1182       handling_use_wallet_link_click_ = false;
   1183       break;
   1184 
   1185     case REQUIRES_PASSIVE_SIGN_IN:
   1186       // Attempt to passively sign in the user.
   1187       DCHECK(!signin_helper_);
   1188       signin_helper_.reset(new wallet::WalletSigninHelper(
   1189           this,
   1190           profile_->GetRequestContext()));
   1191       signin_helper_->StartPassiveSignin(GetWalletClient()->user_index());
   1192       break;
   1193 
   1194     case NOT_CHECKED:
   1195     case REQUIRES_RESPONSE:
   1196       break;
   1197   }
   1198 }
   1199 
   1200 void AutofillDialogControllerImpl::OnWalletOrSigninUpdate() {
   1201   ScopedViewUpdates updates(view_.get());
   1202   SignedInStateUpdated();
   1203   SuggestionsUpdated();
   1204   UpdateAccountChooserView();
   1205 
   1206   if (view_) {
   1207     view_->UpdateButtonStrip();
   1208     view_->UpdateOverlay();
   1209   }
   1210 
   1211   // On the first successful response, compute the initial user state metric.
   1212   if (initial_user_state_ == AutofillMetrics::DIALOG_USER_STATE_UNKNOWN)
   1213     initial_user_state_ = GetInitialUserState();
   1214 }
   1215 
   1216 void AutofillDialogControllerImpl::OnWalletFormFieldError(
   1217     const std::vector<wallet::FormFieldError>& form_field_errors) {
   1218   if (form_field_errors.empty())
   1219     return;
   1220 
   1221   for (std::vector<wallet::FormFieldError>::const_iterator it =
   1222            form_field_errors.begin();
   1223        it != form_field_errors.end(); ++it) {
   1224     if (it->error_type() == wallet::FormFieldError::UNKNOWN_ERROR ||
   1225         it->GetAutofillType() == MAX_VALID_FIELD_TYPE ||
   1226         it->location() == wallet::FormFieldError::UNKNOWN_LOCATION) {
   1227       wallet_server_validation_recoverable_ = false;
   1228       break;
   1229     }
   1230     DialogSection section = SectionFromLocation(it->location());
   1231     wallet_errors_[section][it->GetAutofillType()] =
   1232         std::make_pair(it->GetErrorMessage(),
   1233                        GetValueFromSection(section, it->GetAutofillType()));
   1234   }
   1235 
   1236   // Unrecoverable validation errors.
   1237   if (!wallet_server_validation_recoverable_)
   1238     DisableWallet(wallet::WalletClient::UNKNOWN_ERROR);
   1239 
   1240   UpdateForErrors();
   1241 }
   1242 
   1243 void AutofillDialogControllerImpl::ConstructLegalDocumentsText() {
   1244   legal_documents_text_.clear();
   1245   legal_document_link_ranges_.clear();
   1246 
   1247   if (!wallet_items_)
   1248     return;
   1249 
   1250   PrefService* local_state = g_browser_process->local_state();
   1251   // List of users who have accepted location sharing for fraud protection
   1252   // on this device.
   1253   const base::ListValue* accepted =
   1254       local_state->GetList(::prefs::kAutofillDialogWalletLocationAcceptance);
   1255   bool has_accepted_location_sharing =
   1256       accepted->Find(base::StringValue(
   1257           account_chooser_model_->GetActiveWalletAccountName())) !=
   1258       accepted->end();
   1259 
   1260   if (wallet_items_->legal_documents().empty()) {
   1261     if (!has_accepted_location_sharing) {
   1262       legal_documents_text_ = l10n_util::GetStringUTF16(
   1263           IDS_AUTOFILL_DIALOG_LOCATION_DISCLOSURE);
   1264     }
   1265 
   1266     return;
   1267   }
   1268 
   1269   const std::vector<wallet::WalletItems::LegalDocument*>& documents =
   1270       wallet_items_->legal_documents();
   1271   // There should never be just one document because the privacy policy doc gets
   1272   // tacked on the end of other documents.
   1273   DCHECK_GE(documents.size(), 2U);
   1274 
   1275   std::vector<base::string16> link_names;
   1276   for (size_t i = 0; i < documents.size(); ++i) {
   1277     link_names.push_back(documents[i]->display_name());
   1278   }
   1279 
   1280   int resource_id = 0;
   1281   switch (documents.size()) {
   1282     case 2U:
   1283       resource_id = IDS_AUTOFILL_DIALOG_LEGAL_LINKS_2;
   1284       break;
   1285     case 3U:
   1286       resource_id = IDS_AUTOFILL_DIALOG_LEGAL_LINKS_3;
   1287       break;
   1288     case 4U:
   1289       resource_id = IDS_AUTOFILL_DIALOG_LEGAL_LINKS_4;
   1290       break;
   1291     case 5U:
   1292       resource_id = IDS_AUTOFILL_DIALOG_LEGAL_LINKS_5;
   1293       break;
   1294     case 6U:
   1295       resource_id = IDS_AUTOFILL_DIALOG_LEGAL_LINKS_6;
   1296       break;
   1297     default:
   1298       // We can only handle so many documents. For lack of a better way of
   1299       // handling document overflow, just error out if there are too many.
   1300       DisableWallet(wallet::WalletClient::UNKNOWN_ERROR);
   1301       return;
   1302   }
   1303 
   1304   std::vector<size_t> offsets;
   1305   base::string16 text =
   1306       l10n_util::GetStringFUTF16(resource_id, link_names,&offsets);
   1307 
   1308   // Tack on the location string if need be.
   1309   size_t base_offset = 0;
   1310   if (!has_accepted_location_sharing) {
   1311     text = l10n_util::GetStringFUTF16(
   1312         IDS_AUTOFILL_DIALOG_LOCATION_DISCLOSURE_WITH_LEGAL_DOCS,
   1313         text,
   1314         &base_offset);
   1315   }
   1316 
   1317   for (size_t i = 0; i < documents.size(); ++i) {
   1318     size_t link_start = offsets[i] + base_offset;
   1319     legal_document_link_ranges_.push_back(gfx::Range(
   1320         link_start, link_start + documents[i]->display_name().size()));
   1321   }
   1322   legal_documents_text_ = text;
   1323 }
   1324 
   1325 void AutofillDialogControllerImpl::ResetSectionInput(DialogSection section) {
   1326   SetEditingExistingData(section, false);
   1327   needs_validation_.erase(section);
   1328 
   1329   CountryComboboxModel* model = CountryComboboxModelForSection(section);
   1330   if (model) {
   1331     base::string16 country = model->GetItemAt(model->GetDefaultIndex());
   1332     RebuildInputsForCountry(section, country, false);
   1333   }
   1334 
   1335   DetailInputs* inputs = MutableRequestedFieldsForSection(section);
   1336   for (DetailInputs::iterator it = inputs->begin();
   1337        it != inputs->end(); ++it) {
   1338     if (it->length != DetailInput::NONE) {
   1339       it->initial_value.clear();
   1340     } else if (!it->initial_value.empty() &&
   1341                (it->type == ADDRESS_BILLING_COUNTRY ||
   1342                 it->type == ADDRESS_HOME_COUNTRY)) {
   1343       GetValidator()->LoadRules(AutofillCountry::GetCountryCode(
   1344           it->initial_value, g_browser_process->GetApplicationLocale()));
   1345     }
   1346   }
   1347 }
   1348 
   1349 void AutofillDialogControllerImpl::ShowEditUiIfBadSuggestion(
   1350     DialogSection section) {
   1351   // |CreateWrapper()| returns an empty wrapper if |IsEditingExistingData()|, so
   1352   // get the wrapper before this potentially happens below.
   1353   scoped_ptr<DataModelWrapper> wrapper = CreateWrapper(section);
   1354 
   1355   // If the chosen item in |model| yields an empty suggestion text, it is
   1356   // invalid. In this case, show the edit UI and highlight invalid fields.
   1357   SuggestionsMenuModel* model = SuggestionsMenuModelForSection(section);
   1358   base::string16 unused, unused2;
   1359   if (IsASuggestionItemKey(model->GetItemKeyForCheckedItem()) &&
   1360       !SuggestionTextForSection(section, &unused, &unused2)) {
   1361     SetEditingExistingData(section, true);
   1362   }
   1363 
   1364   if (wrapper && IsEditingExistingData(section)) {
   1365     base::string16 country =
   1366         wrapper->GetInfo(AutofillType(CountryTypeForSection(section)));
   1367     if (!country.empty()) {
   1368       // There's no user input to restore here as this is only called after
   1369       // resetting all section input.
   1370       if (RebuildInputsForCountry(section, country, false))
   1371         UpdateSection(section);
   1372     }
   1373     wrapper->FillInputs(MutableRequestedFieldsForSection(section));
   1374   }
   1375 }
   1376 
   1377 bool AutofillDialogControllerImpl::InputWasEdited(ServerFieldType type,
   1378                                                   const base::string16& value) {
   1379   if (value.empty())
   1380     return false;
   1381 
   1382   // If this is a combobox at the default value, don't preserve it.
   1383   ui::ComboboxModel* model = ComboboxModelForAutofillType(type);
   1384   if (model && model->GetItemAt(model->GetDefaultIndex()) == value)
   1385     return false;
   1386 
   1387   return true;
   1388 }
   1389 
   1390 FieldValueMap AutofillDialogControllerImpl::TakeUserInputSnapshot() {
   1391   FieldValueMap snapshot;
   1392   if (!view_)
   1393     return snapshot;
   1394 
   1395   for (size_t i = SECTION_MIN; i <= SECTION_MAX; ++i) {
   1396     DialogSection section = static_cast<DialogSection>(i);
   1397     SuggestionsMenuModel* model = SuggestionsMenuModelForSection(section);
   1398     if (model->GetItemKeyForCheckedItem() != kAddNewItemKey)
   1399       continue;
   1400 
   1401     FieldValueMap outputs;
   1402     view_->GetUserInput(section, &outputs);
   1403     // Remove fields that are empty, at their default values, or invalid.
   1404     for (FieldValueMap::iterator it = outputs.begin(); it != outputs.end();
   1405          ++it) {
   1406       if (InputWasEdited(it->first, it->second) &&
   1407           InputValidityMessage(section, it->first, it->second).empty()) {
   1408         snapshot.insert(std::make_pair(it->first, it->second));
   1409       }
   1410     }
   1411   }
   1412 
   1413   return snapshot;
   1414 }
   1415 
   1416 void AutofillDialogControllerImpl::RestoreUserInputFromSnapshot(
   1417     const FieldValueMap& snapshot) {
   1418   if (snapshot.empty())
   1419     return;
   1420 
   1421   for (size_t i = SECTION_MIN; i <= SECTION_MAX; ++i) {
   1422     DialogSection section = static_cast<DialogSection>(i);
   1423     if (!SectionIsActive(section))
   1424       continue;
   1425 
   1426     DetailInputs* inputs = MutableRequestedFieldsForSection(section);
   1427     for (size_t i = 0; i < inputs->size(); ++i) {
   1428       DetailInput* input = &(*inputs)[i];
   1429       if (input->length != DetailInput::NONE) {
   1430         input->initial_value =
   1431             GetInfoFromInputs(snapshot, section, AutofillType(input->type));
   1432       }
   1433       if (InputWasEdited(input->type, input->initial_value))
   1434         SuggestionsMenuModelForSection(section)->SetCheckedItem(kAddNewItemKey);
   1435     }
   1436   }
   1437 }
   1438 
   1439 void AutofillDialogControllerImpl::UpdateSection(DialogSection section) {
   1440   if (view_)
   1441     view_->UpdateSection(section);
   1442 }
   1443 
   1444 void AutofillDialogControllerImpl::UpdateForErrors() {
   1445   if (!view_)
   1446     return;
   1447 
   1448   // Currently, the view should only need to be updated if there are
   1449   // |wallet_errors_| or validating a suggestion that's based on existing data.
   1450   bool should_update = !wallet_errors_.empty();
   1451   if (!should_update) {
   1452     for (size_t i = SECTION_MIN; i <= SECTION_MAX; ++i) {
   1453       if (IsEditingExistingData(static_cast<DialogSection>(i))) {
   1454         should_update = true;
   1455         break;
   1456       }
   1457     }
   1458   }
   1459 
   1460   if (should_update)
   1461     view_->UpdateForErrors();
   1462 }
   1463 
   1464 gfx::Image AutofillDialogControllerImpl::GetGeneratedCardImage(
   1465     const base::string16& card_number,
   1466     const base::string16& name,
   1467     const SkColor& gradient_top,
   1468     const SkColor& gradient_bottom) {
   1469   const int kCardWidthPx = 300;
   1470   const int kCardHeightPx = 190;
   1471   const gfx::Size size(kCardWidthPx, kCardHeightPx);
   1472   float scale_factor = ui::GetScaleFactorForNativeView(
   1473       web_contents()->GetNativeView());
   1474   gfx::Canvas canvas(size, scale_factor, false);
   1475 
   1476   gfx::Rect display_rect(size);
   1477 
   1478   skia::RefPtr<SkShader> shader = gfx::CreateGradientShader(
   1479       0, size.height(), gradient_top, gradient_bottom);
   1480   SkPaint paint;
   1481   paint.setShader(shader.get());
   1482   canvas.DrawRoundRect(display_rect, 8, paint);
   1483 
   1484   display_rect.Inset(20, 0, 0, 0);
   1485   gfx::Font font(l10n_util::GetStringUTF8(IDS_FIXED_FONT_FAMILY), 18);
   1486   gfx::FontList font_list(font);
   1487   gfx::ShadowValues shadows;
   1488   shadows.push_back(gfx::ShadowValue(gfx::Point(0, 1), 1.0, SK_ColorBLACK));
   1489   canvas.DrawStringRectWithShadows(
   1490       card_number,
   1491       font_list,
   1492       SK_ColorWHITE,
   1493       display_rect, 0, 0, shadows);
   1494 
   1495   base::string16 capitalized_name = base::i18n::ToUpper(name);
   1496   display_rect.Inset(0, size.height() / 2, 0, 0);
   1497   canvas.DrawStringRectWithShadows(
   1498       capitalized_name,
   1499       font_list,
   1500       SK_ColorWHITE,
   1501       display_rect, 0, 0, shadows);
   1502 
   1503   gfx::ImageSkia skia(canvas.ExtractImageRep());
   1504   return gfx::Image(skia);
   1505 }
   1506 
   1507 void AutofillDialogControllerImpl::StartCardScramblingRefresher() {
   1508   RefreshCardScramblingOverlay();
   1509   card_scrambling_refresher_.Start(
   1510       FROM_HERE,
   1511       base::TimeDelta::FromMilliseconds(75),
   1512       this,
   1513       &AutofillDialogControllerImpl::RefreshCardScramblingOverlay);
   1514 }
   1515 
   1516 void AutofillDialogControllerImpl::RefreshCardScramblingOverlay() {
   1517   scrambled_card_number_ = GenerateRandomCardNumber();
   1518   PushOverlayUpdate();
   1519 }
   1520 
   1521 void AutofillDialogControllerImpl::PushOverlayUpdate() {
   1522   if (view_) {
   1523     ScopedViewUpdates updates(view_.get());
   1524     view_->UpdateOverlay();
   1525   }
   1526 }
   1527 
   1528 const DetailInputs& AutofillDialogControllerImpl::RequestedFieldsForSection(
   1529     DialogSection section) const {
   1530   switch (section) {
   1531     case SECTION_CC:
   1532       return requested_cc_fields_;
   1533     case SECTION_BILLING:
   1534       return requested_billing_fields_;
   1535     case SECTION_CC_BILLING:
   1536       return requested_cc_billing_fields_;
   1537     case SECTION_SHIPPING:
   1538       return requested_shipping_fields_;
   1539   }
   1540 
   1541   NOTREACHED();
   1542   return requested_billing_fields_;
   1543 }
   1544 
   1545 ui::ComboboxModel* AutofillDialogControllerImpl::ComboboxModelForAutofillType(
   1546     ServerFieldType type) {
   1547   switch (type) {
   1548     case CREDIT_CARD_EXP_MONTH:
   1549       return &cc_exp_month_combobox_model_;
   1550 
   1551     case CREDIT_CARD_EXP_4_DIGIT_YEAR:
   1552       return &cc_exp_year_combobox_model_;
   1553 
   1554     case ADDRESS_BILLING_COUNTRY:
   1555       return billing_country_combobox_model_.get();
   1556 
   1557     case ADDRESS_HOME_COUNTRY:
   1558       return shipping_country_combobox_model_.get();
   1559 
   1560     default:
   1561       return NULL;
   1562   }
   1563 }
   1564 
   1565 ui::MenuModel* AutofillDialogControllerImpl::MenuModelForSection(
   1566     DialogSection section) {
   1567   SuggestionsMenuModel* model = SuggestionsMenuModelForSection(section);
   1568   // The shipping section menu is special. It will always show because there is
   1569   // a choice between "Use billing" and "enter new".
   1570   if (section == SECTION_SHIPPING)
   1571     return model;
   1572 
   1573   // For other sections, only show a menu if there's at least one suggestion.
   1574   for (int i = 0; i < model->GetItemCount(); ++i) {
   1575     if (IsASuggestionItemKey(model->GetItemKeyAt(i)))
   1576       return model;
   1577   }
   1578 
   1579   return NULL;
   1580 }
   1581 
   1582 ui::MenuModel* AutofillDialogControllerImpl::MenuModelForAccountChooser() {
   1583   // If there were unrecoverable Wallet errors, or if there are choices other
   1584   // than "Pay without the wallet", show the full menu.
   1585   // TODO(estade): this can present a braindead menu (only 1 option) when
   1586   // there's a wallet error.
   1587   if (wallet_error_notification_ ||
   1588       (SignedInState() == SIGNED_IN &&
   1589        account_chooser_model_->HasAccountsToChoose() &&
   1590        !ShouldShowSignInWebView())) {
   1591     return account_chooser_model_.get();
   1592   }
   1593 
   1594   // Otherwise, there is no menu, just a sign in link.
   1595   return NULL;
   1596 }
   1597 
   1598 gfx::Image AutofillDialogControllerImpl::AccountChooserImage() {
   1599   if (!MenuModelForAccountChooser() && !ShouldShowSignInWebView()) {
   1600     return ui::ResourceBundle::GetSharedInstance().GetImageNamed(
   1601         IDR_WALLET_ICON);
   1602   }
   1603 
   1604   return gfx::Image();
   1605 }
   1606 
   1607 gfx::Image AutofillDialogControllerImpl::ButtonStripImage() const {
   1608   if (IsPayingWithWallet()) {
   1609     return ui::ResourceBundle::GetSharedInstance().GetImageNamed(
   1610         IDR_WALLET_LOGO);
   1611   }
   1612 
   1613   return gfx::Image();
   1614 }
   1615 
   1616 base::string16 AutofillDialogControllerImpl::LabelForSection(
   1617     DialogSection section) const {
   1618   switch (section) {
   1619     case SECTION_CC:
   1620       return l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_SECTION_CC);
   1621     case SECTION_BILLING:
   1622     case SECTION_CC_BILLING:
   1623       return l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_SECTION_BILLING);
   1624     case SECTION_SHIPPING:
   1625       return l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_SECTION_SHIPPING);
   1626   }
   1627   NOTREACHED();
   1628   return base::string16();
   1629 }
   1630 
   1631 SuggestionState AutofillDialogControllerImpl::SuggestionStateForSection(
   1632     DialogSection section) {
   1633   base::string16 vertically_compact, horizontally_compact;
   1634   bool show_suggestion = SuggestionTextForSection(section,
   1635                                                   &vertically_compact,
   1636                                                   &horizontally_compact);
   1637   return SuggestionState(show_suggestion,
   1638                          vertically_compact,
   1639                          horizontally_compact,
   1640                          SuggestionIconForSection(section),
   1641                          ExtraSuggestionTextForSection(section),
   1642                          ExtraSuggestionIconForSection(section));
   1643 }
   1644 
   1645 bool AutofillDialogControllerImpl::SuggestionTextForSection(
   1646     DialogSection section,
   1647     base::string16* vertically_compact,
   1648     base::string16* horizontally_compact) {
   1649   base::string16 action_text = RequiredActionTextForSection(section);
   1650   if (!action_text.empty()) {
   1651     *vertically_compact = *horizontally_compact = action_text;
   1652     return true;
   1653   }
   1654 
   1655   // When the user has clicked 'edit' or a suggestion is somehow invalid (e.g. a
   1656   // user selects a credit card that has expired), don't show a suggestion (even
   1657   // though there is a profile selected in the model).
   1658   if (IsEditingExistingData(section))
   1659     return false;
   1660 
   1661   SuggestionsMenuModel* model = SuggestionsMenuModelForSection(section);
   1662   std::string item_key = model->GetItemKeyForCheckedItem();
   1663   if (item_key == kSameAsBillingKey) {
   1664     *vertically_compact = *horizontally_compact = l10n_util::GetStringUTF16(
   1665         IDS_AUTOFILL_DIALOG_USING_BILLING_FOR_SHIPPING);
   1666     return true;
   1667   }
   1668 
   1669   if (!IsASuggestionItemKey(item_key))
   1670     return false;
   1671 
   1672   if (!IsPayingWithWallet() &&
   1673       (section == SECTION_BILLING || section == SECTION_SHIPPING)) {
   1674     // Also check if the address is invalid (rules may have loaded since
   1675     // the dialog was shown).
   1676     if (HasInvalidAddress(*GetManager()->GetProfileByGUID(item_key)))
   1677       return false;
   1678   }
   1679 
   1680   scoped_ptr<DataModelWrapper> wrapper = CreateWrapper(section);
   1681   return wrapper->GetDisplayText(vertically_compact, horizontally_compact);
   1682 }
   1683 
   1684 base::string16 AutofillDialogControllerImpl::RequiredActionTextForSection(
   1685     DialogSection section) const {
   1686   if (section == SECTION_CC_BILLING && IsSubmitPausedOn(wallet::VERIFY_CVV)) {
   1687     const wallet::WalletItems::MaskedInstrument* current_instrument =
   1688         wallet_items_->GetInstrumentById(active_instrument_id_);
   1689     if (current_instrument)
   1690       return current_instrument->TypeAndLastFourDigits();
   1691 
   1692     FieldValueMap output;
   1693     view_->GetUserInput(section, &output);
   1694     CreditCard card;
   1695     GetBillingInfoFromOutputs(output, &card, NULL, NULL);
   1696     return card.TypeAndLastFourDigits();
   1697   }
   1698 
   1699   return base::string16();
   1700 }
   1701 
   1702 base::string16 AutofillDialogControllerImpl::ExtraSuggestionTextForSection(
   1703     DialogSection section) const {
   1704   if (section == SECTION_CC ||
   1705       (section == SECTION_CC_BILLING && IsSubmitPausedOn(wallet::VERIFY_CVV))) {
   1706     return l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC);
   1707   }
   1708 
   1709   return base::string16();
   1710 }
   1711 
   1712 const wallet::WalletItems::MaskedInstrument* AutofillDialogControllerImpl::
   1713     ActiveInstrument() const {
   1714   if (!IsPayingWithWallet())
   1715     return NULL;
   1716 
   1717   const SuggestionsMenuModel* model =
   1718       SuggestionsMenuModelForSection(SECTION_CC_BILLING);
   1719   const std::string item_key = model->GetItemKeyForCheckedItem();
   1720   if (!IsASuggestionItemKey(item_key))
   1721     return NULL;
   1722 
   1723   int index;
   1724   if (!base::StringToInt(item_key, &index) || index < 0 ||
   1725       static_cast<size_t>(index) >= wallet_items_->instruments().size()) {
   1726     NOTREACHED();
   1727     return NULL;
   1728   }
   1729 
   1730   return wallet_items_->instruments()[index];
   1731 }
   1732 
   1733 const wallet::Address* AutofillDialogControllerImpl::
   1734     ActiveShippingAddress() const {
   1735   if (!IsPayingWithWallet() || !IsShippingAddressRequired())
   1736     return NULL;
   1737 
   1738   const SuggestionsMenuModel* model =
   1739       SuggestionsMenuModelForSection(SECTION_SHIPPING);
   1740   const std::string item_key = model->GetItemKeyForCheckedItem();
   1741   if (!IsASuggestionItemKey(item_key))
   1742     return NULL;
   1743 
   1744   int index;
   1745   if (!base::StringToInt(item_key, &index) || index < 0 ||
   1746       static_cast<size_t>(index) >= wallet_items_->addresses().size()) {
   1747     NOTREACHED();
   1748     return NULL;
   1749   }
   1750 
   1751   return wallet_items_->addresses()[index];
   1752 }
   1753 
   1754 scoped_ptr<DataModelWrapper> AutofillDialogControllerImpl::CreateWrapper(
   1755     DialogSection section) {
   1756   if (IsPayingWithWallet() && full_wallet_ &&
   1757       full_wallet_->required_actions().empty()) {
   1758     if (section == SECTION_CC_BILLING) {
   1759       return scoped_ptr<DataModelWrapper>(
   1760           new FullWalletBillingWrapper(full_wallet_.get()));
   1761     }
   1762     if (section == SECTION_SHIPPING) {
   1763       return scoped_ptr<DataModelWrapper>(
   1764           new FullWalletShippingWrapper(full_wallet_.get()));
   1765     }
   1766   }
   1767 
   1768   SuggestionsMenuModel* model = SuggestionsMenuModelForSection(section);
   1769   std::string item_key = model->GetItemKeyForCheckedItem();
   1770   if (!IsASuggestionItemKey(item_key) || IsManuallyEditingSection(section))
   1771     return scoped_ptr<DataModelWrapper>();
   1772 
   1773   if (IsPayingWithWallet()) {
   1774     if (section == SECTION_CC_BILLING) {
   1775       return scoped_ptr<DataModelWrapper>(
   1776           new WalletInstrumentWrapper(ActiveInstrument()));
   1777     }
   1778 
   1779     if (section == SECTION_SHIPPING) {
   1780       return scoped_ptr<DataModelWrapper>(
   1781           new WalletAddressWrapper(ActiveShippingAddress()));
   1782     }
   1783 
   1784     return scoped_ptr<DataModelWrapper>();
   1785   }
   1786 
   1787   if (section == SECTION_CC) {
   1788     CreditCard* card = GetManager()->GetCreditCardByGUID(item_key);
   1789     DCHECK(card);
   1790     return scoped_ptr<DataModelWrapper>(new AutofillCreditCardWrapper(card));
   1791   }
   1792 
   1793   AutofillProfile* profile = GetManager()->GetProfileByGUID(item_key);
   1794   DCHECK(profile);
   1795   if (section == SECTION_SHIPPING) {
   1796     return scoped_ptr<DataModelWrapper>(
   1797         new AutofillShippingAddressWrapper(profile));
   1798   }
   1799   DCHECK_EQ(SECTION_BILLING, section);
   1800   return scoped_ptr<DataModelWrapper>(
   1801       new AutofillProfileWrapper(profile));
   1802 }
   1803 
   1804 gfx::Image AutofillDialogControllerImpl::SuggestionIconForSection(
   1805     DialogSection section) {
   1806   scoped_ptr<DataModelWrapper> model = CreateWrapper(section);
   1807   if (!model.get())
   1808     return gfx::Image();
   1809 
   1810   return model->GetIcon();
   1811 }
   1812 
   1813 gfx::Image AutofillDialogControllerImpl::ExtraSuggestionIconForSection(
   1814     DialogSection section) {
   1815   if (section != SECTION_CC && section != SECTION_CC_BILLING)
   1816     return gfx::Image();
   1817 
   1818   scoped_ptr<DataModelWrapper> model = CreateWrapper(section);
   1819   if (!model.get())
   1820     return gfx::Image();
   1821 
   1822   return CvcIconForCreditCardType(
   1823       model->GetInfo(AutofillType(CREDIT_CARD_TYPE)));
   1824 }
   1825 
   1826 FieldIconMap AutofillDialogControllerImpl::IconsForFields(
   1827     const FieldValueMap& user_inputs) const {
   1828   FieldIconMap result;
   1829   base::string16 credit_card_type;
   1830 
   1831   FieldValueMap::const_iterator credit_card_iter =
   1832       user_inputs.find(CREDIT_CARD_NUMBER);
   1833   if (credit_card_iter != user_inputs.end()) {
   1834     const base::string16& number = credit_card_iter->second;
   1835     const std::string type = CreditCard::GetCreditCardType(number);
   1836     credit_card_type = CreditCard::TypeForDisplay(type);
   1837     result[CREDIT_CARD_NUMBER] = CreditCardIconForType(type);
   1838   }
   1839 
   1840   if (!user_inputs.count(CREDIT_CARD_VERIFICATION_CODE))
   1841     return result;
   1842 
   1843   result[CREDIT_CARD_VERIFICATION_CODE] =
   1844       CvcIconForCreditCardType(credit_card_type);
   1845 
   1846   return result;
   1847 }
   1848 
   1849 bool AutofillDialogControllerImpl::FieldControlsIcons(
   1850     ServerFieldType type) const {
   1851   return type == CREDIT_CARD_NUMBER;
   1852 }
   1853 
   1854 base::string16 AutofillDialogControllerImpl::TooltipForField(
   1855     ServerFieldType type) const {
   1856   if (type == PHONE_HOME_WHOLE_NUMBER || type == PHONE_BILLING_WHOLE_NUMBER)
   1857     return l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_TOOLTIP_PHONE_NUMBER);
   1858 
   1859   return base::string16();
   1860 }
   1861 
   1862 bool AutofillDialogControllerImpl::InputIsEditable(
   1863     const DetailInput& input,
   1864     DialogSection section) {
   1865   if (section != SECTION_CC_BILLING || !IsPayingWithWallet())
   1866     return true;
   1867 
   1868   if (input.type == CREDIT_CARD_NUMBER)
   1869     return !IsEditingExistingData(section);
   1870 
   1871   // For CVC, only require (allow) input if the user has edited some other
   1872   // aspect of the card.
   1873   if (input.type == CREDIT_CARD_VERIFICATION_CODE &&
   1874       IsEditingExistingData(section)) {
   1875     FieldValueMap output;
   1876     view_->GetUserInput(section, &output);
   1877     WalletInstrumentWrapper wrapper(ActiveInstrument());
   1878 
   1879     for (FieldValueMap::iterator iter = output.begin(); iter != output.end();
   1880          ++iter) {
   1881       if (iter->first == input.type)
   1882         continue;
   1883 
   1884       AutofillType type(iter->first);
   1885       if (type.group() == CREDIT_CARD &&
   1886           iter->second != wrapper.GetInfo(type)) {
   1887         return true;
   1888       }
   1889     }
   1890 
   1891     return false;
   1892   }
   1893 
   1894   return true;
   1895 }
   1896 
   1897 // TODO(groby): Add more tests.
   1898 base::string16 AutofillDialogControllerImpl::InputValidityMessage(
   1899     DialogSection section,
   1900     ServerFieldType type,
   1901     const base::string16& value) {
   1902   // If the field is edited, clear any Wallet errors.
   1903   if (IsPayingWithWallet()) {
   1904     WalletValidationErrors::iterator it = wallet_errors_.find(section);
   1905     if (it != wallet_errors_.end()) {
   1906       TypeErrorInputMap::const_iterator iter = it->second.find(type);
   1907       if (iter != it->second.end()) {
   1908         if (iter->second.second == value)
   1909           return iter->second.first;
   1910         it->second.erase(type);
   1911       }
   1912     }
   1913   }
   1914 
   1915   AutofillType autofill_type(type);
   1916   if (autofill_type.group() == ADDRESS_HOME ||
   1917       autofill_type.group() == ADDRESS_BILLING) {
   1918     return base::string16();
   1919   }
   1920 
   1921   switch (autofill_type.GetStorableType()) {
   1922     case EMAIL_ADDRESS:
   1923       if (!value.empty() && !IsValidEmailAddress(value)) {
   1924         return l10n_util::GetStringUTF16(
   1925             IDS_AUTOFILL_DIALOG_VALIDATION_INVALID_EMAIL_ADDRESS);
   1926       }
   1927       break;
   1928 
   1929     case CREDIT_CARD_NUMBER: {
   1930       if (!value.empty()) {
   1931         base::string16 message = CreditCardNumberValidityMessage(value);
   1932         if (!message.empty())
   1933           return message;
   1934       }
   1935       break;
   1936     }
   1937 
   1938     case CREDIT_CARD_EXP_MONTH:
   1939       if (!InputWasEdited(CREDIT_CARD_EXP_MONTH, value)) {
   1940         return l10n_util::GetStringUTF16(
   1941             IDS_LIBADDRESSINPUT_MISSING_REQUIRED_FIELD);
   1942       }
   1943       break;
   1944 
   1945     case CREDIT_CARD_EXP_4_DIGIT_YEAR:
   1946       if (!InputWasEdited(CREDIT_CARD_EXP_4_DIGIT_YEAR, value)) {
   1947         return l10n_util::GetStringUTF16(
   1948             IDS_LIBADDRESSINPUT_MISSING_REQUIRED_FIELD);
   1949       }
   1950       break;
   1951 
   1952     case CREDIT_CARD_VERIFICATION_CODE:
   1953       if (!value.empty() && !autofill::IsValidCreditCardSecurityCode(value)) {
   1954         return l10n_util::GetStringUTF16(
   1955             IDS_AUTOFILL_DIALOG_VALIDATION_INVALID_CREDIT_CARD_SECURITY_CODE);
   1956       }
   1957       break;
   1958 
   1959     case NAME_FULL:
   1960       // Wallet requires a first and last billing name.
   1961       if (IsPayingWithWallet() && !value.empty() &&
   1962           !IsCardHolderNameValidForWallet(value)) {
   1963         return l10n_util::GetStringUTF16(
   1964             IDS_AUTOFILL_DIALOG_VALIDATION_WALLET_REQUIRES_TWO_NAMES);
   1965       }
   1966       break;
   1967 
   1968     case PHONE_HOME_WHOLE_NUMBER:  // Used in shipping section.
   1969       break;
   1970 
   1971     case PHONE_BILLING_WHOLE_NUMBER:  // Used in billing section.
   1972       break;
   1973 
   1974     default:
   1975       NOTREACHED();  // Trying to validate unknown field.
   1976       break;
   1977   }
   1978 
   1979   return value.empty() ? l10n_util::GetStringUTF16(
   1980                              IDS_LIBADDRESSINPUT_MISSING_REQUIRED_FIELD) :
   1981                          base::string16();
   1982 }
   1983 
   1984 // TODO(groby): Also add tests.
   1985 ValidityMessages AutofillDialogControllerImpl::InputsAreValid(
   1986     DialogSection section,
   1987     const FieldValueMap& inputs) {
   1988   ValidityMessages messages;
   1989   if (inputs.empty())
   1990     return messages;
   1991 
   1992   AddressValidator::Status status = AddressValidator::SUCCESS;
   1993   if (section != SECTION_CC) {
   1994     AutofillProfile profile;
   1995     FillFormGroupFromOutputs(inputs, &profile);
   1996     scoped_ptr<AddressData> address_data =
   1997         i18n::CreateAddressDataFromAutofillProfile(
   1998             profile, g_browser_process->GetApplicationLocale());
   1999     address_data->language_code = AddressLanguageCodeForSection(section);
   2000 
   2001     Localization localization;
   2002     localization.SetGetter(l10n_util::GetStringUTF8);
   2003     FieldProblemMap problems;
   2004     status = GetValidator()->ValidateAddress(*address_data, NULL, &problems);
   2005     bool billing = section != SECTION_SHIPPING;
   2006 
   2007     for (FieldProblemMap::const_iterator iter = problems.begin();
   2008          iter != problems.end(); ++iter) {
   2009       bool sure = iter->second != MISSING_REQUIRED_FIELD;
   2010       base::string16 text = base::UTF8ToUTF16(localization.GetErrorMessage(
   2011           *address_data, iter->first, iter->second, true, false));
   2012       messages.Set(i18n::TypeForField(iter->first, billing),
   2013                    ValidityMessage(text, sure));
   2014     }
   2015   }
   2016 
   2017   for (FieldValueMap::const_iterator iter = inputs.begin();
   2018        iter != inputs.end(); ++iter) {
   2019     const ServerFieldType type = iter->first;
   2020     base::string16 text = InputValidityMessage(section, type, iter->second);
   2021 
   2022     // Skip empty/unchanged fields in edit mode. If the individual field does
   2023     // not have validation errors, assume it to be valid unless later proven
   2024     // otherwise.
   2025     bool sure = InputWasEdited(type, iter->second);
   2026 
   2027     if (sure && status == AddressValidator::RULES_NOT_READY &&
   2028         !ComboboxModelForAutofillType(type) &&
   2029         (AutofillType(type).group() == ADDRESS_HOME ||
   2030          AutofillType(type).group() == ADDRESS_BILLING)) {
   2031       DCHECK(text.empty());
   2032       text = l10n_util::GetStringUTF16(
   2033           IDS_AUTOFILL_DIALOG_VALIDATION_WAITING_FOR_RULES);
   2034       sure = false;
   2035       needs_validation_.insert(section);
   2036     }
   2037 
   2038     messages.Set(type, ValidityMessage(text, sure));
   2039   }
   2040 
   2041   // For the convenience of using operator[].
   2042   FieldValueMap& field_values = const_cast<FieldValueMap&>(inputs);
   2043   // Validate the date formed by month and year field. (Autofill dialog is
   2044   // never supposed to have 2-digit years, so not checked).
   2045   if (field_values.count(CREDIT_CARD_EXP_4_DIGIT_YEAR) &&
   2046       field_values.count(CREDIT_CARD_EXP_MONTH) &&
   2047       InputWasEdited(CREDIT_CARD_EXP_4_DIGIT_YEAR,
   2048                      field_values[CREDIT_CARD_EXP_4_DIGIT_YEAR]) &&
   2049       InputWasEdited(CREDIT_CARD_EXP_MONTH,
   2050                      field_values[CREDIT_CARD_EXP_MONTH])) {
   2051     ValidityMessage year_message(base::string16(), true);
   2052     ValidityMessage month_message(base::string16(), true);
   2053     if (!IsCreditCardExpirationValid(field_values[CREDIT_CARD_EXP_4_DIGIT_YEAR],
   2054                                      field_values[CREDIT_CARD_EXP_MONTH])) {
   2055       // The dialog shows the same error message for the month and year fields.
   2056       year_message.text = l10n_util::GetStringUTF16(
   2057           IDS_AUTOFILL_DIALOG_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_DATE);
   2058       month_message.text = l10n_util::GetStringUTF16(
   2059           IDS_AUTOFILL_DIALOG_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_DATE);
   2060     }
   2061     messages.Set(CREDIT_CARD_EXP_4_DIGIT_YEAR, year_message);
   2062     messages.Set(CREDIT_CARD_EXP_MONTH, month_message);
   2063   }
   2064 
   2065   // If there is a credit card number and a CVC, validate them together.
   2066   if (field_values.count(CREDIT_CARD_NUMBER) &&
   2067       field_values.count(CREDIT_CARD_VERIFICATION_CODE)) {
   2068     ValidityMessage ccv_message(base::string16(), true);
   2069     if (!autofill::IsValidCreditCardSecurityCode(
   2070             field_values[CREDIT_CARD_VERIFICATION_CODE],
   2071             field_values[CREDIT_CARD_NUMBER])) {
   2072       ccv_message.text = l10n_util::GetStringUTF16(
   2073           IDS_AUTOFILL_DIALOG_VALIDATION_INVALID_CREDIT_CARD_SECURITY_CODE);
   2074     }
   2075     messages.Set(CREDIT_CARD_VERIFICATION_CODE, ccv_message);
   2076   }
   2077 
   2078   // Validate the shipping phone number against the country code of the address.
   2079   if (field_values.count(ADDRESS_HOME_COUNTRY) &&
   2080       field_values.count(PHONE_HOME_WHOLE_NUMBER)) {
   2081     messages.Set(
   2082         PHONE_HOME_WHOLE_NUMBER,
   2083         GetPhoneValidityMessage(field_values[ADDRESS_HOME_COUNTRY],
   2084                                 field_values[PHONE_HOME_WHOLE_NUMBER]));
   2085   }
   2086 
   2087   // Validate the billing phone number against the country code of the address.
   2088   if (field_values.count(ADDRESS_BILLING_COUNTRY) &&
   2089       field_values.count(PHONE_BILLING_WHOLE_NUMBER)) {
   2090     messages.Set(
   2091         PHONE_BILLING_WHOLE_NUMBER,
   2092         GetPhoneValidityMessage(field_values[ADDRESS_BILLING_COUNTRY],
   2093                                 field_values[PHONE_BILLING_WHOLE_NUMBER]));
   2094   }
   2095 
   2096   return messages;
   2097 }
   2098 
   2099 void AutofillDialogControllerImpl::UserEditedOrActivatedInput(
   2100     DialogSection section,
   2101     ServerFieldType type,
   2102     gfx::NativeView parent_view,
   2103     const gfx::Rect& content_bounds,
   2104     const base::string16& field_contents,
   2105     bool was_edit) {
   2106   ScopedViewUpdates updates(view_.get());
   2107 
   2108   if (type == ADDRESS_BILLING_COUNTRY || type == ADDRESS_HOME_COUNTRY) {
   2109     const FieldValueMap& snapshot = TakeUserInputSnapshot();
   2110 
   2111     // Clobber the inputs because the view's already been updated.
   2112     RebuildInputsForCountry(section, field_contents, true);
   2113     RestoreUserInputFromSnapshot(snapshot);
   2114     UpdateSection(section);
   2115   }
   2116 
   2117   // The rest of this method applies only to textfields while Autofill is
   2118   // enabled. If a combobox or Autofill is disabled, bail.
   2119   if (ComboboxModelForAutofillType(type) || !IsAutofillEnabled())
   2120     return;
   2121 
   2122   // If the field is edited down to empty, don't show a popup.
   2123   if (was_edit && field_contents.empty()) {
   2124     HidePopup();
   2125     return;
   2126   }
   2127 
   2128   // If the user clicks while the popup is already showing, be sure to hide
   2129   // it.
   2130   if (!was_edit && popup_controller_.get()) {
   2131     HidePopup();
   2132     return;
   2133   }
   2134 
   2135   std::vector<base::string16> popup_values, popup_labels, popup_icons;
   2136   if (common::IsCreditCardType(type)) {
   2137     GetManager()->GetCreditCardSuggestions(AutofillType(type),
   2138                                            field_contents,
   2139                                            &popup_values,
   2140                                            &popup_labels,
   2141                                            &popup_icons,
   2142                                            &popup_guids_);
   2143   } else {
   2144     GetManager()->GetProfileSuggestions(
   2145         AutofillType(type),
   2146         field_contents,
   2147         false,
   2148         RequestedTypesForSection(section),
   2149         base::Bind(&AutofillDialogControllerImpl::ShouldSuggestProfile,
   2150                    base::Unretained(this), section),
   2151         &popup_values,
   2152         &popup_labels,
   2153         &popup_icons,
   2154         &popup_guids_);
   2155 
   2156     GetI18nValidatorSuggestions(section, type, &popup_values, &popup_labels,
   2157                                 &popup_icons);
   2158   }
   2159 
   2160   if (popup_values.empty()) {
   2161     HidePopup();
   2162     return;
   2163   }
   2164 
   2165   // |popup_input_type_| must be set before calling |Show()|.
   2166   popup_input_type_ = type;
   2167   popup_section_ = section;
   2168 
   2169   // TODO(estade): do we need separators and control rows like 'Clear
   2170   // Form'?
   2171   std::vector<int> popup_ids;
   2172   for (size_t i = 0; i < popup_values.size(); ++i) {
   2173     popup_ids.push_back(i);
   2174   }
   2175 
   2176   popup_controller_ = AutofillPopupControllerImpl::GetOrCreate(
   2177       popup_controller_,
   2178       weak_ptr_factory_.GetWeakPtr(),
   2179       NULL,
   2180       parent_view,
   2181       content_bounds,
   2182       base::i18n::IsRTL() ?
   2183           base::i18n::RIGHT_TO_LEFT : base::i18n::LEFT_TO_RIGHT);
   2184   popup_controller_->Show(popup_values,
   2185                           popup_labels,
   2186                           popup_icons,
   2187                           popup_ids);
   2188 }
   2189 
   2190 void AutofillDialogControllerImpl::FocusMoved() {
   2191   HidePopup();
   2192 }
   2193 
   2194 bool AutofillDialogControllerImpl::ShouldShowErrorBubble() const {
   2195   return popup_input_type_ == UNKNOWN_TYPE;
   2196 }
   2197 
   2198 void AutofillDialogControllerImpl::ViewClosed() {
   2199   GetManager()->RemoveObserver(this);
   2200 
   2201   // Called from here rather than in ~AutofillDialogControllerImpl as this
   2202   // relies on virtual methods that change to their base class in the dtor.
   2203   MaybeShowCreditCardBubble();
   2204 
   2205   delete this;
   2206 }
   2207 
   2208 std::vector<DialogNotification> AutofillDialogControllerImpl::
   2209     CurrentNotifications() {
   2210   std::vector<DialogNotification> notifications;
   2211 
   2212   // TODO(dbeam): figure out a way to dismiss this error after a while.
   2213   if (wallet_error_notification_)
   2214     notifications.push_back(*wallet_error_notification_);
   2215 
   2216   if (IsSubmitPausedOn(wallet::VERIFY_CVV)) {
   2217     notifications.push_back(DialogNotification(
   2218         DialogNotification::REQUIRED_ACTION,
   2219         l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_VERIFY_CVV)));
   2220   }
   2221 
   2222   if (!wallet_server_validation_recoverable_) {
   2223     notifications.push_back(DialogNotification(
   2224         DialogNotification::REQUIRED_ACTION,
   2225         l10n_util::GetStringUTF16(
   2226             IDS_AUTOFILL_DIALOG_FAILED_TO_SAVE_WALLET_DATA)));
   2227   }
   2228 
   2229   if (choose_another_instrument_or_address_) {
   2230     notifications.push_back(DialogNotification(
   2231         DialogNotification::REQUIRED_ACTION,
   2232         l10n_util::GetStringUTF16(
   2233             IDS_AUTOFILL_DIALOG_CHOOSE_DIFFERENT_WALLET_INSTRUMENT)));
   2234   }
   2235 
   2236   if (notifications.empty() && MenuModelForAccountChooser()) {
   2237     base::string16 text = l10n_util::GetStringUTF16(
   2238         IsManuallyEditingAnySection() ?
   2239             IDS_AUTOFILL_DIALOG_SAVE_DETAILS_IN_WALLET :
   2240             IDS_AUTOFILL_DIALOG_USE_WALLET);
   2241     DialogNotification notification(
   2242         DialogNotification::WALLET_USAGE_CONFIRMATION,
   2243         text);
   2244     notification.set_tooltip_text(
   2245         l10n_util::GetStringUTF16(
   2246             IDS_AUTOFILL_DIALOG_SAVE_IN_WALLET_TOOLTIP));
   2247     notification.set_checked(IsPayingWithWallet());
   2248     notifications.push_back(notification);
   2249   }
   2250 
   2251   if (IsPayingWithWallet() && !wallet::IsUsingProd()) {
   2252     notifications.push_back(DialogNotification(
   2253         DialogNotification::DEVELOPER_WARNING,
   2254         l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_NOT_PROD_WARNING)));
   2255   }
   2256 
   2257   if (!invoked_from_same_origin_) {
   2258     notifications.push_back(DialogNotification(
   2259         DialogNotification::SECURITY_WARNING,
   2260         l10n_util::GetStringFUTF16(IDS_AUTOFILL_DIALOG_SITE_WARNING,
   2261                                    base::UTF8ToUTF16(source_url_.host()))));
   2262   }
   2263 
   2264   return notifications;
   2265 }
   2266 
   2267 void AutofillDialogControllerImpl::LinkClicked(const GURL& url) {
   2268   OpenTabWithUrl(url);
   2269 }
   2270 
   2271 void AutofillDialogControllerImpl::SignInLinkClicked() {
   2272   ScopedViewUpdates updates(view_.get());
   2273 
   2274   if (SignedInState() == NOT_CHECKED) {
   2275     handling_use_wallet_link_click_ = true;
   2276     account_chooser_model_->SelectWalletAccount(0);
   2277     FetchWalletCookie();
   2278   } else if (signin_registrar_.IsEmpty()) {
   2279     // Start sign in.
   2280     waiting_for_explicit_sign_in_response_ = true;
   2281     content::Source<content::NavigationController> source(view_->ShowSignIn());
   2282     signin_registrar_.Add(
   2283         this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, source);
   2284 
   2285     GetMetricLogger().LogDialogUiEvent(
   2286         AutofillMetrics::DIALOG_UI_SIGNIN_SHOWN);
   2287   } else {
   2288     waiting_for_explicit_sign_in_response_ = false;
   2289     HideSignIn();
   2290   }
   2291 
   2292   view_->UpdateAccountChooser();
   2293   view_->UpdateButtonStrip();
   2294 }
   2295 
   2296 void AutofillDialogControllerImpl::NotificationCheckboxStateChanged(
   2297     DialogNotification::Type type, bool checked) {
   2298   if (type == DialogNotification::WALLET_USAGE_CONFIRMATION) {
   2299     if (checked) {
   2300       account_chooser_model_->SelectWalletAccount(
   2301           GetWalletClient()->user_index());
   2302     } else {
   2303       account_chooser_model_->SelectUseAutofill();
   2304     }
   2305 
   2306     AccountChoiceChanged();
   2307   }
   2308 }
   2309 
   2310 void AutofillDialogControllerImpl::LegalDocumentLinkClicked(
   2311     const gfx::Range& range) {
   2312   for (size_t i = 0; i < legal_document_link_ranges_.size(); ++i) {
   2313     if (legal_document_link_ranges_[i] == range) {
   2314       OpenTabWithUrl(wallet_items_->legal_documents()[i]->url());
   2315       return;
   2316     }
   2317   }
   2318 
   2319   NOTREACHED();
   2320 }
   2321 
   2322 bool AutofillDialogControllerImpl::OnCancel() {
   2323   HidePopup();
   2324   if (!is_submitting_)
   2325     LogOnCancelMetrics();
   2326   callback_.Run(
   2327       AutofillClient::AutocompleteResultErrorCancel, base::string16(), NULL);
   2328   return true;
   2329 }
   2330 
   2331 bool AutofillDialogControllerImpl::OnAccept() {
   2332   ScopedViewUpdates updates(view_.get());
   2333   choose_another_instrument_or_address_ = false;
   2334   wallet_server_validation_recoverable_ = true;
   2335   HidePopup();
   2336 
   2337   // This must come before SetIsSubmitting().
   2338   if (IsPayingWithWallet()) {
   2339     // In the VERIFY_CVV case, hold onto the previously submitted cardholder
   2340     // name.
   2341     if (!IsSubmitPausedOn(wallet::VERIFY_CVV)) {
   2342       submitted_cardholder_name_ =
   2343           GetValueFromSection(SECTION_CC_BILLING, NAME_BILLING_FULL);
   2344 
   2345       // Snag the last four digits of the backing card now as it could be wiped
   2346       // out if a CVC challenge happens.
   2347       if (ActiveInstrument()) {
   2348         backing_card_last_four_ = ActiveInstrument()->TypeAndLastFourDigits();
   2349       } else {
   2350         FieldValueMap output;
   2351         view_->GetUserInput(SECTION_CC_BILLING, &output);
   2352         CreditCard card;
   2353         GetBillingInfoFromOutputs(output, &card, NULL, NULL);
   2354         backing_card_last_four_ = card.TypeAndLastFourDigits();
   2355       }
   2356     }
   2357     DCHECK(!submitted_cardholder_name_.empty());
   2358     DCHECK(!backing_card_last_four_.empty());
   2359   }
   2360 
   2361   SetIsSubmitting(true);
   2362 
   2363   if (IsSubmitPausedOn(wallet::VERIFY_CVV)) {
   2364     DCHECK(!active_instrument_id_.empty());
   2365     full_wallet_.reset();
   2366     GetWalletClient()->AuthenticateInstrument(
   2367         active_instrument_id_,
   2368         base::UTF16ToUTF8(view_->GetCvc()));
   2369     view_->UpdateOverlay();
   2370   } else if (IsPayingWithWallet()) {
   2371     AcceptLegalTerms();
   2372   } else {
   2373     FinishSubmit();
   2374   }
   2375 
   2376   return false;
   2377 }
   2378 
   2379 Profile* AutofillDialogControllerImpl::profile() {
   2380   return profile_;
   2381 }
   2382 
   2383 content::WebContents* AutofillDialogControllerImpl::GetWebContents() {
   2384   return web_contents();
   2385 }
   2386 
   2387 ////////////////////////////////////////////////////////////////////////////////
   2388 // AutofillPopupDelegate implementation.
   2389 
   2390 void AutofillDialogControllerImpl::OnPopupShown() {
   2391   ScopedViewUpdates update(view_.get());
   2392   view_->UpdateErrorBubble();
   2393 
   2394   GetMetricLogger().LogDialogPopupEvent(AutofillMetrics::DIALOG_POPUP_SHOWN);
   2395 }
   2396 
   2397 void AutofillDialogControllerImpl::OnPopupHidden() {}
   2398 
   2399 void AutofillDialogControllerImpl::DidSelectSuggestion(
   2400     const base::string16& value,
   2401     int identifier) {
   2402   // TODO(estade): implement.
   2403 }
   2404 
   2405 void AutofillDialogControllerImpl::DidAcceptSuggestion(
   2406     const base::string16& value,
   2407     int identifier) {
   2408   DCHECK_NE(UNKNOWN_TYPE, popup_input_type_);
   2409   // Because |HidePopup()| can be called from |UpdateSection()|, remember the
   2410   // type of the input for later here.
   2411   const ServerFieldType popup_input_type = popup_input_type_;
   2412 
   2413   ScopedViewUpdates updates(view_.get());
   2414   scoped_ptr<DataModelWrapper> wrapper;
   2415 
   2416   if (static_cast<size_t>(identifier) < popup_guids_.size()) {
   2417     const PersonalDataManager::GUIDPair& pair = popup_guids_[identifier];
   2418     if (common::IsCreditCardType(popup_input_type)) {
   2419       wrapper.reset(new AutofillCreditCardWrapper(
   2420           GetManager()->GetCreditCardByGUID(pair.first)));
   2421     } else {
   2422       wrapper.reset(new AutofillProfileWrapper(
   2423           GetManager()->GetProfileByGUID(pair.first),
   2424           AutofillType(popup_input_type),
   2425           pair.second));
   2426     }
   2427   } else {
   2428     wrapper.reset(new I18nAddressDataWrapper(
   2429         &i18n_validator_suggestions_[identifier - popup_guids_.size()]));
   2430   }
   2431 
   2432   // If the user hasn't switched away from the default country and |wrapper|'s
   2433   // country differs from the |view_|'s, rebuild inputs and restore user data.
   2434   const FieldValueMap snapshot = TakeUserInputSnapshot();
   2435   bool billing_rebuilt = false, shipping_rebuilt = false;
   2436 
   2437   base::string16 billing_country =
   2438       wrapper->GetInfo(AutofillType(ADDRESS_BILLING_COUNTRY));
   2439   if (popup_section_ == ActiveBillingSection() &&
   2440       !snapshot.count(ADDRESS_BILLING_COUNTRY) &&
   2441       !billing_country.empty()) {
   2442     billing_rebuilt = RebuildInputsForCountry(
   2443         ActiveBillingSection(), billing_country, false);
   2444   }
   2445 
   2446   base::string16 shipping_country =
   2447       wrapper->GetInfo(AutofillType(ADDRESS_HOME_COUNTRY));
   2448   if (popup_section_ == SECTION_SHIPPING &&
   2449       !snapshot.count(ADDRESS_HOME_COUNTRY) &&
   2450       !shipping_country.empty()) {
   2451     shipping_rebuilt = RebuildInputsForCountry(
   2452         SECTION_SHIPPING, shipping_country, false);
   2453   }
   2454 
   2455   if (billing_rebuilt || shipping_rebuilt) {
   2456     RestoreUserInputFromSnapshot(snapshot);
   2457     if (billing_rebuilt)
   2458       UpdateSection(ActiveBillingSection());
   2459     if (shipping_rebuilt)
   2460       UpdateSection(SECTION_SHIPPING);
   2461   }
   2462 
   2463   DCHECK(SectionIsActive(popup_section_));
   2464   wrapper->FillInputs(MutableRequestedFieldsForSection(popup_section_));
   2465   view_->FillSection(popup_section_, popup_input_type);
   2466 
   2467   GetMetricLogger().LogDialogPopupEvent(
   2468       AutofillMetrics::DIALOG_POPUP_FORM_FILLED);
   2469 
   2470   // TODO(estade): not sure why it's necessary to do this explicitly.
   2471   HidePopup();
   2472 }
   2473 
   2474 void AutofillDialogControllerImpl::RemoveSuggestion(
   2475     const base::string16& value,
   2476     int identifier) {
   2477   // TODO(estade): implement.
   2478 }
   2479 
   2480 void AutofillDialogControllerImpl::ClearPreviewedForm() {
   2481   // TODO(estade): implement.
   2482 }
   2483 
   2484 ////////////////////////////////////////////////////////////////////////////////
   2485 // content::NotificationObserver implementation.
   2486 
   2487 void AutofillDialogControllerImpl::Observe(
   2488     int type,
   2489     const content::NotificationSource& source,
   2490     const content::NotificationDetails& details) {
   2491   DCHECK_EQ(type, content::NOTIFICATION_NAV_ENTRY_COMMITTED);
   2492   content::LoadCommittedDetails* load_details =
   2493       content::Details<content::LoadCommittedDetails>(details).ptr();
   2494   size_t user_index = 0;
   2495   if (IsSignInContinueUrl(load_details->entry->GetVirtualURL(), &user_index)) {
   2496     GetWalletClient()->SetUserIndex(user_index);
   2497     FetchWalletCookie();
   2498 
   2499     // NOTE: |HideSignIn()| may delete the WebContents which doesn't expect to
   2500     // be deleted while committing a nav entry. Just call |HideSignIn()| later.
   2501     base::MessageLoop::current()->PostTask(FROM_HERE,
   2502         base::Bind(&AutofillDialogControllerImpl::HideSignIn,
   2503                    base::Unretained(this)));
   2504   }
   2505 }
   2506 
   2507 ////////////////////////////////////////////////////////////////////////////////
   2508 // SuggestionsMenuModelDelegate implementation.
   2509 
   2510 void AutofillDialogControllerImpl::SuggestionItemSelected(
   2511     SuggestionsMenuModel* model,
   2512     size_t index) {
   2513   ScopedViewUpdates updates(view_.get());
   2514 
   2515   if (model->GetItemKeyAt(index) == kManageItemsKey) {
   2516     GURL url;
   2517     if (!IsPayingWithWallet()) {
   2518       DCHECK(IsAutofillEnabled());
   2519       GURL settings_url(chrome::kChromeUISettingsURL);
   2520       url = settings_url.Resolve(chrome::kAutofillSubPage);
   2521     } else {
   2522       // Reset |last_wallet_items_fetch_timestamp_| to ensure that the Wallet
   2523       // data is refreshed as soon as the user switches back to this tab after
   2524       // potentially editing his data.
   2525       last_wallet_items_fetch_timestamp_ = base::TimeTicks();
   2526       size_t user_index = GetWalletClient()->user_index();
   2527       url = SectionForSuggestionsMenuModel(*model) == SECTION_SHIPPING ?
   2528           wallet::GetManageAddressesUrl(user_index) :
   2529           wallet::GetManageInstrumentsUrl(user_index);
   2530     }
   2531 
   2532     OpenTabWithUrl(url);
   2533     return;
   2534   }
   2535 
   2536   model->SetCheckedIndex(index);
   2537   DialogSection section = SectionForSuggestionsMenuModel(*model);
   2538 
   2539   ResetSectionInput(section);
   2540   ShowEditUiIfBadSuggestion(section);
   2541   UpdateSection(section);
   2542   view_->UpdateNotificationArea();
   2543   UpdateForErrors();
   2544 
   2545   LogSuggestionItemSelectedMetric(*model);
   2546 }
   2547 
   2548 ////////////////////////////////////////////////////////////////////////////////
   2549 // wallet::WalletClientDelegate implementation.
   2550 
   2551 const AutofillMetrics& AutofillDialogControllerImpl::GetMetricLogger() const {
   2552   return metric_logger_;
   2553 }
   2554 
   2555 std::string AutofillDialogControllerImpl::GetRiskData() const {
   2556   DCHECK(!risk_data_.empty());
   2557   return risk_data_;
   2558 }
   2559 
   2560 std::string AutofillDialogControllerImpl::GetWalletCookieValue() const {
   2561   return wallet_cookie_value_;
   2562 }
   2563 
   2564 bool AutofillDialogControllerImpl::IsShippingAddressRequired() const {
   2565   return cares_about_shipping_;
   2566 }
   2567 
   2568 void AutofillDialogControllerImpl::OnDidAcceptLegalDocuments() {
   2569   DCHECK(is_submitting_ && IsPayingWithWallet());
   2570   has_accepted_legal_documents_ = true;
   2571   LoadRiskFingerprintData();
   2572 }
   2573 
   2574 void AutofillDialogControllerImpl::OnDidAuthenticateInstrument(bool success) {
   2575   DCHECK(is_submitting_ && IsPayingWithWallet());
   2576 
   2577   // TODO(dbeam): use the returned full wallet. http://crbug.com/224992
   2578   if (success) {
   2579     GetFullWallet();
   2580   } else {
   2581     DisableWallet(wallet::WalletClient::UNKNOWN_ERROR);
   2582     SuggestionsUpdated();
   2583   }
   2584 }
   2585 
   2586 void AutofillDialogControllerImpl::OnDidGetFullWallet(
   2587     scoped_ptr<wallet::FullWallet> full_wallet) {
   2588   DCHECK(is_submitting_ && IsPayingWithWallet());
   2589   ScopedViewUpdates updates(view_.get());
   2590 
   2591   full_wallet_ = full_wallet.Pass();
   2592 
   2593   if (full_wallet_->required_actions().empty()) {
   2594     FinishSubmit();
   2595     return;
   2596   }
   2597 
   2598   switch (full_wallet_->required_actions()[0]) {
   2599     case wallet::CHOOSE_ANOTHER_INSTRUMENT_OR_ADDRESS:
   2600       choose_another_instrument_or_address_ = true;
   2601       SetIsSubmitting(false);
   2602       GetWalletItems();
   2603       break;
   2604 
   2605     case wallet::VERIFY_CVV:
   2606       SuggestionsUpdated();
   2607       break;
   2608 
   2609     default:
   2610       DisableWallet(wallet::WalletClient::UNKNOWN_ERROR);
   2611       return;
   2612   }
   2613 
   2614   view_->UpdateNotificationArea();
   2615   view_->UpdateButtonStrip();
   2616   view_->UpdateOverlay();
   2617 }
   2618 
   2619 void AutofillDialogControllerImpl::OnPassiveSigninSuccess() {
   2620   FetchWalletCookie();
   2621 }
   2622 
   2623 void AutofillDialogControllerImpl::OnPassiveSigninFailure(
   2624     const GoogleServiceAuthError& error) {
   2625   signin_helper_.reset();
   2626   passive_failed_ = true;
   2627 
   2628   if (handling_use_wallet_link_click_ ||
   2629       GetWalletClient()->user_index() != 0) {
   2630     // TODO(estade): When a secondary account is selected and fails passive
   2631     // auth, we show a sign in page. Currently we show the generic add account
   2632     // page, but we should instead show sign in for the selected account.
   2633     // http://crbug.com/323327
   2634     SignInLinkClicked();
   2635     handling_use_wallet_link_click_ = false;
   2636   }
   2637 
   2638   OnWalletSigninError();
   2639 }
   2640 
   2641 void AutofillDialogControllerImpl::OnDidFetchWalletCookieValue(
   2642     const std::string& cookie_value) {
   2643   wallet_cookie_value_ = cookie_value;
   2644   signin_helper_.reset();
   2645   GetWalletItems();
   2646 }
   2647 
   2648 void AutofillDialogControllerImpl::OnDidGetWalletItems(
   2649     scoped_ptr<wallet::WalletItems> wallet_items) {
   2650   legal_documents_text_.clear();
   2651   legal_document_link_ranges_.clear();
   2652   has_accepted_legal_documents_ = false;
   2653 
   2654   wallet_items_ = wallet_items.Pass();
   2655 
   2656   if (wallet_items_ && !wallet_items_->ObfuscatedGaiaId().empty()) {
   2657     // Making sure the user index is in sync shouldn't be necessary, but is an
   2658     // extra precaution. But if there is no active account (such as in the
   2659     // PASSIVE_AUTH case), stick with the old active account.
   2660     GetWalletClient()->SetUserIndex(wallet_items_->active_account_index());
   2661 
   2662     std::vector<std::string> usernames;
   2663     for (size_t i = 0; i < wallet_items_->gaia_accounts().size(); ++i) {
   2664       usernames.push_back(wallet_items_->gaia_accounts()[i]->email_address());
   2665     }
   2666     account_chooser_model_->SetWalletAccounts(
   2667         usernames, wallet_items_->active_account_index());
   2668   }
   2669 
   2670   if (wallet_items_) {
   2671     shipping_country_combobox_model_->SetCountries(
   2672         *GetManager(),
   2673         base::Bind(WalletCountryFilter,
   2674                    acceptable_shipping_countries_,
   2675                    wallet_items_->allowed_shipping_countries()));
   2676 
   2677     // If the site doesn't ship to any of the countries Wallet allows shipping
   2678     // to, the merchant is not supported. (Note we generally shouldn't get here
   2679     // as such a merchant wouldn't make it onto the Wallet whitelist.)
   2680     if (shipping_country_combobox_model_->GetItemCount() == 0)
   2681       DisableWallet(wallet::WalletClient::UNSUPPORTED_MERCHANT);
   2682   }
   2683 
   2684   ConstructLegalDocumentsText();
   2685   OnWalletOrSigninUpdate();
   2686 }
   2687 
   2688 void AutofillDialogControllerImpl::OnDidSaveToWallet(
   2689     const std::string& instrument_id,
   2690     const std::string& address_id,
   2691     const std::vector<wallet::RequiredAction>& required_actions,
   2692     const std::vector<wallet::FormFieldError>& form_field_errors) {
   2693   DCHECK(is_submitting_ && IsPayingWithWallet());
   2694 
   2695   if (required_actions.empty()) {
   2696     if (!address_id.empty())
   2697       active_address_id_ = address_id;
   2698     if (!instrument_id.empty())
   2699       active_instrument_id_ = instrument_id;
   2700     GetFullWallet();
   2701   } else {
   2702     OnWalletFormFieldError(form_field_errors);
   2703     HandleSaveOrUpdateRequiredActions(required_actions);
   2704   }
   2705 }
   2706 
   2707 void AutofillDialogControllerImpl::OnWalletError(
   2708     wallet::WalletClient::ErrorType error_type) {
   2709   DisableWallet(error_type);
   2710 }
   2711 
   2712 ////////////////////////////////////////////////////////////////////////////////
   2713 // PersonalDataManagerObserver implementation.
   2714 
   2715 void AutofillDialogControllerImpl::OnPersonalDataChanged() {
   2716   if (is_submitting_)
   2717     return;
   2718 
   2719   SuggestionsUpdated();
   2720 }
   2721 
   2722 ////////////////////////////////////////////////////////////////////////////////
   2723 // AccountChooserModelDelegate implementation.
   2724 
   2725 void AutofillDialogControllerImpl::AccountChoiceChanged() {
   2726   ScopedViewUpdates updates(view_.get());
   2727   wallet::WalletClient* client = GetWalletClient();
   2728 
   2729   if (is_submitting_)
   2730     client->CancelRequest();
   2731 
   2732   SetIsSubmitting(false);
   2733 
   2734   size_t selected_user_index =
   2735       account_chooser_model_->GetActiveWalletAccountIndex();
   2736   if (account_chooser_model_->WalletIsSelected() &&
   2737       client->user_index() != selected_user_index) {
   2738     client->SetUserIndex(selected_user_index);
   2739     // Clear |wallet_items_| so we don't try to restore the selected instrument
   2740     // and address.
   2741     wallet_items_.reset();
   2742     GetWalletItems();
   2743   } else {
   2744     SuggestionsUpdated();
   2745     UpdateAccountChooserView();
   2746   }
   2747 }
   2748 
   2749 void AutofillDialogControllerImpl::AddAccount() {
   2750   SignInLinkClicked();
   2751 }
   2752 
   2753 void AutofillDialogControllerImpl::UpdateAccountChooserView() {
   2754   if (view_) {
   2755     ScopedViewUpdates updates(view_.get());
   2756     view_->UpdateAccountChooser();
   2757     view_->UpdateNotificationArea();
   2758   }
   2759 }
   2760 
   2761 ////////////////////////////////////////////////////////////////////////////////
   2762 
   2763 bool AutofillDialogControllerImpl::HandleKeyPressEventInInput(
   2764     const content::NativeWebKeyboardEvent& event) {
   2765   if (popup_controller_.get())
   2766     return popup_controller_->HandleKeyPressEvent(event);
   2767 
   2768   return false;
   2769 }
   2770 
   2771 bool AutofillDialogControllerImpl::IsSubmitPausedOn(
   2772     wallet::RequiredAction required_action) const {
   2773   return full_wallet_ && full_wallet_->HasRequiredAction(required_action);
   2774 }
   2775 
   2776 void AutofillDialogControllerImpl::ShowNewCreditCardBubble(
   2777     scoped_ptr<CreditCard> new_card,
   2778     scoped_ptr<AutofillProfile> billing_profile) {
   2779   NewCreditCardBubbleController::Show(web_contents(),
   2780                                       new_card.Pass(),
   2781                                       billing_profile.Pass());
   2782 }
   2783 
   2784 void AutofillDialogControllerImpl::SubmitButtonDelayBegin() {
   2785   submit_button_delay_timer_.Start(
   2786       FROM_HERE,
   2787       base::TimeDelta::FromMilliseconds(kSubmitButtonDelayMs),
   2788       this,
   2789       &AutofillDialogControllerImpl::OnSubmitButtonDelayEnd);
   2790 }
   2791 
   2792 void AutofillDialogControllerImpl::SubmitButtonDelayEndForTesting() {
   2793   DCHECK(submit_button_delay_timer_.IsRunning());
   2794   submit_button_delay_timer_.user_task().Run();
   2795   submit_button_delay_timer_.Stop();
   2796 }
   2797 
   2798 void AutofillDialogControllerImpl::
   2799     ClearLastWalletItemsFetchTimestampForTesting() {
   2800   last_wallet_items_fetch_timestamp_ = base::TimeTicks();
   2801 }
   2802 
   2803 AccountChooserModel* AutofillDialogControllerImpl::
   2804     AccountChooserModelForTesting() {
   2805   return account_chooser_model_.get();
   2806 }
   2807 
   2808 bool AutofillDialogControllerImpl::IsSignInContinueUrl(
   2809     const GURL& url,
   2810     size_t* user_index) const {
   2811   return wallet::IsSignInContinueUrl(url, user_index);
   2812 }
   2813 
   2814 AutofillDialogControllerImpl::AutofillDialogControllerImpl(
   2815     content::WebContents* contents,
   2816     const FormData& form_structure,
   2817     const GURL& source_url,
   2818     const AutofillClient::ResultCallback& callback)
   2819     : WebContentsObserver(contents),
   2820       profile_(Profile::FromBrowserContext(contents->GetBrowserContext())),
   2821       initial_user_state_(AutofillMetrics::DIALOG_USER_STATE_UNKNOWN),
   2822       form_structure_(form_structure),
   2823       invoked_from_same_origin_(true),
   2824       source_url_(source_url),
   2825       callback_(callback),
   2826       wallet_client_(profile_->GetRequestContext(), this, source_url),
   2827       wallet_items_requested_(false),
   2828       handling_use_wallet_link_click_(false),
   2829       passive_failed_(false),
   2830       suggested_cc_(this),
   2831       suggested_billing_(this),
   2832       suggested_cc_billing_(this),
   2833       suggested_shipping_(this),
   2834       cares_about_shipping_(true),
   2835       popup_input_type_(UNKNOWN_TYPE),
   2836       popup_section_(SECTION_MIN),
   2837       waiting_for_explicit_sign_in_response_(false),
   2838       has_accepted_legal_documents_(false),
   2839       is_submitting_(false),
   2840       choose_another_instrument_or_address_(false),
   2841       wallet_server_validation_recoverable_(true),
   2842       data_was_passed_back_(false),
   2843       was_ui_latency_logged_(false),
   2844       card_generated_animation_(2000, 60, this),
   2845       weak_ptr_factory_(this) {
   2846   DCHECK(!callback_.is_null());
   2847 }
   2848 
   2849 AutofillDialogView* AutofillDialogControllerImpl::CreateView() {
   2850   return AutofillDialogView::Create(this);
   2851 }
   2852 
   2853 PersonalDataManager* AutofillDialogControllerImpl::GetManager() const {
   2854   return PersonalDataManagerFactory::GetForProfile(profile_);
   2855 }
   2856 
   2857 AddressValidator* AutofillDialogControllerImpl::GetValidator() {
   2858   return validator_.get();
   2859 }
   2860 
   2861 const wallet::WalletClient* AutofillDialogControllerImpl::GetWalletClient()
   2862     const {
   2863   return const_cast<AutofillDialogControllerImpl*>(this)->GetWalletClient();
   2864 }
   2865 
   2866 wallet::WalletClient* AutofillDialogControllerImpl::GetWalletClient() {
   2867   return &wallet_client_;
   2868 }
   2869 
   2870 bool AutofillDialogControllerImpl::IsPayingWithWallet() const {
   2871   return account_chooser_model_->WalletIsSelected() &&
   2872          SignedInState() == SIGNED_IN;
   2873 }
   2874 
   2875 void AutofillDialogControllerImpl::LoadRiskFingerprintData() {
   2876   risk_data_.clear();
   2877 
   2878   uint64 obfuscated_gaia_id = 0;
   2879   bool success = base::StringToUint64(wallet_items_->ObfuscatedGaiaId(),
   2880                                       &obfuscated_gaia_id);
   2881   DCHECK(success);
   2882 
   2883   gfx::Rect window_bounds;
   2884   window_bounds = GetBaseWindowForWebContents(web_contents())->GetBounds();
   2885 
   2886   PrefService* user_prefs = profile_->GetPrefs();
   2887   std::string charset = user_prefs->GetString(::prefs::kDefaultCharset);
   2888   std::string accept_languages =
   2889       user_prefs->GetString(::prefs::kAcceptLanguages);
   2890   base::Time install_time = base::Time::FromTimeT(
   2891       g_browser_process->metrics_service()->GetInstallDate());
   2892 
   2893   risk::GetFingerprint(
   2894       obfuscated_gaia_id, window_bounds, web_contents(),
   2895       chrome::VersionInfo().Version(), charset, accept_languages, install_time,
   2896       g_browser_process->GetApplicationLocale(), GetUserAgent(),
   2897       base::Bind(&AutofillDialogControllerImpl::OnDidLoadRiskFingerprintData,
   2898                  weak_ptr_factory_.GetWeakPtr()));
   2899 }
   2900 
   2901 void AutofillDialogControllerImpl::OnDidLoadRiskFingerprintData(
   2902     scoped_ptr<risk::Fingerprint> fingerprint) {
   2903   DCHECK(AreLegalDocumentsCurrent());
   2904 
   2905   std::string proto_data;
   2906   fingerprint->SerializeToString(&proto_data);
   2907   base::Base64Encode(proto_data, &risk_data_);
   2908 
   2909   SubmitWithWallet();
   2910 }
   2911 
   2912 void AutofillDialogControllerImpl::OpenTabWithUrl(const GURL& url) {
   2913   chrome::NavigateParams params(
   2914       chrome::FindBrowserWithWebContents(web_contents()),
   2915       url,
   2916       ui::PAGE_TRANSITION_LINK);
   2917   params.disposition = NEW_FOREGROUND_TAB;
   2918   chrome::Navigate(&params);
   2919 }
   2920 
   2921 DialogSection AutofillDialogControllerImpl::ActiveBillingSection() const {
   2922   return IsPayingWithWallet() ? SECTION_CC_BILLING : SECTION_BILLING;
   2923 }
   2924 
   2925 bool AutofillDialogControllerImpl::IsEditingExistingData(
   2926     DialogSection section) const {
   2927   return section_editing_state_.count(section) > 0;
   2928 }
   2929 
   2930 bool AutofillDialogControllerImpl::IsManuallyEditingSection(
   2931     DialogSection section) const {
   2932   return IsEditingExistingData(section) ||
   2933          SuggestionsMenuModelForSection(section)->
   2934              GetItemKeyForCheckedItem() == kAddNewItemKey;
   2935 }
   2936 
   2937 void AutofillDialogControllerImpl::OnWalletSigninError() {
   2938   account_chooser_model_->SetHadWalletSigninError();
   2939   GetWalletClient()->CancelRequest();
   2940   LogDialogLatencyToShow();
   2941 }
   2942 
   2943 void AutofillDialogControllerImpl::DisableWallet(
   2944     wallet::WalletClient::ErrorType error_type) {
   2945   signin_helper_.reset();
   2946   wallet_items_.reset();
   2947   wallet_errors_.clear();
   2948   GetWalletClient()->CancelRequest();
   2949   SetIsSubmitting(false);
   2950   wallet_error_notification_ = GetWalletError(error_type);
   2951   account_chooser_model_->SetHadWalletError();
   2952 }
   2953 
   2954 void AutofillDialogControllerImpl::SuggestionsUpdated() {
   2955   ScopedViewUpdates updates(view_.get());
   2956 
   2957   const FieldValueMap snapshot = TakeUserInputSnapshot();
   2958 
   2959   suggested_cc_.Reset();
   2960   suggested_billing_.Reset();
   2961   suggested_cc_billing_.Reset();
   2962   suggested_shipping_.Reset();
   2963   HidePopup();
   2964 
   2965   suggested_shipping_.AddKeyedItem(
   2966       kSameAsBillingKey,
   2967       l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_USE_BILLING_FOR_SHIPPING));
   2968 
   2969   if (IsPayingWithWallet()) {
   2970     const std::vector<wallet::Address*>& addresses =
   2971         wallet_items_->addresses();
   2972 
   2973     bool shipping_same_as_billing = profile_->GetPrefs()->GetBoolean(
   2974         ::prefs::kAutofillDialogWalletShippingSameAsBilling);
   2975 
   2976     if (shipping_same_as_billing)
   2977       suggested_shipping_.SetCheckedItem(kSameAsBillingKey);
   2978 
   2979     for (size_t i = 0; i < addresses.size(); ++i) {
   2980       std::string key = base::IntToString(i);
   2981       suggested_shipping_.AddKeyedItemWithMinorText(
   2982           key,
   2983           addresses[i]->DisplayName(),
   2984           addresses[i]->DisplayNameDetail());
   2985       suggested_shipping_.SetEnabled(
   2986           key,
   2987           CanAcceptCountry(SECTION_SHIPPING,
   2988                            addresses[i]->country_name_code()));
   2989 
   2990       // TODO(scr): Move this assignment outside the loop or comment why it
   2991       // can't be there.
   2992       const std::string default_shipping_address_id =
   2993           GetIdToSelect(wallet_items_->default_address_id(),
   2994                         previous_default_shipping_address_id_,
   2995                         previously_selected_shipping_address_id_);
   2996 
   2997       if (!shipping_same_as_billing &&
   2998           addresses[i]->object_id() == default_shipping_address_id) {
   2999         suggested_shipping_.SetCheckedItem(key);
   3000       }
   3001     }
   3002 
   3003     if (!IsSubmitPausedOn(wallet::VERIFY_CVV)) {
   3004       const std::vector<wallet::WalletItems::MaskedInstrument*>& instruments =
   3005           wallet_items_->instruments();
   3006       std::string first_active_instrument_key;
   3007       std::string default_instrument_key;
   3008       for (size_t i = 0; i < instruments.size(); ++i) {
   3009         bool allowed = IsInstrumentAllowed(*instruments[i]) &&
   3010             CanAcceptCountry(SECTION_BILLING,
   3011                              instruments[i]->address().country_name_code());
   3012         gfx::Image icon = instruments[i]->CardIcon();
   3013         if (!allowed && !icon.IsEmpty()) {
   3014           // Create a grayed disabled icon.
   3015           SkBitmap disabled_bitmap = SkBitmapOperations::CreateHSLShiftedBitmap(
   3016               *icon.ToSkBitmap(), kGrayImageShift);
   3017           icon = gfx::Image(
   3018               gfx::ImageSkia::CreateFrom1xBitmap(disabled_bitmap));
   3019         }
   3020         std::string key = base::IntToString(i);
   3021         suggested_cc_billing_.AddKeyedItemWithMinorTextAndIcon(
   3022             key,
   3023             instruments[i]->DisplayName(),
   3024             instruments[i]->DisplayNameDetail(),
   3025             icon);
   3026         suggested_cc_billing_.SetEnabled(key, allowed);
   3027 
   3028         if (allowed) {
   3029           if (first_active_instrument_key.empty())
   3030             first_active_instrument_key = key;
   3031 
   3032           const std::string default_instrument_id =
   3033               GetIdToSelect(wallet_items_->default_instrument_id(),
   3034                             previous_default_instrument_id_,
   3035                             previously_selected_instrument_id_);
   3036           if (instruments[i]->object_id() == default_instrument_id)
   3037             default_instrument_key = key;
   3038         }
   3039       }
   3040 
   3041       suggested_cc_billing_.AddKeyedItem(
   3042           kAddNewItemKey,
   3043           l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADD_BILLING_DETAILS));
   3044       if (!wallet_items_->HasRequiredAction(wallet::SETUP_WALLET)) {
   3045         suggested_cc_billing_.AddKeyedItemWithMinorText(
   3046             kManageItemsKey,
   3047             l10n_util::GetStringUTF16(
   3048                 IDS_AUTOFILL_DIALOG_MANAGE_BILLING_DETAILS),
   3049                 base::UTF8ToUTF16(wallet::GetManageInstrumentsUrl(0U).host()));
   3050       }
   3051 
   3052       // Determine which instrument item should be selected.
   3053       if (!default_instrument_key.empty())
   3054         suggested_cc_billing_.SetCheckedItem(default_instrument_key);
   3055       else if (!first_active_instrument_key.empty())
   3056         suggested_cc_billing_.SetCheckedItem(first_active_instrument_key);
   3057       else
   3058         suggested_cc_billing_.SetCheckedItem(kAddNewItemKey);
   3059     }
   3060   } else {
   3061     shipping_country_combobox_model_->SetCountries(
   3062         *GetManager(),
   3063         base::Bind(AutofillCountryFilter, acceptable_shipping_countries_));
   3064 
   3065     if (IsAutofillEnabled()) {
   3066       PersonalDataManager* manager = GetManager();
   3067       const std::vector<CreditCard*>& cards = manager->GetCreditCards();
   3068       ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
   3069       for (size_t i = 0; i < cards.size(); ++i) {
   3070         if (!i18ninput::CardHasCompleteAndVerifiedData(*cards[i]))
   3071           continue;
   3072 
   3073         suggested_cc_.AddKeyedItemWithIcon(
   3074             cards[i]->guid(),
   3075             cards[i]->Label(),
   3076             rb.GetImageNamed(CreditCard::IconResourceId(cards[i]->type())));
   3077         suggested_cc_.SetEnabled(
   3078             cards[i]->guid(),
   3079             !ShouldDisallowCcType(cards[i]->TypeForDisplay()));
   3080       }
   3081 
   3082       const std::vector<AutofillProfile*>& profiles = manager->GetProfiles();
   3083       std::vector<base::string16> labels;
   3084       AutofillProfile::CreateDifferentiatingLabels(
   3085           profiles,
   3086           g_browser_process->GetApplicationLocale(),
   3087           &labels);
   3088       DCHECK_EQ(labels.size(), profiles.size());
   3089       for (size_t i = 0; i < profiles.size(); ++i) {
   3090         const AutofillProfile& profile = *profiles[i];
   3091         if (!i18ninput::AddressHasCompleteAndVerifiedData(
   3092                 profile, g_browser_process->GetApplicationLocale())) {
   3093           continue;
   3094         }
   3095 
   3096         // Don't add variants for addresses: name is part of credit card and
   3097         // we'll just ignore email and phone number variants.
   3098         suggested_shipping_.AddKeyedItem(profile.guid(), labels[i]);
   3099         suggested_shipping_.SetEnabled(
   3100             profile.guid(),
   3101             CanAcceptCountry(
   3102                 SECTION_SHIPPING,
   3103                 base::UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY))));
   3104         if (!profile.GetRawInfo(EMAIL_ADDRESS).empty() &&
   3105             !profile.IsPresentButInvalid(EMAIL_ADDRESS)) {
   3106           suggested_billing_.AddKeyedItem(profile.guid(), labels[i]);
   3107           suggested_billing_.SetEnabled(
   3108               profile.guid(),
   3109               CanAcceptCountry(
   3110                   SECTION_BILLING,
   3111                   base::UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY))));
   3112         }
   3113       }
   3114     }
   3115 
   3116     suggested_cc_.AddKeyedItem(
   3117         kAddNewItemKey,
   3118         l10n_util::GetStringUTF16(IsAutofillEnabled() ?
   3119             IDS_AUTOFILL_DIALOG_ADD_CREDIT_CARD :
   3120             IDS_AUTOFILL_DIALOG_ENTER_CREDIT_CARD));
   3121     suggested_cc_.AddKeyedItem(
   3122         kManageItemsKey,
   3123         l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_MANAGE_CREDIT_CARD));
   3124     suggested_billing_.AddKeyedItem(
   3125         kAddNewItemKey,
   3126         l10n_util::GetStringUTF16(IsAutofillEnabled() ?
   3127             IDS_AUTOFILL_DIALOG_ADD_BILLING_ADDRESS :
   3128             IDS_AUTOFILL_DIALOG_ENTER_BILLING_DETAILS));
   3129     suggested_billing_.AddKeyedItem(
   3130         kManageItemsKey,
   3131         l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_MANAGE_BILLING_ADDRESS));
   3132   }
   3133 
   3134   suggested_shipping_.AddKeyedItem(
   3135       kAddNewItemKey,
   3136       l10n_util::GetStringUTF16(IsPayingWithWallet() || IsAutofillEnabled() ?
   3137           IDS_AUTOFILL_DIALOG_ADD_SHIPPING_ADDRESS :
   3138           IDS_AUTOFILL_DIALOG_USE_DIFFERENT_SHIPPING_ADDRESS));
   3139 
   3140   if (!IsPayingWithWallet()) {
   3141     if (IsAutofillEnabled()) {
   3142       suggested_shipping_.AddKeyedItem(
   3143           kManageItemsKey,
   3144           l10n_util::GetStringUTF16(
   3145               IDS_AUTOFILL_DIALOG_MANAGE_SHIPPING_ADDRESS));
   3146     }
   3147   } else if (!wallet_items_->HasRequiredAction(wallet::SETUP_WALLET)) {
   3148     suggested_shipping_.AddKeyedItemWithMinorText(
   3149         kManageItemsKey,
   3150         l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_MANAGE_SHIPPING_ADDRESS),
   3151         base::UTF8ToUTF16(wallet::GetManageAddressesUrl(0U).host()));
   3152   }
   3153 
   3154   if (!IsPayingWithWallet() && IsAutofillEnabled()) {
   3155     for (size_t i = SECTION_MIN; i <= SECTION_MAX; ++i) {
   3156       DialogSection section = static_cast<DialogSection>(i);
   3157       if (!SectionIsActive(section))
   3158         continue;
   3159 
   3160       // Set the starting choice for the menu. First set to the default in case
   3161       // the GUID saved in prefs refers to a profile that no longer exists.
   3162       std::string guid;
   3163       GetDefaultAutofillChoice(section, &guid);
   3164       SuggestionsMenuModel* model = SuggestionsMenuModelForSection(section);
   3165       model->SetCheckedItem(guid);
   3166       if (GetAutofillChoice(section, &guid))
   3167         model->SetCheckedItem(guid);
   3168     }
   3169   }
   3170 
   3171   if (view_)
   3172     view_->ModelChanged();
   3173 
   3174   for (size_t i = SECTION_MIN; i <= SECTION_MAX; ++i) {
   3175     ResetSectionInput(static_cast<DialogSection>(i));
   3176   }
   3177 
   3178   FieldValueMap::const_iterator billing_it =
   3179       snapshot.find(ADDRESS_BILLING_COUNTRY);
   3180   if (billing_it != snapshot.end())
   3181     RebuildInputsForCountry(ActiveBillingSection(), billing_it->second, true);
   3182 
   3183   FieldValueMap::const_iterator shipping_it =
   3184       snapshot.find(ADDRESS_HOME_COUNTRY);
   3185   if (shipping_it != snapshot.end())
   3186     RebuildInputsForCountry(SECTION_SHIPPING, shipping_it->second, true);
   3187 
   3188   RestoreUserInputFromSnapshot(snapshot);
   3189 
   3190   for (size_t i = SECTION_MIN; i <= SECTION_MAX; ++i) {
   3191     DialogSection section = static_cast<DialogSection>(i);
   3192     if (!SectionIsActive(section))
   3193       continue;
   3194 
   3195     ShowEditUiIfBadSuggestion(section);
   3196     UpdateSection(section);
   3197   }
   3198 
   3199   UpdateForErrors();
   3200 }
   3201 
   3202 void AutofillDialogControllerImpl::FillOutputForSectionWithComparator(
   3203     DialogSection section,
   3204     const FormStructure::InputFieldComparator& compare) {
   3205   if (!SectionIsActive(section))
   3206     return;
   3207 
   3208   DetailInputs inputs;
   3209   std::string country_code = CountryCodeForSection(section);
   3210   BuildInputsForSection(section, country_code, &inputs,
   3211                         MutableAddressLanguageCodeForSection(section));
   3212   std::vector<ServerFieldType> types = common::TypesFromInputs(inputs);
   3213 
   3214   scoped_ptr<DataModelWrapper> wrapper = CreateWrapper(section);
   3215   if (wrapper) {
   3216     // Only fill in data that is associated with this section.
   3217     wrapper->FillFormStructure(types, compare, &form_structure_);
   3218 
   3219     // CVC needs special-casing because the CreditCard class doesn't store or
   3220     // handle them. This isn't necessary when filling the combined CC and
   3221     // billing section as CVC comes from |full_wallet_| in this case.
   3222     if (section == SECTION_CC)
   3223       SetOutputForFieldsOfType(CREDIT_CARD_VERIFICATION_CODE, view_->GetCvc());
   3224 
   3225     // When filling from Wallet data, use the email address associated with the
   3226     // account. There is no other email address stored as part of a Wallet
   3227     // address.
   3228     if (section == SECTION_CC_BILLING) {
   3229       SetOutputForFieldsOfType(
   3230           EMAIL_ADDRESS, account_chooser_model_->GetActiveWalletAccountName());
   3231     }
   3232   } else {
   3233     // The user manually input data. If using Autofill, save the info as new or
   3234     // edited data. Always fill local data into |form_structure_|.
   3235     FieldValueMap output;
   3236     view_->GetUserInput(section, &output);
   3237 
   3238     if (section == SECTION_CC) {
   3239       CreditCard card;
   3240       FillFormGroupFromOutputs(output, &card);
   3241 
   3242       // The card holder name comes from the billing address section.
   3243       card.SetRawInfo(CREDIT_CARD_NAME,
   3244                       GetValueFromSection(SECTION_BILLING, NAME_BILLING_FULL));
   3245 
   3246       if (ShouldSaveDetailsLocally()) {
   3247         card.set_origin(kAutofillDialogOrigin);
   3248 
   3249         std::string guid = GetManager()->SaveImportedCreditCard(card);
   3250         newly_saved_data_model_guids_[section] = guid;
   3251         DCHECK(!profile()->IsOffTheRecord());
   3252         newly_saved_card_.reset(new CreditCard(card));
   3253       }
   3254 
   3255       AutofillCreditCardWrapper card_wrapper(&card);
   3256       card_wrapper.FillFormStructure(types, compare, &form_structure_);
   3257 
   3258       // Again, CVC needs special-casing. Fill it in directly from |output|.
   3259       SetOutputForFieldsOfType(
   3260           CREDIT_CARD_VERIFICATION_CODE,
   3261           output[CREDIT_CARD_VERIFICATION_CODE]);
   3262     } else {
   3263       AutofillProfile profile;
   3264       FillFormGroupFromOutputs(output, &profile);
   3265       profile.set_language_code(AddressLanguageCodeForSection(section));
   3266 
   3267       if (ShouldSaveDetailsLocally()) {
   3268         profile.set_origin(RulesAreLoaded(section) ?
   3269             kAutofillDialogOrigin : source_url_.GetOrigin().spec());
   3270 
   3271         std::string guid = GetManager()->SaveImportedProfile(profile);
   3272         newly_saved_data_model_guids_[section] = guid;
   3273       }
   3274 
   3275       AutofillProfileWrapper profile_wrapper(&profile);
   3276       profile_wrapper.FillFormStructure(types, compare, &form_structure_);
   3277     }
   3278   }
   3279 }
   3280 
   3281 void AutofillDialogControllerImpl::FillOutputForSection(DialogSection section) {
   3282   FillOutputForSectionWithComparator(
   3283       section, base::Bind(common::ServerTypeMatchesField, section));
   3284 }
   3285 
   3286 bool AutofillDialogControllerImpl::FormStructureCaresAboutSection(
   3287     DialogSection section) const {
   3288   // For now, only SECTION_SHIPPING may be omitted due to a site not asking for
   3289   // any of the fields.
   3290   if (section == SECTION_SHIPPING)
   3291     return cares_about_shipping_;
   3292 
   3293   return true;
   3294 }
   3295 
   3296 void AutofillDialogControllerImpl::SetOutputForFieldsOfType(
   3297     ServerFieldType type,
   3298     const base::string16& output) {
   3299   for (size_t i = 0; i < form_structure_.field_count(); ++i) {
   3300     AutofillField* field = form_structure_.field(i);
   3301     if (field->Type().GetStorableType() == type)
   3302       field->value = output;
   3303   }
   3304 }
   3305 
   3306 base::string16 AutofillDialogControllerImpl::GetValueFromSection(
   3307     DialogSection section,
   3308     ServerFieldType type) {
   3309   DCHECK(SectionIsActive(section));
   3310 
   3311   scoped_ptr<DataModelWrapper> wrapper = CreateWrapper(section);
   3312   if (wrapper)
   3313     return wrapper->GetInfo(AutofillType(type));
   3314 
   3315   FieldValueMap output;
   3316   view_->GetUserInput(section, &output);
   3317   return output[type];
   3318 }
   3319 
   3320 bool AutofillDialogControllerImpl::CanAcceptCountry(
   3321     DialogSection section,
   3322     const std::string& country_code) {
   3323   DCHECK_EQ(2U, country_code.size());
   3324 
   3325   if (section == SECTION_CC_BILLING)
   3326     return LowerCaseEqualsASCII(country_code, "us");
   3327 
   3328   CountryComboboxModel* model = CountryComboboxModelForSection(section);
   3329   const std::vector<AutofillCountry*>& countries = model->countries();
   3330   for (size_t i = 0; i < countries.size(); ++i) {
   3331     if (countries[i] && countries[i]->country_code() == country_code)
   3332       return true;
   3333   }
   3334 
   3335   return false;
   3336 }
   3337 
   3338 bool AutofillDialogControllerImpl::ShouldSuggestProfile(
   3339     DialogSection section,
   3340     const AutofillProfile& profile) {
   3341   std::string country_code =
   3342       base::UTF16ToASCII(profile.GetRawInfo(ADDRESS_HOME_COUNTRY));
   3343   return country_code.empty() || CanAcceptCountry(section, country_code);
   3344 }
   3345 
   3346 SuggestionsMenuModel* AutofillDialogControllerImpl::
   3347     SuggestionsMenuModelForSection(DialogSection section) {
   3348   switch (section) {
   3349     case SECTION_CC:
   3350       return &suggested_cc_;
   3351     case SECTION_BILLING:
   3352       return &suggested_billing_;
   3353     case SECTION_SHIPPING:
   3354       return &suggested_shipping_;
   3355     case SECTION_CC_BILLING:
   3356       return &suggested_cc_billing_;
   3357   }
   3358 
   3359   NOTREACHED();
   3360   return NULL;
   3361 }
   3362 
   3363 const SuggestionsMenuModel* AutofillDialogControllerImpl::
   3364     SuggestionsMenuModelForSection(DialogSection section) const {
   3365   return const_cast<AutofillDialogControllerImpl*>(this)->
   3366       SuggestionsMenuModelForSection(section);
   3367 }
   3368 
   3369 DialogSection AutofillDialogControllerImpl::SectionForSuggestionsMenuModel(
   3370     const SuggestionsMenuModel& model) {
   3371   if (&model == &suggested_cc_)
   3372     return SECTION_CC;
   3373 
   3374   if (&model == &suggested_billing_)
   3375     return SECTION_BILLING;
   3376 
   3377   if (&model == &suggested_cc_billing_)
   3378     return SECTION_CC_BILLING;
   3379 
   3380   DCHECK_EQ(&model, &suggested_shipping_);
   3381   return SECTION_SHIPPING;
   3382 }
   3383 
   3384 CountryComboboxModel* AutofillDialogControllerImpl::
   3385     CountryComboboxModelForSection(DialogSection section) {
   3386   if (section == SECTION_BILLING)
   3387     return billing_country_combobox_model_.get();
   3388 
   3389   if (section == SECTION_SHIPPING)
   3390     return shipping_country_combobox_model_.get();
   3391 
   3392   return NULL;
   3393 }
   3394 
   3395 void AutofillDialogControllerImpl::GetI18nValidatorSuggestions(
   3396     DialogSection section,
   3397     ServerFieldType type,
   3398     std::vector<base::string16>* popup_values,
   3399     std::vector<base::string16>* popup_labels,
   3400     std::vector<base::string16>* popup_icons) {
   3401   AddressField focused_field;
   3402   if (!i18n::FieldForType(type, &focused_field))
   3403     return;
   3404 
   3405   FieldValueMap inputs;
   3406   view_->GetUserInput(section, &inputs);
   3407 
   3408   AutofillProfile profile;
   3409   FillFormGroupFromOutputs(inputs, &profile);
   3410 
   3411   scoped_ptr<AddressData> user_input =
   3412       i18n::CreateAddressDataFromAutofillProfile(
   3413           profile, g_browser_process->GetApplicationLocale());
   3414   user_input->language_code = AddressLanguageCodeForSection(section);
   3415 
   3416   static const size_t kSuggestionsLimit = 10;
   3417   AddressValidator::Status status = GetValidator()->GetSuggestions(
   3418       *user_input, focused_field, kSuggestionsLimit,
   3419       &i18n_validator_suggestions_);
   3420 
   3421   if (status != AddressValidator::SUCCESS)
   3422     return;
   3423 
   3424   for (size_t i = 0; i < i18n_validator_suggestions_.size(); ++i) {
   3425     popup_values->push_back(base::UTF8ToUTF16(
   3426         i18n_validator_suggestions_[i].GetFieldValue(focused_field)));
   3427 
   3428     // Disambiguate the suggestion by showing the smallest administrative
   3429     // region of the suggested address:
   3430     //    ADMIN_AREA > LOCALITY > DEPENDENT_LOCALITY
   3431     popup_labels->push_back(base::string16());
   3432     for (int field = DEPENDENT_LOCALITY; field >= ADMIN_AREA; --field) {
   3433       const std::string& field_value =
   3434           i18n_validator_suggestions_[i].GetFieldValue(
   3435               static_cast<AddressField>(field));
   3436       if (focused_field != field && !field_value.empty()) {
   3437         popup_labels->back().assign(base::UTF8ToUTF16(field_value));
   3438         break;
   3439       }
   3440     }
   3441   }
   3442   popup_icons->resize(popup_values->size());
   3443 }
   3444 
   3445 DetailInputs* AutofillDialogControllerImpl::MutableRequestedFieldsForSection(
   3446     DialogSection section) {
   3447   return const_cast<DetailInputs*>(&RequestedFieldsForSection(section));
   3448 }
   3449 
   3450 std::string* AutofillDialogControllerImpl::MutableAddressLanguageCodeForSection(
   3451     DialogSection section) {
   3452   switch (section) {
   3453     case SECTION_BILLING:
   3454     case SECTION_CC_BILLING:
   3455       return &billing_address_language_code_;
   3456     case SECTION_SHIPPING:
   3457       return &shipping_address_language_code_;
   3458     case SECTION_CC:
   3459       return NULL;
   3460   }
   3461   NOTREACHED();
   3462   return NULL;
   3463 }
   3464 
   3465 std::string AutofillDialogControllerImpl::AddressLanguageCodeForSection(
   3466     DialogSection section) {
   3467   std::string* language_code = MutableAddressLanguageCodeForSection(section);
   3468   return language_code != NULL ? *language_code : std::string();
   3469 }
   3470 
   3471 std::vector<ServerFieldType> AutofillDialogControllerImpl::
   3472     RequestedTypesForSection(DialogSection section) const {
   3473   return common::TypesFromInputs(RequestedFieldsForSection(section));
   3474 }
   3475 
   3476 std::string AutofillDialogControllerImpl::CountryCodeForSection(
   3477     DialogSection section) {
   3478   base::string16 country;
   3479 
   3480   scoped_ptr<DataModelWrapper> wrapper = CreateWrapper(section);
   3481   if (wrapper) {
   3482     country = wrapper->GetInfo(AutofillType(CountryTypeForSection(section)));
   3483   } else {
   3484     FieldValueMap outputs;
   3485     view_->GetUserInput(section, &outputs);
   3486     country = outputs[CountryTypeForSection(section)];
   3487   }
   3488 
   3489   return AutofillCountry::GetCountryCode(
   3490       country, g_browser_process->GetApplicationLocale());
   3491 }
   3492 
   3493 bool AutofillDialogControllerImpl::RebuildInputsForCountry(
   3494     DialogSection section,
   3495     const base::string16& country_name,
   3496     bool should_clobber) {
   3497   CountryComboboxModel* model = CountryComboboxModelForSection(section);
   3498   if (!model)
   3499     return false;
   3500 
   3501   std::string country_code = AutofillCountry::GetCountryCode(
   3502       country_name, g_browser_process->GetApplicationLocale());
   3503   DCHECK(CanAcceptCountry(section, country_code));
   3504 
   3505   if (view_ && !should_clobber) {
   3506     FieldValueMap outputs;
   3507     view_->GetUserInput(section, &outputs);
   3508 
   3509     // If |country_name| is the same as the view, no-op and let the caller know.
   3510     if (outputs[CountryTypeForSection(section)] == country_name)
   3511       return false;
   3512   }
   3513 
   3514   DetailInputs* inputs = MutableRequestedFieldsForSection(section);
   3515   inputs->clear();
   3516   BuildInputsForSection(section, country_code, inputs,
   3517                         MutableAddressLanguageCodeForSection(section));
   3518 
   3519   if (!country_code.empty()) {
   3520     GetValidator()->LoadRules(AutofillCountry::GetCountryCode(
   3521         country_name, g_browser_process->GetApplicationLocale()));
   3522   }
   3523 
   3524   return true;
   3525 }
   3526 
   3527 void AutofillDialogControllerImpl::HidePopup() {
   3528   if (popup_controller_)
   3529     popup_controller_->Hide();
   3530   popup_input_type_ = UNKNOWN_TYPE;
   3531 }
   3532 
   3533 void AutofillDialogControllerImpl::SetEditingExistingData(
   3534     DialogSection section, bool editing) {
   3535   if (editing)
   3536     section_editing_state_.insert(section);
   3537   else
   3538     section_editing_state_.erase(section);
   3539 }
   3540 
   3541 bool AutofillDialogControllerImpl::IsASuggestionItemKey(
   3542     const std::string& key) const {
   3543   return !key.empty() &&
   3544       key != kAddNewItemKey &&
   3545       key != kManageItemsKey &&
   3546       key != kSameAsBillingKey;
   3547 }
   3548 
   3549 bool AutofillDialogControllerImpl::IsAutofillEnabled() const {
   3550   return profile_->GetPrefs()->GetBoolean(prefs::kAutofillEnabled);
   3551 }
   3552 
   3553 bool AutofillDialogControllerImpl::IsManuallyEditingAnySection() const {
   3554   for (size_t section = SECTION_MIN; section <= SECTION_MAX; ++section) {
   3555     if (IsManuallyEditingSection(static_cast<DialogSection>(section)))
   3556       return true;
   3557   }
   3558   return false;
   3559 }
   3560 
   3561 base::string16 AutofillDialogControllerImpl::CreditCardNumberValidityMessage(
   3562     const base::string16& number) const {
   3563   if (!number.empty() && !autofill::IsValidCreditCardNumber(number)) {
   3564     return l10n_util::GetStringUTF16(
   3565         IDS_AUTOFILL_DIALOG_VALIDATION_INVALID_CREDIT_CARD_NUMBER);
   3566   }
   3567 
   3568   if (!IsPayingWithWallet() &&
   3569       ShouldDisallowCcType(CreditCard::TypeForDisplay(
   3570           CreditCard::GetCreditCardType(number)))) {
   3571     int ids = IDS_AUTOFILL_DIALOG_VALIDATION_UNACCEPTED_GENERIC_CARD;
   3572     const char* const type = CreditCard::GetCreditCardType(number);
   3573     if (type == kAmericanExpressCard)
   3574       ids = IDS_AUTOFILL_DIALOG_VALIDATION_UNACCEPTED_AMEX;
   3575     else if (type == kDiscoverCard)
   3576       ids = IDS_AUTOFILL_DIALOG_VALIDATION_UNACCEPTED_DISCOVER;
   3577     else if (type == kMasterCard)
   3578       ids = IDS_AUTOFILL_DIALOG_VALIDATION_UNACCEPTED_MASTERCARD;
   3579     else if (type == kVisaCard)
   3580       ids = IDS_AUTOFILL_DIALOG_VALIDATION_UNACCEPTED_VISA;
   3581 
   3582     return l10n_util::GetStringUTF16(ids);
   3583   }
   3584 
   3585   base::string16 message;
   3586   if (IsPayingWithWallet() && !wallet_items_->SupportsCard(number, &message))
   3587     return message;
   3588 
   3589   // Card number is good and supported.
   3590   return base::string16();
   3591 }
   3592 
   3593 bool AutofillDialogControllerImpl::AllSectionsAreValid() {
   3594   for (size_t section = SECTION_MIN; section <= SECTION_MAX; ++section) {
   3595     if (!SectionIsValid(static_cast<DialogSection>(section)))
   3596       return false;
   3597   }
   3598   return true;
   3599 }
   3600 
   3601 bool AutofillDialogControllerImpl::SectionIsValid(
   3602     DialogSection section) {
   3603   if (!IsManuallyEditingSection(section))
   3604     return true;
   3605 
   3606   FieldValueMap detail_outputs;
   3607   view_->GetUserInput(section, &detail_outputs);
   3608   return !InputsAreValid(section, detail_outputs).HasSureErrors();
   3609 }
   3610 
   3611 bool AutofillDialogControllerImpl::RulesAreLoaded(DialogSection section) {
   3612   AddressData address_data;
   3613   address_data.region_code = CountryCodeForSection(section);
   3614   AddressValidator::Status status = GetValidator()->ValidateAddress(
   3615       address_data, NULL, NULL);
   3616   return status == AddressValidator::SUCCESS;
   3617 }
   3618 
   3619 bool AutofillDialogControllerImpl::IsCreditCardExpirationValid(
   3620     const base::string16& year,
   3621     const base::string16& month) const {
   3622   // If the expiration is in the past as per the local clock, it's invalid.
   3623   base::Time now = base::Time::Now();
   3624   if (!autofill::IsValidCreditCardExpirationDate(year, month, now))
   3625     return false;
   3626 
   3627   const wallet::WalletItems::MaskedInstrument* instrument =
   3628       ActiveInstrument();
   3629   if (instrument) {
   3630     const std::string& locale = g_browser_process->GetApplicationLocale();
   3631     int month_int;
   3632     if (base::StringToInt(month, &month_int) &&
   3633         instrument->status() ==
   3634             wallet::WalletItems::MaskedInstrument::EXPIRED &&
   3635         year ==
   3636             instrument->GetInfo(
   3637                 AutofillType(CREDIT_CARD_EXP_4_DIGIT_YEAR), locale) &&
   3638         month_int == instrument->expiration_month()) {
   3639       // Otherwise, if the user is editing an instrument that's deemed expired
   3640       // by the Online Wallet server, mark it invalid on selection.
   3641       return false;
   3642     }
   3643   }
   3644 
   3645   return true;
   3646 }
   3647 
   3648 bool AutofillDialogControllerImpl::ShouldDisallowCcType(
   3649     const base::string16& type) const {
   3650   if (acceptable_cc_types_.empty())
   3651     return false;
   3652 
   3653   if (acceptable_cc_types_.find(base::i18n::ToUpper(type)) ==
   3654           acceptable_cc_types_.end()) {
   3655     return true;
   3656   }
   3657 
   3658   return false;
   3659 }
   3660 
   3661 bool AutofillDialogControllerImpl::HasInvalidAddress(
   3662     const AutofillProfile& profile) {
   3663   scoped_ptr<AddressData> address_data =
   3664       i18n::CreateAddressDataFromAutofillProfile(
   3665           profile, g_browser_process->GetApplicationLocale());
   3666 
   3667   FieldProblemMap problems;
   3668   GetValidator()->ValidateAddress(*address_data, NULL, &problems);
   3669   return !problems.empty();
   3670 }
   3671 
   3672 bool AutofillDialogControllerImpl::ShouldUseBillingForShipping() {
   3673   return SectionIsActive(SECTION_SHIPPING) &&
   3674       suggested_shipping_.GetItemKeyForCheckedItem() == kSameAsBillingKey;
   3675 }
   3676 
   3677 bool AutofillDialogControllerImpl::ShouldSaveDetailsLocally() {
   3678   // It's possible that the user checked [X] Save details locally before
   3679   // switching payment methods, so only ask the view whether to save details
   3680   // locally if that checkbox is showing (currently if not paying with wallet).
   3681   // Also, if the user isn't editing any sections, there's no data to save
   3682   // locally.
   3683   return ShouldOfferToSaveInChrome() && view_->SaveDetailsLocally();
   3684 }
   3685 
   3686 void AutofillDialogControllerImpl::SetIsSubmitting(bool submitting) {
   3687   is_submitting_ = submitting;
   3688 
   3689   if (!submitting)
   3690     full_wallet_.reset();
   3691 
   3692   if (view_) {
   3693     ScopedViewUpdates updates(view_.get());
   3694     view_->UpdateButtonStrip();
   3695     view_->UpdateOverlay();
   3696     view_->UpdateNotificationArea();
   3697   }
   3698 }
   3699 
   3700 bool AutofillDialogControllerImpl::AreLegalDocumentsCurrent() const {
   3701   return has_accepted_legal_documents_ ||
   3702       (wallet_items_ && wallet_items_->legal_documents().empty());
   3703 }
   3704 
   3705 void AutofillDialogControllerImpl::AcceptLegalTerms() {
   3706   content::GeolocationProvider::GetInstance()->UserDidOptIntoLocationServices();
   3707   PrefService* local_state = g_browser_process->local_state();
   3708   ListPrefUpdate accepted(
   3709       local_state, ::prefs::kAutofillDialogWalletLocationAcceptance);
   3710   accepted->AppendIfNotPresent(new base::StringValue(
   3711       account_chooser_model_->GetActiveWalletAccountName()));
   3712 
   3713   if (AreLegalDocumentsCurrent()) {
   3714     LoadRiskFingerprintData();
   3715   } else {
   3716     GetWalletClient()->AcceptLegalDocuments(
   3717         wallet_items_->legal_documents(),
   3718         wallet_items_->google_transaction_id());
   3719   }
   3720 }
   3721 
   3722 void AutofillDialogControllerImpl::SubmitWithWallet() {
   3723   active_instrument_id_.clear();
   3724   active_address_id_.clear();
   3725   full_wallet_.reset();
   3726 
   3727   const wallet::WalletItems::MaskedInstrument* active_instrument =
   3728       ActiveInstrument();
   3729   if (!IsManuallyEditingSection(SECTION_CC_BILLING)) {
   3730     active_instrument_id_ = active_instrument->object_id();
   3731     DCHECK(!active_instrument_id_.empty());
   3732   }
   3733 
   3734   const wallet::Address* active_address = ActiveShippingAddress();
   3735   if (!IsManuallyEditingSection(SECTION_SHIPPING) &&
   3736       !ShouldUseBillingForShipping() &&
   3737       IsShippingAddressRequired()) {
   3738     active_address_id_ = active_address->object_id();
   3739     DCHECK(!active_address_id_.empty());
   3740   }
   3741 
   3742   scoped_ptr<wallet::Instrument> inputted_instrument =
   3743       CreateTransientInstrument();
   3744 
   3745   scoped_ptr<wallet::Address> inputted_address;
   3746   if (active_address_id_.empty() && IsShippingAddressRequired()) {
   3747     if (ShouldUseBillingForShipping()) {
   3748       const wallet::Address& address = inputted_instrument ?
   3749           *inputted_instrument->address() : active_instrument->address();
   3750       // Try to find an exact matched shipping address and use it for shipping,
   3751       // otherwise save it as a new shipping address. http://crbug.com/225442
   3752       const wallet::Address* duplicated_address =
   3753           FindDuplicateAddress(wallet_items_->addresses(), address);
   3754       if (duplicated_address) {
   3755         active_address_id_ = duplicated_address->object_id();
   3756         DCHECK(!active_address_id_.empty());
   3757       } else {
   3758         inputted_address.reset(new wallet::Address(address));
   3759         DCHECK(inputted_address->object_id().empty());
   3760       }
   3761     } else {
   3762       inputted_address = CreateTransientAddress();
   3763     }
   3764   }
   3765 
   3766   // If there's neither an address nor instrument to save, |GetFullWallet()|
   3767   // is called when the risk fingerprint is loaded.
   3768   if (!active_instrument_id_.empty() &&
   3769       (!active_address_id_.empty() || !IsShippingAddressRequired())) {
   3770     GetFullWallet();
   3771     return;
   3772   }
   3773 
   3774   GetWalletClient()->SaveToWallet(
   3775       inputted_instrument.Pass(),
   3776       inputted_address.Pass(),
   3777       IsEditingExistingData(SECTION_CC_BILLING) ? active_instrument : NULL,
   3778       IsEditingExistingData(SECTION_SHIPPING) ? active_address : NULL);
   3779 }
   3780 
   3781 scoped_ptr<wallet::Instrument> AutofillDialogControllerImpl::
   3782     CreateTransientInstrument() {
   3783   if (!active_instrument_id_.empty())
   3784     return scoped_ptr<wallet::Instrument>();
   3785 
   3786   FieldValueMap output;
   3787   view_->GetUserInput(SECTION_CC_BILLING, &output);
   3788 
   3789   CreditCard card;
   3790   AutofillProfile profile;
   3791   base::string16 cvc;
   3792   GetBillingInfoFromOutputs(output, &card, &cvc, &profile);
   3793   CanonicalizeState(validator_.get(), &profile);
   3794 
   3795   return scoped_ptr<wallet::Instrument>(
   3796       new wallet::Instrument(card, cvc, profile));
   3797 }
   3798 
   3799 scoped_ptr<wallet::Address>AutofillDialogControllerImpl::
   3800     CreateTransientAddress() {
   3801   // If not using billing for shipping, just scrape the view.
   3802   FieldValueMap output;
   3803   view_->GetUserInput(SECTION_SHIPPING, &output);
   3804 
   3805   AutofillProfile profile;
   3806   FillFormGroupFromOutputs(output, &profile);
   3807   profile.set_language_code(shipping_address_language_code_);
   3808   CanonicalizeState(validator_.get(), &profile);
   3809 
   3810   return scoped_ptr<wallet::Address>(new wallet::Address(profile));
   3811 }
   3812 
   3813 void AutofillDialogControllerImpl::GetFullWallet() {
   3814   DCHECK(is_submitting_);
   3815   DCHECK(IsPayingWithWallet());
   3816   DCHECK(wallet_items_);
   3817   DCHECK(!active_instrument_id_.empty());
   3818   DCHECK(!active_address_id_.empty() || !IsShippingAddressRequired());
   3819 
   3820   std::vector<wallet::WalletClient::RiskCapability> capabilities;
   3821   capabilities.push_back(wallet::WalletClient::VERIFY_CVC);
   3822 
   3823   GetWalletClient()->GetFullWallet(wallet::WalletClient::FullWalletRequest(
   3824       active_instrument_id_,
   3825       active_address_id_,
   3826       wallet_items_->google_transaction_id(),
   3827       capabilities,
   3828       wallet_items_->HasRequiredAction(wallet::SETUP_WALLET)));
   3829 }
   3830 
   3831 void AutofillDialogControllerImpl::HandleSaveOrUpdateRequiredActions(
   3832     const std::vector<wallet::RequiredAction>& required_actions) {
   3833   DCHECK(!required_actions.empty());
   3834 
   3835   // TODO(ahutter): Investigate if we need to support more generic actions on
   3836   // this call such as GAIA_AUTH. See crbug.com/243457.
   3837   for (std::vector<wallet::RequiredAction>::const_iterator iter =
   3838            required_actions.begin();
   3839        iter != required_actions.end(); ++iter) {
   3840     if (*iter != wallet::INVALID_FORM_FIELD) {
   3841       // TODO(dbeam): handle this more gracefully.
   3842       DisableWallet(wallet::WalletClient::UNKNOWN_ERROR);
   3843     }
   3844   }
   3845   SetIsSubmitting(false);
   3846 }
   3847 
   3848 void AutofillDialogControllerImpl::FinishSubmit() {
   3849   if (IsPayingWithWallet()) {
   3850     ScopedViewUpdates updates(view_.get());
   3851     view_->UpdateOverlay();
   3852 
   3853     card_generated_animation_.Start();
   3854     return;
   3855   }
   3856   DoFinishSubmit();
   3857 }
   3858 
   3859 void AutofillDialogControllerImpl::AnimationProgressed(
   3860     const gfx::Animation* animation) {
   3861   DCHECK_EQ(animation, &card_generated_animation_);
   3862   PushOverlayUpdate();
   3863 }
   3864 
   3865 void AutofillDialogControllerImpl::AnimationEnded(
   3866     const gfx::Animation* animation) {
   3867   DCHECK_EQ(animation, &card_generated_animation_);
   3868   DoFinishSubmit();
   3869 }
   3870 
   3871 void AutofillDialogControllerImpl::OnAddressValidationRulesLoaded(
   3872     const std::string& country_code,
   3873     bool success) {
   3874   // Rules may load instantly (during initialization, before the view is
   3875   // even ready). We'll validate when the view is created.
   3876   if (!view_)
   3877     return;
   3878 
   3879   ScopedViewUpdates updates(view_.get());
   3880 
   3881   // TODO(dbeam): should we retry on failure?
   3882   for (size_t i = SECTION_MIN; i <= SECTION_MAX; ++i) {
   3883     DialogSection section = static_cast<DialogSection>(i);
   3884     if (!SectionIsActive(section) ||
   3885         CountryCodeForSection(section) != country_code) {
   3886       continue;
   3887     }
   3888 
   3889     if (IsManuallyEditingSection(section) &&
   3890         needs_validation_.count(section)) {
   3891       view_->ValidateSection(section);
   3892       needs_validation_.erase(section);
   3893     } else if (success) {
   3894       ShowEditUiIfBadSuggestion(section);
   3895       UpdateSection(section);
   3896     }
   3897   }
   3898 }
   3899 
   3900 void AutofillDialogControllerImpl::DoFinishSubmit() {
   3901   FillOutputForSection(SECTION_CC);
   3902   FillOutputForSection(SECTION_BILLING);
   3903   FillOutputForSection(SECTION_CC_BILLING);
   3904 
   3905   if (ShouldUseBillingForShipping()) {
   3906     FillOutputForSectionWithComparator(
   3907         SECTION_BILLING,
   3908         base::Bind(ServerTypeMatchesShippingField));
   3909     FillOutputForSectionWithComparator(
   3910         SECTION_CC,
   3911         base::Bind(ServerTypeMatchesShippingField));
   3912     FillOutputForSectionWithComparator(
   3913         SECTION_CC_BILLING,
   3914         base::Bind(ServerTypeMatchesShippingField));
   3915   } else {
   3916     FillOutputForSection(SECTION_SHIPPING);
   3917   }
   3918 
   3919   if (IsPayingWithWallet()) {
   3920     if (SectionIsActive(SECTION_SHIPPING)) {
   3921       profile_->GetPrefs()->SetBoolean(
   3922           ::prefs::kAutofillDialogWalletShippingSameAsBilling,
   3923           suggested_shipping_.GetItemKeyForCheckedItem() == kSameAsBillingKey);
   3924     }
   3925   } else if (ShouldOfferToSaveInChrome()) {
   3926     for (size_t i = SECTION_MIN; i <= SECTION_MAX; ++i) {
   3927       DialogSection section = static_cast<DialogSection>(i);
   3928       if (!SectionIsActive(section))
   3929         continue;
   3930 
   3931       SuggestionsMenuModel* model = SuggestionsMenuModelForSection(section);
   3932       std::string item_key = model->GetItemKeyForCheckedItem();
   3933       if (IsASuggestionItemKey(item_key) || item_key == kSameAsBillingKey) {
   3934         PersistAutofillChoice(section, item_key);
   3935       } else if (item_key == kAddNewItemKey && ShouldSaveDetailsLocally()) {
   3936         DCHECK(newly_saved_data_model_guids_.count(section));
   3937         PersistAutofillChoice(section, newly_saved_data_model_guids_[section]);
   3938       }
   3939     }
   3940 
   3941     profile_->GetPrefs()->SetBoolean(::prefs::kAutofillDialogSaveData,
   3942                                      view_->SaveDetailsLocally());
   3943   }
   3944 
   3945   // On a successful submit, if the user manually selected "pay without wallet",
   3946   // stop trying to pay with Wallet on future runs of the dialog. On the other
   3947   // hand, if there was an error that prevented the user from having the choice
   3948   // of using Wallet, leave the pref alone.
   3949   if (!wallet_error_notification_ &&
   3950       account_chooser_model_->HasAccountsToChoose()) {
   3951     profile_->GetPrefs()->SetBoolean(
   3952         ::prefs::kAutofillDialogPayWithoutWallet,
   3953         !account_chooser_model_->WalletIsSelected());
   3954   }
   3955 
   3956   LogOnFinishSubmitMetrics();
   3957 
   3958   // Callback should be called as late as possible.
   3959   callback_.Run(AutofillClient::AutocompleteResultSuccess,
   3960                 base::string16(),
   3961                 &form_structure_);
   3962   data_was_passed_back_ = true;
   3963 
   3964   // This might delete us.
   3965   Hide();
   3966 }
   3967 
   3968 void AutofillDialogControllerImpl::PersistAutofillChoice(
   3969     DialogSection section,
   3970     const std::string& guid) {
   3971   DCHECK(!IsPayingWithWallet() && ShouldOfferToSaveInChrome());
   3972   scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
   3973   value->SetString(kGuidPrefKey, guid);
   3974 
   3975   DictionaryPrefUpdate updater(profile()->GetPrefs(),
   3976                                ::prefs::kAutofillDialogAutofillDefault);
   3977   base::DictionaryValue* autofill_choice = updater.Get();
   3978   autofill_choice->Set(SectionToPrefString(section), value.release());
   3979 }
   3980 
   3981 void AutofillDialogControllerImpl::GetDefaultAutofillChoice(
   3982     DialogSection section,
   3983     std::string* guid) {
   3984   DCHECK(!IsPayingWithWallet() && IsAutofillEnabled());
   3985   // The default choice is the first thing in the menu that is a suggestion
   3986   // item.
   3987   SuggestionsMenuModel* model = SuggestionsMenuModelForSection(section);
   3988   for (int i = 0; i < model->GetItemCount(); ++i) {
   3989     // Try the first suggestion item that is enabled.
   3990     if (IsASuggestionItemKey(model->GetItemKeyAt(i)) && model->IsEnabledAt(i)) {
   3991       *guid = model->GetItemKeyAt(i);
   3992       return;
   3993     // Fall back to the first non-suggestion key.
   3994     } else if (!IsASuggestionItemKey(model->GetItemKeyAt(i)) && guid->empty()) {
   3995       *guid = model->GetItemKeyAt(i);
   3996     }
   3997   }
   3998 }
   3999 
   4000 bool AutofillDialogControllerImpl::GetAutofillChoice(DialogSection section,
   4001                                                      std::string* guid) {
   4002   DCHECK(!IsPayingWithWallet() && IsAutofillEnabled());
   4003   const base::DictionaryValue* choices = profile()->GetPrefs()->GetDictionary(
   4004       ::prefs::kAutofillDialogAutofillDefault);
   4005   if (!choices)
   4006     return false;
   4007 
   4008   const base::DictionaryValue* choice = NULL;
   4009   if (!choices->GetDictionary(SectionToPrefString(section), &choice))
   4010     return false;
   4011 
   4012   choice->GetString(kGuidPrefKey, guid);
   4013   return true;
   4014 }
   4015 
   4016 void AutofillDialogControllerImpl::LogOnFinishSubmitMetrics() {
   4017   GetMetricLogger().LogDialogUiDuration(
   4018       base::Time::Now() - dialog_shown_timestamp_,
   4019       AutofillMetrics::DIALOG_ACCEPTED);
   4020 
   4021   GetMetricLogger().LogDialogUiEvent(AutofillMetrics::DIALOG_UI_ACCEPTED);
   4022 
   4023   AutofillMetrics::DialogDismissalState dismissal_state;
   4024   if (!IsManuallyEditingAnySection()) {
   4025     dismissal_state = IsPayingWithWallet() ?
   4026         AutofillMetrics::DIALOG_ACCEPTED_EXISTING_WALLET_DATA :
   4027         AutofillMetrics::DIALOG_ACCEPTED_EXISTING_AUTOFILL_DATA;
   4028   } else if (IsPayingWithWallet()) {
   4029     dismissal_state = AutofillMetrics::DIALOG_ACCEPTED_SAVE_TO_WALLET;
   4030   } else if (ShouldSaveDetailsLocally()) {
   4031     dismissal_state = AutofillMetrics::DIALOG_ACCEPTED_SAVE_TO_AUTOFILL;
   4032   } else {
   4033     dismissal_state = AutofillMetrics::DIALOG_ACCEPTED_NO_SAVE;
   4034   }
   4035 
   4036   GetMetricLogger().LogDialogDismissalState(dismissal_state);
   4037 }
   4038 
   4039 void AutofillDialogControllerImpl::LogOnCancelMetrics() {
   4040   GetMetricLogger().LogDialogUiEvent(AutofillMetrics::DIALOG_UI_CANCELED);
   4041 
   4042   AutofillMetrics::DialogDismissalState dismissal_state;
   4043   if (ShouldShowSignInWebView())
   4044     dismissal_state = AutofillMetrics::DIALOG_CANCELED_DURING_SIGNIN;
   4045   else if (!IsManuallyEditingAnySection())
   4046     dismissal_state = AutofillMetrics::DIALOG_CANCELED_NO_EDITS;
   4047   else if (AllSectionsAreValid())
   4048     dismissal_state = AutofillMetrics::DIALOG_CANCELED_NO_INVALID_FIELDS;
   4049   else
   4050     dismissal_state = AutofillMetrics::DIALOG_CANCELED_WITH_INVALID_FIELDS;
   4051 
   4052   GetMetricLogger().LogDialogDismissalState(dismissal_state);
   4053 
   4054   GetMetricLogger().LogDialogUiDuration(
   4055       base::Time::Now() - dialog_shown_timestamp_,
   4056       AutofillMetrics::DIALOG_CANCELED);
   4057 }
   4058 
   4059 void AutofillDialogControllerImpl::LogSuggestionItemSelectedMetric(
   4060     const SuggestionsMenuModel& model) {
   4061   DialogSection section = SectionForSuggestionsMenuModel(model);
   4062 
   4063   AutofillMetrics::DialogUiEvent dialog_ui_event;
   4064   if (model.GetItemKeyForCheckedItem() == kAddNewItemKey) {
   4065     // Selected to add a new item.
   4066     dialog_ui_event = common::DialogSectionToUiItemAddedEvent(section);
   4067   } else if (IsASuggestionItemKey(model.GetItemKeyForCheckedItem())) {
   4068     // Selected an existing item.
   4069     dialog_ui_event = common::DialogSectionToUiSelectionChangedEvent(section);
   4070   } else {
   4071     // TODO(estade): add logging for "Manage items" or "Use billing for
   4072     // shipping"?
   4073     return;
   4074   }
   4075 
   4076   GetMetricLogger().LogDialogUiEvent(dialog_ui_event);
   4077 }
   4078 
   4079 void AutofillDialogControllerImpl::LogDialogLatencyToShow() {
   4080   if (was_ui_latency_logged_)
   4081     return;
   4082 
   4083   GetMetricLogger().LogDialogLatencyToShow(
   4084       base::Time::Now() - dialog_shown_timestamp_);
   4085   was_ui_latency_logged_ = true;
   4086 }
   4087 
   4088 AutofillMetrics::DialogInitialUserStateMetric
   4089     AutofillDialogControllerImpl::GetInitialUserState() const {
   4090   // Consider a user to be an Autofill user if the user has any credit cards
   4091   // or addresses saved. Check that the item count is greater than 2 because
   4092   // an "empty" menu still has the "add new" menu item and "manage" menu item.
   4093   const bool has_autofill_profiles =
   4094       suggested_cc_.GetItemCount() > 2 ||
   4095       suggested_billing_.GetItemCount() > 2;
   4096 
   4097   if (SignedInState() != SIGNED_IN) {
   4098     // Not signed in.
   4099     return has_autofill_profiles ?
   4100         AutofillMetrics::DIALOG_USER_NOT_SIGNED_IN_HAS_AUTOFILL :
   4101         AutofillMetrics::DIALOG_USER_NOT_SIGNED_IN_NO_AUTOFILL;
   4102   }
   4103 
   4104   // Signed in.
   4105   if (wallet_items_->instruments().empty()) {
   4106     // No Wallet items.
   4107     return has_autofill_profiles ?
   4108         AutofillMetrics::DIALOG_USER_SIGNED_IN_NO_WALLET_HAS_AUTOFILL :
   4109         AutofillMetrics::DIALOG_USER_SIGNED_IN_NO_WALLET_NO_AUTOFILL;
   4110   }
   4111 
   4112   // Has Wallet items.
   4113   return has_autofill_profiles ?
   4114       AutofillMetrics::DIALOG_USER_SIGNED_IN_HAS_WALLET_HAS_AUTOFILL :
   4115       AutofillMetrics::DIALOG_USER_SIGNED_IN_HAS_WALLET_NO_AUTOFILL;
   4116 }
   4117 
   4118 void AutofillDialogControllerImpl::MaybeShowCreditCardBubble() {
   4119   if (!data_was_passed_back_)
   4120     return;
   4121 
   4122   if (newly_saved_card_) {
   4123     scoped_ptr<AutofillProfile> billing_profile;
   4124     if (IsManuallyEditingSection(SECTION_BILLING)) {
   4125       // Scrape the view as the user's entering or updating information.
   4126       FieldValueMap outputs;
   4127       view_->GetUserInput(SECTION_BILLING, &outputs);
   4128       billing_profile.reset(new AutofillProfile);
   4129       FillFormGroupFromOutputs(outputs, billing_profile.get());
   4130       billing_profile->set_language_code(billing_address_language_code_);
   4131     } else {
   4132       // Just snag the currently suggested profile.
   4133       std::string item_key = SuggestionsMenuModelForSection(SECTION_BILLING)->
   4134           GetItemKeyForCheckedItem();
   4135       AutofillProfile* profile = GetManager()->GetProfileByGUID(item_key);
   4136       billing_profile.reset(new AutofillProfile(*profile));
   4137     }
   4138 
   4139     ShowNewCreditCardBubble(newly_saved_card_.Pass(),
   4140                             billing_profile.Pass());
   4141     return;
   4142   }
   4143 
   4144   if (!full_wallet_ || !full_wallet_->billing_address())
   4145     return;
   4146 
   4147   GeneratedCreditCardBubbleController::Show(
   4148       web_contents(),
   4149       full_wallet_->TypeAndLastFourDigits(),
   4150       backing_card_last_four_);
   4151 }
   4152 
   4153 void AutofillDialogControllerImpl::OnSubmitButtonDelayEnd() {
   4154   if (!view_)
   4155     return;
   4156   ScopedViewUpdates updates(view_.get());
   4157   view_->UpdateButtonStrip();
   4158 }
   4159 
   4160 void AutofillDialogControllerImpl::FetchWalletCookie() {
   4161   net::URLRequestContextGetter* request_context = profile_->GetRequestContext();
   4162   signin_helper_.reset(new wallet::WalletSigninHelper(this, request_context));
   4163   signin_helper_->StartWalletCookieValueFetch();
   4164 }
   4165 
   4166 }  // namespace autofill
   4167