 Chromium Code Reviews
 Chromium Code Reviews Issue 1166953002:
  Use net's response header parser for parsing multipart headers.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 1166953002:
  Use net's response header parser for parsing multipart headers.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| OLD | NEW | 
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "content/child/multipart_response_delegate.h" | 5 #include "content/child/multipart_response_delegate.h" | 
| 6 | 6 | 
| 7 #include "base/logging.h" | 7 #include "base/logging.h" | 
| 8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" | 
| 9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" | 
| 10 #include "net/base/net_util.h" | 10 #include "net/base/net_util.h" | 
| 11 #include "net/http/http_response_headers.h" | |
| 11 #include "net/http/http_util.h" | 12 #include "net/http/http_util.h" | 
| 12 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h" | 13 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h" | 
| 13 #include "third_party/WebKit/public/platform/WebString.h" | 14 #include "third_party/WebKit/public/platform/WebString.h" | 
| 14 #include "third_party/WebKit/public/platform/WebURL.h" | 15 #include "third_party/WebKit/public/platform/WebURL.h" | 
| 15 #include "third_party/WebKit/public/platform/WebURLLoaderClient.h" | 16 #include "third_party/WebKit/public/platform/WebURLLoaderClient.h" | 
| 16 | 17 | 
| 17 using blink::WebHTTPHeaderVisitor; | 18 using blink::WebHTTPHeaderVisitor; | 
| 18 using blink::WebString; | 19 using blink::WebString; | 
| 19 using blink::WebURLLoader; | 20 using blink::WebURLLoader; | 
| 20 using blink::WebURLLoaderClient; | 21 using blink::WebURLLoaderClient; | 
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 202 int offset = 0; | 203 int offset = 0; | 
| 203 if (pos < data.length() && (data[pos] == '\r' || data[pos] == '\n')) { | 204 if (pos < data.length() && (data[pos] == '\r' || data[pos] == '\n')) { | 
| 204 ++offset; | 205 ++offset; | 
| 205 if (pos + 1 < data.length() && data[pos + 1] == '\n') | 206 if (pos + 1 < data.length() && data[pos + 1] == '\n') | 
| 206 ++offset; | 207 ++offset; | 
| 207 } | 208 } | 
| 208 return offset; | 209 return offset; | 
| 209 } | 210 } | 
| 210 | 211 | 
| 211 bool MultipartResponseDelegate::ParseHeaders() { | 212 bool MultipartResponseDelegate::ParseHeaders() { | 
| 212 int line_feed_increment = 1; | 213 int headers_end_pos = -1; | 
| 213 | 214 | 
| 214 // Grab the headers being liberal about line endings. | 215 size_t i = 0; | 
| 215 size_t line_start_pos = 0; | 216 while ((data_[i] == '\r' || data_[i] == '\n') && i < data_.size()) | 
| 216 size_t line_end_pos = data_.find('\n'); | 217 i++; | 
| 
mmenke
2015/06/05 16:01:42
This isn't correct (If we have a bunch of LFs or C
 
haavardm
2015/06/09 15:12:35
agh, of course..
 | |
| 217 while (line_end_pos != std::string::npos) { | 218 | 
| 218 // Handle CRLF | 219 if (i > 0) | 
| 219 if (line_end_pos > line_start_pos && data_[line_end_pos - 1] == '\r') { | 220 headers_end_pos = i; | 
| 220 line_feed_increment = 2; | 221 else | 
| 221 --line_end_pos; | 222 headers_end_pos = | 
| 222 } else { | 223 net::HttpUtil::LocateEndOfHeaders(data_.c_str(), data_.size(), 0); | 
| 223 line_feed_increment = 1; | 224 | 
| 224 } | 225 if (headers_end_pos < 0) | 
| 225 if (line_start_pos == line_end_pos) { | |
| 226 // A blank line, end of headers | |
| 227 line_end_pos += line_feed_increment; | |
| 228 break; | |
| 229 } | |
| 230 // Find the next header line. | |
| 231 line_start_pos = line_end_pos + line_feed_increment; | |
| 232 line_end_pos = data_.find('\n', line_start_pos); | |
| 233 } | |
| 234 // Truncated in the middle of a header, stop parsing. | |
| 235 if (line_end_pos == std::string::npos) | |
| 236 return false; | 226 return false; | 
| 237 | 227 | 
| 238 // Eat headers | 228 // Eat headers and prepend a status line as is required by | 
| 239 std::string headers("\n"); | 229 // HttpResponseHeaders. | 
| 240 headers.append(data_, 0, line_end_pos); | 230 std::string headers("HTTP/1.1 200 OK\r\n"); | 
| 241 data_ = data_.substr(line_end_pos); | 231 headers.append(data_, 0, headers_end_pos); | 
| 232 data_ = data_.substr(headers_end_pos); | |
| 233 | |
| 234 scoped_refptr<net::HttpResponseHeaders> response_headers = | |
| 
mmenke
2015/06/05 16:01:42
nit:  include base/ref_counted.h
 
haavardm
2015/06/09 15:12:34
Done.
 | |
| 235 new net::HttpResponseHeaders( | |
| 236 net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.size())); | |
| 
mmenke
2015/06/05 16:01:42
Again, suggest a method for HttpUtil that does thi
 
haavardm
2015/06/09 15:12:34
I'm a bit unsure about what you suggest to add a m
 
mmenke
2015/06/09 20:23:37
I was thinking of making a method that does this:
 | |
| 242 | 237 | 
| 243 // Create a WebURLResponse based on the original set of headers + the | 238 // Create a WebURLResponse based on the original set of headers + the | 
| 244 // replacement headers. We only replace the same few headers that gecko | 239 // replacement headers. We only replace the same few headers that gecko | 
| 245 // does. See netwerk/streamconv/converters/nsMultiMixedConv.cpp. | 240 // does. See netwerk/streamconv/converters/nsMultiMixedConv.cpp. | 
| 246 std::string content_type = net::GetSpecificHeader(headers, "content-type"); | 241 std::string content_type; | 
| 242 WebURLResponse response(original_response_.url()); | |
| 243 | |
| 247 std::string mime_type; | 244 std::string mime_type; | 
| 245 if (response_headers->GetMimeType(&mime_type)) { | |
| 246 response.setMIMEType(WebString::fromUTF8(mime_type)); | |
| 247 } | |
| 248 std::string charset; | 248 std::string charset; | 
| 249 bool has_charset = false; | 249 if (response_headers->GetCharset(&charset)) { | 
| 250 net::HttpUtil::ParseContentType(content_type, &mime_type, &charset, | 250 response.setTextEncodingName(WebString::fromUTF8(charset)); | 
| 251 &has_charset, NULL); | 251 } | 
| 
mmenke
2015/06/05 16:01:42
I don't feel like I can adequately review the impl
 
haavardm
2015/06/09 15:12:35
I think it should handle not setting the mime or t
 | |
| 252 WebURLResponse response(original_response_.url()); | |
| 253 response.setMIMEType(WebString::fromUTF8(mime_type)); | |
| 254 response.setTextEncodingName(WebString::fromUTF8(charset)); | |
| 255 | 252 | 
| 253 // Copy the response headers from the original response. | |
| 256 HeaderCopier copier(&response); | 254 HeaderCopier copier(&response); | 
| 257 original_response_.visitHTTPHeaderFields(&copier); | 255 original_response_.visitHTTPHeaderFields(&copier); | 
| 258 | 256 | 
| 257 // Replace original headers with multipart headers listed in kReplaceHeaders. | |
| 259 for (size_t i = 0; i < arraysize(kReplaceHeaders); ++i) { | 258 for (size_t i = 0; i < arraysize(kReplaceHeaders); ++i) { | 
| 260 std::string name(kReplaceHeaders[i]); | 259 std::string name(kReplaceHeaders[i]); | 
| 261 std::string value = net::GetSpecificHeader(headers, name); | 260 std::string value; | 
| 262 if (!value.empty()) { | 261 if (response_headers->EnumerateHeader(NULL, name, &value)) { | 
| 263 response.setHTTPHeaderField(WebString::fromUTF8(name), | 262 response.setHTTPHeaderField(WebString::fromUTF8(name), | 
| 264 WebString::fromUTF8(value)); | 263 WebString::fromUTF8(value)); | 
| 265 } | 264 } | 
| 266 } | 265 } | 
| 267 // To avoid recording every multipart load as a separate visit in | 266 // To avoid recording every multipart load as a separate visit in | 
| 268 // the history database, we want to keep track of whether the response | 267 // the history database, we want to keep track of whether the response | 
| 269 // is part of a multipart payload. We do want to record the first visit, | 268 // is part of a multipart payload. We do want to record the first visit, | 
| 270 // so we only set isMultipartPayload to true after the first visit. | 269 // so we only set isMultipartPayload to true after the first visit. | 
| 271 response.setIsMultipartPayload(has_sent_first_response_); | 270 response.setIsMultipartPayload(has_sent_first_response_); | 
| 272 has_sent_first_response_ = true; | 271 has_sent_first_response_ = true; | 
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 395 if (!base::StringToInt64(byte_range_upper_bound, content_range_upper_bound)) | 394 if (!base::StringToInt64(byte_range_upper_bound, content_range_upper_bound)) | 
| 396 return false; | 395 return false; | 
| 397 if (!base::StringToInt64(byte_range_instance_size, | 396 if (!base::StringToInt64(byte_range_instance_size, | 
| 398 content_range_instance_size)) { | 397 content_range_instance_size)) { | 
| 399 return false; | 398 return false; | 
| 400 } | 399 } | 
| 401 return true; | 400 return true; | 
| 402 } | 401 } | 
| 403 | 402 | 
| 404 } // namespace content | 403 } // namespace content | 
| OLD | NEW |