1 // Copyright 2019 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/credential_cache.h"
6
7 #include <memory>
8 #include <string>
9
10 #include "base/strings/string_piece.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "components/autofill/core/common/password_form.h"
13 #include "components/password_manager/core/browser/origin_credential_store.h"
14 #include "components/password_manager/core/browser/password_manager_test_utils.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace password_manager {
19
20 namespace {
21
22 using autofill::PasswordForm;
23 using url::Origin;
24
25 using IsPublicSuffixMatch = UiCredential::IsPublicSuffixMatch;
26 using IsAffiliationBasedMatch = UiCredential::IsAffiliationBasedMatch;
27 using IsOriginBlacklisted = CredentialCache::IsOriginBlacklisted;
28
29 constexpr char kExampleSite[] = "https://example.com/";
30 constexpr char kExampleSite2[] = "https://example.two.com/";
31 constexpr char kExampleSiteMobile[] = "https://m.example.com/";
32 constexpr char kExampleSiteSubdomain[] = "https://accounts.example.com/";
33
MakeUiCredential(base::StringPiece username,base::StringPiece password,base::StringPiece origin=kExampleSite,IsPublicSuffixMatch is_public_suffix_match=IsPublicSuffixMatch (false),IsAffiliationBasedMatch is_affiliation_based_match=IsAffiliationBasedMatch (false))34 UiCredential MakeUiCredential(
35 base::StringPiece username,
36 base::StringPiece password,
37 base::StringPiece origin = kExampleSite,
38 IsPublicSuffixMatch is_public_suffix_match = IsPublicSuffixMatch(false),
39 IsAffiliationBasedMatch is_affiliation_based_match =
40 IsAffiliationBasedMatch(false)) {
41 return UiCredential(base::UTF8ToUTF16(username), base::UTF8ToUTF16(password),
42 Origin::Create(GURL(origin)), is_public_suffix_match,
43 is_affiliation_based_match);
44 }
45
46 } // namespace
47
48 class CredentialCacheTest : public testing::Test {
49 public:
cache()50 CredentialCache* cache() { return &cache_; }
51
52 private:
53 CredentialCache cache_;
54 };
55
TEST_F(CredentialCacheTest,ReturnsSameStoreForSameOriginOnly)56 TEST_F(CredentialCacheTest, ReturnsSameStoreForSameOriginOnly) {
57 EXPECT_EQ(&cache()->GetCredentialStore(Origin::Create(GURL(kExampleSite))),
58 &cache()->GetCredentialStore(Origin::Create(GURL(kExampleSite))));
59
60 EXPECT_NE(&cache()->GetCredentialStore(Origin::Create(GURL(kExampleSite))),
61 &cache()->GetCredentialStore(Origin::Create(GURL(kExampleSite2))));
62 }
63
TEST_F(CredentialCacheTest,StoresCredentialsSortedByAplhabetAndOrigins)64 TEST_F(CredentialCacheTest, StoresCredentialsSortedByAplhabetAndOrigins) {
65 Origin origin = Origin::Create(GURL(kExampleSite));
66 cache()->SaveCredentialsAndBlacklistedForOrigin(
67 {CreateEntry("Berta", "30948", GURL(kExampleSite), false, false).get(),
68 CreateEntry("Adam", "Pas83B", GURL(kExampleSite), false, false).get(),
69 CreateEntry("Dora", "PakudC", GURL(kExampleSite), false, false).get(),
70 CreateEntry("Carl", "P1238C", GURL(kExampleSite), false, false).get(),
71 // These entries need to be ordered but come after the examples above.
72 CreateEntry("Cesar", "V3V1V", GURL(kExampleSite), false, true).get(),
73 CreateEntry("Rolf", "A4nd0m", GURL(kExampleSiteMobile), true, false)
74 .get(),
75 CreateEntry("Greg", "5fnd1m", GURL(kExampleSiteSubdomain), true, false)
76 .get(),
77 CreateEntry("Elfi", "a65ddm", GURL(kExampleSiteSubdomain), true, false)
78 .get(),
79 CreateEntry("Alf", "R4nd50m", GURL(kExampleSiteMobile), true, false)
80 .get()},
81 IsOriginBlacklisted(false), origin);
82
83 EXPECT_THAT(
84 cache()->GetCredentialStore(origin).GetCredentials(),
85 testing::ElementsAre(
86
87 // Alphabetical entries of the exactly matching https://example.com:
88 MakeUiCredential("Adam", "Pas83B"),
89 MakeUiCredential("Berta", "30948"),
90 MakeUiCredential("Carl", "P1238C"),
91 // Affiliation based matches are first class citizens and should be
92 // treated as a first-party credential.
93 MakeUiCredential("Cesar", "V3V1V", kExampleSite,
94 IsPublicSuffixMatch(false),
95 IsAffiliationBasedMatch(true)),
96 MakeUiCredential("Dora", "PakudC"),
97
98 // Alphabetical entries of PSL-match https://accounts.example.com:
99 MakeUiCredential("Elfi", "a65ddm", kExampleSiteSubdomain,
100 IsPublicSuffixMatch(true)),
101 MakeUiCredential("Greg", "5fnd1m", kExampleSiteSubdomain,
102 IsPublicSuffixMatch(true)),
103
104 // Alphabetical entries of PSL-match https://m.example.com:
105 MakeUiCredential("Alf", "R4nd50m", kExampleSiteMobile,
106 IsPublicSuffixMatch(true)),
107 MakeUiCredential("Rolf", "A4nd0m", kExampleSiteMobile,
108 IsPublicSuffixMatch(true))));
109 }
110
TEST_F(CredentialCacheTest,StoredCredentialsForIndependentOrigins)111 TEST_F(CredentialCacheTest, StoredCredentialsForIndependentOrigins) {
112 Origin origin = Origin::Create(GURL(kExampleSite));
113 Origin origin2 = Origin::Create(GURL(kExampleSite2));
114
115 cache()->SaveCredentialsAndBlacklistedForOrigin(
116 {CreateEntry("Ben", "S3cur3", GURL(kExampleSite), false, false).get()},
117 IsOriginBlacklisted(false), origin);
118 cache()->SaveCredentialsAndBlacklistedForOrigin(
119 {CreateEntry("Abe", "B4dPW", GURL(kExampleSite2), false, false).get()},
120 IsOriginBlacklisted(false), origin2);
121
122 EXPECT_THAT(cache()->GetCredentialStore(origin).GetCredentials(),
123 testing::ElementsAre(MakeUiCredential("Ben", "S3cur3")));
124 EXPECT_THAT(
125 cache()->GetCredentialStore(origin2).GetCredentials(),
126 testing::ElementsAre(MakeUiCredential("Abe", "B4dPW", kExampleSite2)));
127 }
128
TEST_F(CredentialCacheTest,ClearsCredentials)129 TEST_F(CredentialCacheTest, ClearsCredentials) {
130 Origin origin = Origin::Create(GURL(kExampleSite));
131 cache()->SaveCredentialsAndBlacklistedForOrigin(
132 {CreateEntry("Ben", "S3cur3", GURL(kExampleSite), false, false).get()},
133 IsOriginBlacklisted(false), Origin::Create(GURL(kExampleSite)));
134 ASSERT_THAT(cache()->GetCredentialStore(origin).GetCredentials(),
135 testing::ElementsAre(MakeUiCredential("Ben", "S3cur3")));
136
137 cache()->ClearCredentials();
138 EXPECT_EQ(cache()->GetCredentialStore(origin).GetCredentials().size(), 0u);
139 }
140
TEST_F(CredentialCacheTest,StoresBlacklistedWithCredentials)141 TEST_F(CredentialCacheTest, StoresBlacklistedWithCredentials) {
142 Origin origin = Origin::Create(GURL(kExampleSite));
143 cache()->SaveCredentialsAndBlacklistedForOrigin(
144 {CreateEntry("Ben", "S3cur3", GURL(kExampleSite), false, false).get()},
145 IsOriginBlacklisted(true), Origin::Create(GURL(kExampleSite)));
146 EXPECT_EQ(OriginCredentialStore::BlacklistedStatus::kIsBlacklisted,
147 cache()->GetCredentialStore(origin).GetBlacklistedStatus());
148 }
149
150 } // namespace password_manager
151