Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / safe_browsing / download_feedback.cc
blob27f4008ceb85f532ffd65bfc1b6bf5dc8e1d8820
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.h"
7 #include "base/bind.h"
8 #include "base/files/file_util_proxy.h"
9 #include "base/metrics/histogram.h"
10 #include "base/task_runner.h"
11 #include "chrome/common/safe_browsing/csd.pb.h"
12 #include "net/base/net_errors.h"
14 namespace safe_browsing {
16 namespace {
18 // This enum is used by histograms. Do not change the ordering or remove items.
19 enum UploadResultType {
20 UPLOAD_SUCCESS,
21 UPLOAD_CANCELLED,
22 UPLOAD_METADATA_NET_ERROR,
23 UPLOAD_METADATA_RESPONSE_ERROR,
24 UPLOAD_FILE_NET_ERROR,
25 UPLOAD_FILE_RESPONSE_ERROR,
26 UPLOAD_COMPLETE_RESPONSE_ERROR,
27 // Memory space for histograms is determined by the max.
28 // ALWAYS ADD NEW VALUES BEFORE THIS ONE.
29 UPLOAD_RESULT_MAX
32 // Handles the uploading of a single downloaded binary to the safebrowsing
33 // download feedback service.
34 class DownloadFeedbackImpl : public DownloadFeedback {
35 public:
36 DownloadFeedbackImpl(net::URLRequestContextGetter* request_context_getter,
37 base::TaskRunner* file_task_runner,
38 const base::FilePath& file_path,
39 const std::string& ping_request,
40 const std::string& ping_response);
41 ~DownloadFeedbackImpl() override;
43 void Start(const base::Closure& finish_callback) override;
45 const std::string& GetPingRequestForTesting() const override {
46 return ping_request_;
49 const std::string& GetPingResponseForTesting() const override {
50 return ping_response_;
53 private:
54 // Callback for TwoPhaseUploader completion. Relays the result to the
55 // |finish_callback|.
56 void FinishedUpload(base::Closure finish_callback,
57 TwoPhaseUploader::State state,
58 int net_error,
59 int response_code,
60 const std::string& response);
62 void RecordUploadResult(UploadResultType result);
64 scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
65 scoped_refptr<base::TaskRunner> file_task_runner_;
66 const base::FilePath file_path_;
67 int64 file_size_;
69 // The safebrowsing request and response of checking that this binary is
70 // unsafe.
71 std::string ping_request_;
72 std::string ping_response_;
74 scoped_ptr<TwoPhaseUploader> uploader_;
76 DISALLOW_COPY_AND_ASSIGN(DownloadFeedbackImpl);
79 DownloadFeedbackImpl::DownloadFeedbackImpl(
80 net::URLRequestContextGetter* request_context_getter,
81 base::TaskRunner* file_task_runner,
82 const base::FilePath& file_path,
83 const std::string& ping_request,
84 const std::string& ping_response)
85 : request_context_getter_(request_context_getter),
86 file_task_runner_(file_task_runner),
87 file_path_(file_path),
88 file_size_(-1),
89 ping_request_(ping_request),
90 ping_response_(ping_response) {
91 DVLOG(1) << "DownloadFeedback constructed " << this << " for "
92 << file_path.AsUTF8Unsafe();
95 DownloadFeedbackImpl::~DownloadFeedbackImpl() {
96 DCHECK(CalledOnValidThread());
97 DVLOG(1) << "DownloadFeedback destructed " << this;
99 if (uploader_) {
100 RecordUploadResult(UPLOAD_CANCELLED);
101 // Destroy the uploader before attempting to delete the file.
102 uploader_.reset();
105 base::FileUtilProxy::DeleteFile(file_task_runner_.get(),
106 file_path_,
107 false,
108 base::FileUtilProxy::StatusCallback());
111 void DownloadFeedbackImpl::Start(const base::Closure& finish_callback) {
112 DCHECK(CalledOnValidThread());
113 DCHECK(!uploader_);
115 ClientDownloadReport report_metadata;
117 bool r = report_metadata.mutable_download_request()->ParseFromString(
118 ping_request_);
119 DCHECK(r);
120 r = report_metadata.mutable_download_response()->ParseFromString(
121 ping_response_);
122 DCHECK(r);
123 file_size_ = report_metadata.download_request().length();
125 std::string metadata_string;
126 bool ok = report_metadata.SerializeToString(&metadata_string);
127 DCHECK(ok);
128 uploader_.reset(
129 TwoPhaseUploader::Create(request_context_getter_.get(),
130 file_task_runner_.get(),
131 GURL(kSbFeedbackURL),
132 metadata_string,
133 file_path_,
134 TwoPhaseUploader::ProgressCallback(),
135 base::Bind(&DownloadFeedbackImpl::FinishedUpload,
136 base::Unretained(this),
137 finish_callback)));
138 uploader_->Start();
141 void DownloadFeedbackImpl::FinishedUpload(base::Closure finish_callback,
142 TwoPhaseUploader::State state,
143 int net_error,
144 int response_code,
145 const std::string& response_data) {
146 DCHECK(CalledOnValidThread());
147 DVLOG(1) << __FUNCTION__ << " " << state << " rlen=" << response_data.size();
149 switch (state) {
150 case TwoPhaseUploader::STATE_SUCCESS: {
151 ClientUploadResponse response;
152 if (!response.ParseFromString(response_data) ||
153 response.status() != ClientUploadResponse::SUCCESS)
154 RecordUploadResult(UPLOAD_COMPLETE_RESPONSE_ERROR);
155 else
156 RecordUploadResult(UPLOAD_SUCCESS);
157 break;
159 case TwoPhaseUploader::UPLOAD_FILE:
160 if (net_error != net::OK)
161 RecordUploadResult(UPLOAD_FILE_NET_ERROR);
162 else
163 RecordUploadResult(UPLOAD_FILE_RESPONSE_ERROR);
164 break;
165 case TwoPhaseUploader::UPLOAD_METADATA:
166 if (net_error != net::OK)
167 RecordUploadResult(UPLOAD_METADATA_NET_ERROR);
168 else
169 RecordUploadResult(UPLOAD_METADATA_RESPONSE_ERROR);
170 break;
171 default:
172 NOTREACHED();
175 uploader_.reset();
177 finish_callback.Run();
178 // We may be deleted here.
181 void DownloadFeedbackImpl::RecordUploadResult(UploadResultType result) {
182 if (result == UPLOAD_SUCCESS)
183 UMA_HISTOGRAM_CUSTOM_COUNTS(
184 "SBDownloadFeedback.SizeSuccess", file_size_, 1, kMaxUploadSize, 50);
185 else
186 UMA_HISTOGRAM_CUSTOM_COUNTS(
187 "SBDownloadFeedback.SizeFailure", file_size_, 1, kMaxUploadSize, 50);
188 UMA_HISTOGRAM_ENUMERATION(
189 "SBDownloadFeedback.UploadResult", result, UPLOAD_RESULT_MAX);
192 } // namespace
194 // static
195 const int64 DownloadFeedback::kMaxUploadSize = 50 * 1024 * 1024;
197 // static
198 const char DownloadFeedback::kSbFeedbackURL[] =
199 "https://safebrowsing.google.com/safebrowsing/uploads/chrome";
201 // static
202 DownloadFeedbackFactory* DownloadFeedback::factory_ = NULL;
204 // static
205 DownloadFeedback* DownloadFeedback::Create(
206 net::URLRequestContextGetter* request_context_getter,
207 base::TaskRunner* file_task_runner,
208 const base::FilePath& file_path,
209 const std::string& ping_request,
210 const std::string& ping_response) {
211 if (!DownloadFeedback::factory_)
212 return new DownloadFeedbackImpl(
213 request_context_getter, file_task_runner, file_path, ping_request,
214 ping_response);
215 return DownloadFeedback::factory_->CreateDownloadFeedback(
216 request_context_getter, file_task_runner, file_path, ping_request,
217 ping_response);
220 } // namespace safe_browsing