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 "base/prefs/pref_service.h" 6 #include "base/strings/utf_string_conversions.h" 7 #include "chrome/browser/ui/autofill/account_chooser_model.h" 8 #include "chrome/common/pref_names.h" 9 #include "chrome/test/base/testing_profile.h" 10 #include "components/autofill/core/browser/autofill_metrics.h" 11 #include "testing/gmock/include/gmock/gmock.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 14 using base::ASCIIToUTF16; 15 16 namespace autofill { 17 18 namespace { 19 20 class TestAccountChooserModel : public AccountChooserModel { 21 public: 22 TestAccountChooserModel(AccountChooserModelDelegate* delegate, 23 Profile* profile, 24 bool disable_wallet, 25 const AutofillMetrics& metric_logger) 26 : AccountChooserModel(delegate, profile, disable_wallet, metric_logger) {} 27 virtual ~TestAccountChooserModel() {} 28 29 using AccountChooserModel::kWalletAccountsStartId; 30 using AccountChooserModel::kWalletAddAccountId; 31 using AccountChooserModel::kAutofillItemId; 32 33 private: 34 DISALLOW_COPY_AND_ASSIGN(TestAccountChooserModel); 35 }; 36 37 class MockAccountChooserModelDelegate : public AccountChooserModelDelegate { 38 public: 39 MockAccountChooserModelDelegate() {} 40 virtual ~MockAccountChooserModelDelegate() {} 41 42 MOCK_METHOD0(AccountChoiceChanged, void()); 43 MOCK_METHOD0(AddAccount, void()); 44 MOCK_METHOD0(UpdateAccountChooserView, void()); 45 }; 46 47 class AccountChooserModelTest : public testing::Test { 48 public: 49 AccountChooserModelTest() 50 : model_(&delegate_, &profile_, false, metric_logger_) {} 51 virtual ~AccountChooserModelTest() {} 52 53 TestingProfile* profile() { return &profile_; } 54 MockAccountChooserModelDelegate* delegate() { return &delegate_; } 55 TestAccountChooserModel* model() { return &model_; } 56 const AutofillMetrics& metric_logger() { return metric_logger_; } 57 58 private: 59 TestingProfile profile_; 60 testing::NiceMock<MockAccountChooserModelDelegate> delegate_; 61 TestAccountChooserModel model_; 62 AutofillMetrics metric_logger_; 63 }; 64 65 } // namespace 66 67 TEST_F(AccountChooserModelTest, ObeysPref) { 68 // When "Pay without wallet" is false, use Wallet by default. 69 { 70 profile()->GetPrefs()->SetBoolean( 71 ::prefs::kAutofillDialogPayWithoutWallet, false); 72 TestAccountChooserModel model(delegate(), 73 profile(), 74 false, 75 metric_logger()); 76 EXPECT_TRUE(model.WalletIsSelected()); 77 } 78 // When the user chose to "Pay without wallet", use Autofill. 79 { 80 profile()->GetPrefs()->SetBoolean( 81 ::prefs::kAutofillDialogPayWithoutWallet, true); 82 TestAccountChooserModel model(delegate(), 83 profile(), 84 false, 85 metric_logger()); 86 EXPECT_FALSE(model.WalletIsSelected()); 87 } 88 // When the |disable_wallet| argument is true, use Autofill regardless 89 // of the pref. 90 { 91 profile()->GetPrefs()->SetBoolean( 92 ::prefs::kAutofillDialogPayWithoutWallet, false); 93 TestAccountChooserModel model(delegate(), profile(), true, metric_logger()); 94 EXPECT_FALSE(model.WalletIsSelected()); 95 } 96 // In incognito, use local data regardless of the pref. 97 { 98 Profile* incognito = profile()->GetOffTheRecordProfile(); 99 profile()->GetPrefs()->SetBoolean( 100 ::prefs::kAutofillDialogPayWithoutWallet, false); 101 incognito->GetPrefs()->SetBoolean( 102 ::prefs::kAutofillDialogPayWithoutWallet, false); 103 104 TestAccountChooserModel model( 105 delegate(), incognito, false, metric_logger()); 106 EXPECT_FALSE(model.WalletIsSelected()); 107 } 108 } 109 110 TEST_F(AccountChooserModelTest, IgnoresPrefChanges) { 111 ASSERT_FALSE(profile()->GetPrefs()->GetBoolean( 112 ::prefs::kAutofillDialogPayWithoutWallet)); 113 EXPECT_TRUE(model()->WalletIsSelected()); 114 115 // Check that nothing changes while this dialog is running if a pref changes 116 // (this could cause subtle bugs or annoyances if a user closes another 117 // running dialog). 118 profile()->GetPrefs()->SetBoolean( 119 ::prefs::kAutofillDialogPayWithoutWallet, true); 120 EXPECT_TRUE(model()->WalletIsSelected()); 121 } 122 123 TEST_F(AccountChooserModelTest, HandlesError) { 124 EXPECT_CALL(*delegate(), AccountChoiceChanged()).Times(1); 125 EXPECT_CALL(*delegate(), UpdateAccountChooserView()).Times(1); 126 127 ASSERT_TRUE(model()->WalletIsSelected()); 128 ASSERT_TRUE(model()->IsCommandIdEnabled( 129 TestAccountChooserModel::kWalletAccountsStartId)); 130 131 model()->SetHadWalletError(); 132 EXPECT_FALSE(model()->WalletIsSelected()); 133 EXPECT_FALSE(model()->IsCommandIdEnabled( 134 TestAccountChooserModel::kWalletAccountsStartId)); 135 } 136 137 TEST_F(AccountChooserModelTest, HandlesSigninError) { 138 EXPECT_CALL(*delegate(), AccountChoiceChanged()).Times(1); 139 EXPECT_CALL(*delegate(), UpdateAccountChooserView()).Times(2); 140 141 // 0. "Unknown" wallet account, we don't know if the user is signed-in yet. 142 ASSERT_TRUE(model()->WalletIsSelected()); 143 ASSERT_TRUE(model()->IsCommandIdEnabled( 144 TestAccountChooserModel::kWalletAccountsStartId)); 145 ASSERT_TRUE(model()->WalletIsSelected()); 146 ASSERT_FALSE(model()->HasAccountsToChoose()); 147 ASSERT_EQ(3, model()->GetItemCount()); 148 EXPECT_EQ(base::string16(), model()->GetActiveWalletAccountName()); 149 150 // 1. "Known" wallet account (e.g. after active/passive/automatic sign-in). 151 // Calls UpdateAccountChooserView. 152 std::vector<std::string> accounts; 153 accounts.push_back("john.doe (at) gmail.com"); 154 model()->SetWalletAccounts(accounts, 0U); 155 ASSERT_TRUE(model()->WalletIsSelected()); 156 ASSERT_TRUE(model()->IsCommandIdEnabled( 157 TestAccountChooserModel::kWalletAccountsStartId)); 158 ASSERT_TRUE(model()->WalletIsSelected()); 159 ASSERT_TRUE(model()->HasAccountsToChoose()); 160 EXPECT_EQ(3, model()->GetItemCount()); 161 EXPECT_EQ(ASCIIToUTF16(accounts[0]), model()->GetActiveWalletAccountName()); 162 163 // 2. Sign-in failure. 164 // Autofill data should be selected and be the only valid choice. 165 // Calls UpdateAccountChooserView. 166 // Calls AccountChoiceChanged. 167 model()->SetHadWalletSigninError(); 168 EXPECT_FALSE(model()->WalletIsSelected()); 169 EXPECT_TRUE(model()->IsCommandIdEnabled( 170 TestAccountChooserModel::kWalletAccountsStartId)); 171 EXPECT_FALSE(model()->WalletIsSelected()); 172 EXPECT_FALSE(model()->HasAccountsToChoose()); 173 EXPECT_EQ(2, model()->GetItemCount()); 174 EXPECT_EQ(base::string16(), model()->GetActiveWalletAccountName()); 175 } 176 177 TEST_F(AccountChooserModelTest, RespectsUserChoice) { 178 EXPECT_CALL(*delegate(), AccountChoiceChanged()).Times(2); 179 180 model()->ExecuteCommand(TestAccountChooserModel::kAutofillItemId, 0); 181 EXPECT_FALSE(model()->WalletIsSelected()); 182 183 EXPECT_CALL(*delegate(), AddAccount()); 184 model()->ExecuteCommand(TestAccountChooserModel::kWalletAddAccountId, 0); 185 EXPECT_FALSE(model()->WalletIsSelected()); 186 187 model()->ExecuteCommand(TestAccountChooserModel::kWalletAccountsStartId, 0); 188 EXPECT_TRUE(model()->WalletIsSelected()); 189 } 190 191 TEST_F(AccountChooserModelTest, HandlesMultipleAccounts) { 192 EXPECT_FALSE(model()->HasAccountsToChoose()); 193 194 std::vector<std::string> accounts; 195 accounts.push_back("john.doe (at) gmail.com"); 196 accounts.push_back("jane.smith (at) gmail.com"); 197 model()->SetWalletAccounts(accounts, 0U); 198 EXPECT_TRUE(model()->HasAccountsToChoose()); 199 EXPECT_TRUE(model()->WalletIsSelected()); 200 ASSERT_EQ(4, model()->GetItemCount()); 201 EXPECT_TRUE(model()->IsCommandIdEnabled( 202 TestAccountChooserModel::kWalletAccountsStartId)); 203 EXPECT_TRUE(model()->IsCommandIdEnabled( 204 TestAccountChooserModel::kWalletAccountsStartId + 1)); 205 EXPECT_EQ(ASCIIToUTF16(accounts[0]), model()->GetActiveWalletAccountName()); 206 model()->SetWalletAccounts(accounts, 1U); 207 EXPECT_EQ(ASCIIToUTF16(accounts[1]), model()->GetActiveWalletAccountName()); 208 209 model()->ExecuteCommand(TestAccountChooserModel::kWalletAccountsStartId, 0); 210 EXPECT_EQ(ASCIIToUTF16(accounts[0]), model()->GetActiveWalletAccountName()); 211 model()->ExecuteCommand(TestAccountChooserModel::kWalletAccountsStartId + 1, 212 0); 213 EXPECT_EQ(ASCIIToUTF16(accounts[1]), model()->GetActiveWalletAccountName()); 214 215 // Setting the wallet accounts forces the switch to wallet. 216 model()->ExecuteCommand(TestAccountChooserModel::kAutofillItemId, 0); 217 EXPECT_FALSE(model()->WalletIsSelected()); 218 model()->SetWalletAccounts(accounts, 1U); 219 EXPECT_TRUE(model()->WalletIsSelected()); 220 } 221 222 } // namespace autofill 223