1 // Copyright (c) 2011 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 "webkit/glue/resource_fetcher.h"
6
7 #include "base/logging.h"
8 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
9 #include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
10 #include "third_party/WebKit/Source/WebKit/chromium/public/WebKitClient.h"
11 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLError.h"
12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoader.h"
13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h"
14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
15
16 using base::TimeDelta;
17 using WebKit::WebFrame;
18 using WebKit::WebURLError;
19 using WebKit::WebURLLoader;
20 using WebKit::WebURLRequest;
21 using WebKit::WebURLResponse;
22
23 namespace webkit_glue {
24
ResourceFetcher(const GURL & url,WebFrame * frame,WebURLRequest::TargetType target_type,Callback * callback)25 ResourceFetcher::ResourceFetcher(const GURL& url, WebFrame* frame,
26 WebURLRequest::TargetType target_type,
27 Callback* callback)
28 : url_(url),
29 target_type_(target_type),
30 completed_(false),
31 callback_(callback) {
32 // Can't do anything without a frame. However, delegate can be NULL (so we
33 // can do a http request and ignore the results).
34 DCHECK(frame);
35 Start(frame);
36 }
37
~ResourceFetcher()38 ResourceFetcher::~ResourceFetcher() {
39 if (!completed_ && loader_.get())
40 loader_->cancel();
41 }
42
Cancel()43 void ResourceFetcher::Cancel() {
44 if (!completed_) {
45 loader_->cancel();
46 completed_ = true;
47 }
48 }
49
Start(WebFrame * frame)50 void ResourceFetcher::Start(WebFrame* frame) {
51 WebURLRequest request(url_);
52 request.setTargetType(target_type_);
53 frame->dispatchWillSendRequest(request);
54
55 loader_.reset(WebKit::webKitClient()->createURLLoader());
56 loader_->loadAsynchronously(request, this);
57 }
58
RunCallback(const WebURLResponse & response,const std::string & data)59 void ResourceFetcher::RunCallback(const WebURLResponse& response,
60 const std::string& data) {
61 if (!callback_.get())
62 return;
63
64 // Take care to clear callback_ before running the callback as it may lead to
65 // our destruction.
66 scoped_ptr<Callback> callback;
67 callback.swap(callback_);
68 callback->Run(response, data);
69 }
70
71 /////////////////////////////////////////////////////////////////////////////
72 // WebURLLoaderClient methods
73
willSendRequest(WebURLLoader * loader,WebURLRequest & new_request,const WebURLResponse & redirect_response)74 void ResourceFetcher::willSendRequest(
75 WebURLLoader* loader, WebURLRequest& new_request,
76 const WebURLResponse& redirect_response) {
77 }
78
didSendData(WebURLLoader * loader,unsigned long long bytes_sent,unsigned long long total_bytes_to_be_sent)79 void ResourceFetcher::didSendData(
80 WebURLLoader* loader, unsigned long long bytes_sent,
81 unsigned long long total_bytes_to_be_sent) {
82 }
83
didReceiveResponse(WebURLLoader * loader,const WebURLResponse & response)84 void ResourceFetcher::didReceiveResponse(
85 WebURLLoader* loader, const WebURLResponse& response) {
86 DCHECK(!completed_);
87 response_ = response;
88 }
89
didReceiveData(WebURLLoader * loader,const char * data,int data_length,int encoded_data_length)90 void ResourceFetcher::didReceiveData(
91 WebURLLoader* loader, const char* data, int data_length,
92 int encoded_data_length) {
93 DCHECK(!completed_);
94 DCHECK(data_length > 0);
95
96 data_.append(data, data_length);
97 }
98
didReceiveCachedMetadata(WebURLLoader * loader,const char * data,int data_length)99 void ResourceFetcher::didReceiveCachedMetadata(
100 WebURLLoader* loader, const char* data, int data_length) {
101 DCHECK(!completed_);
102 DCHECK(data_length > 0);
103
104 metadata_.assign(data, data_length);
105 }
106
didFinishLoading(WebURLLoader * loader,double finishTime)107 void ResourceFetcher::didFinishLoading(
108 WebURLLoader* loader, double finishTime) {
109 DCHECK(!completed_);
110 completed_ = true;
111
112 RunCallback(response_, data_);
113 }
114
didFail(WebURLLoader * loader,const WebURLError & error)115 void ResourceFetcher::didFail(WebURLLoader* loader, const WebURLError& error) {
116 DCHECK(!completed_);
117 completed_ = true;
118
119 // Go ahead and tell our delegate that we're done.
120 RunCallback(WebURLResponse(), std::string());
121 }
122
123 /////////////////////////////////////////////////////////////////////////////
124 // A resource fetcher with a timeout
125
ResourceFetcherWithTimeout(const GURL & url,WebFrame * frame,WebURLRequest::TargetType target_type,int timeout_secs,Callback * callback)126 ResourceFetcherWithTimeout::ResourceFetcherWithTimeout(
127 const GURL& url, WebFrame* frame, WebURLRequest::TargetType target_type,
128 int timeout_secs, Callback* callback)
129 : ResourceFetcher(url, frame, target_type, callback) {
130 timeout_timer_.Start(TimeDelta::FromSeconds(timeout_secs), this,
131 &ResourceFetcherWithTimeout::TimeoutFired);
132 }
133
~ResourceFetcherWithTimeout()134 ResourceFetcherWithTimeout::~ResourceFetcherWithTimeout() {
135 }
136
TimeoutFired()137 void ResourceFetcherWithTimeout::TimeoutFired() {
138 if (!completed_) {
139 loader_->cancel();
140 didFail(NULL, WebURLError());
141 }
142 }
143
144 } // namespace webkit_glue
145