OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |