Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / safe_browsing / download_feedback_service.cc
blob04951cd08227701b2faabf39f31d5eeccec67cec
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/safe_browsing/download_feedback_service.h"
7 #include "base/bind.h"
8 #include "base/files/file_path.h"
9 #include "base/files/file_util_proxy.h"
10 #include "base/metrics/histogram.h"
11 #include "base/supports_user_data.h"
12 #include "base/task_runner.h"
13 #include "chrome/browser/safe_browsing/download_feedback.h"
14 #include "content/public/browser/download_danger_type.h"
15 #include "content/public/browser/download_item.h"
17 namespace safe_browsing {
19 namespace {
21 const void* kPingKey = &kPingKey;
23 class DownloadFeedbackPings : public base::SupportsUserData::Data {
24 public:
25 DownloadFeedbackPings(const std::string& ping_request,
26 const std::string& ping_response);
28 // Stores the ping data in the given |download|.
29 static void CreateForDownload(content::DownloadItem* download,
30 const std::string& ping_request,
31 const std::string& ping_response);
33 // Returns the DownloadFeedbackPings object associated with |download|. May
34 // return NULL.
35 static DownloadFeedbackPings* FromDownload(
36 const content::DownloadItem& download);
39 const std::string& ping_request() const {
40 return ping_request_;
43 const std::string& ping_response() const {
44 return ping_response_;
47 private:
48 std::string ping_request_;
49 std::string ping_response_;
52 DownloadFeedbackPings::DownloadFeedbackPings(const std::string& ping_request,
53 const std::string& ping_response)
54 : ping_request_(ping_request),
55 ping_response_(ping_response) {
58 // static
59 void DownloadFeedbackPings::CreateForDownload(
60 content::DownloadItem* download,
61 const std::string& ping_request,
62 const std::string& ping_response) {
63 DownloadFeedbackPings* pings = new DownloadFeedbackPings(ping_request,
64 ping_response);
65 download->SetUserData(kPingKey, pings);
68 // static
69 DownloadFeedbackPings* DownloadFeedbackPings::FromDownload(
70 const content::DownloadItem& download) {
71 return static_cast<DownloadFeedbackPings*>(download.GetUserData(kPingKey));
74 } // namespace
76 DownloadFeedbackService::DownloadFeedbackService(
77 net::URLRequestContextGetter* request_context_getter,
78 base::TaskRunner* file_task_runner)
79 : request_context_getter_(request_context_getter),
80 file_task_runner_(file_task_runner),
81 weak_ptr_factory_(this) {
84 DownloadFeedbackService::~DownloadFeedbackService() {
85 DCHECK(CalledOnValidThread());
88 // static
89 void DownloadFeedbackService::MaybeStorePingsForDownload(
90 DownloadProtectionService::DownloadCheckResult result,
91 content::DownloadItem* download,
92 const std::string& ping,
93 const std::string& response) {
94 if (result != DownloadProtectionService::UNCOMMON &&
95 result != DownloadProtectionService::DANGEROUS_HOST)
96 return;
97 UMA_HISTOGRAM_COUNTS("SBDownloadFeedback.SizeEligibleKB",
98 download->GetReceivedBytes() / 1024);
99 if (download->GetReceivedBytes() > DownloadFeedback::kMaxUploadSize)
100 return;
102 DownloadFeedbackPings::CreateForDownload(download, ping, response);
105 // static
106 bool DownloadFeedbackService::IsEnabledForDownload(
107 const content::DownloadItem& download) {
108 return !!DownloadFeedbackPings::FromDownload(download);
111 // static
112 bool DownloadFeedbackService::GetPingsForDownloadForTesting(
113 const content::DownloadItem& download,
114 std::string* ping,
115 std::string* response) {
116 DownloadFeedbackPings* pings = DownloadFeedbackPings::FromDownload(download);
117 if (!pings)
118 return false;
120 *ping = pings->ping_request();
121 *response = pings->ping_response();
122 return true;
125 // static
126 void DownloadFeedbackService::RecordEligibleDownloadShown(
127 content::DownloadDangerType danger_type) {
128 UMA_HISTOGRAM_ENUMERATION("SBDownloadFeedback.Eligible",
129 danger_type,
130 content::DOWNLOAD_DANGER_TYPE_MAX);
134 void DownloadFeedbackService::BeginFeedbackForDownload(
135 content::DownloadItem* download) {
136 DCHECK(CalledOnValidThread());
138 UMA_HISTOGRAM_ENUMERATION("SBDownloadFeedback.Activations",
139 download->GetDangerType(),
140 content::DOWNLOAD_DANGER_TYPE_MAX);
142 DownloadFeedbackPings* pings = DownloadFeedbackPings::FromDownload(*download);
143 DCHECK(pings);
145 download->StealDangerousDownload(
146 base::Bind(&DownloadFeedbackService::BeginFeedbackOrDeleteFile,
147 file_task_runner_,
148 weak_ptr_factory_.GetWeakPtr(),
149 pings->ping_request(),
150 pings->ping_response()));
153 // static
154 void DownloadFeedbackService::BeginFeedbackOrDeleteFile(
155 const scoped_refptr<base::TaskRunner>& file_task_runner,
156 const base::WeakPtr<DownloadFeedbackService>& service,
157 const std::string& ping_request,
158 const std::string& ping_response,
159 const base::FilePath& path) {
160 if (service) {
161 service->BeginFeedback(ping_request, ping_response, path);
162 } else {
163 base::FileUtilProxy::DeleteFile(file_task_runner.get(),
164 path,
165 false,
166 base::FileUtilProxy::StatusCallback());
170 void DownloadFeedbackService::StartPendingFeedback() {
171 DCHECK(!active_feedback_.empty());
172 active_feedback_.front()->Start(base::Bind(
173 &DownloadFeedbackService::FeedbackComplete, base::Unretained(this)));
176 void DownloadFeedbackService::BeginFeedback(
177 const std::string& ping_request,
178 const std::string& ping_response,
179 const base::FilePath& path) {
180 DCHECK(CalledOnValidThread());
181 DownloadFeedback* feedback =
182 DownloadFeedback::Create(request_context_getter_.get(),
183 file_task_runner_.get(),
184 path,
185 ping_request,
186 ping_response);
187 active_feedback_.push_back(feedback);
188 UMA_HISTOGRAM_COUNTS_100("SBDownloadFeedback.ActiveFeedbacks",
189 active_feedback_.size());
191 if (active_feedback_.size() == 1)
192 StartPendingFeedback();
195 void DownloadFeedbackService::FeedbackComplete() {
196 DVLOG(1) << __FUNCTION__;
197 DCHECK(CalledOnValidThread());
198 DCHECK(!active_feedback_.empty());
199 active_feedback_.erase(active_feedback_.begin());
200 if (!active_feedback_.empty())
201 StartPendingFeedback();
204 } // namespace safe_browsing