Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: chrome/browser/safe_browsing/client_side_detection_host.cc

Issue 7408001: If we show a SafeBrowsing warning we always send the client-side detection (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 262
263 // static 263 // static
264 ClientSideDetectionHost* ClientSideDetectionHost::Create( 264 ClientSideDetectionHost* ClientSideDetectionHost::Create(
265 TabContents* tab) { 265 TabContents* tab) {
266 return new ClientSideDetectionHost(tab); 266 return new ClientSideDetectionHost(tab);
267 } 267 }
268 268
269 ClientSideDetectionHost::ClientSideDetectionHost(TabContents* tab) 269 ClientSideDetectionHost::ClientSideDetectionHost(TabContents* tab)
270 : TabContentsObserver(tab), 270 : TabContentsObserver(tab),
271 csd_service_(NULL), 271 csd_service_(NULL),
272 cb_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { 272 cb_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
273 unsafe_unique_page_id_(-1) {
273 DCHECK(tab); 274 DCHECK(tab);
274 csd_service_ = g_browser_process->safe_browsing_detection_service(); 275 csd_service_ = g_browser_process->safe_browsing_detection_service();
275 feature_extractor_.reset(new BrowserFeatureExtractor(tab, csd_service_)); 276 feature_extractor_.reset(new BrowserFeatureExtractor(tab, csd_service_));
276 sb_service_ = g_browser_process->safe_browsing_service(); 277 sb_service_ = g_browser_process->safe_browsing_service();
277 // Note: csd_service_ and sb_service_ will be NULL here in testing. 278 // Note: csd_service_ and sb_service_ will be NULL here in testing.
278 registrar_.Add(this, content::NOTIFICATION_RESOURCE_RESPONSE_STARTED, 279 registrar_.Add(this, content::NOTIFICATION_RESOURCE_RESPONSE_STARTED,
279 Source<RenderViewHostDelegate>(tab)); 280 Source<RenderViewHostDelegate>(tab));
281 if (sb_service_) {
282 sb_service_->AddObserver(this);
283 }
280 } 284 }
281 285
282 ClientSideDetectionHost::~ClientSideDetectionHost() {} 286 ClientSideDetectionHost::~ClientSideDetectionHost() {
287 if (sb_service_) {
288 sb_service_->RemoveObserver(this);
289 }
290 }
283 291
284 bool ClientSideDetectionHost::OnMessageReceived(const IPC::Message& message) { 292 bool ClientSideDetectionHost::OnMessageReceived(const IPC::Message& message) {
285 bool handled = true; 293 bool handled = true;
286 IPC_BEGIN_MESSAGE_MAP(ClientSideDetectionHost, message) 294 IPC_BEGIN_MESSAGE_MAP(ClientSideDetectionHost, message)
287 IPC_MESSAGE_HANDLER(SafeBrowsingHostMsg_DetectedPhishingSite, 295 IPC_MESSAGE_HANDLER(SafeBrowsingHostMsg_PhishingDetectionDone,
288 OnDetectedPhishingSite) 296 OnPhishingDetectionDone)
289 IPC_MESSAGE_UNHANDLED(handled = false) 297 IPC_MESSAGE_UNHANDLED(handled = false)
290 IPC_END_MESSAGE_MAP() 298 IPC_END_MESSAGE_MAP()
291 return handled; 299 return handled;
292 } 300 }
293 301
294 void ClientSideDetectionHost::DidNavigateMainFramePostCommit( 302 void ClientSideDetectionHost::DidNavigateMainFramePostCommit(
295 const content::LoadCommittedDetails& details, 303 const content::LoadCommittedDetails& details,
296 const ViewHostMsg_FrameNavigate_Params& params) { 304 const ViewHostMsg_FrameNavigate_Params& params) {
297 // TODO(noelutz): move this DCHECK to TabContents and fix all the unit tests 305 // TODO(noelutz): move this DCHECK to TabContents and fix all the unit tests
298 // that don't call this method on the UI thread. 306 // that don't call this method on the UI thread.
(...skipping 26 matching lines...) Expand all
325 333
326 // Notify the renderer if it should classify this URL. 334 // Notify the renderer if it should classify this URL.
327 classification_request_ = new ShouldClassifyUrlRequest(params, 335 classification_request_ = new ShouldClassifyUrlRequest(params,
328 tab_contents(), 336 tab_contents(),
329 csd_service_, 337 csd_service_,
330 sb_service_, 338 sb_service_,
331 this); 339 this);
332 classification_request_->Start(); 340 classification_request_->Start();
333 } 341 }
334 342
343 void ClientSideDetectionHost::OnSafeBrowsingHit(
344 const SafeBrowsingService::UnsafeResource& resource) {
345 // Check that this notification is really for us and that it corresponds to
346 // either a malware or phishing hit. In this case we store the unique page
347 // ID and store it for later. For phishing hits we also require that the
Garrett Casto 2011/07/19 21:18:48 The "In this case ..." sentence seems to have two
noelutz 2011/07/19 22:28:08 Removed the top level phishing check. We can chec
348 // top level URL match the phishing list.
349 if (tab_contents() &&
350 tab_contents()->GetRenderProcessHost()->id() ==
351 resource.render_process_host_id &&
352 tab_contents()->render_view_host()->routing_id() ==
353 resource.render_view_id &&
354 ((resource.threat_type == SafeBrowsingService::URL_PHISHING &&
355 !resource.is_subresource) ||
356 resource.threat_type == SafeBrowsingService::URL_MALWARE) &&
357 tab_contents()->controller().GetActiveEntry()) {
358 unsafe_unique_page_id_ =
359 tab_contents()->controller().GetActiveEntry()->unique_id();
360 }
361 }
362
335 void ClientSideDetectionHost::TabContentsDestroyed(TabContents* tab) { 363 void ClientSideDetectionHost::TabContentsDestroyed(TabContents* tab) {
336 DCHECK(tab); 364 DCHECK(tab);
337 // Tell any pending classification request that it is being canceled. 365 // Tell any pending classification request that it is being canceled.
338 if (classification_request_.get()) { 366 if (classification_request_.get()) {
339 classification_request_->Cancel(); 367 classification_request_->Cancel();
340 } 368 }
341 // Cancel all pending feature extractions. 369 // Cancel all pending feature extractions.
342 feature_extractor_.reset(); 370 feature_extractor_.reset();
343 } 371 }
344 372
345 void ClientSideDetectionHost::OnDetectedPhishingSite( 373 void ClientSideDetectionHost::OnPhishingDetectionDone(
346 const std::string& verdict_str) { 374 const std::string& verdict_str) {
347 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 375 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
348 // There is something seriously wrong if there is no service class but 376 // There is something seriously wrong if there is no service class but
349 // this method is called. The renderer should not start phishing detection 377 // this method is called. The renderer should not start phishing detection
350 // if there isn't any service class in the browser. 378 // if there isn't any service class in the browser.
351 DCHECK(csd_service_); 379 DCHECK(csd_service_);
352 // There shouldn't be any pending requests because we revoke them everytime 380 // There shouldn't be any pending requests because we revoke them everytime
353 // we navigate away. 381 // we navigate away.
354 DCHECK(!cb_factory_.HasPendingCallbacks()); 382 DCHECK(!cb_factory_.HasPendingCallbacks());
355 DCHECK(browse_info_.get()); 383 DCHECK(browse_info_.get());
356 384
357 // We parse the protocol buffer here. If we're unable to parse it we won't 385 // We parse the protocol buffer here. If we're unable to parse it we won't
358 // send the verdict further. 386 // send the verdict further.
359 scoped_ptr<ClientPhishingRequest> verdict(new ClientPhishingRequest); 387 scoped_ptr<ClientPhishingRequest> verdict(new ClientPhishingRequest);
360 if (csd_service_ && 388 if (csd_service_ &&
361 !cb_factory_.HasPendingCallbacks() && 389 !cb_factory_.HasPendingCallbacks() &&
362 browse_info_.get() && 390 browse_info_.get() &&
363 verdict->ParseFromString(verdict_str) && 391 verdict->ParseFromString(verdict_str) &&
364 verdict->IsInitialized()) { 392 verdict->IsInitialized() &&
393 // We only send the verdict to the server if the verdict is phishing or if
394 // a SafeBrowsing interstitial was already shown for this site. E.g., a
395 // malware or phishing interstitial was shown but the user clicked
396 // through.
397 (verdict->is_phishing() || DidShowSBInterstitial())) {
365 if (browse_info_->url.spec() != verdict->url()) { 398 if (browse_info_->url.spec() != verdict->url()) {
366 // I'm not sure we can DCHECK on this one so we keep stats around to see 399 // I'm not sure we can DCHECK on this one so we keep stats around to see
367 // whether this actually happens in practice. 400 // whether this actually happens in practice.
368 UMA_HISTOGRAM_COUNTS("SBClientPhishing.BrowserRendererUrlMismatch", 1); 401 UMA_HISTOGRAM_COUNTS("SBClientPhishing.BrowserRendererUrlMismatch", 1);
369 VLOG(2) << "Browser and renderer URL do not match: " 402 VLOG(2) << "Browser and renderer URL do not match: "
370 << browse_info_->url.spec() << " vs. " << verdict->url(); 403 << browse_info_->url.spec() << " vs. " << verdict->url();
371 } 404 }
372 // Start browser-side feature extraction. Once we're done it will send 405 // Start browser-side feature extraction. Once we're done it will send
373 // the client verdict request. 406 // the client verdict request.
374 feature_extractor_->ExtractFeatures( 407 feature_extractor_->ExtractFeatures(
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 442
410 void ClientSideDetectionHost::FeatureExtractionDone( 443 void ClientSideDetectionHost::FeatureExtractionDone(
411 bool success, 444 bool success,
412 ClientPhishingRequest* request) { 445 ClientPhishingRequest* request) {
413 if (!request) { 446 if (!request) {
414 DLOG(FATAL) << "Invalid request object in FeatureExtractionDone"; 447 DLOG(FATAL) << "Invalid request object in FeatureExtractionDone";
415 return; 448 return;
416 } 449 }
417 VLOG(2) << "Feature extraction done (success:" << success << ") for URL: " 450 VLOG(2) << "Feature extraction done (success:" << success << ") for URL: "
418 << request->url() << ". Start sending client phishing request."; 451 << request->url() << ". Start sending client phishing request.";
419 // Send ping no matter what - even if the browser feature extraction failed. 452 ClientSideDetectionService::ClientReportPhishingRequestCallback* cb = NULL;
453 // If the client-side verdict isn't phishing we don't care about the server
454 // response because we aren't going to display a warning.
455 if (request->is_phishing()) {
Garrett Casto 2011/07/19 21:18:48 So we probably don't want to show a warning if we
noelutz 2011/07/19 22:28:08 I already implemented that a while back in the Saf
456 cb = cb_factory_.NewCallback(
457 &ClientSideDetectionHost::MaybeShowPhishingWarning);
458 }
459 // Send ping even if the browser feature extraction failed.
420 csd_service_->SendClientReportPhishingRequest( 460 csd_service_->SendClientReportPhishingRequest(
421 request, // The service takes ownership of the request object. 461 request, // The service takes ownership of the request object.
422 cb_factory_.NewCallback( 462 cb);
423 &ClientSideDetectionHost::MaybeShowPhishingWarning));
424 } 463 }
425 464
426 void ClientSideDetectionHost::Observe(int type, 465 void ClientSideDetectionHost::Observe(int type,
427 const NotificationSource& source, 466 const NotificationSource& source,
428 const NotificationDetails& details) { 467 const NotificationDetails& details) {
429 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 468 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
430 DCHECK_EQ(type, content::NOTIFICATION_RESOURCE_RESPONSE_STARTED); 469 DCHECK_EQ(type, content::NOTIFICATION_RESOURCE_RESPONSE_STARTED);
431 const ResourceRequestDetails* req = Details<ResourceRequestDetails>( 470 const ResourceRequestDetails* req = Details<ResourceRequestDetails>(
432 details).ptr(); 471 details).ptr();
433 if (req && browse_info_.get()) { 472 if (req && browse_info_.get()) {
434 browse_info_->ips.insert(req->socket_address().host()); 473 browse_info_->ips.insert(req->socket_address().host());
435 } 474 }
436 } 475 }
437 476
477 bool ClientSideDetectionHost::DidShowSBInterstitial() {
478 return (unsafe_unique_page_id_ > 0 &&
479 tab_contents() &&
480 tab_contents()->controller().GetActiveEntry() &&
481 tab_contents()->controller().GetActiveEntry()->unique_id() ==
Brian Ryner 2011/07/19 21:27:10 You could avoid some of the repetition in this met
noelutz 2011/07/19 22:28:08 Done.
482 unsafe_unique_page_id_);
483 }
484
438 void ClientSideDetectionHost::set_client_side_detection_service( 485 void ClientSideDetectionHost::set_client_side_detection_service(
439 ClientSideDetectionService* service) { 486 ClientSideDetectionService* service) {
440 csd_service_ = service; 487 csd_service_ = service;
441 } 488 }
442 489
443 void ClientSideDetectionHost::set_safe_browsing_service( 490 void ClientSideDetectionHost::set_safe_browsing_service(
444 SafeBrowsingService* service) { 491 SafeBrowsingService* service) {
492 if (sb_service_) {
493 sb_service_->RemoveObserver(this);
494 }
445 sb_service_ = service; 495 sb_service_ = service;
496 if (sb_service_) {
497 sb_service_->AddObserver(this);
498 }
446 } 499 }
447 500
448 } // namespace safe_browsing 501 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698