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

Side by Side Diff: net/http/http_response_headers.cc

Issue 266243004: Clang format slam. Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 // The rules for header parsing were borrowed from Firefox: 5 // The rules for header parsing were borrowed from Firefox:
6 // http://lxr.mozilla.org/seamonkey/source/netwerk/protocol/http/src/nsHttpRespo nseHead.cpp 6 // http://lxr.mozilla.org/seamonkey/source/netwerk/protocol/http/src/nsHttpRespo nseHead.cpp
7 // The rules for parsing content-types were also borrowed from Firefox: 7 // The rules for parsing content-types were also borrowed from Firefox:
8 // http://lxr.mozilla.org/mozilla/source/netwerk/base/src/nsURLHelper.cpp#834 8 // http://lxr.mozilla.org/mozilla/source/netwerk/base/src/nsURLHelper.cpp#834
9 9
10 #include "net/http/http_response_headers.h" 10 #include "net/http/http_response_headers.h"
(...skipping 26 matching lines...) Expand all
37 37
38 namespace net { 38 namespace net {
39 39
40 //----------------------------------------------------------------------------- 40 //-----------------------------------------------------------------------------
41 41
42 namespace { 42 namespace {
43 43
44 // These headers are RFC 2616 hop-by-hop headers; 44 // These headers are RFC 2616 hop-by-hop headers;
45 // not to be stored by caches. 45 // not to be stored by caches.
46 const char* const kHopByHopResponseHeaders[] = { 46 const char* const kHopByHopResponseHeaders[] = {
47 "connection", 47 "connection", "proxy-connection", "keep-alive",
48 "proxy-connection", 48 "trailer", "transfer-encoding", "upgrade"};
49 "keep-alive",
50 "trailer",
51 "transfer-encoding",
52 "upgrade"
53 };
54 49
55 // These headers are challenge response headers; 50 // These headers are challenge response headers;
56 // not to be stored by caches. 51 // not to be stored by caches.
57 const char* const kChallengeResponseHeaders[] = { 52 const char* const kChallengeResponseHeaders[] = {"www-authenticate",
58 "www-authenticate", 53 "proxy-authenticate"};
59 "proxy-authenticate"
60 };
61 54
62 // These headers are cookie setting headers; 55 // These headers are cookie setting headers;
63 // not to be stored by caches or disclosed otherwise. 56 // not to be stored by caches or disclosed otherwise.
64 const char* const kCookieResponseHeaders[] = { 57 const char* const kCookieResponseHeaders[] = {"set-cookie", "set-cookie2"};
65 "set-cookie",
66 "set-cookie2"
67 };
68 58
69 // By default, do not cache Strict-Transport-Security or Public-Key-Pins. 59 // By default, do not cache Strict-Transport-Security or Public-Key-Pins.
70 // This avoids erroneously re-processing them on page loads from cache --- 60 // This avoids erroneously re-processing them on page loads from cache ---
71 // they are defined to be valid only on live and error-free HTTPS 61 // they are defined to be valid only on live and error-free HTTPS
72 // connections. 62 // connections.
73 const char* const kSecurityStateHeaders[] = { 63 const char* const kSecurityStateHeaders[] = {"strict-transport-security",
74 "strict-transport-security", 64 "public-key-pins"};
75 "public-key-pins"
76 };
77 65
78 // These response headers are not copied from a 304/206 response to the cached 66 // These response headers are not copied from a 304/206 response to the cached
79 // response headers. This list is based on Mozilla's nsHttpResponseHead.cpp. 67 // response headers. This list is based on Mozilla's nsHttpResponseHead.cpp.
80 const char* const kNonUpdatedHeaders[] = { 68 const char* const kNonUpdatedHeaders[] = {
81 "connection", 69 "connection", "proxy-connection", "keep-alive",
82 "proxy-connection", 70 "www-authenticate", "proxy-authenticate", "trailer",
83 "keep-alive", 71 "transfer-encoding", "upgrade", "etag",
84 "www-authenticate", 72 "x-frame-options", "x-xss-protection",
85 "proxy-authenticate",
86 "trailer",
87 "transfer-encoding",
88 "upgrade",
89 "etag",
90 "x-frame-options",
91 "x-xss-protection",
92 }; 73 };
93 74
94 // Some header prefixes mean "Don't copy this header from a 304 response.". 75 // Some header prefixes mean "Don't copy this header from a 304 response.".
95 // Rather than listing all the relevant headers, we can consolidate them into 76 // Rather than listing all the relevant headers, we can consolidate them into
96 // this list: 77 // this list:
97 const char* const kNonUpdatedHeaderPrefixes[] = { 78 const char* const kNonUpdatedHeaderPrefixes[] = {"content-", "x-content-",
98 "content-", 79 "x-webkit-"};
99 "x-content-",
100 "x-webkit-"
101 };
102 80
103 bool ShouldUpdateHeader(const std::string::const_iterator& name_begin, 81 bool ShouldUpdateHeader(const std::string::const_iterator& name_begin,
104 const std::string::const_iterator& name_end) { 82 const std::string::const_iterator& name_end) {
105 for (size_t i = 0; i < arraysize(kNonUpdatedHeaders); ++i) { 83 for (size_t i = 0; i < arraysize(kNonUpdatedHeaders); ++i) {
106 if (LowerCaseEqualsASCII(name_begin, name_end, kNonUpdatedHeaders[i])) 84 if (LowerCaseEqualsASCII(name_begin, name_end, kNonUpdatedHeaders[i]))
107 return false; 85 return false;
108 } 86 }
109 for (size_t i = 0; i < arraysize(kNonUpdatedHeaderPrefixes); ++i) { 87 for (size_t i = 0; i < arraysize(kNonUpdatedHeaderPrefixes); ++i) {
110 if (StartsWithASCII(std::string(name_begin, name_end), 88 if (StartsWithASCII(std::string(name_begin, name_end),
111 kNonUpdatedHeaderPrefixes[i], false)) 89 kNonUpdatedHeaderPrefixes[i],
90 false))
112 return false; 91 return false;
113 } 92 }
114 return true; 93 return true;
115 } 94 }
116 95
117 void CheckDoesNotHaveEmbededNulls(const std::string& str) { 96 void CheckDoesNotHaveEmbededNulls(const std::string& str) {
118 // Care needs to be taken when adding values to the raw headers string to 97 // Care needs to be taken when adding values to the raw headers string to
119 // make sure it does not contain embeded NULLs. Any embeded '\0' may be 98 // make sure it does not contain embeded NULLs. Any embeded '\0' may be
120 // understood as line terminators and change how header lines get tokenized. 99 // understood as line terminators and change how header lines get tokenized.
121 CHECK(str.find('\0') == std::string::npos); 100 CHECK(str.find('\0') == std::string::npos);
(...skipping 23 matching lines...) Expand all
145 // The most important thing to do with this histogram is find out 124 // The most important thing to do with this histogram is find out
146 // the existence of unusual HTTP status codes. As it happens 125 // the existence of unusual HTTP status codes. As it happens
147 // right now, there aren't double-constructions of response headers 126 // right now, there aren't double-constructions of response headers
148 // using this constructor, so our counts should also be accurate, 127 // using this constructor, so our counts should also be accurate,
149 // without instantiating the histogram in two places. It is also 128 // without instantiating the histogram in two places. It is also
150 // important that this histogram not collect data in the other 129 // important that this histogram not collect data in the other
151 // constructor, which rebuilds an histogram from a pickle, since 130 // constructor, which rebuilds an histogram from a pickle, since
152 // that would actually create a double call between the original 131 // that would actually create a double call between the original
153 // HttpResponseHeader that was serialized, and initialization of the 132 // HttpResponseHeader that was serialized, and initialization of the
154 // new object from that pickle. 133 // new object from that pickle.
155 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.HttpResponseCode", 134 UMA_HISTOGRAM_CUSTOM_ENUMERATION(
156 HttpUtil::MapStatusCodeForHistogram( 135 "Net.HttpResponseCode",
157 response_code_), 136 HttpUtil::MapStatusCodeForHistogram(response_code_),
158 // Note the third argument is only 137 // Note the third argument is only
159 // evaluated once, see macro 138 // evaluated once, see macro
160 // definition for details. 139 // definition for details.
161 HttpUtil::GetStatusCodesForHistogram()); 140 HttpUtil::GetStatusCodesForHistogram());
162 } 141 }
163 142
164 HttpResponseHeaders::HttpResponseHeaders(const Pickle& pickle, 143 HttpResponseHeaders::HttpResponseHeaders(const Pickle& pickle,
165 PickleIterator* iter) 144 PickleIterator* iter)
166 : response_code_(-1) { 145 : response_code_(-1) {
167 std::string raw_input; 146 std::string raw_input;
168 if (pickle.ReadString(iter, &raw_input)) 147 if (pickle.ReadString(iter, &raw_input))
169 Parse(raw_input); 148 Parse(raw_input);
170 } 149 }
171 150
(...skipping 30 matching lines...) Expand all
202 // This copies the status line w/ terminator null. 181 // This copies the status line w/ terminator null.
203 // Note raw_headers_ has embedded nulls instead of \n, 182 // Note raw_headers_ has embedded nulls instead of \n,
204 // so this just copies the first header line. 183 // so this just copies the first header line.
205 blob.assign(raw_headers_.c_str(), strlen(raw_headers_.c_str()) + 1); 184 blob.assign(raw_headers_.c_str(), strlen(raw_headers_.c_str()) + 1);
206 185
207 for (size_t i = 0; i < parsed_.size(); ++i) { 186 for (size_t i = 0; i < parsed_.size(); ++i) {
208 DCHECK(!parsed_[i].is_continuation()); 187 DCHECK(!parsed_[i].is_continuation());
209 188
210 // Locate the start of the next header. 189 // Locate the start of the next header.
211 size_t k = i; 190 size_t k = i;
212 while (++k < parsed_.size() && parsed_[k].is_continuation()) {} 191 while (++k < parsed_.size() && parsed_[k].is_continuation()) {
192 }
213 --k; 193 --k;
214 194
215 std::string header_name(parsed_[i].name_begin, parsed_[i].name_end); 195 std::string header_name(parsed_[i].name_begin, parsed_[i].name_end);
216 StringToLowerASCII(&header_name); 196 StringToLowerASCII(&header_name);
217 197
218 if (filter_headers.find(header_name) == filter_headers.end()) { 198 if (filter_headers.find(header_name) == filter_headers.end()) {
219 // Make sure there is a null after the value. 199 // Make sure there is a null after the value.
220 blob.append(parsed_[i].name_begin, parsed_[k].value_end); 200 blob.append(parsed_[i].name_begin, parsed_[k].value_end);
221 blob.push_back('\0'); 201 blob.push_back('\0');
222 } 202 }
(...skipping 19 matching lines...) Expand all
242 // order should not matter. 222 // order should not matter.
243 223
244 // Figure out which headers we want to take from new_headers: 224 // Figure out which headers we want to take from new_headers:
245 for (size_t i = 0; i < new_headers.parsed_.size(); ++i) { 225 for (size_t i = 0; i < new_headers.parsed_.size(); ++i) {
246 const HeaderList& new_parsed = new_headers.parsed_; 226 const HeaderList& new_parsed = new_headers.parsed_;
247 227
248 DCHECK(!new_parsed[i].is_continuation()); 228 DCHECK(!new_parsed[i].is_continuation());
249 229
250 // Locate the start of the next header. 230 // Locate the start of the next header.
251 size_t k = i; 231 size_t k = i;
252 while (++k < new_parsed.size() && new_parsed[k].is_continuation()) {} 232 while (++k < new_parsed.size() && new_parsed[k].is_continuation()) {
233 }
253 --k; 234 --k;
254 235
255 const std::string::const_iterator& name_begin = new_parsed[i].name_begin; 236 const std::string::const_iterator& name_begin = new_parsed[i].name_begin;
256 const std::string::const_iterator& name_end = new_parsed[i].name_end; 237 const std::string::const_iterator& name_end = new_parsed[i].name_end;
257 if (ShouldUpdateHeader(name_begin, name_end)) { 238 if (ShouldUpdateHeader(name_begin, name_end)) {
258 std::string name(name_begin, name_end); 239 std::string name(name_begin, name_end);
259 StringToLowerASCII(&name); 240 StringToLowerASCII(&name);
260 updated_headers.insert(name); 241 updated_headers.insert(name);
261 242
262 // Preserve this header line in the merged result, making sure there is 243 // Preserve this header line in the merged result, making sure there is
(...skipping 10 matching lines...) Expand all
273 } 254 }
274 255
275 void HttpResponseHeaders::MergeWithHeaders(const std::string& raw_headers, 256 void HttpResponseHeaders::MergeWithHeaders(const std::string& raw_headers,
276 const HeaderSet& headers_to_remove) { 257 const HeaderSet& headers_to_remove) {
277 std::string new_raw_headers(raw_headers); 258 std::string new_raw_headers(raw_headers);
278 for (size_t i = 0; i < parsed_.size(); ++i) { 259 for (size_t i = 0; i < parsed_.size(); ++i) {
279 DCHECK(!parsed_[i].is_continuation()); 260 DCHECK(!parsed_[i].is_continuation());
280 261
281 // Locate the start of the next header. 262 // Locate the start of the next header.
282 size_t k = i; 263 size_t k = i;
283 while (++k < parsed_.size() && parsed_[k].is_continuation()) {} 264 while (++k < parsed_.size() && parsed_[k].is_continuation()) {
265 }
284 --k; 266 --k;
285 267
286 std::string name(parsed_[i].name_begin, parsed_[i].name_end); 268 std::string name(parsed_[i].name_begin, parsed_[i].name_end);
287 StringToLowerASCII(&name); 269 StringToLowerASCII(&name);
288 if (headers_to_remove.find(name) == headers_to_remove.end()) { 270 if (headers_to_remove.find(name) == headers_to_remove.end()) {
289 // It's ok to preserve this header in the final result. 271 // It's ok to preserve this header in the final result.
290 new_raw_headers.append(parsed_[i].name_begin, parsed_[k].value_end); 272 new_raw_headers.append(parsed_[i].name_begin, parsed_[k].value_end);
291 new_raw_headers.push_back('\0'); 273 new_raw_headers.push_back('\0');
292 } 274 }
293 275
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 void HttpResponseHeaders::ReplaceStatusLine(const std::string& new_status) { 349 void HttpResponseHeaders::ReplaceStatusLine(const std::string& new_status) {
368 CheckDoesNotHaveEmbededNulls(new_status); 350 CheckDoesNotHaveEmbededNulls(new_status);
369 // Copy up to the null byte. This just copies the status line. 351 // Copy up to the null byte. This just copies the status line.
370 std::string new_raw_headers(new_status); 352 std::string new_raw_headers(new_status);
371 new_raw_headers.push_back('\0'); 353 new_raw_headers.push_back('\0');
372 354
373 HeaderSet empty_to_remove; 355 HeaderSet empty_to_remove;
374 MergeWithHeaders(new_raw_headers, empty_to_remove); 356 MergeWithHeaders(new_raw_headers, empty_to_remove);
375 } 357 }
376 358
377 void HttpResponseHeaders::UpdateWithNewRange( 359 void HttpResponseHeaders::UpdateWithNewRange(const HttpByteRange& byte_range,
378 const HttpByteRange& byte_range, 360 int64 resource_size,
379 int64 resource_size, 361 bool replace_status_line) {
380 bool replace_status_line) {
381 DCHECK(byte_range.IsValid()); 362 DCHECK(byte_range.IsValid());
382 DCHECK(byte_range.HasFirstBytePosition()); 363 DCHECK(byte_range.HasFirstBytePosition());
383 DCHECK(byte_range.HasLastBytePosition()); 364 DCHECK(byte_range.HasLastBytePosition());
384 365
385 const char kLengthHeader[] = "Content-Length"; 366 const char kLengthHeader[] = "Content-Length";
386 const char kRangeHeader[] = "Content-Range"; 367 const char kRangeHeader[] = "Content-Range";
387 368
388 RemoveHeader(kLengthHeader); 369 RemoveHeader(kLengthHeader);
389 RemoveHeader(kRangeHeader); 370 RemoveHeader(kRangeHeader);
390 371
391 int64 start = byte_range.first_byte_position(); 372 int64 start = byte_range.first_byte_position();
392 int64 end = byte_range.last_byte_position(); 373 int64 end = byte_range.last_byte_position();
393 int64 range_len = end - start + 1; 374 int64 range_len = end - start + 1;
394 375
395 if (replace_status_line) 376 if (replace_status_line)
396 ReplaceStatusLine("HTTP/1.1 206 Partial Content"); 377 ReplaceStatusLine("HTTP/1.1 206 Partial Content");
397 378
398 AddHeader(base::StringPrintf("%s: bytes %" PRId64 "-%" PRId64 "/%" PRId64, 379 AddHeader(base::StringPrintf("%s: bytes %" PRId64 "-%" PRId64 "/%" PRId64,
399 kRangeHeader, start, end, resource_size)); 380 kRangeHeader,
381 start,
382 end,
383 resource_size));
400 AddHeader(base::StringPrintf("%s: %" PRId64, kLengthHeader, range_len)); 384 AddHeader(base::StringPrintf("%s: %" PRId64, kLengthHeader, range_len));
401 } 385 }
402 386
403 void HttpResponseHeaders::Parse(const std::string& raw_input) { 387 void HttpResponseHeaders::Parse(const std::string& raw_input) {
404 raw_headers_.reserve(raw_input.size()); 388 raw_headers_.reserve(raw_input.size());
405 389
406 // ParseStatusLine adds a normalized status line to raw_headers_ 390 // ParseStatusLine adds a normalized status line to raw_headers_
407 std::string::const_iterator line_begin = raw_input.begin(); 391 std::string::const_iterator line_begin = raw_input.begin();
408 std::string::const_iterator line_end = 392 std::string::const_iterator line_end =
409 std::find(line_begin, raw_input.end(), '\0'); 393 std::find(line_begin, raw_input.end(), '\0');
410 // has_headers = true, if there is any data following the status line. 394 // has_headers = true, if there is any data following the status line.
411 // Used by ParseStatusLine() to decide if a HTTP/0.9 is really a HTTP/1.0. 395 // Used by ParseStatusLine() to decide if a HTTP/0.9 is really a HTTP/1.0.
412 bool has_headers = (line_end != raw_input.end() && 396 bool has_headers =
413 (line_end + 1) != raw_input.end() && 397 (line_end != raw_input.end() && (line_end + 1) != raw_input.end() &&
414 *(line_end + 1) != '\0'); 398 *(line_end + 1) != '\0');
415 ParseStatusLine(line_begin, line_end, has_headers); 399 ParseStatusLine(line_begin, line_end, has_headers);
416 raw_headers_.push_back('\0'); // Terminate status line with a null. 400 raw_headers_.push_back('\0'); // Terminate status line with a null.
417 401
418 if (line_end == raw_input.end()) { 402 if (line_end == raw_input.end()) {
419 raw_headers_.push_back('\0'); // Ensure the headers end with a double null. 403 raw_headers_.push_back('\0'); // Ensure the headers end with a double null.
420 404
421 DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 2]); 405 DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 2]);
422 DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 1]); 406 DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 1]);
423 return; 407 return;
424 } 408 }
425 409
426 // Including a terminating null byte. 410 // Including a terminating null byte.
427 size_t status_line_len = raw_headers_.size(); 411 size_t status_line_len = raw_headers_.size();
428 412
429 // Now, we add the rest of the raw headers to raw_headers_, and begin parsing 413 // Now, we add the rest of the raw headers to raw_headers_, and begin parsing
430 // it (to populate our parsed_ vector). 414 // it (to populate our parsed_ vector).
431 raw_headers_.append(line_end + 1, raw_input.end()); 415 raw_headers_.append(line_end + 1, raw_input.end());
432 416
433 // Ensure the headers end with a double null. 417 // Ensure the headers end with a double null.
434 while (raw_headers_.size() < 2 || 418 while (raw_headers_.size() < 2 ||
435 raw_headers_[raw_headers_.size() - 2] != '\0' || 419 raw_headers_[raw_headers_.size() - 2] != '\0' ||
436 raw_headers_[raw_headers_.size() - 1] != '\0') { 420 raw_headers_[raw_headers_.size() - 1] != '\0') {
437 raw_headers_.push_back('\0'); 421 raw_headers_.push_back('\0');
438 } 422 }
439 423
440 // Adjust to point at the null byte following the status line 424 // Adjust to point at the null byte following the status line
441 line_end = raw_headers_.begin() + status_line_len - 1; 425 line_end = raw_headers_.begin() + status_line_len - 1;
442 426
443 HttpUtil::HeadersIterator headers(line_end + 1, raw_headers_.end(), 427 HttpUtil::HeadersIterator headers(
444 std::string(1, '\0')); 428 line_end + 1, raw_headers_.end(), std::string(1, '\0'));
445 while (headers.GetNext()) { 429 while (headers.GetNext()) {
446 AddHeader(headers.name_begin(), 430 AddHeader(headers.name_begin(),
447 headers.name_end(), 431 headers.name_end(),
448 headers.values_begin(), 432 headers.values_begin(),
449 headers.values_end()); 433 headers.values_end());
450 } 434 }
451 435
452 DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 2]); 436 DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 2]);
453 DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 1]); 437 DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 1]);
454 } 438 }
(...skipping 21 matching lines...) Expand all
476 std::vector<std::string> headers; 460 std::vector<std::string> headers;
477 461
478 for (size_t i = 0; i < parsed_.size(); ++i) { 462 for (size_t i = 0; i < parsed_.size(); ++i) {
479 DCHECK(!parsed_[i].is_continuation()); 463 DCHECK(!parsed_[i].is_continuation());
480 464
481 std::string name(parsed_[i].name_begin, parsed_[i].name_end); 465 std::string name(parsed_[i].name_begin, parsed_[i].name_end);
482 std::string lower_name = StringToLowerASCII(name); 466 std::string lower_name = StringToLowerASCII(name);
483 467
484 iter = headers_map.find(lower_name); 468 iter = headers_map.find(lower_name);
485 if (iter == headers_map.end()) { 469 if (iter == headers_map.end()) {
486 iter = headers_map.insert( 470 iter = headers_map.insert(HeadersMap::value_type(lower_name,
487 HeadersMap::value_type(lower_name, headers.size())).first; 471 headers.size())).first;
488 headers.push_back(name + ": "); 472 headers.push_back(name + ": ");
489 } else { 473 } else {
490 headers[iter->second].append(", "); 474 headers[iter->second].append(", ");
491 } 475 }
492 476
493 std::string::const_iterator value_begin = parsed_[i].value_begin; 477 std::string::const_iterator value_begin = parsed_[i].value_begin;
494 std::string::const_iterator value_end = parsed_[i].value_end; 478 std::string::const_iterator value_end = parsed_[i].value_end;
495 while (++i < parsed_.size() && parsed_[i].is_continuation()) 479 while (++i < parsed_.size() && parsed_[i].is_continuation())
496 value_end = parsed_[i].value_end; 480 value_end = parsed_[i].value_end;
497 --i; 481 --i;
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 } 585 }
602 586
603 bool HttpResponseHeaders::HasHeaderValue(const base::StringPiece& name, 587 bool HttpResponseHeaders::HasHeaderValue(const base::StringPiece& name,
604 const base::StringPiece& value) const { 588 const base::StringPiece& value) const {
605 // The value has to be an exact match. This is important since 589 // The value has to be an exact match. This is important since
606 // 'cache-control: no-cache' != 'cache-control: no-cache="foo"' 590 // 'cache-control: no-cache' != 'cache-control: no-cache="foo"'
607 void* iter = NULL; 591 void* iter = NULL;
608 std::string temp; 592 std::string temp;
609 while (EnumerateHeader(&iter, name, &temp)) { 593 while (EnumerateHeader(&iter, name, &temp)) {
610 if (value.size() == temp.size() && 594 if (value.size() == temp.size() &&
611 std::equal(temp.begin(), temp.end(), value.begin(), 595 std::equal(temp.begin(),
596 temp.end(),
597 value.begin(),
612 base::CaseInsensitiveCompare<char>())) 598 base::CaseInsensitiveCompare<char>()))
613 return true; 599 return true;
614 } 600 }
615 return false; 601 return false;
616 } 602 }
617 603
618 bool HttpResponseHeaders::HasHeader(const base::StringPiece& name) const { 604 bool HttpResponseHeaders::HasHeader(const base::StringPiece& name) const {
619 return FindHeader(0, name) != std::string::npos; 605 return FindHeader(0, name) != std::string::npos;
620 } 606 }
621 607
(...skipping 26 matching lines...) Expand all
648 DVLOG(1) << "missing version"; 634 DVLOG(1) << "missing version";
649 return HttpVersion(); 635 return HttpVersion();
650 } 636 }
651 637
652 std::string::const_iterator dot = std::find(p, line_end, '.'); 638 std::string::const_iterator dot = std::find(p, line_end, '.');
653 if (dot == line_end) { 639 if (dot == line_end) {
654 DVLOG(1) << "malformed version"; 640 DVLOG(1) << "malformed version";
655 return HttpVersion(); 641 return HttpVersion();
656 } 642 }
657 643
658 ++p; // from / to first digit. 644 ++p; // from / to first digit.
659 ++dot; // from . to second digit. 645 ++dot; // from . to second digit.
660 646
661 if (!(*p >= '0' && *p <= '9' && *dot >= '0' && *dot <= '9')) { 647 if (!(*p >= '0' && *p <= '9' && *dot >= '0' && *dot <= '9')) {
662 DVLOG(1) << "malformed version number"; 648 DVLOG(1) << "malformed version number";
663 return HttpVersion(); 649 return HttpVersion();
664 } 650 }
665 651
666 uint16 major = *p - '0'; 652 uint16 major = *p - '0';
667 uint16 minor = *dot - '0'; 653 uint16 minor = *dot - '0';
668 654
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 } 729 }
744 730
745 size_t HttpResponseHeaders::FindHeader(size_t from, 731 size_t HttpResponseHeaders::FindHeader(size_t from,
746 const base::StringPiece& search) const { 732 const base::StringPiece& search) const {
747 for (size_t i = from; i < parsed_.size(); ++i) { 733 for (size_t i = from; i < parsed_.size(); ++i) {
748 if (parsed_[i].is_continuation()) 734 if (parsed_[i].is_continuation())
749 continue; 735 continue;
750 const std::string::const_iterator& name_begin = parsed_[i].name_begin; 736 const std::string::const_iterator& name_begin = parsed_[i].name_begin;
751 const std::string::const_iterator& name_end = parsed_[i].name_end; 737 const std::string::const_iterator& name_end = parsed_[i].name_end;
752 if (static_cast<size_t>(name_end - name_begin) == search.size() && 738 if (static_cast<size_t>(name_end - name_begin) == search.size() &&
753 std::equal(name_begin, name_end, search.begin(), 739 std::equal(name_begin,
740 name_end,
741 search.begin(),
754 base::CaseInsensitiveCompare<char>())) 742 base::CaseInsensitiveCompare<char>()))
755 return i; 743 return i;
756 } 744 }
757 745
758 return std::string::npos; 746 return std::string::npos;
759 } 747 }
760 748
761 void HttpResponseHeaders::AddHeader(std::string::const_iterator name_begin, 749 void HttpResponseHeaders::AddHeader(std::string::const_iterator name_begin,
762 std::string::const_iterator name_end, 750 std::string::const_iterator name_end,
763 std::string::const_iterator values_begin, 751 std::string::const_iterator values_begin,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
799 std::string value; 787 std::string value;
800 void* iter = NULL; 788 void* iter = NULL;
801 while (EnumerateHeader(&iter, kCacheControl, &value)) { 789 while (EnumerateHeader(&iter, kCacheControl, &value)) {
802 // If the value is smaller than the prefix and a terminal quote, skip 790 // If the value is smaller than the prefix and a terminal quote, skip
803 // it. 791 // it.
804 if (value.size() <= kPrefixLen || 792 if (value.size() <= kPrefixLen ||
805 value.compare(0, kPrefixLen, kPrefix) != 0) { 793 value.compare(0, kPrefixLen, kPrefix) != 0) {
806 continue; 794 continue;
807 } 795 }
808 // if it doesn't end with a quote, then treat as malformed 796 // if it doesn't end with a quote, then treat as malformed
809 if (value[value.size()-1] != '\"') 797 if (value[value.size() - 1] != '\"')
810 continue; 798 continue;
811 799
812 // process the value as a comma-separated list of items. Each 800 // process the value as a comma-separated list of items. Each
813 // item can be wrapped by linear white space. 801 // item can be wrapped by linear white space.
814 std::string::const_iterator item = value.begin() + kPrefixLen; 802 std::string::const_iterator item = value.begin() + kPrefixLen;
815 std::string::const_iterator end = value.end() - 1; 803 std::string::const_iterator end = value.end() - 1;
816 while (item != end) { 804 while (item != end) {
817 // Find the comma to compute the length of the current item, 805 // Find the comma to compute the length of the current item,
818 // and the position of the next one. 806 // and the position of the next one.
819 std::string::const_iterator item_next = std::find(item, end, ','); 807 std::string::const_iterator item_next = std::find(item, end, ',');
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
912 std::string(parsed_[i].value_begin, parsed_[i].value_end)); 900 std::string(parsed_[i].value_begin, parsed_[i].value_end));
913 } 901 }
914 902
915 return true; 903 return true;
916 } 904 }
917 905
918 // static 906 // static
919 bool HttpResponseHeaders::IsRedirectResponseCode(int response_code) { 907 bool HttpResponseHeaders::IsRedirectResponseCode(int response_code) {
920 // Users probably want to see 300 (multiple choice) pages, so we don't count 908 // Users probably want to see 300 (multiple choice) pages, so we don't count
921 // them as redirects that need to be followed. 909 // them as redirects that need to be followed.
922 return (response_code == 301 || 910 return (response_code == 301 || response_code == 302 ||
923 response_code == 302 || 911 response_code == 303 || response_code == 307 || response_code == 308);
924 response_code == 303 ||
925 response_code == 307 ||
926 response_code == 308);
927 } 912 }
928 913
929 // From RFC 2616 section 13.2.4: 914 // From RFC 2616 section 13.2.4:
930 // 915 //
931 // The calculation to determine if a response has expired is quite simple: 916 // The calculation to determine if a response has expired is quite simple:
932 // 917 //
933 // response_is_fresh = (freshness_lifetime > current_age) 918 // response_is_fresh = (freshness_lifetime > current_age)
934 // 919 //
935 // Of course, there are other factors that can force a response to always be 920 // Of course, there are other factors that can force a response to always be
936 // validated or re-fetched. 921 // validated or re-fetched.
937 // 922 //
938 bool HttpResponseHeaders::RequiresValidation(const Time& request_time, 923 bool HttpResponseHeaders::RequiresValidation(const Time& request_time,
939 const Time& response_time, 924 const Time& response_time,
940 const Time& current_time) const { 925 const Time& current_time) const {
941 TimeDelta lifetime = 926 TimeDelta lifetime = GetFreshnessLifetime(response_time);
942 GetFreshnessLifetime(response_time);
943 if (lifetime == TimeDelta()) 927 if (lifetime == TimeDelta())
944 return true; 928 return true;
945 929
946 return lifetime <= GetCurrentAge(request_time, response_time, current_time); 930 return lifetime <= GetCurrentAge(request_time, response_time, current_time);
947 } 931 }
948 932
949 // From RFC 2616 section 13.2.4: 933 // From RFC 2616 section 13.2.4:
950 // 934 //
951 // The max-age directive takes priority over Expires, so if max-age is present 935 // The max-age directive takes priority over Expires, so if max-age is present
952 // in a response, the calculation is simply: 936 // in a response, the calculation is simply:
(...skipping 15 matching lines...) Expand all
968 // 952 //
969 TimeDelta HttpResponseHeaders::GetFreshnessLifetime( 953 TimeDelta HttpResponseHeaders::GetFreshnessLifetime(
970 const Time& response_time) const { 954 const Time& response_time) const {
971 // Check for headers that force a response to never be fresh. For backwards 955 // Check for headers that force a response to never be fresh. For backwards
972 // compat, we treat "Pragma: no-cache" as a synonym for "Cache-Control: 956 // compat, we treat "Pragma: no-cache" as a synonym for "Cache-Control:
973 // no-cache" even though RFC 2616 does not specify it. 957 // no-cache" even though RFC 2616 does not specify it.
974 if (HasHeaderValue("cache-control", "no-cache") || 958 if (HasHeaderValue("cache-control", "no-cache") ||
975 HasHeaderValue("cache-control", "no-store") || 959 HasHeaderValue("cache-control", "no-store") ||
976 HasHeaderValue("pragma", "no-cache") || 960 HasHeaderValue("pragma", "no-cache") ||
977 HasHeaderValue("vary", "*")) // see RFC 2616 section 13.6 961 HasHeaderValue("vary", "*")) // see RFC 2616 section 13.6
978 return TimeDelta(); // not fresh 962 return TimeDelta(); // not fresh
979 963
980 // NOTE: "Cache-Control: max-age" overrides Expires, so we only check the 964 // NOTE: "Cache-Control: max-age" overrides Expires, so we only check the
981 // Expires header after checking for max-age in GetFreshnessLifetime. This 965 // Expires header after checking for max-age in GetFreshnessLifetime. This
982 // is important since "Expires: <date in the past>" means not fresh, but 966 // is important since "Expires: <date in the past>" means not fresh, but
983 // it should not trump a max-age value. 967 // it should not trump a max-age value.
984 968
985 TimeDelta max_age_value; 969 TimeDelta max_age_value;
986 if (GetMaxAgeValue(&max_age_value)) 970 if (GetMaxAgeValue(&max_age_value))
987 return max_age_value; 971 return max_age_value;
988 972
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1099 bool HttpResponseHeaders::GetMaxAgeValue(TimeDelta* result) const { 1083 bool HttpResponseHeaders::GetMaxAgeValue(TimeDelta* result) const {
1100 std::string name = "cache-control"; 1084 std::string name = "cache-control";
1101 std::string value; 1085 std::string value;
1102 1086
1103 const char kMaxAgePrefix[] = "max-age="; 1087 const char kMaxAgePrefix[] = "max-age=";
1104 const size_t kMaxAgePrefixLen = arraysize(kMaxAgePrefix) - 1; 1088 const size_t kMaxAgePrefixLen = arraysize(kMaxAgePrefix) - 1;
1105 1089
1106 void* iter = NULL; 1090 void* iter = NULL;
1107 while (EnumerateHeader(&iter, name, &value)) { 1091 while (EnumerateHeader(&iter, name, &value)) {
1108 if (value.size() > kMaxAgePrefixLen) { 1092 if (value.size() > kMaxAgePrefixLen) {
1109 if (LowerCaseEqualsASCII(value.begin(), 1093 if (LowerCaseEqualsASCII(
1110 value.begin() + kMaxAgePrefixLen, 1094 value.begin(), value.begin() + kMaxAgePrefixLen, kMaxAgePrefix)) {
1111 kMaxAgePrefix)) {
1112 int64 seconds; 1095 int64 seconds;
1113 base::StringToInt64(StringPiece(value.begin() + kMaxAgePrefixLen, 1096 base::StringToInt64(
1114 value.end()), 1097 StringPiece(value.begin() + kMaxAgePrefixLen, value.end()),
1115 &seconds); 1098 &seconds);
1116 *result = TimeDelta::FromSeconds(seconds); 1099 *result = TimeDelta::FromSeconds(seconds);
1117 return true; 1100 return true;
1118 } 1101 }
1119 } 1102 }
1120 } 1103 }
1121 1104
1122 return false; 1105 return false;
1123 } 1106 }
1124 1107
1125 bool HttpResponseHeaders::GetAgeValue(TimeDelta* result) const { 1108 bool HttpResponseHeaders::GetAgeValue(TimeDelta* result) const {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1189 return keep_alive; 1172 return keep_alive;
1190 } 1173 }
1191 1174
1192 bool HttpResponseHeaders::HasStrongValidators() const { 1175 bool HttpResponseHeaders::HasStrongValidators() const {
1193 std::string etag_header; 1176 std::string etag_header;
1194 EnumerateHeader(NULL, "etag", &etag_header); 1177 EnumerateHeader(NULL, "etag", &etag_header);
1195 std::string last_modified_header; 1178 std::string last_modified_header;
1196 EnumerateHeader(NULL, "Last-Modified", &last_modified_header); 1179 EnumerateHeader(NULL, "Last-Modified", &last_modified_header);
1197 std::string date_header; 1180 std::string date_header;
1198 EnumerateHeader(NULL, "Date", &date_header); 1181 EnumerateHeader(NULL, "Date", &date_header);
1199 return HttpUtil::HasStrongValidators(GetHttpVersion(), 1182 return HttpUtil::HasStrongValidators(
1200 etag_header, 1183 GetHttpVersion(), etag_header, last_modified_header, date_header);
1201 last_modified_header,
1202 date_header);
1203 } 1184 }
1204 1185
1205 // From RFC 2616: 1186 // From RFC 2616:
1206 // Content-Length = "Content-Length" ":" 1*DIGIT 1187 // Content-Length = "Content-Length" ":" 1*DIGIT
1207 int64 HttpResponseHeaders::GetContentLength() const { 1188 int64 HttpResponseHeaders::GetContentLength() const {
1208 return GetInt64HeaderValue("content-length"); 1189 return GetInt64HeaderValue("content-length");
1209 } 1190 }
1210 1191
1211 int64 HttpResponseHeaders::GetInt64HeaderValue( 1192 int64 HttpResponseHeaders::GetInt64HeaderValue(
1212 const std::string& header) const { 1193 const std::string& header) const {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1251 size_t space_position = content_range_spec.find(' '); 1232 size_t space_position = content_range_spec.find(' ');
1252 if (space_position == std::string::npos) 1233 if (space_position == std::string::npos)
1253 return false; 1234 return false;
1254 1235
1255 // Invalid header if it doesn't contain "bytes-unit". 1236 // Invalid header if it doesn't contain "bytes-unit".
1256 std::string::const_iterator content_range_spec_begin = 1237 std::string::const_iterator content_range_spec_begin =
1257 content_range_spec.begin(); 1238 content_range_spec.begin();
1258 std::string::const_iterator content_range_spec_end = 1239 std::string::const_iterator content_range_spec_end =
1259 content_range_spec.begin() + space_position; 1240 content_range_spec.begin() + space_position;
1260 HttpUtil::TrimLWS(&content_range_spec_begin, &content_range_spec_end); 1241 HttpUtil::TrimLWS(&content_range_spec_begin, &content_range_spec_end);
1261 if (!LowerCaseEqualsASCII(content_range_spec_begin, 1242 if (!LowerCaseEqualsASCII(
1262 content_range_spec_end, 1243 content_range_spec_begin, content_range_spec_end, "bytes")) {
1263 "bytes")) {
1264 return false; 1244 return false;
1265 } 1245 }
1266 1246
1267 size_t slash_position = content_range_spec.find('/', space_position + 1); 1247 size_t slash_position = content_range_spec.find('/', space_position + 1);
1268 if (slash_position == std::string::npos) 1248 if (slash_position == std::string::npos)
1269 return false; 1249 return false;
1270 1250
1271 // Obtain the part behind the space and before slash. 1251 // Obtain the part behind the space and before slash.
1272 std::string::const_iterator byte_range_resp_spec_begin = 1252 std::string::const_iterator byte_range_resp_spec_begin =
1273 content_range_spec.begin() + space_position + 1; 1253 content_range_spec.begin() + space_position + 1;
1274 std::string::const_iterator byte_range_resp_spec_end = 1254 std::string::const_iterator byte_range_resp_spec_end =
1275 content_range_spec.begin() + slash_position; 1255 content_range_spec.begin() + slash_position;
1276 HttpUtil::TrimLWS(&byte_range_resp_spec_begin, &byte_range_resp_spec_end); 1256 HttpUtil::TrimLWS(&byte_range_resp_spec_begin, &byte_range_resp_spec_end);
1277 1257
1278 // Parse the byte-range-resp-spec part. 1258 // Parse the byte-range-resp-spec part.
1279 std::string byte_range_resp_spec(byte_range_resp_spec_begin, 1259 std::string byte_range_resp_spec(byte_range_resp_spec_begin,
1280 byte_range_resp_spec_end); 1260 byte_range_resp_spec_end);
1281 // If byte-range-resp-spec != "*". 1261 // If byte-range-resp-spec != "*".
1282 if (!LowerCaseEqualsASCII(byte_range_resp_spec, "*")) { 1262 if (!LowerCaseEqualsASCII(byte_range_resp_spec, "*")) {
1283 size_t minus_position = byte_range_resp_spec.find('-'); 1263 size_t minus_position = byte_range_resp_spec.find('-');
1284 if (minus_position != std::string::npos) { 1264 if (minus_position != std::string::npos) {
1285 // Obtain first-byte-pos. 1265 // Obtain first-byte-pos.
1286 std::string::const_iterator first_byte_pos_begin = 1266 std::string::const_iterator first_byte_pos_begin =
1287 byte_range_resp_spec.begin(); 1267 byte_range_resp_spec.begin();
1288 std::string::const_iterator first_byte_pos_end = 1268 std::string::const_iterator first_byte_pos_end =
1289 byte_range_resp_spec.begin() + minus_position; 1269 byte_range_resp_spec.begin() + minus_position;
1290 HttpUtil::TrimLWS(&first_byte_pos_begin, &first_byte_pos_end); 1270 HttpUtil::TrimLWS(&first_byte_pos_begin, &first_byte_pos_end);
1291 1271
1292 bool ok = base::StringToInt64(StringPiece(first_byte_pos_begin, 1272 bool ok = base::StringToInt64(
1293 first_byte_pos_end), 1273 StringPiece(first_byte_pos_begin, first_byte_pos_end),
1294 first_byte_position); 1274 first_byte_position);
1295 1275
1296 // Obtain last-byte-pos. 1276 // Obtain last-byte-pos.
1297 std::string::const_iterator last_byte_pos_begin = 1277 std::string::const_iterator last_byte_pos_begin =
1298 byte_range_resp_spec.begin() + minus_position + 1; 1278 byte_range_resp_spec.begin() + minus_position + 1;
1299 std::string::const_iterator last_byte_pos_end = 1279 std::string::const_iterator last_byte_pos_end =
1300 byte_range_resp_spec.end(); 1280 byte_range_resp_spec.end();
1301 HttpUtil::TrimLWS(&last_byte_pos_begin, &last_byte_pos_end); 1281 HttpUtil::TrimLWS(&last_byte_pos_begin, &last_byte_pos_end);
1302 1282
1303 ok &= base::StringToInt64(StringPiece(last_byte_pos_begin, 1283 ok &= base::StringToInt64(
1304 last_byte_pos_end), 1284 StringPiece(last_byte_pos_begin, last_byte_pos_end),
1305 last_byte_position); 1285 last_byte_position);
1306 if (!ok) { 1286 if (!ok) {
1307 *first_byte_position = *last_byte_position = -1; 1287 *first_byte_position = *last_byte_position = -1;
1308 return false; 1288 return false;
1309 } 1289 }
1310 if (*first_byte_position < 0 || *last_byte_position < 0 || 1290 if (*first_byte_position < 0 || *last_byte_position < 0 ||
1311 *first_byte_position > *last_byte_position) 1291 *first_byte_position > *last_byte_position)
1312 return false; 1292 return false;
1313 } else { 1293 } else {
1314 return false; 1294 return false;
1315 } 1295 }
1316 } 1296 }
1317 1297
1318 // Parse the instance-length part. 1298 // Parse the instance-length part.
1319 // If instance-length == "*". 1299 // If instance-length == "*".
1320 std::string::const_iterator instance_length_begin = 1300 std::string::const_iterator instance_length_begin =
1321 content_range_spec.begin() + slash_position + 1; 1301 content_range_spec.begin() + slash_position + 1;
1322 std::string::const_iterator instance_length_end = 1302 std::string::const_iterator instance_length_end = content_range_spec.end();
1323 content_range_spec.end();
1324 HttpUtil::TrimLWS(&instance_length_begin, &instance_length_end); 1303 HttpUtil::TrimLWS(&instance_length_begin, &instance_length_end);
1325 1304
1326 if (LowerCaseEqualsASCII(instance_length_begin, instance_length_end, "*")) { 1305 if (LowerCaseEqualsASCII(instance_length_begin, instance_length_end, "*")) {
1327 return false; 1306 return false;
1328 } else if (!base::StringToInt64(StringPiece(instance_length_begin, 1307 } else if (!base::StringToInt64(
1329 instance_length_end), 1308 StringPiece(instance_length_begin, instance_length_end),
1330 instance_length)) { 1309 instance_length)) {
1331 *instance_length = -1; 1310 *instance_length = -1;
1332 return false; 1311 return false;
1333 } 1312 }
1334 1313
1335 // We have all the values; let's verify that they make sense for a 206 1314 // We have all the values; let's verify that they make sense for a 206
1336 // response. 1315 // response.
1337 if (*first_byte_position < 0 || *last_byte_position < 0 || 1316 if (*first_byte_position < 0 || *last_byte_position < 0 ||
1338 *instance_length < 0 || *instance_length - 1 < *last_byte_position) 1317 *instance_length < 0 || *instance_length - 1 < *last_byte_position)
1339 return false; 1318 return false;
1340 1319
1341 return true; 1320 return true;
1342 } 1321 }
1343 1322
1344 base::Value* HttpResponseHeaders::NetLogCallback( 1323 base::Value* HttpResponseHeaders::NetLogCallback(
1345 NetLog::LogLevel log_level) const { 1324 NetLog::LogLevel log_level) const {
1346 base::DictionaryValue* dict = new base::DictionaryValue(); 1325 base::DictionaryValue* dict = new base::DictionaryValue();
1347 base::ListValue* headers = new base::ListValue(); 1326 base::ListValue* headers = new base::ListValue();
1348 headers->Append(new base::StringValue(GetStatusLine())); 1327 headers->Append(new base::StringValue(GetStatusLine()));
1349 void* iterator = NULL; 1328 void* iterator = NULL;
1350 std::string name; 1329 std::string name;
1351 std::string value; 1330 std::string value;
1352 while (EnumerateHeaderLines(&iterator, &name, &value)) { 1331 while (EnumerateHeaderLines(&iterator, &name, &value)) {
1353 std::string log_value = ElideHeaderValueForNetLog(log_level, name, value); 1332 std::string log_value = ElideHeaderValueForNetLog(log_level, name, value);
1354 headers->Append( 1333 headers->Append(new base::StringValue(
1355 new base::StringValue( 1334 base::StringPrintf("%s: %s", name.c_str(), log_value.c_str())));
1356 base::StringPrintf("%s: %s", name.c_str(), log_value.c_str())));
1357 } 1335 }
1358 dict->Set("headers", headers); 1336 dict->Set("headers", headers);
1359 return dict; 1337 return dict;
1360 } 1338 }
1361 1339
1362 // static 1340 // static
1363 bool HttpResponseHeaders::FromNetLogParam( 1341 bool HttpResponseHeaders::FromNetLogParam(
1364 const base::Value* event_param, 1342 const base::Value* event_param,
1365 scoped_refptr<HttpResponseHeaders>* http_response_headers) { 1343 scoped_refptr<HttpResponseHeaders>* http_response_headers) {
1366 *http_response_headers = NULL; 1344 *http_response_headers = NULL;
1367 1345
1368 const base::DictionaryValue* dict = NULL; 1346 const base::DictionaryValue* dict = NULL;
1369 const base::ListValue* header_list = NULL; 1347 const base::ListValue* header_list = NULL;
1370 1348
1371 if (!event_param || 1349 if (!event_param || !event_param->GetAsDictionary(&dict) ||
1372 !event_param->GetAsDictionary(&dict) ||
1373 !dict->GetList("headers", &header_list)) { 1350 !dict->GetList("headers", &header_list)) {
1374 return false; 1351 return false;
1375 } 1352 }
1376 1353
1377 std::string raw_headers; 1354 std::string raw_headers;
1378 for (base::ListValue::const_iterator it = header_list->begin(); 1355 for (base::ListValue::const_iterator it = header_list->begin();
1379 it != header_list->end(); 1356 it != header_list->end();
1380 ++it) { 1357 ++it) {
1381 std::string header_line; 1358 std::string header_line;
1382 if (!(*it)->GetAsString(&header_line)) 1359 if (!(*it)->GetAsString(&header_line))
1383 return false; 1360 return false;
1384 1361
1385 raw_headers.append(header_line); 1362 raw_headers.append(header_line);
1386 raw_headers.push_back('\0'); 1363 raw_headers.push_back('\0');
1387 } 1364 }
1388 raw_headers.push_back('\0'); 1365 raw_headers.push_back('\0');
1389 *http_response_headers = new HttpResponseHeaders(raw_headers); 1366 *http_response_headers = new HttpResponseHeaders(raw_headers);
1390 return true; 1367 return true;
1391 } 1368 }
1392 1369
1393 bool HttpResponseHeaders::IsChunkEncoded() const { 1370 bool HttpResponseHeaders::IsChunkEncoded() const {
1394 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. 1371 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies.
1395 return GetHttpVersion() >= HttpVersion(1, 1) && 1372 return GetHttpVersion() >= HttpVersion(1, 1) &&
1396 HasHeaderValue("Transfer-Encoding", "chunked"); 1373 HasHeaderValue("Transfer-Encoding", "chunked");
1397 } 1374 }
1398 1375
1399 #if defined(SPDY_PROXY_AUTH_ORIGIN) 1376 #if defined(SPDY_PROXY_AUTH_ORIGIN)
1400 bool HttpResponseHeaders::GetDataReductionProxyBypassDuration( 1377 bool HttpResponseHeaders::GetDataReductionProxyBypassDuration(
1401 const std::string& action_prefix, 1378 const std::string& action_prefix,
1402 base::TimeDelta* duration) const { 1379 base::TimeDelta* duration) const {
1403 void* iter = NULL; 1380 void* iter = NULL;
1404 std::string value; 1381 std::string value;
1405 std::string name = "chrome-proxy"; 1382 std::string name = "chrome-proxy";
1406 1383
1407 while (EnumerateHeader(&iter, name, &value)) { 1384 while (EnumerateHeader(&iter, name, &value)) {
1408 if (value.size() > action_prefix.size()) { 1385 if (value.size() > action_prefix.size()) {
1409 if (LowerCaseEqualsASCII(value.begin(), 1386 if (LowerCaseEqualsASCII(value.begin(),
1410 value.begin() + action_prefix.size(), 1387 value.begin() + action_prefix.size(),
1411 action_prefix.c_str())) { 1388 action_prefix.c_str())) {
1412 int64 seconds; 1389 int64 seconds;
1413 if (!base::StringToInt64( 1390 if (!base::StringToInt64(
1414 StringPiece(value.begin() + action_prefix.size(), value.end()), 1391 StringPiece(value.begin() + action_prefix.size(), value.end()),
1415 &seconds) || seconds < 0) { 1392 &seconds) ||
1393 seconds < 0) {
1416 continue; // In case there is a well formed instruction. 1394 continue; // In case there is a well formed instruction.
1417 } 1395 }
1418 *duration = TimeDelta::FromSeconds(seconds); 1396 *duration = TimeDelta::FromSeconds(seconds);
1419 return true; 1397 return true;
1420 } 1398 }
1421 } 1399 }
1422 } 1400 }
1423 return false; 1401 return false;
1424 } 1402 }
1425 1403
1426 bool HttpResponseHeaders::GetDataReductionProxyInfo( 1404 bool HttpResponseHeaders::GetDataReductionProxyInfo(
1427 DataReductionProxyInfo* proxy_info) const { 1405 DataReductionProxyInfo* proxy_info) const {
1428 DCHECK(proxy_info); 1406 DCHECK(proxy_info);
1429 proxy_info->bypass_all = false; 1407 proxy_info->bypass_all = false;
1430 proxy_info->bypass_duration = base::TimeDelta(); 1408 proxy_info->bypass_duration = base::TimeDelta();
1431 // Support header of the form Chrome-Proxy: bypass|block=<duration>, where 1409 // Support header of the form Chrome-Proxy: bypass|block=<duration>, where
1432 // <duration> is the number of seconds to wait before retrying 1410 // <duration> is the number of seconds to wait before retrying
1433 // the proxy. If the duration is 0, then the default proxy retry delay 1411 // the proxy. If the duration is 0, then the default proxy retry delay
1434 // (specified in |ProxyList::UpdateRetryInfoOnFallback|) will be used. 1412 // (specified in |ProxyList::UpdateRetryInfoOnFallback|) will be used.
1435 // 'bypass' instructs Chrome to bypass the currently connected data reduction 1413 // 'bypass' instructs Chrome to bypass the currently connected data reduction
1436 // proxy, whereas 'block' instructs Chrome to bypass all available data 1414 // proxy, whereas 'block' instructs Chrome to bypass all available data
1437 // reduction proxies. 1415 // reduction proxies.
1438 1416
1439 // 'block' takes precedence over 'bypass', so look for it first. 1417 // 'block' takes precedence over 'bypass', so look for it first.
1440 // TODO(bengr): Reduce checks for 'block' and 'bypass' to a single loop. 1418 // TODO(bengr): Reduce checks for 'block' and 'bypass' to a single loop.
1441 if (GetDataReductionProxyBypassDuration( 1419 if (GetDataReductionProxyBypassDuration("block=",
1442 "block=", &proxy_info->bypass_duration)) { 1420 &proxy_info->bypass_duration)) {
1443 proxy_info->bypass_all = true; 1421 proxy_info->bypass_all = true;
1444 return true; 1422 return true;
1445 } 1423 }
1446 1424
1447 // Next, look for 'bypass'. 1425 // Next, look for 'bypass'.
1448 if (GetDataReductionProxyBypassDuration( 1426 if (GetDataReductionProxyBypassDuration("bypass=",
1449 "bypass=", &proxy_info->bypass_duration)) { 1427 &proxy_info->bypass_duration)) {
1450 return true; 1428 return true;
1451 } 1429 }
1452 return false; 1430 return false;
1453 } 1431 }
1454 1432
1455 bool HttpResponseHeaders::IsDataReductionProxyResponse() const { 1433 bool HttpResponseHeaders::IsDataReductionProxyResponse() const {
1456 const size_t kVersionSize = 4; 1434 const size_t kVersionSize = 4;
1457 const char kDataReductionProxyViaValue[] = "Chrome-Compression-Proxy"; 1435 const char kDataReductionProxyViaValue[] = "Chrome-Compression-Proxy";
1458 size_t value_len = strlen(kDataReductionProxyViaValue); 1436 size_t value_len = strlen(kDataReductionProxyViaValue);
1459 void* iter = NULL; 1437 void* iter = NULL;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1503 // should not generate representation metadata other than Cache-Control, 1481 // should not generate representation metadata other than Cache-Control,
1504 // Content-Location, Date, ETag, Expires, and Vary. 1482 // Content-Location, Date, ETag, Expires, and Vary.
1505 return ProxyService::MISSING_VIA_HEADER; 1483 return ProxyService::MISSING_VIA_HEADER;
1506 } 1484 }
1507 // There is no bypass event. 1485 // There is no bypass event.
1508 return ProxyService::BYPASS_EVENT_TYPE_MAX; 1486 return ProxyService::BYPASS_EVENT_TYPE_MAX;
1509 } 1487 }
1510 #endif // defined(SPDY_PROXY_AUTH_ORIGIN) 1488 #endif // defined(SPDY_PROXY_AUTH_ORIGIN)
1511 1489
1512 } // namespace net 1490 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698