0c9eee87632ec702a8b057b5b7402cd86ff127fb
[WebKit-https.git] / Source / WebCore / platform / network / chromium / ResourceHandle.cpp
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 "NetworkingContext.h"
35 #include "ResourceError.h"
36 #include "ResourceHandleClient.h"
37 #include "ResourceHandleInternal.h"
38 #include "ResourceRequest.h"
39 #include "ResourceResponse.h"
40 #include "SharedBuffer.h"
41 #include "WrappedResourceRequest.h"
42 #include "WrappedResourceResponse.h"
43 #include <public/Platform.h>
44 #include <public/WebURLError.h>
45 #include <public/WebURLLoader.h>
46 #include <public/WebURLLoaderClient.h>
47 #include <public/WebURLRequest.h>
48 #include <public/WebURLResponse.h>
49
50 using namespace WebKit;
51
52 namespace WebCore {
53
54 // ResourceHandleInternal -----------------------------------------------------
55 ResourceHandleInternal::ResourceHandleInternal(const ResourceRequest& request, ResourceHandleClient* client)
56     : m_request(request)
57     , m_owner(0)
58     , m_client(client)
59     , m_state(ConnectionStateNew)
60 {
61 }
62
63 void ResourceHandleInternal::start()
64 {
65     if (m_state != ConnectionStateNew)
66         CRASH();
67     m_state = ConnectionStateStarted;
68
69     m_loader = adoptPtr(Platform::current()->createURLLoader());
70     ASSERT(m_loader);
71
72     WrappedResourceRequest wrappedRequest(m_request);
73     wrappedRequest.setAllowStoredCredentials(allowStoredCredentials());
74     m_loader->loadAsynchronously(wrappedRequest, this);
75 }
76
77 void ResourceHandleInternal::cancel()
78 {
79     m_state = ConnectionStateCanceled;
80     m_loader->cancel();
81
82     // Do not make any further calls to the client.
83     m_client = 0;
84 }
85
86 void ResourceHandleInternal::setDefersLoading(bool value)
87 {
88     m_loader->setDefersLoading(value);
89 }
90
91 bool ResourceHandleInternal::allowStoredCredentials() const
92 {
93     return m_client && m_client->shouldUseCredentialStorage(m_owner);
94 }
95
96 void ResourceHandleInternal::willSendRequest(
97     WebURLLoader*, WebURLRequest& request, const WebURLResponse& response)
98 {
99     ASSERT(m_client);
100     ASSERT(!request.isNull());
101     ASSERT(!response.isNull());
102     m_client->willSendRequest(m_owner, request.toMutableResourceRequest(), response.toResourceResponse());
103 }
104
105 void ResourceHandleInternal::didSendData(
106     WebURLLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
107 {
108     ASSERT(m_client);
109     m_client->didSendData(m_owner, bytesSent, totalBytesToBeSent);
110 }
111
112 void ResourceHandleInternal::didReceiveResponse(WebURLLoader*, const WebURLResponse& response)
113 {
114     ASSERT(m_client);
115     ASSERT(!response.isNull());
116     bool isMultipart = response.isMultipartPayload();
117     bool isValidStateTransition = (m_state == ConnectionStateStarted || m_state == ConnectionStateReceivedResponse);
118     // In the case of multipart loads, calls to didReceiveData & didReceiveResponse can be interleaved.
119     if (!isMultipart && !isValidStateTransition)
120         CRASH();
121     m_state = ConnectionStateReceivedResponse;
122     m_client->didReceiveResponse(m_owner, response.toResourceResponse());
123 }
124
125 void ResourceHandleInternal::didDownloadData(WebURLLoader*, int dataLength)
126 {
127     ASSERT(m_client);
128     if (m_state != ConnectionStateReceivedResponse)
129         CRASH();
130
131     m_client->didDownloadData(m_owner, dataLength);
132 }
133
134 void ResourceHandleInternal::didReceiveData(WebURLLoader*, const char* data, int dataLength, int encodedDataLength)
135 {
136     ASSERT(m_client);
137     if (m_state != ConnectionStateReceivedResponse && m_state != ConnectionStateReceivingData)
138         CRASH();
139     m_state = ConnectionStateReceivingData;
140
141     m_client->didReceiveData(m_owner, data, dataLength, encodedDataLength);
142 }
143
144 void ResourceHandleInternal::didReceiveCachedMetadata(WebURLLoader*, const char* data, int dataLength)
145 {
146     ASSERT(m_client);
147     if (m_state != ConnectionStateReceivedResponse && m_state != ConnectionStateReceivingData)
148         CRASH();
149
150     m_client->didReceiveCachedMetadata(m_owner, data, dataLength);
151 }
152
153 void ResourceHandleInternal::didFinishLoading(WebURLLoader*, double finishTime)
154 {
155     ASSERT(m_client);
156     if (m_state != ConnectionStateReceivedResponse && m_state != ConnectionStateReceivingData)
157         CRASH();
158     m_state = ConnectionStateFinishedLoading;
159     m_client->didFinishLoading(m_owner, finishTime);
160 }
161
162 void ResourceHandleInternal::didFail(WebURLLoader*, const WebURLError& error)
163 {
164     ASSERT(m_client);
165     m_state = ConnectionStateFailed;
166     m_client->didFail(m_owner, error);
167 }
168
169 ResourceHandleInternal* ResourceHandleInternal::FromResourceHandle(ResourceHandle* handle)
170 {
171     return handle->d.get();
172 }
173
174 // ResourceHandle -------------------------------------------------------------
175
176 ResourceHandle::ResourceHandle(const ResourceRequest& request,
177                                ResourceHandleClient* client,
178                                bool defersLoading,
179                                bool shouldContentSniff)
180     : d(adoptPtr(new ResourceHandleInternal(request, client)))
181 {
182     d->setOwner(this);
183
184     // FIXME: Figure out what to do with the bool params.
185 }
186
187 PassRefPtr<ResourceHandle> ResourceHandle::create(NetworkingContext* context,
188                                                   const ResourceRequest& request,
189                                                   ResourceHandleClient* client,
190                                                   bool defersLoading,
191                                                   bool shouldContentSniff)
192 {
193     RefPtr<ResourceHandle> newHandle = adoptRef(new ResourceHandle(
194         request, client, defersLoading, shouldContentSniff));
195
196     if (newHandle->start(context))
197         return newHandle.release();
198
199     return 0;
200 }
201
202 ResourceRequest& ResourceHandle::firstRequest()
203 {
204     return d->request();
205 }
206
207 ResourceHandleClient* ResourceHandle::client() const
208 {
209     return d->client();
210 }
211
212 void ResourceHandle::setClient(ResourceHandleClient* client)
213 {
214     d->setClient(client);
215 }
216
217 void ResourceHandle::setDefersLoading(bool value)
218 {
219     d->setDefersLoading(value);
220 }
221
222 bool ResourceHandle::start(NetworkingContext* context)
223 {
224     if (!context)
225         return false;
226
227     d->start();
228     return true;
229 }
230
231 bool ResourceHandle::hasAuthenticationChallenge() const
232 {
233     return false;
234 }
235
236 void ResourceHandle::clearAuthentication()
237 {
238 }
239
240 void ResourceHandle::cancel()
241 {
242     d->cancel();
243 }
244
245 ResourceHandle::~ResourceHandle()
246 {
247     d->setOwner(0);
248 }
249
250 bool ResourceHandle::loadsBlocked()
251 {
252     return false; // This seems to be related to sync XMLHttpRequest...
253 }
254
255 // static
256 void ResourceHandle::loadResourceSynchronously(NetworkingContext* context,
257                                                const ResourceRequest& request,
258                                                StoredCredentials storedCredentials,
259                                                ResourceError& error,
260                                                ResourceResponse& response,
261                                                Vector<char>& data)
262 {
263     OwnPtr<WebURLLoader> loader = adoptPtr(Platform::current()->createURLLoader());
264     ASSERT(loader);
265
266     WrappedResourceRequest requestIn(request);
267     requestIn.setAllowStoredCredentials(storedCredentials == AllowStoredCredentials);
268     WrappedResourceResponse responseOut(response);
269     WebURLError errorOut;
270     WebData dataOut;
271
272     loader->loadSynchronously(requestIn, responseOut, errorOut, dataOut);
273
274     error = errorOut;
275     data.clear();
276     data.append(dataOut.data(), dataOut.size());
277 }
278
279 // static
280 bool ResourceHandle::willLoadFromCache(ResourceRequest& request, Frame*)
281 {
282     // This method is used to determine if a POST request can be repeated from
283     // cache, but you cannot really know until you actually try to read from the
284     // cache. Even if we checked now, something else could come along and wipe
285     // out the cache entry by the time we fetch it.
286     //
287     // So, we always say yes here, to prevent the FrameLoader from initiating a
288     // reload. Then in FrameLoaderClientImpl::dispatchWillSendRequest, we
289     // fix-up the cache policy of the request to force a load from the cache.
290     //
291     ASSERT(request.httpMethod() == "POST");
292     return true;
293 }
294
295 // static
296 void ResourceHandle::cacheMetadata(const ResourceResponse& response, const Vector<char>& data)
297 {
298     WebKit::Platform::current()->cacheMetadata(response.url(), response.responseTime(), data.data(), data.size());
299 }
300
301 } // namespace WebCore