summaryrefslogtreecommitdiffstats
path: root/WebCore/loader/appcache/DOMApplicationCache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/loader/appcache/DOMApplicationCache.cpp')
-rw-r--r--WebCore/loader/appcache/DOMApplicationCache.cpp286
1 files changed, 286 insertions, 0 deletions
diff --git a/WebCore/loader/appcache/DOMApplicationCache.cpp b/WebCore/loader/appcache/DOMApplicationCache.cpp
new file mode 100644
index 0000000..f872a50
--- /dev/null
+++ b/WebCore/loader/appcache/DOMApplicationCache.cpp
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DOMApplicationCache.h"
+
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+
+#include "ApplicationCache.h"
+#include "ApplicationCacheGroup.h"
+#include "DocumentLoader.h"
+#include "Event.h"
+#include "EventException.h"
+#include "EventListener.h"
+#include "EventNames.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+
+namespace WebCore {
+
+DOMApplicationCache::DOMApplicationCache(Frame* frame)
+ : m_frame(frame)
+{
+}
+
+void DOMApplicationCache::disconnectFrame()
+{
+ m_frame = 0;
+}
+
+ApplicationCache* DOMApplicationCache::associatedCache() const
+{
+ if (!m_frame)
+ return 0;
+
+ return m_frame->loader()->documentLoader()->topLevelApplicationCache();
+}
+
+unsigned short DOMApplicationCache::status() const
+{
+ ApplicationCache* cache = associatedCache();
+ if (!cache)
+ return UNCACHED;
+
+ switch (cache->group()->status()) {
+ case ApplicationCacheGroup::Checking:
+ return CHECKING;
+ case ApplicationCacheGroup::Downloading:
+ return DOWNLOADING;
+ case ApplicationCacheGroup::Idle: {
+ if (cache != cache->group()->newestCache())
+ return UPDATEREADY;
+
+ return IDLE;
+ }
+ default:
+ ASSERT_NOT_REACHED();
+ }
+
+ return 0;
+}
+
+void DOMApplicationCache::update(ExceptionCode& ec)
+{
+ ApplicationCache* cache = associatedCache();
+ if (!cache) {
+ ec = INVALID_STATE_ERR;
+ return;
+ }
+
+ cache->group()->update(m_frame);
+}
+
+bool DOMApplicationCache::swapCache()
+{
+ if (!m_frame)
+ return false;
+
+ ApplicationCache* cache = m_frame->loader()->documentLoader()->applicationCache();
+ if (!cache)
+ return false;
+
+ // Check if we already have the newest cache
+ ApplicationCache* newestCache = cache->group()->newestCache();
+ if (cache == newestCache)
+ return false;
+
+ ASSERT(cache->group() == newestCache->group());
+ m_frame->loader()->documentLoader()->setApplicationCache(newestCache);
+
+ return true;
+}
+
+void DOMApplicationCache::swapCache(ExceptionCode& ec)
+{
+ if (!swapCache())
+ ec = INVALID_STATE_ERR;
+}
+
+unsigned DOMApplicationCache::length() const
+{
+ ApplicationCache* cache = associatedCache();
+ if (!cache)
+ return 0;
+
+ return cache->numDynamicEntries();
+}
+
+String DOMApplicationCache::item(unsigned item, ExceptionCode& ec)
+{
+ ApplicationCache* cache = associatedCache();
+ if (!cache) {
+ ec = INVALID_STATE_ERR;
+ return String();
+ }
+
+ if (item >= length()) {
+ ec = INDEX_SIZE_ERR;
+ return String();
+ }
+
+ return cache->dynamicEntry(item);
+}
+
+void DOMApplicationCache::add(const KURL& url, ExceptionCode& ec)
+{
+ ApplicationCache* cache = associatedCache();
+ if (!cache) {
+ ec = INVALID_STATE_ERR;
+ return;
+ }
+
+ if (!url.isValid()) {
+ ec = SYNTAX_ERR;
+ return;
+ }
+
+ if (!cache->addDynamicEntry(url)) {
+ // This should use the (currently not specified) security exceptions in HTML5 4.3.4
+ ec = SECURITY_ERR;
+ }
+}
+
+void DOMApplicationCache::remove(const KURL& url, ExceptionCode& ec)
+{
+ ApplicationCache* cache = associatedCache();
+ if (!cache) {
+ ec = INVALID_STATE_ERR;
+ return;
+ }
+
+ cache->removeDynamicEntry(url);
+}
+
+ScriptExecutionContext* DOMApplicationCache::scriptExecutionContext() const
+{
+ return m_frame->document();
+}
+
+void DOMApplicationCache::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool)
+{
+ EventListenersMap::iterator iter = m_eventListeners.find(eventType);
+ if (iter == m_eventListeners.end()) {
+ ListenerVector listeners;
+ listeners.append(eventListener);
+ m_eventListeners.add(eventType, listeners);
+ } else {
+ ListenerVector& listeners = iter->second;
+ for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) {
+ if (*listenerIter == eventListener)
+ return;
+ }
+
+ listeners.append(eventListener);
+ m_eventListeners.add(eventType, listeners);
+ }
+}
+
+void DOMApplicationCache::removeEventListener(const AtomicString& eventType, EventListener* eventListener, bool useCapture)
+{
+ EventListenersMap::iterator iter = m_eventListeners.find(eventType);
+ if (iter == m_eventListeners.end())
+ return;
+
+ ListenerVector& listeners = iter->second;
+ for (ListenerVector::const_iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) {
+ if (*listenerIter == eventListener) {
+ listeners.remove(listenerIter - listeners.begin());
+ return;
+ }
+ }
+}
+
+bool DOMApplicationCache::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec)
+{
+ if (event->type().isEmpty()) {
+ ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
+ return true;
+ }
+
+ ListenerVector listenersCopy = m_eventListeners.get(event->type());
+ for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); listenerIter != listenersCopy.end(); ++listenerIter) {
+ event->setTarget(this);
+ event->setCurrentTarget(this);
+ listenerIter->get()->handleEvent(event.get(), false);
+ }
+
+ return !event->defaultPrevented();
+}
+
+void DOMApplicationCache::callListener(const AtomicString& eventType, EventListener* listener)
+{
+ ASSERT(m_frame);
+
+ RefPtr<Event> event = Event::create(eventType, false, false);
+ if (listener) {
+ event->setTarget(this);
+ event->setCurrentTarget(this);
+ listener->handleEvent(event.get(), false);
+ }
+
+ ExceptionCode ec = 0;
+ dispatchEvent(event.release(), ec);
+ ASSERT(!ec);
+}
+
+void DOMApplicationCache::callCheckingListener()
+{
+ callListener(eventNames().checkingEvent, m_onCheckingListener.get());
+}
+
+void DOMApplicationCache::callErrorListener()
+{
+ callListener(eventNames().errorEvent, m_onErrorListener.get());
+}
+
+void DOMApplicationCache::callNoUpdateListener()
+{
+ callListener(eventNames().noupdateEvent, m_onNoUpdateListener.get());
+}
+
+void DOMApplicationCache::callDownloadingListener()
+{
+ callListener(eventNames().downloadingEvent, m_onDownloadingListener.get());
+}
+
+void DOMApplicationCache::callProgressListener()
+{
+ callListener(eventNames().progressEvent, m_onProgressListener.get());
+}
+
+void DOMApplicationCache::callUpdateReadyListener()
+{
+ callListener(eventNames().updatereadyEvent, m_onUpdateReadyListener.get());
+}
+
+void DOMApplicationCache::callCachedListener()
+{
+ callListener(eventNames().cachedEvent, m_onCachedListener.get());
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(OFFLINE_WEB_APPLICATIONS)