Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Side by Side Diff: chrome/browser/chromeos/policy/upload_job_impl.cc

Issue 1547593002: Introducing a net::GenerateMimeMultipartBoundary helper. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebasing... Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698