171d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams// Copyright (c) 2012 The Chromium Authors. All rights reserved.
271d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams// Use of this source code is governed by a BSD-style license that can be
36d7cabef7bfbd7f56c3bb2dca3066430b2116985Christian Williams// found in the LICENSE file.
471d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams
56d7cabef7bfbd7f56c3bb2dca3066430b2116985Christian Williams#include "content/renderer/fetchers/resource_fetcher_impl.h"
671d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams
771d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams#include "base/logging.h"
871d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams#include "base/strings/string_util.h"
971d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams#include "base/time/time.h"
1071d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams#include "third_party/WebKit/public/platform/Platform.h"
1171d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams#include "third_party/WebKit/public/platform/WebHTTPBody.h"
1271d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams#include "third_party/WebKit/public/platform/WebURL.h"
1371d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams#include "third_party/WebKit/public/platform/WebURLError.h"
1471d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams#include "third_party/WebKit/public/platform/WebURLLoader.h"
1571d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams#include "third_party/WebKit/public/platform/WebURLRequest.h"
1671d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams#include "third_party/WebKit/public/web/WebDocument.h"
1771d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams#include "third_party/WebKit/public/web/WebFrame.h"
1871d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams#include "third_party/WebKit/public/web/WebKit.h"
1971d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
2071d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams
2171d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williamsusing base::TimeDelta;
2271d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williamsusing blink::WebFrame;
2371d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williamsusing blink::WebHTTPBody;
2471d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williamsusing blink::WebSecurityPolicy;
2571d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williamsusing blink::WebURLError;
2671d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williamsusing blink::WebURLLoader;
2771d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williamsusing blink::WebURLRequest;
2871d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williamsusing blink::WebURLResponse;
2971d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams
3071d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williamsnamespace content {
3171d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams
3271d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams// 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