OLD | NEW |
---|---|
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2015 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/chromeos/policy/upload_job_impl.h" | 5 #include "chrome/browser/chromeos/policy/upload_job_impl.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/rand_util.h" | |
11 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
12 #include "google_apis/gaia/gaia_constants.h" | 11 #include "google_apis/gaia/gaia_constants.h" |
13 #include "google_apis/gaia/google_service_auth_error.h" | 12 #include "google_apis/gaia/google_service_auth_error.h" |
13 #include "net/base/mime_util.h" | |
14 #include "net/http/http_status_code.h" | 14 #include "net/http/http_status_code.h" |
15 #include "net/url_request/url_request_status.h" | 15 #include "net/url_request/url_request_status.h" |
16 | 16 |
17 namespace policy { | 17 namespace policy { |
18 | 18 |
19 namespace { | 19 namespace { |
20 | 20 |
21 // Defines the characters that might appear in strings generated by | |
22 // GenerateRandomString(). | |
23 const char kAlphaNum[] = | |
24 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | |
25 | |
26 // Format for bearer tokens in HTTP requests to access OAuth 2.0 protected | 21 // Format for bearer tokens in HTTP requests to access OAuth 2.0 protected |
27 // resources. | 22 // resources. |
28 const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s"; | 23 const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s"; |
29 | 24 |
30 // Prefix added to a randomly generated string when choosing the MIME boundary. | |
31 const char kMultipartBoundaryPrefix[] = "----**--"; | |
32 | |
33 // Postfix added to a randomly generated string when choosing the MIME boundary. | |
34 const char kMultipartBoundaryPostfix[] = "--**----"; | |
35 | |
36 // Value the "Content-Type" field will be set to in the POST request. | 25 // Value the "Content-Type" field will be set to in the POST request. |
37 const char kUploadContentType[] = "multipart/form-data"; | 26 const char kUploadContentType[] = "multipart/form-data"; |
38 | 27 |
39 // Number of retries when randomly generating a MIME boundary. | 28 // Number of retries when randomly generating a MIME boundary. |
40 const int kMimeBoundaryRetries = 3; | 29 const int kMimeBoundaryRetries = 3; |
41 | 30 |
42 // Length of the random string for the MIME boundary. | |
43 const int kMimeBoundarySize = 32; | |
44 | |
45 // Number of upload retries. | 31 // Number of upload retries. |
46 const int kMaxRetries = 1; | 32 const int kMaxRetries = 1; |
47 | 33 |
48 // Generates a random alphanumeric string of length |length|. | 34 // Max size of MIME boundary according to RFC 1341, section 7.2.1. |
49 std::string GenerateRandomString(size_t length) { | 35 const size_t kMaxMimeBoundarySize = 70; |
50 std::string random; | |
51 random.reserve(length); | |
52 for (size_t i = 0; i < length; i++) | |
53 random.push_back(kAlphaNum[base::RandGenerator(sizeof(kAlphaNum) - 1)]); | |
54 return random; | |
55 } | |
56 | 36 |
57 } // namespace | 37 } // namespace |
58 | 38 |
59 UploadJobImpl::Delegate::~Delegate() { | 39 UploadJobImpl::Delegate::~Delegate() { |
60 } | 40 } |
61 | 41 |
62 UploadJobImpl::MimeBoundaryGenerator::~MimeBoundaryGenerator() { | 42 UploadJobImpl::MimeBoundaryGenerator::~MimeBoundaryGenerator() { |
63 } | 43 } |
64 | 44 |
65 UploadJobImpl::RandomMimeBoundaryGenerator::~RandomMimeBoundaryGenerator() { | 45 UploadJobImpl::RandomMimeBoundaryGenerator::~RandomMimeBoundaryGenerator() { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
138 bool DataSegment::CheckIfDataContains(const std::string& chunk) { | 118 bool DataSegment::CheckIfDataContains(const std::string& chunk) { |
139 DCHECK(data_); | 119 DCHECK(data_); |
140 return data_->find(chunk) != std::string::npos; | 120 return data_->find(chunk) != std::string::npos; |
141 } | 121 } |
142 | 122 |
143 size_t DataSegment::GetDataSize() const { | 123 size_t DataSegment::GetDataSize() const { |
144 DCHECK(data_); | 124 DCHECK(data_); |
145 return data_->size(); | 125 return data_->size(); |
146 } | 126 } |
147 | 127 |
148 std::string UploadJobImpl::RandomMimeBoundaryGenerator::GenerateBoundary( | 128 std::string UploadJobImpl::RandomMimeBoundaryGenerator::GenerateBoundary() |
149 size_t length) const { | 129 const { |
150 std::string boundary; | 130 return net::GenerateMimeMultipartBoundary(); |
151 boundary.reserve(length); | |
152 DCHECK_GT(length, sizeof(kMultipartBoundaryPrefix) + | |
153 sizeof(kMultipartBoundaryPostfix)); | |
154 const size_t random_part_length = length - sizeof(kMultipartBoundaryPrefix) - | |
155 sizeof(kMultipartBoundaryPostfix); | |
156 boundary.append(kMultipartBoundaryPrefix); | |
157 boundary.append(GenerateRandomString(random_part_length)); | |
158 boundary.append(kMultipartBoundaryPostfix); | |
159 return boundary; | |
160 } | 131 } |
161 | 132 |
162 UploadJobImpl::UploadJobImpl( | 133 UploadJobImpl::UploadJobImpl( |
163 const GURL& upload_url, | 134 const GURL& upload_url, |
164 const std::string& account_id, | 135 const std::string& account_id, |
165 OAuth2TokenService* token_service, | 136 OAuth2TokenService* token_service, |
166 scoped_refptr<net::URLRequestContextGetter> url_context_getter, | 137 scoped_refptr<net::URLRequestContextGetter> url_context_getter, |
167 Delegate* delegate, | 138 Delegate* delegate, |
168 scoped_ptr<MimeBoundaryGenerator> boundary_generator) | 139 scoped_ptr<MimeBoundaryGenerator> boundary_generator) |
169 : OAuth2TokenService::Consumer("cros_upload_job"), | 140 : OAuth2TokenService::Consumer("cros_upload_job"), |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
234 return false; | 205 return false; |
235 } | 206 } |
236 | 207 |
237 // Generates random MIME boundaries and tests if they appear in any of the | 208 // Generates random MIME boundaries and tests if they appear in any of the |
238 // data segments. Tries up to |kMimeBoundaryRetries| times to find a MIME | 209 // data segments. Tries up to |kMimeBoundaryRetries| times to find a MIME |
239 // boundary that does not appear within any data segment. | 210 // boundary that does not appear within any data segment. |
240 bool found = false; | 211 bool found = false; |
241 int retry = 0; | 212 int retry = 0; |
242 do { | 213 do { |
243 found = true; | 214 found = true; |
244 mime_boundary_.reset(new std::string( | 215 mime_boundary_.reset( |
245 boundary_generator_->GenerateBoundary(kMimeBoundarySize))); | 216 new std::string(boundary_generator_->GenerateBoundary())); |
246 for (const auto& data_segment : data_segments_) { | 217 for (const auto& data_segment : data_segments_) { |
247 if (data_segment->CheckIfDataContains(*mime_boundary_)) { | 218 if (data_segment->CheckIfDataContains(*mime_boundary_)) { |
248 found = false; | 219 found = false; |
249 break; | 220 break; |
250 } | 221 } |
251 } | 222 } |
252 ++retry; | 223 ++retry; |
253 } while (!found && retry <= kMimeBoundaryRetries); | 224 } while (!found && retry <= kMimeBoundaryRetries); |
Ryan Sleevi
2015/12/28 23:30:00
This seems overly conservative/unnecessary with yo
Łukasz Anforowicz
2015/12/29 18:53:19
Done.
I think you have a good point wrt removing
| |
254 | 225 |
255 // Notify the delegate that content encoding failed. | 226 // Notify the delegate that content encoding failed. |
256 if (!found) { | 227 if (!found) { |
257 delegate_->OnFailure(CONTENT_ENCODING_ERROR); | 228 delegate_->OnFailure(CONTENT_ENCODING_ERROR); |
258 mime_boundary_.reset(); | 229 mime_boundary_.reset(); |
259 return false; | 230 return false; |
260 } | 231 } |
261 | 232 |
262 // Estimate an upper bound for the total message size to make memory | 233 // Estimate an upper bound for the total message size to make memory |
263 // allocation more efficient. It is not an error if this turns out to be too | 234 // allocation more efficient. It is not an error if this turns out to be too |
264 // small as std::string will take care of the realloc. | 235 // small as std::string will take care of the realloc. |
265 size_t size = 0; | 236 size_t size = 0; |
266 for (const auto& data_segment : data_segments_) { | 237 for (const auto& data_segment : data_segments_) { |
267 for (const auto& entry : data_segment->GetHeaderEntries()) | 238 for (const auto& entry : data_segment->GetHeaderEntries()) |
268 size += entry.first.size() + entry.second.size(); | 239 size += entry.first.size() + entry.second.size(); |
269 size += kMimeBoundarySize + data_segment->GetName().size() + | 240 size += kMaxMimeBoundarySize + data_segment->GetName().size() + |
270 data_segment->GetFilename().size() + data_segment->GetDataSize(); | 241 data_segment->GetFilename().size() + data_segment->GetDataSize(); |
271 // Add some extra space for all the constants and control characters. | 242 // Add some extra space for all the constants and control characters. |
272 size += 128; | 243 size += 128; |
273 } | 244 } |
274 | 245 |
275 // Allocate memory of the expected size. | 246 // Allocate memory of the expected size. |
276 post_data_.reset(new std::string); | 247 post_data_.reset(new std::string); |
277 post_data_->reserve(size); | 248 post_data_->reserve(size); |
278 | 249 |
279 for (const auto& data_segment : data_segments_) { | 250 for (const auto& data_segment : data_segments_) { |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
402 if (success) { | 373 if (success) { |
403 state_ = SUCCESS; | 374 state_ = SUCCESS; |
404 delegate_->OnSuccess(); | 375 delegate_->OnSuccess(); |
405 } else { | 376 } else { |
406 state_ = ERROR; | 377 state_ = ERROR; |
407 delegate_->OnFailure(SERVER_ERROR); | 378 delegate_->OnFailure(SERVER_ERROR); |
408 } | 379 } |
409 } | 380 } |
410 | 381 |
411 } // namespace policy | 382 } // namespace policy |
OLD | NEW |