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