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/account_chooser_model.h"
6
7#include "base/bind.h"
8#include "base/prefs/pref_service.h"
9#include "base/strings/string_number_conversions.h"
10#include "base/strings/stringprintf.h"
11#include "base/strings/utf_string_conversions.h"
12#include "base/time/time.h"
13#include "chrome/browser/profiles/profile.h"
14#include "chrome/common/pref_names.h"
15#include "chrome/grit/generated_resources.h"
16#include "components/autofill/core/browser/autofill_metrics.h"
17#include "ui/base/l10n/l10n_util.h"
18
19namespace autofill {
20
21const int AccountChooserModel::kWalletAddAccountId = 0;
22const int AccountChooserModel::kAutofillItemId = 1;
23const int AccountChooserModel::kWalletAccountsStartId = 2;
24
25AccountChooserModelDelegate::~AccountChooserModelDelegate() {}
26
27AccountChooserModel::AccountChooserModel(
28    AccountChooserModelDelegate* delegate,
29    Profile* profile,
30    bool disable_wallet,
31    const AutofillMetrics& metric_logger)
32    : ui::SimpleMenuModel(this),
33      delegate_(delegate),
34      checked_item_(kWalletAccountsStartId),
35      had_wallet_error_(false),
36      metric_logger_(metric_logger) {
37  if (profile->GetPrefs()->GetBoolean(
38          ::prefs::kAutofillDialogPayWithoutWallet) ||
39      profile->IsOffTheRecord() ||
40      disable_wallet) {
41    checked_item_ = kAutofillItemId;
42  }
43
44  ReconstructMenuItems();
45}
46
47AccountChooserModel::~AccountChooserModel() {}
48
49void AccountChooserModel::SelectWalletAccount(size_t user_index) {
50  DCHECK(user_index == 0U || user_index < wallet_accounts_.size());
51  checked_item_ = kWalletAccountsStartId + user_index;
52}
53
54void AccountChooserModel::SelectUseAutofill() {
55  checked_item_ = kAutofillItemId;
56}
57
58bool AccountChooserModel::HasAccountsToChoose() const {
59  return !wallet_accounts_.empty();
60}
61
62void AccountChooserModel::SetWalletAccounts(
63    const std::vector<std::string>& accounts,
64    size_t active_index) {
65  wallet_accounts_ = accounts;
66  SelectWalletAccount(active_index);
67
68  ReconstructMenuItems();
69  delegate_->UpdateAccountChooserView();
70}
71
72void AccountChooserModel::ClearWalletAccounts() {
73  wallet_accounts_.clear();
74  if (WalletIsSelected())
75    checked_item_ = kWalletAccountsStartId;
76
77  ReconstructMenuItems();
78  delegate_->UpdateAccountChooserView();
79}
80
81base::string16 AccountChooserModel::GetActiveWalletAccountName() const {
82  if (wallet_accounts_.empty())
83    return base::string16();
84
85  return base::UTF8ToUTF16(wallet_accounts_[GetActiveWalletAccountIndex()]);
86}
87
88size_t AccountChooserModel::GetActiveWalletAccountIndex() const {
89  if (!WalletIsSelected())
90    return 0;
91
92  return checked_item_ - kWalletAccountsStartId;
93}
94
95bool AccountChooserModel::IsCommandIdChecked(int command_id) const {
96  return command_id == checked_item_;
97}
98
99bool AccountChooserModel::IsCommandIdEnabled(int command_id) const {
100  // Currently, _any_ (non-sign-in) error disables _all_ Wallet accounts.
101  if (command_id != kAutofillItemId && had_wallet_error_)
102    return false;
103
104  return true;
105}
106
107bool AccountChooserModel::GetAcceleratorForCommandId(
108    int command_id,
109    ui::Accelerator* accelerator) {
110  return false;
111}
112
113void AccountChooserModel::ExecuteCommand(int command_id, int event_flags) {
114  if (checked_item_ == command_id)
115    return;
116
117  // Log metrics.
118  AutofillMetrics::DialogUiEvent chooser_event;
119  if (command_id == kAutofillItemId) {
120    chooser_event =
121        AutofillMetrics::DIALOG_UI_ACCOUNT_CHOOSER_SWITCHED_TO_AUTOFILL;
122  } else if (command_id == kWalletAddAccountId) {
123    chooser_event =
124        AutofillMetrics::DIALOG_UI_ACCOUNT_CHOOSER_TRIED_TO_ADD_ACCOUNT;
125  } else if (checked_item_ == kAutofillItemId) {
126    chooser_event =
127        AutofillMetrics::DIALOG_UI_ACCOUNT_CHOOSER_SWITCHED_TO_WALLET;
128  } else {
129    chooser_event =
130        AutofillMetrics::DIALOG_UI_ACCOUNT_CHOOSER_SWITCHED_WALLET_ACCOUNT;
131  }
132  metric_logger_.LogDialogUiEvent(chooser_event);
133
134  DoAccountSwitch(command_id);
135}
136
137void AccountChooserModel::SetHadWalletError() {
138  // Any non-sign-in error disables all Wallet accounts.
139  had_wallet_error_ = true;
140  ClearWalletAccounts();
141  DoAccountSwitch(kAutofillItemId);
142}
143
144void AccountChooserModel::SetHadWalletSigninError() {
145  ClearWalletAccounts();
146  DoAccountSwitch(kAutofillItemId);
147}
148
149bool AccountChooserModel::WalletIsSelected() const {
150  return checked_item_ != kAutofillItemId;
151}
152
153void AccountChooserModel::ReconstructMenuItems() {
154  Clear();
155
156  if (!wallet_accounts_.empty()) {
157    for (size_t i = 0; i < wallet_accounts_.size(); ++i) {
158      int item_id = kWalletAccountsStartId + i;
159      AddCheckItem(item_id, base::UTF8ToUTF16(wallet_accounts_[i]));
160    }
161  } else if (checked_item_ == kWalletAccountsStartId) {
162    // A selected active Wallet account without account names means
163    // that the sign-in attempt is in progress.
164    AddCheckItem(kWalletAccountsStartId,
165                 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_GOOGLE_WALLET));
166  }
167
168  AddCheckItemWithStringId(kWalletAddAccountId,
169                           IDS_AUTOFILL_DIALOG_ADD_ACCOUNT);
170  AddCheckItemWithStringId(kAutofillItemId,
171                           IDS_AUTOFILL_DIALOG_PAY_WITHOUT_WALLET);
172}
173
174void AccountChooserModel::DoAccountSwitch(int command_id) {
175  if (checked_item_ == command_id)
176    return;
177
178  if (command_id == kWalletAddAccountId) {
179    delegate_->AddAccount();
180    return;
181  }
182
183  checked_item_ = command_id;
184  ReconstructMenuItems();
185  delegate_->AccountChoiceChanged();
186}
187
188}  // namespace autofill
189