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::TargetType target_type
,
83 const Callback
& callback
) {
85 DCHECK(!request_
.isNull());
86 DCHECK(callback_
.is_null());
88 if (!request_
.httpBody().isNull())
89 DCHECK_NE("GET", request_
.httpMethod().utf8()) << "GETs can't have bodies.";
93 request_
.setTargetType(target_type
);
94 request_
.setFirstPartyForCookies(frame
->document().firstPartyForCookies());
95 frame
->dispatchWillSendRequest(request_
);
96 loader_
.reset(blink::Platform::current()->createURLLoader());
97 loader_
->loadAsynchronously(request_
, this);
99 // No need to hold on to the request.
103 void ResourceFetcherImpl::SetTimeout(const base::TimeDelta
& timeout
) {
107 timeout_timer_
.Start(FROM_HERE
, timeout
, this,
108 &ResourceFetcherImpl::TimeoutFired
);
111 void ResourceFetcherImpl::RunCallback(const WebURLResponse
& response
,
112 const std::string
& data
) {
114 timeout_timer_
.Stop();
115 if (callback_
.is_null())
118 // Take a reference to the callback as running the callback may lead to our
120 Callback callback
= callback_
;
121 callback
.Run(response
, data
);
124 void ResourceFetcherImpl::TimeoutFired() {
127 RunCallback(WebURLResponse(), std::string());
130 /////////////////////////////////////////////////////////////////////////////
131 // WebURLLoaderClient methods
133 void ResourceFetcherImpl::willSendRequest(
134 WebURLLoader
* loader
, WebURLRequest
& new_request
,
135 const WebURLResponse
& redirect_response
) {
138 void ResourceFetcherImpl::didSendData(
139 WebURLLoader
* loader
, unsigned long long bytes_sent
,
140 unsigned long long total_bytes_to_be_sent
) {
143 void ResourceFetcherImpl::didReceiveResponse(
144 WebURLLoader
* loader
, const WebURLResponse
& response
) {
146 response_
= response
;
149 void ResourceFetcherImpl::didReceiveData(
150 WebURLLoader
* loader
, const char* data
, int data_length
,
151 int encoded_data_length
) {
153 DCHECK(data_length
> 0);
155 data_
.append(data
, data_length
);
158 void ResourceFetcherImpl::didReceiveCachedMetadata(
159 WebURLLoader
* loader
, const char* data
, int data_length
) {
161 DCHECK(data_length
> 0);
163 metadata_
.assign(data
, data_length
);
166 void ResourceFetcherImpl::didFinishLoading(
167 WebURLLoader
* loader
, double finishTime
,
168 int64_t total_encoded_data_length
) {
171 RunCallback(response_
, data_
);
174 void ResourceFetcherImpl::didFail(WebURLLoader
* loader
,
175 const WebURLError
& error
) {
178 // Go ahead and tell our delegate that we're done.
179 RunCallback(WebURLResponse(), std::string());
182 } // namespace content