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 21using base::TimeDelta; 22using blink::WebFrame; 23using blink::WebHTTPBody; 24using blink::WebSecurityPolicy; 25using blink::WebURLError; 26using blink::WebURLLoader; 27using blink::WebURLRequest; 28using blink::WebURLResponse; 29 30namespace content { 31 32// static 33ResourceFetcher* ResourceFetcher::Create(const GURL& url) { 34 return new ResourceFetcherImpl(url); 35} 36 37ResourceFetcherImpl::ResourceFetcherImpl(const GURL& url) 38 : request_(url) { 39} 40 41ResourceFetcherImpl::~ResourceFetcherImpl() { 42 if (!completed() && loader_) 43 loader_->cancel(); 44} 45 46void ResourceFetcherImpl::SetMethod(const std::string& method) { 47 DCHECK(!request_.isNull()); 48 DCHECK(!loader_); 49 50 request_.setHTTPMethod(blink::WebString::fromUTF8(method)); 51} 52 53void ResourceFetcherImpl::SetBody(const std::string& body) { 54 DCHECK(!request_.isNull()); 55 DCHECK(!loader_); 56 57 WebHTTPBody web_http_body; 58 web_http_body.initialize(); 59 web_http_body.appendData(blink::WebData(body)); 60 request_.setHTTPBody(web_http_body); 61} 62 63void ResourceFetcherImpl::SetHeader(const std::string& header, 64 const std::string& value) { 65 DCHECK(!request_.isNull()); 66 DCHECK(!loader_); 67 68 if (LowerCaseEqualsASCII(header, "referer")) { 69 blink::WebString referrer = WebSecurityPolicy::generateReferrerHeader( 70 blink::WebReferrerPolicyDefault, 71 request_.url(), 72 blink::WebString::fromUTF8(value)); 73 request_.setHTTPReferrer(referrer, blink::WebReferrerPolicyDefault); 74 } else { 75 request_.setHTTPHeaderField(blink::WebString::fromUTF8(header), 76 blink::WebString::fromUTF8(value)); 77 } 78} 79 80void ResourceFetcherImpl::Start(WebFrame* frame, 81 WebURLRequest::RequestContext request_context, 82 WebURLRequest::FrameType frame_type, 83 LoaderType loader_type, 84 const Callback& callback) { 85 DCHECK(!loader_); 86 DCHECK(!request_.isNull()); 87 DCHECK(callback_.is_null()); 88 DCHECK(!completed()); 89 if (!request_.httpBody().isNull()) 90 DCHECK_NE("GET", request_.httpMethod().utf8()) << "GETs can't have bodies."; 91 92 callback_ = callback; 93 94 request_.setRequestContext(request_context); 95 request_.setFrameType(frame_type); 96 request_.setFirstPartyForCookies(frame->document().firstPartyForCookies()); 97 frame->dispatchWillSendRequest(request_); 98 99 switch (loader_type) { 100 case PLATFORM_LOADER: 101 loader_.reset(blink::Platform::current()->createURLLoader()); 102 break; 103 case FRAME_ASSOCIATED_LOADER: 104 loader_.reset(frame->createAssociatedURLLoader()); 105 break; 106 } 107 loader_->loadAsynchronously(request_, this); 108 109 // No need to hold on to the request. 110 request_.reset(); 111} 112 113void ResourceFetcherImpl::SetTimeout(const base::TimeDelta& timeout) { 114 DCHECK(loader_); 115 DCHECK(!completed()); 116 117 timeout_timer_.Start(FROM_HERE, timeout, this, &ResourceFetcherImpl::Cancel); 118} 119 120void ResourceFetcherImpl::OnLoadComplete() { 121 timeout_timer_.Stop(); 122 if (callback_.is_null()) 123 return; 124 125 // Take a reference to the callback as running the callback may lead to our 126 // destruction. 127 Callback callback = callback_; 128 callback.Run(status() == LOAD_FAILED ? blink::WebURLResponse() : response(), 129 status() == LOAD_FAILED ? std::string() : data()); 130} 131 132void ResourceFetcherImpl::Cancel() { 133 loader_->cancel(); 134 WebURLLoaderClientImpl::Cancel(); 135} 136 137} // namespace content 138