Home | History | Annotate | Download | only in fetchers
      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