data_model_wrapper.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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
27gfx::Image DataModelWrapper::GetIcon() {
28  return gfx::Image();
29}
30
31void DataModelWrapper::FillInputs(DetailInputs* inputs) {
32  for (size_t i = 0; i < inputs->size(); ++i) {
33    (*inputs)[i].initial_value = GetInfo(AutofillType((*inputs)[i].type));
34  }
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// AutofillDataModelWrapper
107
108AutofillDataModelWrapper::AutofillDataModelWrapper(
109    const AutofillDataModel* data_model,
110    size_t variant)
111    : data_model_(data_model),
112      variant_(variant) {}
113
114AutofillDataModelWrapper::~AutofillDataModelWrapper() {}
115
116base::string16 AutofillDataModelWrapper::GetInfo(const AutofillType& type)
117    const {
118  return data_model_->GetInfo(type, g_browser_process->GetApplicationLocale());
119}
120
121void AutofillDataModelWrapper::FillFormField(AutofillField* field) const {
122  data_model_->FillFormField(
123      *field, variant_, g_browser_process->GetApplicationLocale(), field);
124}
125
126// AutofillProfileWrapper
127
128AutofillProfileWrapper::AutofillProfileWrapper(
129    const AutofillProfile* profile, size_t variant)
130    : AutofillDataModelWrapper(profile, variant),
131      profile_(profile) {}
132
133AutofillProfileWrapper::~AutofillProfileWrapper() {}
134
135void AutofillProfileWrapper::FillInputs(DetailInputs* inputs) {
136  const std::string app_locale = g_browser_process->GetApplicationLocale();
137  for (size_t j = 0; j < inputs->size(); ++j) {
138    std::vector<base::string16> values;
139    profile_->GetMultiInfo(
140        AutofillType((*inputs)[j].type), app_locale, &values);
141    (*inputs)[j].initial_value = values[variant()];
142  }
143}
144
145void AutofillProfileWrapper::FillFormField(AutofillField* field) const {
146  if (field->Type().GetStorableType() == CREDIT_CARD_NAME) {
147    // Cache the field's true type.
148    HtmlFieldType original_type = field->html_type();
149
150    // Requests for the user's credit card are filled from the billing address,
151    // but the AutofillProfile class doesn't know how to fill credit card
152    // fields. So, temporarily set the type to the corresponding profile type.
153    field->SetHtmlType(HTML_TYPE_NAME, field->html_mode());
154    AutofillDataModelWrapper::FillFormField(field);
155
156    // Restore the field's true type.
157    field->SetHtmlType(original_type, field->html_mode());
158  } else {
159    AutofillDataModelWrapper::FillFormField(field);
160  }
161}
162
163AutofillShippingAddressWrapper::AutofillShippingAddressWrapper(
164    const AutofillProfile* profile, size_t variant)
165    : AutofillProfileWrapper(profile, variant) {}
166
167AutofillShippingAddressWrapper::~AutofillShippingAddressWrapper() {}
168
169base::string16 AutofillShippingAddressWrapper::GetInfo(
170    const AutofillType& type) const {
171  // Shipping addresses don't have email addresses associated with them.
172  if (type.GetStorableType() == EMAIL_ADDRESS)
173    return base::string16();
174
175  return AutofillProfileWrapper::GetInfo(type);
176}
177
178// AutofillCreditCardWrapper
179
180AutofillCreditCardWrapper::AutofillCreditCardWrapper(const CreditCard* card)
181    : AutofillDataModelWrapper(card, 0),
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 AutofillDataModelWrapper::GetInfo(type);
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
212// WalletAddressWrapper
213
214WalletAddressWrapper::WalletAddressWrapper(
215    const wallet::Address* address) : address_(address) {}
216
217WalletAddressWrapper::~WalletAddressWrapper() {}
218
219base::string16 WalletAddressWrapper::GetInfo(const AutofillType& type) const {
220  // Reachable from DataModelWrapper::GetDisplayText().
221  if (type.GetStorableType() == EMAIL_ADDRESS)
222    return base::string16();
223
224  return address_->GetInfo(type, g_browser_process->GetApplicationLocale());
225}
226
227bool WalletAddressWrapper::GetDisplayText(
228    base::string16* vertically_compact,
229    base::string16* horizontally_compact) {
230  if (!address_->is_complete_address() ||
231      GetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER)).empty()) {
232    return false;
233  }
234
235  return DataModelWrapper::GetDisplayText(vertically_compact,
236                                          horizontally_compact);
237}
238
239// WalletInstrumentWrapper
240
241WalletInstrumentWrapper::WalletInstrumentWrapper(
242    const wallet::WalletItems::MaskedInstrument* instrument)
243    : instrument_(instrument) {}
244
245WalletInstrumentWrapper::~WalletInstrumentWrapper() {}
246
247base::string16 WalletInstrumentWrapper::GetInfo(const AutofillType& type)
248    const {
249  // Reachable from DataModelWrapper::GetDisplayText().
250  if (type.GetStorableType() == EMAIL_ADDRESS)
251    return base::string16();
252
253  if (type.GetStorableType() == CREDIT_CARD_EXP_MONTH)
254    return MonthComboboxModel::FormatMonth(instrument_->expiration_month());
255
256  return instrument_->GetInfo(type, g_browser_process->GetApplicationLocale());
257}
258
259gfx::Image WalletInstrumentWrapper::GetIcon() {
260  return instrument_->CardIcon();
261}
262
263bool WalletInstrumentWrapper::GetDisplayText(
264    base::string16* vertically_compact,
265    base::string16* horizontally_compact) {
266  // TODO(dbeam): handle other instrument statuses? http://crbug.com/233048
267  if (instrument_->status() == wallet::WalletItems::MaskedInstrument::EXPIRED ||
268      !instrument_->address().is_complete_address() ||
269      GetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER)).empty()) {
270    return false;
271  }
272
273  DataModelWrapper::GetDisplayText(vertically_compact, horizontally_compact);
274  // TODO(estade): descriptive_name() is user-provided. Should we use it or
275  // just type + last 4 digits?
276  base::string16 line1 = instrument_->descriptive_name() + ASCIIToUTF16("\n");
277  *vertically_compact = line1 + *vertically_compact;
278  *horizontally_compact = line1 + *horizontally_compact;
279  return true;
280}
281
282// FullWalletBillingWrapper
283
284FullWalletBillingWrapper::FullWalletBillingWrapper(
285    wallet::FullWallet* full_wallet)
286    : full_wallet_(full_wallet) {
287  DCHECK(full_wallet_);
288}
289
290FullWalletBillingWrapper::~FullWalletBillingWrapper() {}
291
292base::string16 FullWalletBillingWrapper::GetInfo(const AutofillType& type)
293    const {
294  if (type.GetStorableType() == CREDIT_CARD_EXP_MONTH)
295    return MonthComboboxModel::FormatMonth(full_wallet_->expiration_month());
296
297  if (type.group() == CREDIT_CARD)
298    return full_wallet_->GetInfo(type);
299
300  return full_wallet_->billing_address()->GetInfo(
301      type, g_browser_process->GetApplicationLocale());
302}
303
304bool FullWalletBillingWrapper::GetDisplayText(
305    base::string16* vertically_compact,
306    base::string16* horizontally_compact) {
307  // TODO(dbeam): handle other required actions? http://crbug.com/163508
308  if (full_wallet_->HasRequiredAction(wallet::UPDATE_EXPIRATION_DATE))
309    return false;
310
311  return DataModelWrapper::GetDisplayText(vertically_compact,
312                                          horizontally_compact);
313}
314
315// FullWalletShippingWrapper
316
317FullWalletShippingWrapper::FullWalletShippingWrapper(
318    wallet::FullWallet* full_wallet)
319    : full_wallet_(full_wallet) {
320  DCHECK(full_wallet_);
321}
322
323FullWalletShippingWrapper::~FullWalletShippingWrapper() {}
324
325base::string16 FullWalletShippingWrapper::GetInfo(
326    const AutofillType& type) const {
327  return full_wallet_->shipping_address()->GetInfo(
328      type, g_browser_process->GetApplicationLocale());
329}
330
331DetailOutputWrapper::DetailOutputWrapper(const DetailOutputMap& outputs)
332    : outputs_(outputs) {}
333
334DetailOutputWrapper::~DetailOutputWrapper() {}
335
336base::string16 DetailOutputWrapper::GetInfo(const AutofillType& type) const {
337  ServerFieldType storable_type = type.GetStorableType();
338  for (DetailOutputMap::const_iterator it = outputs_.begin();
339       it != outputs_.end(); ++it) {
340    if (storable_type == AutofillType(it->first->type).GetStorableType())
341      return it->second;
342  }
343  return base::string16();
344}
345
346}  // namespace autofill
347