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