WebCore/loader/SubresourceLoader.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions
       
     6  * are met:
       
     7  *
       
     8  * 1.  Redistributions of source code must retain the above copyright
       
     9  *     notice, this list of conditions and the following disclaimer. 
       
    10  * 2.  Redistributions in binary form must reproduce the above copyright
       
    11  *     notice, this list of conditions and the following disclaimer in the
       
    12  *     documentation and/or other materials provided with the distribution. 
       
    13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
       
    14  *     its contributors may be used to endorse or promote products derived
       
    15  *     from this software without specific prior written permission. 
       
    16  *
       
    17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
       
    18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
    19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
       
    20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
       
    21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
       
    22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
       
    23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
       
    24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
       
    26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    27  */
       
    28 
       
    29 #include "config.h"
       
    30 #include "SubresourceLoader.h"
       
    31 
       
    32 #include "DocumentLoader.h"
       
    33 #include "Frame.h"
       
    34 #include "FrameLoader.h"
       
    35 #include "ResourceHandle.h"
       
    36 #include "SecurityOrigin.h"
       
    37 #include "SubresourceLoaderClient.h"
       
    38 #include <wtf/RefCountedLeakCounter.h>
       
    39 
       
    40 namespace WebCore {
       
    41 
       
    42 #ifndef NDEBUG    
       
    43 static WTF::RefCountedLeakCounter subresourceLoaderCounter("SubresourceLoader");
       
    44 #endif
       
    45 
       
    46 SubresourceLoader::SubresourceLoader(Frame* frame, SubresourceLoaderClient* client, bool sendResourceLoadCallbacks, bool shouldContentSniff)
       
    47     : ResourceLoader(frame, sendResourceLoadCallbacks, shouldContentSniff)
       
    48     , m_client(client)
       
    49     , m_loadingMultipartContent(false)
       
    50 {
       
    51 #ifndef NDEBUG
       
    52     subresourceLoaderCounter.increment();
       
    53 #endif
       
    54 }
       
    55 
       
    56 SubresourceLoader::~SubresourceLoader()
       
    57 {
       
    58 #ifndef NDEBUG
       
    59     subresourceLoaderCounter.decrement();
       
    60 #endif
       
    61 }
       
    62 
       
    63 PassRefPtr<SubresourceLoader> SubresourceLoader::create(Frame* frame, SubresourceLoaderClient* client, const ResourceRequest& request, SecurityCheckPolicy securityCheck, bool sendResourceLoadCallbacks, bool shouldContentSniff)
       
    64 {
       
    65     if (!frame)
       
    66         return 0;
       
    67 
       
    68     FrameLoader* fl = frame->loader();
       
    69     if (securityCheck == DoSecurityCheck && (fl->state() == FrameStateProvisional || !fl->activeDocumentLoader() || fl->activeDocumentLoader()->isStopping()))
       
    70         return 0;
       
    71 
       
    72     ResourceRequest newRequest = request;
       
    73 
       
    74     if (securityCheck == DoSecurityCheck
       
    75             && SecurityOrigin::restrictAccessToLocal()
       
    76             && !SecurityOrigin::canLoad(request.url(), String(), frame->document())) {
       
    77         FrameLoader::reportLocalLoadFailed(frame, request.url().string());
       
    78         return 0;
       
    79     }
       
    80     
       
    81     if (SecurityOrigin::shouldHideReferrer(request.url(), fl->outgoingReferrer()))
       
    82         newRequest.clearHTTPReferrer();
       
    83     else if (!request.httpReferrer())
       
    84         newRequest.setHTTPReferrer(fl->outgoingReferrer());
       
    85     FrameLoader::addHTTPOriginIfNeeded(newRequest, fl->outgoingOrigin());
       
    86 
       
    87     fl->addExtraFieldsToSubresourceRequest(newRequest);
       
    88 
       
    89     RefPtr<SubresourceLoader> subloader(adoptRef(new SubresourceLoader(frame, client, sendResourceLoadCallbacks, shouldContentSniff)));
       
    90     subloader->documentLoader()->addSubresourceLoader(subloader.get());
       
    91     if (!subloader->load(newRequest))
       
    92         return 0;
       
    93 
       
    94     return subloader.release();
       
    95 }
       
    96 
       
    97 void SubresourceLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
       
    98 {
       
    99     // Store the previous URL because the call to ResourceLoader::willSendRequest will modify it.
       
   100     KURL previousURL = request().url();
       
   101     
       
   102     ResourceLoader::willSendRequest(newRequest, redirectResponse);
       
   103     if (!previousURL.isNull() && !newRequest.isNull() && previousURL != newRequest.url() && m_client)
       
   104         m_client->willSendRequest(this, newRequest, redirectResponse);
       
   105 }
       
   106 
       
   107 void SubresourceLoader::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
       
   108 {
       
   109     RefPtr<SubresourceLoader> protect(this);
       
   110 
       
   111     if (m_client)
       
   112         m_client->didSendData(this, bytesSent, totalBytesToBeSent);
       
   113 }
       
   114 
       
   115 void SubresourceLoader::didReceiveResponse(const ResourceResponse& r)
       
   116 {
       
   117     ASSERT(!r.isNull());
       
   118 
       
   119     if (r.isMultipart())
       
   120         m_loadingMultipartContent = true;
       
   121 
       
   122     // Reference the object in this method since the additional processing can do
       
   123     // anything including removing the last reference to this object; one example of this is 3266216.
       
   124     RefPtr<SubresourceLoader> protect(this);
       
   125 
       
   126     if (m_client)
       
   127         m_client->didReceiveResponse(this, r);
       
   128     
       
   129     // The loader can cancel a load if it receives a multipart response for a non-image
       
   130     if (reachedTerminalState())
       
   131         return;
       
   132     ResourceLoader::didReceiveResponse(r);
       
   133     
       
   134     RefPtr<SharedBuffer> buffer = resourceData();
       
   135     if (m_loadingMultipartContent && buffer && buffer->size()) {
       
   136         // Since a subresource loader does not load multipart sections progressively,
       
   137         // deliver the previously received data to the loader all at once now.
       
   138         // Then clear the data to make way for the next multipart section.
       
   139         if (m_client)
       
   140             m_client->didReceiveData(this, buffer->data(), buffer->size());
       
   141         clearResourceData();
       
   142         
       
   143         // After the first multipart section is complete, signal to delegates that this load is "finished" 
       
   144         m_documentLoader->subresourceLoaderFinishedLoadingOnePart(this);
       
   145         didFinishLoadingOnePart();
       
   146     }
       
   147 }
       
   148 
       
   149 void SubresourceLoader::didReceiveData(const char* data, int length, long long lengthReceived, bool allAtOnce)
       
   150 {
       
   151     // Reference the object in this method since the additional processing can do
       
   152     // anything including removing the last reference to this object; one example of this is 3266216.
       
   153     RefPtr<SubresourceLoader> protect(this);
       
   154     
       
   155     ResourceLoader::didReceiveData(data, length, lengthReceived, allAtOnce);
       
   156 
       
   157     // A subresource loader does not load multipart sections progressively.
       
   158     // So don't deliver any data to the loader yet.
       
   159     if (!m_loadingMultipartContent && m_client)
       
   160         m_client->didReceiveData(this, data, length);
       
   161 }
       
   162 
       
   163 void SubresourceLoader::didReceiveCachedMetadata(const char* data, int length)
       
   164 {
       
   165     // Reference the object in this method since the additional processing can do
       
   166     // anything including removing the last reference to this object; one example of this is 3266216.
       
   167     RefPtr<SubresourceLoader> protect(this);
       
   168     
       
   169     if (m_client)
       
   170         m_client->didReceiveCachedMetadata(this, data, length);
       
   171 }
       
   172 
       
   173 void SubresourceLoader::didFinishLoading()
       
   174 {
       
   175     if (cancelled())
       
   176         return;
       
   177     ASSERT(!reachedTerminalState());
       
   178 
       
   179     // Calling removeSubresourceLoader will likely result in a call to deref, so we must protect ourselves.
       
   180     RefPtr<SubresourceLoader> protect(this);
       
   181 
       
   182     if (m_client)
       
   183         m_client->didFinishLoading(this);
       
   184     
       
   185     m_handle = 0;
       
   186 
       
   187     if (cancelled())
       
   188         return;
       
   189     m_documentLoader->removeSubresourceLoader(this);
       
   190     ResourceLoader::didFinishLoading();
       
   191 }
       
   192 
       
   193 void SubresourceLoader::didFail(const ResourceError& error)
       
   194 {
       
   195     if (cancelled())
       
   196         return;
       
   197     ASSERT(!reachedTerminalState());
       
   198 
       
   199     // Calling removeSubresourceLoader will likely result in a call to deref, so we must protect ourselves.
       
   200     RefPtr<SubresourceLoader> protect(this);
       
   201 
       
   202     if (m_client)
       
   203         m_client->didFail(this, error);
       
   204     
       
   205     m_handle = 0;
       
   206     
       
   207     if (cancelled())
       
   208         return;
       
   209     m_documentLoader->removeSubresourceLoader(this);
       
   210     ResourceLoader::didFail(error);
       
   211 }
       
   212 
       
   213 void SubresourceLoader::didCancel(const ResourceError& error)
       
   214 {
       
   215     ASSERT(!reachedTerminalState());
       
   216 
       
   217     // Calling removeSubresourceLoader will likely result in a call to deref, so we must protect ourselves.
       
   218     RefPtr<SubresourceLoader> protect(this);
       
   219 
       
   220     if (m_client)
       
   221         m_client->didFail(this, error);
       
   222     
       
   223     if (cancelled())
       
   224         return;
       
   225     
       
   226     // The only way the subresource loader can reach the terminal state here is if the run loop spins when calling
       
   227     // m_client->didFail. This should in theory not happen which is why the assert is here. 
       
   228     ASSERT(!reachedTerminalState());
       
   229     if (reachedTerminalState())
       
   230         return;
       
   231     
       
   232     m_documentLoader->removeSubresourceLoader(this);
       
   233     ResourceLoader::didCancel(error);
       
   234 }
       
   235 
       
   236 bool SubresourceLoader::shouldUseCredentialStorage()
       
   237 {
       
   238     RefPtr<SubresourceLoader> protect(this);
       
   239 
       
   240     bool shouldUse;
       
   241     if (m_client && m_client->getShouldUseCredentialStorage(this, shouldUse))
       
   242         return shouldUse;
       
   243 
       
   244     return ResourceLoader::shouldUseCredentialStorage();
       
   245 }
       
   246 
       
   247 void SubresourceLoader::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge)
       
   248 {
       
   249     RefPtr<SubresourceLoader> protect(this);
       
   250 
       
   251     ASSERT(handle()->hasAuthenticationChallenge());
       
   252 
       
   253     if (m_client)
       
   254         m_client->didReceiveAuthenticationChallenge(this, challenge);
       
   255     
       
   256     // The SubResourceLoaderClient may have cancelled this ResourceLoader in response to the challenge.  
       
   257     // If that's the case, don't call didReceiveAuthenticationChallenge.
       
   258     if (reachedTerminalState())
       
   259         return;
       
   260 
       
   261     // It may have also handled authentication on its own.
       
   262     if (!handle()->hasAuthenticationChallenge())
       
   263         return;
       
   264 
       
   265     ResourceLoader::didReceiveAuthenticationChallenge(challenge);
       
   266 }
       
   267 
       
   268 void SubresourceLoader::receivedCancellation(const AuthenticationChallenge& challenge)
       
   269 {
       
   270     ASSERT(!reachedTerminalState());
       
   271         
       
   272     RefPtr<SubresourceLoader> protect(this);
       
   273 
       
   274     if (m_client)
       
   275         m_client->receivedCancellation(this, challenge);
       
   276     
       
   277     ResourceLoader::receivedCancellation(challenge);
       
   278 }
       
   279     
       
   280 
       
   281 }