data_model_wrapper.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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/address_i18n.h"
18#include "components/autofill/core/browser/autofill_country.h"
19#include "components/autofill/core/browser/autofill_data_model.h"
20#include "components/autofill/core/browser/autofill_field.h"
21#include "components/autofill/core/browser/autofill_profile.h"
22#include "components/autofill/core/browser/autofill_type.h"
23#include "components/autofill/core/browser/credit_card.h"
24#include "components/autofill/core/browser/form_structure.h"
25#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
26#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_field.h"
27#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_formatter.h"
28#include "ui/base/resource/resource_bundle.h"
29#include "ui/gfx/image/image.h"
30
31namespace autofill {
32
33DataModelWrapper::~DataModelWrapper() {}
34
35void DataModelWrapper::FillInputs(DetailInputs* inputs) {
36  for (size_t i = 0; i < inputs->size(); ++i) {
37    (*inputs)[i].initial_value =
38        GetInfoForDisplay(AutofillType((*inputs)[i].type));
39  }
40}
41
42base::string16 DataModelWrapper::GetInfoForDisplay(const AutofillType& type)
43    const {
44  return GetInfo(type);
45}
46
47gfx::Image DataModelWrapper::GetIcon() {
48  return gfx::Image();
49}
50
51bool DataModelWrapper::GetDisplayText(
52    base::string16* vertically_compact,
53    base::string16* horizontally_compact) {
54  base::string16 phone =
55      GetInfoForDisplay(AutofillType(PHONE_HOME_WHOLE_NUMBER));
56  if (phone.empty())
57    return false;
58
59  // Format the address.
60  scoped_ptr< ::i18n::addressinput::AddressData> address_data =
61      i18n::CreateAddressData(
62          base::Bind(&DataModelWrapper::GetInfo, base::Unretained(this)));
63  address_data->language_code = GetLanguageCode();
64  // Interactive autofill dialog does not display organization field.
65  address_data->organization.clear();
66  std::vector<std::string> lines;
67  ::i18n::addressinput::GetFormattedNationalAddress(*address_data, &lines);
68
69  std::string single_line;
70  ::i18n::addressinput::GetFormattedNationalAddressLine(
71       *address_data, &single_line);
72
73  // Email and phone number aren't part of address formatting.
74  base::string16 non_address_info;
75  base::string16 email = GetInfoForDisplay(AutofillType(EMAIL_ADDRESS));
76  if (!email.empty())
77    non_address_info += base::ASCIIToUTF16("\n") + email;
78
79  non_address_info += base::ASCIIToUTF16("\n") + phone;
80
81  *vertically_compact = base::UTF8ToUTF16(single_line) + non_address_info;
82  *horizontally_compact = base::UTF8ToUTF16(JoinString(lines, "\n")) +
83      non_address_info;
84
85  return true;
86}
87
88bool DataModelWrapper::FillFormStructure(
89    const std::vector<ServerFieldType>& types,
90    const FormStructure::InputFieldComparator& compare,
91    FormStructure* form_structure) const {
92  return form_structure->FillFields(
93      types,
94      compare,
95      base::Bind(&DataModelWrapper::GetInfo, base::Unretained(this)),
96      GetLanguageCode(),
97      g_browser_process->GetApplicationLocale());
98}
99
100DataModelWrapper::DataModelWrapper() {}
101
102// AutofillProfileWrapper
103
104AutofillProfileWrapper::AutofillProfileWrapper(const AutofillProfile* profile)
105    : profile_(profile),
106      variant_group_(NO_GROUP),
107      variant_(0) {}
108
109AutofillProfileWrapper::AutofillProfileWrapper(
110    const AutofillProfile* profile,
111    const AutofillType& type,
112    size_t variant)
113    : profile_(profile),
114      variant_group_(type.group()),
115      variant_(variant) {}
116
117AutofillProfileWrapper::~AutofillProfileWrapper() {}
118
119base::string16 AutofillProfileWrapper::GetInfo(const AutofillType& type) const {
120  // Requests for the user's credit card are filled from the billing address,
121  // but the AutofillProfile class doesn't know how to fill credit card
122  // fields. So, request for the corresponding profile type instead.
123  AutofillType effective_type = type;
124  if (type.GetStorableType() == CREDIT_CARD_NAME)
125    effective_type = AutofillType(NAME_BILLING_FULL);
126
127  size_t variant = GetVariantForType(effective_type);
128  const std::string& app_locale = g_browser_process->GetApplicationLocale();
129  return profile_->GetInfoForVariant(effective_type, variant, app_locale);
130}
131
132base::string16 AutofillProfileWrapper::GetInfoForDisplay(
133    const AutofillType& type) const {
134  // We display the "raw" phone number which contains user-defined formatting.
135  if (type.GetStorableType() == PHONE_HOME_WHOLE_NUMBER) {
136    std::vector<base::string16> values;
137    profile_->GetRawMultiInfo(type.GetStorableType(), &values);
138    const base::string16& phone_number = values[GetVariantForType(type)];
139
140    // If there is no user-defined formatting at all, add some standard
141    // formatting.
142    if (base::ContainsOnlyChars(phone_number,
143                                base::ASCIIToUTF16("+0123456789"))) {
144      std::string region = base::UTF16ToASCII(
145          GetInfo(AutofillType(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE)));
146      i18n::PhoneObject phone(phone_number, region);
147      base::string16 formatted_number = phone.GetFormattedNumber();
148      // Formatting may fail.
149      if (!formatted_number.empty())
150        return formatted_number;
151    }
152
153    return phone_number;
154  }
155
156  return DataModelWrapper::GetInfoForDisplay(type);
157}
158
159const std::string& AutofillProfileWrapper::GetLanguageCode() const {
160  return profile_->language_code();
161}
162
163size_t AutofillProfileWrapper::GetVariantForType(const AutofillType& type)
164    const {
165  if (type.group() == variant_group_)
166    return variant_;
167
168  return 0;
169}
170
171// AutofillShippingAddressWrapper
172
173AutofillShippingAddressWrapper::AutofillShippingAddressWrapper(
174    const AutofillProfile* profile)
175    : AutofillProfileWrapper(profile) {}
176
177AutofillShippingAddressWrapper::~AutofillShippingAddressWrapper() {}
178
179base::string16 AutofillShippingAddressWrapper::GetInfo(
180    const AutofillType& type) const {
181  // Shipping addresses don't have email addresses associated with them.
182  if (type.GetStorableType() == EMAIL_ADDRESS)
183    return base::string16();
184
185  return AutofillProfileWrapper::GetInfo(type);
186}
187
188// AutofillCreditCardWrapper
189
190AutofillCreditCardWrapper::AutofillCreditCardWrapper(const CreditCard* card)
191    : card_(card) {}
192
193AutofillCreditCardWrapper::~AutofillCreditCardWrapper() {}
194
195base::string16 AutofillCreditCardWrapper::GetInfo(const AutofillType& type)
196    const {
197  if (type.group() != CREDIT_CARD)
198    return base::string16();
199
200  if (type.GetStorableType() == CREDIT_CARD_EXP_MONTH)
201    return MonthComboboxModel::FormatMonth(card_->expiration_month());
202
203  return card_->GetInfo(type, g_browser_process->GetApplicationLocale());
204}
205
206gfx::Image AutofillCreditCardWrapper::GetIcon() {
207  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
208  return rb.GetImageNamed(CreditCard::IconResourceId(card_->type()));
209}
210
211bool AutofillCreditCardWrapper::GetDisplayText(
212    base::string16* vertically_compact,
213    base::string16* horizontally_compact) {
214  if (!card_->IsValid())
215    return false;
216
217  *vertically_compact = *horizontally_compact = card_->TypeAndLastFourDigits();
218  return true;
219}
220
221const std::string& AutofillCreditCardWrapper::GetLanguageCode() const {
222  // Formatting a credit card for display does not depend on language code.
223  return base::EmptyString();
224}
225
226// WalletAddressWrapper
227
228WalletAddressWrapper::WalletAddressWrapper(
229    const wallet::Address* address) : address_(address) {}
230
231WalletAddressWrapper::~WalletAddressWrapper() {}
232
233base::string16 WalletAddressWrapper::GetInfo(const AutofillType& type) const {
234  // Reachable from DataModelWrapper::GetDisplayText().
235  if (type.GetStorableType() == EMAIL_ADDRESS)
236    return base::string16();
237
238  return address_->GetInfo(type, g_browser_process->GetApplicationLocale());
239}
240
241base::string16 WalletAddressWrapper::GetInfoForDisplay(const AutofillType& type)
242    const {
243  if (type.GetStorableType() == PHONE_HOME_WHOLE_NUMBER)
244    return address_->DisplayPhoneNumber();
245
246  return DataModelWrapper::GetInfoForDisplay(type);
247}
248
249bool WalletAddressWrapper::GetDisplayText(
250    base::string16* vertically_compact,
251    base::string16* horizontally_compact) {
252  if (!address_->is_complete_address())
253    return false;
254
255  return DataModelWrapper::GetDisplayText(vertically_compact,
256                                          horizontally_compact);
257}
258
259const std::string& WalletAddressWrapper::GetLanguageCode() const {
260  return address_->language_code();
261}
262
263// WalletInstrumentWrapper
264
265WalletInstrumentWrapper::WalletInstrumentWrapper(
266    const wallet::WalletItems::MaskedInstrument* instrument)
267    : instrument_(instrument) {}
268
269WalletInstrumentWrapper::~WalletInstrumentWrapper() {}
270
271base::string16 WalletInstrumentWrapper::GetInfo(const AutofillType& type)
272    const {
273  // Reachable from DataModelWrapper::GetDisplayText().
274  if (type.GetStorableType() == EMAIL_ADDRESS)
275    return base::string16();
276
277  if (type.GetStorableType() == CREDIT_CARD_EXP_MONTH)
278    return MonthComboboxModel::FormatMonth(instrument_->expiration_month());
279
280  return instrument_->GetInfo(type, g_browser_process->GetApplicationLocale());
281}
282
283base::string16 WalletInstrumentWrapper::GetInfoForDisplay(
284    const AutofillType& type) const {
285  if (type.GetStorableType() == PHONE_HOME_WHOLE_NUMBER)
286    return instrument_->address().DisplayPhoneNumber();
287
288  return DataModelWrapper::GetInfoForDisplay(type);
289}
290
291gfx::Image WalletInstrumentWrapper::GetIcon() {
292  return instrument_->CardIcon();
293}
294
295bool WalletInstrumentWrapper::GetDisplayText(
296    base::string16* vertically_compact,
297    base::string16* horizontally_compact) {
298  // TODO(dbeam): handle other instrument statuses? http://crbug.com/233048
299  if (instrument_->status() == wallet::WalletItems::MaskedInstrument::EXPIRED ||
300      !instrument_->address().is_complete_address()) {
301    return false;
302  }
303
304  if (!DataModelWrapper::GetDisplayText(vertically_compact,
305                                        horizontally_compact)) {
306    return false;
307  }
308
309  // TODO(estade): descriptive_name() is user-provided. Should we use it or
310  // just type + last 4 digits?
311  base::string16 line1 =
312      instrument_->descriptive_name() + base::ASCIIToUTF16("\n");
313  *vertically_compact = line1 + *vertically_compact;
314  *horizontally_compact = line1 + *horizontally_compact;
315  return true;
316}
317
318const std::string& WalletInstrumentWrapper::GetLanguageCode() const {
319  return instrument_->address().language_code();
320}
321
322// FullWalletBillingWrapper
323
324FullWalletBillingWrapper::FullWalletBillingWrapper(
325    wallet::FullWallet* full_wallet)
326    : full_wallet_(full_wallet) {
327  DCHECK(full_wallet_);
328}
329
330FullWalletBillingWrapper::~FullWalletBillingWrapper() {}
331
332base::string16 FullWalletBillingWrapper::GetInfo(const AutofillType& type)
333    const {
334  return full_wallet_->GetInfo(g_browser_process->GetApplicationLocale(), type);
335}
336
337bool FullWalletBillingWrapper::GetDisplayText(
338    base::string16* vertically_compact,
339    base::string16* horizontally_compact) {
340  // TODO(dbeam): handle other required actions? http://crbug.com/163508
341  if (full_wallet_->HasRequiredAction(wallet::UPDATE_EXPIRATION_DATE))
342    return false;
343
344  return DataModelWrapper::GetDisplayText(vertically_compact,
345                                          horizontally_compact);
346}
347
348const std::string& FullWalletBillingWrapper::GetLanguageCode() const {
349  // Can be NULL if there are required actions.
350  return full_wallet_->billing_address() ?
351      full_wallet_->billing_address()->language_code() : base::EmptyString();
352}
353
354// FullWalletShippingWrapper
355
356FullWalletShippingWrapper::FullWalletShippingWrapper(
357    wallet::FullWallet* full_wallet)
358    : full_wallet_(full_wallet) {
359  DCHECK(full_wallet_);
360}
361
362FullWalletShippingWrapper::~FullWalletShippingWrapper() {}
363
364base::string16 FullWalletShippingWrapper::GetInfo(
365    const AutofillType& type) const {
366  return full_wallet_->shipping_address()->GetInfo(
367      type, g_browser_process->GetApplicationLocale());
368}
369
370const std::string& FullWalletShippingWrapper::GetLanguageCode() const {
371  // Can be NULL if there are required actions or shipping address is not
372  // required.
373  return full_wallet_->shipping_address() ?
374      full_wallet_->shipping_address()->language_code() : base::EmptyString();
375}
376
377// I18nAddressDataWrapper
378
379I18nAddressDataWrapper::I18nAddressDataWrapper(
380    const ::i18n::addressinput::AddressData* address)
381    : address_(address) {}
382
383I18nAddressDataWrapper::~I18nAddressDataWrapper() {}
384
385base::string16 I18nAddressDataWrapper::GetInfo(const AutofillType& type) const {
386  ::i18n::addressinput::AddressField field;
387  if (!i18n::FieldForType(type.GetStorableType(), &field))
388    return base::string16();
389
390  if (field == ::i18n::addressinput::STREET_ADDRESS)
391    return base::string16();
392
393  if (field == ::i18n::addressinput::COUNTRY) {
394    return AutofillCountry(address_->region_code,
395                           g_browser_process->GetApplicationLocale()).name();
396  }
397
398  return base::UTF8ToUTF16(address_->GetFieldValue(field));
399}
400
401const std::string& I18nAddressDataWrapper::GetLanguageCode() const {
402  return address_->language_code;
403}
404
405}  // namespace autofill
406