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. |
|
mattm
2013/12/14 00:09:49
Update CL description
Greg Billock
2013/12/14 18:35:34
Done.
| |
| 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/client_side_detection_host.h" | 5 #include "chrome/browser/safe_browsing/client_side_detection_host.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
| 11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "base/prefs/pref_service.h" | 13 #include "base/prefs/pref_service.h" |
| 14 #include "base/sequenced_task_runner_helpers.h" | 14 #include "base/sequenced_task_runner_helpers.h" |
| 15 #include "base/strings/utf_string_conversions.h" | |
| 15 #include "chrome/browser/browser_process.h" | 16 #include "chrome/browser/browser_process.h" |
| 16 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
| 17 #include "chrome/browser/safe_browsing/browser_feature_extractor.h" | 18 #include "chrome/browser/safe_browsing/browser_feature_extractor.h" |
| 18 #include "chrome/browser/safe_browsing/client_side_detection_service.h" | 19 #include "chrome/browser/safe_browsing/client_side_detection_service.h" |
| 19 #include "chrome/browser/safe_browsing/database_manager.h" | 20 #include "chrome/browser/safe_browsing/database_manager.h" |
| 20 #include "chrome/browser/safe_browsing/safe_browsing_service.h" | 21 #include "chrome/browser/safe_browsing/safe_browsing_service.h" |
| 21 #include "chrome/common/chrome_switches.h" | 22 #include "chrome/common/chrome_switches.h" |
| 22 #include "chrome/common/chrome_version_info.h" | 23 #include "chrome/common/chrome_version_info.h" |
| 23 #include "chrome/common/pref_names.h" | 24 #include "chrome/common/pref_names.h" |
| 24 #include "chrome/common/safe_browsing/csd.pb.h" | 25 #include "chrome/common/safe_browsing/csd.pb.h" |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 40 using content::BrowserThread; | 41 using content::BrowserThread; |
| 41 using content::NavigationEntry; | 42 using content::NavigationEntry; |
| 42 using content::ResourceRequestDetails; | 43 using content::ResourceRequestDetails; |
| 43 using content::WebContents; | 44 using content::WebContents; |
| 44 | 45 |
| 45 namespace safe_browsing { | 46 namespace safe_browsing { |
| 46 | 47 |
| 47 const int ClientSideDetectionHost::kMaxUrlsPerIP = 20; | 48 const int ClientSideDetectionHost::kMaxUrlsPerIP = 20; |
| 48 const int ClientSideDetectionHost::kMaxIPsPerBrowse = 200; | 49 const int ClientSideDetectionHost::kMaxIPsPerBrowse = 200; |
| 49 | 50 |
| 51 const char kSafeBrowsingHitKey[] = "safe_browsing_hit"; | |
|
mattm
2013/12/14 00:09:49
s/hit/match/
Greg Billock
2013/12/14 18:35:34
Done.
| |
| 52 | |
| 50 // This class is instantiated each time a new toplevel URL loads, and | 53 // This class is instantiated each time a new toplevel URL loads, and |
| 51 // asynchronously checks whether the phishing classifier should run for this | 54 // asynchronously checks whether the phishing classifier should run for this |
| 52 // URL. If so, it notifies the renderer with a StartPhishingDetection IPC. | 55 // URL. If so, it notifies the renderer with a StartPhishingDetection IPC. |
| 53 // Objects of this class are ref-counted and will be destroyed once nobody | 56 // Objects of this class are ref-counted and will be destroyed once nobody |
| 54 // uses it anymore. If |web_contents|, |csd_service| or |host| go away you need | 57 // uses it anymore. If |web_contents|, |csd_service| or |host| go away you need |
| 55 // to call Cancel(). We keep the |database_manager| alive in a ref pointer for | 58 // to call Cancel(). We keep the |database_manager| alive in a ref pointer for |
| 56 // as long as it takes. | 59 // as long as it takes. |
| 57 class ClientSideDetectionHost::ShouldClassifyUrlRequest | 60 class ClientSideDetectionHost::ShouldClassifyUrlRequest |
| 58 : public base::RefCountedThreadSafe< | 61 : public base::RefCountedThreadSafe< |
| 59 ClientSideDetectionHost::ShouldClassifyUrlRequest> { | 62 ClientSideDetectionHost::ShouldClassifyUrlRequest> { |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 241 WebContents* tab) { | 244 WebContents* tab) { |
| 242 return new ClientSideDetectionHost(tab); | 245 return new ClientSideDetectionHost(tab); |
| 243 } | 246 } |
| 244 | 247 |
| 245 ClientSideDetectionHost::ClientSideDetectionHost(WebContents* tab) | 248 ClientSideDetectionHost::ClientSideDetectionHost(WebContents* tab) |
| 246 : content::WebContentsObserver(tab), | 249 : content::WebContentsObserver(tab), |
| 247 csd_service_(NULL), | 250 csd_service_(NULL), |
| 248 weak_factory_(this), | 251 weak_factory_(this), |
| 249 unsafe_unique_page_id_(-1), | 252 unsafe_unique_page_id_(-1), |
| 250 malware_killswitch_on_(false), | 253 malware_killswitch_on_(false), |
| 251 malware_report_enabled_(false), | 254 malware_report_enabled_(false) { |
| 252 malware_or_phishing_match_(false) { | |
| 253 DCHECK(tab); | 255 DCHECK(tab); |
| 254 // Note: csd_service_ and sb_service will be NULL here in testing. | 256 // Note: csd_service_ and sb_service will be NULL here in testing. |
| 255 csd_service_ = g_browser_process->safe_browsing_detection_service(); | 257 csd_service_ = g_browser_process->safe_browsing_detection_service(); |
| 256 feature_extractor_.reset(new BrowserFeatureExtractor(tab, this)); | 258 feature_extractor_.reset(new BrowserFeatureExtractor(tab, this)); |
| 257 registrar_.Add(this, content::NOTIFICATION_RESOURCE_RESPONSE_STARTED, | 259 registrar_.Add(this, content::NOTIFICATION_RESOURCE_RESPONSE_STARTED, |
| 258 content::Source<WebContents>(tab)); | 260 content::Source<WebContents>(tab)); |
| 259 | 261 |
| 260 scoped_refptr<SafeBrowsingService> sb_service = | 262 scoped_refptr<SafeBrowsingService> sb_service = |
| 261 g_browser_process->safe_browsing_service(); | 263 g_browser_process->safe_browsing_service(); |
| 262 if (sb_service.get()) { | 264 if (sb_service.get()) { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 284 IPC_MESSAGE_HANDLER(SafeBrowsingHostMsg_PhishingDetectionDone, | 286 IPC_MESSAGE_HANDLER(SafeBrowsingHostMsg_PhishingDetectionDone, |
| 285 OnPhishingDetectionDone) | 287 OnPhishingDetectionDone) |
| 286 IPC_MESSAGE_UNHANDLED(handled = false) | 288 IPC_MESSAGE_UNHANDLED(handled = false) |
| 287 IPC_END_MESSAGE_MAP() | 289 IPC_END_MESSAGE_MAP() |
| 288 return handled; | 290 return handled; |
| 289 } | 291 } |
| 290 | 292 |
| 291 void ClientSideDetectionHost::DidNavigateMainFrame( | 293 void ClientSideDetectionHost::DidNavigateMainFrame( |
| 292 const content::LoadCommittedDetails& details, | 294 const content::LoadCommittedDetails& details, |
| 293 const content::FrameNavigateParams& params) { | 295 const content::FrameNavigateParams& params) { |
| 294 malware_or_phishing_match_ = false; | |
| 295 | |
| 296 // TODO(noelutz): move this DCHECK to WebContents and fix all the unit tests | 296 // TODO(noelutz): move this DCHECK to WebContents and fix all the unit tests |
| 297 // that don't call this method on the UI thread. | 297 // that don't call this method on the UI thread. |
| 298 // DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 298 // DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 299 if (details.is_in_page) { | 299 if (details.is_in_page) { |
| 300 // If the navigation is within the same page, the user isn't really | 300 // If the navigation is within the same page, the user isn't really |
| 301 // navigating away. We don't need to cancel a pending callback or | 301 // navigating away. We don't need to cancel a pending callback or |
| 302 // begin a new classification. | 302 // begin a new classification. |
| 303 return; | 303 return; |
| 304 } | 304 } |
| 305 // If we navigate away and there currently is a pending phishing | 305 // If we navigate away and there currently is a pending phishing |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 348 // Check that this notification is really for us. | 348 // Check that this notification is really for us. |
| 349 content::RenderViewHost* hit_rvh = content::RenderViewHost::FromID( | 349 content::RenderViewHost* hit_rvh = content::RenderViewHost::FromID( |
| 350 resource.render_process_host_id, resource.render_view_id); | 350 resource.render_process_host_id, resource.render_view_id); |
| 351 if (!hit_rvh || | 351 if (!hit_rvh || |
| 352 web_contents() != content::WebContents::FromRenderViewHost(hit_rvh)) | 352 web_contents() != content::WebContents::FromRenderViewHost(hit_rvh)) |
| 353 return; | 353 return; |
| 354 | 354 |
| 355 // Store the unique page ID for later. | 355 // Store the unique page ID for later. |
| 356 unsafe_unique_page_id_ = | 356 unsafe_unique_page_id_ = |
| 357 web_contents()->GetController().GetActiveEntry()->GetUniqueID(); | 357 web_contents()->GetController().GetActiveEntry()->GetUniqueID(); |
| 358 web_contents()->GetController().GetActiveEntry()->SetExtraData( | |
| 359 kSafeBrowsingHitKey, base::ASCIIToUTF16("1")); | |
|
mattm
2013/12/14 00:09:49
This shouldn't be necessary (OnSafeBrowsingMatch s
Greg Billock
2013/12/14 18:35:34
Done.
| |
| 360 | |
| 358 // We also keep the resource around in order to be able to send the | 361 // We also keep the resource around in order to be able to send the |
| 359 // malicious URL to the server. | 362 // malicious URL to the server. |
| 360 unsafe_resource_.reset(new SafeBrowsingUIManager::UnsafeResource(resource)); | 363 unsafe_resource_.reset(new SafeBrowsingUIManager::UnsafeResource(resource)); |
| 361 unsafe_resource_->callback.Reset(); // Don't do anything stupid. | 364 unsafe_resource_->callback.Reset(); // Don't do anything stupid. |
| 362 } | 365 } |
| 363 | 366 |
| 364 void ClientSideDetectionHost::OnSafeBrowsingMatch( | 367 void ClientSideDetectionHost::OnSafeBrowsingMatch( |
| 365 const SafeBrowsingUIManager::UnsafeResource& resource) { | 368 const SafeBrowsingUIManager::UnsafeResource& resource) { |
|
mattm
2013/12/14 00:09:49
derp. Doesn't this function also need to do the ch
Greg Billock
2013/12/14 18:35:34
Looks like we should do if (!web_contents || !wc..
mattm
2013/12/16 22:36:11
OnSafeBrowsingMatch and OnSafeBrowsingHit are both
Greg Billock
2013/12/16 23:00:21
Ah, I see what you mean. OK, done.
| |
| 366 malware_or_phishing_match_ = true; | 369 web_contents()->GetController().GetActiveEntry()->SetExtraData( |
|
mattm
2013/12/14 00:09:49
also do null checks like OnSafeBrowsingHit does
Greg Billock
2013/12/14 18:35:34
Done.
| |
| 370 kSafeBrowsingHitKey, base::ASCIIToUTF16("1")); | |
| 367 } | 371 } |
| 368 | 372 |
| 369 scoped_refptr<SafeBrowsingDatabaseManager> | 373 scoped_refptr<SafeBrowsingDatabaseManager> |
| 370 ClientSideDetectionHost::database_manager() { | 374 ClientSideDetectionHost::database_manager() { |
| 371 return database_manager_; | 375 return database_manager_; |
| 372 } | 376 } |
| 373 | 377 |
| 374 bool ClientSideDetectionHost::DidPageReceiveSafeBrowsingMatch() const { | 378 bool ClientSideDetectionHost::DidPageReceiveSafeBrowsingMatch() const { |
|
mattm
2013/12/14 00:09:49
nit: probably would be cleaner if it first just go
mattm
2013/12/14 00:09:49
null checks here too.
Greg Billock
2013/12/14 18:35:34
Done.
Greg Billock
2013/12/14 18:35:34
Done.
| |
| 375 return malware_or_phishing_match_ || DidShowSBInterstitial(); | 379 if (web_contents()->GetController().GetPendingEntry()) { |
|
mattm
2013/12/14 00:09:49
GetActiveEntry will already return the pending ent
Greg Billock
2013/12/14 18:35:34
Yes, the transient entries are the reason for this
mattm
2013/12/16 22:36:11
Yeah, I didn't understand the comment. Maybe somet
Greg Billock
2013/12/16 23:00:21
I think I always want to check Pending if there is
mattm
2013/12/16 23:28:51
Sorry, my comment neglected a point. In the case I
Greg Billock
2013/12/16 23:59:42
Are there any such cases? That is, can we basicall
mattm
2013/12/17 00:09:19
Yeah, a safebrowsing match can occur either on a p
Greg Billock
2013/12/17 00:18:32
Cool. Yeah, I added a test for that case. Thanks!
| |
| 380 // Check the pending entry if we are displaying an interstitial page. | |
|
mattm
2013/12/14 00:09:49
Comment is a little confusing as it might not actu
Greg Billock
2013/12/14 18:35:34
Yeah, this is for the other case -- that case shou
| |
| 381 base::string16 value; | |
| 382 return web_contents()->GetController().GetPendingEntry()->GetExtraData( | |
| 383 kSafeBrowsingHitKey, &value); | |
| 384 } | |
| 385 | |
| 386 base::string16 value; | |
| 387 return web_contents()->GetController().GetActiveEntry()->GetExtraData( | |
| 388 kSafeBrowsingHitKey, &value); | |
| 376 } | 389 } |
| 377 | 390 |
| 378 void ClientSideDetectionHost::WebContentsDestroyed(WebContents* tab) { | 391 void ClientSideDetectionHost::WebContentsDestroyed(WebContents* tab) { |
| 379 DCHECK(tab); | 392 DCHECK(tab); |
| 380 // Tell any pending classification request that it is being canceled. | 393 // Tell any pending classification request that it is being canceled. |
| 381 if (classification_request_.get()) { | 394 if (classification_request_.get()) { |
| 382 classification_request_->Cancel(); | 395 classification_request_->Cancel(); |
| 383 } | 396 } |
| 384 // Cancel all pending feature extractions. | 397 // Cancel all pending feature extractions. |
| 385 feature_extractor_.reset(); | 398 feature_extractor_.reset(); |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 615 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 628 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 616 return malware_killswitch_on_; | 629 return malware_killswitch_on_; |
| 617 } | 630 } |
| 618 | 631 |
| 619 void ClientSideDetectionHost::SetMalwareKillSwitch(bool killswitch_on) { | 632 void ClientSideDetectionHost::SetMalwareKillSwitch(bool killswitch_on) { |
| 620 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 633 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 621 malware_killswitch_on_ = killswitch_on; | 634 malware_killswitch_on_ = killswitch_on; |
| 622 } | 635 } |
| 623 | 636 |
| 624 } // namespace safe_browsing | 637 } // namespace safe_browsing |
| OLD | NEW |