Clone storage namespaces for window.open
authorandersca@apple.com <andersca@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 17 Apr 2013 00:38:50 +0000 (00:38 +0000)
committerandersca@apple.com <andersca@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 17 Apr 2013 00:38:50 +0000 (00:38 +0000)
https://bugs.webkit.org/show_bug.cgi?id=114703

Reviewed by Sam Weinig.

Source/WebCore:

Pass the new page to StorageNamespace::copy.

* page/Chrome.cpp:
(WebCore::Chrome::createWindow):
* storage/StorageNamespace.h:
(StorageNamespace):
* storage/StorageNamespaceImpl.cpp:
(WebCore::StorageNamespaceImpl::copy):
* storage/StorageNamespaceImpl.h:
(WebCore):
(StorageNamespaceImpl):

Source/WebKit2:

* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::StorageArea::clone):
New helper function for cloning a storage area.

(WebKit::StorageManager::StorageArea::setItem):
Correctly handle the copy-on-write feature of StorageMap if it has multiple storage areas pointing to it.

(WebKit::StorageManager::StorageArea::removeItem):
Ditto.

(WebKit::StorageManager::SessionStorageNamespace::cloneTo):
Add cloned storage areas.

* WebProcess/Storage/StorageNamespaceImpl.cpp:
(WebKit::StorageNamespaceImpl::copy):
Create a new session storage namespace for the new page.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@148585 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/page/Chrome.cpp
Source/WebCore/storage/StorageNamespace.h
Source/WebCore/storage/StorageNamespaceImpl.cpp
Source/WebCore/storage/StorageNamespaceImpl.h
Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/Storage/StorageManager.cpp
Source/WebKit2/WebProcess/Storage/StorageNamespaceImpl.cpp
Source/WebKit2/WebProcess/Storage/StorageNamespaceImpl.h

index f7802cd..ec70a5a 100644 (file)
@@ -1,3 +1,22 @@
+2013-04-16  Anders Carlsson  <andersca@apple.com>
+
+        Clone storage namespaces for window.open
+        https://bugs.webkit.org/show_bug.cgi?id=114703
+
+        Reviewed by Sam Weinig.
+
+        Pass the new page to StorageNamespace::copy.
+
+        * page/Chrome.cpp:
+        (WebCore::Chrome::createWindow):
+        * storage/StorageNamespace.h:
+        (StorageNamespace):
+        * storage/StorageNamespaceImpl.cpp:
+        (WebCore::StorageNamespaceImpl::copy):
+        * storage/StorageNamespaceImpl.h:
+        (WebCore):
+        (StorageNamespaceImpl):
+
 2013-04-16  Sam Weinig  <sam@webkit.org>
 
         Fix fallout after r148545.
index 85a9755..07959d0 100644 (file)
@@ -190,11 +190,11 @@ void Chrome::focusedFrameChanged(Frame* frame) const
 Page* Chrome::createWindow(Frame* frame, const FrameLoadRequest& request, const WindowFeatures& features, const NavigationAction& action) const
 {
     Page* newPage = m_client->createWindow(frame, request, features, action);
+    if (!newPage)
+        return 0;
 
-    if (newPage) {
-        if (StorageNamespace* oldSessionStorage = m_page->sessionStorage(false))
-            newPage->setSessionStorage(oldSessionStorage->copy());
-    }
+    if (StorageNamespace* oldSessionStorage = m_page->sessionStorage(false))
+        newPage->setSessionStorage(oldSessionStorage->copy(newPage));
 
     return newPage;
 }
index 0bc5116..39dbde0 100644 (file)
@@ -43,7 +43,7 @@ public:
 
     virtual ~StorageNamespace() { }
     virtual PassRefPtr<StorageArea> storageArea(PassRefPtr<SecurityOrigin>) = 0;
-    virtual PassRefPtr<StorageNamespace> copy() = 0;
+    virtual PassRefPtr<StorageNamespace> copy(Page* newPage) = 0;
     virtual void close() = 0;
     virtual void clearOriginForDeletion(SecurityOrigin*) = 0;
     virtual void clearAllOriginsForDeletion() = 0;
index 6bd9f40..c66016f 100644 (file)
@@ -87,7 +87,7 @@ StorageNamespaceImpl::~StorageNamespaceImpl()
         close();
 }
 
-PassRefPtr<StorageNamespace> StorageNamespaceImpl::copy()
+PassRefPtr<StorageNamespace> StorageNamespaceImpl::copy(Page*)
 {
     ASSERT(isMainThread());
     ASSERT(!m_isShutdown);
index 04d35b4..5c044ce 100644 (file)
 
 namespace WebCore {
 
-    class StorageAreaImpl;
+class StorageAreaImpl;
 
-    class StorageNamespaceImpl : public StorageNamespace {
-    public:
-        static PassRefPtr<StorageNamespace> localStorageNamespace(const String& path, unsigned quota);
-        static PassRefPtr<StorageNamespace> sessionStorageNamespace(unsigned quota);
+class StorageNamespaceImpl : public StorageNamespace {
+public:
+    static PassRefPtr<StorageNamespace> localStorageNamespace(const String& path, unsigned quota);
+    static PassRefPtr<StorageNamespace> sessionStorageNamespace(unsigned quota);
+    virtual ~StorageNamespaceImpl();
 
-        virtual ~StorageNamespaceImpl();
-        virtual PassRefPtr<StorageArea> storageArea(PassRefPtr<SecurityOrigin>);
-        virtual PassRefPtr<StorageNamespace> copy();
-        virtual void close();
+    virtual PassRefPtr<StorageArea> storageArea(PassRefPtr<SecurityOrigin>)  OVERRIDE;
+    virtual PassRefPtr<StorageNamespace> copy(Page* newPage) OVERRIDE;
+    virtual void close() OVERRIDE;
 
-        // Not removing the origin's StorageArea from m_storageAreaMap because
-        // we're just deleting the underlying db file. If an item is added immediately
-        // after file deletion, we want the same StorageArea to eventually trigger
-        // a sync and for StorageAreaSync to recreate the backing db file.
-        virtual void clearOriginForDeletion(SecurityOrigin*);
-        virtual void clearAllOriginsForDeletion();
-        virtual void sync();
-        virtual void closeIdleLocalStorageDatabases();
+    // Not removing the origin's StorageArea from m_storageAreaMap because
+    // we're just deleting the underlying db file. If an item is added immediately
+    // after file deletion, we want the same StorageArea to eventually trigger
+    // a sync and for StorageAreaSync to recreate the backing db file.
+    virtual void clearOriginForDeletion(SecurityOrigin*) OVERRIDE;
+    virtual void clearAllOriginsForDeletion() OVERRIDE;
+    virtual void sync() OVERRIDE;
+    virtual void closeIdleLocalStorageDatabases() OVERRIDE;
 
-    private:
-        StorageNamespaceImpl(StorageType, const String& path, unsigned quota);
+private:
+    StorageNamespaceImpl(StorageType, const String& path, unsigned quota);
 
-        typedef HashMap<RefPtr<SecurityOrigin>, RefPtr<StorageAreaImpl> > StorageAreaMap;
-        StorageAreaMap m_storageAreaMap;
+    typedef HashMap<RefPtr<SecurityOrigin>, RefPtr<StorageAreaImpl> > StorageAreaMap;
+    StorageAreaMap m_storageAreaMap;
 
-        StorageType m_storageType;
+    StorageType m_storageType;
 
-        // Only used if m_storageType == LocalStorage and the path was not "" in our constructor.
-        String m_path;
-        RefPtr<StorageSyncManager> m_syncManager;
+    // Only used if m_storageType == LocalStorage and the path was not "" in our constructor.
+    String m_path;
+    RefPtr<StorageSyncManager> m_syncManager;
 
-        unsigned m_quota;  // The default quota for each new storage area.
-        bool m_isShutdown;
-    };
+    // The default quota for each new storage area.
+    unsigned m_quota;
+
+    bool m_isShutdown;
+};
 
 } // namespace WebCore
 
index 51c4b0c..0b16d72 100644 (file)
@@ -1,3 +1,27 @@
+2013-04-16  Anders Carlsson  <andersca@apple.com>
+
+        Clone storage namespaces for window.open
+        https://bugs.webkit.org/show_bug.cgi?id=114703
+
+        Reviewed by Sam Weinig.
+
+        * UIProcess/Storage/StorageManager.cpp:
+        (WebKit::StorageManager::StorageArea::clone):
+        New helper function for cloning a storage area.
+
+        (WebKit::StorageManager::StorageArea::setItem):
+        Correctly handle the copy-on-write feature of StorageMap if it has multiple storage areas pointing to it.
+
+        (WebKit::StorageManager::StorageArea::removeItem):
+        Ditto.
+
+        (WebKit::StorageManager::SessionStorageNamespace::cloneTo):
+        Add cloned storage areas.
+
+        * WebProcess/Storage/StorageNamespaceImpl.cpp:
+        (WebKit::StorageNamespaceImpl::copy):
+        Create a new session storage namespace for the new page.
+
 2013-04-16  Beth Dakin  <bdakin@apple.com>
 
         Need a new layout milestone to notify bundle clients when the header has been 
index 0b1700a..ef8f027 100644 (file)
@@ -46,6 +46,8 @@ public:
     void addListener(CoreIPC::Connection*, uint64_t storageMapID);
     void removeListener(CoreIPC::Connection*, uint64_t storageMapID);
 
+    PassRefPtr<StorageArea> clone() const;
+
     void setItem(CoreIPC::Connection* sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& value, const String& urlString, bool& quotaException);
     void removeItem(CoreIPC::Connection* sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& urlString);
     void clear(CoreIPC::Connection* sourceConnection, uint64_t sourceStorageAreaID, const String& urlString);
@@ -90,12 +92,21 @@ void StorageManager::StorageArea::removeListener(CoreIPC::Connection* connection
     m_eventListeners.remove(std::make_pair(connection, storageMapID));
 }
 
-void StorageManager::StorageArea::setItem(CoreIPC::Connection* sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& value, const String& urlString, bool& quotaException)
+PassRefPtr<StorageManager::StorageArea> StorageManager::StorageArea::clone() const
 {
-    ASSERT(m_storageMap->hasOneRef());
+    RefPtr<StorageArea> storageArea = StorageArea::create(m_quotaInBytes);
+    storageArea->m_storageMap = m_storageMap;
+
+    return storageArea.release();
+}
 
+void StorageManager::StorageArea::setItem(CoreIPC::Connection* sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& value, const String& urlString, bool& quotaException)
+{
     String oldValue;
-    m_storageMap->setItem(key, value, oldValue, quotaException);
+
+    RefPtr<StorageMap> newStorageMap = m_storageMap->setItem(key, value, oldValue, quotaException);
+    if (newStorageMap)
+        m_storageMap = newStorageMap.release();
 
     if (!quotaException)
         dispatchEvents(sourceConnection, sourceStorageAreaID, key, oldValue, value, urlString);
@@ -104,7 +115,9 @@ void StorageManager::StorageArea::setItem(CoreIPC::Connection* sourceConnection,
 void StorageManager::StorageArea::removeItem(CoreIPC::Connection* sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& urlString)
 {
     String oldValue;
-    m_storageMap->removeItem(key, oldValue);
+    RefPtr<StorageMap> newStorageMap = m_storageMap->removeItem(key, oldValue);
+    if (newStorageMap)
+        m_storageMap = newStorageMap.release();
 
     if (oldValue.isNull())
         return;
@@ -188,7 +201,8 @@ void StorageManager::SessionStorageNamespace::cloneTo(SessionStorageNamespace& n
 {
     ASSERT_UNUSED(newSessionStorageNamespace, newSessionStorageNamespace.isEmpty());
 
-    // FIXME: Implement.
+    for (HashMap<RefPtr<SecurityOrigin>, RefPtr<StorageArea> >::const_iterator it = m_storageAreaMap.begin(), end = m_storageAreaMap.end(); it != end; ++it)
+        newSessionStorageNamespace.m_storageAreaMap.add(it->key, it->value->clone());
 }
 
 PassRefPtr<StorageManager> StorageManager::create()
index 86cca5d..9a48d12 100644 (file)
@@ -60,11 +60,11 @@ PassRefPtr<StorageArea> StorageNamespaceImpl::storageArea(PassRefPtr<SecurityOri
     return StorageAreaImpl::create(result.iterator->value);
 }
 
-PassRefPtr<StorageNamespace> StorageNamespaceImpl::copy()
+PassRefPtr<StorageNamespace> StorageNamespaceImpl::copy(Page* newPage)
 {
-    // FIXME: Implement this.
-    ASSERT_NOT_REACHED();
-    return 0;
+    ASSERT(m_storageNamespaceID);
+
+    return createSessionStorageNamespace(WebPage::fromCorePage(newPage));
 }
 
 void StorageNamespaceImpl::close()
index 6cb74ae..e59af3b 100644 (file)
@@ -48,7 +48,7 @@ private:
     explicit StorageNamespaceImpl(uint64_t storageNamespaceID, unsigned quotaInBytes);
 
     virtual PassRefPtr<WebCore::StorageArea> storageArea(PassRefPtr<WebCore::SecurityOrigin>) OVERRIDE;
-    virtual PassRefPtr<WebCore::StorageNamespace> copy() OVERRIDE;
+    virtual PassRefPtr<WebCore::StorageNamespace> copy(WebCore::Page*) OVERRIDE;
     virtual void close() OVERRIDE;
     virtual void clearOriginForDeletion(WebCore::SecurityOrigin*) OVERRIDE;
     virtual void clearAllOriginsForDeletion() OVERRIDE;