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

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

Issue 351363002: Revert of Port HistoryService::GetVisibleVisitCountToHost to CancelableTaskTracker (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 6 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) 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/browser_feature_extractor.h" 5 #include "chrome/browser/safe_browsing/browser_feature_extractor.h"
6 6
7 #include <map> 7 #include <map>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/bind_helpers.h" 11 #include "base/bind_helpers.h"
12 #include "base/format_macros.h" 12 #include "base/format_macros.h"
13 #include "base/stl_util.h" 13 #include "base/stl_util.h"
14 #include "base/strings/stringprintf.h" 14 #include "base/strings/stringprintf.h"
15 #include "base/time/time.h" 15 #include "base/time/time.h"
16 #include "chrome/browser/common/cancelable_request.h"
16 #include "chrome/browser/history/history_service.h" 17 #include "chrome/browser/history/history_service.h"
17 #include "chrome/browser/history/history_service_factory.h" 18 #include "chrome/browser/history/history_service_factory.h"
18 #include "chrome/browser/history/history_types.h" 19 #include "chrome/browser/history/history_types.h"
19 #include "chrome/browser/profiles/profile.h" 20 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/safe_browsing/browser_features.h" 21 #include "chrome/browser/safe_browsing/browser_features.h"
21 #include "chrome/browser/safe_browsing/client_side_detection_host.h" 22 #include "chrome/browser/safe_browsing/client_side_detection_host.h"
22 #include "chrome/browser/safe_browsing/database_manager.h" 23 #include "chrome/browser/safe_browsing/database_manager.h"
23 #include "chrome/common/safe_browsing/csd.pb.h" 24 #include "chrome/common/safe_browsing/csd.pb.h"
24 #include "content/public/browser/browser_thread.h" 25 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/navigation_controller.h" 26 #include "content/public/browser/navigation_controller.h"
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 WebContents* tab, 167 WebContents* tab,
167 ClientSideDetectionHost* host) 168 ClientSideDetectionHost* host)
168 : tab_(tab), 169 : tab_(tab),
169 host_(host), 170 host_(host),
170 weak_factory_(this) { 171 weak_factory_(this) {
171 DCHECK(tab); 172 DCHECK(tab);
172 } 173 }
173 174
174 BrowserFeatureExtractor::~BrowserFeatureExtractor() { 175 BrowserFeatureExtractor::~BrowserFeatureExtractor() {
175 weak_factory_.InvalidateWeakPtrs(); 176 weak_factory_.InvalidateWeakPtrs();
177 // Delete all the pending extractions (delete callback and request objects).
178 STLDeleteContainerPairFirstPointers(pending_extractions_.begin(),
179 pending_extractions_.end());
180
181 // Also cancel all the pending history service queries.
182 HistoryService* history;
183 bool success = GetHistoryService(&history);
184 DCHECK(success || pending_queries_.size() == 0);
185 // Cancel all the pending history lookups and cleanup the memory.
186 for (PendingQueriesMap::iterator it = pending_queries_.begin();
187 it != pending_queries_.end(); ++it) {
188 if (history) {
189 history->CancelRequest(it->first);
190 }
191 ExtractionData& extraction = it->second;
192 delete extraction.first; // delete request
193 }
194 pending_queries_.clear();
176 } 195 }
177 196
178 void BrowserFeatureExtractor::ExtractFeatures(const BrowseInfo* info, 197 void BrowserFeatureExtractor::ExtractFeatures(const BrowseInfo* info,
179 ClientPhishingRequest* request, 198 ClientPhishingRequest* request,
180 const DoneCallback& callback) { 199 const DoneCallback& callback) {
181 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
182 DCHECK(request); 201 DCHECK(request);
183 DCHECK(info); 202 DCHECK(info);
184 DCHECK_EQ(0U, request->url().find("http:")); 203 DCHECK_EQ(0U, request->url().find("http:"));
185 DCHECK(!callback.is_null()); 204 DCHECK(!callback.is_null());
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 std::string(), controller, url_index, info->url_redirects, request); 242 std::string(), controller, url_index, info->url_redirects, request);
224 } 243 }
225 if (first_host_index != -1) { 244 if (first_host_index != -1) {
226 AddNavigationFeatures(features::kHostPrefix, 245 AddNavigationFeatures(features::kHostPrefix,
227 controller, 246 controller,
228 first_host_index, 247 first_host_index,
229 info->host_redirects, 248 info->host_redirects,
230 request); 249 request);
231 } 250 }
232 251
233 // The API doesn't take a scoped_ptr because the API gets mocked and we
234 // cannot mock an API that takes scoped_ptr as arguments.
235 scoped_ptr<ClientPhishingRequest> req(request);
236
237 ExtractBrowseInfoFeatures(*info, request); 252 ExtractBrowseInfoFeatures(*info, request);
253 pending_extractions_[request] = callback;
238 base::MessageLoop::current()->PostTask( 254 base::MessageLoop::current()->PostTask(
239 FROM_HERE, 255 FROM_HERE,
240 base::Bind(&BrowserFeatureExtractor::StartExtractFeatures, 256 base::Bind(&BrowserFeatureExtractor::StartExtractFeatures,
241 weak_factory_.GetWeakPtr(), 257 weak_factory_.GetWeakPtr(), request, callback));
242 base::Passed(&req),
243 callback));
244 } 258 }
245 259
246 void BrowserFeatureExtractor::ExtractMalwareFeatures( 260 void BrowserFeatureExtractor::ExtractMalwareFeatures(
247 BrowseInfo* info, 261 BrowseInfo* info,
248 ClientMalwareRequest* request, 262 ClientMalwareRequest* request,
249 const MalwareDoneCallback& callback) { 263 const MalwareDoneCallback& callback) {
250 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 264 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
251 DCHECK(!callback.is_null()); 265 DCHECK(!callback.is_null());
252 266
253 // Grab the IPs because they might go away before we're done 267 // Grab the IPs because they might go away before we're done
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 AddFeature(features::kSafeBrowsingThreatType, 306 AddFeature(features::kSafeBrowsingThreatType,
293 static_cast<double>(info.unsafe_resource->threat_type), 307 static_cast<double>(info.unsafe_resource->threat_type),
294 request); 308 request);
295 } 309 }
296 if (info.http_status_code != 0) { 310 if (info.http_status_code != 0) {
297 AddFeature(features::kHttpStatusCode, info.http_status_code, request); 311 AddFeature(features::kHttpStatusCode, info.http_status_code, request);
298 } 312 }
299 } 313 }
300 314
301 void BrowserFeatureExtractor::StartExtractFeatures( 315 void BrowserFeatureExtractor::StartExtractFeatures(
302 scoped_ptr<ClientPhishingRequest> request, 316 ClientPhishingRequest* request,
303 const DoneCallback& callback) { 317 const DoneCallback& callback) {
304 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 318 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
319 size_t removed = pending_extractions_.erase(request);
320 DCHECK_EQ(1U, removed);
305 HistoryService* history; 321 HistoryService* history;
306 if (!request || !request->IsInitialized() || !GetHistoryService(&history)) { 322 if (!request || !request->IsInitialized() || !GetHistoryService(&history)) {
307 callback.Run(false, request.Pass()); 323 callback.Run(false, request);
308 return; 324 return;
309 } 325 }
310 GURL request_url = GURL(request->url()); 326 // HistoryService::QueryURL migrated from CancelableRequestComsumer to
311 history->QueryURL(request_url, 327 // CancelableRequestTracker and there is no Handle to associate to the
328 // request. Instead manage the request object lifetime by using a scoped_ptr
329 // and using base::Passed(). So if the asynchronous call is canceled, the
330 // request is deleted, otherwise the callback becomes the owner.
331 scoped_ptr<ClientPhishingRequest> owned_request(request);
332 history->QueryURL(GURL(request->url()),
312 true /* wants_visits */, 333 true /* wants_visits */,
313 base::Bind(&BrowserFeatureExtractor::QueryUrlHistoryDone, 334 base::Bind(&BrowserFeatureExtractor::QueryUrlHistoryDone,
314 base::Unretained(this), 335 base::Unretained(this),
315 base::Passed(&request), 336 base::Passed(&owned_request),
316 callback), 337 callback),
317 &cancelable_task_tracker_); 338 &cancelable_task_tracker_);
318 } 339 }
319 340
320 void BrowserFeatureExtractor::QueryUrlHistoryDone( 341 void BrowserFeatureExtractor::QueryUrlHistoryDone(
321 scoped_ptr<ClientPhishingRequest> request, 342 scoped_ptr<ClientPhishingRequest> owned_request,
322 const DoneCallback& callback, 343 const DoneCallback& callback,
323 bool success, 344 bool success,
324 const history::URLRow& row, 345 const history::URLRow& row,
325 const history::VisitVector& visits) { 346 const history::VisitVector& visits) {
326 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 347 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
327 DCHECK(request); 348 DCHECK(owned_request);
328 DCHECK(!callback.is_null()); 349 DCHECK(!callback.is_null());
350 ClientPhishingRequest* request = owned_request.release();
329 if (!success) { 351 if (!success) {
330 // URL is not found in the history. In practice this should not 352 // URL is not found in the history. In practice this should not
331 // happen (unless there is a real error) because we just visited 353 // happen (unless there is a real error) because we just visited
332 // that URL. 354 // that URL.
333 callback.Run(false, request.Pass()); 355 callback.Run(false, request);
334 return; 356 return;
335 } 357 }
336 AddFeature(features::kUrlHistoryVisitCount, 358 AddFeature(features::kUrlHistoryVisitCount,
337 static_cast<double>(row.visit_count()), 359 static_cast<double>(row.visit_count()),
338 request.get()); 360 request);
339 361
340 base::Time threshold = base::Time::Now() - base::TimeDelta::FromDays(1); 362 base::Time threshold = base::Time::Now() - base::TimeDelta::FromDays(1);
341 int num_visits_24h_ago = 0; 363 int num_visits_24h_ago = 0;
342 int num_visits_typed = 0; 364 int num_visits_typed = 0;
343 int num_visits_link = 0; 365 int num_visits_link = 0;
344 for (history::VisitVector::const_iterator it = visits.begin(); 366 for (history::VisitVector::const_iterator it = visits.begin();
345 it != visits.end(); 367 it != visits.end();
346 ++it) { 368 ++it) {
347 if (!content::PageTransitionIsMainFrame(it->transition)) { 369 if (!content::PageTransitionIsMainFrame(it->transition)) {
348 continue; 370 continue;
349 } 371 }
350 if (it->visit_time < threshold) { 372 if (it->visit_time < threshold) {
351 ++num_visits_24h_ago; 373 ++num_visits_24h_ago;
352 } 374 }
353 content::PageTransition transition = content::PageTransitionStripQualifier( 375 content::PageTransition transition = content::PageTransitionStripQualifier(
354 it->transition); 376 it->transition);
355 if (transition == content::PAGE_TRANSITION_TYPED) { 377 if (transition == content::PAGE_TRANSITION_TYPED) {
356 ++num_visits_typed; 378 ++num_visits_typed;
357 } else if (transition == content::PAGE_TRANSITION_LINK) { 379 } else if (transition == content::PAGE_TRANSITION_LINK) {
358 ++num_visits_link; 380 ++num_visits_link;
359 } 381 }
360 } 382 }
361 AddFeature(features::kUrlHistoryVisitCountMoreThan24hAgo, 383 AddFeature(features::kUrlHistoryVisitCountMoreThan24hAgo,
362 static_cast<double>(num_visits_24h_ago), 384 static_cast<double>(num_visits_24h_ago),
363 request.get()); 385 request);
364 AddFeature(features::kUrlHistoryTypedCount, 386 AddFeature(features::kUrlHistoryTypedCount,
365 static_cast<double>(num_visits_typed), 387 static_cast<double>(num_visits_typed),
366 request.get()); 388 request);
367 AddFeature(features::kUrlHistoryLinkCount, 389 AddFeature(features::kUrlHistoryLinkCount,
368 static_cast<double>(num_visits_link), 390 static_cast<double>(num_visits_link),
369 request.get()); 391 request);
370 392
371 // Issue next history lookup for host visits. 393 // Issue next history lookup for host visits.
372 HistoryService* history; 394 HistoryService* history;
373 if (!GetHistoryService(&history)) { 395 if (!GetHistoryService(&history)) {
374 callback.Run(false, request.Pass()); 396 callback.Run(false, request);
375 return; 397 return;
376 } 398 }
377 GURL request_url = GURL(request->url()); 399 CancelableRequestProvider::Handle next_handle =
378 history->GetVisibleVisitCountToHost( 400 history->GetVisibleVisitCountToHost(
379 request_url, 401 GURL(request->url()),
380 base::Bind(&BrowserFeatureExtractor::QueryHttpHostVisitsDone, 402 &request_consumer_,
381 base::Unretained(this), 403 base::Bind(&BrowserFeatureExtractor::QueryHttpHostVisitsDone,
382 base::Passed(&request), 404 base::Unretained(this)));
383 callback), 405 StorePendingQuery(next_handle, request, callback);
384 &cancelable_task_tracker_);
385 } 406 }
386 407
387 void BrowserFeatureExtractor::QueryHttpHostVisitsDone( 408 void BrowserFeatureExtractor::QueryHttpHostVisitsDone(
388 scoped_ptr<ClientPhishingRequest> request, 409 CancelableRequestProvider::Handle handle,
389 const DoneCallback& callback,
390 bool success, 410 bool success,
391 int num_visits, 411 int num_visits,
392 base::Time first_visit) { 412 base::Time first_visit) {
393 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 413 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
414 ClientPhishingRequest* request;
415 DoneCallback callback;
416 if (!GetPendingQuery(handle, &request, &callback)) {
417 DLOG(FATAL) << "No pending history query found";
418 return;
419 }
394 DCHECK(request); 420 DCHECK(request);
395 DCHECK(!callback.is_null()); 421 DCHECK(!callback.is_null());
396 if (!success) { 422 if (!success) {
397 callback.Run(false, request.Pass()); 423 callback.Run(false, request);
398 return; 424 return;
399 } 425 }
400 SetHostVisitsFeatures(num_visits, first_visit, true, request.get()); 426 SetHostVisitsFeatures(num_visits, first_visit, true, request);
401 427
402 // Same lookup but for the HTTPS URL. 428 // Same lookup but for the HTTPS URL.
403 HistoryService* history; 429 HistoryService* history;
404 if (!GetHistoryService(&history)) { 430 if (!GetHistoryService(&history)) {
405 callback.Run(false, request.Pass()); 431 callback.Run(false, request);
406 return; 432 return;
407 } 433 }
408 std::string https_url = request->url(); 434 std::string https_url = request->url();
409 history->GetVisibleVisitCountToHost( 435 CancelableRequestProvider::Handle next_handle =
410 GURL(https_url.replace(0, 5, "https:")), 436 history->GetVisibleVisitCountToHost(
411 base::Bind(&BrowserFeatureExtractor::QueryHttpsHostVisitsDone, 437 GURL(https_url.replace(0, 5, "https:")),
412 base::Unretained(this), 438 &request_consumer_,
413 base::Passed(&request), 439 base::Bind(&BrowserFeatureExtractor::QueryHttpsHostVisitsDone,
414 callback), 440 base::Unretained(this)));
415 &cancelable_task_tracker_); 441 StorePendingQuery(next_handle, request, callback);
416 } 442 }
417 443
418 void BrowserFeatureExtractor::QueryHttpsHostVisitsDone( 444 void BrowserFeatureExtractor::QueryHttpsHostVisitsDone(
419 scoped_ptr<ClientPhishingRequest> request, 445 CancelableRequestProvider::Handle handle,
420 const DoneCallback& callback,
421 bool success, 446 bool success,
422 int num_visits, 447 int num_visits,
423 base::Time first_visit) { 448 base::Time first_visit) {
424 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 449 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
450 ClientPhishingRequest* request;
451 DoneCallback callback;
452 if (!GetPendingQuery(handle, &request, &callback)) {
453 DLOG(FATAL) << "No pending history query found";
454 return;
455 }
425 DCHECK(request); 456 DCHECK(request);
426 DCHECK(!callback.is_null()); 457 DCHECK(!callback.is_null());
427 if (!success) { 458 if (!success) {
428 callback.Run(false, request.Pass()); 459 callback.Run(false, request);
429 return; 460 return;
430 } 461 }
431 SetHostVisitsFeatures(num_visits, first_visit, false, request.get()); 462 SetHostVisitsFeatures(num_visits, first_visit, false, request);
432 callback.Run(true, request.Pass()); 463 callback.Run(true, request); // We're done with all the history lookups.
433 } 464 }
434 465
435 void BrowserFeatureExtractor::SetHostVisitsFeatures( 466 void BrowserFeatureExtractor::SetHostVisitsFeatures(
436 int num_visits, 467 int num_visits,
437 base::Time first_visit, 468 base::Time first_visit,
438 bool is_http_query, 469 bool is_http_query,
439 ClientPhishingRequest* request) { 470 ClientPhishingRequest* request) {
440 DCHECK(request); 471 DCHECK(request);
441 AddFeature(is_http_query ? 472 AddFeature(is_http_query ?
442 features::kHttpHostVisitCount : features::kHttpsHostVisitCount, 473 features::kHttpHostVisitCount : features::kHttpsHostVisitCount,
443 static_cast<double>(num_visits), 474 static_cast<double>(num_visits),
444 request); 475 request);
445 if (num_visits > 0) { 476 if (num_visits > 0) {
446 AddFeature( 477 AddFeature(
447 is_http_query ? 478 is_http_query ?
448 features::kFirstHttpHostVisitMoreThan24hAgo : 479 features::kFirstHttpHostVisitMoreThan24hAgo :
449 features::kFirstHttpsHostVisitMoreThan24hAgo, 480 features::kFirstHttpsHostVisitMoreThan24hAgo,
450 (first_visit < (base::Time::Now() - base::TimeDelta::FromDays(1))) ? 481 (first_visit < (base::Time::Now() - base::TimeDelta::FromDays(1))) ?
451 1.0 : 0.0, 482 1.0 : 0.0,
452 request); 483 request);
453 } 484 }
454 } 485 }
455 486
487 void BrowserFeatureExtractor::StorePendingQuery(
488 CancelableRequestProvider::Handle handle,
489 ClientPhishingRequest* request,
490 const DoneCallback& callback) {
491 DCHECK_EQ(0U, pending_queries_.count(handle));
492 pending_queries_[handle] = std::make_pair(request, callback);
493 }
494
495 bool BrowserFeatureExtractor::GetPendingQuery(
496 CancelableRequestProvider::Handle handle,
497 ClientPhishingRequest** request,
498 DoneCallback* callback) {
499 PendingQueriesMap::iterator it = pending_queries_.find(handle);
500 DCHECK(it != pending_queries_.end());
501 if (it != pending_queries_.end()) {
502 *request = it->second.first;
503 *callback = it->second.second;
504 pending_queries_.erase(it);
505 return true;
506 }
507 return false;
508 }
509
456 bool BrowserFeatureExtractor::GetHistoryService(HistoryService** history) { 510 bool BrowserFeatureExtractor::GetHistoryService(HistoryService** history) {
457 *history = NULL; 511 *history = NULL;
458 if (tab_ && tab_->GetBrowserContext()) { 512 if (tab_ && tab_->GetBrowserContext()) {
459 Profile* profile = Profile::FromBrowserContext(tab_->GetBrowserContext()); 513 Profile* profile = Profile::FromBrowserContext(tab_->GetBrowserContext());
460 *history = HistoryServiceFactory::GetForProfile(profile, 514 *history = HistoryServiceFactory::GetForProfile(profile,
461 Profile::EXPLICIT_ACCESS); 515 Profile::EXPLICIT_ACCESS);
462 if (*history) { 516 if (*history) {
463 return true; 517 return true;
464 } 518 }
465 } 519 }
(...skipping 14 matching lines...) Expand all
480 // Limit the number of matched bad IPs in one request to control 534 // Limit the number of matched bad IPs in one request to control
481 // the request's size 535 // the request's size
482 if (matched_bad_ips >= kMaxMalwareIPPerRequest) { 536 if (matched_bad_ips >= kMaxMalwareIPPerRequest) {
483 break; 537 break;
484 } 538 }
485 } 539 }
486 callback.Run(true, request.Pass()); 540 callback.Run(true, request.Pass());
487 } 541 }
488 542
489 } // namespace safe_browsing 543 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698