| 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 |