diff options
-rw-r--r-- | WebCore/page/DOMWindow.cpp | 13 | ||||
-rw-r--r-- | WebCore/page/DOMWindow.h | 3 | ||||
-rw-r--r-- | WebCore/page/PageGroup.cpp | 90 | ||||
-rw-r--r-- | WebCore/page/PageGroup.h | 8 | ||||
-rw-r--r-- | WebCore/storage/StorageAreaImpl.cpp | 4 | ||||
-rw-r--r-- | WebCore/storage/StorageEventDispatcher.cpp | 4 | ||||
-rw-r--r-- | WebCore/storage/StorageNamespace.h | 4 | ||||
-rw-r--r-- | WebCore/storage/StorageNamespaceImpl.cpp | 23 | ||||
-rw-r--r-- | WebCore/storage/StorageNamespaceImpl.h | 8 | ||||
-rw-r--r-- | WebKit/android/jni/WebStorage.cpp | 7 |
10 files changed, 163 insertions, 1 deletions
diff --git a/WebCore/page/DOMWindow.cpp b/WebCore/page/DOMWindow.cpp index 17b4c3d..7ea69b5 100644 --- a/WebCore/page/DOMWindow.cpp +++ b/WebCore/page/DOMWindow.cpp @@ -1644,4 +1644,17 @@ void DOMWindow::revokeObjectURL(const String& blobURLString) } #endif +#if ENABLE(DOM_STORAGE) && defined(ANDROID) +void DOMWindow::clearDOMStorage() +{ + if (m_sessionStorage) + m_sessionStorage->disconnectFrame(); + m_sessionStorage = 0; + + if (m_localStorage) + m_localStorage->disconnectFrame(); + m_localStorage = 0; +} +#endif + } // namespace WebCore diff --git a/WebCore/page/DOMWindow.h b/WebCore/page/DOMWindow.h index d0a6cce..0cbac78 100644 --- a/WebCore/page/DOMWindow.h +++ b/WebCore/page/DOMWindow.h @@ -222,6 +222,9 @@ namespace WebCore { // HTML 5 key/value storage Storage* sessionStorage(ExceptionCode&) const; Storage* localStorage(ExceptionCode&) const; +#ifdef ANDROID + void clearDOMStorage(); +#endif #endif Console* console() const; diff --git a/WebCore/page/PageGroup.cpp b/WebCore/page/PageGroup.cpp index 8b902c0..746cd04 100644 --- a/WebCore/page/PageGroup.cpp +++ b/WebCore/page/PageGroup.cpp @@ -40,6 +40,11 @@ #include "ChromiumBridge.h" #endif +#ifdef ANDROID +#include "DOMWindow.h" +#include "FileSystem.h" +#endif + namespace WebCore { static unsigned getUniqueIdentifier() @@ -110,6 +115,91 @@ void PageGroup::closeLocalStorage() #endif } +#if ENABLE(DOM_STORAGE) && defined(ANDROID) +void PageGroup::clearDomStorage() +{ + if (!pageGroups) + return; + + + PageGroupMap::iterator end = pageGroups->end(); + + for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) { + String basePath = ""; + + // This is being called as a result of the user explicitly + // asking to clear all stored data (e.g. through a settings + // dialog. We need a page in the page group to fire a + // StorageEvent. There isn't really a correct page to use + // as the source (as the clear request hasn't come from a + // particular page). One thing we should ensure though is that + // we don't try to clear a private browsing mode page as that has no concept + // of DOM storage.. + + HashSet<Page*> pages = it->second->pages(); + HashSet<Page*>::iterator pagesEnd = pages.end(); + Page* page = 0; + for(HashSet<Page*>::iterator pit = pages.begin(); pit != pagesEnd; ++pit) { + Page* p = *pit; + + // Grab the storage location from an arbitrary page. This is set + // to the same value on all private browsing and "normal" pages, + // so we can get it from anything. + if (basePath.isEmpty()) + basePath = p->settings()->localStorageDatabasePath(); + + // DOM storage is disabled in private browsing pages, so nothing to do if + // this is such a page. + if (p->settings()->privateBrowsingEnabled()) + continue; + + // Clear session storage. + StorageNamespace* sessionStorage = p->sessionStorage(false); + if (sessionStorage) + sessionStorage->clear(p); + + // Save this page so we can clear local storage. + page = p; + } + + // If page is still null at this point, then the only pages that are + // open are private browsing pages. Hence no pages are currently using local + // storage, so we don't need a page pointer to send any events and the + // clear function will handle a 0 input. + it->second->localStorage()->clear(page); + it->second->localStorage()->close(); + + // Closing the storage areas will stop the background thread and so + // we need to remove the local storage ref here so that next time + // we come to a site that uses it the thread will get started again. + it->second->removeLocalStorage(); + + // At this point, active local and session storage have been cleared and the + // StorageAreas for this PageGroup closed. The final sync will have taken + // place. All that is left is to purge the database files. + if (!basePath.isEmpty()) { + Vector<String> files = listDirectory(basePath, "*.localstorage"); + Vector<String>::iterator filesEnd = files.end(); + for (Vector<String>::iterator it = files.begin(); it != filesEnd; ++it) + deleteFile(*it); + } + } +} + +void PageGroup::removeLocalStorage() +{ + HashSet<Page*> pages = this->pages(); + HashSet<Page*>::iterator pagesEnd = pages.end(); + for(HashSet<Page*>::iterator pit = pages.begin(); pit != pagesEnd; ++pit) { + Page* p = *pit; + for (Frame* frame = p->mainFrame(); frame; frame = frame->tree()->traverseNext()) + frame->document()->domWindow()->clearDOMStorage(); + } + + m_localStorage = 0; +} +#endif + void PageGroup::addPage(Page* page) { ASSERT(page); diff --git a/WebCore/page/PageGroup.h b/WebCore/page/PageGroup.h index cc47fba..0c4b26f 100644 --- a/WebCore/page/PageGroup.h +++ b/WebCore/page/PageGroup.h @@ -50,6 +50,10 @@ namespace WebCore { static PageGroup* pageGroup(const String& groupName); static void closeLocalStorage(); +#if ENABLE(DOM_STORAGE) && defined(ANDROID) + static void clearDomStorage(); +#endif + const HashSet<Page*>& pages() const { return m_pages; } void addPage(Page*); @@ -101,6 +105,10 @@ namespace WebCore { private: void addVisitedLink(LinkHash stringHash); void resetUserStyleCacheInAllFrames(); + +#if ENABLE(DOM_STORAGE) && defined(ANDROID) + void removeLocalStorage(); +#endif String m_name; diff --git a/WebCore/storage/StorageAreaImpl.cpp b/WebCore/storage/StorageAreaImpl.cpp index dc25e54..54df135 100644 --- a/WebCore/storage/StorageAreaImpl.cpp +++ b/WebCore/storage/StorageAreaImpl.cpp @@ -95,6 +95,10 @@ StorageAreaImpl::StorageAreaImpl(StorageAreaImpl* area) static bool privateBrowsingEnabled(Frame* frame) { +#if PLATFORM(ANDROID) + if (!frame) + return false; +#endif #if PLATFORM(CHROMIUM) // The frame pointer can be NULL in Chromium since this call is made in a different // process from where the Frame object exists. Luckily, private browseing is diff --git a/WebCore/storage/StorageEventDispatcher.cpp b/WebCore/storage/StorageEventDispatcher.cpp index 5833c59..027e090 100644 --- a/WebCore/storage/StorageEventDispatcher.cpp +++ b/WebCore/storage/StorageEventDispatcher.cpp @@ -40,6 +40,10 @@ namespace WebCore { void StorageEventDispatcher::dispatch(const String& key, const String& oldValue, const String& newValue, StorageType storageType, SecurityOrigin* securityOrigin, Frame* sourceFrame) { +#ifdef ANDROID + if (!sourceFrame) + return; +#endif Page* page = sourceFrame->page(); if (!page) return; diff --git a/WebCore/storage/StorageNamespace.h b/WebCore/storage/StorageNamespace.h index 8f09b1a..f7dad1e 100644 --- a/WebCore/storage/StorageNamespace.h +++ b/WebCore/storage/StorageNamespace.h @@ -50,6 +50,10 @@ public: virtual PassRefPtr<StorageNamespace> copy() = 0; virtual void close() = 0; virtual void unlock() = 0; + +#ifdef ANDROID + virtual void clear(Page*) = 0; +#endif }; } // namespace WebCore diff --git a/WebCore/storage/StorageNamespaceImpl.cpp b/WebCore/storage/StorageNamespaceImpl.cpp index 3a21489..68508a7 100644 --- a/WebCore/storage/StorageNamespaceImpl.cpp +++ b/WebCore/storage/StorageNamespaceImpl.cpp @@ -35,6 +35,10 @@ #include <wtf/StdLibExtras.h> #include <wtf/text/StringHash.h> +#ifdef ANDROID +#include "Page.h" +#endif + namespace WebCore { typedef HashMap<String, StorageNamespace*> LocalStorageNamespaceMap; @@ -139,6 +143,25 @@ void StorageNamespaceImpl::close() m_isShutdown = true; } +#ifdef ANDROID +void StorageNamespaceImpl::clear(Page* page) +{ + ASSERT(isMainThread()); + if (m_isShutdown) + return; + + // Clear all the keys for each of the storage areas. + StorageAreaMap::iterator end = m_storageAreaMap.end(); + for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it) { + // if there is no page provided, then the user tried to clear storage + // with only pages in private browsing mode open. So we do not need to + // provide a Frame* here (as the frame is only used to dispatch storage events + // and private browsing pages won't be using them). + it->second->clear(page ? page->mainFrame() : 0); + } +} +#endif + void StorageNamespaceImpl::unlock() { // Because there's a single event loop per-process, this is a no-op. diff --git a/WebCore/storage/StorageNamespaceImpl.h b/WebCore/storage/StorageNamespaceImpl.h index 5221add..c2361fa 100644 --- a/WebCore/storage/StorageNamespaceImpl.h +++ b/WebCore/storage/StorageNamespaceImpl.h @@ -37,7 +37,9 @@ #include <wtf/RefPtr.h> namespace WebCore { - +#ifdef ANDROID + class Page; +#endif class StorageAreaImpl; class StorageNamespaceImpl : public StorageNamespace { @@ -51,6 +53,10 @@ namespace WebCore { virtual void close(); virtual void unlock(); +#ifdef ANDROID + virtual void clear(Page*); +#endif + private: StorageNamespaceImpl(StorageType, const String& path, unsigned quota); diff --git a/WebKit/android/jni/WebStorage.cpp b/WebKit/android/jni/WebStorage.cpp index ebe840b..ca3ccc6 100644 --- a/WebKit/android/jni/WebStorage.cpp +++ b/WebKit/android/jni/WebStorage.cpp @@ -29,6 +29,7 @@ #include "JavaSharedClient.h" #include "KURL.h" +#include "PageGroup.h" #include "WebCoreJni.h" #include <JNIHelp.h> @@ -137,6 +138,12 @@ static void DeleteAllData(JNIEnv* env, jobject obj) int size = manifestUrls.size(); for (int i = 0; i < size; ++i) WebCore::cacheStorage().deleteCacheGroup(manifestUrls[i]); + + // FIXME: this is a workaround for eliminating any DOM Storage data (both + // session and local storage) as there is no functionality inside WebKit at the + // moment to do it. That functionality is a WIP in https://bugs.webkit.org/show_bug.cgi?id=51878 + // and when that patch lands and we merge it, we should move towards that approach instead. + WebCore::PageGroup::clearDomStorage(); } static void SetAppCacheMaximumSize(JNIEnv* env, jobject obj, unsigned long long size) |