Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / components / password_manager / core / browser / password_store_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 "base/basictypes.h"
6 #include "base/bind.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/stl_util.h"
9 #include "base/strings/string_util.h"
10 #include "base/synchronization/waitable_event.h"
11 #include "base/time/time.h"
12 #include "components/password_manager/core/browser/password_form_data.h"
13 #include "components/password_manager/core/browser/password_store_consumer.h"
14 #include "components/password_manager/core/browser/password_store_default.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 using autofill::PasswordForm;
19 using base::WaitableEvent;
20 using testing::_;
21 using testing::DoAll;
22 using testing::WithArg;
23
24 namespace password_manager {
25
26 namespace {
27
28 class MockPasswordStoreConsumer : public PasswordStoreConsumer {
29  public:
30   MOCK_METHOD1(OnGetPasswordStoreResults,
31                void(const std::vector<PasswordForm*>&));
32 };
33
34 class StartSyncFlareMock {
35  public:
36   StartSyncFlareMock() {}
37   ~StartSyncFlareMock() {}
38
39   MOCK_METHOD1(StartSyncFlare, void(syncer::ModelType));
40 };
41
42 }  // namespace
43
44 class PasswordStoreTest : public testing::Test {
45  protected:
46   virtual void SetUp() OVERRIDE {
47     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
48     login_db_.reset(new LoginDatabase());
49     ASSERT_TRUE(login_db_->Init(temp_dir_.path().Append(
50         FILE_PATH_LITERAL("login_test"))));
51   }
52
53   virtual void TearDown() OVERRIDE {
54     ASSERT_TRUE(temp_dir_.Delete());
55   }
56
57   base::MessageLoopForUI message_loop_;
58   scoped_ptr<LoginDatabase> login_db_;
59   base::ScopedTempDir temp_dir_;
60 };
61
62 ACTION(STLDeleteElements0) {
63   STLDeleteContainerPointers(arg0.begin(), arg0.end());
64 }
65
66 TEST_F(PasswordStoreTest, IgnoreOldWwwGoogleLogins) {
67   scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
68       base::MessageLoopProxy::current(),
69       base::MessageLoopProxy::current(),
70       login_db_.release()));
71   store->Init(syncer::SyncableService::StartSyncFlare(), "");
72
73   const time_t cutoff = 1325376000;  // 00:00 Jan 1 2012 UTC
74   // The passwords are all empty because PasswordStoreDefault doesn't store the
75   // actual passwords on OS X (they're stored in the Keychain instead). We could
76   // special-case it, but it's easier to just have empty passwords.
77   static const PasswordFormData form_data[] = {
78     // A form on https://www.google.com/ older than the cutoff. Will be ignored.
79     { PasswordForm::SCHEME_HTML,
80       "https://www.google.com",
81       "https://www.google.com/origin",
82       "https://www.google.com/action",
83       L"submit_element",
84       L"username_element",
85       L"password_element",
86       L"username_value_1",
87       L"",
88       true, true, cutoff - 1 },
89     // A form on https://www.google.com/ older than the cutoff. Will be ignored.
90     { PasswordForm::SCHEME_HTML,
91       "https://www.google.com",
92       "https://www.google.com/origin",
93       "https://www.google.com/action",
94       L"submit_element",
95       L"username_element",
96       L"password_element",
97       L"username_value_2",
98       L"",
99       true, true, cutoff - 1 },
100     // A form on https://www.google.com/ newer than the cutoff.
101     { PasswordForm::SCHEME_HTML,
102       "https://www.google.com",
103       "https://www.google.com/origin",
104       "https://www.google.com/action",
105       L"submit_element",
106       L"username_element",
107       L"password_element",
108       L"username_value_3",
109       L"",
110       true, true, cutoff + 1 },
111     // A form on https://accounts.google.com/ older than the cutoff.
112     { PasswordForm::SCHEME_HTML,
113       "https://accounts.google.com",
114       "https://accounts.google.com/origin",
115       "https://accounts.google.com/action",
116       L"submit_element",
117       L"username_element",
118       L"password_element",
119       L"username_value",
120       L"",
121       true, true, cutoff - 1 },
122     // A form on http://bar.example.com/ older than the cutoff.
123     { PasswordForm::SCHEME_HTML,
124       "http://bar.example.com",
125       "http://bar.example.com/origin",
126       "http://bar.example.com/action",
127       L"submit_element",
128       L"username_element",
129       L"password_element",
130       L"username_value",
131       L"",
132       true, false, cutoff - 1 },
133   };
134
135   // Build the forms vector and add the forms to the store.
136   std::vector<PasswordForm*> all_forms;
137   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(form_data); ++i) {
138     PasswordForm* form = CreatePasswordFormFromData(form_data[i]);
139     all_forms.push_back(form);
140     store->AddLogin(*form);
141   }
142   base::MessageLoop::current()->RunUntilIdle();
143
144   // We expect to get back only the "recent" www.google.com login.
145   // Theoretically these should never actually exist since there are no longer
146   // any login forms on www.google.com to save, but we technically allow them.
147   // We should not get back the older saved password though.
148   PasswordForm www_google;
149   www_google.scheme = PasswordForm::SCHEME_HTML;
150   www_google.signon_realm = "https://www.google.com";
151   std::vector<PasswordForm*> www_google_expected;
152   www_google_expected.push_back(all_forms[2]);
153
154   // We should still get the accounts.google.com login even though it's older
155   // than our cutoff - this is the new location of all Google login forms.
156   PasswordForm accounts_google;
157   accounts_google.scheme = PasswordForm::SCHEME_HTML;
158   accounts_google.signon_realm = "https://accounts.google.com";
159   std::vector<PasswordForm*> accounts_google_expected;
160   accounts_google_expected.push_back(all_forms[3]);
161
162   // Same thing for a generic saved login.
163   PasswordForm bar_example;
164   bar_example.scheme = PasswordForm::SCHEME_HTML;
165   bar_example.signon_realm = "http://bar.example.com";
166   std::vector<PasswordForm*> bar_example_expected;
167   bar_example_expected.push_back(all_forms[4]);
168
169   MockPasswordStoreConsumer consumer;
170
171   // Expect the appropriate replies, as above, in reverse order than we will
172   // issue the queries. Each retires on saturation to avoid matcher spew.
173   EXPECT_CALL(consumer,
174       OnGetPasswordStoreResults(ContainsAllPasswordForms(bar_example_expected)))
175       .WillOnce(WithArg<0>(STLDeleteElements0())).RetiresOnSaturation();
176   EXPECT_CALL(consumer,
177       OnGetPasswordStoreResults(
178           ContainsAllPasswordForms(accounts_google_expected)))
179       .WillOnce(WithArg<0>(STLDeleteElements0())).RetiresOnSaturation();
180   EXPECT_CALL(consumer,
181       OnGetPasswordStoreResults(
182           ContainsAllPasswordForms(www_google_expected)))
183       .WillOnce(WithArg<0>(STLDeleteElements0())).RetiresOnSaturation();
184
185   store->GetLogins(www_google, PasswordStore::ALLOW_PROMPT, &consumer);
186   store->GetLogins(accounts_google, PasswordStore::ALLOW_PROMPT, &consumer);
187   store->GetLogins(bar_example, PasswordStore::ALLOW_PROMPT, &consumer);
188
189   base::MessageLoop::current()->RunUntilIdle();
190
191   STLDeleteElements(&all_forms);
192   store->Shutdown();
193   base::MessageLoop::current()->RunUntilIdle();
194 }
195
196 TEST_F(PasswordStoreTest, StartSyncFlare) {
197   scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
198       base::MessageLoopProxy::current(),
199       base::MessageLoopProxy::current(),
200       login_db_.release()));
201   StartSyncFlareMock mock;
202   store->Init(base::Bind(&StartSyncFlareMock::StartSyncFlare,
203                          base::Unretained(&mock)),
204               "");
205   {
206     PasswordForm form;
207     EXPECT_CALL(mock, StartSyncFlare(syncer::PASSWORDS));
208     store->AddLogin(form);
209     base::MessageLoop::current()->RunUntilIdle();
210   }
211   store->Shutdown();
212   base::MessageLoop::current()->RunUntilIdle();
213 }
214
215 }  // namespace password_manager