OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/safe_browsing/two_phase_uploader.h" | 5 #include "chrome/browser/safe_browsing/two_phase_uploader.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <limits> | 9 #include <limits> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/macros.h" | 12 #include "base/macros.h" |
13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/sequence_checker.h" |
14 #include "base/task_runner.h" | 15 #include "base/task_runner.h" |
15 #include "components/data_use_measurement/core/data_use_user_data.h" | 16 #include "components/data_use_measurement/core/data_use_user_data.h" |
16 #include "content/public/browser/browser_thread.h" | |
17 #include "net/base/net_errors.h" | 17 #include "net/base/net_errors.h" |
18 #include "net/http/http_response_headers.h" | 18 #include "net/http/http_response_headers.h" |
19 #include "net/url_request/url_fetcher.h" | 19 #include "net/url_request/url_fetcher.h" |
20 #include "net/url_request/url_fetcher_delegate.h" | 20 #include "net/url_request/url_fetcher_delegate.h" |
21 #include "net/url_request/url_request_status.h" | 21 #include "net/url_request/url_request_status.h" |
22 | 22 |
23 namespace { | 23 namespace { |
24 | 24 |
25 // Header sent on initial request to start the two phase upload process. | 25 // Header sent on initial request to start the two phase upload process. |
26 const char kStartHeader[] = "x-goog-resumable: start"; | 26 const char kStartHeader[] = "x-goog-resumable: start"; |
27 | 27 |
28 // Header returned on initial response with URL to use for the second phase. | 28 // Header returned on initial response with URL to use for the second phase. |
29 const char kLocationHeader[] = "Location"; | 29 const char kLocationHeader[] = "Location"; |
30 | 30 |
31 const char kUploadContentType[] = "application/octet-stream"; | 31 const char kUploadContentType[] = "application/octet-stream"; |
32 | 32 |
33 class TwoPhaseUploaderImpl : public net::URLFetcherDelegate, | 33 class TwoPhaseUploaderImpl : public net::URLFetcherDelegate, |
34 public TwoPhaseUploader { | 34 public TwoPhaseUploader { |
35 public: | 35 public: |
36 TwoPhaseUploaderImpl( | 36 TwoPhaseUploaderImpl( |
37 net::URLRequestContextGetter* url_request_context_getter, | 37 net::URLRequestContextGetter* url_request_context_getter, |
38 base::TaskRunner* file_task_runner, | 38 base::TaskRunner* file_task_runner, |
39 const GURL& base_url, | 39 const GURL& base_url, |
40 const std::string& metadata, | 40 const std::string& metadata, |
41 const base::FilePath& file_path, | 41 const base::FilePath& file_path, |
42 const ProgressCallback& progress_callback, | 42 const ProgressCallback& progress_callback, |
43 const FinishCallback& finish_callback, | 43 const FinishCallback& finish_callback, |
44 const net::NetworkTrafficAnnotationTag& traffic_annotation); | 44 const net::NetworkTrafficAnnotationTag& traffic_annotation); |
45 ~TwoPhaseUploaderImpl() override; | 45 ~TwoPhaseUploaderImpl() override = default; |
46 | 46 |
47 // Begins the upload process. | 47 // Begins the upload process. |
48 void Start() override; | 48 void Start() override; |
49 | 49 |
50 // net::URLFetcherDelegate implementation: | 50 // net::URLFetcherDelegate implementation: |
51 void OnURLFetchComplete(const net::URLFetcher* source) override; | 51 void OnURLFetchComplete(const net::URLFetcher* source) override; |
52 void OnURLFetchUploadProgress(const net::URLFetcher* source, | 52 void OnURLFetchUploadProgress(const net::URLFetcher* source, |
53 int64_t current, | 53 int64_t current, |
54 int64_t total) override; | 54 int64_t total) override; |
55 | 55 |
56 private: | 56 private: |
57 void UploadMetadata(); | 57 void UploadMetadata(); |
58 void UploadFile(); | 58 void UploadFile(); |
59 void Finish(int net_error, int response_code, const std::string& response); | 59 void Finish(int net_error, int response_code, const std::string& response); |
60 | 60 |
61 State state_; | 61 State state_; |
62 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; | 62 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; |
63 scoped_refptr<base::TaskRunner> file_task_runner_; | 63 scoped_refptr<base::TaskRunner> file_task_runner_; |
64 GURL base_url_; | 64 GURL base_url_; |
65 GURL upload_url_; | 65 GURL upload_url_; |
66 std::string metadata_; | 66 std::string metadata_; |
67 const base::FilePath file_path_; | 67 const base::FilePath file_path_; |
68 ProgressCallback progress_callback_; | 68 ProgressCallback progress_callback_; |
69 FinishCallback finish_callback_; | 69 FinishCallback finish_callback_; |
70 net::NetworkTrafficAnnotationTag traffic_annotation_; | 70 net::NetworkTrafficAnnotationTag traffic_annotation_; |
71 | 71 |
72 std::unique_ptr<net::URLFetcher> url_fetcher_; | 72 std::unique_ptr<net::URLFetcher> url_fetcher_; |
73 | 73 |
| 74 // Ensure access to the state_ variable is sequenced, and that callbacks are |
| 75 // invoked on the same sequence as Start. |
| 76 base::SequenceChecker sequence_checker_; |
| 77 |
74 DISALLOW_COPY_AND_ASSIGN(TwoPhaseUploaderImpl); | 78 DISALLOW_COPY_AND_ASSIGN(TwoPhaseUploaderImpl); |
75 }; | 79 }; |
76 | 80 |
77 TwoPhaseUploaderImpl::TwoPhaseUploaderImpl( | 81 TwoPhaseUploaderImpl::TwoPhaseUploaderImpl( |
78 net::URLRequestContextGetter* url_request_context_getter, | 82 net::URLRequestContextGetter* url_request_context_getter, |
79 base::TaskRunner* file_task_runner, | 83 base::TaskRunner* file_task_runner, |
80 const GURL& base_url, | 84 const GURL& base_url, |
81 const std::string& metadata, | 85 const std::string& metadata, |
82 const base::FilePath& file_path, | 86 const base::FilePath& file_path, |
83 const ProgressCallback& progress_callback, | 87 const ProgressCallback& progress_callback, |
84 const FinishCallback& finish_callback, | 88 const FinishCallback& finish_callback, |
85 const net::NetworkTrafficAnnotationTag& traffic_annotation) | 89 const net::NetworkTrafficAnnotationTag& traffic_annotation) |
86 : state_(STATE_NONE), | 90 : state_(STATE_NONE), |
87 url_request_context_getter_(url_request_context_getter), | 91 url_request_context_getter_(url_request_context_getter), |
88 file_task_runner_(file_task_runner), | 92 file_task_runner_(file_task_runner), |
89 base_url_(base_url), | 93 base_url_(base_url), |
90 metadata_(metadata), | 94 metadata_(metadata), |
91 file_path_(file_path), | 95 file_path_(file_path), |
92 progress_callback_(progress_callback), | 96 progress_callback_(progress_callback), |
93 finish_callback_(finish_callback), | 97 finish_callback_(finish_callback), |
94 traffic_annotation_(traffic_annotation) { | 98 traffic_annotation_(traffic_annotation) { |
95 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 99 // The callbacks must be invoked on the same sequence as Start, but that |
96 } | 100 // doesn't need to be the same sequence the TwoPhaseUploaderImpl was |
97 | 101 // constructed on. |
98 TwoPhaseUploaderImpl::~TwoPhaseUploaderImpl() { | 102 sequence_checker_.DetachFromSequence(); |
99 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
100 } | 103 } |
101 | 104 |
102 void TwoPhaseUploaderImpl::Start() { | 105 void TwoPhaseUploaderImpl::Start() { |
103 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 106 // Bind the sequence checker to the current sequence. |
| 107 DCHECK(sequence_checker_.CalledOnValidSequence()); |
104 DCHECK_EQ(STATE_NONE, state_); | 108 DCHECK_EQ(STATE_NONE, state_); |
105 | 109 |
106 UploadMetadata(); | 110 UploadMetadata(); |
107 } | 111 } |
108 | 112 |
109 void TwoPhaseUploaderImpl::OnURLFetchComplete(const net::URLFetcher* source) { | 113 void TwoPhaseUploaderImpl::OnURLFetchComplete(const net::URLFetcher* source) { |
110 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 114 DCHECK(sequence_checker_.CalledOnValidSequence()); |
111 net::URLRequestStatus status = source->GetStatus(); | 115 net::URLRequestStatus status = source->GetStatus(); |
112 int response_code = source->GetResponseCode(); | 116 int response_code = source->GetResponseCode(); |
113 | 117 |
114 DVLOG(1) << __func__ << " " << source->GetURL().spec() << " " | 118 DVLOG(1) << __func__ << " " << source->GetURL().spec() << " " |
115 << status.status() << " " << response_code; | 119 << status.status() << " " << response_code; |
116 | 120 |
117 if (!status.is_success()) { | 121 if (!status.is_success()) { |
118 LOG(ERROR) << "URLFetcher failed, status=" << status.status() | 122 LOG(ERROR) << "URLFetcher failed, status=" << status.status() |
119 << " err=" << status.error(); | 123 << " err=" << status.error(); |
120 Finish(status.error(), response_code, std::string()); | 124 Finish(status.error(), response_code, std::string()); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 return; | 160 return; |
157 default: | 161 default: |
158 NOTREACHED(); | 162 NOTREACHED(); |
159 } | 163 } |
160 } | 164 } |
161 | 165 |
162 void TwoPhaseUploaderImpl::OnURLFetchUploadProgress( | 166 void TwoPhaseUploaderImpl::OnURLFetchUploadProgress( |
163 const net::URLFetcher* source, | 167 const net::URLFetcher* source, |
164 int64_t current, | 168 int64_t current, |
165 int64_t total) { | 169 int64_t total) { |
166 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 170 DCHECK(sequence_checker_.CalledOnValidSequence()); |
167 DVLOG(3) << __func__ << " " << source->GetURL().spec() << " " << current | 171 DVLOG(3) << __func__ << " " << source->GetURL().spec() << " " << current |
168 << "/" << total; | 172 << "/" << total; |
169 if (state_ == UPLOAD_FILE && !progress_callback_.is_null()) | 173 if (state_ == UPLOAD_FILE && !progress_callback_.is_null()) |
170 progress_callback_.Run(current, total); | 174 progress_callback_.Run(current, total); |
171 } | 175 } |
172 | 176 |
173 void TwoPhaseUploaderImpl::UploadMetadata() { | 177 void TwoPhaseUploaderImpl::UploadMetadata() { |
174 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 178 DCHECK(sequence_checker_.CalledOnValidSequence()); |
175 state_ = UPLOAD_METADATA; | 179 state_ = UPLOAD_METADATA; |
176 url_fetcher_ = net::URLFetcher::Create(base_url_, net::URLFetcher::POST, this, | 180 url_fetcher_ = net::URLFetcher::Create(base_url_, net::URLFetcher::POST, this, |
177 traffic_annotation_); | 181 traffic_annotation_); |
178 | 182 |
179 data_use_measurement::DataUseUserData::AttachToFetcher( | 183 data_use_measurement::DataUseUserData::AttachToFetcher( |
180 url_fetcher_.get(), data_use_measurement::DataUseUserData::SAFE_BROWSING); | 184 url_fetcher_.get(), data_use_measurement::DataUseUserData::SAFE_BROWSING); |
181 url_fetcher_->SetRequestContext(url_request_context_getter_.get()); | 185 url_fetcher_->SetRequestContext(url_request_context_getter_.get()); |
182 url_fetcher_->SetExtraRequestHeaders(kStartHeader); | 186 url_fetcher_->SetExtraRequestHeaders(kStartHeader); |
183 url_fetcher_->SetUploadData(kUploadContentType, metadata_); | 187 url_fetcher_->SetUploadData(kUploadContentType, metadata_); |
184 url_fetcher_->Start(); | 188 url_fetcher_->Start(); |
185 } | 189 } |
186 | 190 |
187 void TwoPhaseUploaderImpl::UploadFile() { | 191 void TwoPhaseUploaderImpl::UploadFile() { |
188 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 192 DCHECK(sequence_checker_.CalledOnValidSequence()); |
189 state_ = UPLOAD_FILE; | 193 state_ = UPLOAD_FILE; |
190 | 194 |
191 url_fetcher_ = net::URLFetcher::Create(upload_url_, net::URLFetcher::PUT, | 195 url_fetcher_ = net::URLFetcher::Create(upload_url_, net::URLFetcher::PUT, |
192 this, traffic_annotation_); | 196 this, traffic_annotation_); |
193 data_use_measurement::DataUseUserData::AttachToFetcher( | 197 data_use_measurement::DataUseUserData::AttachToFetcher( |
194 url_fetcher_.get(), data_use_measurement::DataUseUserData::SAFE_BROWSING); | 198 url_fetcher_.get(), data_use_measurement::DataUseUserData::SAFE_BROWSING); |
195 url_fetcher_->SetRequestContext(url_request_context_getter_.get()); | 199 url_fetcher_->SetRequestContext(url_request_context_getter_.get()); |
196 url_fetcher_->SetUploadFilePath(kUploadContentType, file_path_, 0, | 200 url_fetcher_->SetUploadFilePath(kUploadContentType, file_path_, 0, |
197 std::numeric_limits<uint64_t>::max(), | 201 std::numeric_limits<uint64_t>::max(), |
198 file_task_runner_); | 202 file_task_runner_); |
199 url_fetcher_->Start(); | 203 url_fetcher_->Start(); |
200 } | 204 } |
201 | 205 |
202 void TwoPhaseUploaderImpl::Finish(int net_error, | 206 void TwoPhaseUploaderImpl::Finish(int net_error, |
203 int response_code, | 207 int response_code, |
204 const std::string& response) { | 208 const std::string& response) { |
205 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 209 DCHECK(sequence_checker_.CalledOnValidSequence()); |
206 finish_callback_.Run(state_, net_error, response_code, response); | 210 finish_callback_.Run(state_, net_error, response_code, response); |
207 } | 211 } |
208 | 212 |
209 } // namespace | 213 } // namespace |
210 | 214 |
211 // static | 215 // static |
212 TwoPhaseUploaderFactory* TwoPhaseUploader::factory_ = nullptr; | 216 TwoPhaseUploaderFactory* TwoPhaseUploader::factory_ = nullptr; |
213 | 217 |
214 // static | 218 // static |
215 std::unique_ptr<TwoPhaseUploader> TwoPhaseUploader::Create( | 219 std::unique_ptr<TwoPhaseUploader> TwoPhaseUploader::Create( |
216 net::URLRequestContextGetter* url_request_context_getter, | 220 net::URLRequestContextGetter* url_request_context_getter, |
217 base::TaskRunner* file_task_runner, | 221 base::TaskRunner* file_task_runner, |
218 const GURL& base_url, | 222 const GURL& base_url, |
219 const std::string& metadata, | 223 const std::string& metadata, |
220 const base::FilePath& file_path, | 224 const base::FilePath& file_path, |
221 const ProgressCallback& progress_callback, | 225 const ProgressCallback& progress_callback, |
222 const FinishCallback& finish_callback, | 226 const FinishCallback& finish_callback, |
223 const net::NetworkTrafficAnnotationTag& traffic_annotation) { | 227 const net::NetworkTrafficAnnotationTag& traffic_annotation) { |
224 if (!factory_) { | 228 if (!factory_) { |
225 return base::WrapUnique(new TwoPhaseUploaderImpl( | 229 return base::WrapUnique(new TwoPhaseUploaderImpl( |
226 url_request_context_getter, file_task_runner, base_url, metadata, | 230 url_request_context_getter, file_task_runner, base_url, metadata, |
227 file_path, progress_callback, finish_callback, traffic_annotation)); | 231 file_path, progress_callback, finish_callback, traffic_annotation)); |
228 } | 232 } |
229 return TwoPhaseUploader::factory_->CreateTwoPhaseUploader( | 233 return TwoPhaseUploader::factory_->CreateTwoPhaseUploader( |
230 url_request_context_getter, file_task_runner, base_url, metadata, | 234 url_request_context_getter, file_task_runner, base_url, metadata, |
231 file_path, progress_callback, finish_callback, traffic_annotation); | 235 file_path, progress_callback, finish_callback, traffic_annotation); |
232 } | 236 } |
OLD | NEW |