Index: chrome/browser/safe_browsing/download_feedback_service.cc |
diff --git a/chrome/browser/safe_browsing/download_feedback_service.cc b/chrome/browser/safe_browsing/download_feedback_service.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4b4c6fee86082486f00296da65d15ae3f254e457 |
--- /dev/null |
+++ b/chrome/browser/safe_browsing/download_feedback_service.cc |
@@ -0,0 +1,190 @@ |
+// Copyright 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/safe_browsing/download_feedback_service.h" |
+ |
+#include "base/bind.h" |
+#include "base/command_line.h" |
+#include "base/files/file_path.h" |
+#include "base/metrics/histogram.h" |
+#include "base/stl_util.h" |
+#include "base/supports_user_data.h" |
+#include "base/task_runner.h" |
+#include "chrome/browser/safe_browsing/download_feedback.h" |
+#include "chrome/common/chrome_switches.h" |
+#include "chrome/common/chrome_version_info.h" |
+#include "content/public/browser/download_danger_type.h" |
+#include "content/public/browser/download_item.h" |
+ |
+namespace safe_browsing { |
+ |
+namespace { |
+ |
+const void* kPingKey = &kPingKey; |
+ |
+bool IsEnabled() { |
+ CommandLine* cmdline = CommandLine::ForCurrentProcess(); |
+ if (cmdline->HasSwitch(switches::kSbEnableDownloadFeedback)) |
+ return true; |
+ |
+ chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); |
+ if (channel == chrome::VersionInfo::CHANNEL_UNKNOWN || |
+ channel == chrome::VersionInfo::CHANNEL_CANARY || |
+ channel == chrome::VersionInfo::CHANNEL_DEV) |
+ return true; |
+ |
+ return false; |
+} |
+ |
+class DownloadFeedbackPings : public base::SupportsUserData::Data { |
+ public: |
+ DownloadFeedbackPings(const std::string& ping_request, |
+ const std::string& ping_response); |
+ |
+ // Stores the ping data in the given |download|. |
+ static void CreateForDownload(content::DownloadItem* download, |
+ const std::string& ping_request, |
+ const std::string& ping_response); |
+ |
+ // Returns the DownloadFeedbackPings object associated with |download|. May |
+ // return NULL. |
+ static DownloadFeedbackPings* FromDownload( |
+ const content::DownloadItem& download); |
+ |
+ |
+ const std::string& ping_request() const { |
+ return ping_request_; |
+ } |
+ |
+ const std::string& ping_response() const { |
+ return ping_response_; |
+ } |
+ |
+ private: |
+ std::string ping_request_; |
+ std::string ping_response_; |
+}; |
+ |
+DownloadFeedbackPings::DownloadFeedbackPings(const std::string& ping_request, |
+ const std::string& ping_response) |
+ : ping_request_(ping_request), |
+ ping_response_(ping_response) { |
+} |
+ |
+// static |
+void DownloadFeedbackPings::CreateForDownload( |
+ content::DownloadItem* download, |
+ const std::string& ping_request, |
+ const std::string& ping_response) { |
+ DownloadFeedbackPings* pings = new DownloadFeedbackPings(ping_request, |
+ ping_response); |
+ download->SetUserData(kPingKey, pings); |
+} |
+ |
+// static |
+DownloadFeedbackPings* DownloadFeedbackPings::FromDownload( |
+ const content::DownloadItem& download) { |
+ return static_cast<DownloadFeedbackPings*>(download.GetUserData(kPingKey)); |
+} |
+ |
+} // namespace |
+ |
+DownloadFeedbackService::DownloadFeedbackService( |
+ net::URLRequestContextGetter* request_context_getter, |
+ base::TaskRunner* file_task_runner) |
+ : request_context_getter_(request_context_getter), |
+ file_task_runner_(file_task_runner), |
+ weak_ptr_factory_(this) { |
+} |
+ |
+DownloadFeedbackService::~DownloadFeedbackService() { |
+ DCHECK(CalledOnValidThread()); |
+ STLDeleteContainerPointers(active_feedback_.begin(), active_feedback_.end()); |
+} |
+ |
+// static |
+void DownloadFeedbackService::MaybeStorePingsForDownload( |
+ DownloadProtectionService::DownloadCheckResult result, |
+ content::DownloadItem* download, |
+ const std::string& ping, |
+ const std::string& response) { |
+ if (!IsEnabled() || !(result == DownloadProtectionService::UNCOMMON || |
+ result == DownloadProtectionService::DANGEROUS_HOST)) |
+ return; |
+ UMA_HISTOGRAM_COUNTS("SBDownloadFeedback.SizeEligibleKB", |
+ download->GetReceivedBytes() / 1024); |
+ if (download->GetReceivedBytes() > DownloadFeedback::kMaxUploadSize) |
+ return; |
+ |
+ DownloadFeedbackPings::CreateForDownload(download, ping, response); |
+} |
+ |
+// static |
+bool DownloadFeedbackService::IsEnabledForDownload( |
+ const content::DownloadItem& download) { |
+ return !!DownloadFeedbackPings::FromDownload(download); |
+} |
+ |
+// static |
+bool DownloadFeedbackService::GetPingsForDownloadForTesting( |
+ const content::DownloadItem& download, |
+ std::string* ping, |
+ std::string* response) { |
+ DownloadFeedbackPings* pings = DownloadFeedbackPings::FromDownload(download); |
+ if (!pings) |
+ return false; |
+ |
+ *ping = pings->ping_request(); |
+ *response = pings->ping_response(); |
+ return true; |
+} |
+ |
+// static |
+void DownloadFeedbackService::RecordFeedbackButtonShown( |
+ content::DownloadDangerType danger_type) { |
+ UMA_HISTOGRAM_ENUMERATION("SBDownloadFeedback.Shown", |
+ danger_type, |
+ content::DOWNLOAD_DANGER_TYPE_MAX); |
+} |
+ |
+ |
+void DownloadFeedbackService::BeginFeedbackForDownload( |
+ content::DownloadItem* download) { |
+ DCHECK(CalledOnValidThread()); |
+ |
+ UMA_HISTOGRAM_ENUMERATION("SBDownloadFeedback.Activations", |
+ download->GetDangerType(), |
+ content::DOWNLOAD_DANGER_TYPE_MAX); |
+ |
+ DownloadFeedbackPings* pings = DownloadFeedbackPings::FromDownload(*download); |
+ DCHECK(pings); |
+ |
+ download->StealDangerousDownload( |
+ base::Bind(&DownloadFeedbackService::BeginFeedback, |
+ weak_ptr_factory_.GetWeakPtr(), |
asanka
2013/06/03 16:18:32
When would the service be destroyed?
StealDangero
mattm
2013/06/07 03:09:02
On shutdown.
asanka
2013/06/07 15:39:58
Thanks. The handover should be happening in respon
|
+ pings->ping_request(), |
+ pings->ping_response())); |
+} |
+ |
+void DownloadFeedbackService::BeginFeedback( |
+ const std::string& ping_request, |
+ const std::string& ping_response, |
+ const base::FilePath& path) { |
+ DCHECK(CalledOnValidThread()); |
+ DownloadFeedback* feedback = DownloadFeedback::Create( |
+ request_context_getter_, file_task_runner_, path, |
+ ping_request, ping_response); |
+ active_feedback_.insert(feedback); |
+ feedback->Start(base::Bind(&DownloadFeedbackService::FeedbackComplete, |
+ base::Unretained(this), feedback)); |
+} |
+ |
+void DownloadFeedbackService::FeedbackComplete(DownloadFeedback* feedback) { |
+ DVLOG(1) << __FUNCTION__; |
+ DCHECK(CalledOnValidThread()); |
+ active_feedback_.erase(feedback); |
+ delete feedback; |
+} |
+ |
+} // namespace safe_browsing |