2 * Copyright (C) 2006, 2007 Apple 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"
41 #include "SharedBuffer.h"
45 PassRefPtr
<SharedBuffer
> ResourceLoader::resourceData()
48 return m_resourceData
;
50 if (ResourceHandle::supportsBufferedData() && m_handle
)
51 return m_handle
->bufferedData();
56 ResourceLoader::ResourceLoader(Frame
* frame
, bool sendResourceLoadCallbacks
, bool shouldContentSniff
)
57 : m_reachedTerminalState(false)
59 , m_calledDidFinishLoad(false)
60 , m_sendResourceLoadCallbacks(sendResourceLoadCallbacks
)
61 , m_shouldContentSniff(shouldContentSniff
)
62 , m_shouldBufferData(true)
64 , m_documentLoader(frame
->loader()->activeDocumentLoader())
66 , m_defersLoading(frame
->page()->defersLoading())
70 ResourceLoader::~ResourceLoader()
72 ASSERT(m_reachedTerminalState
);
75 void ResourceLoader::releaseResources()
77 ASSERT(!m_reachedTerminalState
);
79 // It's possible that when we release the handle, it will be
80 // deallocated and release the last reference to this object.
81 // We need to retain to avoid accessing the object after it
82 // has been deallocated and also to avoid reentering this method.
83 RefPtr
<ResourceLoader
> protector(this);
88 // We need to set reachedTerminalState to true before we release
89 // the resources to prevent a double dealloc of WebView <rdar://problem/4372628>
90 m_reachedTerminalState
= true;
95 // Clear out the ResourceHandle's client so that it doesn't try to call
96 // us back after we release it.
97 m_handle
->setClient(0);
102 m_deferredRequest
= ResourceRequest();
105 bool ResourceLoader::load(const ResourceRequest
& r
)
108 ASSERT(m_deferredRequest
.isNull());
109 ASSERT(!frameLoader()->isArchiveLoadPending(this));
111 m_originalURL
= r
.url();
113 ResourceRequest
clientRequest(r
);
114 willSendRequest(clientRequest
, ResourceResponse());
115 if (clientRequest
.isNull()) {
116 didFail(frameLoader()->cancelledError(r
));
120 if (frameLoader()->willUseArchive(this, clientRequest
, m_originalURL
))
123 if (m_defersLoading
) {
124 m_deferredRequest
= clientRequest
;
128 m_handle
= ResourceHandle::create(clientRequest
, this, m_frame
.get(), m_defersLoading
, m_shouldContentSniff
, true);
133 void ResourceLoader::setDefersLoading(bool defers
)
135 m_defersLoading
= defers
;
137 m_handle
->setDefersLoading(defers
);
138 if (!defers
&& !m_deferredRequest
.isNull()) {
139 ResourceRequest
request(m_deferredRequest
);
140 m_deferredRequest
= ResourceRequest();
145 FrameLoader
* ResourceLoader::frameLoader() const
149 return m_frame
->loader();
152 void ResourceLoader::setShouldBufferData(bool shouldBufferData
)
154 m_shouldBufferData
= shouldBufferData
;
156 // Reset any already buffered data
157 if (!m_shouldBufferData
)
162 void ResourceLoader::addData(const char* data
, int length
, bool allAtOnce
)
164 if (!m_shouldBufferData
)
168 m_resourceData
= new SharedBuffer(data
, length
);
172 if (ResourceHandle::supportsBufferedData()) {
173 // Buffer data only if the connection has handed us the data because is has stopped buffering it.
175 m_resourceData
->append(data
, length
);
178 m_resourceData
= new SharedBuffer(data
, length
);
180 m_resourceData
->append(data
, length
);
184 void ResourceLoader::clearResourceData()
187 m_resourceData
->clear();
190 void ResourceLoader::willSendRequest(ResourceRequest
& request
, const ResourceResponse
& redirectResponse
)
192 // Protect this in this delegate method since the additional processing can do
193 // anything including possibly derefing this; one example of this is Radar 3266216.
194 RefPtr
<ResourceLoader
> protector(this);
196 ASSERT(!m_reachedTerminalState
);
198 if (m_sendResourceLoadCallbacks
) {
200 m_identifier
= m_frame
->page()->progress()->createUniqueIdentifier();
201 frameLoader()->assignIdentifierToInitialRequest(m_identifier
, request
);
204 frameLoader()->willSendRequest(this, request
, redirectResponse
);
210 void ResourceLoader::didReceiveResponse(const ResourceResponse
& r
)
212 ASSERT(!m_reachedTerminalState
);
214 // Protect this in this delegate method since the additional processing can do
215 // anything including possibly derefing this; one example of this is Radar 3266216.
216 RefPtr
<ResourceLoader
> protector(this);
220 if (m_sendResourceLoadCallbacks
)
221 frameLoader()->didReceiveResponse(this, m_response
);
224 void ResourceLoader::didReceiveData(const char* data
, int length
, long long lengthReceived
, bool allAtOnce
)
226 // The following assertions are not quite valid here, since a subclass
227 // might override didReceiveData in a way that invalidates them. This
228 // happens with the steps listed in 3266216
229 // ASSERT(con == connection);
230 // ASSERT(!m_reachedTerminalState);
232 // Protect this in this delegate method since the additional processing can do
233 // anything including possibly derefing this; one example of this is Radar 3266216.
234 RefPtr
<ResourceLoader
> protector(this);
236 addData(data
, length
, allAtOnce
);
237 // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
238 // However, with today's computers and networking speeds, this won't happen in practice.
239 // Could be an issue with a giant local file.
240 if (m_sendResourceLoadCallbacks
&& m_frame
)
241 frameLoader()->didReceiveData(this, data
, length
, static_cast<int>(lengthReceived
));
244 void ResourceLoader::willStopBufferingData(const char* data
, int length
)
246 if (!m_shouldBufferData
)
249 ASSERT(!m_resourceData
);
250 m_resourceData
= new SharedBuffer(data
, length
);
253 void ResourceLoader::didFinishLoading()
255 // If load has been cancelled after finishing (which could happen with a
256 // JavaScript that changes the window location), do nothing.
259 ASSERT(!m_reachedTerminalState
);
261 didFinishLoadingOnePart();
265 void ResourceLoader::didFinishLoadingOnePart()
269 ASSERT(!m_reachedTerminalState
);
271 if (m_calledDidFinishLoad
)
273 m_calledDidFinishLoad
= true;
274 if (m_sendResourceLoadCallbacks
)
275 frameLoader()->didFinishLoad(this);
278 void ResourceLoader::didFail(const ResourceError
& error
)
282 ASSERT(!m_reachedTerminalState
);
284 // Protect this in this delegate method since the additional processing can do
285 // anything including possibly derefing this; one example of this is Radar 3266216.
286 RefPtr
<ResourceLoader
> protector(this);
288 if (m_sendResourceLoadCallbacks
&& !m_calledDidFinishLoad
)
289 frameLoader()->didFailToLoad(this, error
);
294 void ResourceLoader::wasBlocked()
296 didFail(blockedError());
299 void ResourceLoader::didCancel(const ResourceError
& error
)
301 ASSERT(!m_cancelled
);
302 ASSERT(!m_reachedTerminalState
);
304 // This flag prevents bad behavior when loads that finish cause the
305 // load itself to be cancelled (which could happen with a javascript that
306 // changes the window location). This is used to prevent both the body
307 // of this method and the body of connectionDidFinishLoading: running
308 // for a single delegate. Cancelling wins.
312 m_handle
->clearAuthentication();
314 frameLoader()->cancelPendingArchiveLoad(this);
319 if (m_sendResourceLoadCallbacks
&& !m_calledDidFinishLoad
)
320 frameLoader()->didFailToLoad(this, error
);
325 void ResourceLoader::cancel()
327 cancel(ResourceError());
330 void ResourceLoader::cancel(const ResourceError
& error
)
332 if (m_reachedTerminalState
)
337 didCancel(cancelledError());
340 const ResourceResponse
& ResourceLoader::response() const
345 ResourceError
ResourceLoader::cancelledError()
347 return frameLoader()->cancelledError(m_request
);
350 ResourceError
ResourceLoader::blockedError()
352 return frameLoader()->blockedError(m_request
);
355 void ResourceLoader::willSendRequest(ResourceHandle
*, ResourceRequest
& request
, const ResourceResponse
& redirectResponse
)
357 willSendRequest(request
, redirectResponse
);
360 void ResourceLoader::didReceiveResponse(ResourceHandle
*, const ResourceResponse
& response
)
362 didReceiveResponse(response
);
365 void ResourceLoader::didReceiveData(ResourceHandle
*, const char* data
, int length
, int lengthReceived
)
367 didReceiveData(data
, length
, lengthReceived
, false);
370 void ResourceLoader::didFinishLoading(ResourceHandle
*)
375 void ResourceLoader::didFail(ResourceHandle
*, const ResourceError
& error
)
380 void ResourceLoader::wasBlocked(ResourceHandle
*)
385 void ResourceLoader::didReceiveAuthenticationChallenge(const AuthenticationChallenge
& challenge
)
387 // Protect this in this delegate method since the additional processing can do
388 // anything including possibly derefing this; one example of this is Radar 3266216.
389 RefPtr
<ResourceLoader
> protector(this);
390 frameLoader()->didReceiveAuthenticationChallenge(this, challenge
);
393 void ResourceLoader::didCancelAuthenticationChallenge(const AuthenticationChallenge
& challenge
)
395 // Protect this in this delegate method since the additional processing can do
396 // anything including possibly derefing this; one example of this is Radar 3266216.
397 RefPtr
<ResourceLoader
> protector(this);
398 frameLoader()->didCancelAuthenticationChallenge(this, challenge
);
401 void ResourceLoader::receivedCancellation(const AuthenticationChallenge
&)
406 void ResourceLoader::willCacheResponse(ResourceHandle
*, CacheStoragePolicy
& policy
)
408 // When in private browsing mode, prevent caching to disk
409 if (policy
== StorageAllowed
&& m_frame
->settings()->privateBrowsingEnabled())
410 policy
= StorageAllowedInMemoryOnly
;