data_model_wrapper.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
1// Copyright (c) 2012 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/data_model_wrapper.h"
6
7#include "base/callback.h"
8#include "base/strings/utf_string_conversions.h"
9#include "chrome/browser/browser_process.h"
10#include "chrome/browser/ui/autofill/autofill_dialog_models.h"
11#include "components/autofill/content/browser/wallet/full_wallet.h"
12#include "components/autofill/content/browser/wallet/wallet_address.h"
13#include "components/autofill/content/browser/wallet/wallet_items.h"
14#include "components/autofill/core/browser/autofill_data_model.h"
15#include "components/autofill/core/browser/autofill_profile.h"
16#include "components/autofill/core/browser/autofill_type.h"
17#include "components/autofill/core/browser/credit_card.h"
18#include "components/autofill/core/browser/form_structure.h"
19#include "components/autofill/core/browser/validation.h"
20#include "ui/base/resource/resource_bundle.h"
21#include "ui/gfx/image/image.h"
22
23namespace autofill {
24
25DataModelWrapper::~DataModelWrapper() {}
26
27void DataModelWrapper::FillInputs(DetailInputs* inputs) {
28  for (size_t i = 0; i < inputs->size(); ++i) {
29    (*inputs)[i].initial_value = GetInfo(AutofillType((*inputs)[i].type));
30  }
31}
32
33gfx::Image DataModelWrapper::GetIcon() {
34  return gfx::Image();
35}
36
37bool DataModelWrapper::GetDisplayText(
38    base::string16* vertically_compact,
39    base::string16* horizontally_compact) {
40  base::string16 comma = ASCIIToUTF16(", ");
41  base::string16 newline = ASCIIToUTF16("\n");
42
43  *vertically_compact = GetAddressDisplayText(comma);
44  *horizontally_compact = GetAddressDisplayText(newline);
45  return true;
46}
47
48bool DataModelWrapper::FillFormStructure(
49    const DetailInputs& inputs,
50    const InputFieldComparator& compare,
51    FormStructure* form_structure) const {
52  bool filled_something = false;
53  for (size_t i = 0; i < form_structure->field_count(); ++i) {
54    AutofillField* field = form_structure->field(i);
55    for (size_t j = 0; j < inputs.size(); ++j) {
56      if (compare.Run(inputs[j], *field)) {
57        FillFormField(field);
58        filled_something = true;
59        break;
60      }
61    }
62  }
63  return filled_something;
64}
65
66DataModelWrapper::DataModelWrapper() {}
67
68void DataModelWrapper::FillFormField(AutofillField* field) const {
69  field->value = GetInfo(field->Type());
70}
71
72base::string16 DataModelWrapper::GetAddressDisplayText(
73    const base::string16& separator) {
74  base::string16 address = GetInfo(AutofillType(NAME_FULL)) + separator +
75      GetInfo(AutofillType(ADDRESS_HOME_LINE1));
76  base::string16 address2 = GetInfo(AutofillType(ADDRESS_HOME_LINE2));
77  if (!address2.empty())
78    address += separator + address2;
79
80  base::string16 comma = ASCIIToUTF16(", ");
81  base::string16 newline = ASCIIToUTF16("\n");
82  address += separator +
83      GetInfo(AutofillType(ADDRESS_HOME_CITY)) + comma +
84      GetInfo(AutofillType(ADDRESS_HOME_STATE)) + ASCIIToUTF16(" ") +
85      GetInfo(AutofillType(ADDRESS_HOME_ZIP));
86
87  base::string16 email = GetInfo(AutofillType(EMAIL_ADDRESS));
88  if (!email.empty())
89    address += newline + email;
90  address += newline + GetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER));
91
92  return address;
93}
94
95// EmptyDataModelWrapper
96
97EmptyDataModelWrapper::EmptyDataModelWrapper() {}
98EmptyDataModelWrapper::~EmptyDataModelWrapper() {}
99
100base::string16 EmptyDataModelWrapper::GetInfo(const AutofillType& type) const {
101  return base::string16();
102}
103
104void EmptyDataModelWrapper::FillFormField(AutofillField* field) const {}
105
106// AutofillProfileWrapper
107
108AutofillProfileWrapper::AutofillProfileWrapper(const AutofillProfile* profile)
109    : profile_(profile),
110      variant_group_(NO_GROUP),
111      variant_(0) {}
112
113AutofillProfileWrapper::AutofillProfileWrapper(
114    const AutofillProfile* profile,
115    const AutofillType& type,
116    size_t variant)
117    : profile_(profile),
118      variant_group_(type.group()),
119      variant_(variant) {}
120
121AutofillProfileWrapper::~AutofillProfileWrapper() {}
122
123base::string16 AutofillProfileWrapper::GetInfo(const AutofillType& type)
124    const {
125  const std::string& app_locale = g_browser_process->GetApplicationLocale();
126  std::vector<base::string16> values;
127  profile_->GetMultiInfo(type, app_locale, &values);
128  return values[GetVariantForType(type)];
129}
130
131void AutofillProfileWrapper::FillFormField(AutofillField* field) const {
132  if (field->Type().GetStorableType() == CREDIT_CARD_NAME) {
133    // Cache the field's true type.
134    HtmlFieldType original_type = field->html_type();
135
136    // Requests for the user's credit card are filled from the billing address,
137    // but the AutofillProfile class doesn't know how to fill credit card
138    // fields. So, temporarily set the type to the corresponding profile type.
139    field->SetHtmlType(HTML_TYPE_NAME, field->html_mode());
140
141    profile_->FillFormField(
142        *field, GetVariantForType(field->Type()),
143        g_browser_process->GetApplicationLocale(), field);
144
145    // Restore the field's true type.
146    field->SetHtmlType(original_type, field->html_mode());
147  } else {
148    profile_->FillFormField(
149        *field, GetVariantForType(field->Type()),
150        g_browser_process->GetApplicationLocale(), field);
151  }
152}
153
154size_t AutofillProfileWrapper::GetVariantForType(const AutofillType& type)
155    const {
156  if (type.group() == variant_group_)
157    return variant_;
158
159  return 0;
160}
161
162// AutofillShippingAddressWrapper
163
164AutofillShippingAddressWrapper::AutofillShippingAddressWrapper(
165    const AutofillProfile* profile)
166    : AutofillProfileWrapper(profile) {}
167
168AutofillShippingAddressWrapper::~AutofillShippingAddressWrapper() {}
169
170base::string16 AutofillShippingAddressWrapper::GetInfo(
171    const AutofillType& type) const {
172  // Shipping addresses don't have email addresses associated with them.
173  if (type.GetStorableType() == EMAIL_ADDRESS)
174    return base::string16();
175
176  return AutofillProfileWrapper::GetInfo(type);
177}
178
179// AutofillCreditCardWrapper
180
181AutofillCreditCardWrapper::AutofillCreditCardWrapper(const CreditCard* card)
182    : card_(card) {}
183
184AutofillCreditCardWrapper::~AutofillCreditCardWrapper() {}
185
186base::string16 AutofillCreditCardWrapper::GetInfo(const AutofillType& type)
187    const {
188  if (type.group() != CREDIT_CARD)
189    return base::string16();
190
191  if (type.GetStorableType() == CREDIT_CARD_EXP_MONTH)
192    return MonthComboboxModel::FormatMonth(card_->expiration_month());
193
194  return card_->GetInfo(type, g_browser_process->GetApplicationLocale());
195}
196
197gfx::Image AutofillCreditCardWrapper::GetIcon() {
198  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
199  return rb.GetImageNamed(CreditCard::IconResourceId(card_->type()));
200}
201
202bool AutofillCreditCardWrapper::GetDisplayText(
203    base::string16* vertically_compact,
204    base::string16* horizontally_compact) {
205  if (!card_->IsValid())
206    return false;
207
208  *vertically_compact = *horizontally_compact = card_->TypeAndLastFourDigits();
209  return true;
210}
211
212void AutofillCreditCardWrapper::FillFormField(AutofillField* field) const {
213  card_->FillFormField(
214      *field, 0, g_browser_process->GetApplicationLocale(), field);
215}
216
217// WalletAddressWrapper
218
219WalletAddressWrapper::WalletAddressWrapper(
220    const wallet::Address* address) : address_(address) {}
221
222WalletAddressWrapper::~WalletAddressWrapper() {}
223
224base::string16 WalletAddressWrapper::GetInfo(const AutofillType& type) const {
225  // Reachable from DataModelWrapper::GetDisplayText().
226  if (type.GetStorableType() == EMAIL_ADDRESS)
227    return base::string16();
228
229  return address_->GetInfo(type, g_browser_process->GetApplicationLocale());
230}
231
232bool WalletAddressWrapper::GetDisplayText(
233    base::string16* vertically_compact,
234    base::string16* horizontally_compact) {
235  if (!address_->is_complete_address() ||
236      GetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER)).empty()) {
237    return false;
238  }
239
240  return DataModelWrapper::GetDisplayText(vertically_compact,
241                                          horizontally_compact);
242}
243
244// WalletInstrumentWrapper
245
246WalletInstrumentWrapper::WalletInstrumentWrapper(
247    const wallet::WalletItems::MaskedInstrument* instrument)
248    : instrument_(instrument) {}
249
250WalletInstrumentWrapper::~WalletInstrumentWrapper() {}
251
252base::string16 WalletInstrumentWrapper::GetInfo(const AutofillType& type)
253    const {
254  // Reachable from DataModelWrapper::GetDisplayText().
255  if (type.GetStorableType() == EMAIL_ADDRESS)
256    return base::string16();
257
258  if (type.GetStorableType() == CREDIT_CARD_EXP_MONTH)
259    return MonthComboboxModel::FormatMonth(instrument_->expiration_month());
260
261  return instrument_->GetInfo(type, g_browser_process->GetApplicationLocale());
262}
263
264gfx::Image WalletInstrumentWrapper::GetIcon() {
265  return instrument_->CardIcon();
266}
267
268bool WalletInstrumentWrapper::GetDisplayText(
269    base::string16* vertically_compact,
270    base::string16* horizontally_compact) {
271  // TODO(dbeam): handle other instrument statuses? http://crbug.com/233048
272  if (instrument_->status() == wallet::WalletItems::MaskedInstrument::EXPIRED ||
273      !instrument_->address().is_complete_address() ||
274      GetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER)).empty()) {
275    return false;
276  }
277
278  DataModelWrapper::GetDisplayText(vertically_compact, horizontally_compact);
279  // TODO(estade): descriptive_name() is user-provided. Should we use it or
280  // just type + last 4 digits?
281  base::string16 line1 = instrument_->descriptive_name() + ASCIIToUTF16("\n");
282  *vertically_compact = line1 + *vertically_compact;
283  *horizontally_compact = line1 + *horizontally_compact;
284  return true;
285}
286
287// FullWalletBillingWrapper
288
289FullWalletBillingWrapper::FullWalletBillingWrapper(
290    wallet::FullWallet* full_wallet)
291    : full_wallet_(full_wallet) {
292  DCHECK(full_wallet_);
293}
294
295FullWalletBillingWrapper::~FullWalletBillingWrapper() {}
296
297base::string16 FullWalletBillingWrapper::GetInfo(const AutofillType& type)
298    const {
299  if (type.GetStorableType() == CREDIT_CARD_EXP_MONTH)
300    return MonthComboboxModel::FormatMonth(full_wallet_->expiration_month());
301
302  if (type.group() == CREDIT_CARD)
303    return full_wallet_->GetInfo(type);
304
305  return full_wallet_->billing_address()->GetInfo(
306      type, g_browser_process->GetApplicationLocale());
307}
308
309bool FullWalletBillingWrapper::GetDisplayText(
310    base::string16* vertically_compact,
311    base::string16* horizontally_compact) {
312  // TODO(dbeam): handle other required actions? http://crbug.com/163508
313  if (full_wallet_->HasRequiredAction(wallet::UPDATE_EXPIRATION_DATE))
314    return false;
315
316  return DataModelWrapper::GetDisplayText(vertically_compact,
317                                          horizontally_compact);
318}
319
320// FullWalletShippingWrapper
321
322FullWalletShippingWrapper::FullWalletShippingWrapper(
323    wallet::FullWallet* full_wallet)
324    : full_wallet_(full_wallet) {
325  DCHECK(full_wallet_);
326}
327
328FullWalletShippingWrapper::~FullWalletShippingWrapper() {}
329
330base::string16 FullWalletShippingWrapper::GetInfo(
331    const AutofillType& type) const {
332  return full_wallet_->shipping_address()->GetInfo(
333      type, g_browser_process->GetApplicationLocale());
334}
335
336DetailOutputWrapper::DetailOutputWrapper(const DetailOutputMap& outputs)
337    : outputs_(outputs) {}
338
339DetailOutputWrapper::~DetailOutputWrapper() {}
340
341base::string16 DetailOutputWrapper::GetInfo(const AutofillType& type) const {
342  ServerFieldType storable_type = type.GetStorableType();
343  for (DetailOutputMap::const_iterator it = outputs_.begin();
344       it != outputs_.end(); ++it) {
345    if (storable_type == AutofillType(it->first->type).GetStorableType())
346      return it->second;
347  }
348  return base::string16();
349}
350
351}  // namespace autofill
352