[Password Manager] Remove NOTIFICATION_LOGINS_CHANGED
[chromium-blink-merge.git] / chrome / browser / password_manager / password_store_default_unittest.cc
blob4bc14e2b1d87e8369b96206a0f8edc5d59f576bd
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"
6 #include "base/bind.h"
7 #include "base/bind_helpers.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/stl_util.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/time/time.h"
14 #include "chrome/browser/chrome_notification_types.h"
15 #include "chrome/browser/password_manager/password_store_change.h"
16 #include "chrome/browser/password_manager/password_store_consumer.h"
17 #include "chrome/browser/password_manager/password_store_default.h"
18 #include "chrome/common/pref_names.h"
19 #include "chrome/test/base/testing_profile.h"
20 #include "components/password_manager/core/browser/password_form_data.h"
21 #include "content/public/browser/notification_details.h"
22 #include "content/public/browser/notification_registrar.h"
23 #include "content/public/browser/notification_source.h"
24 #include "content/public/test/mock_notification_observer.h"
25 #include "content/public/test/test_browser_thread.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
29 using autofill::PasswordForm;
30 using base::WaitableEvent;
31 using content::BrowserThread;
32 using testing::_;
33 using testing::DoAll;
34 using testing::ElementsAreArray;
35 using testing::Pointee;
36 using testing::Property;
37 using testing::WithArg;
39 namespace {
41 class MockPasswordStoreConsumer : public PasswordStoreConsumer {
42 public:
43 MOCK_METHOD1(OnGetPasswordStoreResults,
44 void(const std::vector<PasswordForm*>&));
47 class MockPasswordStoreObserver : public PasswordStore::Observer {
48 public:
49 MOCK_METHOD1(OnLoginsChanged,
50 void(const PasswordStoreChangeList& changes));
53 } // anonymous namespace
55 class PasswordStoreDefaultTest : public testing::Test {
56 protected:
57 PasswordStoreDefaultTest()
58 : ui_thread_(BrowserThread::UI, &message_loop_),
59 db_thread_(BrowserThread::DB) {
62 virtual void SetUp() {
63 ASSERT_TRUE(db_thread_.Start());
65 profile_.reset(new TestingProfile());
67 login_db_.reset(new LoginDatabase());
68 ASSERT_TRUE(login_db_->Init(profile_->GetPath().Append(
69 FILE_PATH_LITERAL("login_test"))));
72 virtual void TearDown() {
73 base::MessageLoop::current()->PostTask(FROM_HERE,
74 base::MessageLoop::QuitClosure());
75 base::MessageLoop::current()->Run();
76 db_thread_.Stop();
79 base::MessageLoopForUI message_loop_;
80 content::TestBrowserThread ui_thread_;
81 // PasswordStore, WDS schedule work on this thread.
82 content::TestBrowserThread db_thread_;
84 scoped_ptr<LoginDatabase> login_db_;
85 scoped_ptr<TestingProfile> profile_;
88 ACTION(STLDeleteElements0) {
89 STLDeleteContainerPointers(arg0.begin(), arg0.end());
92 ACTION(QuitUIMessageLoop) {
93 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
94 base::MessageLoop::current()->Quit();
97 TEST_F(PasswordStoreDefaultTest, NonASCIIData) {
98 scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
99 base::MessageLoopProxy::current(),
100 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB),
101 login_db_.release()));
102 store->Init();
104 // Some non-ASCII password form data.
105 static const PasswordFormData form_data[] = {
106 { PasswordForm::SCHEME_HTML,
107 "http://foo.example.com",
108 "http://foo.example.com/origin",
109 "http://foo.example.com/action",
110 L"มีสีสัน",
111 L"お元気ですか?",
112 L"盆栽",
113 L"أحب كرة",
114 L"£éä국수çà",
115 true, false, 1 },
118 // Build the expected forms vector and add the forms to the store.
119 std::vector<PasswordForm*> expected_forms;
120 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(form_data); ++i) {
121 PasswordForm* form = CreatePasswordFormFromData(form_data[i]);
122 expected_forms.push_back(form);
123 store->AddLogin(*form);
126 // The PasswordStore schedules tasks to run on the DB thread so we schedule
127 // yet another task to notify us that it's safe to carry on with the test.
128 // The PasswordStore doesn't really understand that it's "done" once the tasks
129 // we posted above have completed, so there's no formal notification for that.
130 WaitableEvent done(false, false);
131 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
132 base::Bind(&WaitableEvent::Signal, base::Unretained(&done)));
133 done.Wait();
135 MockPasswordStoreConsumer consumer;
137 // Make sure we quit the MessageLoop even if the test fails.
138 ON_CALL(consumer, OnGetPasswordStoreResults(_))
139 .WillByDefault(QuitUIMessageLoop());
141 // We expect to get the same data back, even though it's not all ASCII.
142 EXPECT_CALL(consumer,
143 OnGetPasswordStoreResults(ContainsAllPasswordForms(expected_forms)))
144 .WillOnce(DoAll(WithArg<0>(STLDeleteElements0()), QuitUIMessageLoop()));
146 store->GetAutofillableLogins(&consumer);
147 base::MessageLoop::current()->Run();
149 STLDeleteElements(&expected_forms);
151 store->Shutdown();
154 TEST_F(PasswordStoreDefaultTest, Notifications) {
155 scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
156 base::MessageLoopProxy::current(),
157 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB),
158 login_db_.release()));
159 store->Init();
161 PasswordFormData form_data =
162 { PasswordForm::SCHEME_HTML,
163 "http://bar.example.com",
164 "http://bar.example.com/origin",
165 "http://bar.example.com/action",
166 L"submit_element",
167 L"username_element",
168 L"password_element",
169 L"username_value",
170 L"password_value",
171 true, false, 1 };
172 scoped_ptr<PasswordForm> form(CreatePasswordFormFromData(form_data));
174 MockPasswordStoreObserver observer;
175 store->AddObserver(&observer);
177 const PasswordStoreChange expected_add_changes[] = {
178 PasswordStoreChange(PasswordStoreChange::ADD, *form),
181 EXPECT_CALL(
182 observer,
183 OnLoginsChanged(ElementsAreArray(expected_add_changes)));
185 // Adding a login should trigger a notification.
186 store->AddLogin(*form);
188 // The PasswordStore schedules tasks to run on the DB thread so we schedule
189 // yet another task to notify us that it's safe to carry on with the test.
190 WaitableEvent done(false, false);
191 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
192 base::Bind(&WaitableEvent::Signal, base::Unretained(&done)));
193 done.Wait();
195 // Notification happens on the same thread that we added the observer on,
196 // so run message loop to get the notification
197 base::MessageLoop::current()->PostTask(
198 FROM_HERE, base::MessageLoop::QuitClosure());
199 base::MessageLoop::current()->Run();
201 // Change the password.
202 form->password_value = base::ASCIIToUTF16("a different password");
204 const PasswordStoreChange expected_update_changes[] = {
205 PasswordStoreChange(PasswordStoreChange::UPDATE, *form),
208 EXPECT_CALL(
209 observer,
210 OnLoginsChanged(ElementsAreArray(expected_update_changes)));
212 // Updating the login with the new password should trigger a notification.
213 store->UpdateLogin(*form);
215 // Wait for PasswordStore to send the notification.
216 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
217 base::Bind(&WaitableEvent::Signal, base::Unretained(&done)));
218 done.Wait();
220 base::MessageLoop::current()->PostTask(
221 FROM_HERE, base::MessageLoop::QuitClosure());
222 base::MessageLoop::current()->Run();
224 const PasswordStoreChange expected_delete_changes[] = {
225 PasswordStoreChange(PasswordStoreChange::REMOVE, *form),
228 EXPECT_CALL(
229 observer,
230 OnLoginsChanged(ElementsAreArray(expected_delete_changes)));
232 // Deleting the login should trigger a notification.
233 store->RemoveLogin(*form);
235 // Wait for PasswordStore to send the notification.
236 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
237 base::Bind(&WaitableEvent::Signal, base::Unretained(&done)));
238 done.Wait();
240 base::MessageLoop::current()->PostTask(
241 FROM_HERE, base::MessageLoop::QuitClosure());
242 base::MessageLoop::current()->Run();
244 store->RemoveObserver(&observer);
245 store->Shutdown();