webengine/osswebengine/WebCore/loader/SubresourceLoader.cpp
changeset 0 dd21522fd290
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2  * Copyright (C) 2006, 2007 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 "Document.h"
       
    33 #include "DocumentLoader.h"
       
    34 #include "Frame.h"
       
    35 #include "FrameLoader.h"
       
    36 #include "Logging.h"
       
    37 #include "ResourceHandle.h"
       
    38 #include "ResourceRequest.h"
       
    39 #include "SubresourceLoaderClient.h"
       
    40 #include "SharedBuffer.h"
       
    41 
       
    42 namespace WebCore {
       
    43 
       
    44 #ifndef NDEBUG
       
    45 WTFLogChannel LogWebCoreSubresourceLoaderLeaks =  { 0x00000000, "", WTFLogChannelOn };
       
    46 
       
    47 struct SubresourceLoaderCounter {
       
    48     static unsigned count; 
       
    49 
       
    50     ~SubresourceLoaderCounter() 
       
    51     { 
       
    52         if (count) 
       
    53             LOG(WebCoreSubresourceLoaderLeaks, "LEAK: %u SubresourceLoader\n", count); 
       
    54     }
       
    55 };
       
    56 unsigned SubresourceLoaderCounter::count = 0;
       
    57 static SubresourceLoaderCounter subresourceLoaderCounter;
       
    58 #endif
       
    59 
       
    60 SubresourceLoader::SubresourceLoader(Frame* frame, SubresourceLoaderClient* client, bool sendResourceLoadCallbacks, bool shouldContentSniff)
       
    61     : ResourceLoader(frame, sendResourceLoadCallbacks, shouldContentSniff)
       
    62     , m_client(client)
       
    63     , m_loadingMultipartContent(false)
       
    64 {
       
    65 #ifndef NDEBUG
       
    66     ++SubresourceLoaderCounter::count;
       
    67 #endif
       
    68     m_documentLoader->addSubresourceLoader(this);
       
    69 }
       
    70 
       
    71 SubresourceLoader::~SubresourceLoader()
       
    72 {
       
    73 #ifndef NDEBUG
       
    74     --SubresourceLoaderCounter::count;
       
    75 #endif
       
    76 }
       
    77 
       
    78 bool SubresourceLoader::load(const ResourceRequest& r)
       
    79 {
       
    80     m_frame->loader()->didTellBridgeAboutLoad(r.url().url());
       
    81     
       
    82     return ResourceLoader::load(r);
       
    83 }
       
    84 
       
    85 PassRefPtr<SubresourceLoader> SubresourceLoader::create(Frame* frame, SubresourceLoaderClient* client, const ResourceRequest& request, bool skipCanLoadCheck, bool sendResourceLoadCallbacks, bool shouldContentSniff)
       
    86 {
       
    87     if (!frame)
       
    88         return 0;
       
    89 
       
    90     FrameLoader* fl = frame->loader();
       
    91     if (!skipCanLoadCheck && fl->state() == FrameStateProvisional)
       
    92         return 0;
       
    93 
       
    94     ResourceRequest newRequest = request;
       
    95 
       
    96     if (!skipCanLoadCheck
       
    97             && FrameLoader::restrictAccessToLocal()
       
    98             && !FrameLoader::canLoad(request.url(), frame->document())) {
       
    99         FrameLoader::reportLocalLoadFailed(frame->page(), request.url().url());
       
   100         return 0;
       
   101     }
       
   102     
       
   103     if (FrameLoader::shouldHideReferrer(request.url(), fl->outgoingReferrer()))
       
   104         newRequest.clearHTTPReferrer();
       
   105     else if (!request.httpReferrer())
       
   106         newRequest.setHTTPReferrer(fl->outgoingReferrer());
       
   107 
       
   108     // Use the original request's cache policy for two reasons:
       
   109     // 1. For POST requests, we mutate the cache policy for the main resource,
       
   110     //    but we do not want this to apply to subresources
       
   111     // 2. Delegates that modify the cache policy using willSendRequest: should
       
   112     //    not affect any other resources. Such changes need to be done
       
   113     //    per request.
       
   114     if (newRequest.isConditional())
       
   115         newRequest.setCachePolicy(ReloadIgnoringCacheData);
       
   116     else
       
   117         newRequest.setCachePolicy(fl->originalRequest().cachePolicy());
       
   118 
       
   119     fl->addExtraFieldsToRequest(newRequest, false, false);
       
   120 
       
   121     RefPtr<SubresourceLoader> subloader(new SubresourceLoader(frame, client, sendResourceLoadCallbacks, shouldContentSniff));
       
   122     if (!subloader->load(newRequest))
       
   123         return 0;
       
   124 
       
   125     return subloader.release();
       
   126 }
       
   127 
       
   128 void SubresourceLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
       
   129 {
       
   130     ResourceLoader::willSendRequest(newRequest, redirectResponse);
       
   131     if (!newRequest.isNull() && m_originalURL != newRequest.url() && m_client)
       
   132         m_client->willSendRequest(this, newRequest, redirectResponse);
       
   133 }
       
   134 
       
   135 void SubresourceLoader::didReceiveResponse(const ResourceResponse& r)
       
   136 {
       
   137     ASSERT(!r.isNull());
       
   138 
       
   139     if (r.isMultipart())
       
   140         m_loadingMultipartContent = true;
       
   141 
       
   142     // Reference the object in this method since the additional processing can do
       
   143     // anything including removing the last reference to this object; one example of this is 3266216.
       
   144     RefPtr<SubresourceLoader> protect(this);
       
   145 
       
   146     if (m_client)
       
   147         m_client->didReceiveResponse(this, r);
       
   148     
       
   149     // The loader can cancel a load if it receives a multipart response for a non-image
       
   150     if (reachedTerminalState())
       
   151         return;
       
   152     ResourceLoader::didReceiveResponse(r);
       
   153     
       
   154     RefPtr<SharedBuffer> buffer = resourceData();
       
   155     if (m_loadingMultipartContent && buffer && buffer->size()) {
       
   156         // Since a subresource loader does not load multipart sections progressively,
       
   157         // deliver the previously received data to the loader all at once now.
       
   158         // Then clear the data to make way for the next multipart section.
       
   159         if (m_client)
       
   160             m_client->didReceiveData(this, buffer->data(), buffer->size());
       
   161         clearResourceData();
       
   162         
       
   163         // After the first multipart section is complete, signal to delegates that this load is "finished" 
       
   164         m_documentLoader->subresourceLoaderFinishedLoadingOnePart(this);
       
   165         didFinishLoadingOnePart();
       
   166     }
       
   167 }
       
   168 
       
   169 void SubresourceLoader::didReceiveData(const char* data, int length, long long lengthReceived, bool allAtOnce)
       
   170 {
       
   171     // Reference the object in this method since the additional processing can do
       
   172     // anything including removing the last reference to this object; one example of this is 3266216.
       
   173     RefPtr<SubresourceLoader> protect(this);
       
   174     
       
   175     ResourceLoader::didReceiveData(data, length, lengthReceived, allAtOnce);
       
   176 
       
   177     // A subresource loader does not load multipart sections progressively.
       
   178     // So don't deliver any data to the loader yet.
       
   179     if (!m_loadingMultipartContent && m_client)
       
   180         m_client->didReceiveData(this, data, length);
       
   181 }
       
   182 
       
   183 void SubresourceLoader::didFinishLoading()
       
   184 {
       
   185     if (cancelled())
       
   186         return;
       
   187     ASSERT(!reachedTerminalState());
       
   188 
       
   189     // Calling removeSubresourceLoader will likely result in a call to deref, so we must protect ourselves.
       
   190     RefPtr<SubresourceLoader> protect(this);
       
   191 
       
   192     if (m_client)
       
   193         m_client->didFinishLoading(this);
       
   194     
       
   195     m_handle = 0;
       
   196 
       
   197     if (cancelled())
       
   198         return;
       
   199     m_documentLoader->removeSubresourceLoader(this);
       
   200     ResourceLoader::didFinishLoading();
       
   201 }
       
   202 
       
   203 void SubresourceLoader::didFail(const ResourceError& error)
       
   204 {
       
   205     if (cancelled())
       
   206         return;
       
   207     ASSERT(!reachedTerminalState());
       
   208 
       
   209     // Calling removeSubresourceLoader will likely result in a call to deref, so we must protect ourselves.
       
   210     RefPtr<SubresourceLoader> protect(this);
       
   211 
       
   212     if (m_client)
       
   213         m_client->didFail(this, error);
       
   214     
       
   215     m_handle = 0;
       
   216     
       
   217     if (cancelled())
       
   218         return;
       
   219     m_documentLoader->removeSubresourceLoader(this);
       
   220     ResourceLoader::didFail(error);
       
   221 }
       
   222 
       
   223 void SubresourceLoader::didCancel(const ResourceError& error)
       
   224 {
       
   225     ASSERT(!reachedTerminalState());
       
   226 
       
   227     // Calling removeSubresourceLoader will likely result in a call to deref, so we must protect ourselves.
       
   228     RefPtr<SubresourceLoader> protect(this);
       
   229 
       
   230     if (m_client)
       
   231         m_client->didFail(this, error);
       
   232     
       
   233     if (cancelled())
       
   234         return;
       
   235     m_documentLoader->removeSubresourceLoader(this);
       
   236     ResourceLoader::didCancel(error);
       
   237 }
       
   238 
       
   239 void SubresourceLoader::receivedCancellation(const AuthenticationChallenge& challenge)
       
   240 {
       
   241     ASSERT(!reachedTerminalState());
       
   242         
       
   243     RefPtr<SubresourceLoader> protect(this);
       
   244 
       
   245     if (m_client)
       
   246         m_client->receivedCancellation(this, challenge);
       
   247     
       
   248     ResourceLoader::receivedCancellation(challenge);
       
   249 }
       
   250     
       
   251 
       
   252 }