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