• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3  *           (C) 2007 Graham Dennis (graham.dennis@gmail.com)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "config.h"
31 #include "ResourceLoader.h"
32 
33 #include "ApplicationCacheHost.h"
34 #include "DocumentLoader.h"
35 #include "Frame.h"
36 #include "FrameLoader.h"
37 #include "Page.h"
38 #include "ProgressTracker.h"
39 #include "ResourceHandle.h"
40 #include "ResourceError.h"
41 #include "Settings.h"
42 #include "SharedBuffer.h"
43 
44 namespace WebCore {
45 
resourceData()46 PassRefPtr<SharedBuffer> ResourceLoader::resourceData()
47 {
48     if (m_resourceData)
49         return m_resourceData;
50 
51     if (ResourceHandle::supportsBufferedData() && m_handle)
52         return m_handle->bufferedData();
53 
54     return 0;
55 }
56 
ResourceLoader(Frame * frame,bool sendResourceLoadCallbacks,bool shouldContentSniff)57 ResourceLoader::ResourceLoader(Frame* frame, bool sendResourceLoadCallbacks, bool shouldContentSniff)
58     : m_frame(frame)
59     , m_documentLoader(frame->loader()->activeDocumentLoader())
60     , m_identifier(0)
61     , m_reachedTerminalState(false)
62     , m_cancelled(false)
63     , m_calledDidFinishLoad(false)
64     , m_sendResourceLoadCallbacks(sendResourceLoadCallbacks)
65     , m_shouldContentSniff(shouldContentSniff)
66     , m_shouldBufferData(true)
67     , m_defersLoading(frame->page()->defersLoading())
68 {
69 }
70 
~ResourceLoader()71 ResourceLoader::~ResourceLoader()
72 {
73     ASSERT(m_reachedTerminalState);
74 }
75 
releaseResources()76 void ResourceLoader::releaseResources()
77 {
78     ASSERT(!m_reachedTerminalState);
79 
80     // It's possible that when we release the handle, it will be
81     // deallocated and release the last reference to this object.
82     // We need to retain to avoid accessing the object after it
83     // has been deallocated and also to avoid reentering this method.
84     RefPtr<ResourceLoader> protector(this);
85 
86     m_frame = 0;
87     m_documentLoader = 0;
88 
89     // We need to set reachedTerminalState to true before we release
90     // the resources to prevent a double dealloc of WebView <rdar://problem/4372628>
91     m_reachedTerminalState = true;
92 
93     m_identifier = 0;
94 
95     if (m_handle) {
96         // Clear out the ResourceHandle's client so that it doesn't try to call
97         // us back after we release it.
98         m_handle->setClient(0);
99         m_handle = 0;
100     }
101 
102     m_resourceData = 0;
103     m_deferredRequest = ResourceRequest();
104 }
105 
load(const ResourceRequest & r)106 bool ResourceLoader::load(const ResourceRequest& r)
107 {
108     ASSERT(!m_handle);
109     ASSERT(m_deferredRequest.isNull());
110     ASSERT(!m_documentLoader->isSubstituteLoadPending(this));
111 
112     ResourceRequest clientRequest(r);
113     willSendRequest(clientRequest, ResourceResponse());
114     if (clientRequest.isNull()) {
115         didFail(frameLoader()->cancelledError(r));
116         return false;
117     }
118 
119 #if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size
120     if (m_documentLoader->scheduleArchiveLoad(this, clientRequest, r.url()))
121         return true;
122 #endif
123 
124 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
125     if (m_documentLoader->applicationCacheHost()->maybeLoadResource(this, clientRequest, r.url()))
126         return true;
127 #endif
128 
129     if (m_defersLoading) {
130         m_deferredRequest = clientRequest;
131         return true;
132     }
133 
134     m_handle = ResourceHandle::create(clientRequest, this, m_frame.get(), m_defersLoading, m_shouldContentSniff, true);
135 
136     return true;
137 }
138 
setDefersLoading(bool defers)139 void ResourceLoader::setDefersLoading(bool defers)
140 {
141     m_defersLoading = defers;
142     if (m_handle)
143         m_handle->setDefersLoading(defers);
144     if (!defers && !m_deferredRequest.isNull()) {
145         ResourceRequest request(m_deferredRequest);
146         m_deferredRequest = ResourceRequest();
147         load(request);
148     }
149 }
150 
frameLoader() const151 FrameLoader* ResourceLoader::frameLoader() const
152 {
153     if (!m_frame)
154         return 0;
155     return m_frame->loader();
156 }
157 
setShouldBufferData(bool shouldBufferData)158 void ResourceLoader::setShouldBufferData(bool shouldBufferData)
159 {
160     m_shouldBufferData = shouldBufferData;
161 
162     // Reset any already buffered data
163     if (!m_shouldBufferData)
164         m_resourceData = 0;
165 }
166 
167 
addData(const char * data,int length,bool allAtOnce)168 void ResourceLoader::addData(const char* data, int length, bool allAtOnce)
169 {
170     if (!m_shouldBufferData)
171         return;
172 
173     if (allAtOnce) {
174         m_resourceData = SharedBuffer::create(data, length);
175         return;
176     }
177 
178     if (ResourceHandle::supportsBufferedData()) {
179         // Buffer data only if the connection has handed us the data because is has stopped buffering it.
180         if (m_resourceData)
181             m_resourceData->append(data, length);
182     } else {
183         if (!m_resourceData)
184             m_resourceData = SharedBuffer::create(data, length);
185         else
186             m_resourceData->append(data, length);
187     }
188 }
189 
clearResourceData()190 void ResourceLoader::clearResourceData()
191 {
192     if (m_resourceData)
193         m_resourceData->clear();
194 }
195 
willSendRequest(ResourceRequest & request,const ResourceResponse & redirectResponse)196 void ResourceLoader::willSendRequest(ResourceRequest& request, const ResourceResponse& redirectResponse)
197 {
198     // Protect this in this delegate method since the additional processing can do
199     // anything including possibly derefing this; one example of this is Radar 3266216.
200     RefPtr<ResourceLoader> protector(this);
201 
202     ASSERT(!m_reachedTerminalState);
203 
204     if (m_sendResourceLoadCallbacks) {
205         if (!m_identifier) {
206             m_identifier = m_frame->page()->progress()->createUniqueIdentifier();
207             frameLoader()->assignIdentifierToInitialRequest(m_identifier, request);
208         }
209 
210         frameLoader()->willSendRequest(this, request, redirectResponse);
211     }
212 
213     m_request = request;
214 }
215 
didSendData(unsigned long long,unsigned long long)216 void ResourceLoader::didSendData(unsigned long long, unsigned long long)
217 {
218 }
219 
didReceiveResponse(const ResourceResponse & r)220 void ResourceLoader::didReceiveResponse(const ResourceResponse& r)
221 {
222     ASSERT(!m_reachedTerminalState);
223 
224     // Protect this in this delegate method since the additional processing can do
225     // anything including possibly derefing this; one example of this is Radar 3266216.
226     RefPtr<ResourceLoader> protector(this);
227 
228     m_response = r;
229 
230     if (FormData* data = m_request.httpBody())
231         data->removeGeneratedFilesIfNeeded();
232 
233     if (m_sendResourceLoadCallbacks)
234         frameLoader()->didReceiveResponse(this, m_response);
235 }
236 
didReceiveData(const char * data,int length,long long lengthReceived,bool allAtOnce)237 void ResourceLoader::didReceiveData(const char* data, int length, long long lengthReceived, bool allAtOnce)
238 {
239     // The following assertions are not quite valid here, since a subclass
240     // might override didReceiveData in a way that invalidates them. This
241     // happens with the steps listed in 3266216
242     // ASSERT(con == connection);
243     // ASSERT(!m_reachedTerminalState);
244 
245     // Protect this in this delegate method since the additional processing can do
246     // anything including possibly derefing this; one example of this is Radar 3266216.
247     RefPtr<ResourceLoader> protector(this);
248 
249     addData(data, length, allAtOnce);
250     // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
251     // However, with today's computers and networking speeds, this won't happen in practice.
252     // Could be an issue with a giant local file.
253     if (m_sendResourceLoadCallbacks && m_frame)
254         frameLoader()->didReceiveData(this, data, length, static_cast<int>(lengthReceived));
255 }
256 
willStopBufferingData(const char * data,int length)257 void ResourceLoader::willStopBufferingData(const char* data, int length)
258 {
259     if (!m_shouldBufferData)
260         return;
261 
262     ASSERT(!m_resourceData);
263     m_resourceData = SharedBuffer::create(data, length);
264 }
265 
didFinishLoading()266 void ResourceLoader::didFinishLoading()
267 {
268     // If load has been cancelled after finishing (which could happen with a
269     // JavaScript that changes the window location), do nothing.
270     if (m_cancelled)
271         return;
272     ASSERT(!m_reachedTerminalState);
273 
274     didFinishLoadingOnePart();
275     releaseResources();
276 }
277 
didFinishLoadingOnePart()278 void ResourceLoader::didFinishLoadingOnePart()
279 {
280     if (m_cancelled)
281         return;
282     ASSERT(!m_reachedTerminalState);
283 
284     if (m_calledDidFinishLoad)
285         return;
286     m_calledDidFinishLoad = true;
287     if (m_sendResourceLoadCallbacks)
288         frameLoader()->didFinishLoad(this);
289 }
290 
didFail(const ResourceError & error)291 void ResourceLoader::didFail(const ResourceError& error)
292 {
293     if (m_cancelled)
294         return;
295     ASSERT(!m_reachedTerminalState);
296 
297     // Protect this in this delegate method since the additional processing can do
298     // anything including possibly derefing this; one example of this is Radar 3266216.
299     RefPtr<ResourceLoader> protector(this);
300 
301     if (FormData* data = m_request.httpBody())
302         data->removeGeneratedFilesIfNeeded();
303 
304     if (m_sendResourceLoadCallbacks && !m_calledDidFinishLoad)
305         frameLoader()->didFailToLoad(this, error);
306 
307     releaseResources();
308 }
309 
didCancel(const ResourceError & error)310 void ResourceLoader::didCancel(const ResourceError& error)
311 {
312     ASSERT(!m_cancelled);
313     ASSERT(!m_reachedTerminalState);
314 
315     if (FormData* data = m_request.httpBody())
316         data->removeGeneratedFilesIfNeeded();
317 
318     // This flag prevents bad behavior when loads that finish cause the
319     // load itself to be cancelled (which could happen with a javascript that
320     // changes the window location). This is used to prevent both the body
321     // of this method and the body of connectionDidFinishLoading: running
322     // for a single delegate. Cancelling wins.
323     m_cancelled = true;
324 
325     if (m_handle)
326         m_handle->clearAuthentication();
327 
328     m_documentLoader->cancelPendingSubstituteLoad(this);
329     if (m_handle) {
330         m_handle->cancel();
331         m_handle = 0;
332     }
333     if (m_sendResourceLoadCallbacks && !m_calledDidFinishLoad)
334         frameLoader()->didFailToLoad(this, error);
335 
336     releaseResources();
337 }
338 
cancel()339 void ResourceLoader::cancel()
340 {
341     cancel(ResourceError());
342 }
343 
cancel(const ResourceError & error)344 void ResourceLoader::cancel(const ResourceError& error)
345 {
346     if (m_reachedTerminalState)
347         return;
348     if (!error.isNull())
349         didCancel(error);
350     else
351         didCancel(cancelledError());
352 }
353 
response() const354 const ResourceResponse& ResourceLoader::response() const
355 {
356     return m_response;
357 }
358 
cancelledError()359 ResourceError ResourceLoader::cancelledError()
360 {
361     return frameLoader()->cancelledError(m_request);
362 }
363 
blockedError()364 ResourceError ResourceLoader::blockedError()
365 {
366     return frameLoader()->blockedError(m_request);
367 }
368 
cannotShowURLError()369 ResourceError ResourceLoader::cannotShowURLError()
370 {
371     return frameLoader()->cannotShowURLError(m_request);
372 }
373 
willSendRequest(ResourceHandle *,ResourceRequest & request,const ResourceResponse & redirectResponse)374 void ResourceLoader::willSendRequest(ResourceHandle*, ResourceRequest& request, const ResourceResponse& redirectResponse)
375 {
376 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
377     if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForRedirect(this, request, redirectResponse))
378         return;
379 #endif
380     willSendRequest(request, redirectResponse);
381 }
382 
didSendData(ResourceHandle *,unsigned long long bytesSent,unsigned long long totalBytesToBeSent)383 void ResourceLoader::didSendData(ResourceHandle*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
384 {
385     didSendData(bytesSent, totalBytesToBeSent);
386 }
387 
didReceiveResponse(ResourceHandle *,const ResourceResponse & response)388 void ResourceLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response)
389 {
390 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
391     if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForResponse(this, response))
392         return;
393 #endif
394     didReceiveResponse(response);
395 }
396 
didReceiveData(ResourceHandle *,const char * data,int length,int lengthReceived)397 void ResourceLoader::didReceiveData(ResourceHandle*, const char* data, int length, int lengthReceived)
398 {
399     didReceiveData(data, length, lengthReceived, false);
400 }
401 
didFinishLoading(ResourceHandle *)402 void ResourceLoader::didFinishLoading(ResourceHandle*)
403 {
404     didFinishLoading();
405 }
406 
didFail(ResourceHandle *,const ResourceError & error)407 void ResourceLoader::didFail(ResourceHandle*, const ResourceError& error)
408 {
409 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
410     if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForError(this, error))
411         return;
412 #endif
413     didFail(error);
414 }
415 
wasBlocked(ResourceHandle *)416 void ResourceLoader::wasBlocked(ResourceHandle*)
417 {
418     didFail(blockedError());
419 }
420 
cannotShowURL(ResourceHandle *)421 void ResourceLoader::cannotShowURL(ResourceHandle*)
422 {
423     didFail(cannotShowURLError());
424 }
425 
shouldUseCredentialStorage()426 bool ResourceLoader::shouldUseCredentialStorage()
427 {
428     RefPtr<ResourceLoader> protector(this);
429     return frameLoader()->shouldUseCredentialStorage(this);
430 }
431 
didReceiveAuthenticationChallenge(const AuthenticationChallenge & challenge)432 void ResourceLoader::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge)
433 {
434     // Protect this in this delegate method since the additional processing can do
435     // anything including possibly derefing this; one example of this is Radar 3266216.
436     RefPtr<ResourceLoader> protector(this);
437     frameLoader()->didReceiveAuthenticationChallenge(this, challenge);
438 }
439 
didCancelAuthenticationChallenge(const AuthenticationChallenge & challenge)440 void ResourceLoader::didCancelAuthenticationChallenge(const AuthenticationChallenge& challenge)
441 {
442     // Protect this in this delegate method since the additional processing can do
443     // anything including possibly derefing this; one example of this is Radar 3266216.
444     RefPtr<ResourceLoader> protector(this);
445     frameLoader()->didCancelAuthenticationChallenge(this, challenge);
446 }
447 
receivedCancellation(const AuthenticationChallenge &)448 void ResourceLoader::receivedCancellation(const AuthenticationChallenge&)
449 {
450     cancel();
451 }
452 
willCacheResponse(ResourceHandle *,CacheStoragePolicy & policy)453 void ResourceLoader::willCacheResponse(ResourceHandle*, CacheStoragePolicy& policy)
454 {
455     // When in private browsing mode, prevent caching to disk
456     if (policy == StorageAllowed && m_frame->settings()->privateBrowsingEnabled())
457         policy = StorageAllowedInMemoryOnly;
458 }
459 
460 }
461