Chromium Code Reviews| 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_service.h" | 5 #include "chrome/browser/safe_browsing/client_side_detection_service.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 53 base::TimeDelta::FromDays(1); | 53 base::TimeDelta::FromDays(1); |
| 54 const base::TimeDelta ClientSideDetectionService::kPositiveCacheInterval = | 54 const base::TimeDelta ClientSideDetectionService::kPositiveCacheInterval = |
| 55 base::TimeDelta::FromMinutes(30); | 55 base::TimeDelta::FromMinutes(30); |
| 56 | 56 |
| 57 const char ClientSideDetectionService::kClientReportPhishingUrl[] = | 57 const char ClientSideDetectionService::kClientReportPhishingUrl[] = |
| 58 "https://sb-ssl.google.com/safebrowsing/clientreport/phishing"; | 58 "https://sb-ssl.google.com/safebrowsing/clientreport/phishing"; |
| 59 const char ClientSideDetectionService::kClientModelUrl[] = | 59 const char ClientSideDetectionService::kClientModelUrl[] = |
| 60 "https://ssl.gstatic.com/safebrowsing/csd/client_model_v4.pb"; | 60 "https://ssl.gstatic.com/safebrowsing/csd/client_model_v4.pb"; |
| 61 | 61 |
| 62 struct ClientSideDetectionService::ClientReportInfo { | 62 struct ClientSideDetectionService::ClientReportInfo { |
| 63 scoped_ptr<ClientReportPhishingRequestCallback> callback; | 63 ClientReportPhishingRequestCallback callback; |
| 64 GURL phishing_url; | 64 GURL phishing_url; |
| 65 }; | 65 }; |
| 66 | 66 |
| 67 ClientSideDetectionService::CacheState::CacheState(bool phish, base::Time time) | 67 ClientSideDetectionService::CacheState::CacheState(bool phish, base::Time time) |
| 68 : is_phishing(phish), | 68 : is_phishing(phish), |
| 69 timestamp(time) {} | 69 timestamp(time) {} |
| 70 | 70 |
| 71 ClientSideDetectionService::ClientSideDetectionService( | 71 ClientSideDetectionService::ClientSideDetectionService( |
| 72 net::URLRequestContextGetter* request_context_getter) | 72 net::URLRequestContextGetter* request_context_getter) |
| 73 : enabled_(false), | 73 : enabled_(false), |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 111 // We delay the first model fetch to avoid slowing down browser startup. | 111 // We delay the first model fetch to avoid slowing down browser startup. |
| 112 ScheduleFetchModel(kInitialClientModelFetchDelayMs); | 112 ScheduleFetchModel(kInitialClientModelFetchDelayMs); |
| 113 } else { | 113 } else { |
| 114 // Cancel pending requests. | 114 // Cancel pending requests. |
| 115 model_fetcher_.reset(); | 115 model_fetcher_.reset(); |
| 116 // Invoke pending callbacks with a false verdict. | 116 // Invoke pending callbacks with a false verdict. |
| 117 for (std::map<const content::URLFetcher*, ClientReportInfo*>::iterator it = | 117 for (std::map<const content::URLFetcher*, ClientReportInfo*>::iterator it = |
| 118 client_phishing_reports_.begin(); | 118 client_phishing_reports_.begin(); |
| 119 it != client_phishing_reports_.end(); ++it) { | 119 it != client_phishing_reports_.end(); ++it) { |
| 120 ClientReportInfo* info = it->second; | 120 ClientReportInfo* info = it->second; |
| 121 if (info->callback.get()) | 121 info->callback.Run(info->phishing_url, false); |
| 122 info->callback->Run(info->phishing_url, false); | |
| 123 } | 122 } |
| 124 STLDeleteContainerPairPointers(client_phishing_reports_.begin(), | 123 STLDeleteContainerPairPointers(client_phishing_reports_.begin(), |
| 125 client_phishing_reports_.end()); | 124 client_phishing_reports_.end()); |
| 126 client_phishing_reports_.clear(); | 125 client_phishing_reports_.clear(); |
| 127 cache_.clear(); | 126 cache_.clear(); |
| 128 } | 127 } |
| 129 } | 128 } |
| 130 | 129 |
| 131 void ClientSideDetectionService::SendClientReportPhishingRequest( | 130 void ClientSideDetectionService::SendClientReportPhishingRequest( |
| 132 ClientPhishingRequest* verdict, | 131 ClientPhishingRequest* verdict, |
| 133 ClientReportPhishingRequestCallback* callback) { | 132 const ClientReportPhishingRequestCallback& callback) { |
| 134 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 133 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 135 MessageLoop::current()->PostTask( | 134 MessageLoop::current()->PostTask( |
| 136 FROM_HERE, | 135 FROM_HERE, |
| 137 base::Bind(&ClientSideDetectionService::StartClientReportPhishingRequest, | 136 base::Bind(&ClientSideDetectionService::StartClientReportPhishingRequest, |
| 138 weak_factory_.GetWeakPtr(), verdict, callback)); | 137 weak_factory_.GetWeakPtr(), verdict, callback)); |
| 139 } | 138 } |
| 140 | 139 |
| 141 bool ClientSideDetectionService::IsPrivateIPAddress( | 140 bool ClientSideDetectionService::IsPrivateIPAddress( |
| 142 const std::string& ip_address) const { | 141 const std::string& ip_address) const { |
| 143 net::IPAddressNumber ip_number; | 142 net::IPAddressNumber ip_number; |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 280 delay_ms = model_max_age_->InMilliseconds(); | 279 delay_ms = model_max_age_->InMilliseconds(); |
| 281 } | 280 } |
| 282 model_max_age_.reset(); | 281 model_max_age_.reset(); |
| 283 | 282 |
| 284 // Schedule the next model reload. | 283 // Schedule the next model reload. |
| 285 ScheduleFetchModel(delay_ms); | 284 ScheduleFetchModel(delay_ms); |
| 286 } | 285 } |
| 287 | 286 |
| 288 void ClientSideDetectionService::StartClientReportPhishingRequest( | 287 void ClientSideDetectionService::StartClientReportPhishingRequest( |
| 289 ClientPhishingRequest* verdict, | 288 ClientPhishingRequest* verdict, |
| 290 ClientReportPhishingRequestCallback* callback) { | 289 const ClientReportPhishingRequestCallback& callback) { |
|
noelutz
2011/11/21 21:46:05
note: this callback can be null.
Scott Hess - ex-Googler
2011/11/21 22:15:20
That's odd. I'm sure I had reviewed the code and
noelutz
2011/11/21 22:24:00
Oh, if this code is safe then we're fine. In othe
| |
| 291 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 290 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 292 scoped_ptr<ClientPhishingRequest> request(verdict); | 291 scoped_ptr<ClientPhishingRequest> request(verdict); |
| 293 scoped_ptr<ClientReportPhishingRequestCallback> cb(callback); | |
| 294 | 292 |
| 295 if (!enabled_) { | 293 if (!enabled_) { |
| 296 if (cb.get()) | 294 callback.Run(GURL(request->url()), false); |
| 297 cb->Run(GURL(request->url()), false); | |
| 298 return; | 295 return; |
| 299 } | 296 } |
| 300 | 297 |
| 301 std::string request_data; | 298 std::string request_data; |
| 302 if (!request->SerializeToString(&request_data)) { | 299 if (!request->SerializeToString(&request_data)) { |
| 303 UMA_HISTOGRAM_COUNTS("SBClientPhishing.RequestNotSerialized", 1); | 300 UMA_HISTOGRAM_COUNTS("SBClientPhishing.RequestNotSerialized", 1); |
| 304 VLOG(1) << "Unable to serialize the CSD request. Proto file changed?"; | 301 VLOG(1) << "Unable to serialize the CSD request. Proto file changed?"; |
| 305 if (cb.get()) { | 302 callback.Run(GURL(request->url()), false); |
| 306 cb->Run(GURL(request->url()), false); | |
| 307 } | |
| 308 return; | 303 return; |
| 309 } | 304 } |
| 310 | 305 |
| 311 content::URLFetcher* fetcher = content::URLFetcher::Create( | 306 content::URLFetcher* fetcher = content::URLFetcher::Create( |
| 312 0 /* ID used for testing */, GURL(kClientReportPhishingUrl), | 307 0 /* ID used for testing */, GURL(kClientReportPhishingUrl), |
| 313 content::URLFetcher::POST, this); | 308 content::URLFetcher::POST, this); |
| 314 | 309 |
| 315 // Remember which callback and URL correspond to the current fetcher object. | 310 // Remember which callback and URL correspond to the current fetcher object. |
| 316 ClientReportInfo* info = new ClientReportInfo; | 311 ClientReportInfo* info = new ClientReportInfo; |
| 317 info->callback.swap(cb); // takes ownership of the callback. | 312 info->callback = callback; |
| 318 info->phishing_url = GURL(request->url()); | 313 info->phishing_url = GURL(request->url()); |
| 319 client_phishing_reports_[fetcher] = info; | 314 client_phishing_reports_[fetcher] = info; |
| 320 | 315 |
| 321 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE); | 316 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE); |
| 322 fetcher->SetRequestContext(request_context_getter_.get()); | 317 fetcher->SetRequestContext(request_context_getter_.get()); |
| 323 fetcher->SetUploadData("application/octet-stream", request_data); | 318 fetcher->SetUploadData("application/octet-stream", request_data); |
| 324 fetcher->Start(); | 319 fetcher->Start(); |
| 325 | 320 |
| 326 // Record that we made a request | 321 // Record that we made a request |
| 327 phishing_report_times_.push(base::Time::Now()); | 322 phishing_report_times_.push(base::Time::Now()); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 383 // Cache response, possibly flushing an old one. | 378 // Cache response, possibly flushing an old one. |
| 384 cache_[info->phishing_url] = | 379 cache_[info->phishing_url] = |
| 385 make_linked_ptr(new CacheState(response.phishy(), base::Time::Now())); | 380 make_linked_ptr(new CacheState(response.phishy(), base::Time::Now())); |
| 386 is_phishing = (response.phishy() && | 381 is_phishing = (response.phishy() && |
| 387 !IsFalsePositiveResponse(info->phishing_url, response)); | 382 !IsFalsePositiveResponse(info->phishing_url, response)); |
| 388 } else { | 383 } else { |
| 389 DLOG(ERROR) << "Unable to get the server verdict for URL: " | 384 DLOG(ERROR) << "Unable to get the server verdict for URL: " |
| 390 << info->phishing_url << " status: " << status.status() << " " | 385 << info->phishing_url << " status: " << status.status() << " " |
| 391 << "response_code:" << response_code; | 386 << "response_code:" << response_code; |
| 392 } | 387 } |
| 393 if (info->callback.get()) { | 388 info->callback.Run(info->phishing_url, is_phishing); |
| 394 info->callback->Run(info->phishing_url, is_phishing); | |
| 395 } | |
| 396 client_phishing_reports_.erase(source); | 389 client_phishing_reports_.erase(source); |
| 397 delete source; | 390 delete source; |
| 398 } | 391 } |
| 399 | 392 |
| 400 bool ClientSideDetectionService::IsInCache(const GURL& url) { | 393 bool ClientSideDetectionService::IsInCache(const GURL& url) { |
| 401 UpdateCache(); | 394 UpdateCache(); |
| 402 | 395 |
| 403 return cache_.find(url) != cache_.end(); | 396 return cache_.find(url) != cache_.end(); |
| 404 } | 397 } |
| 405 | 398 |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 575 &whitelist_patterns); | 568 &whitelist_patterns); |
| 576 for (size_t j = 0; j < whitelist_patterns.size(); ++j) { | 569 for (size_t j = 0; j < whitelist_patterns.size(); ++j) { |
| 577 if (whitelist_patterns[j] == canonical_url_as_pattern) { | 570 if (whitelist_patterns[j] == canonical_url_as_pattern) { |
| 578 return true; | 571 return true; |
| 579 } | 572 } |
| 580 } | 573 } |
| 581 } | 574 } |
| 582 return false; | 575 return false; |
| 583 } | 576 } |
| 584 } // namespace safe_browsing | 577 } // namespace safe_browsing |
| OLD | NEW |