OSDN Git Service

Clear DOM storage when clearing other cached data. Do not merge.
authorBen Murdoch <benm@google.com>
Mon, 11 Apr 2011 19:08:03 +0000 (20:08 +0100)
committerBen Murdoch <benm@google.com>
Mon, 11 Apr 2011 19:35:41 +0000 (20:35 +0100)
Empty out DOM local and session storage in addition to HTML5
database and app cache when we get a request from java to
delete cached data.

Cherry pick of I5b6ee075d2a8fb44ee373ad4462a33623c9c2460

Bug: 4267038

Change-Id: Id2dece1963d443c3758710e9c3e871054991ae32

WebCore/page/DOMWindow.cpp
WebCore/page/DOMWindow.h
WebCore/page/PageGroup.cpp
WebCore/page/PageGroup.h
WebCore/storage/StorageAreaImpl.cpp
WebCore/storage/StorageEventDispatcher.cpp
WebCore/storage/StorageNamespace.h
WebCore/storage/StorageNamespaceImpl.cpp
WebCore/storage/StorageNamespaceImpl.h
WebKit/android/jni/WebStorage.cpp

index 2f0f84f..a004059 100644 (file)
@@ -1406,4 +1406,17 @@ EventTargetData* DOMWindow::ensureEventTargetData()
     return &m_eventTargetData;
 }
 
+#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
index dc1e68c..ee7af7f 100644 (file)
@@ -205,6 +205,9 @@ namespace WebCore {
         // HTML 5 key/value storage
         Storage* sessionStorage() const;
         Storage* localStorage() const;
+#ifdef ANDROID
+        void clearDOMStorage();
+#endif
 #endif
 
         Console* console() const;
index f376d52..b4758c5 100644 (file)
 #include "ChromiumBridge.h"
 #endif
 
+#ifdef ANDROID
+#include "DOMWindow.h"
+#include "FileSystem.h"
+#endif
+
 namespace WebCore {
 
 static unsigned getUniqueIdentifier()
@@ -109,6 +114,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);
index 446f0c7..cd2d9e3 100644 (file)
@@ -48,6 +48,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*);
@@ -90,6 +94,10 @@ namespace WebCore {
     private:
         void addVisitedLink(LinkHash stringHash);
 
+#if ENABLE(DOM_STORAGE) && defined(ANDROID)
+        void removeLocalStorage();
+#endif
+
         String m_name;
 
         HashSet<Page*> m_pages;
index aa04781..d5d75e7 100644 (file)
@@ -93,6 +93,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
index dc0295b..aa91924 100644 (file)
@@ -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;
index e84e5a6..e911c94 100644 (file)
@@ -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
index 19ff6b4..47b2958 100644 (file)
 #include "StorageSyncManager.h"
 #include <wtf/StdLibExtras.h>
 
+#ifdef ANDROID
+#include "Page.h"
+#endif
+
 namespace WebCore {
 
 typedef HashMap<String, StorageNamespace*> LocalStorageNamespaceMap;
@@ -137,6 +141,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.
index b81b55a..8199eab 100644 (file)
@@ -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);
 
index 37792f6..d374875 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "JavaSharedClient.h"
 #include "KURL.h"
+#include "PageGroup.h"
 #include "WebCoreJni.h"
 
 #include <JNIHelp.h>
@@ -130,6 +131,11 @@ static void DeleteAllData(JNIEnv* env, jobject obj)
 {
     WebCore::DatabaseTracker::tracker().deleteAllDatabases();
     WebCore::cacheStorage().empty();
+    // 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)