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
3 // found in the LICENSE file.
5 #include "mojo/services/html_viewer/blink_url_request_type_converters.h"
7 #include "base/strings/string_util.h"
8 #include "mojo/public/cpp/system/data_pipe.h"
9 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
10 #include "third_party/WebKit/public/platform/WebURLRequest.h"
15 // Ripped from web_url_loader_impl.cc.
16 class HeaderFlattener : public blink::WebHTTPHeaderVisitor {
18 HeaderFlattener() : has_accept_header_(false) {}
20 virtual void visitHeader(const blink::WebString& name,
21 const blink::WebString& value) {
22 // Headers are latin1.
23 const std::string& name_latin1 = name.latin1();
24 const std::string& value_latin1 = value.latin1();
26 // Skip over referrer headers found in the header map because we already
27 // pulled it out as a separate parameter.
28 if (LowerCaseEqualsASCII(name_latin1, "referer"))
31 if (LowerCaseEqualsASCII(name_latin1, "accept"))
32 has_accept_header_ = true;
34 buffer_.push_back(name_latin1 + ": " + value_latin1);
37 Array<String> GetBuffer() {
38 // In some cases, WebKit doesn't add an Accept header, but not having the
39 // header confuses some web servers. See bug 808613.
40 if (!has_accept_header_) {
41 buffer_.push_back("Accept: */*");
42 has_accept_header_ = true;
44 return buffer_.Pass();
48 Array<String> buffer_;
49 bool has_accept_header_;
52 void AddRequestBody(URLRequest* url_request,
53 const blink::WebURLRequest& request) {
54 if (request.httpBody().isNull())
58 blink::WebHTTPBody::Element element;
59 while (request.httpBody().elementAt(i++, element)) {
60 switch (element.type) {
61 case blink::WebHTTPBody::Element::TypeData:
62 if (!element.data.isEmpty()) {
63 // WebKit sometimes gives up empty data to append. These aren't
64 // necessary so we just optimize those out here.
65 uint32_t num_bytes = static_cast<uint32_t>(element.data.size());
66 MojoCreateDataPipeOptions options;
67 options.struct_size = sizeof(MojoCreateDataPipeOptions);
68 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
69 options.element_num_bytes = 1;
70 options.capacity_num_bytes = num_bytes;
71 DataPipe data_pipe(options);
72 url_request->body.push_back(
73 data_pipe.consumer_handle.Pass());
74 WriteDataRaw(data_pipe.producer_handle.get(),
77 MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
80 case blink::WebHTTPBody::Element::TypeFile:
81 case blink::WebHTTPBody::Element::TypeFileSystemURL:
82 case blink::WebHTTPBody::Element::TypeBlob:
83 // TODO(mpcomplete): handle these.
94 URLRequestPtr TypeConverter<URLRequestPtr, blink::WebURLRequest>::ConvertFrom(
95 const blink::WebURLRequest& request) {
96 URLRequestPtr url_request(URLRequest::New());
97 url_request->url = request.url().string().utf8();
98 url_request->method = request.httpMethod().utf8();
100 HeaderFlattener flattener;
101 request.visitHTTPHeaderFields(&flattener);
102 url_request->headers = flattener.GetBuffer().Pass();
104 AddRequestBody(url_request.get(), request);
106 return url_request.Pass();