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/memory/ref_counted.h" |
8 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
9 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
10 #include "net/base/net_util.h" | 11 #include "net/base/net_util.h" |
| 12 #include "net/http/http_response_headers.h" |
11 #include "net/http/http_util.h" | 13 #include "net/http/http_util.h" |
12 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h" | 14 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h" |
13 #include "third_party/WebKit/public/platform/WebString.h" | 15 #include "third_party/WebKit/public/platform/WebString.h" |
14 #include "third_party/WebKit/public/platform/WebURL.h" | 16 #include "third_party/WebKit/public/platform/WebURL.h" |
15 #include "third_party/WebKit/public/platform/WebURLLoaderClient.h" | 17 #include "third_party/WebKit/public/platform/WebURLLoaderClient.h" |
16 | 18 |
17 using blink::WebHTTPHeaderVisitor; | 19 using blink::WebHTTPHeaderVisitor; |
18 using blink::WebString; | 20 using blink::WebString; |
19 using blink::WebURLLoader; | 21 using blink::WebURLLoader; |
20 using blink::WebURLLoaderClient; | 22 using blink::WebURLLoaderClient; |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 int offset = 0; | 204 int offset = 0; |
203 if (pos < data.length() && (data[pos] == '\r' || data[pos] == '\n')) { | 205 if (pos < data.length() && (data[pos] == '\r' || data[pos] == '\n')) { |
204 ++offset; | 206 ++offset; |
205 if (pos + 1 < data.length() && data[pos + 1] == '\n') | 207 if (pos + 1 < data.length() && data[pos + 1] == '\n') |
206 ++offset; | 208 ++offset; |
207 } | 209 } |
208 return offset; | 210 return offset; |
209 } | 211 } |
210 | 212 |
211 bool MultipartResponseDelegate::ParseHeaders() { | 213 bool MultipartResponseDelegate::ParseHeaders() { |
212 int line_feed_increment = 1; | 214 int headers_end_pos = net::HttpUtil::LocateEndOfAdditionalHeaders( |
| 215 data_.c_str(), data_.size(), 0); |
213 | 216 |
214 // Grab the headers being liberal about line endings. | 217 if (headers_end_pos < 0) |
215 size_t line_start_pos = 0; | |
216 size_t line_end_pos = data_.find('\n'); | |
217 while (line_end_pos != std::string::npos) { | |
218 // Handle CRLF | |
219 if (line_end_pos > line_start_pos && data_[line_end_pos - 1] == '\r') { | |
220 line_feed_increment = 2; | |
221 --line_end_pos; | |
222 } else { | |
223 line_feed_increment = 1; | |
224 } | |
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; | 218 return false; |
237 | 219 |
238 // Eat headers | 220 // Eat headers and prepend a status line as is required by |
239 std::string headers("\n"); | 221 // HttpResponseHeaders. |
240 headers.append(data_, 0, line_end_pos); | 222 std::string headers("HTTP/1.1 200 OK\r\n"); |
241 data_ = data_.substr(line_end_pos); | 223 headers.append(data_, 0, headers_end_pos); |
| 224 data_ = data_.substr(headers_end_pos); |
| 225 |
| 226 scoped_refptr<net::HttpResponseHeaders> response_headers = |
| 227 new net::HttpResponseHeaders( |
| 228 net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.size())); |
242 | 229 |
243 // Create a WebURLResponse based on the original set of headers + the | 230 // Create a WebURLResponse based on the original set of headers + the |
244 // replacement headers. We only replace the same few headers that gecko | 231 // replacement headers. We only replace the same few headers that gecko |
245 // does. See netwerk/streamconv/converters/nsMultiMixedConv.cpp. | 232 // does. See netwerk/streamconv/converters/nsMultiMixedConv.cpp. |
246 std::string content_type = net::GetSpecificHeader(headers, "content-type"); | 233 WebURLResponse response(original_response_.url()); |
| 234 |
247 std::string mime_type; | 235 std::string mime_type; |
| 236 response_headers->GetMimeType(&mime_type); |
| 237 response.setMIMEType(WebString::fromUTF8(mime_type)); |
| 238 |
248 std::string charset; | 239 std::string charset; |
249 bool has_charset = false; | 240 response_headers->GetCharset(&charset); |
250 net::HttpUtil::ParseContentType(content_type, &mime_type, &charset, | |
251 &has_charset, NULL); | |
252 WebURLResponse response(original_response_.url()); | |
253 response.setMIMEType(WebString::fromUTF8(mime_type)); | |
254 response.setTextEncodingName(WebString::fromUTF8(charset)); | 241 response.setTextEncodingName(WebString::fromUTF8(charset)); |
255 | 242 |
| 243 // Copy the response headers from the original response. |
256 HeaderCopier copier(&response); | 244 HeaderCopier copier(&response); |
257 original_response_.visitHTTPHeaderFields(&copier); | 245 original_response_.visitHTTPHeaderFields(&copier); |
258 | 246 |
| 247 // Replace original headers with multipart headers listed in kReplaceHeaders. |
259 for (size_t i = 0; i < arraysize(kReplaceHeaders); ++i) { | 248 for (size_t i = 0; i < arraysize(kReplaceHeaders); ++i) { |
260 std::string name(kReplaceHeaders[i]); | 249 std::string name(kReplaceHeaders[i]); |
261 std::string value = net::GetSpecificHeader(headers, name); | 250 std::string value; |
262 if (!value.empty()) { | 251 void* iterator = nullptr; |
263 response.setHTTPHeaderField(WebString::fromUTF8(name), | 252 while (response_headers->EnumerateHeader(&iterator, name, &value)) { |
264 WebString::fromUTF8(value)); | 253 response.addHTTPHeaderField(WebString::fromLatin1(name), |
| 254 WebString::fromLatin1(value)); |
265 } | 255 } |
266 } | 256 } |
267 // To avoid recording every multipart load as a separate visit in | 257 // To avoid recording every multipart load as a separate visit in |
268 // the history database, we want to keep track of whether the response | 258 // 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, | 259 // 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. | 260 // so we only set isMultipartPayload to true after the first visit. |
271 response.setIsMultipartPayload(has_sent_first_response_); | 261 response.setIsMultipartPayload(has_sent_first_response_); |
272 has_sent_first_response_ = true; | 262 has_sent_first_response_ = true; |
273 // Send the response! | 263 // Send the response! |
274 if (client_) | 264 if (client_) |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 if (!base::StringToInt64(byte_range_upper_bound, content_range_upper_bound)) | 385 if (!base::StringToInt64(byte_range_upper_bound, content_range_upper_bound)) |
396 return false; | 386 return false; |
397 if (!base::StringToInt64(byte_range_instance_size, | 387 if (!base::StringToInt64(byte_range_instance_size, |
398 content_range_instance_size)) { | 388 content_range_instance_size)) { |
399 return false; | 389 return false; |
400 } | 390 } |
401 return true; | 391 return true; |
402 } | 392 } |
403 | 393 |
404 } // namespace content | 394 } // namespace content |
OLD | NEW |