Chromium Code Reviews| 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 |