1 /* 2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. 3 * (C) 2007 Graham Dennis (graham.dennis (at) 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 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 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 71 ResourceLoader::~ResourceLoader() 72 { 73 ASSERT(m_reachedTerminalState); 74 } 75 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, unless it has been replaced by someone else. 98 if (m_handle->client() == this) 99 m_handle->setClient(0); 100 m_handle = 0; 101 } 102 103 m_resourceData = 0; 104 m_deferredRequest = ResourceRequest(); 105 } 106 107 bool ResourceLoader::load(const ResourceRequest& r) 108 { 109 ASSERT(!m_handle); 110 ASSERT(m_deferredRequest.isNull()); 111 ASSERT(!m_documentLoader->isSubstituteLoadPending(this)); 112 113 ResourceRequest clientRequest(r); 114 willSendRequest(clientRequest, ResourceResponse()); 115 if (clientRequest.isNull()) { 116 didFail(frameLoader()->cancelledError(r)); 117 return false; 118 } 119 120 #if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size 121 if (m_documentLoader->scheduleArchiveLoad(this, clientRequest, r.url())) 122 return true; 123 #endif 124 125 #if ENABLE(OFFLINE_WEB_APPLICATIONS) 126 if (m_documentLoader->applicationCacheHost()->maybeLoadResource(this, clientRequest, r.url())) 127 return true; 128 #endif 129 130 if (m_defersLoading) { 131 m_deferredRequest = clientRequest; 132 return true; 133 } 134 135 m_handle = ResourceHandle::create(clientRequest, this, m_frame.get(), m_defersLoading, m_shouldContentSniff, true); 136 137 return true; 138 } 139 140 void ResourceLoader::setDefersLoading(bool defers) 141 { 142 m_defersLoading = defers; 143 if (m_handle) 144 m_handle->setDefersLoading(defers); 145 if (!defers && !m_deferredRequest.isNull()) { 146 ResourceRequest request(m_deferredRequest); 147 m_deferredRequest = ResourceRequest(); 148 load(request); 149 } 150 } 151 152 #if PLATFORM(ANDROID) 153 // TODO: This needs upstreaming to WebKit. 154 void ResourceLoader::pauseLoad(bool pause) 155 { 156 if (m_handle) 157 m_handle->pauseLoad(pause); 158 } 159 #endif 160 161 FrameLoader* ResourceLoader::frameLoader() const 162 { 163 if (!m_frame) 164 return 0; 165 return m_frame->loader(); 166 } 167 168 void ResourceLoader::setShouldBufferData(bool shouldBufferData) 169 { 170 m_shouldBufferData = shouldBufferData; 171 172 // Reset any already buffered data 173 if (!m_shouldBufferData) 174 m_resourceData = 0; 175 } 176 177 178 void ResourceLoader::addData(const char* data, int length, bool allAtOnce) 179 { 180 if (!m_shouldBufferData) 181 return; 182 183 if (allAtOnce) { 184 m_resourceData = SharedBuffer::create(data, length); 185 return; 186 } 187 188 if (ResourceHandle::supportsBufferedData()) { 189 // Buffer data only if the connection has handed us the data because is has stopped buffering it. 190 if (m_resourceData) 191 m_resourceData->append(data, length); 192 } else { 193 if (!m_resourceData) 194 m_resourceData = SharedBuffer::create(data, length); 195 else 196 m_resourceData->append(data, length); 197 } 198 } 199 200 void ResourceLoader::clearResourceData() 201 { 202 if (m_resourceData) 203 m_resourceData->clear(); 204 } 205 206 void ResourceLoader::willSendRequest(ResourceRequest& request, const ResourceResponse& redirectResponse) 207 { 208 // Protect this in this delegate method since the additional processing can do 209 // anything including possibly derefing this; one example of this is Radar 3266216. 210 RefPtr<ResourceLoader> protector(this); 211 212 ASSERT(!m_reachedTerminalState); 213 214 if (m_sendResourceLoadCallbacks) { 215 if (!m_identifier) { 216 m_identifier = m_frame->page()->progress()->createUniqueIdentifier(); 217 frameLoader()->notifier()->assignIdentifierToInitialRequest(m_identifier, documentLoader(), request); 218 } 219 220 frameLoader()->notifier()->willSendRequest(this, request, redirectResponse); 221 } 222 223 m_request = request; 224 } 225 226 void ResourceLoader::didSendData(unsigned long long, unsigned long long) 227 { 228 } 229 230 void ResourceLoader::didReceiveResponse(const ResourceResponse& r) 231 { 232 ASSERT(!m_reachedTerminalState); 233 234 // Protect this in this delegate method since the additional processing can do 235 // anything including possibly derefing this; one example of this is Radar 3266216. 236 RefPtr<ResourceLoader> protector(this); 237 238 m_response = r; 239 240 if (FormData* data = m_request.httpBody()) 241 data->removeGeneratedFilesIfNeeded(); 242 243 if (m_sendResourceLoadCallbacks) 244 frameLoader()->notifier()->didReceiveResponse(this, m_response); 245 } 246 247 void ResourceLoader::didReceiveData(const char* data, int length, long long lengthReceived, bool allAtOnce) 248 { 249 // The following assertions are not quite valid here, since a subclass 250 // might override didReceiveData in a way that invalidates them. This 251 // happens with the steps listed in 3266216 252 // ASSERT(con == connection); 253 // ASSERT(!m_reachedTerminalState); 254 255 // Protect this in this delegate method since the additional processing can do 256 // anything including possibly derefing this; one example of this is Radar 3266216. 257 RefPtr<ResourceLoader> protector(this); 258 259 addData(data, length, allAtOnce); 260 // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing. 261 // However, with today's computers and networking speeds, this won't happen in practice. 262 // Could be an issue with a giant local file. 263 if (m_sendResourceLoadCallbacks && m_frame) 264 frameLoader()->notifier()->didReceiveData(this, data, length, static_cast<int>(lengthReceived)); 265 } 266 267 void ResourceLoader::willStopBufferingData(const char* data, int length) 268 { 269 if (!m_shouldBufferData) 270 return; 271 272 ASSERT(!m_resourceData); 273 m_resourceData = SharedBuffer::create(data, length); 274 } 275 276 void ResourceLoader::didFinishLoading() 277 { 278 // If load has been cancelled after finishing (which could happen with a 279 // JavaScript that changes the window location), do nothing. 280 if (m_cancelled) 281 return; 282 ASSERT(!m_reachedTerminalState); 283 284 didFinishLoadingOnePart(); 285 releaseResources(); 286 } 287 288 void ResourceLoader::didFinishLoadingOnePart() 289 { 290 if (m_cancelled) 291 return; 292 ASSERT(!m_reachedTerminalState); 293 294 if (m_calledDidFinishLoad) 295 return; 296 m_calledDidFinishLoad = true; 297 if (m_sendResourceLoadCallbacks) 298 frameLoader()->notifier()->didFinishLoad(this); 299 } 300 301 void ResourceLoader::didFail(const ResourceError& error) 302 { 303 if (m_cancelled) 304 return; 305 ASSERT(!m_reachedTerminalState); 306 307 // Protect this in this delegate method since the additional processing can do 308 // anything including possibly derefing this; one example of this is Radar 3266216. 309 RefPtr<ResourceLoader> protector(this); 310 311 if (FormData* data = m_request.httpBody()) 312 data->removeGeneratedFilesIfNeeded(); 313 314 if (m_sendResourceLoadCallbacks && !m_calledDidFinishLoad) 315 frameLoader()->notifier()->didFailToLoad(this, error); 316 317 releaseResources(); 318 } 319 320 void ResourceLoader::didCancel(const ResourceError& error) 321 { 322 ASSERT(!m_cancelled); 323 ASSERT(!m_reachedTerminalState); 324 325 if (FormData* data = m_request.httpBody()) 326 data->removeGeneratedFilesIfNeeded(); 327 328 // This flag prevents bad behavior when loads that finish cause the 329 // load itself to be cancelled (which could happen with a javascript that 330 // changes the window location). This is used to prevent both the body 331 // of this method and the body of connectionDidFinishLoading: running 332 // for a single delegate. Canceling wins. 333 m_cancelled = true; 334 335 if (m_handle) 336 m_handle->clearAuthentication(); 337 338 m_documentLoader->cancelPendingSubstituteLoad(this); 339 if (m_handle) { 340 m_handle->cancel(); 341 m_handle = 0; 342 } 343 if (m_sendResourceLoadCallbacks && !m_calledDidFinishLoad) 344 frameLoader()->notifier()->didFailToLoad(this, error); 345 346 releaseResources(); 347 } 348 349 void ResourceLoader::cancel() 350 { 351 cancel(ResourceError()); 352 } 353 354 void ResourceLoader::cancel(const ResourceError& error) 355 { 356 if (m_reachedTerminalState) 357 return; 358 if (!error.isNull()) 359 didCancel(error); 360 else 361 didCancel(cancelledError()); 362 } 363 364 const ResourceResponse& ResourceLoader::response() const 365 { 366 return m_response; 367 } 368 369 ResourceError ResourceLoader::cancelledError() 370 { 371 return frameLoader()->cancelledError(m_request); 372 } 373 374 ResourceError ResourceLoader::blockedError() 375 { 376 return frameLoader()->blockedError(m_request); 377 } 378 379 ResourceError ResourceLoader::cannotShowURLError() 380 { 381 return frameLoader()->cannotShowURLError(m_request); 382 } 383 384 void ResourceLoader::willSendRequest(ResourceHandle*, ResourceRequest& request, const ResourceResponse& redirectResponse) 385 { 386 #if ENABLE(OFFLINE_WEB_APPLICATIONS) 387 if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForRedirect(this, request, redirectResponse)) 388 return; 389 #endif 390 willSendRequest(request, redirectResponse); 391 } 392 393 void ResourceLoader::didSendData(ResourceHandle*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) 394 { 395 didSendData(bytesSent, totalBytesToBeSent); 396 } 397 398 void ResourceLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response) 399 { 400 #if ENABLE(OFFLINE_WEB_APPLICATIONS) 401 if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForResponse(this, response)) 402 return; 403 #endif 404 didReceiveResponse(response); 405 } 406 407 void ResourceLoader::didReceiveData(ResourceHandle*, const char* data, int length, int lengthReceived) 408 { 409 didReceiveData(data, length, lengthReceived, false); 410 } 411 412 void ResourceLoader::didFinishLoading(ResourceHandle*) 413 { 414 didFinishLoading(); 415 } 416 417 void ResourceLoader::didFail(ResourceHandle*, const ResourceError& error) 418 { 419 #if ENABLE(OFFLINE_WEB_APPLICATIONS) 420 if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForError(this, error)) 421 return; 422 #endif 423 didFail(error); 424 } 425 426 void ResourceLoader::wasBlocked(ResourceHandle*) 427 { 428 didFail(blockedError()); 429 } 430 431 void ResourceLoader::cannotShowURL(ResourceHandle*) 432 { 433 didFail(cannotShowURLError()); 434 } 435 436 bool ResourceLoader::shouldUseCredentialStorage() 437 { 438 RefPtr<ResourceLoader> protector(this); 439 return frameLoader()->shouldUseCredentialStorage(this); 440 } 441 442 void ResourceLoader::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge) 443 { 444 // Protect this in this delegate method since the additional processing can do 445 // anything including possibly derefing this; one example of this is Radar 3266216. 446 RefPtr<ResourceLoader> protector(this); 447 frameLoader()->notifier()->didReceiveAuthenticationChallenge(this, challenge); 448 } 449 450 void ResourceLoader::didCancelAuthenticationChallenge(const AuthenticationChallenge& challenge) 451 { 452 // Protect this in this delegate method since the additional processing can do 453 // anything including possibly derefing this; one example of this is Radar 3266216. 454 RefPtr<ResourceLoader> protector(this); 455 frameLoader()->notifier()->didCancelAuthenticationChallenge(this, challenge); 456 } 457 458 void ResourceLoader::receivedCancellation(const AuthenticationChallenge&) 459 { 460 cancel(); 461 } 462 463 void ResourceLoader::willCacheResponse(ResourceHandle*, CacheStoragePolicy& policy) 464 { 465 // When in private browsing mode, prevent caching to disk 466 if (policy == StorageAllowed && m_frame->settings()->privateBrowsingEnabled()) 467 policy = StorageAllowedInMemoryOnly; 468 } 469 470 } 471