• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "config.h"
32 #include "ResourceHandle.h"
33 
34 #include "PlatformBridge.h"
35 #include "ResourceHandleClient.h"
36 #include "ResourceRequest.h"
37 #include "SharedBuffer.h"
38 
39 #include "WebKit.h"
40 #include "WebKitClient.h"
41 #include "WebURLError.h"
42 #include "WebURLLoader.h"
43 #include "WebURLLoaderClient.h"
44 #include "WebURLRequest.h"
45 #include "WebURLResponse.h"
46 #include "WrappedResourceRequest.h"
47 #include "WrappedResourceResponse.h"
48 
49 using namespace WebKit;
50 
51 namespace WebCore {
52 
53 // ResourceHandleInternal -----------------------------------------------------
54 
55 class ResourceHandleInternal : public WebURLLoaderClient {
56 public:
ResourceHandleInternal(const ResourceRequest & request,ResourceHandleClient * client)57     ResourceHandleInternal(const ResourceRequest& request, ResourceHandleClient* client)
58         : m_request(request)
59         , m_owner(0)
60         , m_client(client)
61         , m_state(ConnectionStateNew)
62     {
63     }
64 
65     void start();
66     void cancel();
67     void setDefersLoading(bool);
68     bool allowStoredCredentials() const;
69 
70     // WebURLLoaderClient methods:
71     virtual void willSendRequest(WebURLLoader*, WebURLRequest&, const WebURLResponse&);
72     virtual void didSendData(
73         WebURLLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent);
74     virtual void didReceiveResponse(WebURLLoader*, const WebURLResponse&);
75     virtual void didReceiveData(WebURLLoader*, const char* data, int dataLength, int encodedDataLength);
76 
77     virtual void didReceiveCachedMetadata(WebURLLoader*, const char* data, int dataLength);
78     virtual void didFinishLoading(WebURLLoader*, double finishTime);
79     virtual void didFail(WebURLLoader*, const WebURLError&);
80 
81     enum ConnectionState {
82         ConnectionStateNew,
83         ConnectionStateStarted,
84         ConnectionStateReceivedResponse,
85         ConnectionStateReceivingData,
86         ConnectionStateFinishedLoading,
87         ConnectionStateCanceled,
88         ConnectionStateFailed,
89     };
90 
91     ResourceRequest m_request;
92     ResourceHandle* m_owner;
93     ResourceHandleClient* m_client;
94     OwnPtr<WebURLLoader> m_loader;
95 
96     // Used for sanity checking to make sure we don't experience illegal state
97     // transitions.
98     ConnectionState m_state;
99 };
100 
start()101 void ResourceHandleInternal::start()
102 {
103     if (m_state != ConnectionStateNew)
104         CRASH();
105     m_state = ConnectionStateStarted;
106 
107     m_loader.set(webKitClient()->createURLLoader());
108     ASSERT(m_loader.get());
109 
110     WrappedResourceRequest wrappedRequest(m_request);
111     wrappedRequest.setAllowStoredCredentials(allowStoredCredentials());
112     m_loader->loadAsynchronously(wrappedRequest, this);
113 }
114 
cancel()115 void ResourceHandleInternal::cancel()
116 {
117     m_state = ConnectionStateCanceled;
118     m_loader->cancel();
119 
120     // Do not make any further calls to the client.
121     m_client = 0;
122 }
123 
setDefersLoading(bool value)124 void ResourceHandleInternal::setDefersLoading(bool value)
125 {
126     m_loader->setDefersLoading(value);
127 }
128 
allowStoredCredentials() const129 bool ResourceHandleInternal::allowStoredCredentials() const
130 {
131     return m_client && m_client->shouldUseCredentialStorage(m_owner);
132 }
133 
willSendRequest(WebURLLoader *,WebURLRequest & request,const WebURLResponse & response)134 void ResourceHandleInternal::willSendRequest(
135     WebURLLoader*, WebURLRequest& request, const WebURLResponse& response)
136 {
137     ASSERT(m_client);
138     ASSERT(!request.isNull());
139     ASSERT(!response.isNull());
140     m_client->willSendRequest(m_owner, request.toMutableResourceRequest(), response.toResourceResponse());
141 }
142 
didSendData(WebURLLoader *,unsigned long long bytesSent,unsigned long long totalBytesToBeSent)143 void ResourceHandleInternal::didSendData(
144     WebURLLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
145 {
146     ASSERT(m_client);
147     m_client->didSendData(m_owner, bytesSent, totalBytesToBeSent);
148 }
149 
didReceiveResponse(WebURLLoader *,const WebURLResponse & response)150 void ResourceHandleInternal::didReceiveResponse(WebURLLoader*, const WebURLResponse& response)
151 {
152     ASSERT(m_client);
153     ASSERT(!response.isNull());
154     bool isMultipart = response.isMultipartPayload();
155     bool isValidStateTransition = (m_state == ConnectionStateStarted || m_state == ConnectionStateReceivedResponse);
156     // In the case of multipart loads, calls to didReceiveData & didReceiveResponse can be interleaved.
157     if (!isMultipart && !isValidStateTransition)
158         CRASH();
159     m_state = ConnectionStateReceivedResponse;
160     m_client->didReceiveResponse(m_owner, response.toResourceResponse());
161 }
162 
didReceiveData(WebURLLoader *,const char * data,int dataLength,int encodedDataLength)163 void ResourceHandleInternal::didReceiveData(WebURLLoader*, const char* data, int dataLength, int encodedDataLength)
164 {
165     ASSERT(m_client);
166     if (m_state != ConnectionStateReceivedResponse && m_state != ConnectionStateReceivingData)
167         CRASH();
168     m_state = ConnectionStateReceivingData;
169 
170     m_client->didReceiveData(m_owner, data, dataLength, encodedDataLength);
171 }
172 
didReceiveCachedMetadata(WebURLLoader *,const char * data,int dataLength)173 void ResourceHandleInternal::didReceiveCachedMetadata(WebURLLoader*, const char* data, int dataLength)
174 {
175     ASSERT(m_client);
176     if (m_state != ConnectionStateReceivedResponse && m_state != ConnectionStateReceivingData)
177         CRASH();
178 
179     m_client->didReceiveCachedMetadata(m_owner, data, dataLength);
180 }
181 
didFinishLoading(WebURLLoader *,double finishTime)182 void ResourceHandleInternal::didFinishLoading(WebURLLoader*, double finishTime)
183 {
184     ASSERT(m_client);
185     if (m_state != ConnectionStateReceivedResponse && m_state != ConnectionStateReceivingData)
186         CRASH();
187     m_state = ConnectionStateFinishedLoading;
188     m_client->didFinishLoading(m_owner, finishTime);
189 }
190 
didFail(WebURLLoader *,const WebURLError & error)191 void ResourceHandleInternal::didFail(WebURLLoader*, const WebURLError& error)
192 {
193     ASSERT(m_client);
194     m_state = ConnectionStateFailed;
195     m_client->didFail(m_owner, error);
196 }
197 
198 // ResourceHandle -------------------------------------------------------------
199 
ResourceHandle(const ResourceRequest & request,ResourceHandleClient * client,bool defersLoading,bool shouldContentSniff)200 ResourceHandle::ResourceHandle(const ResourceRequest& request,
201                                ResourceHandleClient* client,
202                                bool defersLoading,
203                                bool shouldContentSniff)
204     : d(new ResourceHandleInternal(request, client))
205 {
206     d->m_owner = this;
207 
208     // FIXME: Figure out what to do with the bool params.
209 }
210 
create(NetworkingContext * context,const ResourceRequest & request,ResourceHandleClient * client,bool defersLoading,bool shouldContentSniff)211 PassRefPtr<ResourceHandle> ResourceHandle::create(NetworkingContext* context,
212                                                   const ResourceRequest& request,
213                                                   ResourceHandleClient* client,
214                                                   bool defersLoading,
215                                                   bool shouldContentSniff)
216 {
217     RefPtr<ResourceHandle> newHandle = adoptRef(new ResourceHandle(
218         request, client, defersLoading, shouldContentSniff));
219 
220     if (newHandle->start(context))
221         return newHandle.release();
222 
223     return 0;
224 }
225 
firstRequest()226 ResourceRequest& ResourceHandle::firstRequest()
227 {
228     return d->m_request;
229 }
230 
client() const231 ResourceHandleClient* ResourceHandle::client() const
232 {
233     return d->m_client;
234 }
235 
setClient(ResourceHandleClient * client)236 void ResourceHandle::setClient(ResourceHandleClient* client)
237 {
238     d->m_client = client;
239 }
240 
setDefersLoading(bool value)241 void ResourceHandle::setDefersLoading(bool value)
242 {
243     d->setDefersLoading(value);
244 }
245 
start(NetworkingContext * context)246 bool ResourceHandle::start(NetworkingContext* context)
247 {
248     d->start();
249     return true;
250 }
251 
hasAuthenticationChallenge() const252 bool ResourceHandle::hasAuthenticationChallenge() const
253 {
254     return false;
255 }
256 
clearAuthentication()257 void ResourceHandle::clearAuthentication()
258 {
259 }
260 
cancel()261 void ResourceHandle::cancel()
262 {
263     d->cancel();
264 }
265 
~ResourceHandle()266 ResourceHandle::~ResourceHandle()
267 {
268     d->m_owner = 0;
269 }
270 
bufferedData()271 PassRefPtr<SharedBuffer> ResourceHandle::bufferedData()
272 {
273     return 0;
274 }
275 
loadsBlocked()276 bool ResourceHandle::loadsBlocked()
277 {
278     return false;  // This seems to be related to sync XMLHttpRequest...
279 }
280 
281 // static
supportsBufferedData()282 bool ResourceHandle::supportsBufferedData()
283 {
284     return false;  // The loader will buffer manually if it needs to.
285 }
286 
287 // static
loadResourceSynchronously(NetworkingContext * context,const ResourceRequest & request,StoredCredentials storedCredentials,ResourceError & error,ResourceResponse & response,Vector<char> & data)288 void ResourceHandle::loadResourceSynchronously(NetworkingContext* context,
289                                                const ResourceRequest& request,
290                                                StoredCredentials storedCredentials,
291                                                ResourceError& error,
292                                                ResourceResponse& response,
293                                                Vector<char>& data)
294 {
295     OwnPtr<WebURLLoader> loader(webKitClient()->createURLLoader());
296     ASSERT(loader.get());
297 
298     WrappedResourceRequest requestIn(request);
299     requestIn.setAllowStoredCredentials(storedCredentials == AllowStoredCredentials);
300     WrappedResourceResponse responseOut(response);
301     WebURLError errorOut;
302     WebData dataOut;
303 
304     loader->loadSynchronously(requestIn, responseOut, errorOut, dataOut);
305 
306     error = errorOut;
307     data.clear();
308     data.append(dataOut.data(), dataOut.size());
309 }
310 
311 // static
willLoadFromCache(ResourceRequest & request,Frame *)312 bool ResourceHandle::willLoadFromCache(ResourceRequest& request, Frame*)
313 {
314     // This method is used to determine if a POST request can be repeated from
315     // cache, but you cannot really know until you actually try to read from the
316     // cache.  Even if we checked now, something else could come along and wipe
317     // out the cache entry by the time we fetch it.
318     //
319     // So, we always say yes here, to prevent the FrameLoader from initiating a
320     // reload.  Then in FrameLoaderClientImpl::dispatchWillSendRequest, we
321     // fix-up the cache policy of the request to force a load from the cache.
322     //
323     ASSERT(request.httpMethod() == "POST");
324     return true;
325 }
326 
327 // static
cacheMetadata(const ResourceResponse & response,const Vector<char> & data)328 void ResourceHandle::cacheMetadata(const ResourceResponse& response, const Vector<char>& data)
329 {
330     PlatformBridge::cacheMetadata(response.url(), response.responseTime(), data);
331 }
332 
333 } // namespace WebCore
334