Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: components/password_manager/core/browser/password_store_default_unittest.cc

Issue 838453003: Open the LoginDatabase on the DB thread, not the UI thread. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix nits from vabr@. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/basictypes.h" 5 #include "base/basictypes.h"
6 #include "base/bind.h" 6 #include "base/bind.h"
7 #include "base/bind_helpers.h" 7 #include "base/bind_helpers.h"
8 #include "base/files/file_util.h"
8 #include "base/files/scoped_temp_dir.h" 9 #include "base/files/scoped_temp_dir.h"
9 #include "base/prefs/pref_service.h" 10 #include "base/prefs/pref_service.h"
10 #include "base/stl_util.h" 11 #include "base/stl_util.h"
11 #include "base/strings/string_util.h" 12 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h" 13 #include "base/strings/utf_string_conversions.h"
13 #include "base/time/time.h" 14 #include "base/time/time.h"
15 #include "components/password_manager/core/browser/login_database.h"
14 #include "components/password_manager/core/browser/password_form_data.h" 16 #include "components/password_manager/core/browser/password_form_data.h"
15 #include "components/password_manager/core/browser/password_store_change.h" 17 #include "components/password_manager/core/browser/password_store_change.h"
16 #include "components/password_manager/core/browser/password_store_consumer.h" 18 #include "components/password_manager/core/browser/password_store_consumer.h"
17 #include "components/password_manager/core/browser/password_store_default.h" 19 #include "components/password_manager/core/browser/password_store_default.h"
18 #include "testing/gmock/include/gmock/gmock.h" 20 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h" 21 #include "testing/gtest/include/gtest/gtest.h"
20 22
21 using autofill::PasswordForm; 23 using autofill::PasswordForm;
22 using testing::_; 24 using testing::_;
23 using testing::ElementsAreArray; 25 using testing::ElementsAreArray;
24 using testing::WithArg; 26 using testing::WithArg;
25 27
26 namespace password_manager { 28 namespace password_manager {
27 29
28 namespace { 30 namespace {
29 31
30 class MockPasswordStoreConsumer : public PasswordStoreConsumer { 32 class MockPasswordStoreConsumer : public PasswordStoreConsumer {
31 public: 33 public:
32 MOCK_METHOD1(OnGetPasswordStoreResults, 34 MOCK_METHOD1(OnGetPasswordStoreResults,
33 void(const std::vector<PasswordForm*>&)); 35 void(const std::vector<PasswordForm*>&));
34 }; 36 };
35 37
36 class MockPasswordStoreObserver : public PasswordStore::Observer { 38 class MockPasswordStoreObserver : public PasswordStore::Observer {
37 public: 39 public:
38 MOCK_METHOD1(OnLoginsChanged, void(const PasswordStoreChangeList& changes)); 40 MOCK_METHOD1(OnLoginsChanged, void(const PasswordStoreChangeList& changes));
39 }; 41 };
40 42
43 // A mock LoginDatabase that simulates a failing Init() method.
44 class BadLoginDatabase : public LoginDatabase {
45 public:
46 BadLoginDatabase() : LoginDatabase(base::FilePath()) {}
47 ~BadLoginDatabase() override {}
48
49 // LoginDatabase:
50 bool Init() override { return false; }
51
52 private:
53 DISALLOW_COPY_AND_ASSIGN(BadLoginDatabase);
54 };
55
56 PasswordFormData CreateTestPasswordFormData() {
57 PasswordFormData data = {
58 PasswordForm::SCHEME_HTML,
59 "http://bar.example.com",
60 "http://bar.example.com/origin",
61 "http://bar.example.com/action",
62 L"submit_element",
63 L"username_element",
64 L"password_element",
65 L"username_value",
66 L"password_value",
67 true,
68 false,
69 1
70 };
71 return data;
72 }
73
41 } // anonymous namespace 74 } // anonymous namespace
42 75
43 class PasswordStoreDefaultTest : public testing::Test { 76 class PasswordStoreDefaultTest : public testing::Test {
44 protected: 77 protected:
45 void SetUp() override { 78 void SetUp() override {
46 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 79 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
47 login_db_.reset(new LoginDatabase());
48 ASSERT_TRUE(login_db_->Init(
49 temp_dir_.path().Append(FILE_PATH_LITERAL("login_test"))));
50 } 80 }
51 81
52 void TearDown() override { ASSERT_TRUE(temp_dir_.Delete()); } 82 void TearDown() override { ASSERT_TRUE(temp_dir_.Delete()); }
53 83
84 base::FilePath test_login_db_file_path() const {
85 return temp_dir_.path().Append(FILE_PATH_LITERAL("login_test"));
86 }
87
54 base::MessageLoopForUI message_loop_; 88 base::MessageLoopForUI message_loop_;
55 scoped_ptr<LoginDatabase> login_db_;
56 base::ScopedTempDir temp_dir_; 89 base::ScopedTempDir temp_dir_;
57 }; 90 };
58 91
59 ACTION(STLDeleteElements0) { 92 ACTION(STLDeleteElements0) {
60 STLDeleteContainerPointers(arg0.begin(), arg0.end()); 93 STLDeleteContainerPointers(arg0.begin(), arg0.end());
61 } 94 }
62 95
63 TEST_F(PasswordStoreDefaultTest, NonASCIIData) { 96 TEST_F(PasswordStoreDefaultTest, NonASCIIData) {
64 scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault( 97 scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
65 base::MessageLoopProxy::current(), 98 base::MessageLoopProxy::current(), base::MessageLoopProxy::current(),
66 base::MessageLoopProxy::current(), 99 make_scoped_ptr(new LoginDatabase(test_login_db_file_path()))));
67 login_db_.release()));
68 store->Init(syncer::SyncableService::StartSyncFlare()); 100 store->Init(syncer::SyncableService::StartSyncFlare());
69 101
70 // Some non-ASCII password form data. 102 // Some non-ASCII password form data.
71 static const PasswordFormData form_data[] = { 103 static const PasswordFormData form_data[] = {
72 { PasswordForm::SCHEME_HTML, 104 { PasswordForm::SCHEME_HTML,
73 "http://foo.example.com", 105 "http://foo.example.com",
74 "http://foo.example.com/origin", 106 "http://foo.example.com/origin",
75 "http://foo.example.com/action", 107 "http://foo.example.com/action",
76 L"มีสีสัน", 108 L"มีสีสัน",
77 L"お元気ですか?", 109 L"お元気ですか?",
(...skipping 23 matching lines...) Expand all
101 133
102 base::MessageLoop::current()->RunUntilIdle(); 134 base::MessageLoop::current()->RunUntilIdle();
103 135
104 STLDeleteElements(&expected_forms); 136 STLDeleteElements(&expected_forms);
105 store->Shutdown(); 137 store->Shutdown();
106 base::MessageLoop::current()->RunUntilIdle(); 138 base::MessageLoop::current()->RunUntilIdle();
107 } 139 }
108 140
109 TEST_F(PasswordStoreDefaultTest, Notifications) { 141 TEST_F(PasswordStoreDefaultTest, Notifications) {
110 scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault( 142 scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
111 base::MessageLoopProxy::current(), 143 base::MessageLoopProxy::current(), base::MessageLoopProxy::current(),
112 base::MessageLoopProxy::current(), 144 make_scoped_ptr(new LoginDatabase(test_login_db_file_path()))));
113 login_db_.release()));
114 store->Init(syncer::SyncableService::StartSyncFlare()); 145 store->Init(syncer::SyncableService::StartSyncFlare());
115 146
116 PasswordFormData form_data = 147 scoped_ptr<PasswordForm> form(
117 { PasswordForm::SCHEME_HTML, 148 CreatePasswordFormFromData(CreateTestPasswordFormData()));
118 "http://bar.example.com",
119 "http://bar.example.com/origin",
120 "http://bar.example.com/action",
121 L"submit_element",
122 L"username_element",
123 L"password_element",
124 L"username_value",
125 L"password_value",
126 true, false, 1 };
127 scoped_ptr<PasswordForm> form(CreatePasswordFormFromData(form_data));
128 149
129 MockPasswordStoreObserver observer; 150 MockPasswordStoreObserver observer;
130 store->AddObserver(&observer); 151 store->AddObserver(&observer);
131 152
132 const PasswordStoreChange expected_add_changes[] = { 153 const PasswordStoreChange expected_add_changes[] = {
133 PasswordStoreChange(PasswordStoreChange::ADD, *form), 154 PasswordStoreChange(PasswordStoreChange::ADD, *form),
134 }; 155 };
135 156
136 EXPECT_CALL(observer, 157 EXPECT_CALL(observer,
137 OnLoginsChanged(ElementsAreArray(expected_add_changes))); 158 OnLoginsChanged(ElementsAreArray(expected_add_changes)));
(...skipping 25 matching lines...) Expand all
163 184
164 // Deleting the login should trigger a notification. 185 // Deleting the login should trigger a notification.
165 store->RemoveLogin(*form); 186 store->RemoveLogin(*form);
166 base::MessageLoop::current()->RunUntilIdle(); 187 base::MessageLoop::current()->RunUntilIdle();
167 188
168 store->RemoveObserver(&observer); 189 store->RemoveObserver(&observer);
169 store->Shutdown(); 190 store->Shutdown();
170 base::MessageLoop::current()->RunUntilIdle(); 191 base::MessageLoop::current()->RunUntilIdle();
171 } 192 }
172 193
194 // Verify that operations on a PasswordStore with a bad database cause no
195 // explosions, but fail without side effect, return no data and trigger no
196 // notifications.
197 TEST_F(PasswordStoreDefaultTest, OperationsOnABadDatabaseSilentlyFail) {
198 scoped_refptr<PasswordStoreDefault> bad_store(new PasswordStoreDefault(
199 base::MessageLoopProxy::current(), base::MessageLoopProxy::current(),
200 make_scoped_ptr<LoginDatabase>(new BadLoginDatabase)));
201
202 bad_store->Init(syncer::SyncableService::StartSyncFlare());
203 base::MessageLoop::current()->RunUntilIdle();
204 ASSERT_EQ(nullptr, bad_store->login_db());
205
206 testing::StrictMock<MockPasswordStoreObserver> mock_observer;
207 bad_store->AddObserver(&mock_observer);
208
209 // Add a new autofillable login + a blacklisted login.
210 scoped_ptr<PasswordForm> form(
211 CreatePasswordFormFromData(CreateTestPasswordFormData()));
212 scoped_ptr<PasswordForm> blacklisted_form(new PasswordForm(*form));
213 blacklisted_form->signon_realm = "http://foo.example.com";
214 blacklisted_form->origin = GURL("http://foo.example.com/origin");
215 blacklisted_form->action = GURL("http://foo.example.com/action");
216 blacklisted_form->blacklisted_by_user = true;
217 bad_store->AddLogin(*form);
218 bad_store->AddLogin(*blacklisted_form);
219 base::MessageLoop::current()->RunUntilIdle();
220
221 // Get all logins; autofillable logins; blacklisted logins.
222 testing::StrictMock<MockPasswordStoreConsumer> mock_consumer;
223 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResults(testing::ElementsAre()));
224 bad_store->GetLogins(*form, PasswordStore::DISALLOW_PROMPT, &mock_consumer);
225 base::MessageLoop::current()->RunUntilIdle();
226 testing::Mock::VerifyAndClearExpectations(&mock_consumer);
227 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResults(testing::ElementsAre()));
228 bad_store->GetAutofillableLogins(&mock_consumer);
229 base::MessageLoop::current()->RunUntilIdle();
230 testing::Mock::VerifyAndClearExpectations(&mock_consumer);
231 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResults(testing::ElementsAre()));
232 bad_store->GetBlacklistLogins(&mock_consumer);
233 base::MessageLoop::current()->RunUntilIdle();
234
235 // Report metrics.
236 bad_store->ReportMetrics("Test Username", true);
237 base::MessageLoop::current()->RunUntilIdle();
238
239 // Change the login.
240 form->password_value = base::ASCIIToUTF16("a different password");
241 bad_store->UpdateLogin(*form);
242 base::MessageLoop::current()->RunUntilIdle();
243
244 // Delete one login; a range of logins.
245 bad_store->RemoveLogin(*form);
246 base::MessageLoop::current()->RunUntilIdle();
247 bad_store->RemoveLoginsCreatedBetween(base::Time(), base::Time::Max());
248 base::MessageLoop::current()->RunUntilIdle();
249 bad_store->RemoveLoginsSyncedBetween(base::Time(), base::Time::Max());
250 base::MessageLoop::current()->RunUntilIdle();
251
252 // Ensure no notifications and no explosions during shutdown either.
253 bad_store->RemoveObserver(&mock_observer);
254 bad_store->Shutdown();
255 base::MessageLoop::current()->RunUntilIdle();
256 }
257
173 } // namespace password_manager 258 } // namespace password_manager
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698