Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / safe_browsing / download_feedback.cc
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/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"
13
14 namespace safe_browsing {
15
16 namespace {
17
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
30 };
31
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   virtual ~DownloadFeedbackImpl();
42
43   virtual void Start(const base::Closure& finish_callback) OVERRIDE;
44
45   virtual const std::string& GetPingRequestForTesting() const OVERRIDE {
46     return ping_request_;
47   }
48
49   virtual const std::string& GetPingResponseForTesting() const OVERRIDE {
50     return ping_response_;
51   }
52
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);
61
62   void RecordUploadResult(UploadResultType result);
63
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_;
68
69   // The safebrowsing request and response of checking that this binary is
70   // unsafe.
71   std::string ping_request_;
72   std::string ping_response_;
73
74   scoped_ptr<TwoPhaseUploader> uploader_;
75
76   DISALLOW_COPY_AND_ASSIGN(DownloadFeedbackImpl);
77 };
78
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();
93 }
94
95 DownloadFeedbackImpl::~DownloadFeedbackImpl() {
96   DCHECK(CalledOnValidThread());
97   DVLOG(1) << "DownloadFeedback destructed " << this;
98
99   if (uploader_) {
100     RecordUploadResult(UPLOAD_CANCELLED);
101     // Destroy the uploader before attempting to delete the file.
102     uploader_.reset();
103   }
104
105   base::FileUtilProxy::DeleteFile(file_task_runner_.get(),
106                                   file_path_,
107                                   false,
108                                   base::FileUtilProxy::StatusCallback());
109 }
110
111 void DownloadFeedbackImpl::Start(const base::Closure& finish_callback) {
112   DCHECK(CalledOnValidThread());
113   DCHECK(!uploader_);
114
115   ClientDownloadReport report_metadata;
116
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();
124
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();
139 }
140
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();
148
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;
158     }
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();
173   }
174
175   uploader_.reset();
176
177   finish_callback.Run();
178   // We may be deleted here.
179 }
180
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);
190 }
191
192 }  // namespace
193
194 // static
195 const int64 DownloadFeedback::kMaxUploadSize = 50 * 1024 * 1024;
196
197 // static
198 const char DownloadFeedback::kSbFeedbackURL[] =
199     "https://safebrowsing.google.com/safebrowsing/uploads/chrome";
200
201 // static
202 DownloadFeedbackFactory* DownloadFeedback::factory_ = NULL;
203
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);
218 }
219
220 }  // namespace safe_browsing
221