1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/basictypes.h"
7 #include "base/bind_helpers.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/stl_util.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/synchronization/waitable_event.h"
14 #include "base/time/time.h"
15 #include "components/password_manager/core/browser/password_form_data.h"
16 #include "components/password_manager/core/browser/password_store_change.h"
17 #include "components/password_manager/core/browser/password_store_consumer.h"
18 #include "components/password_manager/core/browser/password_store_default.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 using autofill::PasswordForm;
23 using base::WaitableEvent;
26 using testing::ElementsAreArray;
27 using testing::Pointee;
28 using testing::Property;
29 using testing::WithArg;
31 namespace password_manager {
35 class MockPasswordStoreConsumer : public PasswordStoreConsumer {
37 MOCK_METHOD1(OnGetPasswordStoreResults,
38 void(const std::vector<PasswordForm*>&));
41 class MockPasswordStoreObserver : public PasswordStore::Observer {
43 MOCK_METHOD1(OnLoginsChanged,
44 void(const PasswordStoreChangeList& changes));
47 } // anonymous namespace
49 class PasswordStoreDefaultTest : public testing::Test {
51 virtual void SetUp() OVERRIDE {
52 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
53 login_db_.reset(new LoginDatabase());
54 ASSERT_TRUE(login_db_->Init(temp_dir_.path().Append(
55 FILE_PATH_LITERAL("login_test"))));
58 virtual void TearDown() OVERRIDE {
59 ASSERT_TRUE(temp_dir_.Delete());
62 base::MessageLoopForUI message_loop_;
63 scoped_ptr<LoginDatabase> login_db_;
64 base::ScopedTempDir temp_dir_;
67 ACTION(STLDeleteElements0) {
68 STLDeleteContainerPointers(arg0.begin(), arg0.end());
71 TEST_F(PasswordStoreDefaultTest, NonASCIIData) {
72 scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
73 base::MessageLoopProxy::current(),
74 base::MessageLoopProxy::current(),
75 login_db_.release()));
76 store->Init(syncer::SyncableService::StartSyncFlare(), "");
78 // Some non-ASCII password form data.
79 static const PasswordFormData form_data[] = {
80 { PasswordForm::SCHEME_HTML,
81 "http://foo.example.com",
82 "http://foo.example.com/origin",
83 "http://foo.example.com/action",
92 // Build the expected forms vector and add the forms to the store.
93 std::vector<PasswordForm*> expected_forms;
94 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(form_data); ++i) {
95 PasswordForm* form = CreatePasswordFormFromData(form_data[i]);
96 expected_forms.push_back(form);
97 store->AddLogin(*form);
100 base::MessageLoop::current()->RunUntilIdle();
102 MockPasswordStoreConsumer consumer;
104 // We expect to get the same data back, even though it's not all ASCII.
105 EXPECT_CALL(consumer,
106 OnGetPasswordStoreResults(ContainsAllPasswordForms(expected_forms)))
107 .WillOnce(WithArg<0>(STLDeleteElements0()));
108 store->GetAutofillableLogins(&consumer);
110 base::MessageLoop::current()->RunUntilIdle();
112 STLDeleteElements(&expected_forms);
114 base::MessageLoop::current()->RunUntilIdle();
117 TEST_F(PasswordStoreDefaultTest, Notifications) {
118 scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
119 base::MessageLoopProxy::current(),
120 base::MessageLoopProxy::current(),
121 login_db_.release()));
122 store->Init(syncer::SyncableService::StartSyncFlare(), "");
124 PasswordFormData form_data =
125 { PasswordForm::SCHEME_HTML,
126 "http://bar.example.com",
127 "http://bar.example.com/origin",
128 "http://bar.example.com/action",
135 scoped_ptr<PasswordForm> form(CreatePasswordFormFromData(form_data));
137 MockPasswordStoreObserver observer;
138 store->AddObserver(&observer);
140 const PasswordStoreChange expected_add_changes[] = {
141 PasswordStoreChange(PasswordStoreChange::ADD, *form),
146 OnLoginsChanged(ElementsAreArray(expected_add_changes)));
148 // Adding a login should trigger a notification.
149 store->AddLogin(*form);
150 base::MessageLoop::current()->RunUntilIdle();
152 // Change the password.
153 form->password_value = base::ASCIIToUTF16("a different password");
155 const PasswordStoreChange expected_update_changes[] = {
156 PasswordStoreChange(PasswordStoreChange::UPDATE, *form),
161 OnLoginsChanged(ElementsAreArray(expected_update_changes)));
163 // Updating the login with the new password should trigger a notification.
164 store->UpdateLogin(*form);
165 base::MessageLoop::current()->RunUntilIdle();
167 const PasswordStoreChange expected_delete_changes[] = {
168 PasswordStoreChange(PasswordStoreChange::REMOVE, *form),
173 OnLoginsChanged(ElementsAreArray(expected_delete_changes)));
175 // Deleting the login should trigger a notification.
176 store->RemoveLogin(*form);
177 base::MessageLoop::current()->RunUntilIdle();
179 store->RemoveObserver(&observer);
181 base::MessageLoop::current()->RunUntilIdle();
184 } // namespace password_manager