Home | History | Annotate | Download | only in appcache
      1 /*
      2  * Copyright (C) 2008 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  * 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 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 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 "ApplicationCache.h"
     28 
     29 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
     30 
     31 #include "ApplicationCacheGroup.h"
     32 #include "ApplicationCacheResource.h"
     33 #include "ApplicationCacheStorage.h"
     34 #include "ResourceRequest.h"
     35 #include <stdio.h>
     36 
     37 namespace WebCore {
     38 
     39 ApplicationCache::ApplicationCache()
     40     : m_group(0)
     41     , m_manifest(0)
     42     , m_estimatedSizeInStorage(0)
     43     , m_storageID(0)
     44 {
     45 }
     46 
     47 ApplicationCache::~ApplicationCache()
     48 {
     49     if (m_group && !m_group->isCopy())
     50         m_group->cacheDestroyed(this);
     51 }
     52 
     53 void ApplicationCache::setGroup(ApplicationCacheGroup* group)
     54 {
     55     ASSERT(!m_group || group == m_group);
     56     m_group = group;
     57 }
     58 
     59 bool ApplicationCache::isComplete() const
     60 {
     61     return !m_group->cacheIsBeingUpdated(this);
     62 }
     63 
     64 void ApplicationCache::setManifestResource(PassRefPtr<ApplicationCacheResource> manifest)
     65 {
     66     ASSERT(manifest);
     67     ASSERT(!m_manifest);
     68     ASSERT(manifest->type() & ApplicationCacheResource::Manifest);
     69 
     70     m_manifest = manifest.get();
     71 
     72     addResource(manifest);
     73 }
     74 
     75 void ApplicationCache::addResource(PassRefPtr<ApplicationCacheResource> resource)
     76 {
     77     ASSERT(resource);
     78 
     79     const String& url = resource->url();
     80 
     81     ASSERT(!m_resources.contains(url));
     82 
     83     if (m_storageID) {
     84         ASSERT(!resource->storageID());
     85         ASSERT(resource->type() & ApplicationCacheResource::Master);
     86 
     87         // Add the resource to the storage.
     88         cacheStorage().store(resource.get(), this);
     89     }
     90 
     91     m_estimatedSizeInStorage += resource->estimatedSizeInStorage();
     92 
     93     m_resources.set(url, resource);
     94 }
     95 
     96 unsigned ApplicationCache::removeResource(const String& url)
     97 {
     98     HashMap<String, RefPtr<ApplicationCacheResource> >::iterator it = m_resources.find(url);
     99     if (it == m_resources.end())
    100         return 0;
    101 
    102     // The resource exists, get its type so we can return it.
    103     unsigned type = it->second->type();
    104 
    105     m_resources.remove(it);
    106 
    107     m_estimatedSizeInStorage -= it->second->estimatedSizeInStorage();
    108 
    109     return type;
    110 }
    111 
    112 ApplicationCacheResource* ApplicationCache::resourceForURL(const String& url)
    113 {
    114     ASSERT(!KURL(ParsedURLString, url).hasFragmentIdentifier());
    115     return m_resources.get(url).get();
    116 }
    117 
    118 bool ApplicationCache::requestIsHTTPOrHTTPSGet(const ResourceRequest& request)
    119 {
    120     if (!request.url().protocolInHTTPFamily())
    121         return false;
    122 
    123     if (!equalIgnoringCase(request.httpMethod(), "GET"))
    124         return false;
    125 
    126     return true;
    127 }
    128 
    129 ApplicationCacheResource* ApplicationCache::resourceForRequest(const ResourceRequest& request)
    130 {
    131     // We only care about HTTP/HTTPS GET requests.
    132     if (!requestIsHTTPOrHTTPSGet(request))
    133         return false;
    134 
    135     KURL url(request.url());
    136     if (url.hasFragmentIdentifier())
    137         url.removeFragmentIdentifier();
    138 
    139     return resourceForURL(url);
    140 }
    141 
    142 void ApplicationCache::setOnlineWhitelist(const Vector<KURL>& onlineWhitelist)
    143 {
    144     ASSERT(m_onlineWhitelist.isEmpty());
    145     m_onlineWhitelist = onlineWhitelist;
    146 }
    147 
    148 bool ApplicationCache::isURLInOnlineWhitelist(const KURL& url)
    149 {
    150     if (m_allowAllNetworkRequests)
    151         return true;
    152 
    153     size_t whitelistSize = m_onlineWhitelist.size();
    154     for (size_t i = 0; i < whitelistSize; ++i) {
    155         if (protocolHostAndPortAreEqual(url, m_onlineWhitelist[i]) && url.string().startsWith(m_onlineWhitelist[i].string()))
    156             return true;
    157     }
    158     return false;
    159 }
    160 
    161 void ApplicationCache::setFallbackURLs(const FallbackURLVector& fallbackURLs)
    162 {
    163     ASSERT(m_fallbackURLs.isEmpty());
    164     m_fallbackURLs = fallbackURLs;
    165 }
    166 
    167 bool ApplicationCache::urlMatchesFallbackNamespace(const KURL& url, KURL* fallbackURL)
    168 {
    169     size_t fallbackCount = m_fallbackURLs.size();
    170     for (size_t i = 0; i < fallbackCount; ++i) {
    171         if (protocolHostAndPortAreEqual(url, m_fallbackURLs[i].first) && url.string().startsWith(m_fallbackURLs[i].first.string())) {
    172             if (fallbackURL)
    173                 *fallbackURL = m_fallbackURLs[i].second;
    174             return true;
    175         }
    176     }
    177     return false;
    178 }
    179 
    180 void ApplicationCache::clearStorageID()
    181 {
    182     m_storageID = 0;
    183 
    184     ResourceMap::const_iterator end = m_resources.end();
    185     for (ResourceMap::const_iterator it = m_resources.begin(); it != end; ++it)
    186         it->second->clearStorageID();
    187 }
    188 
    189 #ifndef NDEBUG
    190 void ApplicationCache::dump()
    191 {
    192     HashMap<String, RefPtr<ApplicationCacheResource> >::const_iterator end = m_resources.end();
    193 
    194     for (HashMap<String, RefPtr<ApplicationCacheResource> >::const_iterator it = m_resources.begin(); it != end; ++it) {
    195         printf("%s ", it->first.ascii().data());
    196         ApplicationCacheResource::dumpType(it->second->type());
    197     }
    198 }
    199 #endif
    200 
    201 }
    202 
    203 #endif // ENABLE(OFFLINE_WEB_APPLICATIONS)
    204