1 // Copyright (c) 2015 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 <memory>
6
7 #include "base/bind.h"
8 #include "base/run_loop.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/synchronization/waitable_event.h"
11 #include "chrome/browser/password_manager/account_password_store_factory.h"
12 #include "chrome/browser/password_manager/password_store_factory.h"
13 #include "chrome/browser/sync/profile_sync_service_factory.h"
14 #include "chrome/browser/sync/test/integration/passwords_helper.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/test/base/in_process_browser_test.h"
17 #include "components/browsing_data/core/browsing_data_utils.h"
18 #include "components/browsing_data/core/counters/passwords_counter.h"
19 #include "components/browsing_data/core/pref_names.h"
20 #include "components/password_manager/core/browser/password_form.h"
21 #include "components/prefs/pref_service.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "content/public/test/browser_test.h"
24
25 namespace {
26
27 using browsing_data::BrowsingDataCounter;
28 using password_manager::PasswordForm;
29
30 class PasswordsCounterTest : public InProcessBrowserTest {
31 public:
SetUpOnMainThread()32 void SetUpOnMainThread() override {
33 finished_ = false;
34 time_ = base::Time::Now();
35 times_used_ = 0;
36 store_ = PasswordStoreFactory::GetForProfile(
37 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS);
38 SetPasswordsDeletionPref(true);
39 SetDeletionPeriodPref(browsing_data::TimePeriod::ALL_TIME);
40 }
41
AddLogin(const std::string & origin,const std::string & username,bool blocked_by_user)42 void AddLogin(const std::string& origin,
43 const std::string& username,
44 bool blocked_by_user) {
45 // Add login and wait until the password store actually changes.
46 // on the database thread.
47 passwords_helper::AddLogin(
48 store_.get(), CreateCredentials(origin, username, blocked_by_user));
49 }
50
RemoveLogin(const std::string & origin,const std::string & username,bool blocked_by_user)51 void RemoveLogin(const std::string& origin,
52 const std::string& username,
53 bool blocked_by_user) {
54 // Remove login and wait until the password store actually changes
55 // on the database thread.
56 passwords_helper::RemoveLogin(
57 store_.get(), CreateCredentials(origin, username, blocked_by_user));
58 }
59
SetPasswordsDeletionPref(bool value)60 void SetPasswordsDeletionPref(bool value) {
61 browser()->profile()->GetPrefs()->SetBoolean(
62 browsing_data::prefs::kDeletePasswords, value);
63 }
64
SetDeletionPeriodPref(browsing_data::TimePeriod period)65 void SetDeletionPeriodPref(browsing_data::TimePeriod period) {
66 browser()->profile()->GetPrefs()->SetInteger(
67 browsing_data::prefs::kDeleteTimePeriod, static_cast<int>(period));
68 }
69
RevertTimeInDays(int days)70 void RevertTimeInDays(int days) {
71 time_ -= base::TimeDelta::FromDays(days);
72 }
73
SetTimesUsed(int occurrences)74 void SetTimesUsed(int occurrences) { times_used_ = occurrences; }
75
WaitForCounting()76 void WaitForCounting() {
77 // The counting takes place on the database thread. Wait until it finishes.
78 base::WaitableEvent waitable_event(
79 base::WaitableEvent::ResetPolicy::AUTOMATIC,
80 base::WaitableEvent::InitialState::NOT_SIGNALED);
81 store_->ScheduleTask(base::BindOnce(&base::WaitableEvent::Signal,
82 base::Unretained(&waitable_event)));
83 waitable_event.Wait();
84
85 // At this point, the calculation on DB thread should have finished, and
86 // a callback should be scheduled on the UI thread. Process the tasks until
87 // we get a finished result.
88 run_loop_ = std::make_unique<base::RunLoop>();
89 run_loop_->Run();
90 }
91
GetResult()92 BrowsingDataCounter::ResultInt GetResult() {
93 DCHECK(finished_);
94 return result_;
95 }
96
GetDomainExamples()97 std::vector<std::string> GetDomainExamples() {
98 DCHECK(finished_);
99 return domain_examples_;
100 }
101
Callback(std::unique_ptr<BrowsingDataCounter::Result> result)102 void Callback(std::unique_ptr<BrowsingDataCounter::Result> result) {
103 DCHECK(result);
104 finished_ = result->Finished();
105
106 if (finished_) {
107 auto* password_result =
108 static_cast<browsing_data::PasswordsCounter::PasswordsResult*>(
109 result.get());
110 result_ = password_result->Value();
111 domain_examples_ = password_result->domain_examples();
112 }
113 if (run_loop_ && finished_)
114 run_loop_->Quit();
115 }
116
WaitForUICallbacksFromAddingLogins()117 void WaitForUICallbacksFromAddingLogins() {
118 base::RunLoop loop;
119 loop.RunUntilIdle();
120 }
121
122 private:
CreateCredentials(const std::string & origin,const std::string & username,bool blocked_by_user)123 PasswordForm CreateCredentials(const std::string& origin,
124 const std::string& username,
125 bool blocked_by_user) {
126 PasswordForm result;
127 result.signon_realm = origin;
128 result.url = GURL(origin);
129 result.username_value = base::ASCIIToUTF16(username);
130 result.password_value = base::ASCIIToUTF16("hunter2");
131 result.blocked_by_user = blocked_by_user;
132 result.date_created = time_;
133 result.times_used = times_used_;
134 return result;
135 }
136
137 scoped_refptr<password_manager::PasswordStore> store_;
138
139 std::unique_ptr<base::RunLoop> run_loop_;
140 base::Time time_;
141 int times_used_;
142
143 bool finished_;
144 BrowsingDataCounter::ResultInt result_;
145 std::vector<std::string> domain_examples_;
146 };
147
148 // Tests that the counter correctly counts each individual credential on
149 // the same domain.
IN_PROC_BROWSER_TEST_F(PasswordsCounterTest,SameDomain)150 IN_PROC_BROWSER_TEST_F(PasswordsCounterTest, SameDomain) {
151 AddLogin("https://www.google.com", "user1", false);
152 AddLogin("https://www.google.com", "user2", false);
153 AddLogin("https://www.google.com", "user3", false);
154 AddLogin("https://www.chrome.com", "user1", false);
155 AddLogin("https://www.chrome.com", "user2", false);
156 WaitForUICallbacksFromAddingLogins();
157
158 Profile* profile = browser()->profile();
159 browsing_data::PasswordsCounter counter(
160 PasswordStoreFactory::GetForProfile(profile,
161 ServiceAccessType::EXPLICIT_ACCESS),
162 AccountPasswordStoreFactory::GetForProfile(
163 profile, ServiceAccessType::EXPLICIT_ACCESS),
164 ProfileSyncServiceFactory::GetForProfile(profile));
165 counter.Init(
166 profile->GetPrefs(), browsing_data::ClearBrowsingDataTab::ADVANCED,
167 base::Bind(&PasswordsCounterTest::Callback, base::Unretained(this)));
168 counter.Restart();
169
170 WaitForCounting();
171 EXPECT_EQ(5u, GetResult());
172 }
173
174 // Tests that the counter doesn't count blocklisted entries.
IN_PROC_BROWSER_TEST_F(PasswordsCounterTest,blocklisted)175 IN_PROC_BROWSER_TEST_F(PasswordsCounterTest, blocklisted) {
176 AddLogin("https://www.google.com", "user1", false);
177 AddLogin("https://www.google.com", "user2", true);
178 AddLogin("https://www.chrome.com", "user3", true);
179 WaitForUICallbacksFromAddingLogins();
180
181 Profile* profile = browser()->profile();
182 browsing_data::PasswordsCounter counter(
183 PasswordStoreFactory::GetForProfile(profile,
184 ServiceAccessType::EXPLICIT_ACCESS),
185 AccountPasswordStoreFactory::GetForProfile(
186 profile, ServiceAccessType::EXPLICIT_ACCESS),
187 ProfileSyncServiceFactory::GetForProfile(profile));
188
189 counter.Init(
190 profile->GetPrefs(), browsing_data::ClearBrowsingDataTab::ADVANCED,
191 base::Bind(&PasswordsCounterTest::Callback, base::Unretained(this)));
192 counter.Restart();
193
194 WaitForCounting();
195 EXPECT_EQ(1u, GetResult());
196 }
197
198 // Tests that the counter starts counting automatically when the deletion
199 // pref changes to true.
IN_PROC_BROWSER_TEST_F(PasswordsCounterTest,PrefChanged)200 IN_PROC_BROWSER_TEST_F(PasswordsCounterTest, PrefChanged) {
201 SetPasswordsDeletionPref(false);
202 AddLogin("https://www.google.com", "user", false);
203 AddLogin("https://www.chrome.com", "user", false);
204 WaitForUICallbacksFromAddingLogins();
205
206 Profile* profile = browser()->profile();
207 browsing_data::PasswordsCounter counter(
208 PasswordStoreFactory::GetForProfile(profile,
209 ServiceAccessType::EXPLICIT_ACCESS),
210 AccountPasswordStoreFactory::GetForProfile(
211 profile, ServiceAccessType::EXPLICIT_ACCESS),
212 ProfileSyncServiceFactory::GetForProfile(profile));
213 counter.Init(
214 profile->GetPrefs(), browsing_data::ClearBrowsingDataTab::ADVANCED,
215 base::Bind(&PasswordsCounterTest::Callback, base::Unretained(this)));
216 SetPasswordsDeletionPref(true);
217
218 WaitForCounting();
219 EXPECT_EQ(2u, GetResult());
220 }
221
222 // Tests that the counter starts counting automatically when
223 // the password store changes.
IN_PROC_BROWSER_TEST_F(PasswordsCounterTest,StoreChanged)224 IN_PROC_BROWSER_TEST_F(PasswordsCounterTest, StoreChanged) {
225 AddLogin("https://www.google.com", "user", false);
226 WaitForUICallbacksFromAddingLogins();
227
228 Profile* profile = browser()->profile();
229 browsing_data::PasswordsCounter counter(
230 PasswordStoreFactory::GetForProfile(profile,
231 ServiceAccessType::EXPLICIT_ACCESS),
232 AccountPasswordStoreFactory::GetForProfile(
233 profile, ServiceAccessType::EXPLICIT_ACCESS),
234 ProfileSyncServiceFactory::GetForProfile(profile));
235 counter.Init(
236 profile->GetPrefs(), browsing_data::ClearBrowsingDataTab::ADVANCED,
237 base::Bind(&PasswordsCounterTest::Callback, base::Unretained(this)));
238 counter.Restart();
239
240 WaitForCounting();
241 EXPECT_EQ(1u, GetResult());
242
243 AddLogin("https://www.chrome.com", "user", false);
244 WaitForCounting();
245 EXPECT_EQ(2u, GetResult());
246
247 RemoveLogin("https://www.chrome.com", "user", false);
248 WaitForCounting();
249 EXPECT_EQ(1u, GetResult());
250 }
251
252 // Tests that changing the deletion period restarts the counting, and that
253 // the result takes login creation dates into account.
IN_PROC_BROWSER_TEST_F(PasswordsCounterTest,PeriodChanged)254 IN_PROC_BROWSER_TEST_F(PasswordsCounterTest, PeriodChanged) {
255 AddLogin("https://www.google.com", "user", false);
256 RevertTimeInDays(2);
257 AddLogin("https://example.com", "user1", false);
258 RevertTimeInDays(3);
259 AddLogin("https://example.com", "user2", false);
260 RevertTimeInDays(30);
261 AddLogin("https://www.chrome.com", "user", false);
262 WaitForUICallbacksFromAddingLogins();
263
264 Profile* profile = browser()->profile();
265 browsing_data::PasswordsCounter counter(
266 PasswordStoreFactory::GetForProfile(profile,
267 ServiceAccessType::EXPLICIT_ACCESS),
268 AccountPasswordStoreFactory::GetForProfile(
269 profile, ServiceAccessType::EXPLICIT_ACCESS),
270 ProfileSyncServiceFactory::GetForProfile(profile));
271 counter.Init(
272 profile->GetPrefs(), browsing_data::ClearBrowsingDataTab::ADVANCED,
273 base::Bind(&PasswordsCounterTest::Callback, base::Unretained(this)));
274
275 SetDeletionPeriodPref(browsing_data::TimePeriod::LAST_HOUR);
276 WaitForCounting();
277 EXPECT_EQ(1u, GetResult());
278
279 SetDeletionPeriodPref(browsing_data::TimePeriod::LAST_DAY);
280 WaitForCounting();
281 EXPECT_EQ(1u, GetResult());
282
283 SetDeletionPeriodPref(browsing_data::TimePeriod::LAST_WEEK);
284 WaitForCounting();
285 EXPECT_EQ(3u, GetResult());
286
287 SetDeletionPeriodPref(browsing_data::TimePeriod::FOUR_WEEKS);
288 WaitForCounting();
289 EXPECT_EQ(3u, GetResult());
290
291 SetDeletionPeriodPref(browsing_data::TimePeriod::OLDER_THAN_30_DAYS);
292 WaitForCounting();
293 EXPECT_EQ(1u, GetResult());
294
295 SetDeletionPeriodPref(browsing_data::TimePeriod::ALL_TIME);
296 WaitForCounting();
297 EXPECT_EQ(4u, GetResult());
298 }
299
300 // Tests that the two most commonly used domains are chosen as the listed domain
301 // examples.
IN_PROC_BROWSER_TEST_F(PasswordsCounterTest,MostCommonDomains)302 IN_PROC_BROWSER_TEST_F(PasswordsCounterTest, MostCommonDomains) {
303 SetTimesUsed(3);
304 AddLogin("https://www.google.com", "user", false);
305 SetTimesUsed(4);
306 AddLogin("https://wwww.maps.google.com", "user", false);
307 SetTimesUsed(1);
308 AddLogin("https://www.example.com", "user", false);
309 SetTimesUsed(2);
310 AddLogin("https://www.chrome.com", "user", false);
311 WaitForUICallbacksFromAddingLogins();
312
313 Profile* profile = browser()->profile();
314 browsing_data::PasswordsCounter counter(
315 PasswordStoreFactory::GetForProfile(profile,
316 ServiceAccessType::EXPLICIT_ACCESS),
317 AccountPasswordStoreFactory::GetForProfile(
318 profile, ServiceAccessType::EXPLICIT_ACCESS),
319 ProfileSyncServiceFactory::GetForProfile(profile));
320 counter.Init(
321 profile->GetPrefs(), browsing_data::ClearBrowsingDataTab::ADVANCED,
322 base::Bind(&PasswordsCounterTest::Callback, base::Unretained(this)));
323 counter.Restart();
324
325 WaitForCounting();
326 std::vector<std::string> domain_examples = {"google.com", "chrome.com"};
327 EXPECT_EQ(domain_examples, GetDomainExamples());
328 }
329
330 } // namespace
331