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