Commit 21c04acd authored by beidson@apple.com's avatar beidson@apple.com

WebCore:

2008-04-14  Brady Eidson  <beidson@apple.com>

        Reviewed by Anders

        Lay the underpinnings for LocalStorage.

        For now, this just exposes window.localStorage to the dom which returns an in-memory Storage object, much
        like SessionStorage.  The primary difference at this point is that the object returned is shared globally,
        and isn't copied for new top-level browsing contexts like SessionStorage.

        Later, I'll add proper event dispatch and a persistent storage backing.

        * GNUmakefile.am:
        * WebCore.base.exp:
        * WebCore.pro:
        * WebCore.vcproj/WebCore.vcproj:
        * WebCore.xcodeproj/project.pbxproj:
        * WebCoreSources.bkl:

        * bindings/js/JSDOMWindowCustom.cpp:
        (WebCore::JSDOMWindow::mark): Mark the optionalLocalStorage

        * page/DOMWindow.cpp:
        (WebCore::DOMWindow::clear):
        (WebCore::DOMWindow::localStorage):
        * page/DOMWindow.h:
        (WebCore::DOMWindow::optionalLocalStorage):

        * storage/LocalStorage.cpp: Added.
        (WebCore::LocalStorage::sharedLocalStorage):
        (WebCore::LocalStorage::LocalStorage):
        (WebCore::LocalStorage::storageArea):
        (WebCore::LocalStorage::itemChanged):
        (WebCore::LocalStorage::itemRemoved):
        (WebCore::LocalStorage::dispatchStorageEvent):
        * storage/LocalStorage.h: Added.

        * storage/SessionStorage.cpp: Refactor to use the client interface for event dispatching for sessionStorage objects
        (WebCore::SessionStorage::SessionStorage):
        (WebCore::SessionStorage::copy):
        (WebCore::SessionStorage::storageArea):
        (WebCore::SessionStorage::itemChanged):
        (WebCore::SessionStorage::itemRemoved):
        (WebCore::SessionStorage::dispatchStorageEvent):
        * storage/SessionStorage.h:

        * storage/StorageArea.cpp: Add a client parameter, and call to the client when an item is changed or removed.
        (WebCore::StorageArea::create):
        (WebCore::StorageArea::StorageArea):
        (WebCore::StorageArea::copy):
        (WebCore::StorageArea::setItem):
        (WebCore::StorageArea::removeItem):
        (WebCore::StorageArea::setClient):
        * storage/StorageArea.h:
        (WebCore::StorageArea::page):
        (WebCore::StorageArea::securityOrigin):

        * storage/StorageAreaClient.h: Added.  Break out "itemChanged" and "itemRemoved" to a StorageAreaClient
          This way, both SessionStorage and LocalStorage areas can have different behavior on changes with
          that behavior managed from a central location.
        (WebCore::StorageAreaClient::~StorageAreaClient):
        (WebCore::StorageAreaClient::StorageAreaClient):
        (WebCore::StorageAreaClient::itemChanged):
        (WebCore::StorageAreaClient::itemRemoved):

LayoutTests:

2008-04-14  Brady Eidson  <beidson@apple.com>

        Reviewed by Anders

        As underpinnings for LocalStorage are laid, it is exposed to the dom - update the relevant layout tests.

        * fast/dom/Window/window-properties-expected.txt:
        * storage/domstorage/window-attributes-exist-expected.txt:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@31893 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent af2e011f
2008-04-14 Brady Eidson <beidson@apple.com>
Reviewed by Anders
As underpinnings for LocalStorage are laid, it is exposed to the dom - update the relevant layout tests.
* fast/dom/Window/window-properties-expected.txt:
* storage/domstorage/window-attributes-exist-expected.txt:
2008-04-14 Julien Chaffraix <jchaffraix@webkit.org>
Reviewed by Ap.
......@@ -1265,7 +1265,7 @@ window.history.length [number]
window.innerHeight [number]
window.innerWidth [number]
window.length [number]
window.localStorage [null]
window.localStorage [printed above as window.Storage.prototype]
window.location [object Location]
window.location.assign [function]
window.location.hash [string]
......
......@@ -5,5 +5,10 @@ Storage object sessionStorage has key
Storage object sessionStorage has getItem
Storage object sessionStorage has setItem
Storage object sessionStorage has removeItem
window.localStorage DOES NOT exist
window.localStorage exists
Storage object localStorage has length
Storage object localStorage has key
Storage object localStorage has getItem
Storage object localStorage has setItem
Storage object localStorage has removeItem
2008-04-14 Brady Eidson <beidson@apple.com>
Reviewed by Anders
Lay the underpinnings for LocalStorage.
For now, this just exposes window.localStorage to the dom which returns an in-memory Storage object, much
like SessionStorage. The primary difference at this point is that the object returned is shared globally,
and isn't copied for new top-level browsing contexts like SessionStorage.
Later, I'll add proper event dispatch and a persistent storage backing.
* GNUmakefile.am:
* WebCore.base.exp:
* WebCore.pro:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* WebCoreSources.bkl:
* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::JSDOMWindow::mark): Mark the optionalLocalStorage
* page/DOMWindow.cpp:
(WebCore::DOMWindow::clear):
(WebCore::DOMWindow::localStorage):
* page/DOMWindow.h:
(WebCore::DOMWindow::optionalLocalStorage):
* storage/LocalStorage.cpp: Added.
(WebCore::LocalStorage::sharedLocalStorage):
(WebCore::LocalStorage::LocalStorage):
(WebCore::LocalStorage::storageArea):
(WebCore::LocalStorage::itemChanged):
(WebCore::LocalStorage::itemRemoved):
(WebCore::LocalStorage::dispatchStorageEvent):
* storage/LocalStorage.h: Added.
* storage/SessionStorage.cpp: Refactor to use the client interface for event dispatching for sessionStorage objects
(WebCore::SessionStorage::SessionStorage):
(WebCore::SessionStorage::copy):
(WebCore::SessionStorage::storageArea):
(WebCore::SessionStorage::itemChanged):
(WebCore::SessionStorage::itemRemoved):
(WebCore::SessionStorage::dispatchStorageEvent):
* storage/SessionStorage.h:
* storage/StorageArea.cpp: Add a client parameter, and call to the client when an item is changed or removed.
(WebCore::StorageArea::create):
(WebCore::StorageArea::StorageArea):
(WebCore::StorageArea::copy):
(WebCore::StorageArea::setItem):
(WebCore::StorageArea::removeItem):
(WebCore::StorageArea::setClient):
* storage/StorageArea.h:
(WebCore::StorageArea::page):
(WebCore::StorageArea::securityOrigin):
* storage/StorageAreaClient.h: Added. Break out "itemChanged" and "itemRemoved" to a StorageAreaClient
This way, both SessionStorage and LocalStorage areas can have different behavior on changes with
that behavior managed from a central location.
(WebCore::StorageAreaClient::~StorageAreaClient):
(WebCore::StorageAreaClient::StorageAreaClient):
(WebCore::StorageAreaClient::itemChanged):
(WebCore::StorageAreaClient::itemRemoved):
2008-04-14 Brady Eidson <beidson@apple.com>
Reviewed by Anders
......@@ -1197,6 +1197,7 @@ webcore_cppflags += \
-I$(top_srcdir)/WebCore/storage
webcore_sources += \
WebCore/storage/LocalStorage.cpp \
WebCore/storage/Storage.cpp \
WebCore/storage/StorageArea.cpp \
WebCore/storage/StorageEvent.cpp \
......
......@@ -556,6 +556,7 @@ __ZN7WebCore8Settings27setFTPDirectoryTemplatePathERKNS_6StringE
__ZN7WebCore8Settings27setLoadsImagesAutomaticallyEb
__ZN7WebCore8Settings28setForceFTPDirectoryListingsEb
__ZN7WebCore8Settings29setAuthorAndUserStylesEnabledEb
__ZN7WebCore8Settings29setWebArchiveDebugModeEnabledEb
__ZN7WebCore8Settings31setShrinksStandaloneImagesToFitEb
__ZN7WebCore8Settings32setNeedsAdobeFrameReloadingQuirkEb
__ZN7WebCore8Settings40setJavaScriptCanOpenWindowsAutomaticallyEb
......
......@@ -1214,8 +1214,9 @@ contains(DEFINES, ENABLE_DOM_STORAGE=1) {
FEATURE_DEFINES_JAVASCRIPT += ENABLE_DOM_STORAGE =1
SOURCES += \
storage/LocalStorage.cpp \
storage/Storage.cpp \
storage/StorageArea.cpp \
storage/StorageArea.cpp \
storage/StorageEvent.cpp \
storage/StorageMap.cpp \
storage/SessionStorage.cpp \
......
......@@ -15846,6 +15846,14 @@
RelativePath="..\storage\DatabaseTracker.h"
>
</File>
<File
RelativePath="..\storage\LocalStorage.cpp"
>
</File>
<File
RelativePath="..\storage\LocalStorage.h"
>
</File>
<File
RelativePath="..\storage\OriginQuotaManager.cpp"
>
......@@ -15942,6 +15950,10 @@
RelativePath="..\storage\StorageArea.h"
>
</File>
<File
RelativePath="..\storage\StorageAreaClient.h"
>
</File>
<File
RelativePath="..\storage\StorageEvent.cpp"
>
......
......@@ -495,6 +495,9 @@
51B2417B0D931F3F00E83F5C /* LegacyWebArchiveMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51B2417A0D931F3F00E83F5C /* LegacyWebArchiveMac.mm */; };
51BE37DF0DAEE00E001085FC /* StorageArea.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51BE37DD0DAEE00E001085FC /* StorageArea.cpp */; };
51BE37E00DAEE00E001085FC /* StorageArea.h in Headers */ = {isa = PBXBuildFile; fileRef = 51BE37DE0DAEE00E001085FC /* StorageArea.h */; };
51BE38280DAEF7DA001085FC /* LocalStorage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51BE38260DAEF7DA001085FC /* LocalStorage.cpp */; };
51BE38290DAEF7DA001085FC /* LocalStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 51BE38270DAEF7DA001085FC /* LocalStorage.h */; };
51BE382C0DAEF7F3001085FC /* StorageAreaClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 51BE382B0DAEF7F3001085FC /* StorageAreaClient.h */; };
51C81B890C4422F70019ECE3 /* FTPDirectoryParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51C81B870C4422F70019ECE3 /* FTPDirectoryParser.cpp */; };
51C81B8A0C4422F70019ECE3 /* FTPDirectoryParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 51C81B880C4422F70019ECE3 /* FTPDirectoryParser.h */; };
51CBFC990D10E483002DBF51 /* CachedPagePlatformData.h in Headers */ = {isa = PBXBuildFile; fileRef = 51CBFC980D10E483002DBF51 /* CachedPagePlatformData.h */; settings = {ATTRIBUTES = (Private, ); }; };
......@@ -4922,6 +4925,9 @@
51B2417A0D931F3F00E83F5C /* LegacyWebArchiveMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LegacyWebArchiveMac.mm; sourceTree = "<group>"; };
51BE37DD0DAEE00E001085FC /* StorageArea.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StorageArea.cpp; sourceTree = "<group>"; };
51BE37DE0DAEE00E001085FC /* StorageArea.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageArea.h; sourceTree = "<group>"; };
51BE38260DAEF7DA001085FC /* LocalStorage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LocalStorage.cpp; sourceTree = "<group>"; };
51BE38270DAEF7DA001085FC /* LocalStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalStorage.h; sourceTree = "<group>"; };
51BE382B0DAEF7F3001085FC /* StorageAreaClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageAreaClient.h; sourceTree = "<group>"; };
51C81B870C4422F70019ECE3 /* FTPDirectoryParser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FTPDirectoryParser.cpp; sourceTree = "<group>"; };
51C81B880C4422F70019ECE3 /* FTPDirectoryParser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FTPDirectoryParser.h; sourceTree = "<group>"; };
51CBFC980D10E483002DBF51 /* CachedPagePlatformData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedPagePlatformData.h; sourceTree = "<group>"; };
......@@ -8512,6 +8518,8 @@
1AD51A130CB59CD300953D11 /* DatabaseTracker.cpp */,
1AD51A120CB59CD300953D11 /* DatabaseTracker.h */,
51FAFE330CECBF2D00BB3F24 /* DatabaseTrackerClient.h */,
51BE38260DAEF7DA001085FC /* LocalStorage.cpp */,
51BE38270DAEF7DA001085FC /* LocalStorage.h */,
51A926780D53F0570063ECC2 /* OriginQuotaManager.cpp */,
51A926790D53F0570063ECC2 /* OriginQuotaManager.h */,
51A9267A0D53F0570063ECC2 /* OriginUsageRecord.cpp */,
......@@ -8542,6 +8550,7 @@
51E3F9D10DA05D7100250911 /* Storage.idl */,
51BE37DD0DAEE00E001085FC /* StorageArea.cpp */,
51BE37DE0DAEE00E001085FC /* StorageArea.h */,
51BE382B0DAEF7F3001085FC /* StorageAreaClient.h */,
51E0BABA0DA5547100A9E417 /* StorageEvent.cpp */,
51E0BAB90DA5547100A9E417 /* StorageEvent.h */,
51E0BABD0DA5548400A9E417 /* StorageEvent.idl */,
......@@ -14818,6 +14827,8 @@
BC53C5F50DA56B920021EB5D /* Gradient.h in Headers */,
BC53C6920DA591140021EB5D /* CSSGradientValue.h in Headers */,
51BE37E00DAEE00E001085FC /* StorageArea.h in Headers */,
51BE38290DAEF7DA001085FC /* LocalStorage.h in Headers */,
51BE382C0DAEF7F3001085FC /* StorageAreaClient.h in Headers */,
BC23EE920DAED2BC009FDC91 /* CSSImageGeneratorValue.h in Headers */,
BC23F0DB0DAFF4A4009FDC91 /* GeneratedImage.h in Headers */,
BCE04C8A0DAFF7A0007A0F41 /* Generator.h in Headers */,
......@@ -16511,6 +16522,7 @@
4B24F9A80DA7050B00269E58 /* AXObjectCache.cpp in Sources */,
51D0C5160DAA90B7003B3831 /* JSStorageCustom.cpp in Sources */,
51BE37DF0DAEE00E001085FC /* StorageArea.cpp in Sources */,
51BE38280DAEF7DA001085FC /* LocalStorage.cpp in Sources */,
BC23E4E10DAACE0F009FDC91 /* CSSGradientValue.cpp in Sources */,
BC23E76C0DAE88A9009FDC91 /* CSSImageGeneratorValue.cpp in Sources */,
BCE04C940DAFF902007A0F41 /* GeneratedImage.cpp in Sources */,
......@@ -798,6 +798,7 @@ This file contains the list of files needed to build WebCore.
storage/DatabaseTask.cpp
storage/DatabaseThread.cpp
storage/DatabaseTracker.cpp
storage/LocalStorage.cpp
storage/OriginQuotaManager.cpp
storage/OriginUsageRecord.cpp
storage/SQLResultSet.cpp
......
......@@ -63,6 +63,7 @@ void JSDOMWindow::mark()
markDOMObjectWrapper(impl()->optionalLocation());
#if ENABLE(DOM_STORAGE)
markDOMObjectWrapper(impl()->optionalSessionStorage());
markDOMObjectWrapper(impl()->optionalLocalStorage());
#endif
}
......
......@@ -42,6 +42,7 @@
#include "FrameView.h"
#include "HTMLFrameOwnerElement.h"
#include "History.h"
#include "LocalStorage.h"
#include "Location.h"
#include "Navigator.h"
#include "Page.h"
......@@ -179,6 +180,10 @@ void DOMWindow::clear()
if (m_sessionStorage)
m_sessionStorage->disconnectFrame();
m_sessionStorage = 0;
if (m_localStorage)
m_localStorage->disconnectFrame();
m_localStorage = 0;
#endif
}
......@@ -280,8 +285,13 @@ Storage* DOMWindow::sessionStorage() const
Storage* DOMWindow::localStorage() const
{
// FIXME: When implementing LocalStorage, return appropriate object from a centralized "LocalStorage repository"
return 0;
Document* document = this->document();
if (!document)
return 0;
RefPtr<StorageArea> storageArea = LocalStorage::sharedLocalStorage().storageArea(document->securityOrigin());
m_localStorage = Storage::create(m_frame, storageArea.release());
return m_localStorage.get();
}
#endif
......
......@@ -186,6 +186,7 @@ namespace WebCore {
Location* optionalLocation() const { return m_location.get(); }
#if ENABLE(DOM_STORAGE)
Storage* optionalSessionStorage() const { return m_sessionStorage.get(); }
Storage* optionalLocalStorage() const { return m_sessionStorage.get(); }
#endif
private:
......@@ -206,6 +207,7 @@ namespace WebCore {
mutable RefPtr<Location> m_location;
#if ENABLE(DOM_STORAGE)
mutable RefPtr<Storage> m_sessionStorage;
mutable RefPtr<Storage> m_localStorage;
#endif
};
......
/*
* 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 "LocalStorage.h"
#include "StorageArea.h"
namespace WebCore {
LocalStorage& LocalStorage::sharedLocalStorage()
{
static LocalStorage* sharedLocalStorage = 0;
if (!sharedLocalStorage)
sharedLocalStorage = new LocalStorage();
return *sharedLocalStorage;
}
LocalStorage::LocalStorage()
{
}
PassRefPtr<StorageArea> LocalStorage::storageArea(SecurityOrigin* origin)
{
RefPtr<StorageArea> storageArea;
if (storageArea = m_storageAreaMap.get(origin))
return storageArea.release();
storageArea = StorageArea::create(origin, 0, this);
m_storageAreaMap.set(origin, storageArea);
return storageArea.release();
}
void LocalStorage::itemChanged(StorageArea* area, const String& key, const String& oldValue, const String& newValue, Frame* sourceFrame)
{
// FIXME: Flag this change to be written out to the persistent store
dispatchStorageEvent(area, key, oldValue, newValue, sourceFrame);
}
void LocalStorage::itemRemoved(StorageArea* area, const String& key, const String& oldValue, Frame* sourceFrame)
{
// FIXME: Flag this removal to be written out to the persistent store
dispatchStorageEvent(area, key, oldValue, String(), sourceFrame);
}
void LocalStorage::dispatchStorageEvent(StorageArea* area, const String& key, const String& oldValue, const String& newValue, Frame* sourceFrame)
{
// FIXME: StorageEvents for local storage areas need to be dispatched to every WebView currently displaying a document associated with this
// StorageArea. This will involved refering to all open Pages, mapped by SecurityOrigin
}
} // namespace WebCore
/*
* 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.
*/
#ifndef LocalStorage_h
#define LocalStorage_h
#include "SecurityOriginHash.h"
#include "StorageAreaClient.h"
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
namespace WebCore {
class LocalStorage : public StorageAreaClient {
public:
static LocalStorage& sharedLocalStorage();
PassRefPtr<StorageArea> storageArea(SecurityOrigin*);
virtual void itemChanged(StorageArea*, const String& key, const String& oldValue, const String& newValue, Frame* sourceFrame);
virtual void itemRemoved(StorageArea*, const String& key, const String& oldValue, Frame* sourceFrame);
private:
LocalStorage();
void dispatchStorageEvent(StorageArea*, const String& key, const String& oldValue, const String& newValue, Frame* sourceFrame);
typedef HashMap<RefPtr<SecurityOrigin>, RefPtr<StorageArea>, SecurityOriginHash, SecurityOriginTraits> StorageAreaMap;
StorageAreaMap m_storageAreaMap;
};
} // namespace WebCore
#endif // LocalStorage_h
......@@ -26,6 +26,11 @@
#include "config.h"
#include "SessionStorage.h"
#include "EventNames.h"
#include "Frame.h"
#include "FrameTree.h"
#include "Page.h"
#include "SecurityOrigin.h"
#include "StorageArea.h"
#include "StorageMap.h"
......@@ -39,16 +44,21 @@ PassRefPtr<SessionStorage> SessionStorage::create(Page* page)
SessionStorage::SessionStorage(Page* page)
: m_page(page)
{
ASSERT(m_page);
}
PassRefPtr<SessionStorage> SessionStorage::copy(Page* newPage)
{
ASSERT(newPage);
RefPtr<SessionStorage> newSession = SessionStorage::create(newPage);
StorageAreaMap::iterator end = m_storageAreaMap.end();
for (StorageAreaMap::iterator i = m_storageAreaMap.begin(); i != end; ++i)
newSession->m_storageAreaMap.set(i->first, i->second->copy(i->first.get(), newPage));
for (StorageAreaMap::iterator i = m_storageAreaMap.begin(); i != end; ++i) {
RefPtr<StorageArea> areaCopy = i->second->copy(i->first.get(), newPage);
areaCopy->setClient(newSession.get());
newSession->m_storageAreaMap.set(i->first, areaCopy.release());
}
return newSession.release();
}
......@@ -58,9 +68,36 @@ PassRefPtr<StorageArea> SessionStorage::storageArea(SecurityOrigin* origin)
if (storageArea = m_storageAreaMap.get(origin))
return storageArea.release();
storageArea = StorageArea::create(origin, m_page);
storageArea = StorageArea::create(origin, m_page, this);
m_storageAreaMap.set(origin, storageArea);
return storageArea.release();
}
void SessionStorage::itemChanged(StorageArea* area, const String& key, const String& oldValue, const String& newValue, Frame* sourceFrame)
{
dispatchStorageEvent(area, key, oldValue, newValue, sourceFrame);
}
void SessionStorage::itemRemoved(StorageArea* area, const String& key, const String& oldValue, Frame* sourceFrame)
{
dispatchStorageEvent(area, key, oldValue, String(), sourceFrame);
}
void SessionStorage::dispatchStorageEvent(StorageArea* area, const String& key, const String& oldValue, const String& newValue, Frame* sourceFrame)
{
ASSERT(area->page() == m_page);
// For SessionStorage events, each frame in the page's frametree with the same origin as this Storage needs to be notified of the change
Vector<RefPtr<Frame> > frames;
for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext())
frames.append(frame);
for (unsigned i = 0; i < frames.size(); ++i) {
if (frames[i]->document()->securityOrigin()->equal(area->securityOrigin())) {
if (HTMLElement* body = frames[i]->document()->body())
body->dispatchStorageEvent(EventNames::storageEvent, key, oldValue, newValue, sourceFrame);
}
}
}
}
......@@ -28,6 +28,7 @@
#include "SecurityOriginHash.h"
#include "StorageAreaClient.h"
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/RefCounted.h>
......@@ -37,13 +38,16 @@ namespace WebCore {
class StorageArea;
class Page;
class SessionStorage : public RefCounted<SessionStorage> {
class SessionStorage : public StorageAreaClient {
public:
static PassRefPtr<SessionStorage> create(Page*);
PassRefPtr<SessionStorage> copy(Page*);
PassRefPtr<StorageArea> storageArea(SecurityOrigin*);
virtual void itemChanged(StorageArea*, const String& key, const String& oldValue, const String& newValue, Frame* sourceFrame);
virtual void itemRemoved(StorageArea*, const String& key, const String& oldValue, Frame* sourceFrame);
#ifndef NDEBUG
Page* page() { return m_page; }
#endif
......@@ -51,6 +55,8 @@ namespace WebCore {
private:
SessionStorage(Page*);
void dispatchStorageEvent(StorageArea*, const String& key, const String& oldValue, const String& newValue, Frame* sourceFrame);
Page* m_page;
typedef HashMap<RefPtr<SecurityOrigin>, RefPtr<StorageArea>, SecurityOriginHash, SecurityOriginTraits> StorageAreaMap;
......
......@@ -27,34 +27,35 @@
#include "StorageArea.h"
#include "CString.h"
#include "EventNames.h"
#include "ExceptionCode.h"
#include "Frame.h"
#include "FrameTree.h"
#include "Page.h"
#include "PlatformString.h"
#include "SecurityOrigin.h"
#include "StorageAreaClient.h"
#include "StorageMap.h"
namespace WebCore {
PassRefPtr<StorageArea> StorageArea::create(SecurityOrigin* origin, Page* page)
PassRefPtr<StorageArea> StorageArea::create(SecurityOrigin* origin, Page* page, PassRefPtr<StorageAreaClient> client)
{
return adoptRef(new StorageArea(origin, page));
return adoptRef(new StorageArea(origin, page, client));
}
StorageArea::StorageArea(SecurityOrigin* origin, Page* page)
StorageArea::StorageArea(SecurityOrigin* origin, Page* page, PassRefPtr<StorageAreaClient> client)
: m_page(page)
, m_securityOrigin(origin)
, m_storageMap(StorageMap::create())
, m_client(client)
{
ASSERT(m_client);
}
StorageArea::StorageArea(SecurityOrigin* origin, Page* page, PassRefPtr<StorageMap> map)
StorageArea::StorageArea(SecurityOrigin* origin, Page* page, PassRefPtr<StorageMap> map, PassRefPtr<StorageAreaClient> client)
: m_page(page)
, m_securityOrigin(origin)
, m_storageMap(map)
, m_client(client)
{
ASSERT(m_client);
}
StorageArea::~StorageArea()
......@@ -63,7 +64,7 @@ StorageArea::~StorageArea()
PassRefPtr<StorageArea> StorageArea::copy(SecurityOrigin* origin, Page* newPage)
{
return adoptRef(new StorageArea(origin, newPage, m_storageMap));
return adoptRef(new StorageArea(origin, newPage, m_storageMap, m_client));
}
unsigned StorageArea::length() const
......@@ -108,8 +109,10 @@ void StorageArea::setItem(const String& key, const String& value, ExceptionCode&
if (newMap)
m_storageMap = newMap.release();
dispatchStorageEvent(key, oldValue, value, frame);
// Only notify the client if an item was actually changed
if (oldValue != value)
m_client->itemChanged(this, key, oldValue, value, frame);
}
void StorageArea::removeItem(const String& key, Frame* frame)
......@@ -118,10 +121,10 @@ void StorageArea::removeItem(const String& key, Frame* frame)
RefPtr<StorageMap> newMap = m_storageMap->removeItem(key, oldValue);
if (newMap)
m_storageMap = newMap.release();
// Fire a StorageEvent only if an item was actually removed
// Only notify the client if an item was actually removed
if (!oldValue.isNull())
dispatchStorageEvent(key, oldValue, String(), frame);
m_client->itemRemoved(this, key, oldValue, frame);
}
bool StorageArea::contains(const String& key) const
......@@ -129,15 +132,10 @@ bool StorageArea::contains(const String& key) const
return m_storageMap->contains(key);
}
void StorageArea::dispatchStorageEvent(const String& key, const String& oldValue, const String& newValue, Frame* sourceFrame)
void StorageArea::setClient(PassRefPtr<StorageAreaClient> client)
{
// For SessionStorage events, each frame in the page's frametree with the same origin as this Storage needs to be notified of the change
for (Frame* frame = m_page ? m_page->mainFrame() : 0; frame; frame = frame->tree()->traverseNext()) {
if (frame->document()->securityOrigin()->equal(m_securityOrigin.get())) {
if (HTMLElement* body = frame->document()->body())
body->dispatchStorageEvent(EventNames::storageEvent, key, oldValue, newValue, sourceFrame);
}
}
ASSERT(client);
m_client = client;
}
}
......@@ -35,6 +35,7 @@ namespace WebCore {
class Frame;
class Page;
class SecurityOrigin;
class StorageAreaClient;
class StorageMap;
class String;
typedef int ExceptionCode;
......@@ -43,7 +44,7 @@ namespace WebCore {
public:
virtual ~StorageArea();
static PassRefPtr<StorageArea> create(SecurityOrigin*, Page*);
static PassRefPtr<StorageArea> create(SecurityOrigin*, Page*, PassRefPtr<StorageAreaClient>);
PassRefPtr<StorageArea> copy(SecurityOrigin*, Page*);