OLD | NEW |
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> |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 | 252 |
253 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client)); | 253 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client)); |
254 EXPECT_TRUE(db_manager_->CancelApiCheck(&client)); | 254 EXPECT_TRUE(db_manager_->CancelApiCheck(&client)); |
255 base::RunLoop().RunUntilIdle(); | 255 base::RunLoop().RunUntilIdle(); |
256 | 256 |
257 const std::set<std::string>& permissions = client.GetBlockedPermissions(); | 257 const std::set<std::string>& permissions = client.GetBlockedPermissions(); |
258 EXPECT_EQ(0ul, permissions.size()); | 258 EXPECT_EQ(0ul, permissions.size()); |
259 EXPECT_FALSE(client.callback_invoked()); | 259 EXPECT_FALSE(client.callback_invoked()); |
260 } | 260 } |
261 | 261 |
262 TEST_F(SafeBrowsingDatabaseManagerTest, ResultsAreCached) { | |
263 TestClient client; | |
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; | |
472 const GURL url("https://www.example.com/more"); | |
473 | |
474 EXPECT_EQ(1ul, cache.size()); | |
475 EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client)); | |
476 base::RunLoop().RunUntilIdle(); | |
477 | |
478 // Cache should be empty. | |
479 EXPECT_TRUE(client.callback_invoked()); | |
480 EXPECT_TRUE(cache.empty()); | |
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 } | |
539 | |
540 } // namespace safe_browsing | 262 } // namespace safe_browsing |
OLD | NEW |