Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(86)

Side by Side Diff: chrome/browser/safe_browsing/download_feedback.cc

Issue 15881012: Implement safebrowsing download feedback service, enabled for dev & canary only. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/safe_browsing/download_feedback.h"
6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/files/file_util_proxy.h"
10 #include "base/metrics/histogram.h"
11 #include "base/task_runner.h"
12 #include "chrome/common/chrome_switches.h"
13 #include "chrome/common/safe_browsing/csd.pb.h"
14 #include "net/base/net_errors.h"
15
16 namespace safe_browsing {
17
18 namespace {
19
20 // The default URL where browser sends download feedback requests.
21 const char kSbDefaultFeedbackURL[] =
22 "https://safebrowsing.google.com/safebrowsing/uploads/chrome";
23
24 // This enum is used by histograms. Do not change the ordering or remove items.
25 enum UploadResultType {
26 UPLOAD_SUCCESS,
27 UPLOAD_CANCELLED,
28 UPLOAD_METADATA_NET_ERROR,
29 UPLOAD_METADATA_RESPONSE_ERROR,
30 UPLOAD_FILE_NET_ERROR,
31 UPLOAD_FILE_RESPONSE_ERROR,
32 UPLOAD_COMPLETE_RESPONSE_ERROR,
33 // Memory space for histograms is determined by the max.
34 // ALWAYS ADD NEW VALUES BEFORE THIS ONE.
35 UPLOAD_RESULT_MAX
36 };
37
38 // Handles the uploading of a single downloaded binary to the safebrowsing
39 // download feedback service.
40 class DownloadFeedbackImpl : public DownloadFeedback {
41 public:
42 DownloadFeedbackImpl(net::URLRequestContextGetter* request_context_getter,
43 base::TaskRunner* file_task_runner,
44 const base::FilePath& file_path,
45 const std::string& ping_request,
46 const std::string& ping_response);
47 virtual ~DownloadFeedbackImpl();
48
49 virtual void Start(const base::Closure& finish_callback) OVERRIDE;
50
51 virtual const std::string& GetPingRequestForTesting() const OVERRIDE {
52 return ping_request_;
53 }
54
55 virtual const std::string& GetPingResponseForTesting() const OVERRIDE {
56 return ping_response_;
57 }
58
59 private:
60 // Callback for TwoPhaseUploader completion. Relays the result to the
61 // |finish_callback|.
62 void FinishedUpload(base::Closure finish_callback,
63 TwoPhaseUploader::State state,
64 int net_error,
65 int response_code,
66 const std::string& response);
67
68 void RecordUploadResult(UploadResultType result);
69
70 scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
71 scoped_refptr<base::TaskRunner> file_task_runner_;
72 const base::FilePath file_path_;
73 int64 file_size_;
74
75 // The safebrowsing request and response of checking that this binary is
76 // unsafe.
77 std::string ping_request_;
78 std::string ping_response_;
79
80 scoped_ptr<TwoPhaseUploader> uploader_;
81
82 DISALLOW_COPY_AND_ASSIGN(DownloadFeedbackImpl);
83 };
84
85 DownloadFeedbackImpl::DownloadFeedbackImpl(
86 net::URLRequestContextGetter* request_context_getter,
87 base::TaskRunner* file_task_runner,
88 const base::FilePath& file_path,
89 const std::string& ping_request,
90 const std::string& ping_response)
91 : request_context_getter_(request_context_getter),
92 file_task_runner_(file_task_runner),
93 file_path_(file_path),
94 file_size_(-1),
95 ping_request_(ping_request),
96 ping_response_(ping_response) {
97 DVLOG(1) << "DownloadFeedback constructed " << this << " for "
98 << file_path.AsUTF8Unsafe();
99 }
100
101 DownloadFeedbackImpl::~DownloadFeedbackImpl() {
102 DCHECK(CalledOnValidThread());
103 DVLOG(1) << "DownloadFeedback destructed " << this;
104
105 if (uploader_) {
106 RecordUploadResult(UPLOAD_CANCELLED);
107 // Destroy the uploader before attempting to delete the file.
108 uploader_.reset();
109 }
110
111 base::FileUtilProxy::Delete(file_task_runner_, file_path_, false,
112 base::FileUtilProxy::StatusCallback());
113 }
114
115 void DownloadFeedbackImpl::Start(const base::Closure& finish_callback) {
116 DCHECK(CalledOnValidThread());
117 DCHECK(!uploader_);
118
119 CommandLine* cmdline = CommandLine::ForCurrentProcess();
120
121 ClientDownloadReport report_metadata;
122
123 bool r = report_metadata.mutable_download_request()->ParseFromString(
124 ping_request_);
125 DCHECK(r);
126 r = report_metadata.mutable_download_response()->ParseFromString(
127 ping_response_);
128 DCHECK(r);
129 file_size_ = report_metadata.download_request().length();
130
131 GURL url = GURL(cmdline->HasSwitch(switches::kSbDownloadFeedbackURL) ?
132 cmdline->GetSwitchValueASCII(switches::kSbDownloadFeedbackURL) :
133 kSbDefaultFeedbackURL);
134
135 std::string metadata_string;
136 bool ok = report_metadata.SerializeToString(&metadata_string);
137 DCHECK(ok);
138 uploader_.reset(TwoPhaseUploader::Create(
139 request_context_getter_,
140 file_task_runner_,
141 url,
142 metadata_string,
143 file_path_,
144 TwoPhaseUploader::ProgressCallback(),
145 base::Bind(&DownloadFeedbackImpl::FinishedUpload, base::Unretained(this),
146 finish_callback)));
147 uploader_->Start();
148 }
149
150 void DownloadFeedbackImpl::FinishedUpload(base::Closure finish_callback,
151 TwoPhaseUploader::State state,
152 int net_error,
153 int response_code,
154 const std::string& response_data) {
155 DCHECK(CalledOnValidThread());
156 DVLOG(1) << __FUNCTION__ << " " << state << " rlen=" << response_data.size();
157
158 switch (state) {
159 case TwoPhaseUploader::STATE_SUCCESS: {
160 ClientUploadResponse response;
161 if (!response.ParseFromString(response_data) ||
162 response.status() != ClientUploadResponse::SUCCESS)
163 RecordUploadResult(UPLOAD_COMPLETE_RESPONSE_ERROR);
164 else
165 RecordUploadResult(UPLOAD_SUCCESS);
166 break;
167 }
168 case TwoPhaseUploader::UPLOAD_FILE:
169 if (net_error != net::OK)
170 RecordUploadResult(UPLOAD_FILE_NET_ERROR);
171 else
172 RecordUploadResult(UPLOAD_FILE_RESPONSE_ERROR);
173 break;
174 case TwoPhaseUploader::UPLOAD_METADATA:
175 if (net_error != net::OK)
176 RecordUploadResult(UPLOAD_METADATA_NET_ERROR);
177 else
178 RecordUploadResult(UPLOAD_METADATA_RESPONSE_ERROR);
179 break;
180 default:
181 NOTREACHED();
182 }
183
184 uploader_.reset();
185
186 finish_callback.Run();
187 // We may be deleted here.
188 }
189
190 void DownloadFeedbackImpl::RecordUploadResult(UploadResultType result) {
191 if (result == UPLOAD_SUCCESS)
192 UMA_HISTOGRAM_CUSTOM_COUNTS(
193 "SBDownloadFeedback.SizeSuccess", file_size_, 1, kMaxUploadSize, 50);
194 else
195 UMA_HISTOGRAM_CUSTOM_COUNTS(
196 "SBDownloadFeedback.SizeFailure", file_size_, 1, kMaxUploadSize, 50);
197 UMA_HISTOGRAM_ENUMERATION(
198 "SBDownloadFeedback.UploadResult", result, UPLOAD_RESULT_MAX);
199 }
200
201 } // namespace
202
203 // static
204 const int64 DownloadFeedback::kMaxUploadSize = 50 * 1024 * 1024;
205
206 // static
207 DownloadFeedbackFactory* DownloadFeedback::factory_ = NULL;
208
209 // static
210 DownloadFeedback* DownloadFeedback::Create(
211 net::URLRequestContextGetter* request_context_getter,
212 base::TaskRunner* file_task_runner,
213 const base::FilePath& file_path,
214 const std::string& ping_request,
215 const std::string& ping_response) {
216 if (!DownloadFeedback::factory_)
217 return new DownloadFeedbackImpl(
218 request_context_getter, file_task_runner, file_path, ping_request,
219 ping_response);
220 return DownloadFeedback::factory_->CreateDownloadFeedback(
221 request_context_getter, file_task_runner, file_path, ping_request,
222 ping_response);
223 }
224
225 } // namespace safe_browsing
226
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698