OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "chrome/browser/password_manager/password_store_proxy_mac.h" | 5 #include "chrome/browser/password_manager/password_store_mac.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/files/scoped_temp_dir.h" | 9 #include "base/files/scoped_temp_dir.h" |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
12 #include "base/run_loop.h" | 12 #include "base/run_loop.h" |
13 #include "base/scoped_observer.h" | 13 #include "base/scoped_observer.h" |
14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
15 #include "base/test/histogram_tester.h" | 15 #include "base/test/histogram_tester.h" |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 | 64 |
65 std::vector<std::unique_ptr<PasswordForm>> forms_; | 65 std::vector<std::unique_ptr<PasswordForm>> forms_; |
66 base::RunLoop* nested_loop_ = nullptr; | 66 base::RunLoop* nested_loop_ = nullptr; |
67 | 67 |
68 DISALLOW_COPY_AND_ASSIGN(MockPasswordStoreConsumer); | 68 DISALLOW_COPY_AND_ASSIGN(MockPasswordStoreConsumer); |
69 }; | 69 }; |
70 | 70 |
71 class MockPasswordStoreObserver | 71 class MockPasswordStoreObserver |
72 : public password_manager::PasswordStore::Observer { | 72 : public password_manager::PasswordStore::Observer { |
73 public: | 73 public: |
74 explicit MockPasswordStoreObserver(PasswordStoreProxyMac* password_store) | 74 explicit MockPasswordStoreObserver(PasswordStoreMac* password_store) |
75 : guard_(this) { | 75 : guard_(this) { |
76 guard_.Add(password_store); | 76 guard_.Add(password_store); |
77 } | 77 } |
78 MOCK_METHOD1(OnLoginsChanged, | 78 MOCK_METHOD1(OnLoginsChanged, |
79 void(const password_manager::PasswordStoreChangeList& changes)); | 79 void(const password_manager::PasswordStoreChangeList& changes)); |
80 | 80 |
81 private: | 81 private: |
82 ScopedObserver<PasswordStoreProxyMac, MockPasswordStoreObserver> guard_; | 82 ScopedObserver<PasswordStoreMac, MockPasswordStoreObserver> guard_; |
83 | 83 |
84 DISALLOW_COPY_AND_ASSIGN(MockPasswordStoreObserver); | 84 DISALLOW_COPY_AND_ASSIGN(MockPasswordStoreObserver); |
85 }; | 85 }; |
86 | 86 |
87 // A mock LoginDatabase that simulates a failing Init() method. | 87 // A mock LoginDatabase that simulates a failing Init() method. |
88 class BadLoginDatabase : public password_manager::LoginDatabase { | 88 class BadLoginDatabase : public password_manager::LoginDatabase { |
89 public: | 89 public: |
90 BadLoginDatabase() : password_manager::LoginDatabase(base::FilePath()) {} | 90 BadLoginDatabase() : password_manager::LoginDatabase(base::FilePath()) {} |
91 ~BadLoginDatabase() override {} | 91 ~BadLoginDatabase() override {} |
92 | 92 |
93 // LoginDatabase: | 93 // LoginDatabase: |
94 bool Init() override { return false; } | 94 bool Init() override { return false; } |
95 | 95 |
96 private: | 96 private: |
97 DISALLOW_COPY_AND_ASSIGN(BadLoginDatabase); | 97 DISALLOW_COPY_AND_ASSIGN(BadLoginDatabase); |
98 }; | 98 }; |
99 | 99 |
100 class PasswordStoreProxyMacTest | 100 class PasswordStoreMacTest : public testing::TestWithParam<MigrationStatus> { |
101 : public testing::TestWithParam<MigrationStatus> { | |
102 public: | 101 public: |
103 PasswordStoreProxyMacTest(); | 102 PasswordStoreMacTest(); |
104 ~PasswordStoreProxyMacTest() override; | 103 ~PasswordStoreMacTest() override; |
105 | 104 |
106 void CreateAndInitPasswordStore( | 105 void CreateAndInitPasswordStore( |
107 std::unique_ptr<password_manager::LoginDatabase> login_db); | 106 std::unique_ptr<password_manager::LoginDatabase> login_db); |
108 | 107 |
109 void ClosePasswordStore(); | 108 void ClosePasswordStore(); |
110 | 109 |
111 // Do a store-level query to wait for all the previously enqueued operations | 110 // Do a store-level query to wait for all the previously enqueued operations |
112 // to finish. | 111 // to finish. |
113 void FinishAsyncProcessing(); | 112 void FinishAsyncProcessing(); |
114 | 113 |
115 // Add/Update/Remove |form| and verify the operation succeeded. | 114 // Add/Update/Remove |form| and verify the operation succeeded. |
116 void AddForm(const PasswordForm& form); | 115 void AddForm(const PasswordForm& form); |
117 void UpdateForm(const PasswordForm& form); | 116 void UpdateForm(const PasswordForm& form); |
118 void RemoveForm(const PasswordForm& form); | 117 void RemoveForm(const PasswordForm& form); |
119 | 118 |
120 base::FilePath test_login_db_file_path() const; | 119 base::FilePath test_login_db_file_path() const; |
121 | 120 |
122 // Returns the expected migration status after the password store was inited. | 121 // Returns the expected migration status after the password store was inited. |
123 MigrationStatus GetTargetStatus() const; | 122 MigrationStatus GetTargetStatus() const; |
124 | 123 |
125 password_manager::LoginDatabase* login_db() const { | 124 password_manager::LoginDatabase* login_db() const { |
126 return store_->login_metadata_db(); | 125 return store_->login_metadata_db(); |
127 } | 126 } |
128 | 127 |
129 PasswordStoreProxyMac* store() { return store_.get(); } | 128 PasswordStoreMac* store() { return store_.get(); } |
130 | 129 |
131 protected: | 130 protected: |
132 content::TestBrowserThreadBundle ui_thread_; | 131 content::TestBrowserThreadBundle ui_thread_; |
133 | 132 |
134 base::ScopedTempDir db_dir_; | 133 base::ScopedTempDir db_dir_; |
135 scoped_refptr<PasswordStoreProxyMac> store_; | 134 scoped_refptr<PasswordStoreMac> store_; |
136 sync_preferences::TestingPrefServiceSyncable testing_prefs_; | 135 sync_preferences::TestingPrefServiceSyncable testing_prefs_; |
137 }; | 136 }; |
138 | 137 |
139 PasswordStoreProxyMacTest::PasswordStoreProxyMacTest() { | 138 PasswordStoreMacTest::PasswordStoreMacTest() { |
140 EXPECT_TRUE(db_dir_.CreateUniqueTempDir()); | 139 EXPECT_TRUE(db_dir_.CreateUniqueTempDir()); |
141 chrome::RegisterUserProfilePrefs(testing_prefs_.registry()); | 140 chrome::RegisterUserProfilePrefs(testing_prefs_.registry()); |
142 testing_prefs_.SetInteger(password_manager::prefs::kKeychainMigrationStatus, | 141 testing_prefs_.SetInteger(password_manager::prefs::kKeychainMigrationStatus, |
143 static_cast<int>(GetParam())); | 142 static_cast<int>(GetParam())); |
144 // Ensure that LoginDatabase will use the mock keychain if it needs to | 143 // Ensure that LoginDatabase will use the mock keychain if it needs to |
145 // encrypt/decrypt a password. | 144 // encrypt/decrypt a password. |
146 OSCryptMocker::SetUpWithSingleton(); | 145 OSCryptMocker::SetUpWithSingleton(); |
147 } | 146 } |
148 | 147 |
149 PasswordStoreProxyMacTest::~PasswordStoreProxyMacTest() { | 148 PasswordStoreMacTest::~PasswordStoreMacTest() { |
150 ClosePasswordStore(); | 149 ClosePasswordStore(); |
151 OSCryptMocker::TearDown(); | 150 OSCryptMocker::TearDown(); |
152 } | 151 } |
153 | 152 |
154 void PasswordStoreProxyMacTest::CreateAndInitPasswordStore( | 153 void PasswordStoreMacTest::CreateAndInitPasswordStore( |
155 std::unique_ptr<password_manager::LoginDatabase> login_db) { | 154 std::unique_ptr<password_manager::LoginDatabase> login_db) { |
156 store_ = new PasswordStoreProxyMac( | 155 store_ = new PasswordStoreMac( |
157 BrowserThread::GetTaskRunnerForThread(BrowserThread::UI), | 156 BrowserThread::GetTaskRunnerForThread(BrowserThread::UI), |
158 std::move(login_db), &testing_prefs_); | 157 std::move(login_db), &testing_prefs_); |
159 ASSERT_TRUE(store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr)); | 158 ASSERT_TRUE(store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr)); |
160 } | 159 } |
161 | 160 |
162 void PasswordStoreProxyMacTest::ClosePasswordStore() { | 161 void PasswordStoreMacTest::ClosePasswordStore() { |
163 if (!store_) | 162 if (!store_) |
164 return; | 163 return; |
165 store_->ShutdownOnUIThread(); | 164 store_->ShutdownOnUIThread(); |
166 EXPECT_FALSE(store_->GetBackgroundTaskRunner()); | 165 EXPECT_FALSE(store_->GetBackgroundTaskRunner()); |
167 store_ = nullptr; | 166 store_ = nullptr; |
168 } | 167 } |
169 | 168 |
170 void PasswordStoreProxyMacTest::FinishAsyncProcessing() { | 169 void PasswordStoreMacTest::FinishAsyncProcessing() { |
171 // Do a store-level query to wait for all the previously enqueued operations | 170 // Do a store-level query to wait for all the previously enqueued operations |
172 // to finish. | 171 // to finish. |
173 MockPasswordStoreConsumer consumer; | 172 MockPasswordStoreConsumer consumer; |
174 store_->GetLogins({PasswordForm::SCHEME_HTML, std::string(), GURL()}, | 173 store_->GetLogins({PasswordForm::SCHEME_HTML, std::string(), GURL()}, |
175 &consumer); | 174 &consumer); |
176 consumer.WaitForResult(); | 175 consumer.WaitForResult(); |
177 } | 176 } |
178 | 177 |
179 base::FilePath PasswordStoreProxyMacTest::test_login_db_file_path() const { | 178 base::FilePath PasswordStoreMacTest::test_login_db_file_path() const { |
180 return db_dir_.GetPath().Append(FILE_PATH_LITERAL("login.db")); | 179 return db_dir_.GetPath().Append(FILE_PATH_LITERAL("login.db")); |
181 } | 180 } |
182 | 181 |
183 MigrationStatus PasswordStoreProxyMacTest::GetTargetStatus() const { | 182 MigrationStatus PasswordStoreMacTest::GetTargetStatus() const { |
184 if (GetParam() == MigrationStatus::NOT_STARTED || | 183 if (GetParam() == MigrationStatus::NOT_STARTED || |
185 GetParam() == MigrationStatus::FAILED_ONCE || | 184 GetParam() == MigrationStatus::FAILED_ONCE || |
186 GetParam() == MigrationStatus::FAILED_TWICE) { | 185 GetParam() == MigrationStatus::FAILED_TWICE) { |
187 return MigrationStatus::MIGRATION_STOPPED; | 186 return MigrationStatus::MIGRATION_STOPPED; |
188 } | 187 } |
189 return GetParam(); | 188 return GetParam(); |
190 } | 189 } |
191 | 190 |
192 void PasswordStoreProxyMacTest::AddForm(const PasswordForm& form) { | 191 void PasswordStoreMacTest::AddForm(const PasswordForm& form) { |
193 MockPasswordStoreObserver mock_observer(store()); | 192 MockPasswordStoreObserver mock_observer(store()); |
194 | 193 |
195 password_manager::PasswordStoreChangeList list; | 194 password_manager::PasswordStoreChangeList list; |
196 list.push_back(password_manager::PasswordStoreChange( | 195 list.push_back(password_manager::PasswordStoreChange( |
197 password_manager::PasswordStoreChange::ADD, form)); | 196 password_manager::PasswordStoreChange::ADD, form)); |
198 EXPECT_CALL(mock_observer, OnLoginsChanged(list)); | 197 EXPECT_CALL(mock_observer, OnLoginsChanged(list)); |
199 store()->AddLogin(form); | 198 store()->AddLogin(form); |
200 FinishAsyncProcessing(); | 199 FinishAsyncProcessing(); |
201 } | 200 } |
202 | 201 |
203 void PasswordStoreProxyMacTest::UpdateForm(const PasswordForm& form) { | 202 void PasswordStoreMacTest::UpdateForm(const PasswordForm& form) { |
204 MockPasswordStoreObserver mock_observer(store()); | 203 MockPasswordStoreObserver mock_observer(store()); |
205 | 204 |
206 password_manager::PasswordStoreChangeList list; | 205 password_manager::PasswordStoreChangeList list; |
207 list.push_back(password_manager::PasswordStoreChange( | 206 list.push_back(password_manager::PasswordStoreChange( |
208 password_manager::PasswordStoreChange::UPDATE, form)); | 207 password_manager::PasswordStoreChange::UPDATE, form)); |
209 EXPECT_CALL(mock_observer, OnLoginsChanged(list)); | 208 EXPECT_CALL(mock_observer, OnLoginsChanged(list)); |
210 store()->UpdateLogin(form); | 209 store()->UpdateLogin(form); |
211 FinishAsyncProcessing(); | 210 FinishAsyncProcessing(); |
212 } | 211 } |
213 | 212 |
214 void PasswordStoreProxyMacTest::RemoveForm(const PasswordForm& form) { | 213 void PasswordStoreMacTest::RemoveForm(const PasswordForm& form) { |
215 MockPasswordStoreObserver mock_observer(store()); | 214 MockPasswordStoreObserver mock_observer(store()); |
216 | 215 |
217 password_manager::PasswordStoreChangeList list; | 216 password_manager::PasswordStoreChangeList list; |
218 list.push_back(password_manager::PasswordStoreChange( | 217 list.push_back(password_manager::PasswordStoreChange( |
219 password_manager::PasswordStoreChange::REMOVE, form)); | 218 password_manager::PasswordStoreChange::REMOVE, form)); |
220 EXPECT_CALL(mock_observer, OnLoginsChanged(list)); | 219 EXPECT_CALL(mock_observer, OnLoginsChanged(list)); |
221 store()->RemoveLogin(form); | 220 store()->RemoveLogin(form); |
222 FinishAsyncProcessing(); | 221 FinishAsyncProcessing(); |
223 } | 222 } |
224 | 223 |
225 // ----------- Tests ------------- | 224 // ----------- Tests ------------- |
226 | 225 |
227 TEST_P(PasswordStoreProxyMacTest, Sanity) { | 226 TEST_P(PasswordStoreMacTest, Sanity) { |
228 base::HistogramTester histogram_tester; | 227 base::HistogramTester histogram_tester; |
229 | 228 |
230 CreateAndInitPasswordStore(base::MakeUnique<password_manager::LoginDatabase>( | 229 CreateAndInitPasswordStore(base::MakeUnique<password_manager::LoginDatabase>( |
231 test_login_db_file_path())); | 230 test_login_db_file_path())); |
232 FinishAsyncProcessing(); | 231 FinishAsyncProcessing(); |
233 ClosePasswordStore(); | 232 ClosePasswordStore(); |
234 | 233 |
235 int status = testing_prefs_.GetInteger( | 234 int status = testing_prefs_.GetInteger( |
236 password_manager::prefs::kKeychainMigrationStatus); | 235 password_manager::prefs::kKeychainMigrationStatus); |
237 EXPECT_EQ(static_cast<int>(GetTargetStatus()), status); | 236 EXPECT_EQ(static_cast<int>(GetTargetStatus()), status); |
238 histogram_tester.ExpectUniqueSample( | 237 histogram_tester.ExpectUniqueSample( |
239 "PasswordManager.KeychainMigration.Status", status, 1); | 238 "PasswordManager.KeychainMigration.Status", status, 1); |
240 } | 239 } |
241 | 240 |
242 TEST_P(PasswordStoreProxyMacTest, StartAndStop) { | 241 TEST_P(PasswordStoreMacTest, StartAndStop) { |
243 base::HistogramTester histogram_tester; | 242 base::HistogramTester histogram_tester; |
244 // PasswordStore::ShutdownOnUIThread() immediately follows | 243 // PasswordStore::ShutdownOnUIThread() immediately follows |
245 // PasswordStore::Init(). The message loop isn't running in between. Anyway, | 244 // PasswordStore::Init(). The message loop isn't running in between. Anyway, |
246 // PasswordStore should not collapse. | 245 // PasswordStore should not collapse. |
247 CreateAndInitPasswordStore(base::MakeUnique<password_manager::LoginDatabase>( | 246 CreateAndInitPasswordStore(base::MakeUnique<password_manager::LoginDatabase>( |
248 test_login_db_file_path())); | 247 test_login_db_file_path())); |
249 ClosePasswordStore(); | 248 ClosePasswordStore(); |
250 | 249 |
251 histogram_tester.ExpectUniqueSample( | 250 histogram_tester.ExpectUniqueSample( |
252 "PasswordManager.KeychainMigration.Status", | 251 "PasswordManager.KeychainMigration.Status", |
253 static_cast<int>(GetTargetStatus()), 1); | 252 static_cast<int>(GetTargetStatus()), 1); |
254 } | 253 } |
255 | 254 |
256 TEST_P(PasswordStoreProxyMacTest, OperationsOnABadDatabaseSilentlyFail) { | 255 TEST_P(PasswordStoreMacTest, OperationsOnABadDatabaseSilentlyFail) { |
257 // Verify that operations on a PasswordStore with a bad database cause no | 256 // Verify that operations on a PasswordStore with a bad database cause no |
258 // explosions, but fail without side effect, return no data and trigger no | 257 // explosions, but fail without side effect, return no data and trigger no |
259 // notifications. | 258 // notifications. |
260 CreateAndInitPasswordStore(base::MakeUnique<BadLoginDatabase>()); | 259 CreateAndInitPasswordStore(base::MakeUnique<BadLoginDatabase>()); |
261 FinishAsyncProcessing(); | 260 FinishAsyncProcessing(); |
262 EXPECT_FALSE(login_db()); | 261 EXPECT_FALSE(login_db()); |
263 | 262 |
264 // The store should outlive the observer. | 263 // The store should outlive the observer. |
265 scoped_refptr<PasswordStoreProxyMac> store_refptr = store(); | 264 scoped_refptr<PasswordStoreMac> store_refptr = store(); |
266 MockPasswordStoreObserver mock_observer(store()); | 265 MockPasswordStoreObserver mock_observer(store()); |
267 EXPECT_CALL(mock_observer, OnLoginsChanged(_)).Times(0); | 266 EXPECT_CALL(mock_observer, OnLoginsChanged(_)).Times(0); |
268 | 267 |
269 // Add a new autofillable login + a blacklisted login. | 268 // Add a new autofillable login + a blacklisted login. |
270 password_manager::PasswordFormData www_form_data = { | 269 password_manager::PasswordFormData www_form_data = { |
271 PasswordForm::SCHEME_HTML, | 270 PasswordForm::SCHEME_HTML, |
272 "http://www.facebook.com/", | 271 "http://www.facebook.com/", |
273 "http://www.facebook.com/index.html", | 272 "http://www.facebook.com/index.html", |
274 "login", | 273 "login", |
275 L"username", | 274 L"username", |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 store()->RemoveLoginsCreatedBetween(base::Time(), base::Time::Max(), | 317 store()->RemoveLoginsCreatedBetween(base::Time(), base::Time::Max(), |
319 base::Closure()); | 318 base::Closure()); |
320 store()->RemoveLoginsSyncedBetween(base::Time(), base::Time::Max()); | 319 store()->RemoveLoginsSyncedBetween(base::Time(), base::Time::Max()); |
321 FinishAsyncProcessing(); | 320 FinishAsyncProcessing(); |
322 | 321 |
323 // Verify no notifications are fired during shutdown either. | 322 // Verify no notifications are fired during shutdown either. |
324 ClosePasswordStore(); | 323 ClosePasswordStore(); |
325 } | 324 } |
326 | 325 |
327 INSTANTIATE_TEST_CASE_P(, | 326 INSTANTIATE_TEST_CASE_P(, |
328 PasswordStoreProxyMacTest, | 327 PasswordStoreMacTest, |
329 testing::Values(MigrationStatus::NOT_STARTED, | 328 testing::Values(MigrationStatus::NOT_STARTED, |
330 MigrationStatus::MIGRATED, | 329 MigrationStatus::MIGRATED, |
331 MigrationStatus::FAILED_ONCE, | 330 MigrationStatus::FAILED_ONCE, |
332 MigrationStatus::FAILED_TWICE, | 331 MigrationStatus::FAILED_TWICE, |
333 MigrationStatus::MIGRATED_DELETED, | 332 MigrationStatus::MIGRATED_DELETED, |
334 MigrationStatus::MIGRATED_PARTIALLY, | 333 MigrationStatus::MIGRATED_PARTIALLY, |
335 MigrationStatus::MIGRATION_STOPPED)); | 334 MigrationStatus::MIGRATION_STOPPED)); |
336 | 335 |
337 } // namespace | 336 } // namespace |
OLD | NEW |