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/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"
18 using autofill::PasswordForm;
19 using base::WaitableEvent;
22 using testing::WithArg;
24 namespace password_manager {
28 class MockPasswordStoreConsumer : public PasswordStoreConsumer {
30 MOCK_METHOD1(OnGetPasswordStoreResults,
31 void(const std::vector<PasswordForm*>&));
34 class StartSyncFlareMock {
36 StartSyncFlareMock() {}
37 ~StartSyncFlareMock() {}
39 MOCK_METHOD1(StartSyncFlare, void(syncer::ModelType));
44 class PasswordStoreTest : public testing::Test {
46 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"))));
53 void TearDown() override { ASSERT_TRUE(temp_dir_.Delete()); }
55 base::MessageLoopForUI message_loop_;
56 scoped_ptr<LoginDatabase> login_db_;
57 base::ScopedTempDir temp_dir_;
60 ACTION(STLDeleteElements0) {
61 STLDeleteContainerPointers(arg0.begin(), arg0.end());
64 TEST_F(PasswordStoreTest, IgnoreOldWwwGoogleLogins) {
65 scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
66 base::MessageLoopProxy::current(),
67 base::MessageLoopProxy::current(),
68 login_db_.release()));
69 store->Init(syncer::SyncableService::StartSyncFlare());
71 const time_t cutoff = 1325376000; // 00:00 Jan 1 2012 UTC
72 // The passwords are all empty because PasswordStoreDefault doesn't store the
73 // actual passwords on OS X (they're stored in the Keychain instead). We could
74 // special-case it, but it's easier to just have empty passwords.
75 static const PasswordFormData form_data[] = {
76 // A form on https://www.google.com/ older than the cutoff. Will be ignored.
77 { PasswordForm::SCHEME_HTML,
78 "https://www.google.com",
79 "https://www.google.com/origin",
80 "https://www.google.com/action",
86 true, true, cutoff - 1 },
87 // A form on https://www.google.com/ older than the cutoff. Will be ignored.
88 { PasswordForm::SCHEME_HTML,
89 "https://www.google.com",
90 "https://www.google.com/origin",
91 "https://www.google.com/action",
97 true, true, cutoff - 1 },
98 // A form on https://www.google.com/ newer than the cutoff.
99 { PasswordForm::SCHEME_HTML,
100 "https://www.google.com",
101 "https://www.google.com/origin",
102 "https://www.google.com/action",
108 true, true, cutoff + 1 },
109 // A form on https://accounts.google.com/ older than the cutoff.
110 { PasswordForm::SCHEME_HTML,
111 "https://accounts.google.com",
112 "https://accounts.google.com/origin",
113 "https://accounts.google.com/action",
119 true, true, cutoff - 1 },
120 // A form on http://bar.example.com/ older than the cutoff.
121 { PasswordForm::SCHEME_HTML,
122 "http://bar.example.com",
123 "http://bar.example.com/origin",
124 "http://bar.example.com/action",
130 true, false, cutoff - 1 },
133 // Build the forms vector and add the forms to the store.
134 std::vector<PasswordForm*> all_forms;
135 for (size_t i = 0; i < arraysize(form_data); ++i) {
136 PasswordForm* form = CreatePasswordFormFromData(form_data[i]);
137 all_forms.push_back(form);
138 store->AddLogin(*form);
140 base::MessageLoop::current()->RunUntilIdle();
142 // We expect to get back only the "recent" www.google.com login.
143 // Theoretically these should never actually exist since there are no longer
144 // any login forms on www.google.com to save, but we technically allow them.
145 // We should not get back the older saved password though.
146 PasswordForm www_google;
147 www_google.scheme = PasswordForm::SCHEME_HTML;
148 www_google.signon_realm = "https://www.google.com";
149 std::vector<PasswordForm*> www_google_expected;
150 www_google_expected.push_back(all_forms[2]);
152 // We should still get the accounts.google.com login even though it's older
153 // than our cutoff - this is the new location of all Google login forms.
154 PasswordForm accounts_google;
155 accounts_google.scheme = PasswordForm::SCHEME_HTML;
156 accounts_google.signon_realm = "https://accounts.google.com";
157 std::vector<PasswordForm*> accounts_google_expected;
158 accounts_google_expected.push_back(all_forms[3]);
160 // Same thing for a generic saved login.
161 PasswordForm bar_example;
162 bar_example.scheme = PasswordForm::SCHEME_HTML;
163 bar_example.signon_realm = "http://bar.example.com";
164 std::vector<PasswordForm*> bar_example_expected;
165 bar_example_expected.push_back(all_forms[4]);
167 MockPasswordStoreConsumer consumer;
169 // Expect the appropriate replies, as above, in reverse order than we will
170 // issue the queries. Each retires on saturation to avoid matcher spew.
171 EXPECT_CALL(consumer,
172 OnGetPasswordStoreResults(ContainsAllPasswordForms(bar_example_expected)))
173 .WillOnce(WithArg<0>(STLDeleteElements0())).RetiresOnSaturation();
174 EXPECT_CALL(consumer,
175 OnGetPasswordStoreResults(
176 ContainsAllPasswordForms(accounts_google_expected)))
177 .WillOnce(WithArg<0>(STLDeleteElements0())).RetiresOnSaturation();
178 EXPECT_CALL(consumer,
179 OnGetPasswordStoreResults(
180 ContainsAllPasswordForms(www_google_expected)))
181 .WillOnce(WithArg<0>(STLDeleteElements0())).RetiresOnSaturation();
183 store->GetLogins(www_google, PasswordStore::ALLOW_PROMPT, &consumer);
184 store->GetLogins(accounts_google, PasswordStore::ALLOW_PROMPT, &consumer);
185 store->GetLogins(bar_example, PasswordStore::ALLOW_PROMPT, &consumer);
187 base::MessageLoop::current()->RunUntilIdle();
189 STLDeleteElements(&all_forms);
191 base::MessageLoop::current()->RunUntilIdle();
194 TEST_F(PasswordStoreTest, StartSyncFlare) {
195 scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
196 base::MessageLoopProxy::current(),
197 base::MessageLoopProxy::current(),
198 login_db_.release()));
199 StartSyncFlareMock mock;
201 base::Bind(&StartSyncFlareMock::StartSyncFlare, base::Unretained(&mock)));
204 EXPECT_CALL(mock, StartSyncFlare(syncer::PASSWORDS));
205 store->AddLogin(form);
206 base::MessageLoop::current()->RunUntilIdle();
209 base::MessageLoop::current()->RunUntilIdle();
212 } // namespace password_manager