Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2009 Google 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 are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "ApplicationCacheHost.h"
     33 
     34 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
     35 
     36 #include "ApplicationCacheHostInternal.h"
     37 #include "DocumentLoader.h"
     38 #include "DOMApplicationCache.h"
     39 #include "Frame.h"
     40 #include "Settings.h"
     41 #include "WebURL.h"
     42 #include "WebURLError.h"
     43 #include "WebURLResponse.h"
     44 #include "WrappedResourceRequest.h"
     45 #include "WrappedResourceResponse.h"
     46 
     47 using namespace WebKit;
     48 
     49 namespace WebCore {
     50 
     51 // We provide a custom implementation of this class that calls out to the
     52 // embedding application instead of using WebCore's built in appcache system.
     53 // This file replaces webcore/appcache/ApplicationCacheHost.cpp in our build.
     54 
     55 ApplicationCacheHost::ApplicationCacheHost(DocumentLoader* documentLoader)
     56     : m_domApplicationCache(0)
     57     , m_documentLoader(documentLoader)
     58     , m_defersEvents(true)
     59 {
     60     ASSERT(m_documentLoader);
     61 }
     62 
     63 ApplicationCacheHost::~ApplicationCacheHost()
     64 {
     65 }
     66 
     67 void ApplicationCacheHost::maybeLoadMainResource(ResourceRequest& request, SubstituteData&)
     68 {
     69     // We defer creating the outer host object to avoid spurious creation/destruction
     70     // around creating empty documents. At this point, we're initiating a main resource
     71     // load for the document, so its for real.
     72 
     73     if (!isApplicationCacheEnabled())
     74         return;
     75 
     76     m_internal.set(new ApplicationCacheHostInternal(this));
     77     if (m_internal->m_outerHost) {
     78         WrappedResourceRequest wrapped(request);
     79         m_internal->m_outerHost->willStartMainResourceRequest(wrapped);
     80     } else
     81         m_internal.clear();
     82 
     83     // NOTE: The semantics of this method, and others in this interface, are subtly different
     84     // than the method names would suggest. For example, in this method never returns an appcached
     85     // response in the SubstituteData out argument, instead we return the appcached response thru
     86     // the usual resource loading pipeline.
     87 }
     88 
     89 void ApplicationCacheHost::selectCacheWithoutManifest()
     90 {
     91     if (m_internal)
     92         m_internal->m_outerHost->selectCacheWithoutManifest();
     93 }
     94 
     95 void ApplicationCacheHost::selectCacheWithManifest(const KURL& manifestURL)
     96 {
     97     if (m_internal) {
     98         if (!m_internal->m_outerHost->selectCacheWithManifest(manifestURL)) {
     99             // It's a foreign entry, restart the current navigation from the top
    100             // of the navigation algorithm. The navigation will not result in the
    101             // same resource being loaded, because "foreign" entries are never picked
    102             // during navigation.
    103             // see WebCore::ApplicationCacheGroup::selectCache()
    104             const KURL& docURL = m_documentLoader->frame()->document()->url();
    105             String referrer = m_documentLoader->frameLoader()->referrer();
    106             m_documentLoader->frame()->redirectScheduler()->scheduleLocationChange(docURL, referrer);
    107         }
    108     }
    109 }
    110 
    111 bool ApplicationCacheHost::maybeLoadFallbackForMainResponse(const ResourceRequest&, const ResourceResponse& response)
    112 {
    113     if (m_internal) {
    114         WrappedResourceResponse wrapped(response);
    115         m_internal->m_outerHost->didReceiveResponseForMainResource(wrapped);
    116     }
    117     return false;
    118 }
    119 
    120 bool ApplicationCacheHost::maybeLoadFallbackForMainError(const ResourceRequest&, const ResourceError& error)
    121 {
    122     // N/A to the chromium port
    123     return false;
    124 }
    125 
    126 void ApplicationCacheHost::mainResourceDataReceived(const char* data, int length, long long, bool)
    127 {
    128     if (m_internal)
    129         m_internal->m_outerHost->didReceiveDataForMainResource(data, length);
    130 }
    131 
    132 void ApplicationCacheHost::failedLoadingMainResource()
    133 {
    134     if (m_internal)
    135         m_internal->m_outerHost->didFinishLoadingMainResource(false);
    136 }
    137 
    138 void ApplicationCacheHost::finishedLoadingMainResource()
    139 {
    140     if (m_internal)
    141         m_internal->m_outerHost->didFinishLoadingMainResource(true);
    142 }
    143 
    144 bool ApplicationCacheHost::maybeLoadResource(ResourceLoader*, ResourceRequest& request, const KURL&)
    145 {
    146     // FIXME: look into the purpose of the unused KURL& originalURL parameter
    147     if (m_internal) {
    148         WrappedResourceRequest wrapped(request);
    149         m_internal->m_outerHost->willStartSubResourceRequest(wrapped);
    150     }
    151     return false;
    152 }
    153 
    154 bool ApplicationCacheHost::maybeLoadFallbackForRedirect(ResourceLoader*, ResourceRequest&, const ResourceResponse&)
    155 {
    156     // N/A to the chromium port
    157     return false;
    158 }
    159 
    160 bool ApplicationCacheHost::maybeLoadFallbackForResponse(ResourceLoader*, const ResourceResponse&)
    161 {
    162     // N/A to the chromium port
    163     return false;
    164 }
    165 
    166 bool ApplicationCacheHost::maybeLoadFallbackForError(ResourceLoader*, const ResourceError&)
    167 {
    168     // N/A to the chromium port
    169     return false;
    170 }
    171 
    172 bool ApplicationCacheHost::maybeLoadSynchronously(ResourceRequest& request, ResourceError&, ResourceResponse&, Vector<char>&)
    173 {
    174     if (m_internal) {
    175         WrappedResourceRequest wrapped(request);
    176         m_internal->m_outerHost->willStartSubResourceRequest(wrapped);
    177     }
    178     return false;
    179 }
    180 
    181 void ApplicationCacheHost::maybeLoadFallbackSynchronously(const ResourceRequest&, ResourceError&, ResourceResponse&, Vector<char>&)
    182 {
    183     // N/A to the chromium port
    184 }
    185 
    186 bool ApplicationCacheHost::canCacheInPageCache() const
    187 {
    188     // N/A to the chromium port which doesn't use the page cache.
    189     return false;
    190 }
    191 
    192 void ApplicationCacheHost::setDOMApplicationCache(DOMApplicationCache* domApplicationCache)
    193 {
    194     ASSERT(!m_domApplicationCache || !domApplicationCache);
    195     m_domApplicationCache = domApplicationCache;
    196 }
    197 
    198 void ApplicationCacheHost::notifyDOMApplicationCache(EventID id)
    199 {
    200     if (m_defersEvents) {
    201         m_deferredEvents.append(id);
    202         return;
    203     }
    204     if (m_domApplicationCache) {
    205         ExceptionCode ec = 0;
    206         m_domApplicationCache->dispatchEvent(Event::create(DOMApplicationCache::toEventType(id), false, false), ec);
    207         ASSERT(!ec);
    208     }
    209 }
    210 
    211 void ApplicationCacheHost::stopDeferringEvents()
    212 {
    213     RefPtr<DocumentLoader> protect(documentLoader());
    214     for (unsigned i = 0; i < m_deferredEvents.size(); ++i) {
    215         EventID id = m_deferredEvents[i];
    216         if (m_domApplicationCache) {
    217             ExceptionCode ec = 0;
    218             m_domApplicationCache->dispatchEvent(Event::create(DOMApplicationCache::toEventType(id), false, false), ec);
    219             ASSERT(!ec);
    220         }
    221     }
    222     m_deferredEvents.clear();
    223     m_defersEvents = false;
    224 }
    225 
    226 ApplicationCacheHost::Status ApplicationCacheHost::status() const
    227 {
    228     return m_internal ? static_cast<Status>(m_internal->m_outerHost->status()) : UNCACHED;
    229 }
    230 
    231 bool ApplicationCacheHost::update()
    232 {
    233     return m_internal ? m_internal->m_outerHost->startUpdate() : false;
    234 }
    235 
    236 bool ApplicationCacheHost::swapCache()
    237 {
    238     return m_internal ? m_internal->m_outerHost->swapCache() : false;
    239 }
    240 
    241 bool ApplicationCacheHost::isApplicationCacheEnabled()
    242 {
    243     ASSERT(m_documentLoader->frame());
    244     return m_documentLoader->frame()->settings()
    245            && m_documentLoader->frame()->settings()->offlineWebApplicationCacheEnabled();
    246 }
    247 
    248 }  // namespace WebCore
    249 
    250 #endif  // ENABLE(OFFLINE_WEB_APPLICATIONS)
    251