Home | History | Annotate | Download | only in loader
      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