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

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

Issue 2009183002: SafeBrowsing: Implement cache lookup for full hash checks (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Typo Created 4 years, 6 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
« no previous file with comments | « components/safe_browsing_db/database_manager.cc ('k') | components/safe_browsing_db/util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <string> 9 #include <string>
10 #include <vector> 10 #include <vector>
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 negative_cache_expire_), 54 negative_cache_expire_),
55 base::TimeDelta::FromSeconds(delay_seconds_)); 55 base::TimeDelta::FromSeconds(delay_seconds_));
56 } 56 }
57 57
58 void SetDelaySeconds(int delay) { 58 void SetDelaySeconds(int delay) {
59 delay_seconds_ = delay; 59 delay_seconds_ = delay;
60 } 60 }
61 61
62 void SetNegativeCacheDurationMins(base::Time now, 62 void SetNegativeCacheDurationMins(base::Time now,
63 int negative_cache_duration_mins) { 63 int negative_cache_duration_mins) {
64 negative_cache_expire_ = now + 64 // Don't add a TimeDelta to the maximum time to avoid undefined behavior.
65 base::TimeDelta::FromMinutes(negative_cache_duration_mins); 65 negative_cache_expire_ = now.is_max() ? now :
66 now + base::TimeDelta::FromMinutes(negative_cache_duration_mins);
66 } 67 }
67 68
68 // Prepare the GetFullHash results for the next request. 69 // Prepare the GetFullHash results for the next request.
69 void AddGetFullHashResponse(const SBFullHashResult& full_hash_result) { 70 void AddGetFullHashResponse(const SBFullHashResult& full_hash_result) {
70 full_hashes_.push_back(full_hash_result); 71 full_hashes_.push_back(full_hash_result);
71 } 72 }
72 73
74 // Clear the GetFullHash results for the next request.
75 void ClearFullHashResponse() {
76 full_hashes_.clear();
77 }
78
73 // Returns the prefixes that were sent in the last request. 79 // Returns the prefixes that were sent in the last request.
74 const std::vector<SBPrefix>& GetRequestPrefixes() { return prefixes_; } 80 const std::vector<SBPrefix>& GetRequestPrefixes() { return prefixes_; }
75 81
76 private: 82 private:
77 std::vector<SBPrefix> prefixes_; 83 std::vector<SBPrefix> prefixes_;
78 std::vector<SBFullHashResult> full_hashes_; 84 std::vector<SBFullHashResult> full_hashes_;
79 base::Time negative_cache_expire_; 85 base::Time negative_cache_expire_;
80 int delay_seconds_; 86 int delay_seconds_;
81 }; 87 };
82 88
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 TestV4GetHashProtocolManager* pm = static_cast<TestV4GetHashProtocolManager*>( 262 TestV4GetHashProtocolManager* pm = static_cast<TestV4GetHashProtocolManager*>(
257 db_manager_->v4_get_hash_protocol_manager_); 263 db_manager_->v4_get_hash_protocol_manager_);
258 base::Time now = base::Time::UnixEpoch(); 264 base::Time now = base::Time::UnixEpoch();
259 SBFullHashResult full_hash_result; 265 SBFullHashResult full_hash_result;
260 full_hash_result.hash = SBFullHashForString("example.com/"); 266 full_hash_result.hash = SBFullHashForString("example.com/");
261 full_hash_result.metadata.api_permissions.push_back("GEOLOCATION"); 267 full_hash_result.metadata.api_permissions.push_back("GEOLOCATION");
262 full_hash_result.cache_expire_after = now + base::TimeDelta::FromMinutes(3); 268 full_hash_result.cache_expire_after = now + base::TimeDelta::FromMinutes(3);
263 pm->AddGetFullHashResponse(full_hash_result); 269 pm->AddGetFullHashResponse(full_hash_result);
264 pm->SetNegativeCacheDurationMins(now, 5); 270 pm->SetNegativeCacheDurationMins(now, 5);
265 271
266 EXPECT_TRUE(db_manager_->api_cache_.empty()); 272 EXPECT_TRUE(db_manager_->v4_full_hash_cache_.empty());
267 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client)); 273 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
268 base::RunLoop().RunUntilIdle(); 274 base::RunLoop().RunUntilIdle();
269 275
270 EXPECT_TRUE(client.callback_invoked()); 276 EXPECT_TRUE(client.callback_invoked());
271 const std::vector<std::string>& permissions = client.GetBlockedPermissions(); 277 const std::vector<std::string>& permissions = client.GetBlockedPermissions();
272 EXPECT_EQ(1ul, permissions.size()); 278 EXPECT_EQ(1ul, permissions.size());
273 EXPECT_EQ("GEOLOCATION", permissions[0]); 279 EXPECT_EQ("GEOLOCATION", permissions[0]);
274 280
275 // Check the cache. 281 // Check the cache.
282 const SafeBrowsingDatabaseManager::PrefixToFullHashResultsMap& cache =
283 db_manager_->v4_full_hash_cache_[SB_THREAT_TYPE_API_ABUSE];
276 // Generated from the sorted output of UrlToFullHashes in util.h. 284 // Generated from the sorted output of UrlToFullHashes in util.h.
277 std::vector<SBPrefix> expected_prefixes = 285 std::vector<SBPrefix> expected_prefixes =
278 {1237562338, 2871045197, 3553205461, 3766933875}; 286 {1237562338, 2871045197, 3553205461, 3766933875};
279 EXPECT_EQ(expected_prefixes.size(), db_manager_->api_cache_.size()); 287 EXPECT_EQ(expected_prefixes.size(),
288 db_manager_->v4_full_hash_cache_[SB_THREAT_TYPE_API_ABUSE].size());
280 289
281 auto entry = db_manager_->api_cache_.find(expected_prefixes[0]); 290 auto entry = cache.find(expected_prefixes[0]);
282 EXPECT_NE(db_manager_->api_cache_.end(), entry); 291 EXPECT_NE(cache.end(), entry);
283 EXPECT_EQ(now + base::TimeDelta::FromMinutes(5), entry->second.expire_after); 292 EXPECT_EQ(now + base::TimeDelta::FromMinutes(5), entry->second.expire_after);
284 EXPECT_EQ(0ul, entry->second.full_hashes.size()); 293 EXPECT_EQ(0ul, entry->second.full_hashes.size());
285 294
286 entry = db_manager_->api_cache_.find(expected_prefixes[1]); 295 entry = cache.find(expected_prefixes[1]);
287 EXPECT_NE(db_manager_->api_cache_.end(), entry); 296 EXPECT_NE(cache.end(), entry);
288 EXPECT_EQ(now + base::TimeDelta::FromMinutes(5), entry->second.expire_after); 297 EXPECT_EQ(now + base::TimeDelta::FromMinutes(5), entry->second.expire_after);
289 EXPECT_EQ(0ul, entry->second.full_hashes.size()); 298 EXPECT_EQ(0ul, entry->second.full_hashes.size());
290 299
291 entry = db_manager_->api_cache_.find(expected_prefixes[2]); 300 entry = cache.find(expected_prefixes[2]);
292 EXPECT_NE(db_manager_->api_cache_.end(), entry); 301 EXPECT_NE(cache.end(), entry);
293 EXPECT_EQ(now + base::TimeDelta::FromMinutes(5), entry->second.expire_after); 302 EXPECT_EQ(now + base::TimeDelta::FromMinutes(5), entry->second.expire_after);
294 EXPECT_EQ(0ul, entry->second.full_hashes.size()); 303 EXPECT_EQ(0ul, entry->second.full_hashes.size());
295 304
296 entry = db_manager_->api_cache_.find(expected_prefixes[3]); 305 entry = cache.find(expected_prefixes[3]);
297 EXPECT_NE(db_manager_->api_cache_.end(), entry); 306 EXPECT_NE(cache.end(), entry);
298 EXPECT_EQ(now + base::TimeDelta::FromMinutes(5), entry->second.expire_after); 307 EXPECT_EQ(now + base::TimeDelta::FromMinutes(5), entry->second.expire_after);
299 EXPECT_EQ(1ul, entry->second.full_hashes.size()); 308 EXPECT_EQ(1ul, entry->second.full_hashes.size());
300 EXPECT_TRUE(SBFullHashEqual(full_hash_result.hash, 309 EXPECT_TRUE(SBFullHashEqual(full_hash_result.hash,
301 entry->second.full_hashes[0].hash)); 310 entry->second.full_hashes[0].hash));
302 EXPECT_EQ(1ul, entry->second.full_hashes[0].metadata.api_permissions.size()); 311 EXPECT_EQ(1ul, entry->second.full_hashes[0].metadata.api_permissions.size());
303 EXPECT_EQ("GEOLOCATION", 312 EXPECT_EQ("GEOLOCATION",
304 entry->second.full_hashes[0].metadata.api_permissions[0]); 313 entry->second.full_hashes[0].metadata.api_permissions[0]);
305 EXPECT_EQ(full_hash_result.cache_expire_after, 314 EXPECT_EQ(full_hash_result.cache_expire_after,
306 entry->second.full_hashes[0].cache_expire_after); 315 entry->second.full_hashes[0].cache_expire_after);
307 } 316 }
308 317
309 // An uninitialized value for negative cache expire does not cache results. 318 // An uninitialized value for negative cache expire does not cache results.
310 TEST_F(SafeBrowsingDatabaseManagerTest, ResultsAreNotCachedOnNull) { 319 TEST_F(SafeBrowsingDatabaseManagerTest, ResultsAreNotCachedOnNull) {
311 TestClient client; 320 TestClient client;
312 const GURL url("https://www.example.com/more"); 321 const GURL url("https://www.example.com/more");
313 TestV4GetHashProtocolManager* pm = static_cast<TestV4GetHashProtocolManager*>( 322 TestV4GetHashProtocolManager* pm = static_cast<TestV4GetHashProtocolManager*>(
314 db_manager_->v4_get_hash_protocol_manager_); 323 db_manager_->v4_get_hash_protocol_manager_);
315 base::Time now = base::Time::UnixEpoch(); 324 base::Time now = base::Time::UnixEpoch();
316 SBFullHashResult full_hash_result; 325 SBFullHashResult full_hash_result;
317 full_hash_result.hash = SBFullHashForString("example.com/"); 326 full_hash_result.hash = SBFullHashForString("example.com/");
318 full_hash_result.metadata.api_permissions.push_back("GEOLOCATION"); 327 full_hash_result.metadata.api_permissions.push_back("GEOLOCATION");
319 full_hash_result.cache_expire_after = now + base::TimeDelta::FromMinutes(3); 328 full_hash_result.cache_expire_after = now + base::TimeDelta::FromMinutes(3);
320 pm->AddGetFullHashResponse(full_hash_result); 329 pm->AddGetFullHashResponse(full_hash_result);
321 330
322 EXPECT_TRUE(db_manager_->api_cache_.empty()); 331 EXPECT_TRUE(db_manager_->v4_full_hash_cache_.empty());
323 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client)); 332 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
324 base::RunLoop().RunUntilIdle(); 333 base::RunLoop().RunUntilIdle();
325 334
326 EXPECT_TRUE(client.callback_invoked()); 335 EXPECT_TRUE(client.callback_invoked());
327 EXPECT_TRUE(db_manager_->api_cache_.empty()); 336 EXPECT_TRUE(
337 db_manager_->v4_full_hash_cache_[SB_THREAT_TYPE_API_ABUSE].empty());
338 }
339
340 // Checks that results are looked up correctly in the cache.
341 TEST_F(SafeBrowsingDatabaseManagerTest, GetCachedResults) {
342 base::Time now = base::Time::UnixEpoch();
343 std::vector<SBFullHash> full_hashes;
344 SBFullHash full_hash = SBFullHashForString("example.com/");
345 full_hashes.push_back(full_hash);
346 std::vector<SBFullHashResult> cached_results;
347 std::vector<SBPrefix> prefixes;
348 db_manager_->GetFullHashCachedResults(SB_THREAT_TYPE_API_ABUSE,
349 full_hashes, now, &prefixes, &cached_results);
350
351 // The cache is empty.
352 EXPECT_TRUE(cached_results.empty());
353 EXPECT_EQ(1ul, prefixes.size());
354 EXPECT_EQ(full_hash.prefix, prefixes[0]);
355
356 // Prefix has a cache entry but full hash is not there.
357 SBCachedFullHashResult& entry = db_manager_->
358 v4_full_hash_cache_[SB_THREAT_TYPE_API_ABUSE][full_hash.prefix] =
359 SBCachedFullHashResult(now + base::TimeDelta::FromMinutes(5));
360 db_manager_->GetFullHashCachedResults(SB_THREAT_TYPE_API_ABUSE,
361 full_hashes, now, &prefixes, &cached_results);
362
363 EXPECT_TRUE(prefixes.empty());
364 EXPECT_TRUE(cached_results.empty());
365
366 // Expired negative cache entry.
367 entry.expire_after = now - base::TimeDelta::FromMinutes(5);
368 db_manager_->GetFullHashCachedResults(SB_THREAT_TYPE_API_ABUSE,
369 full_hashes, now, &prefixes, &cached_results);
370
371 EXPECT_TRUE(cached_results.empty());
372 EXPECT_EQ(1ul, prefixes.size());
373 EXPECT_EQ(full_hash.prefix, prefixes[0]);
374
375 // Now put the full hash in the cache.
376 SBFullHashResult full_hash_result;
377 full_hash_result.hash = full_hash;
378 full_hash_result.cache_expire_after = now + base::TimeDelta::FromMinutes(3);
379 entry.full_hashes.push_back(full_hash_result);
380 db_manager_->GetFullHashCachedResults(SB_THREAT_TYPE_API_ABUSE,
381 full_hashes, now, &prefixes, &cached_results);
382
383 EXPECT_TRUE(prefixes.empty());
384 EXPECT_EQ(1ul, cached_results.size());
385 EXPECT_TRUE(SBFullHashEqual(full_hash, cached_results[0].hash));
386
387 // Expired full hash in cache.
388 entry.full_hashes.clear();
389 full_hash_result.cache_expire_after = now - base::TimeDelta::FromMinutes(3);
390 entry.full_hashes.push_back(full_hash_result);
391 db_manager_->GetFullHashCachedResults(SB_THREAT_TYPE_API_ABUSE,
392 full_hashes, now, &prefixes, &cached_results);
393
394 EXPECT_TRUE(cached_results.empty());
395 EXPECT_EQ(1ul, prefixes.size());
396 EXPECT_EQ(full_hash.prefix, prefixes[0]);
397 }
398
399 // Checks that the cached results and request results are merged.
400 TEST_F(SafeBrowsingDatabaseManagerTest, CachedResultsMerged) {
401 TestClient client;
402 const GURL url("https://www.example.com/more");
403 TestV4GetHashProtocolManager* pm = static_cast<TestV4GetHashProtocolManager*>(
404 db_manager_->v4_get_hash_protocol_manager_);
405 // Set now to max time so the cache expire times are in the future.
406 SBFullHashResult full_hash_result;
407 full_hash_result.hash = SBFullHashForString("example.com/");
408 full_hash_result.metadata.api_permissions.push_back("GEOLOCATION");
409 full_hash_result.cache_expire_after = base::Time::Max();
410 pm->AddGetFullHashResponse(full_hash_result);
411 pm->SetNegativeCacheDurationMins(base::Time::Max(), 0);
412
413 EXPECT_TRUE(db_manager_->v4_full_hash_cache_.empty());
414 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
415 base::RunLoop().RunUntilIdle();
416
417 EXPECT_TRUE(client.callback_invoked());
418 const std::vector<std::string>& permissions = client.GetBlockedPermissions();
419 EXPECT_EQ(1ul, permissions.size());
420 EXPECT_EQ("GEOLOCATION", permissions[0]);
421
422 // The results should be cached, so remove them from the protocol manager
423 // response.
424 TestClient client2;
425 pm->ClearFullHashResponse();
426 pm->SetNegativeCacheDurationMins(base::Time(), 0);
427 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client2));
428 base::RunLoop().RunUntilIdle();
429
430 EXPECT_TRUE(client2.callback_invoked());
431 const std::vector<std::string>& permissions2 =
432 client2.GetBlockedPermissions();
433 EXPECT_EQ(1ul, permissions2.size());
434 EXPECT_EQ("GEOLOCATION", permissions2[0]);
435
436 // Add a different result to the protocol manager response and ensure it is
437 // merged with the cached result in the metadata.
438 TestClient client3;
439 const GURL url2("https://m.example.com/more");
440 full_hash_result.hash = SBFullHashForString("m.example.com/");
441 full_hash_result.metadata.api_permissions.push_back("NOTIFICATIONS");
442 pm->AddGetFullHashResponse(full_hash_result);
443 pm->SetNegativeCacheDurationMins(base::Time::Max(), 0);
444 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url2, &client3));
445 base::RunLoop().RunUntilIdle();
446
447 EXPECT_TRUE(client3.callback_invoked());
448 const std::vector<std::string>& permissions3 =
449 client3.GetBlockedPermissions();
450 EXPECT_EQ(3ul, permissions3.size());
451 // TODO(kcarattini): Fix the metadata storage of permissions to avoid
452 // duplicates.
453 EXPECT_EQ("GEOLOCATION", permissions3[0]);
454 EXPECT_EQ("NOTIFICATIONS", permissions3[1]);
455 EXPECT_EQ("GEOLOCATION", permissions3[2]);
328 } 456 }
329 457
330 } // namespace safe_browsing 458 } // namespace safe_browsing
OLDNEW
« no previous file with comments | « components/safe_browsing_db/database_manager.cc ('k') | components/safe_browsing_db/util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698