Chromium Code Reviews| 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 |