Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1052)

Side by Side Diff: components/safe_browsing/password_protection/password_protection_service_unittest.cc

Issue 2747313002: PasswordProtectionService verdict cache management (Closed)
Patch Set: remove extra deps Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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 #include "components/safe_browsing/password_protection/password_protection_servi ce.h" 4 #include "components/safe_browsing/password_protection/password_protection_servi ce.h"
5 5
6 #include "base/memory/ptr_util.h" 6 #include "base/memory/ptr_util.h"
7 #include "base/run_loop.h" 7 #include "base/run_loop.h"
8 #include "base/strings/string_number_conversions.h"
8 #include "base/test/histogram_tester.h" 9 #include "base/test/histogram_tester.h"
9 #include "components/safe_browsing_db/test_database_manager.h" 10 #include "components/safe_browsing_db/test_database_manager.h"
11 #include "components/sync_preferences/testing_pref_service_syncable.h"
10 #include "content/public/test/test_browser_thread_bundle.h" 12 #include "content/public/test/test_browser_thread_bundle.h"
11 #include "testing/gmock/include/gmock/gmock.h" 13 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h" 14 #include "testing/gtest/include/gtest/gtest.h"
13 15
14 namespace { 16 namespace {
15 17
16 const char kPasswordReuseMatchWhitelistHistogramName[] = 18 const char kPasswordReuseMatchWhitelistHistogramName[] =
17 "PasswordManager.PasswordReuse.MainFrameMatchCsdWhitelist"; 19 "PasswordManager.PasswordReuse.MainFrameMatchCsdWhitelist";
18 const char kWhitelistedUrl[] = "http://inwhitelist.com"; 20 const char kWhitelistedUrl[] = "http://inwhitelist.com";
19 const char kNoneWhitelistedUrl[] = "http://notinwhitelist.com"; 21 const char kNoneWhitelistedUrl[] = "http://notinwhitelist.com";
(...skipping 12 matching lines...) Expand all
32 ~MockSafeBrowsingDatabaseManager() override {} 34 ~MockSafeBrowsingDatabaseManager() override {}
33 35
34 private: 36 private:
35 DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingDatabaseManager); 37 DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingDatabaseManager);
36 }; 38 };
37 39
38 class PasswordProtectionServiceTest : public testing::Test { 40 class PasswordProtectionServiceTest : public testing::Test {
39 public: 41 public:
40 PasswordProtectionServiceTest(){}; 42 PasswordProtectionServiceTest(){};
41 43
44 ~PasswordProtectionServiceTest() override {
45 content_setting_map_->ShutdownOnUIThread();
46 }
47
48 LoginReputationClientResponse CreateVerdictProto(
49 LoginReputationClientResponse::VerdictType verdict,
50 int cache_duration_sec,
51 const std::string& cache_expression) {
52 LoginReputationClientResponse verdict_proto;
53 verdict_proto.set_verdict_type(verdict);
54 verdict_proto.set_cache_duration_sec(cache_duration_sec);
55 verdict_proto.set_cache_expression(cache_expression);
56 return verdict_proto;
57 }
58
42 void SetUp() override { 59 void SetUp() override {
43 database_manager_ = new MockSafeBrowsingDatabaseManager(); 60 database_manager_ = new MockSafeBrowsingDatabaseManager();
44 password_protection_service_ = 61 password_protection_service_ =
45 base::MakeUnique<PasswordProtectionService>(database_manager_); 62 base::MakeUnique<PasswordProtectionService>(database_manager_);
63 HostContentSettingsMap::RegisterProfilePrefs(test_pref_service_.registry());
64 content_setting_map_ = new HostContentSettingsMap(
65 &test_pref_service_, false /* incognito */, false /* guest_profile */);
46 } 66 }
47 67
48 protected: 68 protected:
49 // |thread_bundle_| is needed here because this test involves both UI and IO 69 // |thread_bundle_| is needed here because this test involves both UI and IO
50 // threads. 70 // threads.
51 content::TestBrowserThreadBundle thread_bundle_; 71 content::TestBrowserThreadBundle thread_bundle_;
52 scoped_refptr<MockSafeBrowsingDatabaseManager> database_manager_; 72 scoped_refptr<MockSafeBrowsingDatabaseManager> database_manager_;
53 std::unique_ptr<PasswordProtectionService> password_protection_service_; 73 std::unique_ptr<PasswordProtectionService> password_protection_service_;
74 sync_preferences::TestingPrefServiceSyncable test_pref_service_;
75 scoped_refptr<HostContentSettingsMap> content_setting_map_;
54 }; 76 };
55 77
56 TEST_F(PasswordProtectionServiceTest, 78 TEST_F(PasswordProtectionServiceTest,
57 TestPasswordReuseMatchWhitelistHistogram) { 79 TestPasswordReuseMatchWhitelistHistogram) {
58 const GURL whitelisted_url(kWhitelistedUrl); 80 const GURL whitelisted_url(kWhitelistedUrl);
59 const GURL not_whitelisted_url(kNoneWhitelistedUrl); 81 const GURL not_whitelisted_url(kNoneWhitelistedUrl);
60 EXPECT_CALL(*database_manager_.get(), MatchCsdWhitelistUrl(whitelisted_url)) 82 EXPECT_CALL(*database_manager_.get(), MatchCsdWhitelistUrl(whitelisted_url))
61 .WillOnce(testing::Return(true)); 83 .WillOnce(testing::Return(true));
62 EXPECT_CALL(*database_manager_.get(), 84 EXPECT_CALL(*database_manager_.get(),
63 MatchCsdWhitelistUrl(not_whitelisted_url)) 85 MatchCsdWhitelistUrl(not_whitelisted_url))
(...skipping 14 matching lines...) Expand all
78 testing::ElementsAre(base::Bucket(1, 1))); 100 testing::ElementsAre(base::Bucket(1, 1)));
79 101
80 // Non-whitelisted url should increase "False" bucket by 1. 102 // Non-whitelisted url should increase "False" bucket by 1.
81 password_protection_service_->RecordPasswordReuse(not_whitelisted_url); 103 password_protection_service_->RecordPasswordReuse(not_whitelisted_url);
82 base::RunLoop().RunUntilIdle(); 104 base::RunLoop().RunUntilIdle();
83 EXPECT_THAT( 105 EXPECT_THAT(
84 histograms.GetAllSamples(kPasswordReuseMatchWhitelistHistogramName), 106 histograms.GetAllSamples(kPasswordReuseMatchWhitelistHistogramName),
85 testing::ElementsAre(base::Bucket(0, 1), base::Bucket(1, 1))); 107 testing::ElementsAre(base::Bucket(0, 1), base::Bucket(1, 1)));
86 } 108 }
87 109
110 TEST_F(PasswordProtectionServiceTest, TestParseVerdictEntry) {
Nathan Parker 2017/03/16 21:27:11 nit: split valid/invalid cases into two tests, sin
Jialiu Lin 2017/03/18 23:46:32 Done.
111 int now_in_sec = static_cast<int>(base::Time::Now().ToDoubleT());
112 std::unique_ptr<base::DictionaryValue> valid_verdict_entry =
113 base::MakeUnique<base::DictionaryValue>();
114 valid_verdict_entry->SetInteger("cache_ttl", 10 * 60);
115 valid_verdict_entry->SetInteger("cache_creation_time", now_in_sec);
116 valid_verdict_entry->SetInteger("verdict", 1 /* SAFE */);
117
118 std::unique_ptr<base::DictionaryValue> invalid_verdict_entry =
119 base::MakeUnique<base::DictionaryValue>();
120 invalid_verdict_entry->SetString("cache_ttl", "invalid_ttl");
121
122 int cache_creation_time, cache_ttl, verdict_type_value;
123 // ParseVerdictEntry fails if input is empty.
124 EXPECT_FALSE(PasswordProtectionService::ParseVerdictEntry(
125 nullptr, &cache_creation_time, &cache_ttl, &verdict_type_value));
126
127 // ParseVerdictEntry fails if the input dict value is invalid.
128 EXPECT_FALSE(PasswordProtectionService::ParseVerdictEntry(
129 invalid_verdict_entry.get(), &cache_creation_time, &cache_ttl,
130 &verdict_type_value));
131
132 // ParseVerdictEntry success case.
133 ASSERT_TRUE(PasswordProtectionService::ParseVerdictEntry(
134 valid_verdict_entry.get(), &cache_creation_time, &cache_ttl,
135 &verdict_type_value));
136 EXPECT_EQ(600, cache_ttl);
137 EXPECT_EQ(now_in_sec, cache_creation_time);
138 EXPECT_EQ(LoginReputationClientResponse::SAFE,
139 static_cast<LoginReputationClientResponse::VerdictType>(
140 verdict_type_value));
141 }
142
143 TEST_F(PasswordProtectionServiceTest, TestUrlMatchCacheExpression) {
144 // Cache expression without path.
145 std::string cache_expression("google.com");
146 EXPECT_TRUE(PasswordProtectionService::UrlMatchCacheExpression(
147 GURL("https://www.google.com"), cache_expression));
Nathan Parker 2017/03/16 21:27:11 How about w/ and w/o the trailing slash? Is there
Jialiu Lin 2017/03/18 23:46:32 Sure.
148 EXPECT_TRUE(PasswordProtectionService::UrlMatchCacheExpression(
149 GURL("http://google.com"), cache_expression));
150 EXPECT_TRUE(PasswordProtectionService::UrlMatchCacheExpression(
151 GURL("https://maps.google.com"), cache_expression));
152 EXPECT_TRUE(PasswordProtectionService::UrlMatchCacheExpression(
153 GURL("https://www.google.com/maps/local/"), cache_expression));
154
155 // Cache expression with sub-domain.
156 cache_expression = "maps.google.com";
157 EXPECT_FALSE(PasswordProtectionService::UrlMatchCacheExpression(
158 GURL("https://google.com"), cache_expression));
159 EXPECT_FALSE(PasswordProtectionService::UrlMatchCacheExpression(
160 GURL("https://www.google.com"), cache_expression));
161 EXPECT_TRUE(PasswordProtectionService::UrlMatchCacheExpression(
162 GURL("https://maps.google.com"), cache_expression));
163 EXPECT_TRUE(PasswordProtectionService::UrlMatchCacheExpression(
164 GURL("https://maps.google.com/local/"), cache_expression));
165
166 // Cache expression with path.
167 cache_expression = std::string("evil.com/bad");
168 EXPECT_TRUE(PasswordProtectionService::UrlMatchCacheExpression(
169 GURL("http://evil.com/bad/index.html"), cache_expression));
170 EXPECT_FALSE(PasswordProtectionService::UrlMatchCacheExpression(
171 GURL("http://evil.com/worse/index.html"), cache_expression));
172 EXPECT_TRUE(PasswordProtectionService::UrlMatchCacheExpression(
173 GURL("http://phishing.malware.evil.com/bad/index.html"),
174 cache_expression));
175 }
176
177 TEST_F(PasswordProtectionServiceTest, TestSetGetAndClearCachedVerdict) {
178 // Assume each verdict has a TTL of 10 minutes.
179 LoginReputationClientResponse verdict_proto_1(CreateVerdictProto(
180 LoginReputationClientResponse::SAFE, 10 * 60, "test.com/foo"));
181 LoginReputationClientResponse verdict_proto_2(CreateVerdictProto(
182 LoginReputationClientResponse::LOW_REPUTATION, 10 * 60, "test.com/bar"));
183 LoginReputationClientResponse verdict_proto_3(CreateVerdictProto(
184 LoginReputationClientResponse::PHISHING, 10 * 60, "evil.com"));
185
186 base::Time now = base::Time::Now();
187 base::Time yesterday =
188 base::Time::FromDoubleT(now.ToDoubleT() - 24.0 * 60.0 * 60.0);
189 base::Time one_minute_ago = base::Time::FromDoubleT(now.ToDoubleT() - 60.0);
190 password_protection_service_->CacheVerdict(
Nathan Parker 2017/03/16 21:27:11 nit: I find these a bit hard to reason about. Wou
Jialiu Lin 2017/03/18 23:46:32 Regrouped test case. There are multiple SAFE enum
191 content_setting_map_.get(), GURL("http://www.test.com/foo/index.html"),
192 &verdict_proto_1, now);
193 password_protection_service_->CacheVerdict(
194 content_setting_map_.get(), GURL("http://www.test.com/bar/index.html"),
195 &verdict_proto_2, yesterday);
196 password_protection_service_->CacheVerdict(
197 content_setting_map_.get(),
198 GURL("http://phishing.evil.com/local/login.html"), &verdict_proto_3,
199 one_minute_ago);
200
201 // Return VERDICT_TYPE_UNSPECIFIED if content setting map has nothing of this
202 // origin.
203 EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
204 password_protection_service_->GetCachedVerdict(
205 content_setting_map_.get(),
206 GURL("http://www.unkown.com/index.html")));
Nathan Parker 2017/03/16 21:27:11 (nit: www.unknown.com)
Jialiu Lin 2017/03/18 23:46:32 Good eye!
207
208 // Return VERDICT_TYPE_UNSPECIFIED if verdict is expired.
209 EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
210 password_protection_service_->GetCachedVerdict(
211 content_setting_map_.get(),
212 GURL("http://www.test.com/bar/test.html")));
213
214 // Return its corresponding verdict type if verdict is available and not
215 // expired.
216 EXPECT_EQ(LoginReputationClientResponse::SAFE,
217 password_protection_service_->GetCachedVerdict(
218 content_setting_map_.get(),
219 GURL("http://www.test.com/foo/index1.html")));
220 EXPECT_EQ(LoginReputationClientResponse::PHISHING,
221 password_protection_service_->GetCachedVerdict(
222 content_setting_map_.get(),
223 GURL("http://phishing.evil.com/phishing/")));
224
225 // Cache www.test.com/bar again, but this time it is not expired.
226 password_protection_service_->CacheVerdict(
227 content_setting_map_.get(), GURL("http://www.test.com/bar/index.html"),
228 &verdict_proto_2, now);
229 EXPECT_EQ(LoginReputationClientResponse::LOW_REPUTATION,
230 password_protection_service_->GetCachedVerdict(
231 content_setting_map_.get(),
232 GURL("http://www.test.com/bar/test2.html")));
233
234 // Now, there should be cached verdicts for 2 origins: http://www.test.com,
235 // and http://phishing.evil.com
236 ContentSettingsForOneType password_protection_settings;
237 content_setting_map_->GetSettingsForOneType(
238 CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(),
239 &password_protection_settings);
240 EXPECT_EQ(2U, password_protection_settings.size());
241
242 history::URLRows deleted_urls;
243 deleted_urls.push_back(
244 history::URLRow(GURL("http://phishing.evil.com/phishing/")));
245 // We delete the history of http://phishing.evil.com/phishing.
246 password_protection_service_->RemoveContentSettingsOnURLsDeleted(
247 content_setting_map_.get(), false, deleted_urls);
248 content_setting_map_->GetSettingsForOneType(
249 CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(),
250 &password_protection_settings);
251 EXPECT_EQ(1U, password_protection_settings.size());
252 EXPECT_EQ(LoginReputationClientResponse::LOW_REPUTATION,
253 password_protection_service_->GetCachedVerdict(
254 content_setting_map_.get(),
255 GURL("http://www.test.com/bar/test2.html")));
256
257 // Now we delete all history. All password protection content settings will be
258 // gone too.
259 password_protection_service_->RemoveContentSettingsOnURLsDeleted(
260 content_setting_map_.get(), true, deleted_urls);
261 content_setting_map_->GetSettingsForOneType(
262 CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(),
263 &password_protection_settings);
264 EXPECT_EQ(0U, password_protection_settings.size());
265 }
Nathan Parker 2017/03/16 21:27:11 This is a long test testing multiple different thi
Jialiu Lin 2017/03/18 23:46:32 Done. Separated this one into 3 tests.
266
88 } // namespace safe_browsing 267 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698