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. 4 5 #include "content/renderer/fetchers/resource_fetcher_impl.h" 6 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" 20 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; 29 30 namespace content { 31 32 // static 33 ResourceFetcher* ResourceFetcher::Create(const GURL& url) { 34 return new ResourceFetcherImpl(url); 35 } 36 37 ResourceFetcherImpl::ResourceFetcherImpl(const GURL& url) 38 : request_(url), 39 completed_(false) { 40 } 41 42 ResourceFetcherImpl::~ResourceFetcherImpl() { 43 if (!completed_ && loader_) 44 loader_->cancel(); 45 } 46 47 void ResourceFetcherImpl::SetMethod(const std::string& method) { 48 DCHECK(!request_.isNull()); 49 DCHECK(!loader_); 50 51 request_.setHTTPMethod(blink::WebString::fromUTF8(method)); 52 } 53 54 void ResourceFetcherImpl::SetBody(const std::string& body) { 55 DCHECK(!request_.isNull()); 56 DCHECK(!loader_); 57 58 WebHTTPBody web_http_body; 59 web_http_body.initialize(); 60 web_http_body.appendData(blink::WebData(body)); 61 request_.setHTTPBody(web_http_body); 62 } 63 64 void ResourceFetcherImpl::SetHeader(const std::string& header, 65 const std::string& value) { 66 DCHECK(!request_.isNull()); 67 DCHECK(!loader_); 68 69 if (LowerCaseEqualsASCII(header, "referer")) { 70 blink::WebString referrer = WebSecurityPolicy::generateReferrerHeader( 71 blink::WebReferrerPolicyDefault, 72 request_.url(), 73 blink::WebString::fromUTF8(value)); 74 request_.setHTTPReferrer(referrer, blink::WebReferrerPolicyDefault); 75 } else { 76 request_.setHTTPHeaderField(blink::WebString::fromUTF8(header), 77 blink::WebString::fromUTF8(value)); 78 } 79 } 80 81 void ResourceFetcherImpl::Start(WebFrame* frame, 82 WebURLRequest::TargetType target_type, 83 const Callback& callback) { 84 DCHECK(!loader_); 85 DCHECK(!request_.isNull()); 86 DCHECK(callback_.is_null()); 87 DCHECK(!completed_); 88 if (!request_.httpBody().isNull()) 89 DCHECK_NE("GET", request_.httpMethod().utf8()) << "GETs can't have bodies."; 90 91 callback_ = callback; 92 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); 98 99 // No need to hold on to the request. 100 request_.reset(); 101 } 102 103 void ResourceFetcherImpl::SetTimeout(const base::TimeDelta& timeout) { 104 DCHECK(loader_); 105 DCHECK(!completed_); 106 107 timeout_timer_.Start(FROM_HERE, timeout, this, 108 &ResourceFetcherImpl::TimeoutFired); 109 } 110 111 void ResourceFetcherImpl::RunCallback(const WebURLResponse& response, 112 const std::string& data) { 113 completed_ = true; 114 timeout_timer_.Stop(); 115 if (callback_.is_null()) 116 return; 117 118 // Take a reference to the callback as running the callback may lead to our 119 // destruction. 120 Callback callback = callback_; 121 callback.Run(response, data); 122 } 123 124 void ResourceFetcherImpl::TimeoutFired() { 125 DCHECK(!completed_); 126 loader_->cancel(); 127 RunCallback(WebURLResponse(), std::string()); 128 } 129 130 ///////////////////////////////////////////////////////////////////////////// 131 // WebURLLoaderClient methods 132 133 void ResourceFetcherImpl::willSendRequest( 134 WebURLLoader* loader, WebURLRequest& new_request, 135 const WebURLResponse& redirect_response) { 136 } 137 138 void ResourceFetcherImpl::didSendData( 139 WebURLLoader* loader, unsigned long long bytes_sent, 140 unsigned long long total_bytes_to_be_sent) { 141 } 142 143 void ResourceFetcherImpl::didReceiveResponse( 144 WebURLLoader* loader, const WebURLResponse& response) { 145 DCHECK(!completed_); 146 response_ = response; 147 } 148 149 void ResourceFetcherImpl::didReceiveData( 150 WebURLLoader* loader, const char* data, int data_length, 151 int encoded_data_length) { 152 DCHECK(!completed_); 153 DCHECK(data_length > 0); 154 155 data_.append(data, data_length); 156 } 157 158 void ResourceFetcherImpl::didReceiveCachedMetadata( 159 WebURLLoader* loader, const char* data, int data_length) { 160 DCHECK(!completed_); 161 DCHECK(data_length > 0); 162 163 metadata_.assign(data, data_length); 164 } 165 166 void ResourceFetcherImpl::didFinishLoading( 167 WebURLLoader* loader, double finishTime, 168 int64_t total_encoded_data_length) { 169 DCHECK(!completed_); 170 171 RunCallback(response_, data_); 172 } 173 174 void ResourceFetcherImpl::didFail(WebURLLoader* loader, 175 const WebURLError& error) { 176 DCHECK(!completed_); 177 178 // Go ahead and tell our delegate that we're done. 179 RunCallback(WebURLResponse(), std::string()); 180 } 181 182 } // namespace content 183