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