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