WebCore/loader/icon/IconLoader.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2006 Apple Computer, 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  * 1. Redistributions of source code must retain the above copyright
       
     8  *    notice, this list of conditions and the following disclaimer.
       
     9  * 2. Redistributions in binary form must reproduce the above copyright
       
    10  *    notice, this list of conditions and the following disclaimer in the
       
    11  *    documentation and/or other materials provided with the distribution.
       
    12  *
       
    13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
       
    14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       
    16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
       
    17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
       
    18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
       
    19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
       
    20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
       
    21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
       
    24  */
       
    25  
       
    26 #include "config.h"
       
    27 #include "IconLoader.h"
       
    28 
       
    29 #include "Document.h"
       
    30 #include "Frame.h"
       
    31 #include "FrameLoader.h"
       
    32 #include "FrameLoaderClient.h"
       
    33 #include "IconDatabase.h"
       
    34 #include "Logging.h"
       
    35 #include "ResourceHandle.h"
       
    36 #include "ResourceResponse.h"
       
    37 #include "ResourceRequest.h"
       
    38 #include "SharedBuffer.h"
       
    39 #include "SubresourceLoader.h"
       
    40 #include <wtf/UnusedParam.h>
       
    41 
       
    42 using namespace std;
       
    43 
       
    44 namespace WebCore {
       
    45 
       
    46 IconLoader::IconLoader(Frame* frame)
       
    47     : m_frame(frame)
       
    48     , m_loadIsInProgress(false)
       
    49 {
       
    50 }
       
    51 
       
    52 PassOwnPtr<IconLoader> IconLoader::create(Frame* frame)
       
    53 {
       
    54     return new IconLoader(frame);
       
    55 }
       
    56 
       
    57 IconLoader::~IconLoader()
       
    58 {
       
    59 }
       
    60 
       
    61 void IconLoader::startLoading()
       
    62 {    
       
    63     if (m_resourceLoader)
       
    64         return;
       
    65 
       
    66     // Set flag so we can detect the case where the load completes before
       
    67     // SubresourceLoader::create returns.
       
    68     m_loadIsInProgress = true;
       
    69 
       
    70     RefPtr<SubresourceLoader> loader = SubresourceLoader::create(m_frame, this, m_frame->loader()->iconURL());
       
    71     if (!loader)
       
    72         LOG_ERROR("Failed to start load for icon at url %s", m_frame->loader()->iconURL().string().ascii().data());
       
    73 
       
    74     // Store the handle so we can cancel the load if stopLoading is called later.
       
    75     // But only do it if the load hasn't already completed.
       
    76     if (m_loadIsInProgress)
       
    77         m_resourceLoader = loader.release();
       
    78 }
       
    79 
       
    80 void IconLoader::stopLoading()
       
    81 {
       
    82     clearLoadingState();
       
    83 }
       
    84 
       
    85 void IconLoader::didReceiveResponse(SubresourceLoader* resourceLoader, const ResourceResponse& response)
       
    86 {
       
    87     // If we got a status code indicating an invalid response, then lets
       
    88     // ignore the data and not try to decode the error page as an icon.
       
    89     int status = response.httpStatusCode();
       
    90     LOG(IconDatabase, "IconLoader::didReceiveResponse() - Loader %p, response %i", resourceLoader, status);
       
    91 
       
    92     if (status && (status < 200 || status > 299)) {
       
    93         ResourceHandle* handle = resourceLoader->handle();
       
    94         finishLoading(handle ? handle->firstRequest().url() : KURL(), 0);
       
    95     }
       
    96 }
       
    97 
       
    98 void IconLoader::didReceiveData(SubresourceLoader* unusedLoader, const char*, int unusedSize)
       
    99 {
       
   100 #if LOG_DISABLED
       
   101     UNUSED_PARAM(unusedLoader);
       
   102     UNUSED_PARAM(unusedSize);
       
   103 #endif
       
   104     LOG(IconDatabase, "IconLoader::didReceiveData() - Loader %p, number of bytes %i", unusedLoader, unusedSize);
       
   105 }
       
   106 
       
   107 void IconLoader::didFail(SubresourceLoader* resourceLoader, const ResourceError&)
       
   108 {
       
   109     LOG(IconDatabase, "IconLoader::didFail() - Loader %p", resourceLoader);
       
   110     
       
   111     // Until <rdar://problem/5463392> is resolved and we can properly cancel SubresourceLoaders when they get an error response,
       
   112     // we need to be prepared to receive this call even after we've "finished loading" once.
       
   113     // After it is resolved, we can restore an assertion that the load is in progress if ::didFail() is called
       
   114     
       
   115     if (m_loadIsInProgress) {
       
   116         ASSERT(resourceLoader == m_resourceLoader);
       
   117         ResourceHandle* handle = resourceLoader->handle();
       
   118         finishLoading(handle ? handle->firstRequest().url() : KURL(), 0);
       
   119     }
       
   120 }
       
   121 
       
   122 void IconLoader::didReceiveAuthenticationChallenge(SubresourceLoader*, const AuthenticationChallenge&)
       
   123 {
       
   124     // We don't ever want to prompt for authentication just for a site icon, so
       
   125     // implement this method to cancel the resource load
       
   126     m_resourceLoader->cancel();
       
   127 }
       
   128 
       
   129 void IconLoader::didFinishLoading(SubresourceLoader* resourceLoader)
       
   130 {
       
   131     LOG(IconDatabase, "IconLoader::didFinishLoading() - Loader %p", resourceLoader);
       
   132 
       
   133     // Until <rdar://problem/5463392> is resolved and we can properly cancel SubresourceLoaders when they get an error response,
       
   134     // we need to be prepared to receive this call even after we've "finished loading" once.
       
   135     // After it is resolved, we can restore an assertion that the load is in progress if ::didFail() is called
       
   136     
       
   137     if (m_loadIsInProgress) {
       
   138         ASSERT(resourceLoader == m_resourceLoader);
       
   139         ResourceHandle* handle = resourceLoader->handle();
       
   140         finishLoading(handle ? handle->firstRequest().url() : KURL(), m_resourceLoader->resourceData());
       
   141     }
       
   142 }
       
   143 
       
   144 void IconLoader::finishLoading(const KURL& iconURL, PassRefPtr<SharedBuffer> data)
       
   145 {
       
   146     // When an icon load results in a 404 we commit it to the database here and clear the loading state.  
       
   147     // But the SubresourceLoader continues pulling in data in the background for the 404 page if the server sends one.  
       
   148     // Once that data finishes loading or if the load is cancelled while that data is being read, finishLoading ends up being called a second time.
       
   149     // We need to change SubresourceLoader to have a mode where it will stop itself after receiving a 404 so this won't happen -
       
   150     // in the meantime, we'll only commit this data to the IconDatabase if it's the first time ::finishLoading() is called
       
   151     // <rdar://problem/5463392> tracks that enhancement
       
   152     
       
   153     if (!iconURL.isEmpty() && m_loadIsInProgress) {
       
   154         LOG(IconDatabase, "IconLoader::finishLoading() - Committing iconURL %s to database", iconURL.string().ascii().data());
       
   155         m_frame->loader()->commitIconURLToIconDatabase(iconURL);
       
   156         // Setting the icon data only after committing to the database ensures that the data is
       
   157         // kept in memory (so it does not have to be read from the database asynchronously), since
       
   158         // there is a page URL referencing it.
       
   159         iconDatabase()->setIconDataForIconURL(data, iconURL.string());
       
   160         m_frame->loader()->client()->dispatchDidReceiveIcon();
       
   161     }
       
   162 
       
   163     clearLoadingState();
       
   164 }
       
   165 
       
   166 void IconLoader::clearLoadingState()
       
   167 {
       
   168     m_resourceLoader = 0;
       
   169     m_loadIsInProgress = false;
       
   170 }
       
   171 
       
   172 }