Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(334)

Side by Side Diff: chrome/browser/password_manager/password_store_mac_unittest.cc

Issue 1414463004: Implement origin-based deletion for passwords in PasswordDefaultMac. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@lkgr
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/files/scoped_temp_dir.h" 8 #include "base/files/scoped_temp_dir.h"
9 #include "base/scoped_observer.h" 9 #include "base/scoped_observer.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
11 #include "base/strings/string_util.h" 11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
13 #include "base/synchronization/waitable_event.h" 13 #include "base/synchronization/waitable_event.h"
14 #include "base/test/histogram_tester.h" 14 #include "base/test/histogram_tester.h"
15 #include "base/thread_task_runner_handle.h" 15 #include "base/thread_task_runner_handle.h"
16 #include "chrome/browser/password_manager/password_store_mac_internal.h" 16 #include "chrome/browser/password_manager/password_store_mac_internal.h"
17 #include "chrome/common/chrome_paths.h" 17 #include "chrome/common/chrome_paths.h"
18 #include "components/os_crypt/os_crypt.h" 18 #include "components/os_crypt/os_crypt.h"
19 #include "components/password_manager/core/browser/login_database.h" 19 #include "components/password_manager/core/browser/login_database.h"
20 #include "components/password_manager/core/browser/password_manager_test_utils.h " 20 #include "components/password_manager/core/browser/password_manager_test_utils.h "
21 #include "components/password_manager/core/browser/password_store_common_unittes t.h"
21 #include "components/password_manager/core/browser/password_store_consumer.h" 22 #include "components/password_manager/core/browser/password_store_consumer.h"
22 #include "content/public/test/test_browser_thread.h" 23 #include "content/public/test/test_browser_thread.h"
23 #include "content/public/test/test_utils.h" 24 #include "content/public/test/test_utils.h"
24 #include "crypto/mock_apple_keychain.h" 25 #include "crypto/mock_apple_keychain.h"
25 #include "testing/gmock/include/gmock/gmock.h" 26 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h" 27 #include "testing/gtest/include/gtest/gtest.h"
27 28
28 using autofill::PasswordForm; 29 using autofill::PasswordForm;
29 using base::ASCIIToUTF16; 30 using base::ASCIIToUTF16;
30 using base::WideToUTF16; 31 using base::WideToUTF16;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 public: 68 public:
68 MOCK_METHOD1(OnGetPasswordStoreResultsConstRef, 69 MOCK_METHOD1(OnGetPasswordStoreResultsConstRef,
69 void(const std::vector<PasswordForm*>&)); 70 void(const std::vector<PasswordForm*>&));
70 71
71 // GMock cannot mock methods with move-only args. 72 // GMock cannot mock methods with move-only args.
72 void OnGetPasswordStoreResults(ScopedVector<PasswordForm> results) override { 73 void OnGetPasswordStoreResults(ScopedVector<PasswordForm> results) override {
73 OnGetPasswordStoreResultsConstRef(results.get()); 74 OnGetPasswordStoreResultsConstRef(results.get());
74 } 75 }
75 }; 76 };
76 77
77 class MockPasswordStoreObserver : public PasswordStore::Observer {
78 public:
79 MOCK_METHOD1(OnLoginsChanged,
80 void(const password_manager::PasswordStoreChangeList& changes));
81 };
82
83 // A LoginDatabase that simulates an Init() method that takes a long time. 78 // A LoginDatabase that simulates an Init() method that takes a long time.
84 class SlowToInitLoginDatabase : public password_manager::LoginDatabase { 79 class SlowToInitLoginDatabase : public password_manager::LoginDatabase {
85 public: 80 public:
86 // Creates an instance whose Init() method will block until |event| is 81 // Creates an instance whose Init() method will block until |event| is
87 // signaled. |event| must outlive |this|. 82 // signaled. |event| must outlive |this|.
88 SlowToInitLoginDatabase(const base::FilePath& db_path, 83 SlowToInitLoginDatabase(const base::FilePath& db_path,
89 base::WaitableEvent* event) 84 base::WaitableEvent* event)
90 : password_manager::LoginDatabase(db_path), event_(event) {} 85 : password_manager::LoginDatabase(db_path), event_(event) {}
91 ~SlowToInitLoginDatabase() override {} 86 ~SlowToInitLoginDatabase() override {}
92 87
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 } 162 }
168 } 163 }
169 164
170 PasswordStoreChangeList AddChangeForForm(const PasswordForm& form) { 165 PasswordStoreChangeList AddChangeForForm(const PasswordForm& form) {
171 return PasswordStoreChangeList( 166 return PasswordStoreChangeList(
172 1, PasswordStoreChange(PasswordStoreChange::ADD, form)); 167 1, PasswordStoreChange(PasswordStoreChange::ADD, form));
173 } 168 }
174 169
175 } // namespace 170 } // namespace
176 171
172 namespace password_manager {
vasilii 2015/10/21 16:47:56 You don't need this namespace. Use the anonymous o
Timo Reimann 2015/11/17 23:10:55 Done.
173
174 class PasswordStoreMacTestDelegate {
175 public:
176 PasswordStoreMacTestDelegate()
177 : ui_thread_(BrowserThread::UI, &message_loop_) {
178 initialize();
vasilii 2015/10/21 16:47:56 Method's name should start with a capital letter.
Timo Reimann 2015/11/17 23:10:55 Done.
179 }
180 ~PasswordStoreMacTestDelegate() {
181 ClosePasswordStore();
182 thread_.reset();
183 login_db_.reset();
184 }
185
186 PasswordStoreMac* store() { return store_.get(); }
187
188 void FinishAsyncProcessing() {
189 scoped_refptr<content::MessageLoopRunner> runner =
190 new content::MessageLoopRunner;
191 ASSERT_TRUE(thread_->task_runner()->PostTaskAndReply(
192 FROM_HERE, base::Bind(&Noop), runner->QuitClosure()));
193 runner->Run();
194 }
195
196 base::Thread* thread() { return thread_.get(); }
vasilii 2015/10/21 16:47:56 Why is it needed?
Timo Reimann 2015/11/17 23:10:55 PasswordStoreMacTest.ImportFromKeychain, PasswordS
vasilii 2015/11/18 16:27:42 You can expose a task runner, not a thread.
Timo Reimann 2015/11/18 23:42:14 I use ThreadTaskRunnerHandle now. Hope that's the
197
198 private:
199 base::MessageLoopForUI message_loop_;
vasilii 2015/10/21 16:47:56 Methods should be above. They are complex enough s
Timo Reimann 2015/11/17 23:10:55 Done (for PasswordStoreDefaultTest too).
200 content::TestBrowserThread ui_thread_;
201 // Thread that the synchronous methods are run on.
202 scoped_ptr<base::Thread> thread_;
203
204 base::ScopedTempDir db_dir_;
205 scoped_ptr<LoginDatabase> login_db_;
206 scoped_refptr<PasswordStoreMac> store_;
207
208 static void InitLoginDatabase(LoginDatabase* login_db) {
209 ASSERT_TRUE(login_db->Init());
210 }
211
212 void initialize() {
Timo Reimann 2015/10/20 20:47:09 The initialization of PasswordStoreMac for testing
vasilii 2015/10/21 16:47:56 For your tests you can definitely simplify Passwor
213 ASSERT_TRUE(db_dir_.CreateUniqueTempDir());
214
215 // Ensure that LoginDatabase will use the mock keychain if it needs to
216 // encrypt/decrypt a password.
217 OSCrypt::UseMockKeychain(true);
vasilii 2015/10/21 16:47:56 You just pass the Keychain instance into construct
Timo Reimann 2015/11/17 23:10:55 Which constructor do you mean? The test already pa
218 login_db_.reset(new LoginDatabase(test_login_db_file_path()));
219 thread_.reset(new base::Thread("Chrome_PasswordStore_Thread"));
220 ASSERT_TRUE(thread_->Start());
221 ASSERT_TRUE(thread_->task_runner()->PostTask(
222 FROM_HERE, base::Bind(&PasswordStoreMacTestDelegate::InitLoginDatabase,
223 base::Unretained(login_db_.get()))));
224 CreateAndInitPasswordStore(login_db_.get());
225 // Make sure deferred initialization is performed before some tests start
226 // accessing the |login_db| directly.
227 FinishAsyncProcessing();
228 }
229
230 base::FilePath test_login_db_file_path() const {
231 return db_dir_.path().Append(FILE_PATH_LITERAL("login.db"));
232 }
233
234 void CreateAndInitPasswordStore(LoginDatabase* login_db) {
vasilii 2015/10/21 16:47:56 merge the method into initialize()
Timo Reimann 2015/11/17 23:10:55 Done.
235 store_ = new PasswordStoreMac(
236 base::ThreadTaskRunnerHandle::Get(), nullptr,
237 make_scoped_ptr<AppleKeychain>(new MockAppleKeychain));
238 ASSERT_TRUE(thread_->task_runner()->PostTask(
239 FROM_HERE, base::Bind(&PasswordStoreMac::InitWithTaskRunner, store_,
240 thread_->task_runner())));
241
242 ASSERT_TRUE(thread_->task_runner()->PostTask(
243 FROM_HERE, base::Bind(&PasswordStoreMac::set_login_metadata_db, store_,
244 base::Unretained(login_db))));
245 }
246
247 void ClosePasswordStore() {
248 if (!store_)
vasilii 2015/10/21 16:47:56 It can't be true.
Timo Reimann 2015/11/17 23:10:55 I agree, unless there's a bug where store is attem
vasilii 2015/11/18 16:27:42 Just drop.
Timo Reimann 2015/11/18 23:42:14 Done.
249 return;
250
251 store_->Shutdown();
252 store_ = nullptr;
253 }
254 };
255
256 INSTANTIATE_TYPED_TEST_CASE_P(Mac,
257 PasswordStoreCommonTest,
258 PasswordStoreMacTestDelegate);
259
260 } // namespace password_manager
261
177 #pragma mark - 262 #pragma mark -
178 263
179 class PasswordStoreMacInternalsTest : public testing::Test { 264 class PasswordStoreMacInternalsTest : public testing::Test {
180 public: 265 public:
181 void SetUp() override { 266 void SetUp() override {
182 MockAppleKeychain::KeychainTestData test_data[] = { 267 MockAppleKeychain::KeychainTestData test_data[] = {
183 // Basic HTML form. 268 // Basic HTML form.
184 {kSecAuthenticationTypeHTMLForm, 269 {kSecAuthenticationTypeHTMLForm,
185 "some.domain.com", 270 "some.domain.com",
186 kSecProtocolTypeHTTP, 271 kSecProtocolTypeHTTP,
(...skipping 979 matching lines...) Expand 10 before | Expand all | Expand 10 after
1166 1251
1167 ScopedVector<autofill::PasswordForm> owned_passwords = 1252 ScopedVector<autofill::PasswordForm> owned_passwords =
1168 owned_keychain_adapter.GetAllPasswordFormPasswords(); 1253 owned_keychain_adapter.GetAllPasswordFormPasswords();
1169 EXPECT_EQ(arraysize(owned_password_data), owned_passwords.size()); 1254 EXPECT_EQ(arraysize(owned_password_data), owned_passwords.size());
1170 } 1255 }
1171 1256
1172 #pragma mark - 1257 #pragma mark -
1173 1258
1174 class PasswordStoreMacTest : public testing::Test { 1259 class PasswordStoreMacTest : public testing::Test {
1175 public: 1260 public:
1176 PasswordStoreMacTest() : ui_thread_(BrowserThread::UI, &message_loop_) {} 1261 PasswordStoreMacTest()
1262 : histogram_tester_(new base::HistogramTester),
1263 store_(delegate_.store()) {}
vasilii 2015/10/21 16:47:56 I'm generally against changing this class. Instead
Timo Reimann 2015/11/17 23:10:55 I'm not sure I understand: The delegate was create
1177 1264
1178 void SetUp() override { 1265 ~PasswordStoreMacTest() override {
1179 ASSERT_TRUE(db_dir_.CreateUniqueTempDir());
1180 histogram_tester_.reset(new base::HistogramTester);
1181
1182 // Ensure that LoginDatabase will use the mock keychain if it needs to
1183 // encrypt/decrypt a password.
1184 OSCrypt::UseMockKeychain(true);
1185 login_db_.reset(
1186 new password_manager::LoginDatabase(test_login_db_file_path()));
1187 thread_.reset(new base::Thread("Chrome_PasswordStore_Thread"));
1188 ASSERT_TRUE(thread_->Start());
1189 ASSERT_TRUE(thread_->task_runner()->PostTask(
1190 FROM_HERE, base::Bind(&PasswordStoreMacTest::InitLoginDatabase,
1191 base::Unretained(login_db_.get()))));
1192 CreateAndInitPasswordStore(login_db_.get());
1193 // Make sure deferred initialization is performed before some tests start
1194 // accessing the |login_db| directly.
1195 FinishAsyncProcessing();
1196 }
1197
1198 void TearDown() override {
1199 ClosePasswordStore();
1200 thread_.reset();
1201 login_db_.reset();
1202 // Whatever a test did, PasswordStoreMac stores only empty password values 1266 // Whatever a test did, PasswordStoreMac stores only empty password values
1203 // in LoginDatabase. The empty valus do not require encryption and therefore 1267 // in LoginDatabase. The empty valus do not require encryption and therefore
1204 // 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
1205 // internet passwords. 1269 // internet passwords.
1206 if (histogram_tester_) { 1270 if (histogram_tester_) {
1207 histogram_tester_->ExpectTotalCount("OSX.Keychain.Access", 0); 1271 histogram_tester_->ExpectTotalCount("OSX.Keychain.Access", 0);
1208 } 1272 }
1209 } 1273 }
1210 1274
1211 static void InitLoginDatabase(password_manager::LoginDatabase* login_db) {
1212 ASSERT_TRUE(login_db->Init());
1213 }
1214
1215 void CreateAndInitPasswordStore(password_manager::LoginDatabase* login_db) {
1216 store_ = new PasswordStoreMac(
1217 base::ThreadTaskRunnerHandle::Get(), nullptr,
1218 make_scoped_ptr<AppleKeychain>(new MockAppleKeychain));
1219 ASSERT_TRUE(thread_->task_runner()->PostTask(
1220 FROM_HERE, base::Bind(&PasswordStoreMac::InitWithTaskRunner, store_,
1221 thread_->task_runner())));
1222
1223 ASSERT_TRUE(thread_->task_runner()->PostTask(
1224 FROM_HERE, base::Bind(&PasswordStoreMac::set_login_metadata_db, store_,
1225 base::Unretained(login_db))));
1226 }
1227
1228 void ClosePasswordStore() {
1229 if (!store_)
1230 return;
1231
1232 store_->Shutdown();
1233 store_ = nullptr;
1234 }
1235
1236 // 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
1237 // retrieved by FillMatchingLogins() and GetAutofillableLogins(), and then it 1276 // retrieved by FillMatchingLogins() and GetAutofillableLogins(), and then it
1238 // can be properly removed. 1277 // can be properly removed.
1239 void VerifyCredentialLifecycle(const PasswordForm& form) { 1278 void VerifyCredentialLifecycle(const PasswordForm& form) {
1240 // 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
1241 // prevent storing the form a second time. 1280 // prevent storing the form a second time.
1242 for (size_t iteration = 0; iteration < 2; ++iteration) { 1281 for (size_t iteration = 0; iteration < 2; ++iteration) {
1243 SCOPED_TRACE(testing::Message("Iteration: ") << iteration); 1282 SCOPED_TRACE(testing::Message("Iteration: ") << iteration);
1244 1283
1245 MockPasswordStoreConsumer mock_consumer; 1284 MockPasswordStoreConsumer mock_consumer;
1246 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(IsEmpty())) 1285 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(IsEmpty()))
1247 .WillOnce(QuitUIMessageLoop()); 1286 .WillOnce(QuitUIMessageLoop());
1248 store()->GetAutofillableLogins(&mock_consumer); 1287 store()->GetAutofillableLogins(&mock_consumer);
1249 base::MessageLoop::current()->Run(); 1288 base::MessageLoop::current()->Run();
1250 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer); 1289 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer);
1251 1290
1252 store()->AddLogin(form); 1291 store()->AddLogin(form);
1253 FinishAsyncProcessing(); 1292 delegate_.FinishAsyncProcessing();
1254 1293
1255 PasswordForm returned_form; 1294 PasswordForm returned_form;
1256 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(SizeIs(1u))) 1295 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(SizeIs(1u)))
1257 .WillOnce( 1296 .WillOnce(
1258 DoAll(SaveACopyOfFirstForm(&returned_form), QuitUIMessageLoop())); 1297 DoAll(SaveACopyOfFirstForm(&returned_form), QuitUIMessageLoop()));
1259 1298
1260 // The query operations will also do some housekeeping: they will remove 1299 // The query operations will also do some housekeeping: they will remove
1261 // dangling credentials in the LoginDatabase without a matching Keychain 1300 // dangling credentials in the LoginDatabase without a matching Keychain
1262 // 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
1263 // 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
(...skipping 12 matching lines...) Expand all
1276 store()->GetLogins(query_form, PasswordStore::ALLOW_PROMPT, 1315 store()->GetLogins(query_form, PasswordStore::ALLOW_PROMPT,
1277 &mock_consumer); 1316 &mock_consumer);
1278 base::MessageLoop::current()->Run(); 1317 base::MessageLoop::current()->Run();
1279 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer); 1318 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer);
1280 EXPECT_EQ(form, returned_form); 1319 EXPECT_EQ(form, returned_form);
1281 1320
1282 store()->RemoveLogin(form); 1321 store()->RemoveLogin(form);
1283 } 1322 }
1284 } 1323 }
1285 1324
1286 base::FilePath test_login_db_file_path() const {
1287 return db_dir_.path().Append(FILE_PATH_LITERAL("login.db"));
1288 }
1289
1290 password_manager::LoginDatabase* login_db() const { 1325 password_manager::LoginDatabase* login_db() const {
1291 return store_->login_metadata_db(); 1326 return store_->login_metadata_db();
1292 } 1327 }
1293 1328
1294 MockAppleKeychain* keychain() { 1329 MockAppleKeychain* keychain() {
1295 return static_cast<MockAppleKeychain*>(store_->keychain()); 1330 return static_cast<MockAppleKeychain*>(store_->keychain());
1296 } 1331 }
1297 1332
1298 void FinishAsyncProcessing() { 1333 PasswordStoreMac* store() { return store_; }
1299 scoped_refptr<content::MessageLoopRunner> runner = 1334
1300 new content::MessageLoopRunner; 1335 password_manager::PasswordStoreMacTestDelegate& delegate() {
1301 ASSERT_TRUE(thread_->task_runner()->PostTaskAndReply( 1336 return delegate_;
1302 FROM_HERE, base::Bind(&Noop), runner->QuitClosure()));
1303 runner->Run();
1304 } 1337 }
1305 1338
1306 PasswordStoreMac* store() { return store_.get(); }
1307
1308 protected: 1339 protected:
1309 base::MessageLoopForUI message_loop_;
1310 content::TestBrowserThread ui_thread_;
1311 // Thread that the synchronous methods are run on.
1312 scoped_ptr<base::Thread> thread_;
1313
1314 base::ScopedTempDir db_dir_;
1315 scoped_ptr<password_manager::LoginDatabase> login_db_;
1316 scoped_refptr<PasswordStoreMac> store_;
1317 scoped_ptr<base::HistogramTester> histogram_tester_; 1340 scoped_ptr<base::HistogramTester> histogram_tester_;
1341 password_manager::PasswordStoreMacTestDelegate delegate_;
1342 PasswordStoreMac* store_;
1318 }; 1343 };
1319 1344
1320 TEST_F(PasswordStoreMacTest, TestStoreUpdate) { 1345 TEST_F(PasswordStoreMacTest, TestStoreUpdate) {
1321 // Insert a password into both the database and the keychain. 1346 // Insert a password into both the database and the keychain.
1322 // This is done manually, rather than through store_->AddLogin, because the 1347 // This is done manually, rather than through store_->AddLogin, because the
1323 // Mock Keychain isn't smart enough to be able to support update generically, 1348 // Mock Keychain isn't smart enough to be able to support update generically,
1324 // so some.domain.com triggers special handling to test it that make inserting 1349 // so some.domain.com triggers special handling to test it that make inserting
1325 // fail. 1350 // fail.
1326 PasswordFormData joint_data = { 1351 PasswordFormData joint_data = {
1327 PasswordForm::SCHEME_HTML, "http://some.domain.com/", 1352 PasswordForm::SCHEME_HTML, "http://some.domain.com/",
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1376 true, false, 2 }, 1401 true, false, 2 },
1377 NULL, 1402 NULL,
1378 }, 1403 },
1379 }; 1404 };
1380 for (unsigned int i = 0; i < arraysize(updates); ++i) { 1405 for (unsigned int i = 0; i < arraysize(updates); ++i) {
1381 scoped_ptr<PasswordForm> form = 1406 scoped_ptr<PasswordForm> form =
1382 CreatePasswordFormFromDataForTesting(updates[i].form_data); 1407 CreatePasswordFormFromDataForTesting(updates[i].form_data);
1383 store_->UpdateLogin(*form); 1408 store_->UpdateLogin(*form);
1384 } 1409 }
1385 1410
1386 FinishAsyncProcessing(); 1411 delegate_.FinishAsyncProcessing();
1387 1412
1388 MacKeychainPasswordFormAdapter keychain_adapter(keychain()); 1413 MacKeychainPasswordFormAdapter keychain_adapter(keychain());
1389 for (unsigned int i = 0; i < arraysize(updates); ++i) { 1414 for (unsigned int i = 0; i < arraysize(updates); ++i) {
1390 scoped_ptr<PasswordForm> query_form = 1415 scoped_ptr<PasswordForm> query_form =
1391 CreatePasswordFormFromDataForTesting(updates[i].form_data); 1416 CreatePasswordFormFromDataForTesting(updates[i].form_data);
1392 1417
1393 ScopedVector<autofill::PasswordForm> matching_items = 1418 ScopedVector<autofill::PasswordForm> matching_items =
1394 keychain_adapter.PasswordsFillingForm(query_form->signon_realm, 1419 keychain_adapter.PasswordsFillingForm(query_form->signon_realm,
1395 query_form->scheme); 1420 query_form->scheme);
1396 if (updates[i].password) { 1421 if (updates[i].password) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1453 // 3. Add the returned password for m.facebook.com. 1478 // 3. Add the returned password for m.facebook.com.
1454 returned_form.signon_realm = "http://m.facebook.com"; 1479 returned_form.signon_realm = "http://m.facebook.com";
1455 returned_form.origin = GURL("http://m.facebook.com/index.html"); 1480 returned_form.origin = GURL("http://m.facebook.com/index.html");
1456 EXPECT_EQ(AddChangeForForm(returned_form), 1481 EXPECT_EQ(AddChangeForForm(returned_form),
1457 login_db()->AddLogin(returned_form)); 1482 login_db()->AddLogin(returned_form));
1458 owned_keychain_adapter.AddPassword(m_form); 1483 owned_keychain_adapter.AddPassword(m_form);
1459 1484
1460 // 4. Remove both passwords. 1485 // 4. Remove both passwords.
1461 store_->RemoveLogin(*www_form); 1486 store_->RemoveLogin(*www_form);
1462 store_->RemoveLogin(m_form); 1487 store_->RemoveLogin(m_form);
1463 FinishAsyncProcessing(); 1488 delegate_.FinishAsyncProcessing();
1464 1489
1465 // No trace of www.facebook.com. 1490 // No trace of www.facebook.com.
1466 ScopedVector<autofill::PasswordForm> matching_items = 1491 ScopedVector<autofill::PasswordForm> matching_items =
1467 owned_keychain_adapter.PasswordsFillingForm(www_form->signon_realm, 1492 owned_keychain_adapter.PasswordsFillingForm(www_form->signon_realm,
1468 www_form->scheme); 1493 www_form->scheme);
1469 EXPECT_EQ(0u, matching_items.size()); 1494 EXPECT_EQ(0u, matching_items.size());
1470 EXPECT_TRUE(login_db()->GetLogins(*www_form, &matching_items)); 1495 EXPECT_TRUE(login_db()->GetLogins(*www_form, &matching_items));
1471 EXPECT_EQ(0u, matching_items.size()); 1496 EXPECT_EQ(0u, matching_items.size());
1472 // No trace of m.facebook.com. 1497 // No trace of m.facebook.com.
1473 matching_items = owned_keychain_adapter.PasswordsFillingForm( 1498 matching_items = owned_keychain_adapter.PasswordsFillingForm(
1474 m_form.signon_realm, m_form.scheme); 1499 m_form.signon_realm, m_form.scheme);
1475 EXPECT_EQ(0u, matching_items.size()); 1500 EXPECT_EQ(0u, matching_items.size());
1476 EXPECT_TRUE(login_db()->GetLogins(m_form, &matching_items)); 1501 EXPECT_TRUE(login_db()->GetLogins(m_form, &matching_items));
1477 EXPECT_EQ(0u, matching_items.size()); 1502 EXPECT_EQ(0u, matching_items.size());
1478 } 1503 }
1479 1504
1480 namespace { 1505 namespace {
1481 1506
1482 class PasswordsChangeObserver : 1507 class PasswordsChangeObserver :
1483 public password_manager::PasswordStore::Observer { 1508 public password_manager::PasswordStore::Observer {
1484 public: 1509 public:
1485 PasswordsChangeObserver(PasswordStoreMac* store) : observer_(this) { 1510 PasswordsChangeObserver(PasswordStoreMac* store) : observer_(this) {
1486 observer_.Add(store); 1511 observer_.Add(store);
1487 } 1512 }
1488 1513
1489 void WaitAndVerify(PasswordStoreMacTest* test) { 1514 void WaitAndVerify(PasswordStoreMacTest* test) {
1490 test->FinishAsyncProcessing(); 1515 test->delegate().FinishAsyncProcessing();
1491 ::testing::Mock::VerifyAndClearExpectations(this); 1516 ::testing::Mock::VerifyAndClearExpectations(this);
1492 } 1517 }
1493 1518
1494 // password_manager::PasswordStore::Observer: 1519 // password_manager::PasswordStore::Observer:
1495 MOCK_METHOD1(OnLoginsChanged, 1520 MOCK_METHOD1(OnLoginsChanged,
1496 void(const password_manager::PasswordStoreChangeList& changes)); 1521 void(const password_manager::PasswordStoreChangeList& changes));
1497 1522
1498 private: 1523 private:
1499 ScopedObserver<password_manager::PasswordStore, 1524 ScopedObserver<password_manager::PasswordStore,
1500 PasswordsChangeObserver> observer_; 1525 PasswordsChangeObserver> observer_;
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
1636 CreatePasswordFormFromDataForTesting(www_form_data1); 1661 CreatePasswordFormFromDataForTesting(www_form_data1);
1637 EXPECT_TRUE(owned_keychain_adapter.AddPassword(*www_form)); 1662 EXPECT_TRUE(owned_keychain_adapter.AddPassword(*www_form));
1638 1663
1639 // Add a password from the current profile. 1664 // Add a password from the current profile.
1640 PasswordFormData www_form_data2 = { 1665 PasswordFormData www_form_data2 = {
1641 PasswordForm::SCHEME_HTML, "http://www.facebook.com/", 1666 PasswordForm::SCHEME_HTML, "http://www.facebook.com/",
1642 "http://www.facebook.com/index.html", "login", L"username", L"password", 1667 "http://www.facebook.com/index.html", "login", L"username", L"password",
1643 L"submit", L"not_joe_user", L"12345", true, false, 1 }; 1668 L"submit", L"not_joe_user", L"12345", true, false, 1 };
1644 www_form = CreatePasswordFormFromDataForTesting(www_form_data2); 1669 www_form = CreatePasswordFormFromDataForTesting(www_form_data2);
1645 store_->AddLogin(*www_form); 1670 store_->AddLogin(*www_form);
1646 FinishAsyncProcessing(); 1671 delegate_.FinishAsyncProcessing();
1647 1672
1648 ScopedVector<PasswordForm> matching_items; 1673 ScopedVector<PasswordForm> matching_items;
1649 EXPECT_TRUE(login_db()->GetLogins(*www_form, &matching_items)); 1674 EXPECT_TRUE(login_db()->GetLogins(*www_form, &matching_items));
1650 EXPECT_EQ(1u, matching_items.size()); 1675 EXPECT_EQ(1u, matching_items.size());
1651 1676
1652 store_->RemoveLoginsCreatedBetween(base::Time(), base::Time(), 1677 store_->RemoveLoginsCreatedBetween(base::Time(), base::Time(),
1653 base::Closure()); 1678 base::Closure());
1654 FinishAsyncProcessing(); 1679 delegate_.FinishAsyncProcessing();
1655 1680
1656 // Check the second facebook form is gone. 1681 // Check the second facebook form is gone.
1657 EXPECT_TRUE(login_db()->GetLogins(*www_form, &matching_items)); 1682 EXPECT_TRUE(login_db()->GetLogins(*www_form, &matching_items));
1658 EXPECT_EQ(0u, matching_items.size()); 1683 EXPECT_EQ(0u, matching_items.size());
1659 1684
1660 // Check the first facebook form is still there. 1685 // Check the first facebook form is still there.
1661 matching_items = owned_keychain_adapter.PasswordsFillingForm( 1686 matching_items = owned_keychain_adapter.PasswordsFillingForm(
1662 www_form->signon_realm, www_form->scheme); 1687 www_form->signon_realm, www_form->scheme);
1663 ASSERT_EQ(1u, matching_items.size()); 1688 ASSERT_EQ(1u, matching_items.size());
1664 EXPECT_EQ(ASCIIToUTF16("joe_user"), matching_items[0]->username_value); 1689 EXPECT_EQ(ASCIIToUTF16("joe_user"), matching_items[0]->username_value);
1665 1690
1666 // Check the third-party password is still there. 1691 // Check the third-party password is still there.
1667 owned_keychain_adapter.SetFindsOnlyOwnedItems(false); 1692 owned_keychain_adapter.SetFindsOnlyOwnedItems(false);
1668 matching_items = owned_keychain_adapter.PasswordsFillingForm( 1693 matching_items = owned_keychain_adapter.PasswordsFillingForm(
1669 "http://some.domain.com/insecure.html", PasswordForm::SCHEME_HTML); 1694 "http://some.domain.com/insecure.html", PasswordForm::SCHEME_HTML);
1670 ASSERT_EQ(1u, matching_items.size()); 1695 ASSERT_EQ(1u, matching_items.size());
1671 } 1696 }
1672 1697
1673 // Add a facebook form to the store but not to the keychain. The form is to be 1698 // Add a facebook form to the store but not to the keychain. The form is to be
1674 // implicitly deleted. However, the observers shouldn't get notified about 1699 // implicitly deleted. However, the observers shouldn't get notified about
1675 // deletion of non-existent forms like m.facebook.com. 1700 // deletion of non-existent forms like m.facebook.com.
1676 TEST_F(PasswordStoreMacTest, SilentlyRemoveOrphanedForm) { 1701 TEST_F(PasswordStoreMacTest, SilentlyRemoveOrphanedForm) {
1677 testing::StrictMock<MockPasswordStoreObserver> mock_observer; 1702 testing::StrictMock<password_manager::MockPasswordStoreObserver>
1703 mock_observer;
1678 store()->AddObserver(&mock_observer); 1704 store()->AddObserver(&mock_observer);
1679 1705
1680 // 1. Add a password for www.facebook.com to the LoginDatabase. 1706 // 1. Add a password for www.facebook.com to the LoginDatabase.
1681 PasswordFormData www_form_data = { 1707 PasswordFormData www_form_data = {
1682 PasswordForm::SCHEME_HTML, "http://www.facebook.com/", 1708 PasswordForm::SCHEME_HTML, "http://www.facebook.com/",
1683 "http://www.facebook.com/index.html", "login", 1709 "http://www.facebook.com/index.html", "login",
1684 L"username", L"password", L"submit", L"joe_user", L"", true, false, 1 1710 L"username", L"password", L"submit", L"joe_user", L"", true, false, 1
1685 }; 1711 };
1686 scoped_ptr<PasswordForm> www_form( 1712 scoped_ptr<PasswordForm> www_form(
1687 CreatePasswordFormFromDataForTesting(www_form_data)); 1713 CreatePasswordFormFromDataForTesting(www_form_data));
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1763 form2.password_value = ASCIIToUTF16("my_password"); 1789 form2.password_value = ASCIIToUTF16("my_password");
1764 1790
1765 PasswordForm blacklisted_form; 1791 PasswordForm blacklisted_form;
1766 blacklisted_form.origin = GURL("http://badsite.com/Login"); 1792 blacklisted_form.origin = GURL("http://badsite.com/Login");
1767 blacklisted_form.signon_realm = "http://badsite.com/"; 1793 blacklisted_form.signon_realm = "http://badsite.com/";
1768 blacklisted_form.blacklisted_by_user = true; 1794 blacklisted_form.blacklisted_by_user = true;
1769 1795
1770 store()->AddLogin(form1); 1796 store()->AddLogin(form1);
1771 store()->AddLogin(form2); 1797 store()->AddLogin(form2);
1772 store()->AddLogin(blacklisted_form); 1798 store()->AddLogin(blacklisted_form);
1773 FinishAsyncProcessing(); 1799 delegate_.FinishAsyncProcessing();
1774 1800
1775 ASSERT_TRUE(base::PostTaskAndReplyWithResult( 1801 ASSERT_TRUE(base::PostTaskAndReplyWithResult(
1776 thread_->task_runner().get(), FROM_HERE, 1802 delegate_.thread()->task_runner().get(), FROM_HERE,
1777 base::Bind(&PasswordStoreMac::ImportFromKeychain, store()), 1803 base::Bind(&PasswordStoreMac::ImportFromKeychain, store()),
1778 base::Bind(&CheckMigrationResult, PasswordStoreMac::MIGRATION_OK))); 1804 base::Bind(&CheckMigrationResult, PasswordStoreMac::MIGRATION_OK)));
1779 FinishAsyncProcessing(); 1805 delegate_.FinishAsyncProcessing();
1780 1806
1781 // The password should be stored in the database by now. 1807 // The password should be stored in the database by now.
1782 ScopedVector<PasswordForm> matching_items; 1808 ScopedVector<PasswordForm> matching_items;
1783 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items)); 1809 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items));
1784 ASSERT_EQ(1u, matching_items.size()); 1810 ASSERT_EQ(1u, matching_items.size());
1785 EXPECT_EQ(form1, *matching_items[0]); 1811 EXPECT_EQ(form1, *matching_items[0]);
1786 1812
1787 EXPECT_TRUE(login_db()->GetLogins(form2, &matching_items)); 1813 EXPECT_TRUE(login_db()->GetLogins(form2, &matching_items));
1788 ASSERT_EQ(1u, matching_items.size()); 1814 ASSERT_EQ(1u, matching_items.size());
1789 EXPECT_EQ(form2, *matching_items[0]); 1815 EXPECT_EQ(form2, *matching_items[0]);
(...skipping 11 matching lines...) Expand all
1801 // Import a federated credential while the Keychain is locked. 1827 // Import a federated credential while the Keychain is locked.
1802 TEST_F(PasswordStoreMacTest, ImportFederatedFromLockedKeychain) { 1828 TEST_F(PasswordStoreMacTest, ImportFederatedFromLockedKeychain) {
1803 keychain()->set_locked(true); 1829 keychain()->set_locked(true);
1804 PasswordForm form1; 1830 PasswordForm form1;
1805 form1.origin = GURL("http://example.com/Login"); 1831 form1.origin = GURL("http://example.com/Login");
1806 form1.signon_realm = "http://example.com/"; 1832 form1.signon_realm = "http://example.com/";
1807 form1.username_value = ASCIIToUTF16("my_username"); 1833 form1.username_value = ASCIIToUTF16("my_username");
1808 form1.federation_url = GURL("https://accounts.google.com/"); 1834 form1.federation_url = GURL("https://accounts.google.com/");
1809 1835
1810 store()->AddLogin(form1); 1836 store()->AddLogin(form1);
1811 FinishAsyncProcessing(); 1837 delegate_.FinishAsyncProcessing();
1812 ASSERT_TRUE(base::PostTaskAndReplyWithResult( 1838 ASSERT_TRUE(base::PostTaskAndReplyWithResult(
1813 thread_->task_runner().get(), FROM_HERE, 1839 delegate_.thread()->task_runner().get(), FROM_HERE,
1814 base::Bind(&PasswordStoreMac::ImportFromKeychain, store()), 1840 base::Bind(&PasswordStoreMac::ImportFromKeychain, store()),
1815 base::Bind(&CheckMigrationResult, PasswordStoreMac::MIGRATION_OK))); 1841 base::Bind(&CheckMigrationResult, PasswordStoreMac::MIGRATION_OK)));
1816 FinishAsyncProcessing(); 1842 delegate_.FinishAsyncProcessing();
1817 1843
1818 ScopedVector<PasswordForm> matching_items; 1844 ScopedVector<PasswordForm> matching_items;
1819 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items)); 1845 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items));
1820 ASSERT_EQ(1u, matching_items.size()); 1846 ASSERT_EQ(1u, matching_items.size());
1821 EXPECT_EQ(form1, *matching_items[0]); 1847 EXPECT_EQ(form1, *matching_items[0]);
1822 } 1848 }
1823 1849
1824 // Try to import while the Keychain is locked but the encryption key had been 1850 // Try to import while the Keychain is locked but the encryption key had been
1825 // read earlier. 1851 // read earlier.
1826 TEST_F(PasswordStoreMacTest, ImportFromLockedKeychainError) { 1852 TEST_F(PasswordStoreMacTest, ImportFromLockedKeychainError) {
1827 PasswordForm form1; 1853 PasswordForm form1;
1828 form1.origin = GURL("http://accounts.google.com/LoginAuth"); 1854 form1.origin = GURL("http://accounts.google.com/LoginAuth");
1829 form1.signon_realm = "http://accounts.google.com/"; 1855 form1.signon_realm = "http://accounts.google.com/";
1830 form1.username_value = ASCIIToUTF16("my_username"); 1856 form1.username_value = ASCIIToUTF16("my_username");
1831 form1.password_value = ASCIIToUTF16("my_password"); 1857 form1.password_value = ASCIIToUTF16("my_password");
1832 store()->AddLogin(form1); 1858 store()->AddLogin(form1);
1833 FinishAsyncProcessing(); 1859 delegate_.FinishAsyncProcessing();
1834 1860
1835 // Add a second keychain item matching the Database entry. 1861 // Add a second keychain item matching the Database entry.
1836 PasswordForm form2 = form1; 1862 PasswordForm form2 = form1;
1837 form2.origin = GURL("http://accounts.google.com/Login"); 1863 form2.origin = GURL("http://accounts.google.com/Login");
1838 form2.password_value = ASCIIToUTF16("1234"); 1864 form2.password_value = ASCIIToUTF16("1234");
1839 MacKeychainPasswordFormAdapter adapter(keychain()); 1865 MacKeychainPasswordFormAdapter adapter(keychain());
1840 EXPECT_TRUE(adapter.AddPassword(form2)); 1866 EXPECT_TRUE(adapter.AddPassword(form2));
1841 1867
1842 keychain()->set_locked(true); 1868 keychain()->set_locked(true);
1843 ASSERT_TRUE(base::PostTaskAndReplyWithResult( 1869 ASSERT_TRUE(base::PostTaskAndReplyWithResult(
1844 thread_->task_runner().get(), FROM_HERE, 1870 delegate_.thread()->task_runner().get(), FROM_HERE,
1845 base::Bind(&PasswordStoreMac::ImportFromKeychain, store()), 1871 base::Bind(&PasswordStoreMac::ImportFromKeychain, store()),
1846 base::Bind(&CheckMigrationResult, PasswordStoreMac::KEYCHAIN_BLOCKED))); 1872 base::Bind(&CheckMigrationResult, PasswordStoreMac::KEYCHAIN_BLOCKED)));
1847 FinishAsyncProcessing(); 1873 delegate_.FinishAsyncProcessing();
1848 1874
1849 ScopedVector<PasswordForm> matching_items; 1875 ScopedVector<PasswordForm> matching_items;
1850 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items)); 1876 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items));
1851 ASSERT_EQ(1u, matching_items.size()); 1877 ASSERT_EQ(1u, matching_items.size());
1852 EXPECT_EQ(base::string16(), matching_items[0]->password_value); 1878 EXPECT_EQ(base::string16(), matching_items[0]->password_value);
1853 1879
1854 histogram_tester_->ExpectUniqueSample( 1880 histogram_tester_->ExpectUniqueSample(
1855 "PasswordManager.KeychainMigration.NumPasswordsOnFailure", 1, 1); 1881 "PasswordManager.KeychainMigration.NumPasswordsOnFailure", 1, 1);
1856 histogram_tester_->ExpectUniqueSample( 1882 histogram_tester_->ExpectUniqueSample(
1857 "PasswordManager.KeychainMigration.NumFailedPasswords", 1, 1); 1883 "PasswordManager.KeychainMigration.NumFailedPasswords", 1, 1);
1858 histogram_tester_->ExpectUniqueSample( 1884 histogram_tester_->ExpectUniqueSample(
1859 "PasswordManager.KeychainMigration.NumChromeOwnedInaccessiblePasswords", 1885 "PasswordManager.KeychainMigration.NumChromeOwnedInaccessiblePasswords",
1860 2, 1); 1886 2, 1);
1861 // Don't test the encryption key access. 1887 // Don't test the encryption key access.
1862 histogram_tester_.reset(); 1888 histogram_tester_.reset();
1863 } 1889 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698