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

Side by Side Diff: components/safe_browsing_db/database_manager_unittest.cc

Issue 2233103002: Move full hash caching logic to v4_get_hash_protocol_manager (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: shess@ feedback - part 2. Created 4 years, 3 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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 4
5 #include "components/safe_browsing_db/database_manager.h" 5 #include "components/safe_browsing_db/database_manager.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <set> 9 #include <set>
10 #include <string> 10 #include <string>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/base64.h"
13 #include "base/location.h" 14 #include "base/location.h"
14 #include "base/macros.h" 15 #include "base/macros.h"
15 #include "base/memory/ptr_util.h" 16 #include "base/memory/ptr_util.h"
16 #include "base/memory/ref_counted.h" 17 #include "base/memory/ref_counted.h"
17 #include "base/run_loop.h" 18 #include "base/run_loop.h"
18 #include "base/single_thread_task_runner.h" 19 #include "base/single_thread_task_runner.h"
19 #include "base/threading/thread_task_runner_handle.h" 20 #include "base/threading/thread_task_runner_handle.h"
20 #include "components/safe_browsing_db/test_database_manager.h" 21 #include "components/safe_browsing_db/test_database_manager.h"
21 #include "components/safe_browsing_db/v4_get_hash_protocol_manager.h" 22 #include "components/safe_browsing_db/v4_protocol_manager_util.h"
22 #include "content/public/browser/browser_thread.h" 23 #include "content/public/browser/browser_thread.h"
23 #include "content/public/test/test_browser_thread_bundle.h" 24 #include "content/public/test/test_browser_thread_bundle.h"
25 #include "crypto/sha2.h"
26 #include "net/url_request/test_url_fetcher_factory.h"
27 #include "net/url_request/url_fetcher_delegate.h"
24 #include "testing/gtest/include/gtest/gtest.h" 28 #include "testing/gtest/include/gtest/gtest.h"
25 #include "url/gurl.h" 29 #include "url/gurl.h"
26 30
27 using content::BrowserThread; 31 using content::BrowserThread;
28 32
29 namespace safe_browsing { 33 namespace safe_browsing {
30 34
31 namespace { 35 namespace {
32 36
33 void InvokeFullHashCallback(
34 V4GetHashProtocolManager::FullHashCallback callback,
35 const std::vector<SBFullHashResult>& full_hashes,
36 base::Time negative_cache_expire) {
37 callback.Run(full_hashes, negative_cache_expire);
38 }
39
40 // A TestV4GetHashProtocolManager that returns fixed responses from the
41 // Safe Browsing server for testing purpose.
42 class TestV4GetHashProtocolManager : public V4GetHashProtocolManager {
43 public:
44 TestV4GetHashProtocolManager(
45 net::URLRequestContextGetter* request_context_getter,
46 const V4ProtocolConfig& config)
47 : V4GetHashProtocolManager(request_context_getter, config),
48 negative_cache_expire_(base::Time()), delay_seconds_(0) {}
49
50 ~TestV4GetHashProtocolManager() override {}
51
52 void GetFullHashesWithApis(const std::vector<SBPrefix>& prefixes,
53 FullHashCallback callback) override {
54 prefixes_ = prefixes;
55 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
56 FROM_HERE, base::Bind(InvokeFullHashCallback, callback, full_hashes_,
57 negative_cache_expire_),
58 base::TimeDelta::FromSeconds(delay_seconds_));
59 }
60
61 void SetDelaySeconds(int delay) {
62 delay_seconds_ = delay;
63 }
64
65 void SetNegativeCacheDurationMins(base::Time now,
66 int negative_cache_duration_mins) {
67 // Don't add a TimeDelta to the maximum time to avoid undefined behavior.
68 negative_cache_expire_ = now.is_max() ? now :
69 now + base::TimeDelta::FromMinutes(negative_cache_duration_mins);
70 }
71
72 // Prepare the GetFullHash results for the next request.
73 void AddGetFullHashResponse(const SBFullHashResult& full_hash_result) {
74 full_hashes_.push_back(full_hash_result);
75 }
76
77 // Clear the GetFullHash results for the next request.
78 void ClearFullHashResponse() {
79 full_hashes_.clear();
80 }
81
82 // Returns the prefixes that were sent in the last request.
83 const std::vector<SBPrefix>& GetRequestPrefixes() { return prefixes_; }
84
85 private:
86 std::vector<SBPrefix> prefixes_;
87 std::vector<SBFullHashResult> full_hashes_;
88 base::Time negative_cache_expire_;
89 int delay_seconds_;
90 };
91
92 // Factory that creates test protocol manager instances.
93 class TestV4GetHashProtocolManagerFactory :
94 public V4GetHashProtocolManagerFactory {
95 public:
96 TestV4GetHashProtocolManagerFactory() {}
97 ~TestV4GetHashProtocolManagerFactory() override {}
98
99 V4GetHashProtocolManager* CreateProtocolManager(
100 net::URLRequestContextGetter* request_context_getter,
101 const V4ProtocolConfig& config) override {
102 return new TestV4GetHashProtocolManager(request_context_getter, config);
103 }
104 };
105
106 class TestClient : public SafeBrowsingDatabaseManager::Client { 37 class TestClient : public SafeBrowsingDatabaseManager::Client {
107 public: 38 public:
108 TestClient() : callback_invoked_(false) {} 39 TestClient() : callback_invoked_(false) {}
109 ~TestClient() override {} 40 ~TestClient() override {}
110 41
111 void OnCheckApiBlacklistUrlResult(const GURL& url, 42 void OnCheckApiBlacklistUrlResult(const GURL& url,
112 const ThreatMetadata& metadata) override { 43 const ThreatMetadata& metadata) override {
113 blocked_permissions_ = metadata.api_permissions; 44 blocked_permissions_ = metadata.api_permissions;
114 callback_invoked_ = true; 45 callback_invoked_ = true;
115 } 46 }
116 47
117 const std::set<std::string>& GetBlockedPermissions() { 48 const std::set<std::string>& GetBlockedPermissions() {
118 return blocked_permissions_; 49 return blocked_permissions_;
119 } 50 }
120 51
121 bool callback_invoked() {return callback_invoked_;} 52 bool callback_invoked() {return callback_invoked_;}
122 53
123 private: 54 private:
124 std::set<std::string> blocked_permissions_; 55 std::set<std::string> blocked_permissions_;
125 bool callback_invoked_; 56 bool callback_invoked_;
126 DISALLOW_COPY_AND_ASSIGN(TestClient); 57 DISALLOW_COPY_AND_ASSIGN(TestClient);
127 }; 58 };
128 59
129 } // namespace 60 } // namespace
130 61
131 class SafeBrowsingDatabaseManagerTest : public testing::Test { 62 class SafeBrowsingDatabaseManagerTest : public testing::Test {
132 protected: 63 protected:
133 void SetUp() override { 64 void SetUp() override {
134 V4GetHashProtocolManager::RegisterFactory(
135 base::MakeUnique<TestV4GetHashProtocolManagerFactory>());
136
137 db_manager_ = new TestSafeBrowsingDatabaseManager(); 65 db_manager_ = new TestSafeBrowsingDatabaseManager();
138 db_manager_->StartOnIOThread(NULL, V4ProtocolConfig()); 66 db_manager_->StartOnIOThread(NULL, V4ProtocolConfig());
139 } 67 }
140 68
141 void TearDown() override { 69 void TearDown() override {
142 base::RunLoop().RunUntilIdle(); 70 base::RunLoop().RunUntilIdle();
143 db_manager_->StopOnIOThread(false); 71 db_manager_->StopOnIOThread(false);
144 V4GetHashProtocolManager::RegisterFactory(nullptr); 72 }
73
74 std::string GetStockV4GetHashResponse() {
75 UpdateListIdentifier list_id = GetChromeUrlApiId();
76 FullHash full_hash = crypto::SHA256HashString("example.com/more");
77
78 FindFullHashesResponse response;
79 response.mutable_negative_cache_duration()->set_seconds(600);
80 ThreatMatch* m = response.add_matches();
81 m->set_platform_type(list_id.platform_type);
82 m->set_threat_entry_type(list_id.threat_entry_type);
83 m->set_threat_type(list_id.threat_type);
84 m->mutable_threat()->set_hash(full_hash);
85 m->mutable_cache_duration()->set_seconds(300);
86
87 ThreatEntryMetadata::MetadataEntry* e =
88 m->mutable_threat_entry_metadata()->add_entries();
89 e->set_key("permission");
90 e->set_value("GEOLOCATION");
91
92 std::string res_data;
93 response.SerializeToString(&res_data);
94 return res_data;
145 } 95 }
146 96
147 scoped_refptr<SafeBrowsingDatabaseManager> db_manager_; 97 scoped_refptr<SafeBrowsingDatabaseManager> db_manager_;
148 98
149 private: 99 private:
150 content::TestBrowserThreadBundle test_browser_thread_bundle_; 100 content::TestBrowserThreadBundle test_browser_thread_bundle_;
151 }; 101 };
152 102
153 TEST_F(SafeBrowsingDatabaseManagerTest, CheckApiBlacklistUrlWrongScheme) { 103 TEST_F(SafeBrowsingDatabaseManagerTest, CheckApiBlacklistUrlWrongScheme) {
154 TestClient client; 104 EXPECT_TRUE(
155 const GURL url("file://example.txt"); 105 db_manager_->CheckApiBlacklistUrl(GURL("file://example.txt"), nullptr));
156 EXPECT_TRUE(db_manager_->CheckApiBlacklistUrl(url, &client));
157 }
158
159 TEST_F(SafeBrowsingDatabaseManagerTest, CheckApiBlacklistUrlPrefixes) {
160 TestClient client;
161 const GURL url("https://www.example.com/more");
162 // Generated from the sorted output of UrlToFullHashes in util.h.
163 std::vector<SBPrefix> expected_prefixes =
164 {1237562338, 2871045197, 3553205461, 3766933875};
165
166 TestV4GetHashProtocolManager* pm = static_cast<TestV4GetHashProtocolManager*>(
167 db_manager_->v4_get_hash_protocol_manager_);
168 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
169 base::RunLoop().RunUntilIdle();
170 std::vector<SBPrefix> prefixes = pm->GetRequestPrefixes();
171 EXPECT_EQ(expected_prefixes.size(), prefixes.size());
172 for (unsigned int i = 0; i < prefixes.size(); ++i) {
173 EXPECT_EQ(expected_prefixes[i], prefixes[i]);
174 }
175 }
176
177 TEST_F(SafeBrowsingDatabaseManagerTest, HandleGetHashesWithApisResults) {
178 TestClient client;
179 const GURL url("https://www.example.com/more");
180 TestV4GetHashProtocolManager* pm = static_cast<TestV4GetHashProtocolManager*>(
181 db_manager_->v4_get_hash_protocol_manager_);
182 SBFullHashResult full_hash_result;
183 full_hash_result.hash = SBFullHashForString("example.com/");
184 full_hash_result.metadata.api_permissions.insert("GEOLOCATION");
185 pm->AddGetFullHashResponse(full_hash_result);
186
187 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
188 base::RunLoop().RunUntilIdle();
189
190 EXPECT_TRUE(client.callback_invoked());
191 const std::set<std::string>& permissions = client.GetBlockedPermissions();
192 EXPECT_EQ(1ul, permissions.size());
193 EXPECT_EQ(1ul, permissions.count("GEOLOCATION"));
194 }
195
196 TEST_F(SafeBrowsingDatabaseManagerTest, HandleGetHashesWithApisResultsNoMatch) {
197 TestClient client;
198 const GURL url("https://www.example.com/more");
199 TestV4GetHashProtocolManager* pm = static_cast<TestV4GetHashProtocolManager*>(
200 db_manager_->v4_get_hash_protocol_manager_);
201 SBFullHashResult full_hash_result;
202 full_hash_result.hash = SBFullHashForString("wrongexample.com/");
203 full_hash_result.metadata.api_permissions.insert("GEOLOCATION");
204 pm->AddGetFullHashResponse(full_hash_result);
205
206 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
207 base::RunLoop().RunUntilIdle();
208
209 EXPECT_TRUE(client.callback_invoked());
210 const std::set<std::string>& permissions = client.GetBlockedPermissions();
211 EXPECT_EQ(0ul, permissions.size());
212 }
213
214 TEST_F(SafeBrowsingDatabaseManagerTest, HandleGetHashesWithApisResultsMatches) {
215 TestClient client;
216 const GURL url("https://www.example.com/more");
217 TestV4GetHashProtocolManager* pm = static_cast<TestV4GetHashProtocolManager*>(
218 db_manager_->v4_get_hash_protocol_manager_);
219 SBFullHashResult full_hash_result;
220 full_hash_result.hash = SBFullHashForString("example.com/");
221 full_hash_result.metadata.api_permissions.insert("GEOLOCATION");
222 pm->AddGetFullHashResponse(full_hash_result);
223 SBFullHashResult full_hash_result2;
224 full_hash_result2.hash = SBFullHashForString("example.com/more");
225 full_hash_result2.metadata.api_permissions.insert("NOTIFICATIONS");
226 pm->AddGetFullHashResponse(full_hash_result2);
227 SBFullHashResult full_hash_result3;
228 full_hash_result3.hash = SBFullHashForString("wrongexample.com/");
229 full_hash_result3.metadata.api_permissions.insert("AUDIO_CAPTURE");
230 pm->AddGetFullHashResponse(full_hash_result3);
231
232 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
233 base::RunLoop().RunUntilIdle();
234
235 EXPECT_TRUE(client.callback_invoked());
236 const std::set<std::string>& permissions = client.GetBlockedPermissions();
237 EXPECT_EQ(2ul, permissions.size());
238 EXPECT_EQ(1ul, permissions.count("GEOLOCATION"));
239 EXPECT_EQ(1ul, permissions.count("NOTIFICATIONS"));
240 } 106 }
241 107
242 TEST_F(SafeBrowsingDatabaseManagerTest, CancelApiCheck) { 108 TEST_F(SafeBrowsingDatabaseManagerTest, CancelApiCheck) {
109 net::TestURLFetcherFactory factory;
243 TestClient client; 110 TestClient client;
244 const GURL url("https://www.example.com/more"); 111 const GURL url("https://www.example.com/more");
245 TestV4GetHashProtocolManager* pm = static_cast<TestV4GetHashProtocolManager*>(
246 db_manager_->v4_get_hash_protocol_manager_);
247 SBFullHashResult full_hash_result;
248 full_hash_result.hash = SBFullHashForString("example.com/");
249 full_hash_result.metadata.api_permissions.insert("GEOLOCATION");
250 pm->AddGetFullHashResponse(full_hash_result);
251 pm->SetDelaySeconds(100);
252 112
253 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client)); 113 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
254 EXPECT_TRUE(db_manager_->CancelApiCheck(&client)); 114 EXPECT_TRUE(db_manager_->CancelApiCheck(&client));
115
116 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
117 DCHECK(fetcher);
118 fetcher->set_status(net::URLRequestStatus());
119 fetcher->set_response_code(200);
120 fetcher->SetResponseString(GetStockV4GetHashResponse());
121 fetcher->delegate()->OnURLFetchComplete(fetcher);
122
255 base::RunLoop().RunUntilIdle(); 123 base::RunLoop().RunUntilIdle();
256 124
257 const std::set<std::string>& permissions = client.GetBlockedPermissions();
258 EXPECT_EQ(0ul, permissions.size());
259 EXPECT_FALSE(client.callback_invoked()); 125 EXPECT_FALSE(client.callback_invoked());
126 EXPECT_EQ(0ul, client.GetBlockedPermissions().size());
260 } 127 }
261 128
262 TEST_F(SafeBrowsingDatabaseManagerTest, ResultsAreCached) { 129 TEST_F(SafeBrowsingDatabaseManagerTest, GetApiCheckResponse) {
263 TestClient client; 130 net::TestURLFetcherFactory factory;
264 const GURL url("https://www.example.com/more");
265 TestV4GetHashProtocolManager* pm = static_cast<TestV4GetHashProtocolManager*>(
266 db_manager_->v4_get_hash_protocol_manager_);
267 base::Time now = base::Time::UnixEpoch();
268 SBFullHashResult full_hash_result;
269 full_hash_result.hash = SBFullHashForString("example.com/");
270 full_hash_result.metadata.api_permissions.insert("GEOLOCATION");
271 full_hash_result.cache_expire_after = now + base::TimeDelta::FromMinutes(3);
272 pm->AddGetFullHashResponse(full_hash_result);
273 pm->SetNegativeCacheDurationMins(now, 5);
274
275 EXPECT_TRUE(db_manager_->v4_full_hash_cache_.empty());
276 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
277 base::RunLoop().RunUntilIdle();
278
279 EXPECT_TRUE(client.callback_invoked());
280 const std::set<std::string>& permissions = client.GetBlockedPermissions();
281 EXPECT_EQ(1ul, permissions.size());
282 EXPECT_EQ(1ul, permissions.count("GEOLOCATION"));
283
284 // Check the cache.
285 const SafeBrowsingDatabaseManager::PrefixToFullHashResultsMap& cache =
286 db_manager_->v4_full_hash_cache_[SB_THREAT_TYPE_API_ABUSE];
287 // Generated from the sorted output of UrlToFullHashes in util.h.
288 std::vector<SBPrefix> expected_prefixes =
289 {1237562338, 2871045197, 3553205461, 3766933875};
290 EXPECT_EQ(expected_prefixes.size(),
291 db_manager_->v4_full_hash_cache_[SB_THREAT_TYPE_API_ABUSE].size());
292
293 auto entry = cache.find(expected_prefixes[0]);
294 EXPECT_NE(cache.end(), entry);
295 EXPECT_EQ(now + base::TimeDelta::FromMinutes(5), entry->second.expire_after);
296 EXPECT_EQ(0ul, entry->second.full_hashes.size());
297
298 entry = cache.find(expected_prefixes[1]);
299 EXPECT_NE(cache.end(), entry);
300 EXPECT_EQ(now + base::TimeDelta::FromMinutes(5), entry->second.expire_after);
301 EXPECT_EQ(0ul, entry->second.full_hashes.size());
302
303 entry = cache.find(expected_prefixes[2]);
304 EXPECT_NE(cache.end(), entry);
305 EXPECT_EQ(now + base::TimeDelta::FromMinutes(5), entry->second.expire_after);
306 EXPECT_EQ(0ul, entry->second.full_hashes.size());
307
308 entry = cache.find(expected_prefixes[3]);
309 EXPECT_NE(cache.end(), entry);
310 EXPECT_EQ(now + base::TimeDelta::FromMinutes(5), entry->second.expire_after);
311 EXPECT_EQ(1ul, entry->second.full_hashes.size());
312 EXPECT_TRUE(SBFullHashEqual(full_hash_result.hash,
313 entry->second.full_hashes[0].hash));
314 EXPECT_EQ(1ul, entry->second.full_hashes[0].metadata.api_permissions.size());
315 EXPECT_EQ(1ul, entry->second.full_hashes[0].metadata.api_permissions.
316 count("GEOLOCATION"));
317 EXPECT_EQ(full_hash_result.cache_expire_after,
318 entry->second.full_hashes[0].cache_expire_after);
319 }
320
321 // An uninitialized value for negative cache expire does not cache results.
322 TEST_F(SafeBrowsingDatabaseManagerTest, ResultsAreNotCachedOnNull) {
323 TestClient client;
324 const GURL url("https://www.example.com/more");
325 TestV4GetHashProtocolManager* pm = static_cast<TestV4GetHashProtocolManager*>(
326 db_manager_->v4_get_hash_protocol_manager_);
327 base::Time now = base::Time::UnixEpoch();
328 SBFullHashResult full_hash_result;
329 full_hash_result.hash = SBFullHashForString("example.com/");
330 full_hash_result.cache_expire_after = now + base::TimeDelta::FromMinutes(3);
331 pm->AddGetFullHashResponse(full_hash_result);
332
333 EXPECT_TRUE(db_manager_->v4_full_hash_cache_.empty());
334 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
335 base::RunLoop().RunUntilIdle();
336
337 EXPECT_TRUE(client.callback_invoked());
338 EXPECT_TRUE(
339 db_manager_->v4_full_hash_cache_[SB_THREAT_TYPE_API_ABUSE].empty());
340 }
341
342 // Checks that results are looked up correctly in the cache.
343 TEST_F(SafeBrowsingDatabaseManagerTest, GetCachedResults) {
344 base::Time now = base::Time::UnixEpoch();
345 std::vector<SBFullHash> full_hashes;
346 SBFullHash full_hash = SBFullHashForString("example.com/");
347 full_hashes.push_back(full_hash);
348 std::vector<SBFullHashResult> cached_results;
349 std::vector<SBPrefix> prefixes;
350 db_manager_->GetFullHashCachedResults(SB_THREAT_TYPE_API_ABUSE,
351 full_hashes, now, &prefixes, &cached_results);
352
353 // The cache is empty.
354 EXPECT_TRUE(cached_results.empty());
355 EXPECT_EQ(1ul, prefixes.size());
356 EXPECT_EQ(full_hash.prefix, prefixes[0]);
357
358 // Prefix has a cache entry but full hash is not there.
359 SBCachedFullHashResult& entry = db_manager_->
360 v4_full_hash_cache_[SB_THREAT_TYPE_API_ABUSE][full_hash.prefix] =
361 SBCachedFullHashResult(now + base::TimeDelta::FromMinutes(5));
362 db_manager_->GetFullHashCachedResults(SB_THREAT_TYPE_API_ABUSE,
363 full_hashes, now, &prefixes, &cached_results);
364
365 EXPECT_TRUE(prefixes.empty());
366 EXPECT_TRUE(cached_results.empty());
367
368 // Expired negative cache entry.
369 entry.expire_after = now - base::TimeDelta::FromMinutes(5);
370 db_manager_->GetFullHashCachedResults(SB_THREAT_TYPE_API_ABUSE,
371 full_hashes, now, &prefixes, &cached_results);
372
373 EXPECT_TRUE(cached_results.empty());
374 EXPECT_EQ(1ul, prefixes.size());
375 EXPECT_EQ(full_hash.prefix, prefixes[0]);
376
377 // Now put the full hash in the cache.
378 SBFullHashResult full_hash_result;
379 full_hash_result.hash = full_hash;
380 full_hash_result.cache_expire_after = now + base::TimeDelta::FromMinutes(3);
381 entry.full_hashes.push_back(full_hash_result);
382 db_manager_->GetFullHashCachedResults(SB_THREAT_TYPE_API_ABUSE,
383 full_hashes, now, &prefixes, &cached_results);
384
385 EXPECT_TRUE(prefixes.empty());
386 EXPECT_EQ(1ul, cached_results.size());
387 EXPECT_TRUE(SBFullHashEqual(full_hash, cached_results[0].hash));
388
389 // Expired full hash in cache.
390 entry.full_hashes.clear();
391 full_hash_result.cache_expire_after = now - base::TimeDelta::FromMinutes(3);
392 entry.full_hashes.push_back(full_hash_result);
393 db_manager_->GetFullHashCachedResults(SB_THREAT_TYPE_API_ABUSE,
394 full_hashes, now, &prefixes, &cached_results);
395
396 EXPECT_TRUE(cached_results.empty());
397 EXPECT_EQ(1ul, prefixes.size());
398 EXPECT_EQ(full_hash.prefix, prefixes[0]);
399 }
400
401 // Checks that the cached results and request results are merged.
402 TEST_F(SafeBrowsingDatabaseManagerTest, CachedResultsMerged) {
403 TestClient client;
404 const GURL url("https://www.example.com/more");
405 TestV4GetHashProtocolManager* pm = static_cast<TestV4GetHashProtocolManager*>(
406 db_manager_->v4_get_hash_protocol_manager_);
407 // Set now to max time so the cache expire times are in the future.
408 SBFullHashResult full_hash_result;
409 full_hash_result.hash = SBFullHashForString("example.com/");
410 full_hash_result.metadata.api_permissions.insert("GEOLOCATION");
411 full_hash_result.cache_expire_after = base::Time::Max();
412 pm->AddGetFullHashResponse(full_hash_result);
413 pm->SetNegativeCacheDurationMins(base::Time::Max(), 0);
414
415 EXPECT_TRUE(db_manager_->v4_full_hash_cache_.empty());
416 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
417 base::RunLoop().RunUntilIdle();
418
419 EXPECT_TRUE(client.callback_invoked());
420 const std::set<std::string>& permissions = client.GetBlockedPermissions();
421 EXPECT_EQ(1ul, permissions.size());
422 EXPECT_EQ(1ul, permissions.count("GEOLOCATION"));
423
424 // The results should be cached, so remove them from the protocol manager
425 // response.
426 TestClient client2;
427 pm->ClearFullHashResponse();
428 pm->SetNegativeCacheDurationMins(base::Time(), 0);
429 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client2));
430 base::RunLoop().RunUntilIdle();
431
432 EXPECT_TRUE(client2.callback_invoked());
433 const std::set<std::string>& permissions2 =
434 client2.GetBlockedPermissions();
435 EXPECT_EQ(1ul, permissions2.size());
436 EXPECT_EQ(1ul, permissions2.count("GEOLOCATION"));
437
438 // Add a different result to the protocol manager response and ensure it is
439 // merged with the cached result in the metadata.
440 TestClient client3;
441 const GURL url2("https://m.example.com/more");
442 full_hash_result.hash = SBFullHashForString("m.example.com/");
443 full_hash_result.metadata.api_permissions.insert("NOTIFICATIONS");
444 pm->AddGetFullHashResponse(full_hash_result);
445 pm->SetNegativeCacheDurationMins(base::Time::Max(), 0);
446 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url2, &client3));
447 base::RunLoop().RunUntilIdle();
448
449 EXPECT_TRUE(client3.callback_invoked());
450 const std::set<std::string>& permissions3 =
451 client3.GetBlockedPermissions();
452 EXPECT_EQ(2ul, permissions3.size());
453 EXPECT_EQ(1ul, permissions3.count("GEOLOCATION"));
454 EXPECT_EQ(1ul, permissions3.count("NOTIFICATIONS"));
455 }
456
457 TEST_F(SafeBrowsingDatabaseManagerTest, CachedResultsAreEvicted) {
458 base::Time epoch = base::Time::UnixEpoch();
459 SBFullHashResult full_hash_result;
460 full_hash_result.hash = SBFullHashForString("example.com/");
461 full_hash_result.cache_expire_after = epoch;
462
463 SafeBrowsingDatabaseManager::PrefixToFullHashResultsMap& cache =
464 db_manager_->v4_full_hash_cache_[SB_THREAT_TYPE_API_ABUSE];
465
466 // Fill the cache with some expired entries.
467 // Both negative cache and full hash expired.
468 cache[full_hash_result.hash.prefix] = SBCachedFullHashResult(epoch);
469 cache[full_hash_result.hash.prefix].full_hashes.push_back(full_hash_result);
470
471 TestClient client; 131 TestClient client;
472 const GURL url("https://www.example.com/more"); 132 const GURL url("https://www.example.com/more");
473 133
474 EXPECT_EQ(1ul, cache.size());
475 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client)); 134 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
135
136 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
137 DCHECK(fetcher);
138 fetcher->set_status(net::URLRequestStatus());
139 fetcher->set_response_code(200);
140 fetcher->SetResponseString(GetStockV4GetHashResponse());
141 fetcher->delegate()->OnURLFetchComplete(fetcher);
142
476 base::RunLoop().RunUntilIdle(); 143 base::RunLoop().RunUntilIdle();
477 144
478 // Cache should be empty. 145 ASSERT_TRUE(client.callback_invoked());
479 EXPECT_TRUE(client.callback_invoked()); 146 ASSERT_EQ(1ul, client.GetBlockedPermissions().size());
480 EXPECT_TRUE(cache.empty()); 147 EXPECT_EQ("GEOLOCATION", *(client.GetBlockedPermissions().begin()));
481
482 // Negative cache still valid and full hash expired.
483 cache[full_hash_result.hash.prefix] =
484 SBCachedFullHashResult(base::Time::Max());
485 cache[full_hash_result.hash.prefix].full_hashes.push_back(full_hash_result);
486
487 EXPECT_EQ(1ul, cache.size());
488 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
489 base::RunLoop().RunUntilIdle();
490
491 // Cache entry should still be there.
492 EXPECT_EQ(1ul, cache.size());
493 auto entry = cache.find(full_hash_result.hash.prefix);
494 EXPECT_NE(cache.end(), entry);
495 EXPECT_EQ(base::Time::Max(), entry->second.expire_after);
496 EXPECT_EQ(1ul, entry->second.full_hashes.size());
497 EXPECT_TRUE(SBFullHashEqual(full_hash_result.hash,
498 entry->second.full_hashes[0].hash));
499 EXPECT_EQ(full_hash_result.cache_expire_after,
500 entry->second.full_hashes[0].cache_expire_after);
501
502 // Negative cache still valid and full hash still valid.
503 cache[full_hash_result.hash.prefix].full_hashes[0].
504 cache_expire_after = base::Time::Max();
505
506 EXPECT_EQ(1ul, cache.size());
507 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
508 base::RunLoop().RunUntilIdle();
509
510 // Cache entry should still be there.
511 EXPECT_EQ(1ul, cache.size());
512 entry = cache.find(full_hash_result.hash.prefix);
513 EXPECT_NE(cache.end(), entry);
514 EXPECT_EQ(base::Time::Max(), entry->second.expire_after);
515 EXPECT_EQ(1ul, entry->second.full_hashes.size());
516 EXPECT_TRUE(SBFullHashEqual(full_hash_result.hash,
517 entry->second.full_hashes[0].hash));
518 EXPECT_EQ(base::Time::Max(),
519 entry->second.full_hashes[0].cache_expire_after);
520
521 // Negative cache expired and full hash still valid.
522 cache[full_hash_result.hash.prefix].expire_after = epoch;
523
524 EXPECT_EQ(1ul, cache.size());
525 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
526 base::RunLoop().RunUntilIdle();
527
528 // Cache entry should still be there.
529 EXPECT_EQ(1ul, cache.size());
530 entry = cache.find(full_hash_result.hash.prefix);
531 EXPECT_NE(cache.end(), entry);
532 EXPECT_EQ(epoch, entry->second.expire_after);
533 EXPECT_EQ(1ul, entry->second.full_hashes.size());
534 EXPECT_TRUE(SBFullHashEqual(full_hash_result.hash,
535 entry->second.full_hashes[0].hash));
536 EXPECT_EQ(base::Time::Max(),
537 entry->second.full_hashes[0].cache_expire_after);
538 } 148 }
539 149
540 } // namespace safe_browsing 150 } // namespace safe_browsing
OLDNEW
« no previous file with comments | « components/safe_browsing_db/database_manager.cc ('k') | components/safe_browsing_db/testing_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698