| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/safe_browsing/ui_manager.h" | 5 #include "chrome/browser/safe_browsing/ui_manager.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/callback.h" | 9 #include "base/callback.h" |
| 10 #include "base/debug/leak_tracker.h" | 10 #include "base/debug/leak_tracker.h" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 #include "ipc/ipc_message.h" | 32 #include "ipc/ipc_message.h" |
| 33 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | 33 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
| 34 #include "net/ssl/ssl_info.h" | 34 #include "net/ssl/ssl_info.h" |
| 35 #include "net/url_request/url_request_context.h" | 35 #include "net/url_request/url_request_context.h" |
| 36 #include "net/url_request/url_request_context_getter.h" | 36 #include "net/url_request/url_request_context_getter.h" |
| 37 | 37 |
| 38 using content::BrowserThread; | 38 using content::BrowserThread; |
| 39 using content::NavigationEntry; | 39 using content::NavigationEntry; |
| 40 using content::WebContents; | 40 using content::WebContents; |
| 41 using safe_browsing::HitReport; | 41 using safe_browsing::HitReport; |
| 42 using safe_browsing::SBThreatType; |
| 42 | 43 |
| 43 namespace { | 44 namespace { |
| 44 | 45 |
| 45 const void* const kWhitelistKey = &kWhitelistKey; | 46 const void* const kWhitelistKey = &kWhitelistKey; |
| 46 | 47 |
| 47 // A WhitelistUrlSet holds the set of URLs that have been whitelisted for a | 48 // A WhitelistUrlSet holds the set of URLs that have been whitelisted |
| 48 // specific WebContents, along with pending entries that are still undecided. | 49 // for a specific WebContents, along with pending entries that are still |
| 49 // The URLs in this set should come from GetWhitelistUrl() or | 50 // undecided. Each URL is associated with the first SBThreatType that |
| 50 // GetMainFrameWhitelistUrlForResource(). | 51 // was seen for that URL. The URLs in this set should come from |
| 52 // GetWhitelistUrl() or GetMainFrameWhitelistUrlForResource(). |
| 51 class WhitelistUrlSet : public base::SupportsUserData::Data { | 53 class WhitelistUrlSet : public base::SupportsUserData::Data { |
| 52 public: | 54 public: |
| 53 WhitelistUrlSet() {} | 55 WhitelistUrlSet() {} |
| 54 | 56 |
| 55 bool Contains(const GURL url) { return set_.find(url) != set_.end(); } | 57 bool Contains(const GURL url, SBThreatType* threat_type) { |
| 58 auto found = map_.find(url); |
| 59 if (found == map_.end()) |
| 60 return false; |
| 61 if (threat_type) |
| 62 *threat_type = found->second; |
| 63 return true; |
| 64 } |
| 56 | 65 |
| 57 void RemovePending(const GURL& url) { pending_.erase(url); } | 66 void RemovePending(const GURL& url) { pending_.erase(url); } |
| 58 | 67 |
| 59 void Insert(const GURL url) { | 68 void Insert(const GURL url, SBThreatType threat_type) { |
| 60 set_.insert(url); | 69 if (Contains(url, nullptr)) |
| 70 return; |
| 71 map_[url] = threat_type; |
| 61 RemovePending(url); | 72 RemovePending(url); |
| 62 } | 73 } |
| 63 | 74 |
| 64 bool ContainsPending(const GURL url) { | 75 bool ContainsPending(const GURL& url, SBThreatType* threat_type) { |
| 65 return pending_.find(url) != pending_.end(); | 76 auto found = pending_.find(url); |
| 77 if (found == pending_.end()) |
| 78 return false; |
| 79 if (threat_type) |
| 80 *threat_type = found->second; |
| 81 return true; |
| 66 } | 82 } |
| 67 | 83 |
| 68 void InsertPending(const GURL url) { pending_.insert(url); } | 84 void InsertPending(const GURL url, SBThreatType threat_type) { |
| 85 if (ContainsPending(url, nullptr)) |
| 86 return; |
| 87 pending_[url] = threat_type; |
| 88 } |
| 69 | 89 |
| 70 private: | 90 private: |
| 71 std::set<GURL> set_; | 91 std::map<GURL, SBThreatType> map_; |
| 72 std::set<GURL> pending_; | 92 std::map<GURL, SBThreatType> pending_; |
| 73 | 93 |
| 74 DISALLOW_COPY_AND_ASSIGN(WhitelistUrlSet); | 94 DISALLOW_COPY_AND_ASSIGN(WhitelistUrlSet); |
| 75 }; | 95 }; |
| 76 | 96 |
| 77 // Returns the URL that should be used in a WhitelistUrlSet for the given | 97 // Returns the URL that should be used in a WhitelistUrlSet for the given |
| 78 // |resource|. | 98 // |resource|. |
| 79 GURL GetMainFrameWhitelistUrlForResource( | 99 GURL GetMainFrameWhitelistUrlForResource( |
| 80 const safe_browsing::SafeBrowsingUIManager::UnsafeResource& resource) { | 100 const safe_browsing::SafeBrowsingUIManager::UnsafeResource& resource) { |
| 81 if (resource.is_subresource) { | 101 if (resource.is_subresource) { |
| 82 NavigationEntry* entry = resource.GetNavigationEntryForResource(); | 102 NavigationEntry* entry = resource.GetNavigationEntryForResource(); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 DCHECK(resource.callback_thread); | 218 DCHECK(resource.callback_thread); |
| 199 resource.callback_thread->PostTask( | 219 resource.callback_thread->PostTask( |
| 200 FROM_HERE, base::Bind(resource.callback, proceed)); | 220 FROM_HERE, base::Bind(resource.callback, proceed)); |
| 201 } | 221 } |
| 202 | 222 |
| 203 GURL whitelist_url = GetWhitelistUrl( | 223 GURL whitelist_url = GetWhitelistUrl( |
| 204 main_frame_url, false /* is subresource */, | 224 main_frame_url, false /* is subresource */, |
| 205 nullptr /* no navigation entry needed for main resource */); | 225 nullptr /* no navigation entry needed for main resource */); |
| 206 if (proceed) { | 226 if (proceed) { |
| 207 AddToWhitelistUrlSet(whitelist_url, web_contents, | 227 AddToWhitelistUrlSet(whitelist_url, web_contents, |
| 208 false /* Pending -> permanent */); | 228 false /* Pending -> permanent */, |
| 229 resource.threat_type); |
| 209 } else if (web_contents) { | 230 } else if (web_contents) { |
| 210 // |web_contents| doesn't exist if the tab has been closed. | 231 // |web_contents| doesn't exist if the tab has been closed. |
| 211 RemoveFromPendingWhitelistUrlSet(whitelist_url, web_contents); | 232 RemoveFromPendingWhitelistUrlSet(whitelist_url, web_contents); |
| 212 } | 233 } |
| 213 } | 234 } |
| 214 } | 235 } |
| 215 | 236 |
| 216 void SafeBrowsingUIManager::DisplayBlockingPage( | 237 void SafeBrowsingUIManager::DisplayBlockingPage( |
| 217 const UnsafeResource& resource) { | 238 const UnsafeResource& resource) { |
| 218 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 239 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 | 316 |
| 296 MaybeReportSafeBrowsingHit(hit_report); | 317 MaybeReportSafeBrowsingHit(hit_report); |
| 297 } | 318 } |
| 298 | 319 |
| 299 if (resource.threat_type != SB_THREAT_TYPE_SAFE) { | 320 if (resource.threat_type != SB_THREAT_TYPE_SAFE) { |
| 300 for (Observer& observer : observer_list_) | 321 for (Observer& observer : observer_list_) |
| 301 observer.OnSafeBrowsingHit(resource); | 322 observer.OnSafeBrowsingHit(resource); |
| 302 } | 323 } |
| 303 AddToWhitelistUrlSet(GetMainFrameWhitelistUrlForResource(resource), | 324 AddToWhitelistUrlSet(GetMainFrameWhitelistUrlForResource(resource), |
| 304 resource.web_contents_getter.Run(), | 325 resource.web_contents_getter.Run(), |
| 305 true /* A decision is now pending */); | 326 true /* A decision is now pending */, |
| 327 resource.threat_type); |
| 306 SafeBrowsingBlockingPage::ShowBlockingPage(this, resource); | 328 SafeBrowsingBlockingPage::ShowBlockingPage(this, resource); |
| 307 } | 329 } |
| 308 | 330 |
| 309 // A safebrowsing hit is sent after a blocking page for malware/phishing | 331 // A safebrowsing hit is sent after a blocking page for malware/phishing |
| 310 // or after the warning dialog for download urls, only for | 332 // or after the warning dialog for download urls, only for |
| 311 // UMA || extended_reporting users. | 333 // UMA || extended_reporting users. |
| 312 void SafeBrowsingUIManager::MaybeReportSafeBrowsingHit( | 334 void SafeBrowsingUIManager::MaybeReportSafeBrowsingHit( |
| 313 const HitReport& hit_report) { | 335 const HitReport& hit_report) { |
| 314 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 336 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 315 | 337 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 sb_service_->ping_manager()->ReportThreatDetails(serialized); | 436 sb_service_->ping_manager()->ReportThreatDetails(serialized); |
| 415 } | 437 } |
| 416 } | 438 } |
| 417 | 439 |
| 418 // Record this domain in the given WebContents as either whitelisted or | 440 // Record this domain in the given WebContents as either whitelisted or |
| 419 // pending whitelisting (if an interstitial is currently displayed). If an | 441 // pending whitelisting (if an interstitial is currently displayed). If an |
| 420 // existing WhitelistUrlSet does not yet exist, create a new WhitelistUrlSet. | 442 // existing WhitelistUrlSet does not yet exist, create a new WhitelistUrlSet. |
| 421 void SafeBrowsingUIManager::AddToWhitelistUrlSet( | 443 void SafeBrowsingUIManager::AddToWhitelistUrlSet( |
| 422 const GURL& whitelist_url, | 444 const GURL& whitelist_url, |
| 423 content::WebContents* web_contents, | 445 content::WebContents* web_contents, |
| 424 bool pending) { | 446 bool pending, |
| 447 SBThreatType threat_type) { |
| 425 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 448 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 426 | 449 |
| 427 // A WebContents might not exist if the tab has been closed. | 450 // A WebContents might not exist if the tab has been closed. |
| 428 if (!web_contents) | 451 if (!web_contents) |
| 429 return; | 452 return; |
| 430 | 453 |
| 431 WhitelistUrlSet* site_list = GetOrCreateWhitelist(web_contents); | 454 WhitelistUrlSet* site_list = GetOrCreateWhitelist(web_contents); |
| 432 | 455 |
| 433 if (whitelist_url.is_empty()) | 456 if (whitelist_url.is_empty()) |
| 434 return; | 457 return; |
| 435 | 458 |
| 436 if (pending) { | 459 if (pending) { |
| 437 site_list->InsertPending(whitelist_url); | 460 site_list->InsertPending(whitelist_url, threat_type); |
| 438 } else { | 461 } else { |
| 439 site_list->Insert(whitelist_url); | 462 site_list->Insert(whitelist_url, threat_type); |
| 440 } | 463 } |
| 441 | 464 |
| 442 // Notify security UI that security state has changed. | 465 // Notify security UI that security state has changed. |
| 443 web_contents->DidChangeVisibleSecurityState(); | 466 web_contents->DidChangeVisibleSecurityState(); |
| 444 } | 467 } |
| 445 | 468 |
| 446 void SafeBrowsingUIManager::RemoveFromPendingWhitelistUrlSet( | 469 void SafeBrowsingUIManager::RemoveFromPendingWhitelistUrlSet( |
| 447 const GURL& whitelist_url, | 470 const GURL& whitelist_url, |
| 448 content::WebContents* web_contents) { | 471 content::WebContents* web_contents) { |
| 449 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 472 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 466 // appears in the pending whitelist. In the common case, it's expected | 489 // appears in the pending whitelist. In the common case, it's expected |
| 467 // that a URL is in the pending whitelist when it is removed, but it's | 490 // that a URL is in the pending whitelist when it is removed, but it's |
| 468 // not always the case. For example, if there are several blocking | 491 // not always the case. For example, if there are several blocking |
| 469 // pages queued up for different resources on the same page, and the | 492 // pages queued up for different resources on the same page, and the |
| 470 // user goes back to dimiss the first one, the subsequent blocking | 493 // user goes back to dimiss the first one, the subsequent blocking |
| 471 // pages get dismissed as well (as if the user had clicked "Back to | 494 // pages get dismissed as well (as if the user had clicked "Back to |
| 472 // safety" on each of them). In this case, the first dismissal will | 495 // safety" on each of them). In this case, the first dismissal will |
| 473 // remove the main-frame URL from the pending whitelist, so the | 496 // remove the main-frame URL from the pending whitelist, so the |
| 474 // main-frame URL will have already been removed when the subsequent | 497 // main-frame URL will have already been removed when the subsequent |
| 475 // blocking pages are dismissed. | 498 // blocking pages are dismissed. |
| 476 if (site_list->ContainsPending(whitelist_url)) | 499 if (site_list->ContainsPending(whitelist_url, nullptr)) |
| 477 site_list->RemovePending(whitelist_url); | 500 site_list->RemovePending(whitelist_url); |
| 478 | 501 |
| 479 // Notify security UI that security state has changed. | 502 // Notify security UI that security state has changed. |
| 480 web_contents->DidChangeVisibleSecurityState(); | 503 web_contents->DidChangeVisibleSecurityState(); |
| 481 } | 504 } |
| 482 | 505 |
| 483 bool SafeBrowsingUIManager::IsWhitelisted(const UnsafeResource& resource) { | 506 bool SafeBrowsingUIManager::IsWhitelisted(const UnsafeResource& resource) { |
| 484 NavigationEntry* entry = nullptr; | 507 NavigationEntry* entry = nullptr; |
| 485 if (resource.is_subresource) { | 508 if (resource.is_subresource) { |
| 486 entry = resource.GetNavigationEntryForResource(); | 509 entry = resource.GetNavigationEntryForResource(); |
| 487 } | 510 } |
| 511 SBThreatType unused_threat_type; |
| 488 return IsUrlWhitelistedOrPendingForWebContents( | 512 return IsUrlWhitelistedOrPendingForWebContents( |
| 489 resource.url, resource.is_subresource, entry, | 513 resource.url, resource.is_subresource, entry, |
| 490 resource.web_contents_getter.Run(), true); | 514 resource.web_contents_getter.Run(), true, &unused_threat_type); |
| 491 } | 515 } |
| 492 | 516 |
| 493 // Check if the user has already seen and/or ignored a SB warning for this | 517 // Check if the user has already seen and/or ignored a SB warning for this |
| 494 // WebContents and top-level domain. | 518 // WebContents and top-level domain. |
| 495 bool SafeBrowsingUIManager::IsUrlWhitelistedOrPendingForWebContents( | 519 bool SafeBrowsingUIManager::IsUrlWhitelistedOrPendingForWebContents( |
| 496 const GURL& url, | 520 const GURL& url, |
| 497 bool is_subresource, | 521 bool is_subresource, |
| 498 NavigationEntry* entry, | 522 NavigationEntry* entry, |
| 499 content::WebContents* web_contents, | 523 content::WebContents* web_contents, |
| 500 bool whitelist_only) { | 524 bool whitelist_only, |
| 525 SBThreatType* threat_type) { |
| 501 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 526 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 502 | 527 |
| 503 GURL lookup_url = GetWhitelistUrl(url, is_subresource, entry); | 528 GURL lookup_url = GetWhitelistUrl(url, is_subresource, entry); |
| 504 if (lookup_url.is_empty()) | 529 if (lookup_url.is_empty()) |
| 505 return false; | 530 return false; |
| 506 | 531 |
| 507 WhitelistUrlSet* site_list = | 532 WhitelistUrlSet* site_list = |
| 508 static_cast<WhitelistUrlSet*>(web_contents->GetUserData(kWhitelistKey)); | 533 static_cast<WhitelistUrlSet*>(web_contents->GetUserData(kWhitelistKey)); |
| 509 if (!site_list) | 534 if (!site_list) |
| 510 return false; | 535 return false; |
| 511 | 536 |
| 512 bool whitelisted = site_list->Contains(lookup_url); | 537 bool whitelisted = site_list->Contains(lookup_url, threat_type); |
| 513 if (whitelist_only) { | 538 if (whitelist_only) { |
| 514 return whitelisted; | 539 return whitelisted; |
| 515 } else { | 540 } else { |
| 516 return whitelisted || site_list->ContainsPending(lookup_url); | 541 return whitelisted || site_list->ContainsPending(lookup_url, threat_type); |
| 517 } | 542 } |
| 518 } | 543 } |
| 519 | 544 |
| 520 // Static. | 545 // Static. |
| 521 GURL SafeBrowsingUIManager::GetMainFrameWhitelistUrlForResourceForTesting( | 546 GURL SafeBrowsingUIManager::GetMainFrameWhitelistUrlForResourceForTesting( |
| 522 const safe_browsing::SafeBrowsingUIManager::UnsafeResource& resource) { | 547 const safe_browsing::SafeBrowsingUIManager::UnsafeResource& resource) { |
| 523 return GetMainFrameWhitelistUrlForResource(resource); | 548 return GetMainFrameWhitelistUrlForResource(resource); |
| 524 } | 549 } |
| 525 | 550 |
| 526 } // namespace safe_browsing | 551 } // namespace safe_browsing |
| OLD | NEW |