2 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
3 * (C) 2007 Graham Dennis (graham.dennis@gmail.com)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
31 #include "ResourceLoader.h"
33 #include "DocumentLoader.h"
35 #include "FrameLoader.h"
37 #include "ProgressTracker.h"
38 #include "ResourceHandle.h"
39 #include "ResourceError.h"
40 #include "SharedBuffer.h"
44 PassRefPtr<SharedBuffer> ResourceLoader::resourceData()
47 return m_resourceData;
49 if (ResourceHandle::supportsBufferedData() && m_handle)
50 return m_handle->bufferedData();
55 ResourceLoader::ResourceLoader(Frame* frame, bool sendResourceLoadCallbacks)
56 : m_reachedTerminalState(false)
58 , m_calledDidFinishLoad(false)
59 , m_sendResourceLoadCallbacks(sendResourceLoadCallbacks)
61 , m_documentLoader(frame->loader()->activeDocumentLoader())
63 , m_defersLoading(frame->page()->defersLoading())
67 ResourceLoader::~ResourceLoader()
69 ASSERT(m_reachedTerminalState);
72 void ResourceLoader::releaseResources()
74 ASSERT(!m_reachedTerminalState);
76 // It's possible that when we release the handle, it will be
77 // deallocated and release the last reference to this object.
78 // We need to retain to avoid accessing the object after it
79 // has been deallocated and also to avoid reentering this method.
80 RefPtr<ResourceLoader> protector(this);
85 // We need to set reachedTerminalState to true before we release
86 // the resources to prevent a double dealloc of WebView <rdar://problem/4372628>
87 m_reachedTerminalState = true;
93 m_deferredRequest = ResourceRequest();
96 bool ResourceLoader::load(const ResourceRequest& r)
99 ASSERT(m_deferredRequest.isNull());
100 ASSERT(!frameLoader()->isArchiveLoadPending(this));
102 m_originalURL = r.url();
104 ResourceRequest clientRequest(r);
105 willSendRequest(clientRequest, ResourceResponse());
106 if (clientRequest.isNull()) {
107 didFail(frameLoader()->cancelledError(r));
111 if (frameLoader()->willUseArchive(this, clientRequest, m_originalURL))
114 if (m_defersLoading) {
115 m_deferredRequest = clientRequest;
119 m_handle = ResourceHandle::create(clientRequest, this, m_frame.get(), m_defersLoading);
124 void ResourceLoader::setDefersLoading(bool defers)
126 m_defersLoading = defers;
128 m_handle->setDefersLoading(defers);
129 if (!defers && !m_deferredRequest.isNull()) {
130 ResourceRequest request(m_deferredRequest);
131 m_deferredRequest = ResourceRequest();
136 FrameLoader* ResourceLoader::frameLoader() const
140 return m_frame->loader();
143 void ResourceLoader::addData(const char* data, int length, bool allAtOnce)
146 m_resourceData = new SharedBuffer(data, length);
150 if (ResourceHandle::supportsBufferedData()) {
151 // Buffer data only if the connection has handed us the data because is has stopped buffering it.
153 m_resourceData->append(data, length);
156 m_resourceData = new SharedBuffer(data, length);
158 m_resourceData->append(data, length);
162 void ResourceLoader::clearResourceData()
164 m_resourceData->clear();
167 void ResourceLoader::willSendRequest(ResourceRequest& request, const ResourceResponse& redirectResponse)
169 // Protect this in this delegate method since the additional processing can do
170 // anything including possibly derefing this; one example of this is Radar 3266216.
171 RefPtr<ResourceLoader> protector(this);
173 ASSERT(!m_reachedTerminalState);
175 if (m_sendResourceLoadCallbacks) {
177 m_identifier = m_frame->page()->progress()->createUniqueIdentifier();
178 frameLoader()->assignIdentifierToInitialRequest(m_identifier, request);
181 frameLoader()->willSendRequest(this, request, redirectResponse);
187 void ResourceLoader::didReceiveResponse(const ResourceResponse& r)
189 ASSERT(!m_reachedTerminalState);
191 // Protect this in this delegate method since the additional processing can do
192 // anything including possibly derefing this; one example of this is Radar 3266216.
193 RefPtr<ResourceLoader> protector(this);
197 if (m_sendResourceLoadCallbacks)
198 frameLoader()->didReceiveResponse(this, m_response);
201 void ResourceLoader::didReceiveData(const char* data, int length, long long lengthReceived, bool allAtOnce)
203 // The following assertions are not quite valid here, since a subclass
204 // might override didReceiveData in a way that invalidates them. This
205 // happens with the steps listed in 3266216
206 // ASSERT(con == connection);
207 // ASSERT(!m_reachedTerminalState);
209 // Protect this in this delegate method since the additional processing can do
210 // anything including possibly derefing this; one example of this is Radar 3266216.
211 RefPtr<ResourceLoader> protector(this);
213 addData(data, length, allAtOnce);
214 // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
215 // However, with today's computers and networking speeds, this won't happen in practice.
216 // Could be an issue with a giant local file.
217 if (m_sendResourceLoadCallbacks && m_frame)
218 frameLoader()->didReceiveData(this, data, length, static_cast<int>(lengthReceived));
221 void ResourceLoader::willStopBufferingData(const char* data, int length)
223 ASSERT(!m_resourceData);
224 m_resourceData = new SharedBuffer(data, length);
227 void ResourceLoader::didFinishLoading()
229 // If load has been cancelled after finishing (which could happen with a
230 // JavaScript that changes the window location), do nothing.
233 ASSERT(!m_reachedTerminalState);
235 didFinishLoadingOnePart();
239 void ResourceLoader::didFinishLoadingOnePart()
243 ASSERT(!m_reachedTerminalState);
245 if (m_calledDidFinishLoad)
247 m_calledDidFinishLoad = true;
248 if (m_sendResourceLoadCallbacks)
249 frameLoader()->didFinishLoad(this);
252 void ResourceLoader::didFail(const ResourceError& error)
256 ASSERT(!m_reachedTerminalState);
258 // Protect this in this delegate method since the additional processing can do
259 // anything including possibly derefing this; one example of this is Radar 3266216.
260 RefPtr<ResourceLoader> protector(this);
262 if (m_sendResourceLoadCallbacks && !m_calledDidFinishLoad)
263 frameLoader()->didFailToLoad(this, error);
268 void ResourceLoader::wasBlocked()
270 didFail(blockedError());
273 void ResourceLoader::didCancel(const ResourceError& error)
275 ASSERT(!m_cancelled);
276 ASSERT(!m_reachedTerminalState);
278 // This flag prevents bad behavior when loads that finish cause the
279 // load itself to be cancelled (which could happen with a javascript that
280 // changes the window location). This is used to prevent both the body
281 // of this method and the body of connectionDidFinishLoading: running
282 // for a single delegate. Cancelling wins.
286 m_handle->clearAuthentication();
288 frameLoader()->cancelPendingArchiveLoad(this);
293 if (m_sendResourceLoadCallbacks && !m_calledDidFinishLoad)
294 frameLoader()->didFailToLoad(this, error);
299 void ResourceLoader::cancel()
301 cancel(ResourceError());
304 void ResourceLoader::cancel(const ResourceError& error)
306 if (m_reachedTerminalState)
311 didCancel(cancelledError());
314 const ResourceResponse& ResourceLoader::response() const
319 ResourceError ResourceLoader::cancelledError()
321 return frameLoader()->cancelledError(m_request);
324 ResourceError ResourceLoader::blockedError()
326 return frameLoader()->blockedError(m_request);
329 void ResourceLoader::willSendRequest(ResourceHandle*, ResourceRequest& request, const ResourceResponse& redirectResponse)
331 willSendRequest(request, redirectResponse);
334 void ResourceLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response)
336 didReceiveResponse(response);
339 void ResourceLoader::didReceiveData(ResourceHandle*, const char* data, int length, int lengthReceived)
341 didReceiveData(data, length, lengthReceived, false);
344 void ResourceLoader::didFinishLoading(ResourceHandle*)
349 void ResourceLoader::didFail(ResourceHandle*, const ResourceError& error)
354 void ResourceLoader::wasBlocked(ResourceHandle*)
359 void ResourceLoader::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge)
361 // Protect this in this delegate method since the additional processing can do
362 // anything including possibly derefing this; one example of this is Radar 3266216.
363 RefPtr<ResourceLoader> protector(this);
364 frameLoader()->didReceiveAuthenticationChallenge(this, challenge);
367 void ResourceLoader::didCancelAuthenticationChallenge(const AuthenticationChallenge& challenge)
369 // Protect this in this delegate method since the additional processing can do
370 // anything including possibly derefing this; one example of this is Radar 3266216.
371 RefPtr<ResourceLoader> protector(this);
372 frameLoader()->didCancelAuthenticationChallenge(this, challenge);
375 void ResourceLoader::receivedCancellation(const AuthenticationChallenge&)
380 void ResourceLoader::willCacheResponse(ResourceHandle*, CacheStoragePolicy& policy)
382 // When in private browsing mode, prevent caching to disk
383 if (policy == StorageAllowed && frameLoader()->privateBrowsingEnabled())
384 policy = StorageAllowedInMemoryOnly;