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/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" |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 ClientSideDetectionService* service) | 111 ClientSideDetectionService* service) |
112 : tab_(tab), | 112 : tab_(tab), |
113 service_(service), | 113 service_(service), |
114 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { | 114 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
115 DCHECK(tab); | 115 DCHECK(tab); |
116 } | 116 } |
117 | 117 |
118 BrowserFeatureExtractor::~BrowserFeatureExtractor() { | 118 BrowserFeatureExtractor::~BrowserFeatureExtractor() { |
119 weak_factory_.InvalidateWeakPtrs(); | 119 weak_factory_.InvalidateWeakPtrs(); |
120 // Delete all the pending extractions (delete callback and request objects). | 120 // Delete all the pending extractions (delete callback and request objects). |
121 STLDeleteContainerPairPointers(pending_extractions_.begin(), | 121 STLDeleteContainerPairFirstPointers(pending_extractions_.begin(), |
122 pending_extractions_.end()); | 122 pending_extractions_.end()); |
| 123 |
123 // Also cancel all the pending history service queries. | 124 // Also cancel all the pending history service queries. |
124 HistoryService* history; | 125 HistoryService* history; |
125 bool success = GetHistoryService(&history); | 126 bool success = GetHistoryService(&history); |
126 DCHECK(success || pending_queries_.size() == 0); | 127 DCHECK(success || pending_queries_.size() == 0); |
127 // Cancel all the pending history lookups and cleanup the memory. | 128 // Cancel all the pending history lookups and cleanup the memory. |
128 for (PendingQueriesMap::iterator it = pending_queries_.begin(); | 129 for (PendingQueriesMap::iterator it = pending_queries_.begin(); |
129 it != pending_queries_.end(); ++it) { | 130 it != pending_queries_.end(); ++it) { |
130 if (history) { | 131 if (history) { |
131 history->CancelRequest(it->first); | 132 history->CancelRequest(it->first); |
132 } | 133 } |
133 ExtractionData& extraction = it->second; | 134 ExtractionData& extraction = it->second; |
134 delete extraction.first; // delete request | 135 delete extraction.first; // delete request |
135 delete extraction.second; // delete callback | |
136 } | 136 } |
137 pending_queries_.clear(); | 137 pending_queries_.clear(); |
138 } | 138 } |
139 | 139 |
140 void BrowserFeatureExtractor::ExtractFeatures(const BrowseInfo* info, | 140 void BrowserFeatureExtractor::ExtractFeatures(const BrowseInfo* info, |
141 ClientPhishingRequest* request, | 141 ClientPhishingRequest* request, |
142 DoneCallback* callback) { | 142 const DoneCallback& callback) { |
143 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 143 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
144 DCHECK(request); | 144 DCHECK(request); |
145 DCHECK(info); | 145 DCHECK(info); |
146 DCHECK_EQ(0U, request->url().find("http:")); | 146 DCHECK_EQ(0U, request->url().find("http:")); |
147 DCHECK(callback); | 147 DCHECK(!callback.is_null()); |
148 if (!callback) { | 148 if (callback.is_null()) { |
149 DLOG(ERROR) << "ExtractFeatures called without a callback object"; | 149 DLOG(ERROR) << "ExtractFeatures called without a callback object"; |
150 return; | 150 return; |
151 } | 151 } |
152 | 152 |
153 // Extract features pertaining to this navigation. | 153 // Extract features pertaining to this navigation. |
154 const NavigationController& controller = tab_->controller(); | 154 const NavigationController& controller = tab_->controller(); |
155 int url_index = -1; | 155 int url_index = -1; |
156 int first_host_index = -1; | 156 int first_host_index = -1; |
157 | 157 |
158 GURL request_url(request->url()); | 158 GURL request_url(request->url()); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 } | 191 } |
192 if (first_host_index != -1) { | 192 if (first_host_index != -1) { |
193 AddNavigationFeatures(features::kHostPrefix, | 193 AddNavigationFeatures(features::kHostPrefix, |
194 controller, | 194 controller, |
195 first_host_index, | 195 first_host_index, |
196 info->host_redirects, | 196 info->host_redirects, |
197 request); | 197 request); |
198 } | 198 } |
199 | 199 |
200 ExtractBrowseInfoFeatures(*info, request); | 200 ExtractBrowseInfoFeatures(*info, request); |
201 pending_extractions_.insert(std::make_pair(request, callback)); | 201 pending_extractions_[request] = callback; |
202 MessageLoop::current()->PostTask( | 202 MessageLoop::current()->PostTask( |
203 FROM_HERE, | 203 FROM_HERE, |
204 base::Bind(&BrowserFeatureExtractor::StartExtractFeatures, | 204 base::Bind(&BrowserFeatureExtractor::StartExtractFeatures, |
205 weak_factory_.GetWeakPtr(), request, callback)); | 205 weak_factory_.GetWeakPtr(), request, callback)); |
206 } | 206 } |
207 | 207 |
208 void BrowserFeatureExtractor::ExtractBrowseInfoFeatures( | 208 void BrowserFeatureExtractor::ExtractBrowseInfoFeatures( |
209 const BrowseInfo& info, | 209 const BrowseInfo& info, |
210 ClientPhishingRequest* request) { | 210 ClientPhishingRequest* request) { |
211 if (service_) { | 211 if (service_) { |
(...skipping 21 matching lines...) Expand all Loading... |
233 static_cast<double>(info.unsafe_resource->threat_type), | 233 static_cast<double>(info.unsafe_resource->threat_type), |
234 request); | 234 request); |
235 } | 235 } |
236 if (info.http_status_code != 0) { | 236 if (info.http_status_code != 0) { |
237 AddFeature(features::kHttpStatusCode, info.http_status_code, request); | 237 AddFeature(features::kHttpStatusCode, info.http_status_code, request); |
238 } | 238 } |
239 } | 239 } |
240 | 240 |
241 void BrowserFeatureExtractor::StartExtractFeatures( | 241 void BrowserFeatureExtractor::StartExtractFeatures( |
242 ClientPhishingRequest* request, | 242 ClientPhishingRequest* request, |
243 DoneCallback* callback) { | 243 const DoneCallback& callback) { |
244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
245 ExtractionData extraction = std::make_pair(request, callback); | 245 size_t removed = pending_extractions_.erase(request); |
246 size_t removed = pending_extractions_.erase(extraction); | |
247 DCHECK_EQ(1U, removed); | 246 DCHECK_EQ(1U, removed); |
248 HistoryService* history; | 247 HistoryService* history; |
249 if (!request || !request->IsInitialized() || !GetHistoryService(&history)) { | 248 if (!request || !request->IsInitialized() || !GetHistoryService(&history)) { |
250 callback->Run(false, request); | 249 callback.Run(false, request); |
251 delete callback; | |
252 return; | 250 return; |
253 } | 251 } |
254 CancelableRequestProvider::Handle handle = history->QueryURL( | 252 CancelableRequestProvider::Handle handle = history->QueryURL( |
255 GURL(request->url()), | 253 GURL(request->url()), |
256 true /* wants_visits */, | 254 true /* wants_visits */, |
257 &request_consumer_, | 255 &request_consumer_, |
258 base::Bind(&BrowserFeatureExtractor::QueryUrlHistoryDone, | 256 base::Bind(&BrowserFeatureExtractor::QueryUrlHistoryDone, |
259 base::Unretained(this))); | 257 base::Unretained(this))); |
260 | 258 |
261 StorePendingQuery(handle, request, callback); | 259 StorePendingQuery(handle, request, callback); |
262 } | 260 } |
263 | 261 |
264 void BrowserFeatureExtractor::QueryUrlHistoryDone( | 262 void BrowserFeatureExtractor::QueryUrlHistoryDone( |
265 CancelableRequestProvider::Handle handle, | 263 CancelableRequestProvider::Handle handle, |
266 bool success, | 264 bool success, |
267 const history::URLRow* row, | 265 const history::URLRow* row, |
268 history::VisitVector* visits) { | 266 history::VisitVector* visits) { |
269 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
270 ClientPhishingRequest* request; | 268 ClientPhishingRequest* request; |
271 DoneCallback* callback; | 269 DoneCallback callback; |
272 if (!GetPendingQuery(handle, &request, &callback)) { | 270 if (!GetPendingQuery(handle, &request, &callback)) { |
273 DLOG(FATAL) << "No pending history query found"; | 271 DLOG(FATAL) << "No pending history query found"; |
274 return; | 272 return; |
275 } | 273 } |
276 DCHECK(request); | 274 DCHECK(request); |
277 DCHECK(callback); | 275 DCHECK(!callback.is_null()); |
278 if (!success) { | 276 if (!success) { |
279 // URL is not found in the history. In practice this should not | 277 // URL is not found in the history. In practice this should not |
280 // happen (unless there is a real error) because we just visited | 278 // happen (unless there is a real error) because we just visited |
281 // that URL. | 279 // that URL. |
282 callback->Run(false, request); | 280 callback.Run(false, request); |
283 delete callback; | |
284 return; | 281 return; |
285 } | 282 } |
286 AddFeature(features::kUrlHistoryVisitCount, | 283 AddFeature(features::kUrlHistoryVisitCount, |
287 static_cast<double>(row->visit_count()), | 284 static_cast<double>(row->visit_count()), |
288 request); | 285 request); |
289 | 286 |
290 base::Time threshold = base::Time::Now() - base::TimeDelta::FromDays(1); | 287 base::Time threshold = base::Time::Now() - base::TimeDelta::FromDays(1); |
291 int num_visits_24h_ago = 0; | 288 int num_visits_24h_ago = 0; |
292 int num_visits_typed = 0; | 289 int num_visits_typed = 0; |
293 int num_visits_link = 0; | 290 int num_visits_link = 0; |
(...skipping 19 matching lines...) Expand all Loading... |
313 AddFeature(features::kUrlHistoryTypedCount, | 310 AddFeature(features::kUrlHistoryTypedCount, |
314 static_cast<double>(num_visits_typed), | 311 static_cast<double>(num_visits_typed), |
315 request); | 312 request); |
316 AddFeature(features::kUrlHistoryLinkCount, | 313 AddFeature(features::kUrlHistoryLinkCount, |
317 static_cast<double>(num_visits_link), | 314 static_cast<double>(num_visits_link), |
318 request); | 315 request); |
319 | 316 |
320 // Issue next history lookup for host visits. | 317 // Issue next history lookup for host visits. |
321 HistoryService* history; | 318 HistoryService* history; |
322 if (!GetHistoryService(&history)) { | 319 if (!GetHistoryService(&history)) { |
323 callback->Run(false, request); | 320 callback.Run(false, request); |
324 delete callback; | |
325 return; | 321 return; |
326 } | 322 } |
327 CancelableRequestProvider::Handle next_handle = | 323 CancelableRequestProvider::Handle next_handle = |
328 history->GetVisibleVisitCountToHost( | 324 history->GetVisibleVisitCountToHost( |
329 GURL(request->url()), | 325 GURL(request->url()), |
330 &request_consumer_, | 326 &request_consumer_, |
331 base::Bind(&BrowserFeatureExtractor::QueryHttpHostVisitsDone, | 327 base::Bind(&BrowserFeatureExtractor::QueryHttpHostVisitsDone, |
332 base::Unretained(this))); | 328 base::Unretained(this))); |
333 StorePendingQuery(next_handle, request, callback); | 329 StorePendingQuery(next_handle, request, callback); |
334 } | 330 } |
335 | 331 |
336 void BrowserFeatureExtractor::QueryHttpHostVisitsDone( | 332 void BrowserFeatureExtractor::QueryHttpHostVisitsDone( |
337 CancelableRequestProvider::Handle handle, | 333 CancelableRequestProvider::Handle handle, |
338 bool success, | 334 bool success, |
339 int num_visits, | 335 int num_visits, |
340 base::Time first_visit) { | 336 base::Time first_visit) { |
341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 337 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
342 ClientPhishingRequest* request; | 338 ClientPhishingRequest* request; |
343 DoneCallback* callback; | 339 DoneCallback callback; |
344 if (!GetPendingQuery(handle, &request, &callback)) { | 340 if (!GetPendingQuery(handle, &request, &callback)) { |
345 DLOG(FATAL) << "No pending history query found"; | 341 DLOG(FATAL) << "No pending history query found"; |
346 return; | 342 return; |
347 } | 343 } |
348 DCHECK(request); | 344 DCHECK(request); |
349 DCHECK(callback); | 345 DCHECK(!callback.is_null()); |
350 if (!success) { | 346 if (!success) { |
351 callback->Run(false, request); | 347 callback.Run(false, request); |
352 delete callback; | |
353 return; | 348 return; |
354 } | 349 } |
355 SetHostVisitsFeatures(num_visits, first_visit, true, request); | 350 SetHostVisitsFeatures(num_visits, first_visit, true, request); |
356 | 351 |
357 // Same lookup but for the HTTPS URL. | 352 // Same lookup but for the HTTPS URL. |
358 HistoryService* history; | 353 HistoryService* history; |
359 if (!GetHistoryService(&history)) { | 354 if (!GetHistoryService(&history)) { |
360 callback->Run(false, request); | 355 callback.Run(false, request); |
361 delete callback; | |
362 return; | 356 return; |
363 } | 357 } |
364 std::string https_url = request->url(); | 358 std::string https_url = request->url(); |
365 CancelableRequestProvider::Handle next_handle = | 359 CancelableRequestProvider::Handle next_handle = |
366 history->GetVisibleVisitCountToHost( | 360 history->GetVisibleVisitCountToHost( |
367 GURL(https_url.replace(0, 5, "https:")), | 361 GURL(https_url.replace(0, 5, "https:")), |
368 &request_consumer_, | 362 &request_consumer_, |
369 base::Bind(&BrowserFeatureExtractor::QueryHttpsHostVisitsDone, | 363 base::Bind(&BrowserFeatureExtractor::QueryHttpsHostVisitsDone, |
370 base::Unretained(this))); | 364 base::Unretained(this))); |
371 StorePendingQuery(next_handle, request, callback); | 365 StorePendingQuery(next_handle, request, callback); |
372 } | 366 } |
373 | 367 |
374 void BrowserFeatureExtractor::QueryHttpsHostVisitsDone( | 368 void BrowserFeatureExtractor::QueryHttpsHostVisitsDone( |
375 CancelableRequestProvider::Handle handle, | 369 CancelableRequestProvider::Handle handle, |
376 bool success, | 370 bool success, |
377 int num_visits, | 371 int num_visits, |
378 base::Time first_visit) { | 372 base::Time first_visit) { |
379 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 373 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
380 ClientPhishingRequest* request; | 374 ClientPhishingRequest* request; |
381 DoneCallback* callback; | 375 DoneCallback callback; |
382 if (!GetPendingQuery(handle, &request, &callback)) { | 376 if (!GetPendingQuery(handle, &request, &callback)) { |
383 DLOG(FATAL) << "No pending history query found"; | 377 DLOG(FATAL) << "No pending history query found"; |
384 return; | 378 return; |
385 } | 379 } |
386 DCHECK(request); | 380 DCHECK(request); |
387 DCHECK(callback); | 381 DCHECK(!callback.is_null()); |
388 if (!success) { | 382 if (!success) { |
389 callback->Run(false, request); | 383 callback.Run(false, request); |
390 delete callback; | |
391 return; | 384 return; |
392 } | 385 } |
393 SetHostVisitsFeatures(num_visits, first_visit, false, request); | 386 SetHostVisitsFeatures(num_visits, first_visit, false, request); |
394 callback->Run(true, request); // We're done with all the history lookups. | 387 callback.Run(true, request); // We're done with all the history lookups. |
395 delete callback; | |
396 } | 388 } |
397 | 389 |
398 void BrowserFeatureExtractor::SetHostVisitsFeatures( | 390 void BrowserFeatureExtractor::SetHostVisitsFeatures( |
399 int num_visits, | 391 int num_visits, |
400 base::Time first_visit, | 392 base::Time first_visit, |
401 bool is_http_query, | 393 bool is_http_query, |
402 ClientPhishingRequest* request) { | 394 ClientPhishingRequest* request) { |
403 DCHECK(request); | 395 DCHECK(request); |
404 AddFeature(is_http_query ? | 396 AddFeature(is_http_query ? |
405 features::kHttpHostVisitCount : features::kHttpsHostVisitCount, | 397 features::kHttpHostVisitCount : features::kHttpsHostVisitCount, |
406 static_cast<double>(num_visits), | 398 static_cast<double>(num_visits), |
407 request); | 399 request); |
408 if (num_visits > 0) { | 400 if (num_visits > 0) { |
409 AddFeature( | 401 AddFeature( |
410 is_http_query ? | 402 is_http_query ? |
411 features::kFirstHttpHostVisitMoreThan24hAgo : | 403 features::kFirstHttpHostVisitMoreThan24hAgo : |
412 features::kFirstHttpsHostVisitMoreThan24hAgo, | 404 features::kFirstHttpsHostVisitMoreThan24hAgo, |
413 (first_visit < (base::Time::Now() - base::TimeDelta::FromDays(1))) ? | 405 (first_visit < (base::Time::Now() - base::TimeDelta::FromDays(1))) ? |
414 1.0 : 0.0, | 406 1.0 : 0.0, |
415 request); | 407 request); |
416 } | 408 } |
417 } | 409 } |
418 | 410 |
419 void BrowserFeatureExtractor::StorePendingQuery( | 411 void BrowserFeatureExtractor::StorePendingQuery( |
420 CancelableRequestProvider::Handle handle, | 412 CancelableRequestProvider::Handle handle, |
421 ClientPhishingRequest* request, | 413 ClientPhishingRequest* request, |
422 DoneCallback* callback) { | 414 const DoneCallback& callback) { |
423 DCHECK_EQ(0U, pending_queries_.count(handle)); | 415 DCHECK_EQ(0U, pending_queries_.count(handle)); |
424 pending_queries_[handle] = std::make_pair(request, callback); | 416 pending_queries_[handle] = std::make_pair(request, callback); |
425 } | 417 } |
426 | 418 |
427 bool BrowserFeatureExtractor::GetPendingQuery( | 419 bool BrowserFeatureExtractor::GetPendingQuery( |
428 CancelableRequestProvider::Handle handle, | 420 CancelableRequestProvider::Handle handle, |
429 ClientPhishingRequest** request, | 421 ClientPhishingRequest** request, |
430 DoneCallback** callback) { | 422 DoneCallback* callback) { |
431 PendingQueriesMap::iterator it = pending_queries_.find(handle); | 423 PendingQueriesMap::iterator it = pending_queries_.find(handle); |
432 DCHECK(it != pending_queries_.end()); | 424 DCHECK(it != pending_queries_.end()); |
433 if (it != pending_queries_.end()) { | 425 if (it != pending_queries_.end()) { |
434 *request = it->second.first; | 426 *request = it->second.first; |
435 *callback = it->second.second; | 427 *callback = it->second.second; |
436 pending_queries_.erase(it); | 428 pending_queries_.erase(it); |
437 return true; | 429 return true; |
438 } | 430 } |
439 return false; | 431 return false; |
440 } | 432 } |
441 | 433 |
442 bool BrowserFeatureExtractor::GetHistoryService(HistoryService** history) { | 434 bool BrowserFeatureExtractor::GetHistoryService(HistoryService** history) { |
443 *history = NULL; | 435 *history = NULL; |
444 if (tab_ && tab_->browser_context()) { | 436 if (tab_ && tab_->browser_context()) { |
445 Profile* profile = Profile::FromBrowserContext(tab_->browser_context()); | 437 Profile* profile = Profile::FromBrowserContext(tab_->browser_context()); |
446 *history = profile->GetHistoryService(Profile::EXPLICIT_ACCESS); | 438 *history = profile->GetHistoryService(Profile::EXPLICIT_ACCESS); |
447 if (*history) { | 439 if (*history) { |
448 return true; | 440 return true; |
449 } | 441 } |
450 } | 442 } |
451 VLOG(2) << "Unable to query history. No history service available."; | 443 VLOG(2) << "Unable to query history. No history service available."; |
452 return false; | 444 return false; |
453 } | 445 } |
454 | 446 |
455 } // namespace safe_browsing | 447 } // namespace safe_browsing |
OLD | NEW |