Update mojo surfaces bindings and mojo/cc/ glue
[chromium-blink-merge.git] / chrome / browser / password_manager / password_store_win_unittest.cc
blob77579e6569bb7721db66130e6660683eea8e42fc
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 <windows.h>
6 #include <wincrypt.h>
7 #include <string>
8 #include <vector>
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/prefs/pref_service.h"
16 #include "base/stl_util.h"
17 #include "base/synchronization/waitable_event.h"
18 #include "base/time/time.h"
19 #include "chrome/browser/password_manager/password_store_win.h"
20 #include "chrome/test/base/testing_profile.h"
21 #include "components/os_crypt/ie7_password_win.h"
22 #include "components/password_manager/core/browser/password_form_data.h"
23 #include "components/password_manager/core/browser/password_store_consumer.h"
24 #include "components/password_manager/core/browser/webdata/logins_table.h"
25 #include "components/password_manager/core/browser/webdata/password_web_data_service_win.h"
26 #include "components/password_manager/core/common/password_manager_pref_names.h"
27 #include "components/webdata/common/web_database_service.h"
28 #include "content/public/test/test_browser_thread.h"
29 #include "testing/gmock/include/gmock/gmock.h"
30 #include "testing/gtest/include/gtest/gtest.h"
32 using autofill::PasswordForm;
33 using base::WaitableEvent;
34 using content::BrowserThread;
35 using password_manager::LoginDatabase;
36 using password_manager::ContainsAllPasswordForms;
37 using password_manager::PasswordFormData;
38 using password_manager::PasswordStore;
39 using password_manager::PasswordStoreConsumer;
40 using testing::_;
41 using testing::DoAll;
42 using testing::WithArg;
44 namespace {
46 class MockPasswordStoreConsumer : public PasswordStoreConsumer {
47 public:
48 MOCK_METHOD1(OnGetPasswordStoreResults,
49 void(const std::vector<autofill::PasswordForm*>&));
52 class MockWebDataServiceConsumer : public WebDataServiceConsumer {
53 public:
54 MOCK_METHOD2(OnWebDataServiceRequestDone,
55 void(PasswordWebDataService::Handle, const WDTypedResult*));
58 } // anonymous namespace
60 typedef std::vector<PasswordForm*> VectorOfForms;
62 class PasswordStoreWinTest : public testing::Test {
63 protected:
64 PasswordStoreWinTest()
65 : ui_thread_(BrowserThread::UI, &message_loop_),
66 db_thread_(BrowserThread::DB) {
69 bool CreateIE7PasswordInfo(const std::wstring& url, const base::Time& created,
70 IE7PasswordInfo* info) {
71 // Copied from chrome/browser/importer/importer_unittest.cc
72 // The username is "abcdefgh" and the password "abcdefghijkl".
73 unsigned char data[] = "\x0c\x00\x00\x00\x38\x00\x00\x00\x2c\x00\x00\x00"
74 "\x57\x49\x43\x4b\x18\x00\x00\x00\x02\x00\x00\x00"
75 "\x67\x00\x72\x00\x01\x00\x00\x00\x00\x00\x00\x00"
76 "\x00\x00\x00\x00\x4e\xfa\x67\x76\x22\x94\xc8\x01"
77 "\x08\x00\x00\x00\x12\x00\x00\x00\x4e\xfa\x67\x76"
78 "\x22\x94\xc8\x01\x0c\x00\x00\x00\x61\x00\x62\x00"
79 "\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00"
80 "\x00\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00"
81 "\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00"
82 "\x6c\x00\x00\x00";
83 DATA_BLOB input = {0};
84 DATA_BLOB url_key = {0};
85 DATA_BLOB output = {0};
87 input.pbData = data;
88 input.cbData = sizeof(data);
90 url_key.pbData = reinterpret_cast<unsigned char*>(
91 const_cast<wchar_t*>(url.data()));
92 url_key.cbData = static_cast<DWORD>((url.size() + 1) *
93 sizeof(std::wstring::value_type));
95 if (!CryptProtectData(&input, NULL, &url_key, NULL, NULL,
96 CRYPTPROTECT_UI_FORBIDDEN, &output))
97 return false;
99 std::vector<unsigned char> encrypted_data;
100 encrypted_data.resize(output.cbData);
101 memcpy(&encrypted_data.front(), output.pbData, output.cbData);
103 LocalFree(output.pbData);
105 info->url_hash = ie7_password::GetUrlHash(url);
106 info->encrypted_data = encrypted_data;
107 info->date_created = created;
109 return true;
112 virtual void SetUp() {
113 ASSERT_TRUE(db_thread_.Start());
114 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
116 profile_.reset(new TestingProfile());
118 login_db_.reset(new LoginDatabase());
119 ASSERT_TRUE(login_db_->Init(temp_dir_.path().Append(
120 FILE_PATH_LITERAL("login_test"))));
121 base::FilePath path = temp_dir_.path().AppendASCII("web_data_test");
122 wdbs_ = new WebDatabaseService(path,
123 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
124 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB));
125 // Need to add at least one table so the database gets created.
126 wdbs_->AddTable(scoped_ptr<WebDatabaseTable>(new LoginsTable()));
127 wdbs_->LoadDatabase();
128 wds_ = new PasswordWebDataService(
129 wdbs_,
130 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
131 WebDataServiceBase::ProfileErrorCallback());
132 wds_->Init();
135 virtual void TearDown() {
136 if (store_)
137 store_->Shutdown();
138 wds_->ShutdownOnUIThread();
139 wdbs_->ShutdownDatabase();
140 wds_ = NULL;
141 wdbs_ = NULL;
142 base::WaitableEvent done(false, false);
143 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
144 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done)));
145 done.Wait();
146 base::MessageLoop::current()->PostTask(FROM_HERE,
147 base::MessageLoop::QuitClosure());
148 base::MessageLoop::current()->Run();
149 db_thread_.Stop();
152 PasswordStoreWin* CreatePasswordStore() {
153 return new PasswordStoreWin(
154 base::MessageLoopProxy::current(),
155 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB),
156 login_db_.release(),
157 wds_.get());
160 base::MessageLoopForUI message_loop_;
161 content::TestBrowserThread ui_thread_;
162 // PasswordStore, WDS schedule work on this thread.
163 content::TestBrowserThread db_thread_;
165 base::ScopedTempDir temp_dir_;
166 scoped_ptr<TestingProfile> profile_;
167 scoped_ptr<LoginDatabase> login_db_;
168 scoped_refptr<PasswordWebDataService> wds_;
169 scoped_refptr<WebDatabaseService> wdbs_;
170 scoped_refptr<PasswordStore> store_;
173 ACTION(STLDeleteElements0) {
174 STLDeleteContainerPointers(arg0.begin(), arg0.end());
177 ACTION(QuitUIMessageLoop) {
178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
179 base::MessageLoop::current()->Quit();
182 MATCHER(EmptyWDResult, "") {
183 return static_cast<const WDResult<std::vector<PasswordForm*> >*>(
184 arg)->GetValue().empty();
187 // Hangs flakily, http://crbug.com/71385.
188 TEST_F(PasswordStoreWinTest, DISABLED_ConvertIE7Login) {
189 IE7PasswordInfo password_info;
190 ASSERT_TRUE(CreateIE7PasswordInfo(L"http://example.com/origin",
191 base::Time::FromDoubleT(1),
192 &password_info));
193 // Verify the URL hash
194 ASSERT_EQ(L"39471418FF5453FEEB3731E382DEB5D53E14FAF9B5",
195 password_info.url_hash);
197 // This IE7 password will be retrieved by the GetLogins call.
198 wds_->AddIE7Login(password_info);
200 // The WDS schedules tasks to run on the DB thread so we schedule yet another
201 // task to notify us that it's safe to carry on with the test.
202 WaitableEvent done(false, false);
203 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
204 base::Bind(&WaitableEvent::Signal, base::Unretained(&done)));
205 done.Wait();
207 store_ = CreatePasswordStore();
208 EXPECT_TRUE(store_->Init(syncer::SyncableService::StartSyncFlare(), ""));
210 MockPasswordStoreConsumer consumer;
212 // Make sure we quit the MessageLoop even if the test fails.
213 ON_CALL(consumer, OnGetPasswordStoreResults(_))
214 .WillByDefault(QuitUIMessageLoop());
216 PasswordFormData form_data = {
217 PasswordForm::SCHEME_HTML,
218 "http://example.com/",
219 "http://example.com/origin",
220 "http://example.com/action",
221 L"submit_element",
222 L"username_element",
223 L"password_element",
224 L"",
225 L"",
226 true, false, 1,
228 scoped_ptr<PasswordForm> form(CreatePasswordFormFromData(form_data));
230 // The returned form will not have 'action' or '*_element' fields set. This
231 // is because credentials imported from IE don't have this information.
232 PasswordFormData expected_form_data = {
233 PasswordForm::SCHEME_HTML,
234 "http://example.com/",
235 "http://example.com/origin",
237 L"",
238 L"",
239 L"",
240 L"abcdefgh",
241 L"abcdefghijkl",
242 true, false, 1,
244 std::vector<PasswordForm*> forms;
245 forms.push_back(CreatePasswordFormFromData(expected_form_data));
247 // The IE7 password should be returned.
248 EXPECT_CALL(consumer,
249 OnGetPasswordStoreResults(ContainsAllPasswordForms(forms)))
250 .WillOnce(QuitUIMessageLoop());
252 store_->GetLogins(*form, PasswordStore::DISALLOW_PROMPT, &consumer);
253 base::MessageLoop::current()->Run();
255 STLDeleteElements(&forms);
258 // Crashy. http://crbug.com/86558
259 TEST_F(PasswordStoreWinTest, DISABLED_OutstandingWDSQueries) {
260 store_ = CreatePasswordStore();
261 EXPECT_TRUE(store_->Init(syncer::SyncableService::StartSyncFlare(), ""));
263 PasswordFormData form_data = {
264 PasswordForm::SCHEME_HTML,
265 "http://example.com/",
266 "http://example.com/origin",
267 "http://example.com/action",
268 L"submit_element",
269 L"username_element",
270 L"password_element",
271 L"",
272 L"",
273 true, false, 1,
275 scoped_ptr<PasswordForm> form(CreatePasswordFormFromData(form_data));
277 MockPasswordStoreConsumer consumer;
278 store_->GetLogins(*form, PasswordStore::DISALLOW_PROMPT, &consumer);
280 // Release the PSW and the WDS before the query can return.
281 store_->Shutdown();
282 store_ = NULL;
283 wds_ = NULL;
285 base::MessageLoop::current()->RunUntilIdle();
288 // Hangs flakily, see http://crbug.com/43836.
289 TEST_F(PasswordStoreWinTest, DISABLED_MultipleWDSQueriesOnDifferentThreads) {
290 IE7PasswordInfo password_info;
291 ASSERT_TRUE(CreateIE7PasswordInfo(L"http://example.com/origin",
292 base::Time::FromDoubleT(1),
293 &password_info));
294 wds_->AddIE7Login(password_info);
296 // The WDS schedules tasks to run on the DB thread so we schedule yet another
297 // task to notify us that it's safe to carry on with the test.
298 WaitableEvent done(false, false);
299 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
300 base::Bind(&WaitableEvent::Signal, base::Unretained(&done)));
301 done.Wait();
303 store_ = CreatePasswordStore();
304 EXPECT_TRUE(store_->Init(syncer::SyncableService::StartSyncFlare(), ""));
306 MockPasswordStoreConsumer password_consumer;
307 // Make sure we quit the MessageLoop even if the test fails.
308 ON_CALL(password_consumer, OnGetPasswordStoreResults(_))
309 .WillByDefault(QuitUIMessageLoop());
311 PasswordFormData form_data = {
312 PasswordForm::SCHEME_HTML,
313 "http://example.com/",
314 "http://example.com/origin",
315 "http://example.com/action",
316 L"submit_element",
317 L"username_element",
318 L"password_element",
319 L"",
320 L"",
321 true, false, 1,
323 scoped_ptr<PasswordForm> form(CreatePasswordFormFromData(form_data));
325 PasswordFormData expected_form_data = {
326 PasswordForm::SCHEME_HTML,
327 "http://example.com/",
328 "http://example.com/origin",
329 "http://example.com/action",
330 L"submit_element",
331 L"username_element",
332 L"password_element",
333 L"abcdefgh",
334 L"abcdefghijkl",
335 true, false, 1,
337 std::vector<PasswordForm*> forms;
338 forms.push_back(CreatePasswordFormFromData(expected_form_data));
340 // The IE7 password should be returned.
341 EXPECT_CALL(password_consumer,
342 OnGetPasswordStoreResults(ContainsAllPasswordForms(forms)))
343 .WillOnce(QuitUIMessageLoop());
345 store_->GetLogins(*form, PasswordStore::DISALLOW_PROMPT, &password_consumer);
347 MockWebDataServiceConsumer wds_consumer;
349 EXPECT_CALL(wds_consumer,
350 OnWebDataServiceRequestDone(_, _))
351 .WillOnce(QuitUIMessageLoop());
353 wds_->GetIE7Login(password_info, &wds_consumer);
355 // Run the MessageLoop twice: once for the GetIE7Login that PasswordStoreWin
356 // schedules on the DB thread and once for the one we just scheduled on the UI
357 // thread.
358 base::MessageLoop::current()->Run();
359 base::MessageLoop::current()->Run();
361 STLDeleteElements(&forms);
364 TEST_F(PasswordStoreWinTest, EmptyLogins) {
365 store_ = CreatePasswordStore();
366 store_->Init(syncer::SyncableService::StartSyncFlare(), "");
368 PasswordFormData form_data = {
369 PasswordForm::SCHEME_HTML,
370 "http://example.com/",
371 "http://example.com/origin",
372 "http://example.com/action",
373 L"submit_element",
374 L"username_element",
375 L"password_element",
376 L"",
377 L"",
378 true, false, 1,
380 scoped_ptr<PasswordForm> form(CreatePasswordFormFromData(form_data));
382 MockPasswordStoreConsumer consumer;
384 // Make sure we quit the MessageLoop even if the test fails.
385 ON_CALL(consumer, OnGetPasswordStoreResults(_))
386 .WillByDefault(QuitUIMessageLoop());
388 VectorOfForms expect_none;
389 // expect that we get no results;
390 EXPECT_CALL(consumer,
391 OnGetPasswordStoreResults(ContainsAllPasswordForms(expect_none)))
392 .WillOnce(DoAll(WithArg<0>(STLDeleteElements0()), QuitUIMessageLoop()));
394 store_->GetLogins(*form, PasswordStore::DISALLOW_PROMPT, &consumer);
395 base::MessageLoop::current()->Run();
398 TEST_F(PasswordStoreWinTest, EmptyBlacklistLogins) {
399 store_ = CreatePasswordStore();
400 store_->Init(syncer::SyncableService::StartSyncFlare(), "");
402 MockPasswordStoreConsumer consumer;
404 // Make sure we quit the MessageLoop even if the test fails.
405 ON_CALL(consumer, OnGetPasswordStoreResults(_))
406 .WillByDefault(QuitUIMessageLoop());
408 VectorOfForms expect_none;
409 // expect that we get no results;
410 EXPECT_CALL(
411 consumer,
412 OnGetPasswordStoreResults(ContainsAllPasswordForms(expect_none)))
413 .WillOnce(DoAll(WithArg<0>(STLDeleteElements0()), QuitUIMessageLoop()));
415 store_->GetBlacklistLogins(&consumer);
416 base::MessageLoop::current()->Run();
419 TEST_F(PasswordStoreWinTest, EmptyAutofillableLogins) {
420 store_ = CreatePasswordStore();
421 store_->Init(syncer::SyncableService::StartSyncFlare(), "");
423 MockPasswordStoreConsumer consumer;
425 // Make sure we quit the MessageLoop even if the test fails.
426 ON_CALL(consumer, OnGetPasswordStoreResults(_))
427 .WillByDefault(QuitUIMessageLoop());
429 VectorOfForms expect_none;
430 // expect that we get no results;
431 EXPECT_CALL(
432 consumer,
433 OnGetPasswordStoreResults(ContainsAllPasswordForms(expect_none)))
434 .WillOnce(DoAll(WithArg<0>(STLDeleteElements0()), QuitUIMessageLoop()));
436 store_->GetAutofillableLogins(&consumer);
437 base::MessageLoop::current()->Run();