Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/password_manager/password_store_mac.h" | 5 #include "chrome/browser/password_manager/password_store_mac.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/files/scoped_temp_dir.h" | 10 #include "base/files/scoped_temp_dir.h" |
| 11 #include "base/scoped_observer.h" | 11 #include "base/scoped_observer.h" |
| 12 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
| 13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
| 14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
| 15 #include "base/synchronization/waitable_event.h" | 15 #include "base/synchronization/waitable_event.h" |
| 16 #include "base/test/histogram_tester.h" | 16 #include "base/test/histogram_tester.h" |
| 17 #include "base/thread_task_runner_handle.h" | 17 #include "base/thread_task_runner_handle.h" |
| 18 #include "chrome/browser/password_manager/password_store_mac_internal.h" | 18 #include "chrome/browser/password_manager/password_store_mac_internal.h" |
| 19 #include "chrome/common/chrome_paths.h" | 19 #include "chrome/common/chrome_paths.h" |
| 20 #include "components/os_crypt/os_crypt.h" | 20 #include "components/os_crypt/os_crypt.h" |
| 21 #include "components/password_manager/core/browser/login_database.h" | 21 #include "components/password_manager/core/browser/login_database.h" |
| 22 #include "components/password_manager/core/browser/password_manager_test_utils.h " | 22 #include "components/password_manager/core/browser/password_manager_test_utils.h " |
| 23 #include "components/password_manager/core/browser/password_store_consumer.h" | 23 #include "components/password_manager/core/browser/password_store_consumer.h" |
| 24 #include "content/public/test/test_browser_thread.h" | 24 #include "components/password_manager/core/browser/password_store_origin_unittes t.h" |
| 25 #include "content/public/test/test_browser_thread_bundle.h" | |
| 25 #include "content/public/test/test_utils.h" | 26 #include "content/public/test/test_utils.h" |
| 26 #include "crypto/mock_apple_keychain.h" | 27 #include "crypto/mock_apple_keychain.h" |
| 27 #include "testing/gmock/include/gmock/gmock.h" | 28 #include "testing/gmock/include/gmock/gmock.h" |
| 28 #include "testing/gtest/include/gtest/gtest.h" | 29 #include "testing/gtest/include/gtest/gtest.h" |
| 29 | 30 |
| 30 using autofill::PasswordForm; | 31 using autofill::PasswordForm; |
| 31 using base::ASCIIToUTF16; | 32 using base::ASCIIToUTF16; |
| 32 using base::WideToUTF16; | 33 using base::WideToUTF16; |
| 33 using content::BrowserThread; | 34 using content::BrowserThread; |
| 34 using crypto::MockAppleKeychain; | 35 using crypto::MockAppleKeychain; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 69 public: | 70 public: |
| 70 MOCK_METHOD1(OnGetPasswordStoreResultsConstRef, | 71 MOCK_METHOD1(OnGetPasswordStoreResultsConstRef, |
| 71 void(const std::vector<PasswordForm*>&)); | 72 void(const std::vector<PasswordForm*>&)); |
| 72 | 73 |
| 73 // GMock cannot mock methods with move-only args. | 74 // GMock cannot mock methods with move-only args. |
| 74 void OnGetPasswordStoreResults(ScopedVector<PasswordForm> results) override { | 75 void OnGetPasswordStoreResults(ScopedVector<PasswordForm> results) override { |
| 75 OnGetPasswordStoreResultsConstRef(results.get()); | 76 OnGetPasswordStoreResultsConstRef(results.get()); |
| 76 } | 77 } |
| 77 }; | 78 }; |
| 78 | 79 |
| 79 class MockPasswordStoreObserver : public PasswordStore::Observer { | |
| 80 public: | |
| 81 MOCK_METHOD1(OnLoginsChanged, | |
| 82 void(const password_manager::PasswordStoreChangeList& changes)); | |
| 83 }; | |
| 84 | |
| 85 // A LoginDatabase that simulates an Init() method that takes a long time. | 80 // A LoginDatabase that simulates an Init() method that takes a long time. |
| 86 class SlowToInitLoginDatabase : public password_manager::LoginDatabase { | 81 class SlowToInitLoginDatabase : public password_manager::LoginDatabase { |
| 87 public: | 82 public: |
| 88 // Creates an instance whose Init() method will block until |event| is | 83 // Creates an instance whose Init() method will block until |event| is |
| 89 // signaled. |event| must outlive |this|. | 84 // signaled. |event| must outlive |this|. |
| 90 SlowToInitLoginDatabase(const base::FilePath& db_path, | 85 SlowToInitLoginDatabase(const base::FilePath& db_path, |
| 91 base::WaitableEvent* event) | 86 base::WaitableEvent* event) |
| 92 : password_manager::LoginDatabase(db_path), event_(event) {} | 87 : password_manager::LoginDatabase(db_path), event_(event) {} |
| 93 ~SlowToInitLoginDatabase() override {} | 88 ~SlowToInitLoginDatabase() override {} |
| 94 | 89 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 167 form->date_synced); | 162 form->date_synced); |
| 168 EXPECT_EQ(GURL(password_manager::kTestingIconUrlSpec), form->icon_url); | 163 EXPECT_EQ(GURL(password_manager::kTestingIconUrlSpec), form->icon_url); |
| 169 } | 164 } |
| 170 } | 165 } |
| 171 | 166 |
| 172 PasswordStoreChangeList AddChangeForForm(const PasswordForm& form) { | 167 PasswordStoreChangeList AddChangeForForm(const PasswordForm& form) { |
| 173 return PasswordStoreChangeList( | 168 return PasswordStoreChangeList( |
| 174 1, PasswordStoreChange(PasswordStoreChange::ADD, form)); | 169 1, PasswordStoreChange(PasswordStoreChange::ADD, form)); |
| 175 } | 170 } |
| 176 | 171 |
| 172 class PasswordStoreMacTestDelegate { | |
| 173 public: | |
| 174 PasswordStoreMacTestDelegate(); | |
| 175 ~PasswordStoreMacTestDelegate(); | |
| 176 | |
| 177 static void FinishAsyncProcessing() { | |
| 178 scoped_refptr<content::MessageLoopRunner> runner = | |
| 179 new content::MessageLoopRunner; | |
| 180 ASSERT_TRUE(base::ThreadTaskRunnerHandle::Get()->PostTaskAndReply( | |
| 181 FROM_HERE, base::Bind(&Noop), runner->QuitClosure())); | |
| 182 runner->Run(); | |
| 183 } | |
| 184 | |
| 185 PasswordStoreMac* store() const { return store_.get(); } | |
|
vasilii
2015/11/23 15:04:56
What is the point of having the const method?
Timo Reimann
2015/11/24 02:36:09
As mentioned before, "I had to add a const overloa
vasilii
2015/11/25 18:18:39
Then remove the non-const method.
Timo Reimann
2015/11/26 01:12:52
Obsoleted by the PasswordStoreMacDelegate rewrite.
| |
| 186 | |
| 187 PasswordStoreMac* store() { return store_.get(); } | |
| 188 | |
| 189 private: | |
| 190 static void InitLoginDatabase(LoginDatabase* login_db); | |
| 191 void Initialize(); | |
| 192 base::FilePath test_login_db_file_path() const; | |
| 193 | |
| 194 void ClosePasswordStore(); | |
| 195 | |
| 196 content::TestBrowserThreadBundle thread_bundle_; | |
| 197 | |
| 198 base::ScopedTempDir db_dir_; | |
| 199 scoped_ptr<LoginDatabase> login_db_; | |
| 200 scoped_refptr<PasswordStoreMac> store_; | |
| 201 | |
| 202 DISALLOW_COPY_AND_ASSIGN(PasswordStoreMacTestDelegate); | |
| 203 }; | |
| 204 | |
| 205 PasswordStoreMacTestDelegate::PasswordStoreMacTestDelegate() { | |
| 206 Initialize(); | |
| 207 } | |
| 208 | |
| 209 PasswordStoreMacTestDelegate::~PasswordStoreMacTestDelegate() { | |
| 210 ClosePasswordStore(); | |
| 211 login_db_.reset(); | |
| 212 } | |
| 213 | |
| 214 void PasswordStoreMacTestDelegate::Initialize() { | |
| 215 ASSERT_TRUE(db_dir_.CreateUniqueTempDir()); | |
| 216 | |
| 217 // Ensure that LoginDatabase will use the mock keychain if it needs to | |
| 218 // encrypt/decrypt a password. | |
| 219 OSCrypt::UseMockKeychain(true); | |
| 220 login_db_.reset(new LoginDatabase(test_login_db_file_path())); | |
| 221 ASSERT_TRUE(base::ThreadTaskRunnerHandle::Get()->PostTask( | |
|
vasilii
2015/11/23 15:04:56
All this PostTasks make no sense in a single threa
Timo Reimann
2015/11/24 02:36:09
I updated it, hopefully for the better.
| |
| 222 FROM_HERE, base::Bind(&PasswordStoreMacTestDelegate::InitLoginDatabase, | |
| 223 base::Unretained(login_db_.get())))); | |
| 224 | |
| 225 // Creat and initialize the password store. | |
| 226 store_ = new PasswordStoreMac(base::ThreadTaskRunnerHandle::Get(), nullptr, | |
| 227 make_scoped_ptr(new MockAppleKeychain)); | |
| 228 ASSERT_TRUE(base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 229 FROM_HERE, base::Bind(&PasswordStoreMac::InitWithTaskRunner, store_, | |
| 230 base::ThreadTaskRunnerHandle::Get()))); | |
| 231 | |
| 232 ASSERT_TRUE(base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 233 FROM_HERE, base::Bind(&PasswordStoreMac::set_login_metadata_db, store_, | |
| 234 base::Unretained(login_db_.get())))); | |
| 235 | |
| 236 // Make sure deferred initialization is performed before some tests start | |
| 237 // accessing the |login_db| directly. | |
| 238 FinishAsyncProcessing(); | |
| 239 } | |
| 240 | |
| 241 void PasswordStoreMacTestDelegate::InitLoginDatabase(LoginDatabase* login_db) { | |
| 242 ASSERT_TRUE(login_db->Init()); | |
| 243 } | |
| 244 | |
| 245 base::FilePath PasswordStoreMacTestDelegate::test_login_db_file_path() const { | |
| 246 return db_dir_.path().Append(FILE_PATH_LITERAL("login.db")); | |
| 247 } | |
| 248 | |
| 249 void PasswordStoreMacTestDelegate::ClosePasswordStore() { | |
| 250 store_->ShutdownOnUIThread(); | |
| 251 FinishAsyncProcessing(); | |
| 252 } | |
| 253 | |
| 177 } // namespace | 254 } // namespace |
| 178 | 255 |
| 256 namespace password_manager { | |
| 257 | |
| 258 INSTANTIATE_TYPED_TEST_CASE_P(Mac, | |
| 259 PasswordStoreOriginTest, | |
| 260 PasswordStoreMacTestDelegate); | |
| 261 | |
| 262 } // namespace password_manager | |
| 263 | |
| 179 #pragma mark - | 264 #pragma mark - |
| 180 | 265 |
| 181 class PasswordStoreMacInternalsTest : public testing::Test { | 266 class PasswordStoreMacInternalsTest : public testing::Test { |
| 182 public: | 267 public: |
| 183 void SetUp() override { | 268 void SetUp() override { |
| 184 MockAppleKeychain::KeychainTestData test_data[] = { | 269 MockAppleKeychain::KeychainTestData test_data[] = { |
| 185 // Basic HTML form. | 270 // Basic HTML form. |
| 186 {kSecAuthenticationTypeHTMLForm, | 271 {kSecAuthenticationTypeHTMLForm, |
| 187 "some.domain.com", | 272 "some.domain.com", |
| 188 kSecProtocolTypeHTTP, | 273 kSecProtocolTypeHTTP, |
| (...skipping 979 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1168 | 1253 |
| 1169 ScopedVector<autofill::PasswordForm> owned_passwords = | 1254 ScopedVector<autofill::PasswordForm> owned_passwords = |
| 1170 owned_keychain_adapter.GetAllPasswordFormPasswords(); | 1255 owned_keychain_adapter.GetAllPasswordFormPasswords(); |
| 1171 EXPECT_EQ(arraysize(owned_password_data), owned_passwords.size()); | 1256 EXPECT_EQ(arraysize(owned_password_data), owned_passwords.size()); |
| 1172 } | 1257 } |
| 1173 | 1258 |
| 1174 #pragma mark - | 1259 #pragma mark - |
| 1175 | 1260 |
| 1176 class PasswordStoreMacTest : public testing::Test { | 1261 class PasswordStoreMacTest : public testing::Test { |
| 1177 public: | 1262 public: |
| 1178 PasswordStoreMacTest() : ui_thread_(BrowserThread::UI, &message_loop_) {} | 1263 PasswordStoreMacTest() : histogram_tester_(new base::HistogramTester) {} |
| 1179 | 1264 |
| 1180 void SetUp() override { | 1265 ~PasswordStoreMacTest() override { |
| 1181 ASSERT_TRUE(db_dir_.CreateUniqueTempDir()); | |
| 1182 histogram_tester_.reset(new base::HistogramTester); | |
| 1183 | |
| 1184 // Ensure that LoginDatabase will use the mock keychain if it needs to | |
| 1185 // encrypt/decrypt a password. | |
| 1186 OSCrypt::UseMockKeychain(true); | |
| 1187 login_db_.reset( | |
| 1188 new password_manager::LoginDatabase(test_login_db_file_path())); | |
| 1189 thread_.reset(new base::Thread("Chrome_PasswordStore_Thread")); | |
| 1190 ASSERT_TRUE(thread_->Start()); | |
| 1191 ASSERT_TRUE(thread_->task_runner()->PostTask( | |
| 1192 FROM_HERE, base::Bind(&PasswordStoreMacTest::InitLoginDatabase, | |
| 1193 base::Unretained(login_db_.get())))); | |
| 1194 CreateAndInitPasswordStore(login_db_.get()); | |
| 1195 // Make sure deferred initialization is performed before some tests start | |
| 1196 // accessing the |login_db| directly. | |
| 1197 FinishAsyncProcessing(); | |
| 1198 } | |
| 1199 | |
| 1200 void TearDown() override { | |
| 1201 ClosePasswordStore(); | |
| 1202 thread_.reset(); | |
| 1203 login_db_.reset(); | |
| 1204 // Whatever a test did, PasswordStoreMac stores only empty password values | 1266 // Whatever a test did, PasswordStoreMac stores only empty password values |
| 1205 // in LoginDatabase. The empty valus do not require encryption and therefore | 1267 // in LoginDatabase. The empty valus do not require encryption and therefore |
| 1206 // OSCrypt shouldn't call the Keychain. The histogram doesn't cover the | 1268 // OSCrypt shouldn't call the Keychain. The histogram doesn't cover the |
| 1207 // internet passwords. | 1269 // internet passwords. |
| 1208 if (histogram_tester_) { | 1270 if (histogram_tester_) { |
| 1209 histogram_tester_->ExpectTotalCount("OSX.Keychain.Access", 0); | 1271 histogram_tester_->ExpectTotalCount("OSX.Keychain.Access", 0); |
| 1210 } | 1272 } |
| 1211 } | 1273 } |
| 1212 | 1274 |
| 1213 static void InitLoginDatabase(password_manager::LoginDatabase* login_db) { | |
| 1214 ASSERT_TRUE(login_db->Init()); | |
| 1215 } | |
| 1216 | |
| 1217 void CreateAndInitPasswordStore(password_manager::LoginDatabase* login_db) { | |
| 1218 store_ = new PasswordStoreMac( | |
| 1219 base::ThreadTaskRunnerHandle::Get(), nullptr, | |
| 1220 make_scoped_ptr<AppleKeychain>(new MockAppleKeychain)); | |
| 1221 ASSERT_TRUE(thread_->task_runner()->PostTask( | |
| 1222 FROM_HERE, base::Bind(&PasswordStoreMac::InitWithTaskRunner, store_, | |
| 1223 thread_->task_runner()))); | |
| 1224 | |
| 1225 ASSERT_TRUE(thread_->task_runner()->PostTask( | |
| 1226 FROM_HERE, base::Bind(&PasswordStoreMac::set_login_metadata_db, store_, | |
| 1227 base::Unretained(login_db)))); | |
| 1228 } | |
| 1229 | |
| 1230 void ClosePasswordStore() { | |
| 1231 if (!store_) | |
| 1232 return; | |
| 1233 | |
| 1234 store_->ShutdownOnUIThread(); | |
| 1235 store_ = nullptr; | |
| 1236 } | |
| 1237 | |
| 1238 // Verifies that the given |form| can be properly stored so that it can be | 1275 // Verifies that the given |form| can be properly stored so that it can be |
| 1239 // retrieved by FillMatchingLogins() and GetAutofillableLogins(), and then it | 1276 // retrieved by FillMatchingLogins() and GetAutofillableLogins(), and then it |
| 1240 // can be properly removed. | 1277 // can be properly removed. |
| 1241 void VerifyCredentialLifecycle(const PasswordForm& form) { | 1278 void VerifyCredentialLifecycle(const PasswordForm& form) { |
| 1242 // Run everything twice to make sure no garbage is left behind that would | 1279 // Run everything twice to make sure no garbage is left behind that would |
| 1243 // prevent storing the form a second time. | 1280 // prevent storing the form a second time. |
| 1244 for (size_t iteration = 0; iteration < 2; ++iteration) { | 1281 for (size_t iteration = 0; iteration < 2; ++iteration) { |
| 1245 SCOPED_TRACE(testing::Message("Iteration: ") << iteration); | 1282 SCOPED_TRACE(testing::Message("Iteration: ") << iteration); |
| 1246 | 1283 |
| 1247 MockPasswordStoreConsumer mock_consumer; | 1284 MockPasswordStoreConsumer mock_consumer; |
| 1248 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(IsEmpty())) | 1285 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(IsEmpty())) |
| 1249 .WillOnce(QuitUIMessageLoop()); | 1286 .WillOnce(QuitUIMessageLoop()); |
| 1250 store()->GetAutofillableLogins(&mock_consumer); | 1287 delegate_.store()->GetAutofillableLogins(&mock_consumer); |
| 1251 base::MessageLoop::current()->Run(); | 1288 base::MessageLoop::current()->Run(); |
| 1252 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer); | 1289 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer); |
| 1253 | 1290 |
| 1254 store()->AddLogin(form); | 1291 delegate_.store()->AddLogin(form); |
| 1255 FinishAsyncProcessing(); | 1292 delegate_.FinishAsyncProcessing(); |
| 1256 | 1293 |
| 1257 PasswordForm returned_form; | 1294 PasswordForm returned_form; |
| 1258 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(SizeIs(1u))) | 1295 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(SizeIs(1u))) |
| 1259 .WillOnce( | 1296 .WillOnce( |
| 1260 DoAll(SaveACopyOfFirstForm(&returned_form), QuitUIMessageLoop())); | 1297 DoAll(SaveACopyOfFirstForm(&returned_form), QuitUIMessageLoop())); |
| 1261 | 1298 |
| 1262 // The query operations will also do some housekeeping: they will remove | 1299 // The query operations will also do some housekeeping: they will remove |
| 1263 // dangling credentials in the LoginDatabase without a matching Keychain | 1300 // dangling credentials in the LoginDatabase without a matching Keychain |
| 1264 // item when one is expected. If the logic that stores the Keychain item | 1301 // item when one is expected. If the logic that stores the Keychain item |
| 1265 // is incorrect, this will wipe the newly added form before the second | 1302 // is incorrect, this will wipe the newly added form before the second |
| 1266 // query. | 1303 // query. |
| 1267 store()->GetAutofillableLogins(&mock_consumer); | 1304 delegate_.store()->GetAutofillableLogins(&mock_consumer); |
| 1268 base::MessageLoop::current()->Run(); | 1305 base::MessageLoop::current()->Run(); |
| 1269 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer); | 1306 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer); |
| 1270 EXPECT_EQ(form, returned_form); | 1307 EXPECT_EQ(form, returned_form); |
| 1271 | 1308 |
| 1272 PasswordForm query_form = form; | 1309 PasswordForm query_form = form; |
| 1273 query_form.password_value.clear(); | 1310 query_form.password_value.clear(); |
| 1274 query_form.username_value.clear(); | 1311 query_form.username_value.clear(); |
| 1275 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(SizeIs(1u))) | 1312 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(SizeIs(1u))) |
| 1276 .WillOnce( | 1313 .WillOnce( |
| 1277 DoAll(SaveACopyOfFirstForm(&returned_form), QuitUIMessageLoop())); | 1314 DoAll(SaveACopyOfFirstForm(&returned_form), QuitUIMessageLoop())); |
| 1278 store()->GetLogins(query_form, PasswordStore::ALLOW_PROMPT, | 1315 delegate_.store()->GetLogins(query_form, PasswordStore::ALLOW_PROMPT, |
| 1279 &mock_consumer); | 1316 &mock_consumer); |
| 1280 base::MessageLoop::current()->Run(); | 1317 base::MessageLoop::current()->Run(); |
| 1281 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer); | 1318 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer); |
| 1282 EXPECT_EQ(form, returned_form); | 1319 EXPECT_EQ(form, returned_form); |
| 1283 | 1320 |
| 1284 store()->RemoveLogin(form); | 1321 delegate_.store()->RemoveLogin(form); |
| 1285 } | 1322 } |
| 1286 } | 1323 } |
| 1287 | 1324 |
| 1288 base::FilePath test_login_db_file_path() const { | |
| 1289 return db_dir_.path().Append(FILE_PATH_LITERAL("login.db")); | |
| 1290 } | |
| 1291 | |
| 1292 password_manager::LoginDatabase* login_db() const { | 1325 password_manager::LoginDatabase* login_db() const { |
| 1293 return store_->login_metadata_db(); | 1326 return delegate_.store()->login_metadata_db(); |
| 1294 } | 1327 } |
| 1295 | 1328 |
| 1296 MockAppleKeychain* keychain() { | 1329 MockAppleKeychain* keychain() { |
| 1297 return static_cast<MockAppleKeychain*>(store_->keychain()); | 1330 return static_cast<MockAppleKeychain*>(delegate_.store()->keychain()); |
| 1298 } | 1331 } |
| 1299 | 1332 |
| 1300 void FinishAsyncProcessing() { | 1333 PasswordStoreMacTestDelegate& delegate() { return delegate_; } |
| 1301 scoped_refptr<content::MessageLoopRunner> runner = | |
| 1302 new content::MessageLoopRunner; | |
| 1303 ASSERT_TRUE(thread_->task_runner()->PostTaskAndReply( | |
| 1304 FROM_HERE, base::Bind(&Noop), runner->QuitClosure())); | |
| 1305 runner->Run(); | |
| 1306 } | |
| 1307 | |
| 1308 PasswordStoreMac* store() { return store_.get(); } | |
| 1309 | 1334 |
| 1310 protected: | 1335 protected: |
| 1311 base::MessageLoopForUI message_loop_; | |
| 1312 content::TestBrowserThread ui_thread_; | |
| 1313 // Thread that the synchronous methods are run on. | |
| 1314 scoped_ptr<base::Thread> thread_; | |
| 1315 | |
| 1316 base::ScopedTempDir db_dir_; | |
| 1317 scoped_ptr<password_manager::LoginDatabase> login_db_; | |
| 1318 scoped_refptr<PasswordStoreMac> store_; | |
| 1319 scoped_ptr<base::HistogramTester> histogram_tester_; | 1336 scoped_ptr<base::HistogramTester> histogram_tester_; |
| 1337 PasswordStoreMacTestDelegate delegate_; | |
| 1320 }; | 1338 }; |
| 1321 | 1339 |
| 1322 TEST_F(PasswordStoreMacTest, TestStoreUpdate) { | 1340 TEST_F(PasswordStoreMacTest, TestStoreUpdate) { |
| 1323 // Insert a password into both the database and the keychain. | 1341 // Insert a password into both the database and the keychain. |
| 1324 // This is done manually, rather than through store_->AddLogin, because the | 1342 // This is done manually, rather than through delegate_.store()->AddLogin, |
| 1343 // because the | |
| 1325 // Mock Keychain isn't smart enough to be able to support update generically, | 1344 // Mock Keychain isn't smart enough to be able to support update generically, |
| 1326 // so some.domain.com triggers special handling to test it that make inserting | 1345 // so some.domain.com triggers special handling to test it that make inserting |
| 1327 // fail. | 1346 // fail. |
| 1328 PasswordFormData joint_data = { | 1347 PasswordFormData joint_data = { |
| 1329 PasswordForm::SCHEME_HTML, "http://some.domain.com/", | 1348 PasswordForm::SCHEME_HTML, "http://some.domain.com/", |
| 1330 "http://some.domain.com/insecure.html", "login.cgi", | 1349 "http://some.domain.com/insecure.html", "login.cgi", |
| 1331 L"username", L"password", L"submit", L"joe_user", L"sekrit", true, false, 1 | 1350 L"username", L"password", L"submit", L"joe_user", L"sekrit", true, false, 1 |
| 1332 }; | 1351 }; |
| 1333 scoped_ptr<PasswordForm> joint_form = | 1352 scoped_ptr<PasswordForm> joint_form = |
| 1334 CreatePasswordFormFromDataForTesting(joint_data); | 1353 CreatePasswordFormFromDataForTesting(joint_data); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1375 { { PasswordForm::SCHEME_HTML, "http://different.com/", | 1394 { { PasswordForm::SCHEME_HTML, "http://different.com/", |
| 1376 "http://different.com/index.html", "login.cgi", | 1395 "http://different.com/index.html", "login.cgi", |
| 1377 L"username", L"password", L"submit", L"abc", L"123", | 1396 L"username", L"password", L"submit", L"abc", L"123", |
| 1378 true, false, 2 }, | 1397 true, false, 2 }, |
| 1379 NULL, | 1398 NULL, |
| 1380 }, | 1399 }, |
| 1381 }; | 1400 }; |
| 1382 for (unsigned int i = 0; i < arraysize(updates); ++i) { | 1401 for (unsigned int i = 0; i < arraysize(updates); ++i) { |
| 1383 scoped_ptr<PasswordForm> form = | 1402 scoped_ptr<PasswordForm> form = |
| 1384 CreatePasswordFormFromDataForTesting(updates[i].form_data); | 1403 CreatePasswordFormFromDataForTesting(updates[i].form_data); |
| 1385 store_->UpdateLogin(*form); | 1404 delegate_.store()->UpdateLogin(*form); |
| 1386 } | 1405 } |
| 1387 | 1406 |
| 1388 FinishAsyncProcessing(); | 1407 delegate_.FinishAsyncProcessing(); |
| 1389 | 1408 |
| 1390 MacKeychainPasswordFormAdapter keychain_adapter(keychain()); | 1409 MacKeychainPasswordFormAdapter keychain_adapter(keychain()); |
| 1391 for (unsigned int i = 0; i < arraysize(updates); ++i) { | 1410 for (unsigned int i = 0; i < arraysize(updates); ++i) { |
| 1392 scoped_ptr<PasswordForm> query_form = | 1411 scoped_ptr<PasswordForm> query_form = |
| 1393 CreatePasswordFormFromDataForTesting(updates[i].form_data); | 1412 CreatePasswordFormFromDataForTesting(updates[i].form_data); |
| 1394 | 1413 |
| 1395 ScopedVector<autofill::PasswordForm> matching_items = | 1414 ScopedVector<autofill::PasswordForm> matching_items = |
| 1396 keychain_adapter.PasswordsFillingForm(query_form->signon_realm, | 1415 keychain_adapter.PasswordsFillingForm(query_form->signon_realm, |
| 1397 query_form->scheme); | 1416 query_form->scheme); |
| 1398 if (updates[i].password) { | 1417 if (updates[i].password) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1438 MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain()); | 1457 MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain()); |
| 1439 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); | 1458 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); |
| 1440 owned_keychain_adapter.AddPassword(*www_form); | 1459 owned_keychain_adapter.AddPassword(*www_form); |
| 1441 | 1460 |
| 1442 // 2. Get a password for m.facebook.com. | 1461 // 2. Get a password for m.facebook.com. |
| 1443 PasswordForm m_form(*www_form); | 1462 PasswordForm m_form(*www_form); |
| 1444 m_form.signon_realm = "http://m.facebook.com"; | 1463 m_form.signon_realm = "http://m.facebook.com"; |
| 1445 m_form.origin = GURL("http://m.facebook.com/index.html"); | 1464 m_form.origin = GURL("http://m.facebook.com/index.html"); |
| 1446 | 1465 |
| 1447 MockPasswordStoreConsumer consumer; | 1466 MockPasswordStoreConsumer consumer; |
| 1448 store_->GetLogins(m_form, PasswordStore::ALLOW_PROMPT, &consumer); | 1467 delegate_.store()->GetLogins(m_form, PasswordStore::ALLOW_PROMPT, &consumer); |
| 1449 PasswordForm returned_form; | 1468 PasswordForm returned_form; |
| 1450 EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(SizeIs(1u))) | 1469 EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(SizeIs(1u))) |
| 1451 .WillOnce( | 1470 .WillOnce( |
| 1452 DoAll(SaveACopyOfFirstForm(&returned_form), QuitUIMessageLoop())); | 1471 DoAll(SaveACopyOfFirstForm(&returned_form), QuitUIMessageLoop())); |
| 1453 base::MessageLoop::current()->Run(); | 1472 base::MessageLoop::current()->Run(); |
| 1454 | 1473 |
| 1455 // 3. Add the returned password for m.facebook.com. | 1474 // 3. Add the returned password for m.facebook.com. |
| 1456 returned_form.signon_realm = "http://m.facebook.com"; | 1475 returned_form.signon_realm = "http://m.facebook.com"; |
| 1457 returned_form.origin = GURL("http://m.facebook.com/index.html"); | 1476 returned_form.origin = GURL("http://m.facebook.com/index.html"); |
| 1458 EXPECT_EQ(AddChangeForForm(returned_form), | 1477 EXPECT_EQ(AddChangeForForm(returned_form), |
| 1459 login_db()->AddLogin(returned_form)); | 1478 login_db()->AddLogin(returned_form)); |
| 1460 owned_keychain_adapter.AddPassword(m_form); | 1479 owned_keychain_adapter.AddPassword(m_form); |
| 1461 | 1480 |
| 1462 // 4. Remove both passwords. | 1481 // 4. Remove both passwords. |
| 1463 store_->RemoveLogin(*www_form); | 1482 delegate_.store()->RemoveLogin(*www_form); |
| 1464 store_->RemoveLogin(m_form); | 1483 delegate_.store()->RemoveLogin(m_form); |
| 1465 FinishAsyncProcessing(); | 1484 delegate_.FinishAsyncProcessing(); |
| 1466 | 1485 |
| 1467 // No trace of www.facebook.com. | 1486 // No trace of www.facebook.com. |
| 1468 ScopedVector<autofill::PasswordForm> matching_items = | 1487 ScopedVector<autofill::PasswordForm> matching_items = |
| 1469 owned_keychain_adapter.PasswordsFillingForm(www_form->signon_realm, | 1488 owned_keychain_adapter.PasswordsFillingForm(www_form->signon_realm, |
| 1470 www_form->scheme); | 1489 www_form->scheme); |
| 1471 EXPECT_EQ(0u, matching_items.size()); | 1490 EXPECT_EQ(0u, matching_items.size()); |
| 1472 EXPECT_TRUE(login_db()->GetLogins(*www_form, &matching_items)); | 1491 EXPECT_TRUE(login_db()->GetLogins(*www_form, &matching_items)); |
| 1473 EXPECT_EQ(0u, matching_items.size()); | 1492 EXPECT_EQ(0u, matching_items.size()); |
| 1474 // No trace of m.facebook.com. | 1493 // No trace of m.facebook.com. |
| 1475 matching_items = owned_keychain_adapter.PasswordsFillingForm( | 1494 matching_items = owned_keychain_adapter.PasswordsFillingForm( |
| 1476 m_form.signon_realm, m_form.scheme); | 1495 m_form.signon_realm, m_form.scheme); |
| 1477 EXPECT_EQ(0u, matching_items.size()); | 1496 EXPECT_EQ(0u, matching_items.size()); |
| 1478 EXPECT_TRUE(login_db()->GetLogins(m_form, &matching_items)); | 1497 EXPECT_TRUE(login_db()->GetLogins(m_form, &matching_items)); |
| 1479 EXPECT_EQ(0u, matching_items.size()); | 1498 EXPECT_EQ(0u, matching_items.size()); |
| 1480 } | 1499 } |
| 1481 | 1500 |
| 1482 namespace { | 1501 namespace { |
| 1483 | 1502 |
| 1484 class PasswordsChangeObserver | 1503 class PasswordsChangeObserver |
| 1485 : public password_manager::PasswordStore::Observer { | 1504 : public password_manager::PasswordStore::Observer { |
| 1486 public: | 1505 public: |
| 1487 explicit PasswordsChangeObserver(PasswordStoreMac* store) : observer_(this) { | 1506 explicit PasswordsChangeObserver(PasswordStoreMac* store) : observer_(this) { |
| 1488 observer_.Add(store); | 1507 observer_.Add(store); |
| 1489 } | 1508 } |
| 1490 | 1509 |
| 1491 void WaitAndVerify(PasswordStoreMacTest* test) { | 1510 void WaitAndVerify(PasswordStoreMacTest* test) { |
| 1492 test->FinishAsyncProcessing(); | 1511 test->delegate().FinishAsyncProcessing(); |
| 1493 ::testing::Mock::VerifyAndClearExpectations(this); | 1512 ::testing::Mock::VerifyAndClearExpectations(this); |
| 1494 } | 1513 } |
| 1495 | 1514 |
| 1496 // password_manager::PasswordStore::Observer: | 1515 // password_manager::PasswordStore::Observer: |
| 1497 MOCK_METHOD1(OnLoginsChanged, | 1516 MOCK_METHOD1(OnLoginsChanged, |
| 1498 void(const password_manager::PasswordStoreChangeList& changes)); | 1517 void(const password_manager::PasswordStoreChangeList& changes)); |
| 1499 | 1518 |
| 1500 private: | 1519 private: |
| 1501 ScopedObserver<password_manager::PasswordStore, PasswordsChangeObserver> | 1520 ScopedObserver<password_manager::PasswordStore, PasswordsChangeObserver> |
| 1502 observer_; | 1521 observer_; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1536 if (check_created) { | 1555 if (check_created) { |
| 1537 form_facebook_old->date_created = now; | 1556 form_facebook_old->date_created = now; |
| 1538 form_facebook->date_created = next_day; | 1557 form_facebook->date_created = next_day; |
| 1539 form_other->date_created = next_day; | 1558 form_other->date_created = next_day; |
| 1540 } else { | 1559 } else { |
| 1541 form_facebook_old->date_synced = now; | 1560 form_facebook_old->date_synced = now; |
| 1542 form_facebook->date_synced = next_day; | 1561 form_facebook->date_synced = next_day; |
| 1543 form_other->date_synced = next_day; | 1562 form_other->date_synced = next_day; |
| 1544 } | 1563 } |
| 1545 | 1564 |
| 1546 PasswordsChangeObserver observer(test->store()); | 1565 PasswordsChangeObserver observer(test->delegate().store()); |
| 1547 test->store()->AddLogin(*form_facebook_old); | 1566 test->delegate().store()->AddLogin(*form_facebook_old); |
| 1548 test->store()->AddLogin(*form_facebook); | 1567 test->delegate().store()->AddLogin(*form_facebook); |
| 1549 test->store()->AddLogin(*form_other); | 1568 test->delegate().store()->AddLogin(*form_other); |
| 1550 EXPECT_CALL(observer, OnLoginsChanged(GetAddChangeList(*form_facebook_old))); | 1569 EXPECT_CALL(observer, OnLoginsChanged(GetAddChangeList(*form_facebook_old))); |
| 1551 EXPECT_CALL(observer, OnLoginsChanged(GetAddChangeList(*form_facebook))); | 1570 EXPECT_CALL(observer, OnLoginsChanged(GetAddChangeList(*form_facebook))); |
| 1552 EXPECT_CALL(observer, OnLoginsChanged(GetAddChangeList(*form_other))); | 1571 EXPECT_CALL(observer, OnLoginsChanged(GetAddChangeList(*form_other))); |
| 1553 observer.WaitAndVerify(test); | 1572 observer.WaitAndVerify(test); |
| 1554 | 1573 |
| 1555 // Check the keychain content. | 1574 // Check the keychain content. |
| 1556 MacKeychainPasswordFormAdapter owned_keychain_adapter(test->keychain()); | 1575 MacKeychainPasswordFormAdapter owned_keychain_adapter(test->keychain()); |
| 1557 owned_keychain_adapter.SetFindsOnlyOwnedItems(false); | 1576 owned_keychain_adapter.SetFindsOnlyOwnedItems(false); |
| 1558 ScopedVector<PasswordForm> matching_items( | 1577 ScopedVector<PasswordForm> matching_items( |
| 1559 owned_keychain_adapter.PasswordsFillingForm(form_facebook->signon_realm, | 1578 owned_keychain_adapter.PasswordsFillingForm(form_facebook->signon_realm, |
| 1560 form_facebook->scheme)); | 1579 form_facebook->scheme)); |
| 1561 EXPECT_EQ(1u, matching_items.size()); | 1580 EXPECT_EQ(1u, matching_items.size()); |
| 1562 matching_items = owned_keychain_adapter.PasswordsFillingForm( | 1581 matching_items = owned_keychain_adapter.PasswordsFillingForm( |
| 1563 form_other->signon_realm, form_other->scheme); | 1582 form_other->signon_realm, form_other->scheme); |
| 1564 EXPECT_EQ(1u, matching_items.size()); | 1583 EXPECT_EQ(1u, matching_items.size()); |
| 1565 | 1584 |
| 1566 // Remove facebook. | 1585 // Remove facebook. |
| 1567 if (check_created) { | 1586 if (check_created) { |
| 1568 test->store()->RemoveLoginsCreatedBetween(base::Time(), next_day, | 1587 test->delegate().store()->RemoveLoginsCreatedBetween(base::Time(), next_day, |
| 1569 base::Closure()); | 1588 base::Closure()); |
| 1570 } else { | 1589 } else { |
| 1571 test->store()->RemoveLoginsSyncedBetween(base::Time(), next_day); | 1590 test->delegate().store()->RemoveLoginsSyncedBetween(base::Time(), next_day); |
| 1572 } | 1591 } |
| 1573 password_manager::PasswordStoreChangeList list; | 1592 password_manager::PasswordStoreChangeList list; |
| 1574 form_facebook_old->password_value.clear(); | 1593 form_facebook_old->password_value.clear(); |
| 1575 form_facebook->password_value.clear(); | 1594 form_facebook->password_value.clear(); |
| 1576 list.push_back(password_manager::PasswordStoreChange( | 1595 list.push_back(password_manager::PasswordStoreChange( |
| 1577 password_manager::PasswordStoreChange::REMOVE, *form_facebook_old)); | 1596 password_manager::PasswordStoreChange::REMOVE, *form_facebook_old)); |
| 1578 list.push_back(password_manager::PasswordStoreChange( | 1597 list.push_back(password_manager::PasswordStoreChange( |
| 1579 password_manager::PasswordStoreChange::REMOVE, *form_facebook)); | 1598 password_manager::PasswordStoreChange::REMOVE, *form_facebook)); |
| 1580 EXPECT_CALL(observer, OnLoginsChanged(list)); | 1599 EXPECT_CALL(observer, OnLoginsChanged(list)); |
| 1581 list.clear(); | 1600 list.clear(); |
| 1582 observer.WaitAndVerify(test); | 1601 observer.WaitAndVerify(test); |
| 1583 | 1602 |
| 1584 matching_items = owned_keychain_adapter.PasswordsFillingForm( | 1603 matching_items = owned_keychain_adapter.PasswordsFillingForm( |
| 1585 form_facebook->signon_realm, form_facebook->scheme); | 1604 form_facebook->signon_realm, form_facebook->scheme); |
| 1586 EXPECT_EQ(0u, matching_items.size()); | 1605 EXPECT_EQ(0u, matching_items.size()); |
| 1587 matching_items = owned_keychain_adapter.PasswordsFillingForm( | 1606 matching_items = owned_keychain_adapter.PasswordsFillingForm( |
| 1588 form_other->signon_realm, form_other->scheme); | 1607 form_other->signon_realm, form_other->scheme); |
| 1589 EXPECT_EQ(1u, matching_items.size()); | 1608 EXPECT_EQ(1u, matching_items.size()); |
| 1590 | 1609 |
| 1591 // Remove form_other. | 1610 // Remove form_other. |
| 1592 if (check_created) { | 1611 if (check_created) { |
| 1593 test->store()->RemoveLoginsCreatedBetween(next_day, base::Time(), | 1612 test->delegate().store()->RemoveLoginsCreatedBetween(next_day, base::Time(), |
| 1594 base::Closure()); | 1613 base::Closure()); |
| 1595 } else { | 1614 } else { |
| 1596 test->store()->RemoveLoginsSyncedBetween(next_day, base::Time()); | 1615 test->delegate().store()->RemoveLoginsSyncedBetween(next_day, base::Time()); |
| 1597 } | 1616 } |
| 1598 form_other->password_value.clear(); | 1617 form_other->password_value.clear(); |
| 1599 list.push_back(password_manager::PasswordStoreChange( | 1618 list.push_back(password_manager::PasswordStoreChange( |
| 1600 password_manager::PasswordStoreChange::REMOVE, *form_other)); | 1619 password_manager::PasswordStoreChange::REMOVE, *form_other)); |
| 1601 EXPECT_CALL(observer, OnLoginsChanged(list)); | 1620 EXPECT_CALL(observer, OnLoginsChanged(list)); |
| 1602 observer.WaitAndVerify(test); | 1621 observer.WaitAndVerify(test); |
| 1603 matching_items = owned_keychain_adapter.PasswordsFillingForm( | 1622 matching_items = owned_keychain_adapter.PasswordsFillingForm( |
| 1604 form_other->signon_realm, form_other->scheme); | 1623 form_other->signon_realm, form_other->scheme); |
| 1605 EXPECT_EQ(0u, matching_items.size()); | 1624 EXPECT_EQ(0u, matching_items.size()); |
| 1606 } | 1625 } |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 1637 scoped_ptr<PasswordForm> www_form = | 1656 scoped_ptr<PasswordForm> www_form = |
| 1638 CreatePasswordFormFromDataForTesting(www_form_data1); | 1657 CreatePasswordFormFromDataForTesting(www_form_data1); |
| 1639 EXPECT_TRUE(owned_keychain_adapter.AddPassword(*www_form)); | 1658 EXPECT_TRUE(owned_keychain_adapter.AddPassword(*www_form)); |
| 1640 | 1659 |
| 1641 // Add a password from the current profile. | 1660 // Add a password from the current profile. |
| 1642 PasswordFormData www_form_data2 = { | 1661 PasswordFormData www_form_data2 = { |
| 1643 PasswordForm::SCHEME_HTML, "http://www.facebook.com/", | 1662 PasswordForm::SCHEME_HTML, "http://www.facebook.com/", |
| 1644 "http://www.facebook.com/index.html", "login", L"username", L"password", | 1663 "http://www.facebook.com/index.html", "login", L"username", L"password", |
| 1645 L"submit", L"not_joe_user", L"12345", true, false, 1 }; | 1664 L"submit", L"not_joe_user", L"12345", true, false, 1 }; |
| 1646 www_form = CreatePasswordFormFromDataForTesting(www_form_data2); | 1665 www_form = CreatePasswordFormFromDataForTesting(www_form_data2); |
| 1647 store_->AddLogin(*www_form); | 1666 delegate_.store()->AddLogin(*www_form); |
| 1648 FinishAsyncProcessing(); | 1667 delegate_.FinishAsyncProcessing(); |
| 1649 | 1668 |
| 1650 ScopedVector<PasswordForm> matching_items; | 1669 ScopedVector<PasswordForm> matching_items; |
| 1651 EXPECT_TRUE(login_db()->GetLogins(*www_form, &matching_items)); | 1670 EXPECT_TRUE(login_db()->GetLogins(*www_form, &matching_items)); |
| 1652 EXPECT_EQ(1u, matching_items.size()); | 1671 EXPECT_EQ(1u, matching_items.size()); |
| 1653 | 1672 |
| 1654 store_->RemoveLoginsCreatedBetween(base::Time(), base::Time(), | 1673 delegate_.store()->RemoveLoginsCreatedBetween(base::Time(), base::Time(), |
| 1655 base::Closure()); | 1674 base::Closure()); |
| 1656 FinishAsyncProcessing(); | 1675 delegate_.FinishAsyncProcessing(); |
| 1657 | 1676 |
| 1658 // Check the second facebook form is gone. | 1677 // Check the second facebook form is gone. |
| 1659 EXPECT_TRUE(login_db()->GetLogins(*www_form, &matching_items)); | 1678 EXPECT_TRUE(login_db()->GetLogins(*www_form, &matching_items)); |
| 1660 EXPECT_EQ(0u, matching_items.size()); | 1679 EXPECT_EQ(0u, matching_items.size()); |
| 1661 | 1680 |
| 1662 // Check the first facebook form is still there. | 1681 // Check the first facebook form is still there. |
| 1663 matching_items = owned_keychain_adapter.PasswordsFillingForm( | 1682 matching_items = owned_keychain_adapter.PasswordsFillingForm( |
| 1664 www_form->signon_realm, www_form->scheme); | 1683 www_form->signon_realm, www_form->scheme); |
| 1665 ASSERT_EQ(1u, matching_items.size()); | 1684 ASSERT_EQ(1u, matching_items.size()); |
| 1666 EXPECT_EQ(ASCIIToUTF16("joe_user"), matching_items[0]->username_value); | 1685 EXPECT_EQ(ASCIIToUTF16("joe_user"), matching_items[0]->username_value); |
| 1667 | 1686 |
| 1668 // Check the third-party password is still there. | 1687 // Check the third-party password is still there. |
| 1669 owned_keychain_adapter.SetFindsOnlyOwnedItems(false); | 1688 owned_keychain_adapter.SetFindsOnlyOwnedItems(false); |
| 1670 matching_items = owned_keychain_adapter.PasswordsFillingForm( | 1689 matching_items = owned_keychain_adapter.PasswordsFillingForm( |
| 1671 "http://some.domain.com/insecure.html", PasswordForm::SCHEME_HTML); | 1690 "http://some.domain.com/insecure.html", PasswordForm::SCHEME_HTML); |
| 1672 ASSERT_EQ(1u, matching_items.size()); | 1691 ASSERT_EQ(1u, matching_items.size()); |
| 1673 } | 1692 } |
| 1674 | 1693 |
| 1675 // Add a facebook form to the store but not to the keychain. The form is to be | 1694 // Add a facebook form to the store but not to the keychain. The form is to be |
| 1676 // implicitly deleted. However, the observers shouldn't get notified about | 1695 // implicitly deleted. However, the observers shouldn't get notified about |
| 1677 // deletion of non-existent forms like m.facebook.com. | 1696 // deletion of non-existent forms like m.facebook.com. |
| 1678 TEST_F(PasswordStoreMacTest, SilentlyRemoveOrphanedForm) { | 1697 TEST_F(PasswordStoreMacTest, SilentlyRemoveOrphanedForm) { |
| 1679 testing::StrictMock<MockPasswordStoreObserver> mock_observer; | 1698 testing::StrictMock<password_manager::MockPasswordStoreObserver> |
| 1680 store()->AddObserver(&mock_observer); | 1699 mock_observer; |
| 1700 delegate_.store()->AddObserver(&mock_observer); | |
| 1681 | 1701 |
| 1682 // 1. Add a password for www.facebook.com to the LoginDatabase. | 1702 // 1. Add a password for www.facebook.com to the LoginDatabase. |
| 1683 PasswordFormData www_form_data = { | 1703 PasswordFormData www_form_data = { |
| 1684 PasswordForm::SCHEME_HTML, "http://www.facebook.com/", | 1704 PasswordForm::SCHEME_HTML, "http://www.facebook.com/", |
| 1685 "http://www.facebook.com/index.html", "login", | 1705 "http://www.facebook.com/index.html", "login", |
| 1686 L"username", L"password", L"submit", L"joe_user", L"", true, false, 1 | 1706 L"username", L"password", L"submit", L"joe_user", L"", true, false, 1 |
| 1687 }; | 1707 }; |
| 1688 scoped_ptr<PasswordForm> www_form( | 1708 scoped_ptr<PasswordForm> www_form( |
| 1689 CreatePasswordFormFromDataForTesting(www_form_data)); | 1709 CreatePasswordFormFromDataForTesting(www_form_data)); |
| 1690 EXPECT_EQ(AddChangeForForm(*www_form), login_db()->AddLogin(*www_form)); | 1710 EXPECT_EQ(AddChangeForForm(*www_form), login_db()->AddLogin(*www_form)); |
| 1691 | 1711 |
| 1692 // 2. Get a PSL-matched password for m.facebook.com. The observer isn't | 1712 // 2. Get a PSL-matched password for m.facebook.com. The observer isn't |
| 1693 // notified because the form isn't in the database. | 1713 // notified because the form isn't in the database. |
| 1694 PasswordForm m_form(*www_form); | 1714 PasswordForm m_form(*www_form); |
| 1695 m_form.signon_realm = "http://m.facebook.com"; | 1715 m_form.signon_realm = "http://m.facebook.com"; |
| 1696 m_form.origin = GURL("http://m.facebook.com/index.html"); | 1716 m_form.origin = GURL("http://m.facebook.com/index.html"); |
| 1697 | 1717 |
| 1698 MockPasswordStoreConsumer consumer; | 1718 MockPasswordStoreConsumer consumer; |
| 1699 ON_CALL(consumer, OnGetPasswordStoreResultsConstRef(_)) | 1719 ON_CALL(consumer, OnGetPasswordStoreResultsConstRef(_)) |
| 1700 .WillByDefault(QuitUIMessageLoop()); | 1720 .WillByDefault(QuitUIMessageLoop()); |
| 1701 EXPECT_CALL(mock_observer, OnLoginsChanged(_)).Times(0); | 1721 EXPECT_CALL(mock_observer, OnLoginsChanged(_)).Times(0); |
| 1702 // The PSL-matched form isn't returned because there is no actual password in | 1722 // The PSL-matched form isn't returned because there is no actual password in |
| 1703 // the keychain. | 1723 // the keychain. |
| 1704 EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(IsEmpty())); | 1724 EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(IsEmpty())); |
| 1705 store_->GetLogins(m_form, PasswordStore::ALLOW_PROMPT, &consumer); | 1725 delegate_.store()->GetLogins(m_form, PasswordStore::ALLOW_PROMPT, &consumer); |
| 1706 base::MessageLoop::current()->Run(); | 1726 base::MessageLoop::current()->Run(); |
| 1707 ScopedVector<autofill::PasswordForm> all_forms; | 1727 ScopedVector<autofill::PasswordForm> all_forms; |
| 1708 EXPECT_TRUE(login_db()->GetAutofillableLogins(&all_forms)); | 1728 EXPECT_TRUE(login_db()->GetAutofillableLogins(&all_forms)); |
| 1709 EXPECT_EQ(1u, all_forms.size()); | 1729 EXPECT_EQ(1u, all_forms.size()); |
| 1710 ::testing::Mock::VerifyAndClearExpectations(&mock_observer); | 1730 ::testing::Mock::VerifyAndClearExpectations(&mock_observer); |
| 1711 | 1731 |
| 1712 // 3. Get a password for www.facebook.com. The form is implicitly removed and | 1732 // 3. Get a password for www.facebook.com. The form is implicitly removed and |
| 1713 // the observer is notified. | 1733 // the observer is notified. |
| 1714 password_manager::PasswordStoreChangeList list; | 1734 password_manager::PasswordStoreChangeList list; |
| 1715 list.push_back(password_manager::PasswordStoreChange( | 1735 list.push_back(password_manager::PasswordStoreChange( |
| 1716 password_manager::PasswordStoreChange::REMOVE, *www_form)); | 1736 password_manager::PasswordStoreChange::REMOVE, *www_form)); |
| 1717 EXPECT_CALL(mock_observer, OnLoginsChanged(list)); | 1737 EXPECT_CALL(mock_observer, OnLoginsChanged(list)); |
| 1718 EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(IsEmpty())); | 1738 EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(IsEmpty())); |
| 1719 store_->GetLogins(*www_form, PasswordStore::ALLOW_PROMPT, &consumer); | 1739 delegate_.store()->GetLogins(*www_form, PasswordStore::ALLOW_PROMPT, |
| 1740 &consumer); | |
| 1720 base::MessageLoop::current()->Run(); | 1741 base::MessageLoop::current()->Run(); |
| 1721 EXPECT_TRUE(login_db()->GetAutofillableLogins(&all_forms)); | 1742 EXPECT_TRUE(login_db()->GetAutofillableLogins(&all_forms)); |
| 1722 EXPECT_EQ(0u, all_forms.size()); | 1743 EXPECT_EQ(0u, all_forms.size()); |
| 1723 } | 1744 } |
| 1724 | 1745 |
| 1725 // Verify that Android app passwords can be stored, retrieved, and deleted. | 1746 // Verify that Android app passwords can be stored, retrieved, and deleted. |
| 1726 // Regression test for http://crbug.com/455551 | 1747 // Regression test for http://crbug.com/455551 |
| 1727 TEST_F(PasswordStoreMacTest, StoringAndRetrievingAndroidCredentials) { | 1748 TEST_F(PasswordStoreMacTest, StoringAndRetrievingAndroidCredentials) { |
| 1728 PasswordForm form; | 1749 PasswordForm form; |
| 1729 form.signon_realm = "android://7x7IDboo8u9YKraUsbmVkuf1@net.rateflix.app/"; | 1750 form.signon_realm = "android://7x7IDboo8u9YKraUsbmVkuf1@net.rateflix.app/"; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1762 form2.origin = GURL("http://facebook.com/Login"); | 1783 form2.origin = GURL("http://facebook.com/Login"); |
| 1763 form2.signon_realm = "http://facebook.com/"; | 1784 form2.signon_realm = "http://facebook.com/"; |
| 1764 form2.username_value = ASCIIToUTF16("my_username"); | 1785 form2.username_value = ASCIIToUTF16("my_username"); |
| 1765 form2.password_value = ASCIIToUTF16("my_password"); | 1786 form2.password_value = ASCIIToUTF16("my_password"); |
| 1766 | 1787 |
| 1767 PasswordForm blacklisted_form; | 1788 PasswordForm blacklisted_form; |
| 1768 blacklisted_form.origin = GURL("http://badsite.com/Login"); | 1789 blacklisted_form.origin = GURL("http://badsite.com/Login"); |
| 1769 blacklisted_form.signon_realm = "http://badsite.com/"; | 1790 blacklisted_form.signon_realm = "http://badsite.com/"; |
| 1770 blacklisted_form.blacklisted_by_user = true; | 1791 blacklisted_form.blacklisted_by_user = true; |
| 1771 | 1792 |
| 1772 store()->AddLogin(form1); | 1793 delegate_.store()->AddLogin(form1); |
| 1773 store()->AddLogin(form2); | 1794 delegate_.store()->AddLogin(form2); |
| 1774 store()->AddLogin(blacklisted_form); | 1795 delegate_.store()->AddLogin(blacklisted_form); |
| 1775 FinishAsyncProcessing(); | 1796 delegate_.FinishAsyncProcessing(); |
| 1776 | 1797 |
| 1777 ASSERT_TRUE(base::PostTaskAndReplyWithResult( | 1798 ASSERT_TRUE(base::PostTaskAndReplyWithResult( |
| 1778 thread_->task_runner().get(), FROM_HERE, | 1799 base::ThreadTaskRunnerHandle::Get().get(), FROM_HERE, |
| 1779 base::Bind(&PasswordStoreMac::ImportFromKeychain, store()), | 1800 base::Bind(&PasswordStoreMac::ImportFromKeychain, delegate_.store()), |
| 1780 base::Bind(&CheckMigrationResult, PasswordStoreMac::MIGRATION_OK))); | 1801 base::Bind(&CheckMigrationResult, PasswordStoreMac::MIGRATION_OK))); |
| 1781 FinishAsyncProcessing(); | 1802 delegate_.FinishAsyncProcessing(); |
| 1782 | 1803 |
| 1783 // The password should be stored in the database by now. | 1804 // The password should be stored in the database by now. |
| 1784 ScopedVector<PasswordForm> matching_items; | 1805 ScopedVector<PasswordForm> matching_items; |
| 1785 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items)); | 1806 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items)); |
| 1786 ASSERT_EQ(1u, matching_items.size()); | 1807 ASSERT_EQ(1u, matching_items.size()); |
| 1787 EXPECT_EQ(form1, *matching_items[0]); | 1808 EXPECT_EQ(form1, *matching_items[0]); |
| 1788 | 1809 |
| 1789 EXPECT_TRUE(login_db()->GetLogins(form2, &matching_items)); | 1810 EXPECT_TRUE(login_db()->GetLogins(form2, &matching_items)); |
| 1790 ASSERT_EQ(1u, matching_items.size()); | 1811 ASSERT_EQ(1u, matching_items.size()); |
| 1791 EXPECT_EQ(form2, *matching_items[0]); | 1812 EXPECT_EQ(form2, *matching_items[0]); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1802 | 1823 |
| 1803 // Import a federated credential while the Keychain is locked. | 1824 // Import a federated credential while the Keychain is locked. |
| 1804 TEST_F(PasswordStoreMacTest, ImportFederatedFromLockedKeychain) { | 1825 TEST_F(PasswordStoreMacTest, ImportFederatedFromLockedKeychain) { |
| 1805 keychain()->set_locked(true); | 1826 keychain()->set_locked(true); |
| 1806 PasswordForm form1; | 1827 PasswordForm form1; |
| 1807 form1.origin = GURL("http://example.com/Login"); | 1828 form1.origin = GURL("http://example.com/Login"); |
| 1808 form1.signon_realm = "http://example.com/"; | 1829 form1.signon_realm = "http://example.com/"; |
| 1809 form1.username_value = ASCIIToUTF16("my_username"); | 1830 form1.username_value = ASCIIToUTF16("my_username"); |
| 1810 form1.federation_url = GURL("https://accounts.google.com/"); | 1831 form1.federation_url = GURL("https://accounts.google.com/"); |
| 1811 | 1832 |
| 1812 store()->AddLogin(form1); | 1833 delegate_.store()->AddLogin(form1); |
| 1813 FinishAsyncProcessing(); | 1834 delegate_.FinishAsyncProcessing(); |
| 1814 ASSERT_TRUE(base::PostTaskAndReplyWithResult( | 1835 ASSERT_TRUE(base::PostTaskAndReplyWithResult( |
| 1815 thread_->task_runner().get(), FROM_HERE, | 1836 base::ThreadTaskRunnerHandle::Get().get(), FROM_HERE, |
| 1816 base::Bind(&PasswordStoreMac::ImportFromKeychain, store()), | 1837 base::Bind(&PasswordStoreMac::ImportFromKeychain, delegate_.store()), |
| 1817 base::Bind(&CheckMigrationResult, PasswordStoreMac::MIGRATION_OK))); | 1838 base::Bind(&CheckMigrationResult, PasswordStoreMac::MIGRATION_OK))); |
| 1818 FinishAsyncProcessing(); | 1839 delegate_.FinishAsyncProcessing(); |
| 1819 | 1840 |
| 1820 ScopedVector<PasswordForm> matching_items; | 1841 ScopedVector<PasswordForm> matching_items; |
| 1821 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items)); | 1842 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items)); |
| 1822 ASSERT_EQ(1u, matching_items.size()); | 1843 ASSERT_EQ(1u, matching_items.size()); |
| 1823 EXPECT_EQ(form1, *matching_items[0]); | 1844 EXPECT_EQ(form1, *matching_items[0]); |
| 1824 } | 1845 } |
| 1825 | 1846 |
| 1826 // Try to import while the Keychain is locked but the encryption key had been | 1847 // Try to import while the Keychain is locked but the encryption key had been |
| 1827 // read earlier. | 1848 // read earlier. |
| 1828 TEST_F(PasswordStoreMacTest, ImportFromLockedKeychainError) { | 1849 TEST_F(PasswordStoreMacTest, ImportFromLockedKeychainError) { |
| 1829 PasswordForm form1; | 1850 PasswordForm form1; |
| 1830 form1.origin = GURL("http://accounts.google.com/LoginAuth"); | 1851 form1.origin = GURL("http://accounts.google.com/LoginAuth"); |
| 1831 form1.signon_realm = "http://accounts.google.com/"; | 1852 form1.signon_realm = "http://accounts.google.com/"; |
| 1832 form1.username_value = ASCIIToUTF16("my_username"); | 1853 form1.username_value = ASCIIToUTF16("my_username"); |
| 1833 form1.password_value = ASCIIToUTF16("my_password"); | 1854 form1.password_value = ASCIIToUTF16("my_password"); |
| 1834 store()->AddLogin(form1); | 1855 delegate_.store()->AddLogin(form1); |
| 1835 FinishAsyncProcessing(); | 1856 delegate_.FinishAsyncProcessing(); |
| 1836 | 1857 |
| 1837 // Add a second keychain item matching the Database entry. | 1858 // Add a second keychain item matching the Database entry. |
| 1838 PasswordForm form2 = form1; | 1859 PasswordForm form2 = form1; |
| 1839 form2.origin = GURL("http://accounts.google.com/Login"); | 1860 form2.origin = GURL("http://accounts.google.com/Login"); |
| 1840 form2.password_value = ASCIIToUTF16("1234"); | 1861 form2.password_value = ASCIIToUTF16("1234"); |
| 1841 MacKeychainPasswordFormAdapter adapter(keychain()); | 1862 MacKeychainPasswordFormAdapter adapter(keychain()); |
| 1842 EXPECT_TRUE(adapter.AddPassword(form2)); | 1863 EXPECT_TRUE(adapter.AddPassword(form2)); |
| 1843 | 1864 |
| 1844 keychain()->set_locked(true); | 1865 keychain()->set_locked(true); |
| 1845 ASSERT_TRUE(base::PostTaskAndReplyWithResult( | 1866 ASSERT_TRUE(base::PostTaskAndReplyWithResult( |
| 1846 thread_->task_runner().get(), FROM_HERE, | 1867 base::ThreadTaskRunnerHandle::Get().get(), FROM_HERE, |
| 1847 base::Bind(&PasswordStoreMac::ImportFromKeychain, store()), | 1868 base::Bind(&PasswordStoreMac::ImportFromKeychain, delegate_.store()), |
| 1848 base::Bind(&CheckMigrationResult, PasswordStoreMac::KEYCHAIN_BLOCKED))); | 1869 base::Bind(&CheckMigrationResult, PasswordStoreMac::KEYCHAIN_BLOCKED))); |
| 1849 FinishAsyncProcessing(); | 1870 delegate_.FinishAsyncProcessing(); |
| 1850 | 1871 |
| 1851 ScopedVector<PasswordForm> matching_items; | 1872 ScopedVector<PasswordForm> matching_items; |
| 1852 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items)); | 1873 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items)); |
| 1853 ASSERT_EQ(1u, matching_items.size()); | 1874 ASSERT_EQ(1u, matching_items.size()); |
| 1854 EXPECT_EQ(base::string16(), matching_items[0]->password_value); | 1875 EXPECT_EQ(base::string16(), matching_items[0]->password_value); |
| 1855 | 1876 |
| 1856 histogram_tester_->ExpectUniqueSample( | 1877 histogram_tester_->ExpectUniqueSample( |
| 1857 "PasswordManager.KeychainMigration.NumPasswordsOnFailure", 1, 1); | 1878 "PasswordManager.KeychainMigration.NumPasswordsOnFailure", 1, 1); |
| 1858 histogram_tester_->ExpectUniqueSample( | 1879 histogram_tester_->ExpectUniqueSample( |
| 1859 "PasswordManager.KeychainMigration.NumFailedPasswords", 1, 1); | 1880 "PasswordManager.KeychainMigration.NumFailedPasswords", 1, 1); |
| 1860 histogram_tester_->ExpectUniqueSample( | 1881 histogram_tester_->ExpectUniqueSample( |
| 1861 "PasswordManager.KeychainMigration.NumChromeOwnedInaccessiblePasswords", | 1882 "PasswordManager.KeychainMigration.NumChromeOwnedInaccessiblePasswords", |
| 1862 2, 1); | 1883 2, 1); |
| 1863 // Don't test the encryption key access. | 1884 // Don't test the encryption key access. |
| 1864 histogram_tester_.reset(); | 1885 histogram_tester_.reset(); |
| 1865 } | 1886 } |
| OLD | NEW |