1 // Copyright (c) 2012 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/renderer/fetchers/resource_fetcher_impl.h"
7 #include "base/logging.h"
8 #include "base/strings/string_util.h"
9 #include "base/time/time.h"
10 #include "third_party/WebKit/public/platform/Platform.h"
11 #include "third_party/WebKit/public/platform/WebHTTPBody.h"
12 #include "third_party/WebKit/public/platform/WebURL.h"
13 #include "third_party/WebKit/public/platform/WebURLError.h"
14 #include "third_party/WebKit/public/platform/WebURLLoader.h"
15 #include "third_party/WebKit/public/platform/WebURLRequest.h"
16 #include "third_party/WebKit/public/web/WebDocument.h"
17 #include "third_party/WebKit/public/web/WebFrame.h"
18 #include "third_party/WebKit/public/web/WebKit.h"
19 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
21 using base::TimeDelta
;
22 using blink::WebFrame
;
23 using blink::WebHTTPBody
;
24 using blink::WebSecurityPolicy
;
25 using blink::WebURLError
;
26 using blink::WebURLLoader
;
27 using blink::WebURLRequest
;
28 using blink::WebURLResponse
;
33 ResourceFetcher
* ResourceFetcher::Create(const GURL
& url
) {
34 return new ResourceFetcherImpl(url
);
37 ResourceFetcherImpl::ResourceFetcherImpl(const GURL
& url
)
42 ResourceFetcherImpl::~ResourceFetcherImpl() {
43 if (!completed_
&& loader_
)
47 void ResourceFetcherImpl::SetMethod(const std::string
& method
) {
48 DCHECK(!request_
.isNull());
51 request_
.setHTTPMethod(blink::WebString::fromUTF8(method
));
54 void ResourceFetcherImpl::SetBody(const std::string
& body
) {
55 DCHECK(!request_
.isNull());
58 WebHTTPBody web_http_body
;
59 web_http_body
.initialize();
60 web_http_body
.appendData(blink::WebData(body
));
61 request_
.setHTTPBody(web_http_body
);
64 void ResourceFetcherImpl::SetHeader(const std::string
& header
,
65 const std::string
& value
) {
66 DCHECK(!request_
.isNull());
69 if (LowerCaseEqualsASCII(header
, "referer")) {
70 blink::WebString referrer
= WebSecurityPolicy::generateReferrerHeader(
71 blink::WebReferrerPolicyDefault
,
73 blink::WebString::fromUTF8(value
));
74 request_
.setHTTPReferrer(referrer
, blink::WebReferrerPolicyDefault
);
76 request_
.setHTTPHeaderField(blink::WebString::fromUTF8(header
),
77 blink::WebString::fromUTF8(value
));
81 void ResourceFetcherImpl::Start(WebFrame
* frame
,
82 WebURLRequest::RequestContext request_context
,
83 WebURLRequest::FrameType frame_type
,
84 const Callback
& callback
) {
86 DCHECK(!request_
.isNull());
87 DCHECK(callback_
.is_null());
89 if (!request_
.httpBody().isNull())
90 DCHECK_NE("GET", request_
.httpMethod().utf8()) << "GETs can't have bodies.";
94 request_
.setRequestContext(request_context
);
95 request_
.setFrameType(frame_type
);
96 request_
.setFirstPartyForCookies(frame
->document().firstPartyForCookies());
97 frame
->dispatchWillSendRequest(request_
);
98 loader_
.reset(blink::Platform::current()->createURLLoader());
99 loader_
->loadAsynchronously(request_
, this);
101 // No need to hold on to the request.
105 void ResourceFetcherImpl::SetTimeout(const base::TimeDelta
& timeout
) {
109 timeout_timer_
.Start(FROM_HERE
, timeout
, this,
110 &ResourceFetcherImpl::TimeoutFired
);
113 void ResourceFetcherImpl::RunCallback(const WebURLResponse
& response
,
114 const std::string
& data
) {
116 timeout_timer_
.Stop();
117 if (callback_
.is_null())
120 // Take a reference to the callback as running the callback may lead to our
122 Callback callback
= callback_
;
123 callback
.Run(response
, data
);
126 void ResourceFetcherImpl::TimeoutFired() {
129 RunCallback(WebURLResponse(), std::string());
132 /////////////////////////////////////////////////////////////////////////////
133 // WebURLLoaderClient methods
135 void ResourceFetcherImpl::willSendRequest(
136 WebURLLoader
* loader
, WebURLRequest
& new_request
,
137 const WebURLResponse
& redirect_response
) {
140 void ResourceFetcherImpl::didSendData(
141 WebURLLoader
* loader
, unsigned long long bytes_sent
,
142 unsigned long long total_bytes_to_be_sent
) {
145 void ResourceFetcherImpl::didReceiveResponse(
146 WebURLLoader
* loader
, const WebURLResponse
& response
) {
148 response_
= response
;
151 void ResourceFetcherImpl::didReceiveData(
152 WebURLLoader
* loader
, const char* data
, int data_length
,
153 int encoded_data_length
) {
155 DCHECK(data_length
> 0);
157 data_
.append(data
, data_length
);
160 void ResourceFetcherImpl::didReceiveCachedMetadata(
161 WebURLLoader
* loader
, const char* data
, int data_length
) {
163 DCHECK(data_length
> 0);
165 metadata_
.assign(data
, data_length
);
168 void ResourceFetcherImpl::didFinishLoading(
169 WebURLLoader
* loader
, double finishTime
,
170 int64_t total_encoded_data_length
) {
173 RunCallback(response_
, data_
);
176 void ResourceFetcherImpl::didFail(WebURLLoader
* loader
,
177 const WebURLError
& error
) {
180 // Go ahead and tell our delegate that we're done.
181 RunCallback(WebURLResponse(), std::string());
184 } // namespace content