OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved. | 2 * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
12 * | 12 * |
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 */ | 24 */ |
25 | 25 |
26 #include "config.h" | 26 #include "config.h" |
27 #include "DOMApplicationCache.h" | 27 #include "DOMApplicationCache.h" |
28 | 28 |
29 #if ENABLE(OFFLINE_WEB_APPLICATIONS) | 29 #if ENABLE(APPLICATION_CACHE) |
30 | 30 |
31 #include "ApplicationCache.h" | |
32 #include "ApplicationCacheGroup.h" | |
33 #include "ApplicationCacheResource.h" | |
34 #include "DocumentLoader.h" | |
35 #include "Event.h" | 31 #include "Event.h" |
36 #include "EventException.h" | 32 #include "EventException.h" |
37 #include "EventListener.h" | 33 #include "EventListener.h" |
38 #include "EventNames.h" | 34 #include "EventNames.h" |
39 #include "Frame.h" | 35 #include "Frame.h" |
40 #include "FrameLoader.h" | 36 #include "FrameLoader.h" |
41 #include "StaticStringList.h" | 37 #include "StaticStringList.h" |
42 | 38 |
43 namespace WebCore { | 39 namespace WebCore { |
44 | 40 |
45 DOMApplicationCache::DOMApplicationCache(Frame* frame) | 41 DOMApplicationCache::DOMApplicationCache(Frame* frame) |
46 : m_frame(frame) | 42 : m_frame(frame) |
| 43 , m_appcacheFrontend(frame->loader()->appcacheFrontend()) |
47 { | 44 { |
| 45 appcacheFrontend()->setDOMApplicationCache(this); |
48 } | 46 } |
49 | 47 |
50 void DOMApplicationCache::disconnectFrame() | 48 void DOMApplicationCache::disconnectFrame() |
51 { | 49 { |
| 50 appcacheFrontend()->setDOMApplicationCache(0); |
52 m_frame = 0; | 51 m_frame = 0; |
53 } | 52 m_appcacheFrontend = 0; |
54 | |
55 ApplicationCache* DOMApplicationCache::associatedCache() const | |
56 { | |
57 if (!m_frame) | |
58 return 0; | |
59 | |
60 return m_frame->loader()->documentLoader()->applicationCache(); | |
61 } | 53 } |
62 | 54 |
63 unsigned short DOMApplicationCache::status() const | 55 unsigned short DOMApplicationCache::status() const |
64 { | 56 { |
65 ApplicationCache* cache = associatedCache(); | 57 ApplicationCacheFrontend* cache = appcacheFrontend(); |
66 if (!cache) | 58 return cache ? cache->status() : APPCACHE_UNCACHED; |
67 return UNCACHED; | |
68 | |
69 switch (cache->group()->updateStatus()) { | |
70 case ApplicationCacheGroup::Checking: | |
71 return CHECKING; | |
72 case ApplicationCacheGroup::Downloading: | |
73 return DOWNLOADING; | |
74 case ApplicationCacheGroup::Idle: { | |
75 if (cache->group()->isObsolete()) | |
76 return OBSOLETE; | |
77 if (cache != cache->group()->newestCache()) | |
78 return UPDATEREADY; | |
79 return IDLE; | |
80 } | |
81 } | |
82 | |
83 ASSERT_NOT_REACHED(); | |
84 return 0; | |
85 } | 59 } |
86 | 60 |
87 void DOMApplicationCache::update(ExceptionCode& ec) | 61 void DOMApplicationCache::update(ExceptionCode& ec) |
88 { | 62 { |
89 ApplicationCache* cache = associatedCache(); | 63 ApplicationCacheFrontend* cache = appcacheFrontend(); |
90 if (!cache) { | 64 if (!cache) { |
91 ec = INVALID_STATE_ERR; | 65 ec = INVALID_STATE_ERR; |
92 return; | 66 return; |
93 } | 67 } |
94 | 68 cache->update(); |
95 cache->group()->update(m_frame, ApplicationCacheUpdateWithoutBrowsingContext
); | |
96 } | 69 } |
97 | 70 |
98 bool DOMApplicationCache::swapCache() | 71 bool DOMApplicationCache::swapCache() |
99 { | 72 { |
100 if (!m_frame) | 73 ApplicationCacheFrontend* cache = appcacheFrontend(); |
101 return false; | |
102 | |
103 ApplicationCache* cache = m_frame->loader()->documentLoader()->applicationCa
che(); | |
104 if (!cache) | 74 if (!cache) |
105 return false; | 75 return false; |
106 | 76 return cache->swapCache(); |
107 // If the group of application caches to which cache belongs has the lifecyc
le status obsolete, unassociate document from cache. | |
108 if (cache->group()->isObsolete()) { | |
109 cache->group()->disassociateDocumentLoader(m_frame->loader()->documentLo
ader()); | |
110 return true; | |
111 } | |
112 | |
113 // If there is no newer cache, raise an INVALID_STATE_ERR exception. | |
114 ApplicationCache* newestCache = cache->group()->newestCache(); | |
115 if (cache == newestCache) | |
116 return false; | |
117 | |
118 ASSERT(cache->group() == newestCache->group()); | |
119 m_frame->loader()->documentLoader()->setApplicationCache(newestCache); | |
120 | |
121 return true; | |
122 } | 77 } |
123 | 78 |
124 void DOMApplicationCache::swapCache(ExceptionCode& ec) | 79 void DOMApplicationCache::swapCache(ExceptionCode& ec) |
125 { | 80 { |
126 if (!swapCache()) | 81 if (!swapCache()) |
127 ec = INVALID_STATE_ERR; | 82 ec = INVALID_STATE_ERR; |
128 } | 83 } |
129 | 84 |
130 PassRefPtr<DOMStringList> DOMApplicationCache::items() | |
131 { | |
132 Vector<String> result; | |
133 if (ApplicationCache* cache = associatedCache()) { | |
134 unsigned numEntries = cache->numDynamicEntries(); | |
135 result.reserveInitialCapacity(numEntries); | |
136 for (unsigned i = 0; i < numEntries; ++i) | |
137 result.append(cache->dynamicEntry(i)); | |
138 } | |
139 return StaticStringList::adopt(result); | |
140 } | |
141 | |
142 bool DOMApplicationCache::hasItem(const KURL& url, ExceptionCode& ec) | |
143 { | |
144 ApplicationCache* cache = associatedCache(); | |
145 if (!cache) { | |
146 ec = INVALID_STATE_ERR; | |
147 return false; | |
148 } | |
149 | |
150 if (!url.isValid()) { | |
151 ec = SYNTAX_ERR; | |
152 return false; | |
153 } | |
154 | |
155 ApplicationCacheResource* resource = cache->resourceForURL(url.string()); | |
156 return resource && (resource->type() & ApplicationCacheResource::Dynamic); | |
157 } | |
158 | |
159 void DOMApplicationCache::add(const KURL& url, ExceptionCode& ec) | |
160 { | |
161 ApplicationCache* cache = associatedCache(); | |
162 if (!cache) { | |
163 ec = INVALID_STATE_ERR; | |
164 return; | |
165 } | |
166 | |
167 if (!url.isValid()) { | |
168 ec = SYNTAX_ERR; | |
169 return; | |
170 } | |
171 | |
172 if (!cache->addDynamicEntry(url)) { | |
173 // This should use the (currently not specified) security exceptions in
HTML5 4.3.4 | |
174 ec = SECURITY_ERR; | |
175 } | |
176 } | |
177 | |
178 void DOMApplicationCache::remove(const KURL& url, ExceptionCode& ec) | |
179 { | |
180 ApplicationCache* cache = associatedCache(); | |
181 if (!cache) { | |
182 ec = INVALID_STATE_ERR; | |
183 return; | |
184 } | |
185 | |
186 cache->removeDynamicEntry(url); | |
187 } | |
188 | |
189 ScriptExecutionContext* DOMApplicationCache::scriptExecutionContext() const | 85 ScriptExecutionContext* DOMApplicationCache::scriptExecutionContext() const |
190 { | 86 { |
191 return m_frame->document(); | 87 return m_frame ? m_frame->document() : 0; |
192 } | 88 } |
193 | 89 |
194 void DOMApplicationCache::addEventListener(const AtomicString& eventType, PassRe
fPtr<EventListener> eventListener, bool) | 90 void DOMApplicationCache::addEventListener(const AtomicString& eventName, PassRe
fPtr<EventListener> eventListener, bool) |
195 { | 91 { |
196 EventListenersMap::iterator iter = m_eventListeners.find(eventType); | 92 EventListenersMap::iterator iter = m_eventListeners.find(eventName); |
197 if (iter == m_eventListeners.end()) { | 93 if (iter == m_eventListeners.end()) { |
198 ListenerVector listeners; | 94 ListenerVector listeners; |
199 listeners.append(eventListener); | 95 listeners.append(eventListener); |
200 m_eventListeners.add(eventType, listeners); | 96 m_eventListeners.add(eventName, listeners); |
201 } else { | 97 } else { |
202 ListenerVector& listeners = iter->second; | 98 ListenerVector& listeners = iter->second; |
203 for (ListenerVector::iterator listenerIter = listeners.begin(); listener
Iter != listeners.end(); ++listenerIter) { | 99 for (ListenerVector::iterator listenerIter = listeners.begin(); listener
Iter != listeners.end(); ++listenerIter) { |
204 if (*listenerIter == eventListener) | 100 if (*listenerIter == eventListener) |
205 return; | 101 return; |
206 } | 102 } |
207 | 103 |
208 listeners.append(eventListener); | 104 listeners.append(eventListener); |
209 m_eventListeners.add(eventType, listeners); | 105 m_eventListeners.add(eventName, listeners); |
210 } | 106 } |
211 } | 107 } |
212 | 108 |
213 void DOMApplicationCache::removeEventListener(const AtomicString& eventType, Eve
ntListener* eventListener, bool) | 109 void DOMApplicationCache::removeEventListener(const AtomicString& eventName, Eve
ntListener* eventListener, bool) |
214 { | 110 { |
215 EventListenersMap::iterator iter = m_eventListeners.find(eventType); | 111 EventListenersMap::iterator iter = m_eventListeners.find(eventName); |
216 if (iter == m_eventListeners.end()) | 112 if (iter == m_eventListeners.end()) |
217 return; | 113 return; |
218 | 114 |
219 ListenerVector& listeners = iter->second; | 115 ListenerVector& listeners = iter->second; |
220 for (ListenerVector::const_iterator listenerIter = listeners.begin(); listen
erIter != listeners.end(); ++listenerIter) { | 116 for (ListenerVector::const_iterator listenerIter = listeners.begin(); listen
erIter != listeners.end(); ++listenerIter) { |
221 if (*listenerIter == eventListener) { | 117 if (*listenerIter == eventListener) { |
222 listeners.remove(listenerIter - listeners.begin()); | 118 listeners.remove(listenerIter - listeners.begin()); |
223 return; | 119 return; |
224 } | 120 } |
225 } | 121 } |
226 } | 122 } |
227 | 123 |
228 bool DOMApplicationCache::dispatchEvent(PassRefPtr<Event> event, ExceptionCode&
ec) | 124 bool DOMApplicationCache::dispatchEvent(PassRefPtr<Event> event, ExceptionCode&
ec) |
229 { | 125 { |
230 if (!event || event->type().isEmpty()) { | 126 if (!event || event->type().isEmpty()) { |
231 ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR; | 127 ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR; |
232 return true; | 128 return true; |
233 } | 129 } |
234 | 130 |
235 ListenerVector listenersCopy = m_eventListeners.get(event->type()); | 131 ListenerVector listenersCopy = m_eventListeners.get(event->type()); |
236 for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); li
stenerIter != listenersCopy.end(); ++listenerIter) { | 132 for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); li
stenerIter != listenersCopy.end(); ++listenerIter) { |
237 event->setTarget(this); | 133 event->setTarget(this); |
238 event->setCurrentTarget(this); | 134 event->setCurrentTarget(this); |
239 listenerIter->get()->handleEvent(event.get(), false); | 135 listenerIter->get()->handleEvent(event.get(), false); |
240 } | 136 } |
241 | 137 |
242 return !event->defaultPrevented(); | 138 return !event->defaultPrevented(); |
243 } | 139 } |
244 | 140 |
245 void DOMApplicationCache::callListener(const AtomicString& eventType, EventListe
ner* listener) | 141 void DOMApplicationCache::callListener(const AtomicString& eventType, EventListe
ner* listener) |
246 { | 142 { |
247 ASSERT(m_frame); | 143 ASSERT(m_frame); |
248 | 144 |
249 RefPtr<Event> event = Event::create(eventType, false, false); | 145 RefPtr<Event> event = Event::create(eventType, false, false); |
250 if (listener) { | 146 if (listener) { |
251 event->setTarget(this); | 147 event->setTarget(this); |
252 event->setCurrentTarget(this); | 148 event->setCurrentTarget(this); |
253 listener->handleEvent(event.get(), false); | 149 listener->handleEvent(event.get(), false); |
254 } | 150 } |
255 | 151 |
256 ExceptionCode ec = 0; | 152 ExceptionCode ec = 0; |
257 dispatchEvent(event.release(), ec); | 153 dispatchEvent(event.release(), ec); |
258 ASSERT(!ec); | 154 ASSERT(!ec); |
259 } | 155 } |
260 | 156 |
261 void DOMApplicationCache::callCheckingListener() | 157 // static |
| 158 const AtomicString& DOMApplicationCache::toEventName(ApplicationCacheEventType e
ventType) |
262 { | 159 { |
263 callListener(eventNames().checkingEvent, m_onCheckingListener.get()); | 160 switch (eventType) { |
| 161 case APPCACHE_CHECKING_EVENT: |
| 162 return eventNames().checkingEvent; |
| 163 case APPCACHE_ERROR_EVENT: |
| 164 return eventNames().errorEvent; |
| 165 case APPCACHE_NOUPDATE_EVENT: |
| 166 return eventNames().noupdateEvent; |
| 167 case APPCACHE_DOWNLOADING_EVENT: |
| 168 return eventNames().downloadingEvent; |
| 169 case APPCACHE_PROGRESS_EVENT: |
| 170 return eventNames().progressEvent; |
| 171 case APPCACHE_UPDATEREADY_EVENT: |
| 172 return eventNames().updatereadyEvent; |
| 173 case APPCACHE_CACHED_EVENT: |
| 174 return eventNames().cachedEvent; |
| 175 case APPCACHE_OBSOLETE_EVENT: |
| 176 return eventNames().obsoleteEvent; |
| 177 } |
| 178 ASSERT(false); |
| 179 return eventNames().abortEvent; |
264 } | 180 } |
265 | 181 |
266 void DOMApplicationCache::callErrorListener() | 182 // static |
| 183 ApplicationCacheEventType DOMApplicationCache::toEventType(const AtomicString& e
ventName) |
267 { | 184 { |
268 callListener(eventNames().errorEvent, m_onErrorListener.get()); | 185 if (eventName == eventNames().checkingEvent) |
| 186 return APPCACHE_CHECKING_EVENT; |
| 187 if (eventName == eventNames().errorEvent) |
| 188 return APPCACHE_ERROR_EVENT; |
| 189 if (eventName == eventNames().noupdateEvent) |
| 190 return APPCACHE_NOUPDATE_EVENT; |
| 191 if (eventName == eventNames().downloadingEvent) |
| 192 return APPCACHE_DOWNLOADING_EVENT; |
| 193 if (eventName == eventNames().progressEvent) |
| 194 return APPCACHE_PROGRESS_EVENT; |
| 195 if (eventName == eventNames().updatereadyEvent) |
| 196 return APPCACHE_UPDATEREADY_EVENT; |
| 197 if (eventName == eventNames().cachedEvent) |
| 198 return APPCACHE_CACHED_EVENT; |
| 199 if (eventName == eventNames().obsoleteEvent) |
| 200 return APPCACHE_OBSOLETE_EVENT; |
| 201 |
| 202 ASSERT(false); |
| 203 return NUMBER_OF_APPCACHE_EVENT_TYPES; |
269 } | 204 } |
270 | 205 |
271 void DOMApplicationCache::callNoUpdateListener() | |
272 { | |
273 callListener(eventNames().noupdateEvent, m_onNoUpdateListener.get()); | |
274 } | |
275 | |
276 void DOMApplicationCache::callDownloadingListener() | |
277 { | |
278 callListener(eventNames().downloadingEvent, m_onDownloadingListener.get()); | |
279 } | |
280 | |
281 void DOMApplicationCache::callProgressListener() | |
282 { | |
283 callListener(eventNames().progressEvent, m_onProgressListener.get()); | |
284 } | |
285 | |
286 void DOMApplicationCache::callUpdateReadyListener() | |
287 { | |
288 callListener(eventNames().updatereadyEvent, m_onUpdateReadyListener.get()); | |
289 } | |
290 | |
291 void DOMApplicationCache::callCachedListener() | |
292 { | |
293 callListener(eventNames().cachedEvent, m_onCachedListener.get()); | |
294 } | |
295 | |
296 void DOMApplicationCache::callObsoleteListener() | |
297 { | |
298 callListener(eventNames().obsoleteEvent, m_onObsoleteListener.get()); | |
299 } | |
300 | 206 |
301 } // namespace WebCore | 207 } // namespace WebCore |
302 | 208 |
303 #endif // ENABLE(OFFLINE_WEB_APPLICATIONS) | 209 #endif // ENABLE(APPLICATION_CACHE) |
OLD | NEW |