OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/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" |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
108 } | 108 } |
109 | 109 |
110 // We lookup the csd-whitelist before we lookup the cache because | 110 // We lookup the csd-whitelist before we lookup the cache because |
111 // a URL may have recently been whitelisted. If the URL matches | 111 // a URL may have recently been whitelisted. If the URL matches |
112 // the csd-whitelist we won't start classification. The | 112 // the csd-whitelist we won't start classification. The |
113 // csd-whitelist check has to be done on the IO thread because it | 113 // csd-whitelist check has to be done on the IO thread because it |
114 // uses the SafeBrowsing service class. | 114 // uses the SafeBrowsing service class. |
115 BrowserThread::PostTask( | 115 BrowserThread::PostTask( |
116 BrowserThread::IO, | 116 BrowserThread::IO, |
117 FROM_HERE, | 117 FROM_HERE, |
118 NewRunnableMethod(this, | 118 base::Bind(&ShouldClassifyUrlRequest::CheckCsdWhitelist, |
119 &ShouldClassifyUrlRequest::CheckCsdWhitelist, | 119 this, params_.url)); |
120 params_.url)); | |
121 } | 120 } |
122 | 121 |
123 void Cancel() { | 122 void Cancel() { |
124 canceled_ = true; | 123 canceled_ = true; |
125 // Just to make sure we don't do anything stupid we reset all these | 124 // Just to make sure we don't do anything stupid we reset all these |
126 // pointers except for the safebrowsing service class which may be | 125 // pointers except for the safebrowsing service class which may be |
127 // accessed by CheckCsdWhitelist(). | 126 // accessed by CheckCsdWhitelist(). |
128 tab_contents_ = NULL; | 127 tab_contents_ = NULL; |
129 csd_service_ = NULL; | 128 csd_service_ = NULL; |
130 host_ = NULL; | 129 host_ = NULL; |
(...skipping 26 matching lines...) Expand all Loading... | |
157 << " because it matches the csd whitelist"; | 156 << " because it matches the csd whitelist"; |
158 UMA_HISTOGRAM_ENUMERATION("SBClientPhishing.PreClassificationCheckFail", | 157 UMA_HISTOGRAM_ENUMERATION("SBClientPhishing.PreClassificationCheckFail", |
159 NO_CLASSIFY_MATCH_CSD_WHITELIST, | 158 NO_CLASSIFY_MATCH_CSD_WHITELIST, |
160 NO_CLASSIFY_MAX); | 159 NO_CLASSIFY_MAX); |
161 return; | 160 return; |
162 } | 161 } |
163 | 162 |
164 BrowserThread::PostTask( | 163 BrowserThread::PostTask( |
165 BrowserThread::UI, | 164 BrowserThread::UI, |
166 FROM_HERE, | 165 FROM_HERE, |
167 NewRunnableMethod(this, | 166 base::Bind(&ShouldClassifyUrlRequest::CheckCache, this)); |
168 &ShouldClassifyUrlRequest::CheckCache)); | |
169 } | 167 } |
170 | 168 |
171 void CheckCache() { | 169 void CheckCache() { |
172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
173 if (canceled_) { | 171 if (canceled_) { |
174 return; | 172 return; |
175 } | 173 } |
176 | 174 |
177 // If result is cached, we don't want to run classification again | 175 // If result is cached, we don't want to run classification again |
178 bool is_phishing; | 176 bool is_phishing; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
253 | 251 |
254 // static | 252 // static |
255 ClientSideDetectionHost* ClientSideDetectionHost::Create( | 253 ClientSideDetectionHost* ClientSideDetectionHost::Create( |
256 TabContents* tab) { | 254 TabContents* tab) { |
257 return new ClientSideDetectionHost(tab); | 255 return new ClientSideDetectionHost(tab); |
258 } | 256 } |
259 | 257 |
260 ClientSideDetectionHost::ClientSideDetectionHost(TabContents* tab) | 258 ClientSideDetectionHost::ClientSideDetectionHost(TabContents* tab) |
261 : TabContentsObserver(tab), | 259 : TabContentsObserver(tab), |
262 csd_service_(NULL), | 260 csd_service_(NULL), |
263 cb_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 261 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
264 unsafe_unique_page_id_(-1) { | 262 unsafe_unique_page_id_(-1) { |
265 DCHECK(tab); | 263 DCHECK(tab); |
266 csd_service_ = g_browser_process->safe_browsing_detection_service(); | 264 csd_service_ = g_browser_process->safe_browsing_detection_service(); |
267 feature_extractor_.reset(new BrowserFeatureExtractor(tab, csd_service_)); | 265 feature_extractor_.reset(new BrowserFeatureExtractor(tab, csd_service_)); |
268 sb_service_ = g_browser_process->safe_browsing_service(); | 266 sb_service_ = g_browser_process->safe_browsing_service(); |
269 // Note: csd_service_ and sb_service_ will be NULL here in testing. | 267 // Note: csd_service_ and sb_service_ will be NULL here in testing. |
270 registrar_.Add(this, content::NOTIFICATION_RESOURCE_RESPONSE_STARTED, | 268 registrar_.Add(this, content::NOTIFICATION_RESOURCE_RESPONSE_STARTED, |
271 content::Source<RenderViewHostDelegate>(tab)); | 269 content::Source<RenderViewHostDelegate>(tab)); |
272 if (sb_service_) { | 270 if (sb_service_) { |
273 sb_service_->AddObserver(this); | 271 sb_service_->AddObserver(this); |
(...skipping 26 matching lines...) Expand all Loading... | |
300 // If the navigation is within the same page, the user isn't really | 298 // 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 | 299 // navigating away. We don't need to cancel a pending callback or |
302 // begin a new classification. | 300 // begin a new classification. |
303 return; | 301 return; |
304 } | 302 } |
305 // If we navigate away and there currently is a pending phishing | 303 // If we navigate away and there currently is a pending phishing |
306 // report request we have to cancel it to make sure we don't display | 304 // report request we have to cancel it to make sure we don't display |
307 // an interstitial for the wrong page. Note that this won't cancel | 305 // an interstitial for the wrong page. Note that this won't cancel |
308 // the server ping back but only cancel the showing of the | 306 // the server ping back but only cancel the showing of the |
309 // interstial. | 307 // interstial. |
310 cb_factory_.RevokeAll(); | 308 weak_factory_.InvalidateWeakPtrs(); |
311 | 309 |
312 if (!csd_service_) { | 310 if (!csd_service_) { |
313 return; | 311 return; |
314 } | 312 } |
315 | 313 |
316 // Cancel any pending classification request. | 314 // Cancel any pending classification request. |
317 if (classification_request_.get()) { | 315 if (classification_request_.get()) { |
318 classification_request_->Cancel(); | 316 classification_request_->Cancel(); |
319 } | 317 } |
320 browse_info_.reset(new BrowseInfo); | 318 browse_info_.reset(new BrowseInfo); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
371 | 369 |
372 void ClientSideDetectionHost::OnPhishingDetectionDone( | 370 void ClientSideDetectionHost::OnPhishingDetectionDone( |
373 const std::string& verdict_str) { | 371 const std::string& verdict_str) { |
374 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 372 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
375 // There is something seriously wrong if there is no service class but | 373 // There is something seriously wrong if there is no service class but |
376 // this method is called. The renderer should not start phishing detection | 374 // this method is called. The renderer should not start phishing detection |
377 // if there isn't any service class in the browser. | 375 // if there isn't any service class in the browser. |
378 DCHECK(csd_service_); | 376 DCHECK(csd_service_); |
379 // There shouldn't be any pending requests because we revoke them everytime | 377 // There shouldn't be any pending requests because we revoke them everytime |
380 // we navigate away. | 378 // we navigate away. |
381 DCHECK(!cb_factory_.HasPendingCallbacks()); | 379 DCHECK(!weak_factory_.HasWeakPtrs()); |
382 DCHECK(browse_info_.get()); | 380 DCHECK(browse_info_.get()); |
383 | 381 |
384 // We parse the protocol buffer here. If we're unable to parse it we won't | 382 // We parse the protocol buffer here. If we're unable to parse it we won't |
385 // send the verdict further. | 383 // send the verdict further. |
386 scoped_ptr<ClientPhishingRequest> verdict(new ClientPhishingRequest); | 384 scoped_ptr<ClientPhishingRequest> verdict(new ClientPhishingRequest); |
387 if (csd_service_ && | 385 if (csd_service_ && |
388 !cb_factory_.HasPendingCallbacks() && | 386 !weak_factory_.HasWeakPtrs() && |
389 browse_info_.get() && | 387 browse_info_.get() && |
390 verdict->ParseFromString(verdict_str) && | 388 verdict->ParseFromString(verdict_str) && |
391 verdict->IsInitialized() && | 389 verdict->IsInitialized() && |
392 // We only send the verdict to the server if the verdict is phishing or if | 390 // We only send the verdict to the server if the verdict is phishing or if |
393 // a SafeBrowsing interstitial was already shown for this site. E.g., a | 391 // a SafeBrowsing interstitial was already shown for this site. E.g., a |
394 // malware or phishing interstitial was shown but the user clicked | 392 // malware or phishing interstitial was shown but the user clicked |
395 // through. | 393 // through. |
396 (verdict->is_phishing() || DidShowSBInterstitial())) { | 394 (verdict->is_phishing() || DidShowSBInterstitial())) { |
397 if (DidShowSBInterstitial()) { | 395 if (DidShowSBInterstitial()) { |
398 browse_info_->unsafe_resource.reset(unsafe_resource_.release()); | 396 browse_info_->unsafe_resource.reset(unsafe_resource_.release()); |
399 } | 397 } |
400 // Start browser-side feature extraction. Once we're done it will send | 398 // Start browser-side feature extraction. Once we're done it will send |
401 // the client verdict request. | 399 // the client verdict request. |
402 feature_extractor_->ExtractFeatures( | 400 feature_extractor_->ExtractFeatures( |
403 browse_info_.get(), | 401 browse_info_.get(), |
404 verdict.release(), | 402 verdict.release(), |
405 NewCallback(this, &ClientSideDetectionHost::FeatureExtractionDone)); | 403 base::Bind(&ClientSideDetectionHost::FeatureExtractionDone, |
404 weak_factory_.GetWeakPtr())); | |
awong
2011/11/21 21:59:00
To confirm, in this setup, if ClientSideDetectionH
noelutz
2011/11/21 22:13:51
It's OK of the callback is never called.
| |
406 } | 405 } |
407 browse_info_.reset(); | 406 browse_info_.reset(); |
408 } | 407 } |
409 | 408 |
410 void ClientSideDetectionHost::MaybeShowPhishingWarning(GURL phishing_url, | 409 void ClientSideDetectionHost::MaybeShowPhishingWarning(GURL phishing_url, |
411 bool is_phishing) { | 410 bool is_phishing) { |
412 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 411 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
413 VLOG(2) << "Received server phishing verdict for URL:" << phishing_url | 412 VLOG(2) << "Received server phishing verdict for URL:" << phishing_url |
414 << " is_phishing:" << is_phishing; | 413 << " is_phishing:" << is_phishing; |
415 if (is_phishing) { | 414 if (is_phishing) { |
(...skipping 21 matching lines...) Expand all Loading... | |
437 | 436 |
438 void ClientSideDetectionHost::FeatureExtractionDone( | 437 void ClientSideDetectionHost::FeatureExtractionDone( |
439 bool success, | 438 bool success, |
440 ClientPhishingRequest* request) { | 439 ClientPhishingRequest* request) { |
441 if (!request) { | 440 if (!request) { |
442 DLOG(FATAL) << "Invalid request object in FeatureExtractionDone"; | 441 DLOG(FATAL) << "Invalid request object in FeatureExtractionDone"; |
443 return; | 442 return; |
444 } | 443 } |
445 VLOG(2) << "Feature extraction done (success:" << success << ") for URL: " | 444 VLOG(2) << "Feature extraction done (success:" << success << ") for URL: " |
446 << request->url() << ". Start sending client phishing request."; | 445 << request->url() << ". Start sending client phishing request."; |
447 ClientSideDetectionService::ClientReportPhishingRequestCallback* cb = NULL; | 446 ClientSideDetectionService::ClientReportPhishingRequestCallback callback; |
448 // If the client-side verdict isn't phishing we don't care about the server | 447 // If the client-side verdict isn't phishing we don't care about the server |
449 // response because we aren't going to display a warning. | 448 // response because we aren't going to display a warning. |
450 if (request->is_phishing()) { | 449 if (request->is_phishing()) { |
451 cb = cb_factory_.NewCallback( | 450 callback = base::Bind(&ClientSideDetectionHost::MaybeShowPhishingWarning, |
452 &ClientSideDetectionHost::MaybeShowPhishingWarning); | 451 weak_factory_.GetWeakPtr()); |
453 } | 452 } |
454 // Send ping even if the browser feature extraction failed. | 453 // Send ping even if the browser feature extraction failed. |
455 csd_service_->SendClientReportPhishingRequest( | 454 csd_service_->SendClientReportPhishingRequest( |
456 request, // The service takes ownership of the request object. | 455 request, // The service takes ownership of the request object. |
457 cb); | 456 callback); |
458 } | 457 } |
459 | 458 |
460 void ClientSideDetectionHost::Observe( | 459 void ClientSideDetectionHost::Observe( |
461 int type, | 460 int type, |
462 const content::NotificationSource& source, | 461 const content::NotificationSource& source, |
463 const content::NotificationDetails& details) { | 462 const content::NotificationDetails& details) { |
464 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 463 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
465 DCHECK_EQ(type, content::NOTIFICATION_RESOURCE_RESPONSE_STARTED); | 464 DCHECK_EQ(type, content::NOTIFICATION_RESOURCE_RESPONSE_STARTED); |
466 const ResourceRequestDetails* req = content::Details<ResourceRequestDetails>( | 465 const ResourceRequestDetails* req = content::Details<ResourceRequestDetails>( |
467 details).ptr(); | 466 details).ptr(); |
(...skipping 21 matching lines...) Expand all Loading... | |
489 if (sb_service_) { | 488 if (sb_service_) { |
490 sb_service_->RemoveObserver(this); | 489 sb_service_->RemoveObserver(this); |
491 } | 490 } |
492 sb_service_ = service; | 491 sb_service_ = service; |
493 if (sb_service_) { | 492 if (sb_service_) { |
494 sb_service_->AddObserver(this); | 493 sb_service_->AddObserver(this); |
495 } | 494 } |
496 } | 495 } |
497 | 496 |
498 } // namespace safe_browsing | 497 } // namespace safe_browsing |
OLD | NEW |