1 /*
2 * Copyright (C) 2008, 2009 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 "DOMApplicationCache.h"
28
29 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
30
31 #include "ApplicationCacheHost.h"
32 #include "DocumentLoader.h"
33 #include "Event.h"
34 #include "EventException.h"
35 #include "EventListener.h"
36 #include "EventNames.h"
37 #include "Frame.h"
38 #include "FrameLoader.h"
39
40 namespace WebCore {
41
DOMApplicationCache(Frame * frame)42 DOMApplicationCache::DOMApplicationCache(Frame* frame)
43 : m_frame(frame)
44 {
45 ASSERT(applicationCacheHost());
46 applicationCacheHost()->setDOMApplicationCache(this);
47 }
48
disconnectFrame()49 void DOMApplicationCache::disconnectFrame()
50 {
51 ApplicationCacheHost* cacheHost = applicationCacheHost();
52 if (cacheHost)
53 cacheHost->setDOMApplicationCache(0);
54 m_frame = 0;
55 }
56
applicationCacheHost() const57 ApplicationCacheHost* DOMApplicationCache::applicationCacheHost() const
58 {
59 if (!m_frame || !m_frame->loader()->documentLoader())
60 return 0;
61 return m_frame->loader()->documentLoader()->applicationCacheHost();
62 }
63
status() const64 unsigned short DOMApplicationCache::status() const
65 {
66 ApplicationCacheHost* cacheHost = applicationCacheHost();
67 if (!cacheHost)
68 return ApplicationCacheHost::UNCACHED;
69 return cacheHost->status();
70 }
71
update(ExceptionCode & ec)72 void DOMApplicationCache::update(ExceptionCode& ec)
73 {
74 ApplicationCacheHost* cacheHost = applicationCacheHost();
75 if (!cacheHost || !cacheHost->update())
76 ec = INVALID_STATE_ERR;
77 }
78
swapCache()79 bool DOMApplicationCache::swapCache()
80 {
81 ApplicationCacheHost* cacheHost = applicationCacheHost();
82 if (!cacheHost)
83 return false;
84 return cacheHost->swapCache();
85 }
86
swapCache(ExceptionCode & ec)87 void DOMApplicationCache::swapCache(ExceptionCode& ec)
88 {
89 if (!swapCache())
90 ec = INVALID_STATE_ERR;
91 }
92
scriptExecutionContext() const93 ScriptExecutionContext* DOMApplicationCache::scriptExecutionContext() const
94 {
95 return m_frame->document();
96 }
97
addEventListener(const AtomicString & eventType,PassRefPtr<EventListener> eventListener,bool)98 void DOMApplicationCache::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool)
99 {
100 EventListenersMap::iterator iter = m_eventListeners.find(eventType);
101 if (iter == m_eventListeners.end()) {
102 ListenerVector listeners;
103 listeners.append(eventListener);
104 m_eventListeners.add(eventType, listeners);
105 } else {
106 ListenerVector& listeners = iter->second;
107 for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) {
108 if (*listenerIter == eventListener)
109 return;
110 }
111
112 listeners.append(eventListener);
113 m_eventListeners.add(eventType, listeners);
114 }
115 }
116
removeEventListener(const AtomicString & eventType,EventListener * eventListener,bool)117 void DOMApplicationCache::removeEventListener(const AtomicString& eventType, EventListener* eventListener, bool)
118 {
119 EventListenersMap::iterator iter = m_eventListeners.find(eventType);
120 if (iter == m_eventListeners.end())
121 return;
122
123 ListenerVector& listeners = iter->second;
124 for (ListenerVector::const_iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) {
125 if (*listenerIter == eventListener) {
126 listeners.remove(listenerIter - listeners.begin());
127 return;
128 }
129 }
130 }
131
dispatchEvent(PassRefPtr<Event> event,ExceptionCode & ec)132 bool DOMApplicationCache::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec)
133 {
134 if (!event || event->type().isEmpty()) {
135 ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
136 return true;
137 }
138
139 ListenerVector listenersCopy = m_eventListeners.get(event->type());
140 for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); listenerIter != listenersCopy.end(); ++listenerIter) {
141 event->setTarget(this);
142 event->setCurrentTarget(this);
143 listenerIter->get()->handleEvent(event.get(), false);
144 }
145
146 return !event->defaultPrevented();
147 }
148
callListener(const AtomicString & eventType,EventListener * listener)149 void DOMApplicationCache::callListener(const AtomicString& eventType, EventListener* listener)
150 {
151 ASSERT(m_frame);
152
153 RefPtr<Event> event = Event::create(eventType, false, false);
154 if (listener) {
155 event->setTarget(this);
156 event->setCurrentTarget(this);
157 listener->handleEvent(event.get(), false);
158 }
159
160 ExceptionCode ec = 0;
161 dispatchEvent(event.release(), ec);
162 ASSERT(!ec);
163 }
164
toEventType(ApplicationCacheHost::EventID id)165 const AtomicString& DOMApplicationCache::toEventType(ApplicationCacheHost::EventID id)
166 {
167 switch (id) {
168 case ApplicationCacheHost::CHECKING_EVENT:
169 return eventNames().checkingEvent;
170 case ApplicationCacheHost::ERROR_EVENT:
171 return eventNames().errorEvent;
172 case ApplicationCacheHost::NOUPDATE_EVENT:
173 return eventNames().noupdateEvent;
174 case ApplicationCacheHost::DOWNLOADING_EVENT:
175 return eventNames().downloadingEvent;
176 case ApplicationCacheHost::PROGRESS_EVENT:
177 return eventNames().progressEvent;
178 case ApplicationCacheHost::UPDATEREADY_EVENT:
179 return eventNames().updatereadyEvent;
180 case ApplicationCacheHost::CACHED_EVENT:
181 return eventNames().cachedEvent;
182 case ApplicationCacheHost::OBSOLETE_EVENT:
183 return eventNames().obsoleteEvent;
184 }
185 ASSERT_NOT_REACHED();
186 return eventNames().errorEvent;
187 }
188
toEventID(const AtomicString & eventType)189 ApplicationCacheHost::EventID DOMApplicationCache::toEventID(const AtomicString& eventType)
190 {
191 if (eventType == eventNames().checkingEvent)
192 return ApplicationCacheHost::CHECKING_EVENT;
193 if (eventType == eventNames().errorEvent)
194 return ApplicationCacheHost::ERROR_EVENT;
195 if (eventType == eventNames().noupdateEvent)
196 return ApplicationCacheHost::NOUPDATE_EVENT;
197 if (eventType == eventNames().downloadingEvent)
198 return ApplicationCacheHost::DOWNLOADING_EVENT;
199 if (eventType == eventNames().progressEvent)
200 return ApplicationCacheHost::PROGRESS_EVENT;
201 if (eventType == eventNames().updatereadyEvent)
202 return ApplicationCacheHost::UPDATEREADY_EVENT;
203 if (eventType == eventNames().cachedEvent)
204 return ApplicationCacheHost::CACHED_EVENT;
205 if (eventType == eventNames().obsoleteEvent)
206 return ApplicationCacheHost::OBSOLETE_EVENT;
207
208 ASSERT_NOT_REACHED();
209 return ApplicationCacheHost::ERROR_EVENT;
210 }
211
212 } // namespace WebCore
213
214 #endif // ENABLE(OFFLINE_WEB_APPLICATIONS)
215