Index: chrome/browser/safe_browsing/download_protection_service.cc |
=================================================================== |
--- chrome/browser/safe_browsing/download_protection_service.cc (revision 106761) |
+++ chrome/browser/safe_browsing/download_protection_service.cc (working copy) |
@@ -8,7 +8,9 @@ |
#include "base/memory/scoped_ptr.h" |
#include "base/metrics/histogram.h" |
#include "base/stl_util.h" |
+#include "base/string_util.h" |
#include "chrome/browser/safe_browsing/safe_browsing_service.h" |
+#include "chrome/browser/safe_browsing/signature_util.h" |
#include "chrome/common/net/http_return.h" |
#include "chrome/common/safe_browsing/csd.pb.h" |
#include "content/browser/browser_thread.h" |
@@ -21,6 +23,14 @@ |
const char DownloadProtectionService::kDownloadRequestUrl[] = |
"https://sb-ssl.google.com/safebrowsing/clientreport/download"; |
+namespace { |
+bool IsBinaryFile(const FilePath& file) { |
+ return (file.MatchesExtension(FILE_PATH_LITERAL(".exe")) || |
+ file.MatchesExtension(FILE_PATH_LITERAL(".cab")) || |
+ file.MatchesExtension(FILE_PATH_LITERAL(".msi"))); |
+} |
+} // namespace |
+ |
DownloadProtectionService::DownloadInfo::DownloadInfo() |
: total_bytes(0), user_initiated(false) {} |
@@ -34,6 +44,7 @@ |
enabled_(false) {} |
DownloadProtectionService::~DownloadProtectionService() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
STLDeleteContainerPairFirstPointers(download_requests_.begin(), |
download_requests_.end()); |
download_requests_.clear(); |
@@ -45,7 +56,7 @@ |
BrowserThread::IO, |
FROM_HERE, |
base::Bind(&DownloadProtectionService::SetEnabledOnIOThread, |
- this, enabled)); |
+ base::Unretained(this), enabled)); |
noelutz
2011/10/22 00:41:46
I just want to make sure I follow the code here.
|
} |
void DownloadProtectionService::SetEnabledOnIOThread(bool enabled) { |
@@ -98,7 +109,7 @@ |
BrowserThread::UI, |
FROM_HERE, |
base::Bind(&DownloadProtectionService::EndCheckClientDownload, |
- this, SAFE, reason, callback)); |
+ base::Unretained(this), SAFE, reason, callback)); |
} else { |
NOTREACHED(); |
} |
@@ -120,6 +131,37 @@ |
RecordStats(REASON_INVALID_URL); |
return true; // For now we only support HTTP download URLs. |
} |
+ |
+ if (!IsBinaryFile(info.local_file)) { |
+ RecordStats(REASON_NOT_BINARY_FILE); |
+ return true; |
+ } |
+ |
+ // Compute features from the file contents. Note that we record histograms |
+ // based on the result, so this runs regardless of whether the pingbacks are |
+ // enabled. Since we do blocking I/O, this happens on the file thread. |
+ BrowserThread::PostTask( |
+ BrowserThread::FILE, |
+ FROM_HERE, |
+ base::Bind(&DownloadProtectionService::ExtractFileFeatures, |
+ base::Unretained(this), info, enabled_, callback)); |
noelutz
2011/10/22 00:41:46
I think there is a race condition here. You acces
|
+ return false; |
+} |
+ |
+void DownloadProtectionService::ExtractFileFeatures( |
+ const DownloadInfo& info, |
+ bool pingback_enabled, |
+ const CheckDownloadCallback& callback) { |
+ bool is_signed; |
+ if (safe_browsing::signature_util::IsSigned(info.local_file)) { |
+ VLOG(2) << "Downloaded a signed binary: " << info.local_file.value(); |
+ is_signed = true; |
+ } else { |
+ VLOG(2) << "Downloaded an unsigned binary: " << info.local_file.value(); |
+ is_signed = false; |
+ } |
+ UMA_HISTOGRAM_BOOLEAN("SBClientDownload.SignedBinaryDownload", is_signed); |
+ |
// TODO(noelutz): DownloadInfo should also contain the IP address of every |
// URL in the redirect chain. We also should check whether the download URL |
// is hosted on the internal network. |
@@ -127,20 +169,25 @@ |
BrowserThread::IO, |
FROM_HERE, |
base::Bind(&DownloadProtectionService::StartCheckClientDownload, |
- this, info, callback)); |
- return false; |
+ base::Unretained(this), info, pingback_enabled, callback)); |
} |
void DownloadProtectionService::StartCheckClientDownload( |
const DownloadInfo& info, |
+ bool pingback_enabled, |
const CheckDownloadCallback& callback) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- if (!enabled_ || !sb_service_.get()) { |
- // This is a hard fail. We won't even call the callback in this case. |
- RecordStats(REASON_SB_DISABLED); |
+ DownloadCheckResultReason reason = REASON_MAX; |
+ if (!enabled_ || !sb_service_) { |
+ reason = REASON_SB_DISABLED; |
+ RecordStats(reason); |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&DownloadProtectionService::EndCheckClientDownload, |
+ base::Unretained(this), SAFE, reason, callback)); |
noelutz
2011/10/22 00:41:46
Will this always work? What if the destructor is
|
return; |
} |
- DownloadCheckResultReason reason = REASON_MAX; |
for (size_t i = 0; i < info.download_url_chain.size(); ++i) { |
if (sb_service_->MatchDownloadWhitelistUrl(info.download_url_chain[i])) { |
reason = REASON_WHITELISTED_URL; |
@@ -180,7 +227,7 @@ |
BrowserThread::UI, |
FROM_HERE, |
base::Bind(&DownloadProtectionService::EndCheckClientDownload, |
- this, SAFE, reason, callback)); |
+ base::Unretained(this), SAFE, reason, callback)); |
noelutz
2011/10/22 00:41:46
same question as above.
|
return; |
} |