Chromium Code Reviews| 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 *threat_type = found->second; | |
| 62 return true; | |
| 63 } | |
| 56 | 64 |
| 57 void RemovePending(const GURL& url) { pending_.erase(url); } | 65 void RemovePending(const GURL& url) { pending_.erase(url); } |
| 58 | 66 |
| 59 void Insert(const GURL url) { | 67 void Insert(const GURL url, SBThreatType threat_type) { |
| 60 set_.insert(url); | 68 SBThreatType existing_threat_type; |
| 69 if (Contains(url, &existing_threat_type)) | |
|
Nathan Parker
2016/11/10 00:13:03
I'm not sure this should ever happen. Can you thi
estark
2016/11/11 20:28:13
Hmm. I can't think of a case where this does happe
| |
| 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 *threat_type = found->second; | |
| 80 return true; | |
| 66 } | 81 } |
| 67 | 82 |
| 68 void InsertPending(const GURL url) { pending_.insert(url); } | 83 void InsertPending(const GURL url, SBThreatType threat_type) { |
| 84 SBThreatType existing_threat_type; | |
| 85 if (ContainsPending(url, &existing_threat_type)) | |
| 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 SBThreatType threat_type; |
| 500 if (site_list->ContainsPending(whitelist_url, &threat_type)) | |
|
Nathan Parker
2016/11/10 00:13:03
nit: How about passing a nullptr, and having the f
estark
2016/11/11 20:28:13
Done.
| |
| 477 site_list->RemovePending(whitelist_url); | 501 site_list->RemovePending(whitelist_url); |
| 478 | 502 |
| 479 // Notify security UI that security state has changed. | 503 // Notify security UI that security state has changed. |
| 480 web_contents->DidChangeVisibleSecurityState(); | 504 web_contents->DidChangeVisibleSecurityState(); |
| 481 } | 505 } |
| 482 | 506 |
| 483 bool SafeBrowsingUIManager::IsWhitelisted(const UnsafeResource& resource) { | 507 bool SafeBrowsingUIManager::IsWhitelisted(const UnsafeResource& resource) { |
| 484 NavigationEntry* entry = nullptr; | 508 NavigationEntry* entry = nullptr; |
| 485 if (resource.is_subresource) { | 509 if (resource.is_subresource) { |
| 486 entry = resource.GetNavigationEntryForResource(); | 510 entry = resource.GetNavigationEntryForResource(); |
| 487 } | 511 } |
| 512 SBThreatType unused_threat_type; | |
| 488 return IsUrlWhitelistedOrPendingForWebContents( | 513 return IsUrlWhitelistedOrPendingForWebContents( |
| 489 resource.url, resource.is_subresource, entry, | 514 resource.url, resource.is_subresource, entry, |
| 490 resource.web_contents_getter.Run(), true); | 515 resource.web_contents_getter.Run(), true, &unused_threat_type); |
| 491 } | 516 } |
| 492 | 517 |
| 493 // Check if the user has already seen and/or ignored a SB warning for this | 518 // Check if the user has already seen and/or ignored a SB warning for this |
| 494 // WebContents and top-level domain. | 519 // WebContents and top-level domain. |
| 495 bool SafeBrowsingUIManager::IsUrlWhitelistedOrPendingForWebContents( | 520 bool SafeBrowsingUIManager::IsUrlWhitelistedOrPendingForWebContents( |
| 496 const GURL& url, | 521 const GURL& url, |
| 497 bool is_subresource, | 522 bool is_subresource, |
| 498 NavigationEntry* entry, | 523 NavigationEntry* entry, |
| 499 content::WebContents* web_contents, | 524 content::WebContents* web_contents, |
| 500 bool whitelist_only) { | 525 bool whitelist_only, |
| 526 SBThreatType* threat_type) { | |
| 501 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 527 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 502 | 528 |
| 503 GURL lookup_url = GetWhitelistUrl(url, is_subresource, entry); | 529 GURL lookup_url = GetWhitelistUrl(url, is_subresource, entry); |
| 504 if (lookup_url.is_empty()) | 530 if (lookup_url.is_empty()) |
| 505 return false; | 531 return false; |
| 506 | 532 |
| 507 WhitelistUrlSet* site_list = | 533 WhitelistUrlSet* site_list = |
| 508 static_cast<WhitelistUrlSet*>(web_contents->GetUserData(kWhitelistKey)); | 534 static_cast<WhitelistUrlSet*>(web_contents->GetUserData(kWhitelistKey)); |
| 509 if (!site_list) | 535 if (!site_list) |
| 510 return false; | 536 return false; |
| 511 | 537 |
| 512 bool whitelisted = site_list->Contains(lookup_url); | 538 bool whitelisted = site_list->Contains(lookup_url, threat_type); |
| 513 if (whitelist_only) { | 539 if (whitelist_only) { |
| 514 return whitelisted; | 540 return whitelisted; |
| 515 } else { | 541 } else { |
| 516 return whitelisted || site_list->ContainsPending(lookup_url); | 542 return whitelisted || site_list->ContainsPending(lookup_url, threat_type); |
| 517 } | 543 } |
| 518 } | 544 } |
| 519 | 545 |
| 520 // Static. | 546 // Static. |
| 521 GURL SafeBrowsingUIManager::GetMainFrameWhitelistUrlForResourceForTesting( | 547 GURL SafeBrowsingUIManager::GetMainFrameWhitelistUrlForResourceForTesting( |
| 522 const safe_browsing::SafeBrowsingUIManager::UnsafeResource& resource) { | 548 const safe_browsing::SafeBrowsingUIManager::UnsafeResource& resource) { |
| 523 return GetMainFrameWhitelistUrlForResource(resource); | 549 return GetMainFrameWhitelistUrlForResource(resource); |
| 524 } | 550 } |
| 525 | 551 |
| 526 } // namespace safe_browsing | 552 } // namespace safe_browsing |
| OLD | NEW |