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