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 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/rand_util.h" | 12 #include "base/rand_util.h" |
|
bartfab (slow)
2016/01/05 14:20:45
Nit: No longer used.
Łukasz Anforowicz
2016/01/05 19:16:48
Done.
| |
| 13 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
| 14 #include "google_apis/gaia/gaia_constants.h" | 14 #include "google_apis/gaia/gaia_constants.h" |
| 15 #include "google_apis/gaia/google_service_auth_error.h" | 15 #include "google_apis/gaia/google_service_auth_error.h" |
| 16 #include "net/base/mime_util.h" | |
| 16 #include "net/http/http_status_code.h" | 17 #include "net/http/http_status_code.h" |
| 17 #include "net/url_request/url_request_status.h" | 18 #include "net/url_request/url_request_status.h" |
| 18 | 19 |
| 19 namespace policy { | 20 namespace policy { |
| 20 | 21 |
| 21 namespace { | 22 namespace { |
| 22 | 23 |
| 23 // Defines the characters that might appear in strings generated by | |
| 24 // GenerateRandomString(). | |
| 25 const char kAlphaNum[] = | |
| 26 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | |
| 27 | |
| 28 // Format for bearer tokens in HTTP requests to access OAuth 2.0 protected | 24 // Format for bearer tokens in HTTP requests to access OAuth 2.0 protected |
| 29 // resources. | 25 // resources. |
| 30 const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s"; | 26 const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s"; |
| 31 | 27 |
| 32 // Prefix added to a randomly generated string when choosing the MIME boundary. | |
| 33 const char kMultipartBoundaryPrefix[] = "----**--"; | |
| 34 | |
| 35 // Postfix added to a randomly generated string when choosing the MIME boundary. | |
| 36 const char kMultipartBoundaryPostfix[] = "--**----"; | |
| 37 | |
| 38 // Value the "Content-Type" field will be set to in the POST request. | 28 // Value the "Content-Type" field will be set to in the POST request. |
| 39 const char kUploadContentType[] = "multipart/form-data"; | 29 const char kUploadContentType[] = "multipart/form-data"; |
| 40 | 30 |
| 41 // Number of retries when randomly generating a MIME boundary. | |
| 42 const int kMimeBoundaryRetries = 3; | |
| 43 | |
| 44 // Length of the random string for the MIME boundary. | |
| 45 const int kMimeBoundarySize = 32; | |
| 46 | |
| 47 // Number of upload retries. | 31 // Number of upload retries. |
| 48 const int kMaxRetries = 1; | 32 const int kMaxRetries = 1; |
| 49 | 33 |
| 50 // Generates a random alphanumeric string of length |length|. | 34 // Max size of MIME boundary according to RFC 1341, section 7.2.1. |
| 51 std::string GenerateRandomString(size_t length) { | 35 const size_t kMaxMimeBoundarySize = 70; |
|
bartfab (slow)
2016/01/05 14:20:45
Nit: #include <stddef.h>
Łukasz Anforowicz
2016/01/05 19:16:48
Done.
| |
| 52 std::string random; | |
| 53 random.reserve(length); | |
| 54 for (size_t i = 0; i < length; i++) | |
| 55 random.push_back(kAlphaNum[base::RandGenerator(sizeof(kAlphaNum) - 1)]); | |
| 56 return random; | |
| 57 } | |
| 58 | 36 |
| 59 } // namespace | 37 } // namespace |
| 60 | 38 |
| 61 UploadJobImpl::Delegate::~Delegate() { | 39 UploadJobImpl::Delegate::~Delegate() { |
| 62 } | 40 } |
| 63 | 41 |
| 64 UploadJobImpl::MimeBoundaryGenerator::~MimeBoundaryGenerator() { | 42 UploadJobImpl::MimeBoundaryGenerator::~MimeBoundaryGenerator() { |
| 65 } | 43 } |
| 66 | 44 |
| 67 UploadJobImpl::RandomMimeBoundaryGenerator::~RandomMimeBoundaryGenerator() { | 45 UploadJobImpl::RandomMimeBoundaryGenerator::~RandomMimeBoundaryGenerator() { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 90 const std::string& GetFilename() const; | 68 const std::string& GetFilename() const; |
| 91 | 69 |
| 92 // Returns the data contained in this DataSegment. Ownership is passed. | 70 // Returns the data contained in this DataSegment. Ownership is passed. |
| 93 scoped_ptr<std::string> GetData(); | 71 scoped_ptr<std::string> GetData(); |
| 94 | 72 |
| 95 // Returns the size in bytes of the blob in |data_|. | 73 // Returns the size in bytes of the blob in |data_|. |
| 96 size_t GetDataSize() const; | 74 size_t GetDataSize() const; |
| 97 | 75 |
| 98 // Helper method that performs a substring match of |chunk| in |data_|. | 76 // Helper method that performs a substring match of |chunk| in |data_|. |
| 99 // Returns |true| if |chunk| matches a substring, |false| otherwise. | 77 // Returns |true| if |chunk| matches a substring, |false| otherwise. |
| 100 bool CheckIfDataContains(const std::string& chunk); | 78 bool CheckIfDataContains(const std::string& chunk); |
|
bartfab (slow)
2016/01/05 14:20:45
Nit: This method is no longer used.
Łukasz Anforowicz
2016/01/05 19:16:48
Done. Thanks for catching this and other places w
| |
| 101 | 79 |
| 102 private: | 80 private: |
| 103 const std::string name_; | 81 const std::string name_; |
| 104 const std::string filename_; | 82 const std::string filename_; |
| 105 scoped_ptr<std::string> data_; | 83 scoped_ptr<std::string> data_; |
| 106 std::map<std::string, std::string> header_entries_; | 84 std::map<std::string, std::string> header_entries_; |
| 107 | 85 |
| 108 DISALLOW_COPY_AND_ASSIGN(DataSegment); | 86 DISALLOW_COPY_AND_ASSIGN(DataSegment); |
| 109 }; | 87 }; |
| 110 | 88 |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 140 bool DataSegment::CheckIfDataContains(const std::string& chunk) { | 118 bool DataSegment::CheckIfDataContains(const std::string& chunk) { |
| 141 DCHECK(data_); | 119 DCHECK(data_); |
| 142 return data_->find(chunk) != std::string::npos; | 120 return data_->find(chunk) != std::string::npos; |
| 143 } | 121 } |
| 144 | 122 |
| 145 size_t DataSegment::GetDataSize() const { | 123 size_t DataSegment::GetDataSize() const { |
| 146 DCHECK(data_); | 124 DCHECK(data_); |
| 147 return data_->size(); | 125 return data_->size(); |
| 148 } | 126 } |
| 149 | 127 |
| 150 std::string UploadJobImpl::RandomMimeBoundaryGenerator::GenerateBoundary( | 128 std::string UploadJobImpl::RandomMimeBoundaryGenerator::GenerateBoundary() |
| 151 size_t length) const { | 129 const { |
| 152 std::string boundary; | 130 return net::GenerateMimeMultipartBoundary(); |
| 153 boundary.reserve(length); | |
| 154 DCHECK_GT(length, sizeof(kMultipartBoundaryPrefix) + | |
| 155 sizeof(kMultipartBoundaryPostfix)); | |
| 156 const size_t random_part_length = length - sizeof(kMultipartBoundaryPrefix) - | |
| 157 sizeof(kMultipartBoundaryPostfix); | |
| 158 boundary.append(kMultipartBoundaryPrefix); | |
| 159 boundary.append(GenerateRandomString(random_part_length)); | |
| 160 boundary.append(kMultipartBoundaryPostfix); | |
| 161 return boundary; | |
| 162 } | 131 } |
| 163 | 132 |
| 164 UploadJobImpl::UploadJobImpl( | 133 UploadJobImpl::UploadJobImpl( |
| 165 const GURL& upload_url, | 134 const GURL& upload_url, |
| 166 const std::string& account_id, | 135 const std::string& account_id, |
| 167 OAuth2TokenService* token_service, | 136 OAuth2TokenService* token_service, |
| 168 scoped_refptr<net::URLRequestContextGetter> url_context_getter, | 137 scoped_refptr<net::URLRequestContextGetter> url_context_getter, |
| 169 Delegate* delegate, | 138 Delegate* delegate, |
| 170 scoped_ptr<MimeBoundaryGenerator> boundary_generator) | 139 scoped_ptr<MimeBoundaryGenerator> boundary_generator) |
| 171 : OAuth2TokenService::Consumer("cros_upload_job"), | 140 : OAuth2TokenService::Consumer("cros_upload_job"), |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 229 return true; | 198 return true; |
| 230 | 199 |
| 231 std::set<std::string> used_names; | 200 std::set<std::string> used_names; |
| 232 | 201 |
| 233 // Check uniqueness of header field names. | 202 // Check uniqueness of header field names. |
| 234 for (const auto& data_segment : data_segments_) { | 203 for (const auto& data_segment : data_segments_) { |
| 235 if (!used_names.insert(data_segment->GetName()).second) | 204 if (!used_names.insert(data_segment->GetName()).second) |
| 236 return false; | 205 return false; |
| 237 } | 206 } |
| 238 | 207 |
| 239 // Generates random MIME boundaries and tests if they appear in any of the | 208 mime_boundary_.reset( |
| 240 // data segments. Tries up to |kMimeBoundaryRetries| times to find a MIME | 209 new std::string(boundary_generator_->GenerateBoundary())); |
| 241 // boundary that does not appear within any data segment. | |
| 242 bool found = false; | |
| 243 int retry = 0; | |
| 244 do { | |
| 245 found = true; | |
| 246 mime_boundary_.reset(new std::string( | |
| 247 boundary_generator_->GenerateBoundary(kMimeBoundarySize))); | |
| 248 for (const auto& data_segment : data_segments_) { | |
| 249 if (data_segment->CheckIfDataContains(*mime_boundary_)) { | |
| 250 found = false; | |
| 251 break; | |
| 252 } | |
| 253 } | |
| 254 ++retry; | |
| 255 } while (!found && retry <= kMimeBoundaryRetries); | |
| 256 | |
| 257 // Notify the delegate that content encoding failed. | |
| 258 if (!found) { | |
| 259 delegate_->OnFailure(CONTENT_ENCODING_ERROR); | |
|
bartfab (slow)
2016/01/05 14:20:45
Nit: Remove CONTENT_ENCODING_ERROR from upload_job
Łukasz Anforowicz
2016/01/05 19:16:48
Done.
| |
| 260 mime_boundary_.reset(); | |
| 261 return false; | |
| 262 } | |
| 263 | 210 |
| 264 // Estimate an upper bound for the total message size to make memory | 211 // Estimate an upper bound for the total message size to make memory |
| 265 // allocation more efficient. It is not an error if this turns out to be too | 212 // allocation more efficient. It is not an error if this turns out to be too |
| 266 // small as std::string will take care of the realloc. | 213 // small as std::string will take care of the realloc. |
| 267 size_t size = 0; | 214 size_t size = 0; |
| 268 for (const auto& data_segment : data_segments_) { | 215 for (const auto& data_segment : data_segments_) { |
| 269 for (const auto& entry : data_segment->GetHeaderEntries()) | 216 for (const auto& entry : data_segment->GetHeaderEntries()) |
| 270 size += entry.first.size() + entry.second.size(); | 217 size += entry.first.size() + entry.second.size(); |
| 271 size += kMimeBoundarySize + data_segment->GetName().size() + | 218 size += kMaxMimeBoundarySize + data_segment->GetName().size() + |
| 272 data_segment->GetFilename().size() + data_segment->GetDataSize(); | 219 data_segment->GetFilename().size() + data_segment->GetDataSize(); |
| 273 // Add some extra space for all the constants and control characters. | 220 // Add some extra space for all the constants and control characters. |
| 274 size += 128; | 221 size += 128; |
| 275 } | 222 } |
| 276 | 223 |
| 277 // Allocate memory of the expected size. | 224 // Allocate memory of the expected size. |
| 278 post_data_.reset(new std::string); | 225 post_data_.reset(new std::string); |
| 279 post_data_->reserve(size); | 226 post_data_->reserve(size); |
| 280 | 227 |
| 281 for (const auto& data_segment : data_segments_) { | 228 for (const auto& data_segment : data_segments_) { |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 404 if (success) { | 351 if (success) { |
| 405 state_ = SUCCESS; | 352 state_ = SUCCESS; |
| 406 delegate_->OnSuccess(); | 353 delegate_->OnSuccess(); |
| 407 } else { | 354 } else { |
| 408 state_ = ERROR; | 355 state_ = ERROR; |
| 409 delegate_->OnFailure(SERVER_ERROR); | 356 delegate_->OnFailure(SERVER_ERROR); |
| 410 } | 357 } |
| 411 } | 358 } |
| 412 | 359 |
| 413 } // namespace policy | 360 } // namespace policy |
| OLD | NEW |