Index: chrome/browser/safe_browsing/download_protection_service.cc |
diff --git a/chrome/browser/safe_browsing/download_protection_service.cc b/chrome/browser/safe_browsing/download_protection_service.cc |
index 71fa9c3e71d3638eec0041145ec6af4bdc6f01f0..957dd1a55aac455e7a16ed4291126a15963e3bfb 100644 |
--- a/chrome/browser/safe_browsing/download_protection_service.cc |
+++ b/chrome/browser/safe_browsing/download_protection_service.cc |
@@ -7,6 +7,7 @@ |
#include "base/bind.h" |
#include "base/format_macros.h" |
#include "base/memory/scoped_ptr.h" |
+#include "base/memory/weak_ptr.h" |
#include "base/metrics/histogram.h" |
#include "base/stl_util.h" |
#include "base/string_number_conversions.h" |
@@ -27,6 +28,10 @@ |
using content::BrowserThread; |
+namespace { |
+static const int64 kDownloadRequestTimeoutMs = 3000; |
+} // namespace |
+ |
namespace safe_browsing { |
const char DownloadProtectionService::kDownloadRequestUrl[] = |
@@ -144,7 +149,7 @@ DownloadProtectionService::DownloadInfo::FromDownloadItem( |
download_info.target_file = item.GetTargetFilePath(); |
download_info.download_url_chain = item.url_chain(); |
download_info.referrer_url = item.referrer_url(); |
- // TODO(bryner): Fill in the hash (we shouldn't compute it again) |
+ download_info.sha256_hash = item.hash(); |
download_info.total_bytes = item.total_bytes(); |
// TODO(bryner): Populate user_initiated |
return download_info; |
@@ -332,7 +337,9 @@ class DownloadProtectionService::CheckClientDownloadRequest |
service_(service), |
signature_util_(signature_util), |
sb_service_(sb_service), |
- pingback_enabled_(service_->enabled()) { |
+ pingback_enabled_(service_->enabled()), |
+ finished_(false), |
+ ALLOW_THIS_IN_INITIALIZER_LIST(timeout_weakptr_factory_(this)) { |
Brian Ryner
2011/11/17 20:25:30
#include "base/compiler_specific.h" for this macro
|
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
} |
@@ -373,24 +380,34 @@ class DownloadProtectionService::CheckClientDownloadRequest |
BrowserThread::FILE, |
FROM_HERE, |
base::Bind(&CheckClientDownloadRequest::ExtractFileFeatures, this)); |
+ |
+ // If the request takes too long we cancel it. |
+ BrowserThread::PostDelayedTask( |
+ BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&CheckClientDownloadRequest::Cancel, |
+ timeout_weakptr_factory_.GetWeakPtr()), |
+ service_->download_request_timeout_ms()); |
} |
- // Canceling a request will cause us to always report the result as SAFE. |
- // In addition, the DownloadProtectionService will not be notified when the |
- // request finishes, so it must drop its reference after calling Cancel. |
+ // Canceling a request will cause us to always report the result as SAFE |
+ // unless a pending request is about to call FinishRequest. |
void Cancel() { |
+ // Calling FinishRequest might delete this object if we don't keep a |
+ // reference around until Cancel() is finished running. |
+ scoped_refptr<CheckClientDownloadRequest> request(this); |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- service_ = NULL; |
+ FinishRequest(SAFE); |
if (fetcher_.get()) { |
// The DownloadProtectionService is going to release its reference, so we |
// might be destroyed before the URLFetcher completes. Cancel the |
// fetcher so it does not try to invoke OnURLFetchComplete. |
- FinishRequest(SAFE); |
fetcher_.reset(); |
} |
// Note: If there is no fetcher, then some callback is still holding a |
// reference to this object. We'll eventually wind up in some method on |
// the UI thread that will call FinishRequest() and run the callback. |
Brian Ryner
2011/11/17 20:25:30
nit: this comment is now a little out of date. Si
noelutz
2011/11/17 21:28:40
Done.
|
+ service_ = NULL; |
} |
// From the content::URLFetcherDelegate interface. |
@@ -430,6 +447,7 @@ class DownloadProtectionService::CheckClientDownloadRequest |
virtual ~CheckClientDownloadRequest() { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ timeout_weakptr_factory_.InvalidateWeakPtrs(); |
mattm
2011/11/17 21:43:34
the WeakPtrFactory destructor should do this alrea
noelutz
2011/11/17 21:46:06
Done.
|
} |
void ExtractFileFeatures() { |
@@ -552,6 +570,7 @@ class DownloadProtectionService::CheckClientDownloadRequest |
content::URLFetcher::POST, |
this)); |
fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE); |
+ fetcher_->SetAutomaticallyRetryOn5xx(false); // Don't retry on error. |
fetcher_->SetRequestContext(service_->request_context_getter_.get()); |
fetcher_->SetUploadData("application/octet-stream", request_data); |
fetcher_->Start(); |
@@ -566,6 +585,10 @@ class DownloadProtectionService::CheckClientDownloadRequest |
void FinishRequest(DownloadCheckResult result) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ if (finished_) { |
+ return; |
+ } |
+ finished_ = true; |
if (service_) { |
callback_.Run(result); |
service_->RequestFinished(this); |
@@ -589,6 +612,8 @@ class DownloadProtectionService::CheckClientDownloadRequest |
scoped_refptr<SafeBrowsingService> sb_service_; |
const bool pingback_enabled_; |
scoped_ptr<content::URLFetcher> fetcher_; |
+ bool finished_; |
+ base::WeakPtrFactory<CheckClientDownloadRequest> timeout_weakptr_factory_; |
DISALLOW_COPY_AND_ASSIGN(CheckClientDownloadRequest); |
}; |
@@ -599,7 +624,8 @@ DownloadProtectionService::DownloadProtectionService( |
: sb_service_(sb_service), |
request_context_getter_(request_context_getter), |
enabled_(false), |
- signature_util_(new SignatureUtil()) {} |
+ signature_util_(new SignatureUtil()), |
+ download_request_timeout_ms_(kDownloadRequestTimeoutMs) {} |
DownloadProtectionService::~DownloadProtectionService() { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
@@ -644,10 +670,13 @@ void DownloadProtectionService::CancelPendingRequests() { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
for (std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it = |
download_requests_.begin(); |
- it != download_requests_.end(); ++it) { |
- (*it)->Cancel(); |
+ it != download_requests_.end();) { |
+ // We need to advance the iterator before we cancel because canceling |
+ // the request will invalidate it when RequestFinished is called below. |
+ scoped_refptr<CheckClientDownloadRequest> tmp = *it++; |
+ tmp->Cancel(); |
} |
- download_requests_.clear(); |
+ DCHECK(download_requests_.empty()); |
} |
void DownloadProtectionService::RequestFinished( |