1 // Copyright 2020 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 "components/password_manager/core/browser/ui/insecure_credentials_manager.h"
6 
7 #include "base/memory/scoped_refptr.h"
8 #include "base/strings/string_piece_forward.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/test/metrics/histogram_tester.h"
11 #include "base/test/mock_callback.h"
12 #include "base/test/task_environment.h"
13 #include "base/timer/elapsed_timer.h"
14 #include "build/build_config.h"
15 #include "components/password_manager/core/browser/compromised_credentials_table.h"
16 #include "components/password_manager/core/browser/password_form.h"
17 #include "components/password_manager/core/browser/test_password_store.h"
18 #include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 
22 namespace password_manager {
23 
24 namespace {
25 
26 constexpr char kExampleCom[] = "https://example.com";
27 constexpr char kExampleOrg[] = "https://example.org";
28 
29 constexpr char kUsername1[] = "alice";
30 constexpr char kUsername2[] = "bob";
31 
32 constexpr char kPassword1[] = "f00b4r";
33 constexpr char kPassword2[] = "s3cr3t";
34 constexpr char kPassword3[] = "484her";
35 
36 constexpr char kWeakPassword1[] = "123456";
37 constexpr char kWeakPassword2[] = "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcda";
38 constexpr char kStrongPassword1[] = "fnlsr4@cm^mdls@fkspnsg3d";
39 constexpr char kStrongPassword2[] = "pmsFlsnoab4nsl#losb@skpfnsbkjb^klsnbs!cns";
40 
41 using ::testing::ElementsAre;
42 using ::testing::ElementsAreArray;
43 using ::testing::IsEmpty;
44 
45 // Delay in milliseconds.
46 const int kDelay = 2;
47 
48 struct MockInsecureCredentialsManagerObserver
49     : InsecureCredentialsManager::Observer {
50   MOCK_METHOD(void,
51               OnCompromisedCredentialsChanged,
52               (InsecureCredentialsManager::CredentialsView),
53               (override));
54   MOCK_METHOD(void, OnWeakCredentialsChanged, (), (override));
55 };
56 
57 using StrictMockInsecureCredentialsManagerObserver =
58     ::testing::StrictMock<MockInsecureCredentialsManagerObserver>;
59 
MakeCompromised(base::StringPiece signon_realm,base::StringPiece username,CompromiseType type=CompromiseType::kLeaked)60 CompromisedCredentials MakeCompromised(
61     base::StringPiece signon_realm,
62     base::StringPiece username,
63     CompromiseType type = CompromiseType::kLeaked) {
64   return {.signon_realm = std::string(signon_realm),
65           .username = base::ASCIIToUTF16(username),
66           .compromise_type = type};
67 }
68 
MakeSavedPassword(base::StringPiece signon_realm,base::StringPiece username,base::StringPiece password,base::StringPiece username_element="")69 PasswordForm MakeSavedPassword(base::StringPiece signon_realm,
70                                base::StringPiece username,
71                                base::StringPiece password,
72                                base::StringPiece username_element = "") {
73   PasswordForm form;
74   form.signon_realm = std::string(signon_realm);
75   form.url = GURL(signon_realm);
76   form.username_value = base::ASCIIToUTF16(username);
77   form.password_value = base::ASCIIToUTF16(password);
78   form.username_element = base::ASCIIToUTF16(username_element);
79   return form;
80 }
81 
MakeLeakCredential(base::StringPiece username,base::StringPiece password)82 LeakCheckCredential MakeLeakCredential(base::StringPiece username,
83                                        base::StringPiece password) {
84   return LeakCheckCredential(base::ASCIIToUTF16(username),
85                              base::ASCIIToUTF16(password));
86 }
87 
MakeCompromisedCredential(const PasswordForm & form,const CompromisedCredentials & credential)88 CredentialWithPassword MakeCompromisedCredential(
89     const PasswordForm& form,
90     const CompromisedCredentials& credential) {
91   CredentialWithPassword credential_with_password((CredentialView(form)));
92   credential_with_password.create_time = credential.create_time;
93   credential_with_password.insecure_type =
94       credential.compromise_type == CompromiseType::kLeaked
95           ? InsecureCredentialTypeFlags::kCredentialLeaked
96           : InsecureCredentialTypeFlags::kCredentialPhished;
97   return credential_with_password;
98 }
99 
MakeWeakCredential(const PasswordForm & form)100 CredentialWithPassword MakeWeakCredential(const PasswordForm& form) {
101   CredentialWithPassword weak_credential{CredentialView(form)};
102   weak_credential.insecure_type = InsecureCredentialTypeFlags::kWeakCredential;
103   return weak_credential;
104 }
105 
MakeWeakAndCompromisedCredential(const PasswordForm & form,const CompromisedCredentials & credential)106 CredentialWithPassword MakeWeakAndCompromisedCredential(
107     const PasswordForm& form,
108     const CompromisedCredentials& credential) {
109   CredentialWithPassword credential_with_password =
110       MakeCompromisedCredential(form, credential);
111   credential_with_password.insecure_type |=
112       InsecureCredentialTypeFlags::kWeakCredential;
113   return credential_with_password;
114 }
115 
116 class InsecureCredentialsManagerTest : public ::testing::Test {
117  protected:
InsecureCredentialsManagerTest()118   InsecureCredentialsManagerTest() { store_->Init(/*prefs=*/nullptr); }
119 
~InsecureCredentialsManagerTest()120   ~InsecureCredentialsManagerTest() override {
121     store_->ShutdownOnUIThread();
122     task_env_.RunUntilIdle();
123   }
124 
store()125   TestPasswordStore& store() { return *store_; }
provider()126   InsecureCredentialsManager& provider() { return provider_; }
127 
RunUntilIdle()128   void RunUntilIdle() { task_env_.RunUntilIdle(); }
129 
130   // Returns saved password if it matches with |signon_realm| and |username|.
131   // Otherwise, returns an empty string, because the saved password should never
132   // be empty, unless it's a federated credential or "Never save" entry.
GetSavedPasswordForUsername(const std::string & signon_realm,const std::string & username)133   std::string GetSavedPasswordForUsername(const std::string& signon_realm,
134                                           const std::string& username) {
135     SavedPasswordsPresenter::SavedPasswordsView saved_passwords =
136         presenter_.GetSavedPasswords();
137     for (const auto& form : saved_passwords) {
138       if (form.signon_realm == signon_realm &&
139           form.username_value == base::UTF8ToUTF16(username)) {
140         return base::UTF16ToUTF8(form.password_value);
141       }
142     }
143     return std::string();
144   }
145 
histogram_tester()146   base::HistogramTester& histogram_tester() { return histogram_tester_; }
147 
AdvanceClock(base::TimeDelta time)148   void AdvanceClock(base::TimeDelta time) { task_env_.AdvanceClock(time); }
149 
150  private:
151   base::test::TaskEnvironment task_env_{
152       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
153   base::HistogramTester histogram_tester_;
154   scoped_refptr<TestPasswordStore> store_ =
155       base::MakeRefCounted<TestPasswordStore>();
156   SavedPasswordsPresenter presenter_{store_};
157   InsecureCredentialsManager provider_{&presenter_, store_};
158 };
159 
160 }  // namespace
161 
operator ==(const CredentialWithPassword & lhs,const CredentialWithPassword & rhs)162 bool operator==(const CredentialWithPassword& lhs,
163                 const CredentialWithPassword& rhs) {
164   return lhs.signon_realm == rhs.signon_realm && lhs.username == rhs.username &&
165          lhs.create_time == rhs.create_time &&
166          lhs.insecure_type == rhs.insecure_type && lhs.password == rhs.password;
167 }
168 
operator <<(std::ostream & out,const CredentialWithPassword & credential)169 std::ostream& operator<<(std::ostream& out,
170                          const CredentialWithPassword& credential) {
171   return out << "{ signon_realm: " << credential.signon_realm
172              << ", username: " << credential.username
173              << ", create_time: " << credential.create_time
174              << ", compromise_type: "
175              << static_cast<int>(credential.insecure_type)
176              << ", password: " << credential.password << " }";
177 }
178 
179 // Tests whether adding and removing an observer works as expected.
TEST_F(InsecureCredentialsManagerTest,NotifyObserversAboutCompromisedCredentialChanges)180 TEST_F(InsecureCredentialsManagerTest,
181        NotifyObserversAboutCompromisedCredentialChanges) {
182   std::vector<CompromisedCredentials> credentials = {
183       MakeCompromised(kExampleCom, kUsername1)};
184 
185   StrictMockInsecureCredentialsManagerObserver observer;
186   provider().AddObserver(&observer);
187 
188   // Adding a compromised credential should notify observers.
189   EXPECT_CALL(observer, OnCompromisedCredentialsChanged);
190   store().AddCompromisedCredentials(credentials[0]);
191   RunUntilIdle();
192   EXPECT_THAT(store().compromised_credentials(), ElementsAreArray(credentials));
193 
194   // Adding the exact same credential should not result in a notification, as
195   // the database is not actually modified.
196   EXPECT_CALL(observer, OnCompromisedCredentialsChanged).Times(0);
197   store().AddCompromisedCredentials(credentials[0]);
198   RunUntilIdle();
199 
200   // Remove should notify, and observers should be passed an empty list.
201   EXPECT_CALL(observer, OnCompromisedCredentialsChanged(IsEmpty()));
202   store().RemoveCompromisedCredentials(
203       credentials[0].signon_realm, credentials[0].username,
204       RemoveCompromisedCredentialsReason::kRemove);
205   RunUntilIdle();
206   EXPECT_THAT(store().compromised_credentials(), IsEmpty());
207 
208   // Similarly to repeated add, a repeated remove should not notify either.
209   EXPECT_CALL(observer, OnCompromisedCredentialsChanged).Times(0);
210   store().RemoveCompromisedCredentials(
211       credentials[0].signon_realm, credentials[0].username,
212       RemoveCompromisedCredentialsReason::kRemove);
213   RunUntilIdle();
214 
215   // After an observer is removed it should no longer receive notifications.
216   provider().RemoveObserver(&observer);
217   EXPECT_CALL(observer, OnCompromisedCredentialsChanged).Times(0);
218   store().AddCompromisedCredentials(credentials[0]);
219   RunUntilIdle();
220   EXPECT_THAT(store().compromised_credentials(), ElementsAreArray(credentials));
221 }
222 
223 // Tests removing a compromised credentials by compromise type triggers an
224 // observer works as expected.
TEST_F(InsecureCredentialsManagerTest,NotifyObserversAboutRemovingCompromisedCredentialsByCompromisedType)225 TEST_F(InsecureCredentialsManagerTest,
226        NotifyObserversAboutRemovingCompromisedCredentialsByCompromisedType) {
227   CompromisedCredentials phished_credentials =
228       MakeCompromised(kExampleCom, kUsername1, CompromiseType::kPhished);
229   CompromisedCredentials leaked_credentials =
230       MakeCompromised(kExampleCom, kUsername1, CompromiseType::kLeaked);
231 
232   StrictMockInsecureCredentialsManagerObserver observer;
233   provider().AddObserver(&observer);
234   EXPECT_CALL(observer, OnCompromisedCredentialsChanged);
235   store().AddCompromisedCredentials(phished_credentials);
236   RunUntilIdle();
237   EXPECT_CALL(observer, OnCompromisedCredentialsChanged);
238   store().AddCompromisedCredentials(leaked_credentials);
239   RunUntilIdle();
240 
241   EXPECT_CALL(observer, OnCompromisedCredentialsChanged).Times(1);
242   store().RemoveCompromisedCredentialsByCompromiseType(
243       phished_credentials.signon_realm, phished_credentials.username,
244       CompromiseType::kPhished, RemoveCompromisedCredentialsReason::kRemove);
245   RunUntilIdle();
246   EXPECT_THAT(store().compromised_credentials(),
247               ElementsAre(leaked_credentials));
248 
249   EXPECT_CALL(observer, OnCompromisedCredentialsChanged).Times(1);
250   store().RemoveCompromisedCredentialsByCompromiseType(
251       leaked_credentials.signon_realm, leaked_credentials.username,
252       CompromiseType::kLeaked, RemoveCompromisedCredentialsReason::kRemove);
253   RunUntilIdle();
254   EXPECT_THAT(store().compromised_credentials(), IsEmpty());
255   provider().RemoveObserver(&observer);
256 }
257 
258 // Tests whether adding and removing an observer works as expected.
TEST_F(InsecureCredentialsManagerTest,NotifyObserversAboutSavedPasswordsChanges)259 TEST_F(InsecureCredentialsManagerTest,
260        NotifyObserversAboutSavedPasswordsChanges) {
261   StrictMockInsecureCredentialsManagerObserver observer;
262   provider().AddObserver(&observer);
263 
264   PasswordForm saved_password =
265       MakeSavedPassword(kExampleCom, kUsername1, kPassword1);
266 
267   // Adding a saved password should notify observers.
268   EXPECT_CALL(observer, OnCompromisedCredentialsChanged);
269   EXPECT_CALL(observer, OnWeakCredentialsChanged);
270   store().AddLogin(saved_password);
271   RunUntilIdle();
272 
273   // Updating a saved password should notify observers.
274   saved_password.password_value = base::ASCIIToUTF16(kPassword2);
275   EXPECT_CALL(observer, OnCompromisedCredentialsChanged);
276   EXPECT_CALL(observer, OnWeakCredentialsChanged);
277   store().UpdateLogin(saved_password);
278   RunUntilIdle();
279 
280   // Removing a saved password should notify observers.
281   EXPECT_CALL(observer, OnCompromisedCredentialsChanged);
282   EXPECT_CALL(observer, OnWeakCredentialsChanged);
283   store().RemoveLogin(saved_password);
284   RunUntilIdle();
285 
286   // After an observer is removed it should no longer receive notifications.
287   provider().RemoveObserver(&observer);
288   EXPECT_CALL(observer, OnCompromisedCredentialsChanged).Times(0);
289   EXPECT_CALL(observer, OnWeakCredentialsChanged).Times(0);
290   store().AddLogin(saved_password);
291   RunUntilIdle();
292 }
293 
294 // Tests that the provider is able to join a single password with a compromised
295 // credential.
TEST_F(InsecureCredentialsManagerTest,JoinSingleCredentials)296 TEST_F(InsecureCredentialsManagerTest, JoinSingleCredentials) {
297   PasswordForm password =
298       MakeSavedPassword(kExampleCom, kUsername1, kPassword1);
299   CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1);
300 
301   store().AddLogin(password);
302   store().AddCompromisedCredentials(credential);
303   RunUntilIdle();
304 
305   CredentialWithPassword expected =
306       MakeCompromisedCredential(password, credential);
307   expected.password = password.password_value;
308   EXPECT_THAT(provider().GetCompromisedCredentials(), ElementsAre(expected));
309 }
310 
311 // Tests that the provider is able to join a password with a credential that was
312 // compromised in multiple ways.
TEST_F(InsecureCredentialsManagerTest,JoinPhishedAndLeaked)313 TEST_F(InsecureCredentialsManagerTest, JoinPhishedAndLeaked) {
314   PasswordForm password =
315       MakeSavedPassword(kExampleCom, kUsername1, kPassword1);
316   CompromisedCredentials leaked =
317       MakeCompromised(kExampleCom, kUsername1, CompromiseType::kLeaked);
318   CompromisedCredentials phished =
319       MakeCompromised(kExampleCom, kUsername1, CompromiseType::kPhished);
320 
321   store().AddLogin(password);
322   store().AddCompromisedCredentials(leaked);
323   store().AddCompromisedCredentials(phished);
324   RunUntilIdle();
325 
326   CredentialWithPassword expected = MakeCompromisedCredential(password, leaked);
327   expected.password = password.password_value;
328   expected.insecure_type = (InsecureCredentialTypeFlags::kCredentialLeaked |
329                             InsecureCredentialTypeFlags::kCredentialPhished);
330 
331   EXPECT_THAT(provider().GetCompromisedCredentials(), ElementsAre(expected));
332 }
333 
334 // Tests that the provider reacts whenever the saved passwords or the
335 // compromised credentials change.
TEST_F(InsecureCredentialsManagerTest,ReactToChangesInBothTables)336 TEST_F(InsecureCredentialsManagerTest, ReactToChangesInBothTables) {
337   std::vector<PasswordForm> passwords = {
338       MakeSavedPassword(kExampleCom, kUsername1, kPassword1),
339       MakeSavedPassword(kExampleCom, kUsername2, kPassword2)};
340 
341   std::vector<CompromisedCredentials> credentials = {
342       MakeCompromised(kExampleCom, kUsername1),
343       MakeCompromised(kExampleCom, kUsername2)};
344 
345   std::vector<CredentialWithPassword> expected = {
346       MakeCompromisedCredential(passwords[0], credentials[0]),
347       MakeCompromisedCredential(passwords[1], credentials[1])};
348 
349   store().AddLogin(passwords[0]);
350   RunUntilIdle();
351   EXPECT_THAT(provider().GetCompromisedCredentials(), IsEmpty());
352 
353   store().AddCompromisedCredentials(credentials[0]);
354   RunUntilIdle();
355   EXPECT_THAT(provider().GetCompromisedCredentials(), ElementsAre(expected[0]));
356 
357   store().AddLogin(passwords[1]);
358   RunUntilIdle();
359   EXPECT_THAT(provider().GetCompromisedCredentials(), ElementsAre(expected[0]));
360 
361   store().AddCompromisedCredentials(credentials[1]);
362   RunUntilIdle();
363   EXPECT_THAT(provider().GetCompromisedCredentials(),
364               ElementsAreArray(expected));
365 
366   store().RemoveLogin(passwords[0]);
367   RunUntilIdle();
368   EXPECT_THAT(provider().GetCompromisedCredentials(), ElementsAre(expected[1]));
369 
370   store().RemoveLogin(passwords[1]);
371   RunUntilIdle();
372   EXPECT_THAT(provider().GetCompromisedCredentials(), IsEmpty());
373 }
374 
375 // Tests that the provider is able to join multiple passwords with compromised
376 // credentials.
TEST_F(InsecureCredentialsManagerTest,JoinMultipleCredentials)377 TEST_F(InsecureCredentialsManagerTest, JoinMultipleCredentials) {
378   std::vector<PasswordForm> passwords = {
379       MakeSavedPassword(kExampleCom, kUsername1, kPassword1),
380       MakeSavedPassword(kExampleCom, kUsername2, kPassword2)};
381 
382   std::vector<CompromisedCredentials> credentials = {
383       MakeCompromised(kExampleCom, kUsername1),
384       MakeCompromised(kExampleCom, kUsername2)};
385 
386   store().AddLogin(passwords[0]);
387   store().AddLogin(passwords[1]);
388   store().AddCompromisedCredentials(credentials[0]);
389   store().AddCompromisedCredentials(credentials[1]);
390   RunUntilIdle();
391 
392   CredentialWithPassword expected1 =
393       MakeCompromisedCredential(passwords[0], credentials[0]);
394   CredentialWithPassword expected2 =
395       MakeCompromisedCredential(passwords[1], credentials[1]);
396 
397   EXPECT_THAT(provider().GetCompromisedCredentials(),
398               ElementsAre(expected1, expected2));
399 }
400 
401 // Tests that joining a compromised credential with saved passwords with a
402 // different username results in an empty list.
TEST_F(InsecureCredentialsManagerTest,JoinWitDifferentUsername)403 TEST_F(InsecureCredentialsManagerTest, JoinWitDifferentUsername) {
404   std::vector<PasswordForm> passwords = {
405       MakeSavedPassword(kExampleCom, kUsername2, kPassword1),
406       MakeSavedPassword(kExampleCom, kUsername2, kPassword2)};
407 
408   CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1);
409 
410   store().AddLogin(passwords[0]);
411   store().AddLogin(passwords[1]);
412   store().AddCompromisedCredentials(credential);
413   RunUntilIdle();
414 
415   EXPECT_THAT(provider().GetCompromisedCredentials(), IsEmpty());
416 }
417 
418 // Tests that joining a compromised credential with saved passwords with a
419 // matching username but different signon_realm results in an empty list.
TEST_F(InsecureCredentialsManagerTest,JoinWitDifferentSignonRealm)420 TEST_F(InsecureCredentialsManagerTest, JoinWitDifferentSignonRealm) {
421   std::vector<PasswordForm> passwords = {
422       MakeSavedPassword(kExampleOrg, kUsername1, kPassword1),
423       MakeSavedPassword(kExampleOrg, kUsername1, kPassword2)};
424 
425   CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1);
426 
427   store().AddLogin(passwords[0]);
428   store().AddLogin(passwords[1]);
429   store().AddCompromisedCredentials(credential);
430   RunUntilIdle();
431 
432   EXPECT_THAT(provider().GetCompromisedCredentials(), IsEmpty());
433 }
434 
435 // Tests that joining a compromised credential with multiple saved passwords for
436 // the same signon_realm and username combination results in multiple entries
437 // when the passwords are distinct.
TEST_F(InsecureCredentialsManagerTest,JoinWithMultipleDistinctPasswords)438 TEST_F(InsecureCredentialsManagerTest, JoinWithMultipleDistinctPasswords) {
439   std::vector<PasswordForm> passwords = {
440       MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_1"),
441       MakeSavedPassword(kExampleCom, kUsername1, kPassword2, "element_2")};
442 
443   CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1);
444 
445   store().AddLogin(passwords[0]);
446   store().AddLogin(passwords[1]);
447   store().AddCompromisedCredentials(credential);
448   RunUntilIdle();
449 
450   CredentialWithPassword expected1 =
451       MakeCompromisedCredential(passwords[0], credential);
452   CredentialWithPassword expected2 =
453       MakeCompromisedCredential(passwords[1], credential);
454 
455   EXPECT_THAT(provider().GetCompromisedCredentials(),
456               ElementsAre(expected1, expected2));
457 }
458 
459 // Tests that joining a compromised credential with multiple saved passwords for
460 // the same signon_realm and username combination results in a single entry
461 // when the passwords are the same.
TEST_F(InsecureCredentialsManagerTest,JoinWithMultipleRepeatedPasswords)462 TEST_F(InsecureCredentialsManagerTest, JoinWithMultipleRepeatedPasswords) {
463   CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1);
464   std::vector<PasswordForm> passwords = {
465       MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_1"),
466       MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_2")};
467 
468   store().AddLogin(passwords[0]);
469   store().AddLogin(passwords[1]);
470   store().AddCompromisedCredentials(credential);
471   RunUntilIdle();
472 
473   CredentialWithPassword expected =
474       MakeCompromisedCredential(passwords[0], credential);
475 
476   EXPECT_THAT(provider().GetCompromisedCredentials(), ElementsAre(expected));
477 }
478 
479 // Tests that verifies mapping compromised credentials to passwords works
480 // correctly.
TEST_F(InsecureCredentialsManagerTest,MapCompromisedPasswordsToPasswords)481 TEST_F(InsecureCredentialsManagerTest, MapCompromisedPasswordsToPasswords) {
482   std::vector<PasswordForm> passwords = {
483       MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_1"),
484       MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_2"),
485       MakeSavedPassword(kExampleOrg, kUsername2, kPassword2)};
486 
487   std::vector<CompromisedCredentials> credentials = {
488       MakeCompromised(kExampleCom, kUsername1),
489       MakeCompromised(kExampleOrg, kUsername2)};
490 
491   std::vector<CredentialWithPassword> credentials_with_password = {
492       MakeCompromisedCredential(passwords[0], credentials[0]),
493       MakeCompromisedCredential(passwords[1], credentials[0]),
494       MakeCompromisedCredential(passwords[2], credentials[1])};
495 
496   store().AddLogin(passwords[0]);
497   store().AddLogin(passwords[1]);
498   store().AddLogin(passwords[2]);
499   store().AddCompromisedCredentials(credentials[0]);
500   store().AddCompromisedCredentials(credentials[1]);
501 
502   RunUntilIdle();
503   EXPECT_THAT(provider().GetSavedPasswordsFor(credentials_with_password[0]),
504               ElementsAreArray(store().stored_passwords().at(kExampleCom)));
505 
506   EXPECT_THAT(provider().GetSavedPasswordsFor(credentials_with_password[1]),
507               ElementsAreArray(store().stored_passwords().at(kExampleCom)));
508 
509   EXPECT_THAT(provider().GetSavedPasswordsFor(credentials_with_password[2]),
510               ElementsAreArray(store().stored_passwords().at(kExampleOrg)));
511 }
512 
TEST_F(InsecureCredentialsManagerTest,StartWeakCheckNotifiesOnCompletion)513 TEST_F(InsecureCredentialsManagerTest, StartWeakCheckNotifiesOnCompletion) {
514   base::MockOnceClosure closure;
515   provider().StartWeakCheck(closure.Get());
516   EXPECT_CALL(closure, Run);
517   RunUntilIdle();
518 }
519 
TEST_F(InsecureCredentialsManagerTest,StartWeakCheckOnEmptyPasswordsList)520 TEST_F(InsecureCredentialsManagerTest, StartWeakCheckOnEmptyPasswordsList) {
521   EXPECT_THAT(
522       histogram_tester().GetTotalCountsForPrefix("PasswordManager.WeakCheck"),
523       IsEmpty());
524 
525   RunUntilIdle();
526   provider().StartWeakCheck();
527   AdvanceClock(base::TimeDelta::FromMilliseconds(kDelay));
528   RunUntilIdle();
529 
530   EXPECT_THAT(provider().GetWeakCredentials(), IsEmpty());
531 
532   histogram_tester().ExpectUniqueSample(
533       "PasswordManager.WeakCheck.CheckedPasswords", 0, 1);
534   histogram_tester().ExpectUniqueSample("PasswordManager.WeakCheck.Time",
535                                         kDelay, 1);
536   histogram_tester().ExpectUniqueSample(
537       "PasswordManager.WeakCheck.WeakPasswords", 0, 1);
538 }
539 
TEST_F(InsecureCredentialsManagerTest,WeakCredentialsNotFound)540 TEST_F(InsecureCredentialsManagerTest, WeakCredentialsNotFound) {
541   std::vector<PasswordForm> passwords = {
542       MakeSavedPassword(kExampleCom, kUsername1, kStrongPassword1),
543       MakeSavedPassword(kExampleCom, kUsername2, kStrongPassword2)};
544 
545   store().AddLogin(passwords[0]);
546   store().AddLogin(passwords[1]);
547   EXPECT_THAT(
548       histogram_tester().GetTotalCountsForPrefix("PasswordManager.WeakCheck"),
549       IsEmpty());
550 
551   RunUntilIdle();
552   provider().StartWeakCheck();
553   AdvanceClock(base::TimeDelta::FromMilliseconds(2 * kDelay));
554   RunUntilIdle();
555 
556   EXPECT_THAT(provider().GetWeakCredentials(), IsEmpty());
557 
558   histogram_tester().ExpectUniqueSample(
559       "PasswordManager.WeakCheck.CheckedPasswords", 2, 1);
560   histogram_tester().ExpectUniqueSample("PasswordManager.WeakCheck.Time",
561                                         2 * kDelay, 1);
562   histogram_tester().ExpectUniqueSample(
563       "PasswordManager.WeakCheck.WeakPasswords", 0, 1);
564   histogram_tester().ExpectUniqueSample(
565       "PasswordManager.WeakCheck.PasswordScore", 4, 2);
566 }
567 
TEST_F(InsecureCredentialsManagerTest,DetectedWeakCredential)568 TEST_F(InsecureCredentialsManagerTest, DetectedWeakCredential) {
569   std::vector<PasswordForm> passwords = {
570       MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1),
571       MakeSavedPassword(kExampleCom, kUsername2, kStrongPassword1)};
572 
573   store().AddLogin(passwords[0]);
574   store().AddLogin(passwords[1]);
575   EXPECT_THAT(
576       histogram_tester().GetTotalCountsForPrefix("PasswordManager.WeakCheck"),
577       IsEmpty());
578 
579   RunUntilIdle();
580   provider().StartWeakCheck();
581   AdvanceClock(base::TimeDelta::FromMilliseconds(kDelay));
582   RunUntilIdle();
583 
584   std::vector<CredentialWithPassword> weak_credentials =
585       provider().GetWeakCredentials();
586 
587   ASSERT_EQ(weak_credentials.size(), 1u);
588   EXPECT_EQ(base::UTF16ToUTF8(weak_credentials[0].password), kWeakPassword1);
589   EXPECT_TRUE(IsWeak(weak_credentials[0].insecure_type));
590 
591   histogram_tester().ExpectUniqueSample(
592       "PasswordManager.WeakCheck.CheckedPasswords", 2, 1);
593   histogram_tester().ExpectUniqueSample("PasswordManager.WeakCheck.Time",
594                                         kDelay, 1);
595   histogram_tester().ExpectUniqueSample(
596       "PasswordManager.WeakCheck.WeakPasswords", 1, 1);
597   histogram_tester().ExpectTotalCount("PasswordManager.WeakCheck.PasswordScore",
598                                       2);
599 }
600 
601 // Tests that credentials with the same signon_realm and username, but different
602 // passwords will be both returned by GetWeakCredentials().
TEST_F(InsecureCredentialsManagerTest,FindBothWeakCredentialsWithDifferentPasswords)603 TEST_F(InsecureCredentialsManagerTest,
604        FindBothWeakCredentialsWithDifferentPasswords) {
605   std::vector<PasswordForm> passwords = {
606       MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1, "element_1"),
607       MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword2, "element_2")};
608 
609   store().AddLogin(passwords[0]);
610   store().AddLogin(passwords[1]);
611 
612   RunUntilIdle();
613   provider().StartWeakCheck();
614   AdvanceClock(base::TimeDelta::FromMilliseconds(kDelay));
615   RunUntilIdle();
616 
617   std::vector<CredentialWithPassword> weak_credentials =
618       provider().GetWeakCredentials();
619 
620   ASSERT_EQ(weak_credentials.size(), 2u);
621   EXPECT_TRUE(IsWeak(weak_credentials[0].insecure_type));
622   EXPECT_TRUE(IsWeak(weak_credentials[1].insecure_type));
623 
624   histogram_tester().ExpectUniqueSample(
625       "PasswordManager.WeakCheck.CheckedPasswords", 2, 1);
626   histogram_tester().ExpectUniqueSample("PasswordManager.WeakCheck.Time",
627                                         kDelay, 1);
628   histogram_tester().ExpectUniqueSample(
629       "PasswordManager.WeakCheck.WeakPasswords", 2, 1);
630   histogram_tester().ExpectTotalCount("PasswordManager.WeakCheck.PasswordScore",
631                                       2);
632 }
633 
634 // Tests that credentials with the same signon_realm, username and passwords
635 // will be joind and GetWeakCredentials() will return one credential.
TEST_F(InsecureCredentialsManagerTest,JoinWeakCredentialsWithTheSamePasswords)636 TEST_F(InsecureCredentialsManagerTest,
637        JoinWeakCredentialsWithTheSamePasswords) {
638   std::vector<PasswordForm> passwords = {
639       MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1, "element_1"),
640       MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1, "element_2")};
641 
642   store().AddLogin(passwords[0]);
643   store().AddLogin(passwords[1]);
644 
645   RunUntilIdle();
646   provider().StartWeakCheck();
647   AdvanceClock(base::TimeDelta::FromMilliseconds(kDelay));
648   RunUntilIdle();
649 
650   std::vector<CredentialWithPassword> weak_credentials =
651       provider().GetWeakCredentials();
652 
653   ASSERT_EQ(weak_credentials.size(), 1u);
654   EXPECT_EQ(base::UTF16ToUTF8(weak_credentials[0].password), kWeakPassword1);
655   EXPECT_TRUE(IsWeak(weak_credentials[0].insecure_type));
656 
657   histogram_tester().ExpectUniqueSample(
658       "PasswordManager.WeakCheck.CheckedPasswords", 1, 1);
659   histogram_tester().ExpectUniqueSample("PasswordManager.WeakCheck.Time",
660                                         kDelay, 1);
661   histogram_tester().ExpectUniqueSample(
662       "PasswordManager.WeakCheck.WeakPasswords", 1, 1);
663   histogram_tester().ExpectUniqueSample(
664       "PasswordManager.WeakCheck.PasswordScore", 0, 1);
665 }
666 
TEST_F(InsecureCredentialsManagerTest,BothWeakAndCompromisedCredentialsExist)667 TEST_F(InsecureCredentialsManagerTest, BothWeakAndCompromisedCredentialsExist) {
668   std::vector<PasswordForm> passwords = {
669       MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1),
670       MakeSavedPassword(kExampleCom, kUsername2, kStrongPassword1)};
671   std::vector<CompromisedCredentials> compromised_credentials = {
672       MakeCompromised(kExampleCom, kUsername1),
673       MakeCompromised(kExampleCom, kUsername2)};
674 
675   store().AddLogin(passwords[0]);
676   store().AddLogin(passwords[1]);
677   store().AddCompromisedCredentials(compromised_credentials[0]);
678   store().AddCompromisedCredentials(compromised_credentials[1]);
679 
680   RunUntilIdle();
681   provider().StartWeakCheck();
682   AdvanceClock(base::TimeDelta::FromMilliseconds(kDelay));
683   RunUntilIdle();
684 
685   std::vector<CredentialWithPassword> returned_weak_credentials =
686       provider().GetWeakCredentials();
687   std::vector<CredentialWithPassword> returned_compromised_credentials =
688       provider().GetCompromisedCredentials();
689 
690   ASSERT_EQ(returned_weak_credentials.size(), 1u);
691   EXPECT_EQ(base::UTF16ToUTF8(returned_weak_credentials[0].password),
692             kWeakPassword1);
693   EXPECT_TRUE(IsWeak(returned_weak_credentials[0].insecure_type));
694 
695   ASSERT_EQ(returned_compromised_credentials.size(), 2u);
696   EXPECT_TRUE(IsCompromised(returned_compromised_credentials[0].insecure_type));
697   EXPECT_TRUE(IsCompromised(returned_compromised_credentials[1].insecure_type));
698 
699   histogram_tester().ExpectUniqueSample(
700       "PasswordManager.WeakCheck.CheckedPasswords", 2, 1);
701   histogram_tester().ExpectUniqueSample("PasswordManager.WeakCheck.Time",
702                                         kDelay, 1);
703   histogram_tester().ExpectUniqueSample(
704       "PasswordManager.WeakCheck.WeakPasswords", 1, 1);
705   histogram_tester().ExpectTotalCount("PasswordManager.WeakCheck.PasswordScore",
706                                       2);
707 }
708 
709 // Checks that for a credential that is both weak and compromised,
710 // getWeakCredentials and GetCompromisedCredentials will return this credential
711 // in one instance.
TEST_F(InsecureCredentialsManagerTest,SingleCredentialIsWeakAndCompromised)712 TEST_F(InsecureCredentialsManagerTest, SingleCredentialIsWeakAndCompromised) {
713   std::vector<PasswordForm> passwords = {
714       MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1)};
715   std::vector<CompromisedCredentials> compromised_credentials = {
716       MakeCompromised(kExampleCom, kUsername1)};
717 
718   store().AddLogin(passwords[0]);
719   store().AddCompromisedCredentials(compromised_credentials[0]);
720 
721   RunUntilIdle();
722   provider().StartWeakCheck();
723   AdvanceClock(base::TimeDelta::FromMilliseconds(kDelay));
724   RunUntilIdle();
725 
726   std::vector<CredentialWithPassword> returned_weak_credentials =
727       provider().GetWeakCredentials();
728   std::vector<CredentialWithPassword> returned_compromised_credentials =
729       provider().GetCompromisedCredentials();
730 
731   // Since the credential is weak and compromised, the |insecure_type| should be
732   // weak and compromised for elements from |returned_weak_credentials| and
733   // |returned_compromised_credentials|.
734   ASSERT_EQ(returned_weak_credentials.size(), 1u);
735   EXPECT_EQ(base::UTF16ToUTF8(returned_weak_credentials[0].password),
736             kWeakPassword1);
737   EXPECT_TRUE(IsWeak(returned_weak_credentials[0].insecure_type));
738   EXPECT_TRUE(IsCompromised(returned_weak_credentials[0].insecure_type));
739 
740   ASSERT_EQ(returned_compromised_credentials.size(), 1u);
741   EXPECT_EQ(base::UTF16ToUTF8(returned_compromised_credentials[0].password),
742             kWeakPassword1);
743   EXPECT_TRUE(IsWeak(returned_compromised_credentials[0].insecure_type));
744   EXPECT_TRUE(IsCompromised(returned_compromised_credentials[0].insecure_type));
745 
746   histogram_tester().ExpectUniqueSample(
747       "PasswordManager.WeakCheck.CheckedPasswords", 1, 1);
748   histogram_tester().ExpectUniqueSample("PasswordManager.WeakCheck.Time",
749                                         kDelay, 1);
750   histogram_tester().ExpectUniqueSample(
751       "PasswordManager.WeakCheck.WeakPasswords", 1, 1);
752   histogram_tester().ExpectUniqueSample(
753       "PasswordManager.WeakCheck.PasswordScore", 0, 1);
754 }
755 
756 // Test verifies that saving LeakCheckCredential via provider adds expected
757 // compromised credential.
TEST_F(InsecureCredentialsManagerTest,SaveCompromisedPassword)758 TEST_F(InsecureCredentialsManagerTest, SaveCompromisedPassword) {
759   PasswordForm password_form =
760       MakeSavedPassword(kExampleCom, kUsername1, kPassword1);
761   LeakCheckCredential credential = MakeLeakCredential(kUsername1, kPassword1);
762   CompromisedCredentials compromised_credential =
763       MakeCompromised(kExampleCom, kUsername1);
764 
765   store().AddLogin(password_form);
766   RunUntilIdle();
767 
768   CredentialWithPassword expected =
769       MakeCompromisedCredential(password_form, compromised_credential);
770   expected.create_time = base::Time::Now();
771 
772   provider().SaveCompromisedCredential(credential);
773   RunUntilIdle();
774 
775   EXPECT_THAT(provider().GetCompromisedCredentials(), ElementsAre(expected));
776 }
777 
778 // Test verifies that editing Compromised Credential via provider change the
779 // original password form.
TEST_F(InsecureCredentialsManagerTest,UpdateCompromisedPassword)780 TEST_F(InsecureCredentialsManagerTest, UpdateCompromisedPassword) {
781   PasswordForm password_form =
782       MakeSavedPassword(kExampleCom, kUsername1, kPassword1);
783   CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1);
784 
785   store().AddLogin(password_form);
786   store().AddCompromisedCredentials(credential);
787 
788   RunUntilIdle();
789   CredentialWithPassword expected =
790 #if !defined(OS_ANDROID) && !defined(OS_IOS)
791       MakeWeakAndCompromisedCredential(password_form, credential);
792 #else
793       MakeCompromisedCredential(password_form, credential);
794 #endif
795 
796   EXPECT_TRUE(provider().UpdateCredential(expected, kPassword2));
797   RunUntilIdle();
798   expected.password = base::UTF8ToUTF16(kPassword2);
799 
800   EXPECT_THAT(provider().GetCompromisedCredentials(), ElementsAre(expected));
801 }
802 
803 // Test verifies that editing weak credential via provider has affect on weak
804 // credentials and updates password in the store.
TEST_F(InsecureCredentialsManagerTest,UpdateWeakPassword)805 TEST_F(InsecureCredentialsManagerTest, UpdateWeakPassword) {
806   PasswordForm password_form =
807       MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1);
808 
809   store().AddLogin(password_form);
810   RunUntilIdle();
811   provider().StartWeakCheck();
812   RunUntilIdle();
813 
814   EXPECT_EQ(provider().GetWeakCredentials().size(), 1u);
815   EXPECT_TRUE(provider().UpdateCredential(CredentialView(password_form),
816                                           kStrongPassword1));
817   RunUntilIdle();
818 
819   EXPECT_THAT(provider().GetWeakCredentials(), IsEmpty());
820   EXPECT_EQ(GetSavedPasswordForUsername(kExampleCom, kUsername1),
821             kStrongPassword1);
822 }
823 
824 #if !defined(OS_ANDROID) && !defined(OS_IOS)
825 // Test verifies that editing a weak credential to another weak credential
826 // continues to be treated weak.
TEST_F(InsecureCredentialsManagerTest,UpdatedWeakPasswordRemainsWeak)827 TEST_F(InsecureCredentialsManagerTest, UpdatedWeakPasswordRemainsWeak) {
828   PasswordForm password_form =
829       MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1);
830 
831   store().AddLogin(password_form);
832   RunUntilIdle();
833 
834   provider().StartWeakCheck();
835   RunUntilIdle();
836 
837   CredentialWithPassword expected = MakeWeakCredential(password_form);
838   EXPECT_THAT(provider().GetWeakCredentials(), ElementsAre(expected));
839 
840   EXPECT_TRUE(provider().UpdateCredential(expected, kWeakPassword2));
841   RunUntilIdle();
842 
843   expected.password = base::ASCIIToUTF16(kWeakPassword2);
844   EXPECT_THAT(provider().GetWeakCredentials(), ElementsAre(expected));
845 }
846 #endif
847 
848 // Test verifies that editing credential that is weak and compromised via
849 // provider change the saved password.
TEST_F(InsecureCredentialsManagerTest,UpdateInsecurePassword)850 TEST_F(InsecureCredentialsManagerTest, UpdateInsecurePassword) {
851   PasswordForm password_form =
852       MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1);
853   CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1);
854 
855   store().AddLogin(password_form);
856   store().AddCompromisedCredentials(credential);
857   RunUntilIdle();
858   provider().StartWeakCheck();
859   RunUntilIdle();
860 
861   CredentialWithPassword expected =
862       MakeWeakAndCompromisedCredential(password_form, credential);
863   EXPECT_THAT(provider().GetWeakCredentials(), ElementsAre(expected));
864   EXPECT_THAT(provider().GetCompromisedCredentials(), ElementsAre(expected));
865 
866   EXPECT_TRUE(provider().UpdateCredential(expected, kStrongPassword1));
867   RunUntilIdle();
868 
869   EXPECT_EQ(GetSavedPasswordForUsername(kExampleCom, kUsername1),
870             kStrongPassword1);
871 }
872 
TEST_F(InsecureCredentialsManagerTest,RemoveCompromisedCredential)873 TEST_F(InsecureCredentialsManagerTest, RemoveCompromisedCredential) {
874   CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1);
875   PasswordForm password =
876       MakeSavedPassword(kExampleCom, kUsername1, kPassword1);
877 
878   store().AddLogin(password);
879   store().AddCompromisedCredentials(credential);
880   RunUntilIdle();
881 
882   CredentialWithPassword expected =
883       MakeCompromisedCredential(password, credential);
884   expected.password = password.password_value;
885 
886   EXPECT_THAT(provider().GetCompromisedCredentials(), ElementsAre(expected));
887 
888   EXPECT_TRUE(provider().RemoveCredential(expected));
889   RunUntilIdle();
890   EXPECT_THAT(provider().GetCompromisedCredentials(), IsEmpty());
891 }
892 
TEST_F(InsecureCredentialsManagerTest,RemoveWeakCredential)893 TEST_F(InsecureCredentialsManagerTest, RemoveWeakCredential) {
894   PasswordForm password =
895       MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1);
896 
897   store().AddLogin(password);
898   RunUntilIdle();
899   provider().StartWeakCheck();
900   RunUntilIdle();
901 
902   EXPECT_EQ(provider().GetWeakCredentials().size(), 1u);
903   EXPECT_TRUE(provider().RemoveCredential(CredentialView(password)));
904   RunUntilIdle();
905   EXPECT_THAT(GetSavedPasswordForUsername(kExampleCom, kUsername1), IsEmpty());
906 }
907 
TEST_F(InsecureCredentialsManagerTest,RemoveInsecureCredential)908 TEST_F(InsecureCredentialsManagerTest, RemoveInsecureCredential) {
909   PasswordForm password_form =
910       MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1);
911   CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1);
912 
913   store().AddLogin(password_form);
914   store().AddCompromisedCredentials(credential);
915   RunUntilIdle();
916   provider().StartWeakCheck();
917   RunUntilIdle();
918 
919   CredentialWithPassword expected =
920       MakeWeakAndCompromisedCredential(password_form, credential);
921   EXPECT_THAT(provider().GetWeakCredentials(), ElementsAre(expected));
922   EXPECT_THAT(provider().GetCompromisedCredentials(), ElementsAre(expected));
923 
924   EXPECT_TRUE(provider().RemoveCredential(expected));
925   RunUntilIdle();
926   EXPECT_THAT(GetSavedPasswordForUsername(kExampleCom, kUsername1), IsEmpty());
927 }
928 
929 // Verifues that GetWeakCredentials() returns sorted weak credentials by using
930 // CreateSortKey.
TEST_F(InsecureCredentialsManagerTest,GetWeakCredentialsReturnsSortedData)931 TEST_F(InsecureCredentialsManagerTest, GetWeakCredentialsReturnsSortedData) {
932   const std::vector<PasswordForm> password_forms = {
933       MakeSavedPassword("http://example-a.com", "user_a1", "pwd"),
934       MakeSavedPassword("http://example-a.com", "user_a2", "pwd"),
935       MakeSavedPassword("http://example-b.com", "user_a", "pwd"),
936       MakeSavedPassword("http://example-c.com", "user_a", "pwd")};
937   store().AddLogin(password_forms[0]);
938   store().AddLogin(password_forms[1]);
939   store().AddLogin(password_forms[2]);
940   store().AddLogin(password_forms[3]);
941   RunUntilIdle();
942 
943   provider().StartWeakCheck();
944   RunUntilIdle();
945 
946   EXPECT_THAT(provider().GetWeakCredentials(),
947               ElementsAre(MakeWeakCredential(password_forms[0]),
948                           MakeWeakCredential(password_forms[1]),
949                           MakeWeakCredential(password_forms[2]),
950                           MakeWeakCredential(password_forms[3])));
951 }
952 
953 namespace {
954 class InsecureCredentialsManagerWithTwoStoresTest : public ::testing::Test {
955  protected:
InsecureCredentialsManagerWithTwoStoresTest()956   InsecureCredentialsManagerWithTwoStoresTest() {
957     profile_store_->Init(/*prefs=*/nullptr);
958     account_store_->Init(/*prefs=*/nullptr);
959   }
960 
~InsecureCredentialsManagerWithTwoStoresTest()961   ~InsecureCredentialsManagerWithTwoStoresTest() override {
962     account_store_->ShutdownOnUIThread();
963     profile_store_->ShutdownOnUIThread();
964     task_env_.RunUntilIdle();
965   }
966 
profile_store()967   TestPasswordStore& profile_store() { return *profile_store_; }
account_store()968   TestPasswordStore& account_store() { return *account_store_; }
provider()969   InsecureCredentialsManager& provider() { return provider_; }
970 
RunUntilIdle()971   void RunUntilIdle() { task_env_.RunUntilIdle(); }
972 
973  private:
974   base::test::TaskEnvironment task_env_;
975   scoped_refptr<TestPasswordStore> profile_store_ =
976       base::MakeRefCounted<TestPasswordStore>(IsAccountStore(false));
977   scoped_refptr<TestPasswordStore> account_store_ =
978       base::MakeRefCounted<TestPasswordStore>(IsAccountStore(true));
979   SavedPasswordsPresenter presenter_{profile_store_, account_store_};
980   InsecureCredentialsManager provider_{&presenter_, profile_store_,
981                                        account_store_};
982 };
983 }  // namespace
984 
985 // Tests that verifies mapping compromised credentials to passwords works
986 // correctly.
TEST_F(InsecureCredentialsManagerWithTwoStoresTest,MapCompromisedPasswordsToPasswords)987 TEST_F(InsecureCredentialsManagerWithTwoStoresTest,
988        MapCompromisedPasswordsToPasswords) {
989   // Add credentials for both `kExampleCom` and `kExampleOrg` in both stores
990   // with the same username and difference passwords. For `kUsername1`, the
991   // `kPassword1` are `kPassword2` are compromised while
992   // `kPassword3` is safe.
993   std::vector<PasswordForm> profile_store_passwords = {
994       MakeSavedPassword(kExampleCom, kUsername1, kPassword1),
995       MakeSavedPassword(kExampleOrg, kUsername1, kPassword3)};
996   for (const PasswordForm& profile_password : profile_store_passwords)
997     profile_store().AddLogin(profile_password);
998 
999   std::vector<PasswordForm> account_store_passwords = {
1000       MakeSavedPassword(kExampleCom, kUsername1, kPassword3),
1001       MakeSavedPassword(kExampleOrg, kUsername1, kPassword2)};
1002   for (const PasswordForm& account_password : account_store_passwords)
1003     account_store().AddLogin(account_password);
1004 
1005   // Mark `kPassword1` to be compromised in the profile store, and `kPassword2`
1006   // to be compromised in the account store.
1007   profile_store().AddCompromisedCredentials(
1008       MakeCompromised(kExampleCom, kUsername1));
1009   account_store().AddCompromisedCredentials(
1010       MakeCompromised(kExampleOrg, kUsername1));
1011 
1012   RunUntilIdle();
1013 
1014   // Each password should be joined only with compromised credential from
1015   // their store.
1016   EXPECT_THAT(
1017       provider().GetSavedPasswordsFor(
1018           CredentialView(kExampleCom, GURL(), base::ASCIIToUTF16(kUsername1),
1019                          base::ASCIIToUTF16(kPassword1))),
1020       ElementsAreArray(profile_store().stored_passwords().at(kExampleCom)));
1021 
1022   EXPECT_THAT(provider().GetSavedPasswordsFor(CredentialView(
1023                   kExampleOrg, GURL(), base::ASCIIToUTF16(kUsername1),
1024                   base::ASCIIToUTF16(kPassword3))),
1025               IsEmpty());
1026 
1027   EXPECT_THAT(provider().GetSavedPasswordsFor(CredentialView(
1028                   kExampleCom, GURL(), base::ASCIIToUTF16(kUsername1),
1029                   base::ASCIIToUTF16(kPassword3))),
1030               IsEmpty());
1031 
1032   EXPECT_THAT(
1033       provider().GetSavedPasswordsFor(
1034           CredentialView(kExampleOrg, GURL(), base::ASCIIToUTF16(kUsername1),
1035                          base::ASCIIToUTF16(kPassword2))),
1036       ElementsAreArray(account_store().stored_passwords().at(kExampleOrg)));
1037 }
1038 
1039 // Test verifies that saving LeakCheckCredential via provider adds expected
1040 // compromised credential to the correct store.
TEST_F(InsecureCredentialsManagerWithTwoStoresTest,SaveCompromisedPassword)1041 TEST_F(InsecureCredentialsManagerWithTwoStoresTest, SaveCompromisedPassword) {
1042   ASSERT_TRUE(profile_store().compromised_credentials().empty());
1043   ASSERT_TRUE(account_store().compromised_credentials().empty());
1044   // Add `kUsername1`,`kPassword1` to both stores.
1045   // And add `kUsername1`,`kPassword2` to the account store only.
1046   profile_store().AddLogin(
1047       MakeSavedPassword(kExampleCom, kUsername1, kPassword1));
1048 
1049   account_store().AddLogin(
1050       MakeSavedPassword(kExampleOrg, kUsername1, kPassword1));
1051   account_store().AddLogin(
1052       MakeSavedPassword(kExampleCom, kUsername1, kPassword2));
1053 
1054   RunUntilIdle();
1055 
1056   // Mark `kUsername1`, `kPassword1` as compromised, a new entry should be
1057   // added to both stores.
1058   provider().SaveCompromisedCredential(
1059       MakeLeakCredential(kUsername1, kPassword1));
1060   RunUntilIdle();
1061 
1062   EXPECT_EQ(1U, profile_store().compromised_credentials().size());
1063   EXPECT_EQ(1U, account_store().compromised_credentials().size());
1064 
1065   // Now, mark `kUsername1`, `kPassword2` as compromised, a new entry should be
1066   // added only to the account store.
1067   provider().SaveCompromisedCredential(
1068       MakeLeakCredential(kUsername1, kPassword2));
1069   RunUntilIdle();
1070 
1071   EXPECT_EQ(1U, profile_store().compromised_credentials().size());
1072   EXPECT_EQ(2U, account_store().compromised_credentials().size());
1073 }
1074 
TEST_F(InsecureCredentialsManagerWithTwoStoresTest,RemoveCompromisedCredential)1075 TEST_F(InsecureCredentialsManagerWithTwoStoresTest,
1076        RemoveCompromisedCredential) {
1077   // Add `kUsername1`,`kPassword1` to both stores.
1078   profile_store().AddLogin(
1079       MakeSavedPassword(kExampleCom, kUsername1, kPassword1));
1080   account_store().AddLogin(
1081       MakeSavedPassword(kExampleCom, kUsername1, kPassword1));
1082 
1083   // Mark `kUsername1` and `kPassword1` to be compromised in both stores.
1084   profile_store().AddCompromisedCredentials(
1085       MakeCompromised(kExampleCom, kUsername1));
1086   account_store().AddCompromisedCredentials(
1087       MakeCompromised(kExampleCom, kUsername1));
1088   RunUntilIdle();
1089 
1090   // Now remove the compromised credentials
1091   EXPECT_TRUE(provider().RemoveCredential(
1092       CredentialView(kExampleCom, GURL(), base::ASCIIToUTF16(kUsername1),
1093                      base::ASCIIToUTF16(kPassword1))));
1094   RunUntilIdle();
1095 
1096   // It should have been removed from both stores.
1097   EXPECT_TRUE(profile_store().stored_passwords().at(kExampleCom).empty());
1098   EXPECT_TRUE(account_store().stored_passwords().at(kExampleCom).empty());
1099 }
1100 
TEST_F(InsecureCredentialsManagerWithTwoStoresTest,RemoveWeakCredential)1101 TEST_F(InsecureCredentialsManagerWithTwoStoresTest, RemoveWeakCredential) {
1102   // Add `kUsername1`,`kPassword1` to both stores.
1103   profile_store().AddLogin(
1104       MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1));
1105   account_store().AddLogin(
1106       MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1));
1107   RunUntilIdle();
1108   provider().StartWeakCheck();
1109   RunUntilIdle();
1110 
1111   // Now remove the weak credential
1112   EXPECT_TRUE(provider().RemoveCredential(
1113       CredentialView(kExampleCom, GURL(), base::ASCIIToUTF16(kUsername1),
1114                      base::ASCIIToUTF16(kWeakPassword1))));
1115   RunUntilIdle();
1116 
1117   // It should have been removed from both stores.
1118   EXPECT_THAT(profile_store().stored_passwords().at(kExampleCom), IsEmpty());
1119   EXPECT_THAT(account_store().stored_passwords().at(kExampleCom), IsEmpty());
1120 }
1121 
1122 }  // namespace password_manager
1123