data_model_wrapper.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
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/bind.h"
8#include "base/callback.h"
9#include "base/strings/string_util.h"
10#include "base/strings/utf_string_conversions.h"
11#include "chrome/browser/browser_process.h"
12#include "chrome/browser/ui/autofill/autofill_dialog_i18n_input.h"
13#include "chrome/browser/ui/autofill/autofill_dialog_models.h"
14#include "components/autofill/content/browser/wallet/full_wallet.h"
15#include "components/autofill/content/browser/wallet/wallet_address.h"
16#include "components/autofill/content/browser/wallet/wallet_items.h"
17#include "components/autofill/core/browser/autofill_country.h"
18#include "components/autofill/core/browser/autofill_data_model.h"
19#include "components/autofill/core/browser/autofill_field.h"
20#include "components/autofill/core/browser/autofill_profile.h"
21#include "components/autofill/core/browser/autofill_type.h"
22#include "components/autofill/core/browser/credit_card.h"
23#include "components/autofill/core/browser/form_structure.h"
24#include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_data.h"
25#include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_ui.h"
26#include "ui/base/resource/resource_bundle.h"
27#include "ui/gfx/image/image.h"
28
29namespace autofill {
30
31DataModelWrapper::~DataModelWrapper() {}
32
33void DataModelWrapper::FillInputs(DetailInputs* inputs) {
34  for (size_t i = 0; i < inputs->size(); ++i) {
35    (*inputs)[i].initial_value =
36        GetInfoForDisplay(AutofillType((*inputs)[i].type));
37  }
38}
39
40base::string16 DataModelWrapper::GetInfoForDisplay(const AutofillType& type)
41    const {
42  return GetInfo(type);
43}
44
45gfx::Image DataModelWrapper::GetIcon() {
46  return gfx::Image();
47}
48
49bool DataModelWrapper::GetDisplayText(
50    base::string16* vertically_compact,
51    base::string16* horizontally_compact) {
52  base::string16 phone =
53      GetInfoForDisplay(AutofillType(PHONE_HOME_WHOLE_NUMBER));
54  if (phone.empty())
55    return false;
56
57  // Format the address.
58  ::i18n::addressinput::AddressData address_data;
59  i18ninput::CreateAddressData(
60      base::Bind(&DataModelWrapper::GetInfo, base::Unretained(this)),
61      &address_data);
62  std::vector<std::string> lines;
63  address_data.FormatForDisplay(&lines);
64
65  // Email and phone number aren't part of address formatting.
66  base::string16 non_address_info;
67  base::string16 email = GetInfoForDisplay(AutofillType(EMAIL_ADDRESS));
68  if (!email.empty())
69    non_address_info += base::ASCIIToUTF16("\n") + email;
70
71  non_address_info += base::ASCIIToUTF16("\n") + phone;
72
73  // The separator is locale-specific.
74  std::string compact_separator =
75      ::i18n::addressinput::GetCompactAddressLinesSeparator(
76          g_browser_process->GetApplicationLocale());
77  *vertically_compact =
78      base::UTF8ToUTF16(JoinString(lines, compact_separator)) +
79          non_address_info;
80  *horizontally_compact = base::UTF8ToUTF16(JoinString(lines, "\n")) +
81      non_address_info;
82
83  return true;
84}
85
86bool DataModelWrapper::FillFormStructure(
87    const std::vector<ServerFieldType>& types,
88    const FormStructure::InputFieldComparator& compare,
89    FormStructure* form_structure) const {
90  return form_structure->FillFields(
91      types,
92      compare,
93      base::Bind(&DataModelWrapper::GetInfo, base::Unretained(this)),
94      g_browser_process->GetApplicationLocale());
95}
96
97DataModelWrapper::DataModelWrapper() {}
98
99// AutofillProfileWrapper
100
101AutofillProfileWrapper::AutofillProfileWrapper(const AutofillProfile* profile)
102    : profile_(profile),
103      variant_group_(NO_GROUP),
104      variant_(0) {}
105
106AutofillProfileWrapper::AutofillProfileWrapper(
107    const AutofillProfile* profile,
108    const AutofillType& type,
109    size_t variant)
110    : profile_(profile),
111      variant_group_(type.group()),
112      variant_(variant) {}
113
114AutofillProfileWrapper::~AutofillProfileWrapper() {}
115
116base::string16 AutofillProfileWrapper::GetInfo(const AutofillType& type) const {
117  // Requests for the user's credit card are filled from the billing address,
118  // but the AutofillProfile class doesn't know how to fill credit card
119  // fields. So, request for the corresponding profile type instead.
120  AutofillType effective_type = type;
121  if (type.GetStorableType() == CREDIT_CARD_NAME)
122    effective_type = AutofillType(NAME_BILLING_FULL);
123
124  size_t variant = GetVariantForType(effective_type);
125  const std::string& app_locale = g_browser_process->GetApplicationLocale();
126  return profile_->GetInfoForVariant(effective_type, variant, app_locale);
127}
128
129base::string16 AutofillProfileWrapper::GetInfoForDisplay(
130    const AutofillType& type) const {
131  // We display the "raw" phone number which contains user-defined formatting.
132  if (type.GetStorableType() == PHONE_HOME_WHOLE_NUMBER) {
133    std::vector<base::string16> values;
134    profile_->GetRawMultiInfo(type.GetStorableType(), &values);
135    const base::string16& phone_number = values[GetVariantForType(type)];
136
137    // If there is no user-defined formatting at all, add some standard
138    // formatting.
139    if (base::ContainsOnlyChars(phone_number,
140                                base::ASCIIToUTF16("0123456789"))) {
141      std::string region = base::UTF16ToASCII(
142          GetInfo(AutofillType(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE)));
143      i18n::PhoneObject phone(phone_number, region);
144      return phone.GetFormattedNumber();
145    }
146
147    return phone_number;
148  }
149
150  return DataModelWrapper::GetInfoForDisplay(type);
151}
152
153size_t AutofillProfileWrapper::GetVariantForType(const AutofillType& type)
154    const {
155  if (type.group() == variant_group_)
156    return variant_;
157
158  return 0;
159}
160
161// AutofillShippingAddressWrapper
162
163AutofillShippingAddressWrapper::AutofillShippingAddressWrapper(
164    const AutofillProfile* profile)
165    : AutofillProfileWrapper(profile) {}
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    : card_(card) {}
182
183AutofillCreditCardWrapper::~AutofillCreditCardWrapper() {}
184
185base::string16 AutofillCreditCardWrapper::GetInfo(const AutofillType& type)
186    const {
187  if (type.group() != CREDIT_CARD)
188    return base::string16();
189
190  if (type.GetStorableType() == CREDIT_CARD_EXP_MONTH)
191    return MonthComboboxModel::FormatMonth(card_->expiration_month());
192
193  return card_->GetInfo(type, g_browser_process->GetApplicationLocale());
194}
195
196gfx::Image AutofillCreditCardWrapper::GetIcon() {
197  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
198  return rb.GetImageNamed(CreditCard::IconResourceId(card_->type()));
199}
200
201bool AutofillCreditCardWrapper::GetDisplayText(
202    base::string16* vertically_compact,
203    base::string16* horizontally_compact) {
204  if (!card_->IsValid())
205    return false;
206
207  *vertically_compact = *horizontally_compact = card_->TypeAndLastFourDigits();
208  return true;
209}
210
211// WalletAddressWrapper
212
213WalletAddressWrapper::WalletAddressWrapper(
214    const wallet::Address* address) : address_(address) {}
215
216WalletAddressWrapper::~WalletAddressWrapper() {}
217
218base::string16 WalletAddressWrapper::GetInfo(const AutofillType& type) const {
219  // Reachable from DataModelWrapper::GetDisplayText().
220  if (type.GetStorableType() == EMAIL_ADDRESS)
221    return base::string16();
222
223  return address_->GetInfo(type, g_browser_process->GetApplicationLocale());
224}
225
226base::string16 WalletAddressWrapper::GetInfoForDisplay(const AutofillType& type)
227    const {
228  if (type.GetStorableType() == PHONE_HOME_WHOLE_NUMBER)
229    return address_->DisplayPhoneNumber();
230
231  return DataModelWrapper::GetInfoForDisplay(type);
232}
233
234bool WalletAddressWrapper::GetDisplayText(
235    base::string16* vertically_compact,
236    base::string16* horizontally_compact) {
237  if (!address_->is_complete_address())
238    return false;
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
264base::string16 WalletInstrumentWrapper::GetInfoForDisplay(
265    const AutofillType& type) const {
266  if (type.GetStorableType() == PHONE_HOME_WHOLE_NUMBER)
267    return instrument_->address().DisplayPhoneNumber();
268
269  return DataModelWrapper::GetInfoForDisplay(type);
270}
271
272gfx::Image WalletInstrumentWrapper::GetIcon() {
273  return instrument_->CardIcon();
274}
275
276bool WalletInstrumentWrapper::GetDisplayText(
277    base::string16* vertically_compact,
278    base::string16* horizontally_compact) {
279  // TODO(dbeam): handle other instrument statuses? http://crbug.com/233048
280  if (instrument_->status() == wallet::WalletItems::MaskedInstrument::EXPIRED ||
281      !instrument_->address().is_complete_address()) {
282    return false;
283  }
284
285  if (!DataModelWrapper::GetDisplayText(vertically_compact,
286                                        horizontally_compact)) {
287    return false;
288  }
289
290  // TODO(estade): descriptive_name() is user-provided. Should we use it or
291  // just type + last 4 digits?
292  base::string16 line1 =
293      instrument_->descriptive_name() + base::ASCIIToUTF16("\n");
294  *vertically_compact = line1 + *vertically_compact;
295  *horizontally_compact = line1 + *horizontally_compact;
296  return true;
297}
298
299// FullWalletBillingWrapper
300
301FullWalletBillingWrapper::FullWalletBillingWrapper(
302    wallet::FullWallet* full_wallet)
303    : full_wallet_(full_wallet) {
304  DCHECK(full_wallet_);
305}
306
307FullWalletBillingWrapper::~FullWalletBillingWrapper() {}
308
309base::string16 FullWalletBillingWrapper::GetInfo(const AutofillType& type)
310    const {
311  return full_wallet_->GetInfo(
312      g_browser_process->GetApplicationLocale(),
313      AutofillType(AutofillType::GetEquivalentBillingFieldType(
314          type.GetStorableType())));
315}
316
317bool FullWalletBillingWrapper::GetDisplayText(
318    base::string16* vertically_compact,
319    base::string16* horizontally_compact) {
320  // TODO(dbeam): handle other required actions? http://crbug.com/163508
321  if (full_wallet_->HasRequiredAction(wallet::UPDATE_EXPIRATION_DATE))
322    return false;
323
324  return DataModelWrapper::GetDisplayText(vertically_compact,
325                                          horizontally_compact);
326}
327
328// FullWalletShippingWrapper
329
330FullWalletShippingWrapper::FullWalletShippingWrapper(
331    wallet::FullWallet* full_wallet)
332    : full_wallet_(full_wallet) {
333  DCHECK(full_wallet_);
334}
335
336FullWalletShippingWrapper::~FullWalletShippingWrapper() {}
337
338base::string16 FullWalletShippingWrapper::GetInfo(
339    const AutofillType& type) const {
340  return full_wallet_->shipping_address()->GetInfo(
341      type, g_browser_process->GetApplicationLocale());
342}
343
344I18nAddressDataWrapper::I18nAddressDataWrapper(
345    const ::i18n::addressinput::AddressData* address)
346    : address_(address) {}
347
348I18nAddressDataWrapper::~I18nAddressDataWrapper() {}
349
350base::string16 I18nAddressDataWrapper::GetInfo(const AutofillType& type) const {
351  ::i18n::addressinput::AddressField field;
352  if (!i18ninput::FieldForType(type.GetStorableType(), &field))
353    return base::string16();
354
355  if (field == ::i18n::addressinput::STREET_ADDRESS)
356    return base::string16();
357
358  if (field == ::i18n::addressinput::COUNTRY) {
359    return AutofillCountry(address_->country_code,
360                           g_browser_process->GetApplicationLocale()).name();
361  }
362
363  return base::UTF8ToUTF16(address_->GetFieldValue(field));
364}
365
366}  // namespace autofill
367