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