Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / child / web_url_request_util.cc
blob145537e300d8e5409f5c8157686812f5f3e9cacb
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 "content/child/web_url_request_util.h"
7 #include "base/logging.h"
8 #include "base/strings/string_util.h"
9 #include "net/base/load_flags.h"
10 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
11 #include "third_party/WebKit/public/platform/WebString.h"
12 #include "third_party/WebKit/public/platform/WebURLRequest.h"
14 using blink::WebHTTPBody;
15 using blink::WebString;
16 using blink::WebURLRequest;
18 namespace content {
20 namespace {
22 class HeaderFlattener : public blink::WebHTTPHeaderVisitor {
23 public:
24 HeaderFlattener() : has_accept_header_(false) {}
26 virtual void visitHeader(const WebString& name, const WebString& value) {
27 // Headers are latin1.
28 const std::string& name_latin1 = name.latin1();
29 const std::string& value_latin1 = value.latin1();
31 // Skip over referrer headers found in the header map because we already
32 // pulled it out as a separate parameter.
33 if (LowerCaseEqualsASCII(name_latin1, "referer"))
34 return;
36 if (LowerCaseEqualsASCII(name_latin1, "accept"))
37 has_accept_header_ = true;
39 if (!buffer_.empty())
40 buffer_.append("\r\n");
41 buffer_.append(name_latin1 + ": " + value_latin1);
44 const std::string& GetBuffer() {
45 // In some cases, WebKit doesn't add an Accept header, but not having the
46 // header confuses some web servers. See bug 808613.
47 if (!has_accept_header_) {
48 if (!buffer_.empty())
49 buffer_.append("\r\n");
50 buffer_.append("Accept: */*");
51 has_accept_header_ = true;
53 return buffer_;
56 private:
57 std::string buffer_;
58 bool has_accept_header_;
61 } // namespace
63 ResourceType WebURLRequestToResourceType(const WebURLRequest& request) {
64 WebURLRequest::RequestContext requestContext = request.requestContext();
65 if (request.frameType() != WebURLRequest::FrameTypeNone) {
66 DCHECK(requestContext == WebURLRequest::RequestContextForm ||
67 requestContext == WebURLRequest::RequestContextFrame ||
68 requestContext == WebURLRequest::RequestContextHyperlink ||
69 requestContext == WebURLRequest::RequestContextIframe ||
70 requestContext == WebURLRequest::RequestContextInternal ||
71 requestContext == WebURLRequest::RequestContextLocation);
72 if (request.frameType() == WebURLRequest::FrameTypeTopLevel ||
73 request.frameType() == WebURLRequest::FrameTypeAuxiliary) {
74 return RESOURCE_TYPE_MAIN_FRAME;
76 if (request.frameType() == WebURLRequest::FrameTypeNested)
77 return RESOURCE_TYPE_SUB_FRAME;
78 NOTREACHED();
79 return RESOURCE_TYPE_SUB_RESOURCE;
82 switch (requestContext) {
83 // Favicon
84 case WebURLRequest::RequestContextFavicon:
85 return RESOURCE_TYPE_FAVICON;
87 // Font
88 case WebURLRequest::RequestContextFont:
89 return RESOURCE_TYPE_FONT_RESOURCE;
91 // Image
92 case WebURLRequest::RequestContextImage:
93 case WebURLRequest::RequestContextImageSet:
94 return RESOURCE_TYPE_IMAGE;
96 // Media
97 case WebURLRequest::RequestContextAudio:
98 case WebURLRequest::RequestContextVideo:
99 return RESOURCE_TYPE_MEDIA;
101 // Object
102 case WebURLRequest::RequestContextEmbed:
103 case WebURLRequest::RequestContextObject:
104 return RESOURCE_TYPE_OBJECT;
106 // Ping
107 case WebURLRequest::RequestContextBeacon:
108 case WebURLRequest::RequestContextCSPReport:
109 case WebURLRequest::RequestContextPing:
110 return RESOURCE_TYPE_PING;
112 // Prefetch
113 case WebURLRequest::RequestContextPrefetch:
114 return RESOURCE_TYPE_PREFETCH;
116 // Script
117 case WebURLRequest::RequestContextImport:
118 case WebURLRequest::RequestContextScript:
119 return RESOURCE_TYPE_SCRIPT;
121 // Style
122 case WebURLRequest::RequestContextXSLT:
123 case WebURLRequest::RequestContextStyle:
124 return RESOURCE_TYPE_STYLESHEET;
126 // Subresource
127 case WebURLRequest::RequestContextDownload:
128 case WebURLRequest::RequestContextManifest:
129 case WebURLRequest::RequestContextSubresource:
130 case WebURLRequest::RequestContextPlugin:
131 return RESOURCE_TYPE_SUB_RESOURCE;
133 // TextTrack
134 case WebURLRequest::RequestContextTrack:
135 return RESOURCE_TYPE_MEDIA;
137 // Workers
138 case WebURLRequest::RequestContextServiceWorker:
139 return RESOURCE_TYPE_SERVICE_WORKER;
140 case WebURLRequest::RequestContextSharedWorker:
141 return RESOURCE_TYPE_SHARED_WORKER;
142 case WebURLRequest::RequestContextWorker:
143 return RESOURCE_TYPE_WORKER;
145 // Unspecified
146 case WebURLRequest::RequestContextInternal:
147 case WebURLRequest::RequestContextUnspecified:
148 return RESOURCE_TYPE_SUB_RESOURCE;
150 // XHR
151 case WebURLRequest::RequestContextEventSource:
152 case WebURLRequest::RequestContextFetch:
153 case WebURLRequest::RequestContextXMLHttpRequest:
154 return RESOURCE_TYPE_XHR;
156 // These should be handled by the FrameType checks at the top of the
157 // function.
158 case WebURLRequest::RequestContextForm:
159 case WebURLRequest::RequestContextHyperlink:
160 case WebURLRequest::RequestContextLocation:
161 case WebURLRequest::RequestContextFrame:
162 case WebURLRequest::RequestContextIframe:
163 NOTREACHED();
164 return RESOURCE_TYPE_SUB_RESOURCE;
166 default:
167 NOTREACHED();
168 return RESOURCE_TYPE_SUB_RESOURCE;
172 std::string GetWebURLRequestHeaders(const blink::WebURLRequest& request) {
173 HeaderFlattener flattener;
174 request.visitHTTPHeaderFields(&flattener);
175 return flattener.GetBuffer();
178 int GetLoadFlagsForWebURLRequest(const blink::WebURLRequest& request) {
179 int load_flags = net::LOAD_NORMAL;
180 GURL url = request.url();
181 switch (request.cachePolicy()) {
182 case WebURLRequest::ReloadIgnoringCacheData:
183 // Required by LayoutTests/http/tests/misc/refresh-headers.php
184 load_flags |= net::LOAD_VALIDATE_CACHE;
185 break;
186 case WebURLRequest::ReloadBypassingCache:
187 load_flags |= net::LOAD_BYPASS_CACHE;
188 break;
189 case WebURLRequest::ReturnCacheDataElseLoad:
190 load_flags |= net::LOAD_PREFERRING_CACHE;
191 break;
192 case WebURLRequest::ReturnCacheDataDontLoad:
193 load_flags |= net::LOAD_ONLY_FROM_CACHE;
194 break;
195 case WebURLRequest::UseProtocolCachePolicy:
196 break;
197 default:
198 NOTREACHED();
201 if (request.reportRawHeaders())
202 load_flags |= net::LOAD_REPORT_RAW_HEADERS;
204 if (!request.allowStoredCredentials()) {
205 load_flags |= net::LOAD_DO_NOT_SAVE_COOKIES;
206 load_flags |= net::LOAD_DO_NOT_SEND_COOKIES;
209 if (!request.allowStoredCredentials())
210 load_flags |= net::LOAD_DO_NOT_SEND_AUTH_DATA;
212 return load_flags;
215 scoped_refptr<ResourceRequestBody> GetRequestBodyForWebURLRequest(
216 const blink::WebURLRequest& request) {
217 scoped_refptr<ResourceRequestBody> request_body;
219 if (request.httpBody().isNull()) {
220 return request_body;
223 const std::string& method = request.httpMethod().latin1();
224 // GET and HEAD requests shouldn't have http bodies.
225 DCHECK(method != "GET" && method != "HEAD");
227 const WebHTTPBody& httpBody = request.httpBody();
228 request_body = new ResourceRequestBody();
229 size_t i = 0;
230 WebHTTPBody::Element element;
231 while (httpBody.elementAt(i++, element)) {
232 switch (element.type) {
233 case WebHTTPBody::Element::TypeData:
234 if (!element.data.isEmpty()) {
235 // Blink sometimes gives empty data to append. These aren't
236 // necessary so they are just optimized out here.
237 request_body->AppendBytes(
238 element.data.data(), static_cast<int>(element.data.size()));
240 break;
241 case WebHTTPBody::Element::TypeFile:
242 if (element.fileLength == -1) {
243 request_body->AppendFileRange(
244 base::FilePath::FromUTF16Unsafe(element.filePath),
245 0, kuint64max, base::Time());
246 } else {
247 request_body->AppendFileRange(
248 base::FilePath::FromUTF16Unsafe(element.filePath),
249 static_cast<uint64>(element.fileStart),
250 static_cast<uint64>(element.fileLength),
251 base::Time::FromDoubleT(element.modificationTime));
253 break;
254 case WebHTTPBody::Element::TypeFileSystemURL: {
255 GURL file_system_url = element.fileSystemURL;
256 DCHECK(file_system_url.SchemeIsFileSystem());
257 request_body->AppendFileSystemFileRange(
258 file_system_url,
259 static_cast<uint64>(element.fileStart),
260 static_cast<uint64>(element.fileLength),
261 base::Time::FromDoubleT(element.modificationTime));
262 break;
264 case WebHTTPBody::Element::TypeBlob:
265 request_body->AppendBlob(element.blobUUID.utf8());
266 break;
267 default:
268 NOTREACHED();
271 request_body->set_identifier(request.httpBody().identifier());
272 return request_body;
275 } // namespace content