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
;
22 class HeaderFlattener
: public blink::WebHTTPHeaderVisitor
{
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"))
36 if (LowerCaseEqualsASCII(name_latin1
, "accept"))
37 has_accept_header_
= true;
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_
) {
49 buffer_
.append("\r\n");
50 buffer_
.append("Accept: */*");
51 has_accept_header_
= true;
58 bool has_accept_header_
;
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
;
79 return RESOURCE_TYPE_SUB_RESOURCE
;
82 switch (requestContext
) {
84 case WebURLRequest::RequestContextFavicon
:
85 return RESOURCE_TYPE_FAVICON
;
88 case WebURLRequest::RequestContextFont
:
89 return RESOURCE_TYPE_FONT_RESOURCE
;
92 case WebURLRequest::RequestContextImage
:
93 case WebURLRequest::RequestContextImageSet
:
94 return RESOURCE_TYPE_IMAGE
;
97 case WebURLRequest::RequestContextAudio
:
98 case WebURLRequest::RequestContextVideo
:
99 return RESOURCE_TYPE_MEDIA
;
102 case WebURLRequest::RequestContextEmbed
:
103 case WebURLRequest::RequestContextObject
:
104 return RESOURCE_TYPE_OBJECT
;
107 case WebURLRequest::RequestContextBeacon
:
108 case WebURLRequest::RequestContextCSPReport
:
109 case WebURLRequest::RequestContextPing
:
110 return RESOURCE_TYPE_PING
;
113 case WebURLRequest::RequestContextPrefetch
:
114 return RESOURCE_TYPE_PREFETCH
;
117 case WebURLRequest::RequestContextImport
:
118 case WebURLRequest::RequestContextScript
:
119 return RESOURCE_TYPE_SCRIPT
;
122 case WebURLRequest::RequestContextXSLT
:
123 case WebURLRequest::RequestContextStyle
:
124 return RESOURCE_TYPE_STYLESHEET
;
127 case WebURLRequest::RequestContextDownload
:
128 case WebURLRequest::RequestContextManifest
:
129 case WebURLRequest::RequestContextSubresource
:
130 case WebURLRequest::RequestContextPlugin
:
131 return RESOURCE_TYPE_SUB_RESOURCE
;
134 case WebURLRequest::RequestContextTrack
:
135 return RESOURCE_TYPE_MEDIA
;
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
;
146 case WebURLRequest::RequestContextInternal
:
147 case WebURLRequest::RequestContextUnspecified
:
148 return RESOURCE_TYPE_SUB_RESOURCE
;
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
158 case WebURLRequest::RequestContextForm
:
159 case WebURLRequest::RequestContextHyperlink
:
160 case WebURLRequest::RequestContextLocation
:
161 case WebURLRequest::RequestContextFrame
:
162 case WebURLRequest::RequestContextIframe
:
164 return RESOURCE_TYPE_SUB_RESOURCE
;
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
;
186 case WebURLRequest::ReloadBypassingCache
:
187 load_flags
|= net::LOAD_BYPASS_CACHE
;
189 case WebURLRequest::ReturnCacheDataElseLoad
:
190 load_flags
|= net::LOAD_PREFERRING_CACHE
;
192 case WebURLRequest::ReturnCacheDataDontLoad
:
193 load_flags
|= net::LOAD_ONLY_FROM_CACHE
;
195 case WebURLRequest::UseProtocolCachePolicy
:
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
;
215 scoped_refptr
<ResourceRequestBody
> GetRequestBodyForWebURLRequest(
216 const blink::WebURLRequest
& request
) {
217 scoped_refptr
<ResourceRequestBody
> request_body
;
219 if (request
.httpBody().isNull()) {
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();
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()));
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());
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
));
254 case WebHTTPBody::Element::TypeFileSystemURL
: {
255 GURL file_system_url
= element
.fileSystemURL
;
256 DCHECK(file_system_url
.SchemeIsFileSystem());
257 request_body
->AppendFileSystemFileRange(
259 static_cast<uint64
>(element
.fileStart
),
260 static_cast<uint64
>(element
.fileLength
),
261 base::Time::FromDoubleT(element
.modificationTime
));
264 case WebHTTPBody::Element::TypeBlob
:
265 request_body
->AppendBlob(element
.blobUUID
.utf8());
271 request_body
->set_identifier(request
.httpBody().identifier());
275 } // namespace content