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