Rubber-stamped by Darin Adler.
[WebKit-https.git] / WebCore / loader / appcache / ApplicationCache.cpp
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_storageID(0)
43 {
44 }
45
46 ApplicationCache::~ApplicationCache()
47 {
48     if (m_group && !m_group->isCopy())
49         m_group->cacheDestroyed(this);
50 }
51     
52 void ApplicationCache::setGroup(ApplicationCacheGroup* group)
53 {
54     ASSERT(!m_group || group == m_group);
55     m_group = group;
56 }
57
58 bool ApplicationCache::isComplete() const
59 {
60     return !m_group->cacheIsBeingUpdated(this);
61 }
62
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     
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::Master));
85         
86         // Add the resource to the storage.
87         cacheStorage().store(resource.get(), this);
88     }
89     
90     m_resources.set(url, resource);
91 }
92
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     
107 ApplicationCacheResource* ApplicationCache::resourceForURL(const String& url)
108 {
109     return m_resources.get(url).get();
110 }    
111
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
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
132 unsigned ApplicationCache::numDynamicEntries() const
133 {
134     // FIXME: Implement
135     return 0;
136 }
137     
138 String ApplicationCache::dynamicEntry(unsigned) const
139 {
140     // FIXME: Implement
141     return String();
142 }
143     
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     
153 void ApplicationCache::removeDynamicEntry(const String&)
154 {
155     // FIXME: Implement
156 }
157
158 void ApplicationCache::setOnlineWhitelist(const Vector<KURL>& onlineWhitelist)
159 {
160     ASSERT(m_onlineWhitelist.isEmpty());
161     m_onlineWhitelist = onlineWhitelist; 
162 }
163
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
174 void ApplicationCache::setFallbackURLs(const FallbackURLVector& fallbackURLs)
175 {
176     ASSERT(m_fallbackURLs.isEmpty());
177     m_fallbackURLs = fallbackURLs;
178 }
179
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
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
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)