diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/storage | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/storage')
29 files changed, 312 insertions, 2766 deletions
diff --git a/Source/WebCore/storage/Storage.cpp b/Source/WebCore/storage/Storage.cpp index c484b96aa..11f919a82 100644 --- a/Source/WebCore/storage/Storage.cpp +++ b/Source/WebCore/storage/Storage.cpp @@ -31,21 +31,21 @@ #include "Frame.h" #include "Page.h" #include "SchemeRegistry.h" -#include "Settings.h" +#include "SecurityOrigin.h" #include "StorageArea.h" -#include <wtf/PassRefPtr.h> +#include "StorageType.h" #include <wtf/text/WTFString.h> namespace WebCore { -PassRefPtr<Storage> Storage::create(Frame* frame, PassRefPtr<StorageArea> storageArea) +Ref<Storage> Storage::create(Frame* frame, RefPtr<StorageArea>&& storageArea) { - return adoptRef(new Storage(frame, storageArea)); + return adoptRef(*new Storage(frame, WTFMove(storageArea))); } -Storage::Storage(Frame* frame, PassRefPtr<StorageArea> storageArea) +Storage::Storage(Frame* frame, RefPtr<StorageArea>&& storageArea) : DOMWindowProperty(frame) - , m_storageArea(storageArea) + , m_storageArea(WTFMove(storageArea)) { ASSERT(m_frame); ASSERT(m_storageArea); @@ -58,115 +58,66 @@ Storage::~Storage() m_storageArea->decrementAccessCount(); } -unsigned Storage::length(ExceptionCode& ec) const +ExceptionOr<unsigned> Storage::length() const { - ec = 0; - if (!m_storageArea->canAccessStorage(m_frame)) { - ec = SECURITY_ERR; - return 0; - } - - if (isDisabledByPrivateBrowsing()) - return 0; + if (!m_storageArea->canAccessStorage(m_frame)) + return Exception { SECURITY_ERR }; return m_storageArea->length(); } -String Storage::key(unsigned index, ExceptionCode& ec) const +ExceptionOr<String> Storage::key(unsigned index) const { - if (!m_storageArea->canAccessStorage(m_frame)) { - ec = SECURITY_ERR; - return String(); - } - - if (isDisabledByPrivateBrowsing()) - return String(); + if (!m_storageArea->canAccessStorage(m_frame)) + return Exception { SECURITY_ERR }; return m_storageArea->key(index); } -String Storage::getItem(const String& key, ExceptionCode& ec) const +ExceptionOr<String> Storage::getItem(const String& key) const { - if (!m_storageArea->canAccessStorage(m_frame)) { - ec = SECURITY_ERR; - return String(); - } - - if (isDisabledByPrivateBrowsing()) - return String(); + if (!m_storageArea->canAccessStorage(m_frame)) + return Exception { SECURITY_ERR }; return m_storageArea->item(key); } -void Storage::setItem(const String& key, const String& value, ExceptionCode& ec) +ExceptionOr<void> Storage::setItem(const String& key, const String& value) { - if (!m_storageArea->canAccessStorage(m_frame)) { - ec = SECURITY_ERR; - return; - } - - if (isDisabledByPrivateBrowsing()) { - ec = QUOTA_EXCEEDED_ERR; - return; - } + if (!m_storageArea->canAccessStorage(m_frame)) + return Exception { SECURITY_ERR }; bool quotaException = false; m_storageArea->setItem(m_frame, key, value, quotaException); - if (quotaException) - ec = QUOTA_EXCEEDED_ERR; + return Exception { QUOTA_EXCEEDED_ERR }; + return { }; } -void Storage::removeItem(const String& key, ExceptionCode& ec) +ExceptionOr<void> Storage::removeItem(const String& key) { - if (!m_storageArea->canAccessStorage(m_frame)) { - ec = SECURITY_ERR; - return; - } - - if (isDisabledByPrivateBrowsing()) - return; + if (!m_storageArea->canAccessStorage(m_frame)) + return Exception { SECURITY_ERR }; m_storageArea->removeItem(m_frame, key); + return { }; } -void Storage::clear(ExceptionCode& ec) +ExceptionOr<void> Storage::clear() { - if (!m_storageArea->canAccessStorage(m_frame)) { - ec = SECURITY_ERR; - return; - } - - if (isDisabledByPrivateBrowsing()) - return; + if (!m_storageArea->canAccessStorage(m_frame)) + return Exception { SECURITY_ERR }; m_storageArea->clear(m_frame); + return { }; } -bool Storage::contains(const String& key, ExceptionCode& ec) const +ExceptionOr<bool> Storage::contains(const String& key) const { - if (!m_storageArea->canAccessStorage(m_frame)) { - ec = SECURITY_ERR; - return false; - } - - if (isDisabledByPrivateBrowsing()) - return false; + if (!m_storageArea->canAccessStorage(m_frame)) + return Exception { SECURITY_ERR }; return m_storageArea->contains(key); } -bool Storage::isDisabledByPrivateBrowsing() const -{ - if (!m_frame->page()->settings().privateBrowsingEnabled()) - return false; - - if (m_storageArea->storageType() == LocalStorage) { - if (SchemeRegistry::allowsLocalStorageAccessInPrivateBrowsing(m_frame->document()->securityOrigin()->protocol())) - return false; - } - - return true; -} - } // namespace WebCore diff --git a/Source/WebCore/storage/Storage.h b/Source/WebCore/storage/Storage.h index 1e9fdab76..5df3ae9a8 100644 --- a/Source/WebCore/storage/Storage.h +++ b/Source/WebCore/storage/Storage.h @@ -23,39 +23,34 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Storage_h -#define Storage_h +#pragma once #include "DOMWindowProperty.h" +#include "ExceptionOr.h" #include "ScriptWrappable.h" -#include <wtf/Forward.h> -#include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> namespace WebCore { class Frame; class StorageArea; -typedef int ExceptionCode; - class Storage : public ScriptWrappable, public RefCounted<Storage>, public DOMWindowProperty { public: - static PassRefPtr<Storage> create(Frame*, PassRefPtr<StorageArea>); + static Ref<Storage> create(Frame*, RefPtr<StorageArea>&&); ~Storage(); - unsigned length(ExceptionCode&) const; - String key(unsigned index, ExceptionCode&) const; - String getItem(const String& key, ExceptionCode&) const; - void setItem(const String& key, const String& value, ExceptionCode&); - void removeItem(const String& key, ExceptionCode&); - void clear(ExceptionCode&); - bool contains(const String& key, ExceptionCode&) const; + ExceptionOr<unsigned> length() const; + ExceptionOr<String> key(unsigned index) const; + ExceptionOr<String> getItem(const String& key) const; + ExceptionOr<void> setItem(const String& key, const String& value); + ExceptionOr<void> removeItem(const String& key); + ExceptionOr<void> clear(); + ExceptionOr<bool> contains(const String& key) const; StorageArea& area() const { return *m_storageArea; } private: - Storage(Frame*, PassRefPtr<StorageArea>); + Storage(Frame*, RefPtr<StorageArea>&&); bool isDisabledByPrivateBrowsing() const; @@ -63,5 +58,3 @@ private: }; } // namespace WebCore - -#endif // Storage_h diff --git a/Source/WebCore/storage/Storage.idl b/Source/WebCore/storage/Storage.idl index 5514b9121..3d4aa56e1 100644 --- a/Source/WebCore/storage/Storage.idl +++ b/Source/WebCore/storage/Storage.idl @@ -30,11 +30,11 @@ CustomNamedSetter, SkipVTableValidation, ] interface Storage { - [NotEnumerable, GetterRaisesException] readonly attribute unsigned long length; - [NotEnumerable, TreatReturnedNullStringAs=Null, RaisesException] DOMString key(unsigned long index); - [NotEnumerable, TreatReturnedNullStringAs=Null, RaisesException] getter DOMString getItem(DOMString key); - [NotEnumerable, RaisesException] void setItem(DOMString key, DOMString data); - [NotEnumerable, RaisesException] void removeItem(DOMString key); - [NotEnumerable, RaisesException] void clear(); + [GetterMayThrowException] readonly attribute unsigned long length; + [MayThrowException] DOMString? key(unsigned long index); + [MayThrowException] getter DOMString? getItem(DOMString key); + [MayThrowException] void setItem(DOMString key, DOMString data); + [MayThrowException] void removeItem(DOMString key); + [MayThrowException] void clear(); }; diff --git a/Source/WebCore/storage/StorageArea.h b/Source/WebCore/storage/StorageArea.h index 86e9c2051..9743fded2 100644 --- a/Source/WebCore/storage/StorageArea.h +++ b/Source/WebCore/storage/StorageArea.h @@ -23,20 +23,21 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef StorageArea_h -#define StorageArea_h +#pragma once #include <wtf/Forward.h> -#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/text/WTFString.h> namespace WebCore { class Frame; +class SecurityOrigin; class StorageSyncManager; -typedef int ExceptionCode; -enum StorageType { LocalStorage, SessionStorage }; + +enum class StorageType; + +struct SecurityOriginData; class StorageArea : public RefCounted<StorageArea> { public: @@ -58,8 +59,8 @@ public: virtual void incrementAccessCount() { } virtual void decrementAccessCount() { } virtual void closeDatabaseIfIdle() { } + + virtual SecurityOriginData securityOrigin() const = 0; }; } // namespace WebCore - -#endif // StorageArea_h diff --git a/Source/WebCore/storage/StorageAreaImpl.cpp b/Source/WebCore/storage/StorageAreaImpl.cpp deleted file mode 100644 index 74e2c81ff..000000000 --- a/Source/WebCore/storage/StorageAreaImpl.cpp +++ /dev/null @@ -1,306 +0,0 @@ -/* - * 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 "StorageAreaImpl.h" - -#include "Document.h" -#include "ExceptionCode.h" -#include "Frame.h" -#include "Page.h" -#include "SchemeRegistry.h" -#include "SecurityOrigin.h" -#include "Settings.h" -#include "StorageAreaSync.h" -#include "StorageEventDispatcher.h" -#include "StorageMap.h" -#include "StorageSyncManager.h" -#include "StorageTracker.h" -#include <wtf/MainThread.h> - -namespace WebCore { - -StorageAreaImpl::~StorageAreaImpl() -{ - ASSERT(isMainThread()); -} - -inline StorageAreaImpl::StorageAreaImpl(StorageType storageType, PassRefPtr<SecurityOrigin> origin, PassRefPtr<StorageSyncManager> syncManager, unsigned quota) - : m_storageType(storageType) - , m_securityOrigin(origin) - , m_storageMap(StorageMap::create(quota)) - , m_storageSyncManager(syncManager) -#ifndef NDEBUG - , m_isShutdown(false) -#endif - , m_accessCount(0) - , m_closeDatabaseTimer(this, &StorageAreaImpl::closeDatabaseTimerFired) -{ - ASSERT(isMainThread()); - ASSERT(m_securityOrigin); - ASSERT(m_storageMap); - - // Accessing the shared global StorageTracker when a StorageArea is created - // ensures that the tracker is properly initialized before anyone actually needs to use it. - StorageTracker::tracker(); -} - -PassRefPtr<StorageAreaImpl> StorageAreaImpl::create(StorageType storageType, PassRefPtr<SecurityOrigin> origin, PassRefPtr<StorageSyncManager> syncManager, unsigned quota) -{ - RefPtr<StorageAreaImpl> area = adoptRef(new StorageAreaImpl(storageType, origin, syncManager, quota)); - - // FIXME: If there's no backing storage for LocalStorage, the default WebKit behavior should be that of private browsing, - // not silently ignoring it. https://bugs.webkit.org/show_bug.cgi?id=25894 - if (area->m_storageSyncManager) { - area->m_storageAreaSync = StorageAreaSync::create(area->m_storageSyncManager, area.get(), area->m_securityOrigin->databaseIdentifier()); - ASSERT(area->m_storageAreaSync); - } - - return area.release(); -} - -PassRefPtr<StorageAreaImpl> StorageAreaImpl::copy() -{ - ASSERT(!m_isShutdown); - return adoptRef(new StorageAreaImpl(this)); -} - -StorageAreaImpl::StorageAreaImpl(StorageAreaImpl* area) - : m_storageType(area->m_storageType) - , m_securityOrigin(area->m_securityOrigin) - , m_storageMap(area->m_storageMap) - , m_storageSyncManager(area->m_storageSyncManager) -#ifndef NDEBUG - , m_isShutdown(area->m_isShutdown) -#endif - , m_accessCount(0) - , m_closeDatabaseTimer(this, &StorageAreaImpl::closeDatabaseTimerFired) -{ - ASSERT(isMainThread()); - ASSERT(m_securityOrigin); - ASSERT(m_storageMap); - ASSERT(!m_isShutdown); -} - -bool StorageAreaImpl::canAccessStorage(Frame* frame) -{ - return frame && frame->page(); -} - -StorageType StorageAreaImpl::storageType() const -{ - return m_storageType; -} - -unsigned StorageAreaImpl::length() -{ - ASSERT(!m_isShutdown); - blockUntilImportComplete(); - - return m_storageMap->length(); -} - -String StorageAreaImpl::key(unsigned index) -{ - ASSERT(!m_isShutdown); - blockUntilImportComplete(); - - return m_storageMap->key(index); -} - -String StorageAreaImpl::item(const String& key) -{ - ASSERT(!m_isShutdown); - blockUntilImportComplete(); - - return m_storageMap->getItem(key); -} - -void StorageAreaImpl::setItem(Frame* sourceFrame, const String& key, const String& value, bool& quotaException) -{ - ASSERT(!m_isShutdown); - ASSERT(!value.isNull()); - blockUntilImportComplete(); - - String oldValue; - RefPtr<StorageMap> newMap = m_storageMap->setItem(key, value, oldValue, quotaException); - if (newMap) - m_storageMap = newMap.release(); - - if (quotaException) - return; - - if (oldValue == value) - return; - - if (m_storageAreaSync) - m_storageAreaSync->scheduleItemForSync(key, value); - - dispatchStorageEvent(key, oldValue, value, sourceFrame); -} - -void StorageAreaImpl::removeItem(Frame* sourceFrame, const String& key) -{ - ASSERT(!m_isShutdown); - blockUntilImportComplete(); - - String oldValue; - RefPtr<StorageMap> newMap = m_storageMap->removeItem(key, oldValue); - if (newMap) - m_storageMap = newMap.release(); - - if (oldValue.isNull()) - return; - - if (m_storageAreaSync) - m_storageAreaSync->scheduleItemForSync(key, String()); - - dispatchStorageEvent(key, oldValue, String(), sourceFrame); -} - -void StorageAreaImpl::clear(Frame* sourceFrame) -{ - ASSERT(!m_isShutdown); - blockUntilImportComplete(); - - if (!m_storageMap->length()) - return; - - unsigned quota = m_storageMap->quota(); - m_storageMap = StorageMap::create(quota); - - if (m_storageAreaSync) - m_storageAreaSync->scheduleClear(); - - dispatchStorageEvent(String(), String(), String(), sourceFrame); -} - -bool StorageAreaImpl::contains(const String& key) -{ - ASSERT(!m_isShutdown); - blockUntilImportComplete(); - - return m_storageMap->contains(key); -} - -void StorageAreaImpl::importItems(const HashMap<String, String>& items) -{ - ASSERT(!m_isShutdown); - - m_storageMap->importItems(items); -} - -void StorageAreaImpl::close() -{ - if (m_storageAreaSync) - m_storageAreaSync->scheduleFinalSync(); - -#ifndef NDEBUG - m_isShutdown = true; -#endif -} - -void StorageAreaImpl::clearForOriginDeletion() -{ - ASSERT(!m_isShutdown); - blockUntilImportComplete(); - - if (m_storageMap->length()) { - unsigned quota = m_storageMap->quota(); - m_storageMap = StorageMap::create(quota); - } - - if (m_storageAreaSync) { - m_storageAreaSync->scheduleClear(); - m_storageAreaSync->scheduleCloseDatabase(); - } -} - -void StorageAreaImpl::sync() -{ - ASSERT(!m_isShutdown); - blockUntilImportComplete(); - - if (m_storageAreaSync) - m_storageAreaSync->scheduleSync(); -} - -void StorageAreaImpl::blockUntilImportComplete() const -{ - if (m_storageAreaSync) - m_storageAreaSync->blockUntilImportComplete(); -} - -size_t StorageAreaImpl::memoryBytesUsedByCache() -{ - return 0; -} - -void StorageAreaImpl::incrementAccessCount() -{ - m_accessCount++; - - if (m_closeDatabaseTimer.isActive()) - m_closeDatabaseTimer.stop(); -} - -void StorageAreaImpl::decrementAccessCount() -{ - ASSERT(m_accessCount); - --m_accessCount; - - if (!m_accessCount) { - if (m_closeDatabaseTimer.isActive()) - m_closeDatabaseTimer.stop(); - m_closeDatabaseTimer.startOneShot(StorageTracker::tracker().storageDatabaseIdleInterval()); - } -} - -void StorageAreaImpl::closeDatabaseTimerFired(Timer<StorageAreaImpl> *) -{ - blockUntilImportComplete(); - if (m_storageAreaSync) - m_storageAreaSync->scheduleCloseDatabase(); -} - -void StorageAreaImpl::closeDatabaseIfIdle() -{ - if (m_closeDatabaseTimer.isActive()) { - ASSERT(!m_accessCount); - m_closeDatabaseTimer.stop(); - - closeDatabaseTimerFired(&m_closeDatabaseTimer); - } -} - -void StorageAreaImpl::dispatchStorageEvent(const String& key, const String& oldValue, const String& newValue, Frame* sourceFrame) -{ - if (m_storageType == LocalStorage) - StorageEventDispatcher::dispatchLocalStorageEvents(key, oldValue, newValue, m_securityOrigin.get(), sourceFrame); - else - StorageEventDispatcher::dispatchSessionStorageEvents(key, oldValue, newValue, m_securityOrigin.get(), sourceFrame); -} - -} // namespace WebCore diff --git a/Source/WebCore/storage/StorageAreaImpl.h b/Source/WebCore/storage/StorageAreaImpl.h deleted file mode 100644 index f384e0dd1..000000000 --- a/Source/WebCore/storage/StorageAreaImpl.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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 StorageAreaImpl_h -#define StorageAreaImpl_h - -#include "StorageArea.h" -#include "Timer.h" - -#include <wtf/HashMap.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> - -namespace WebCore { - -class SecurityOrigin; -class StorageMap; -class StorageAreaSync; - -class StorageAreaImpl : public StorageArea { -public: - static PassRefPtr<StorageAreaImpl> create(StorageType, PassRefPtr<SecurityOrigin>, PassRefPtr<StorageSyncManager>, unsigned quota); - virtual ~StorageAreaImpl(); - - virtual unsigned length() override; - virtual String key(unsigned index) override; - virtual String item(const String& key) override; - virtual void setItem(Frame* sourceFrame, const String& key, const String& value, bool& quotaException) override; - virtual void removeItem(Frame* sourceFrame, const String& key) override; - virtual void clear(Frame* sourceFrame) override; - virtual bool contains(const String& key) override; - - virtual bool canAccessStorage(Frame* sourceFrame) override; - virtual StorageType storageType() const override; - - virtual size_t memoryBytesUsedByCache() override; - - virtual void incrementAccessCount(); - virtual void decrementAccessCount(); - virtual void closeDatabaseIfIdle(); - - PassRefPtr<StorageAreaImpl> copy(); - void close(); - - // Only called from a background thread. - void importItems(const HashMap<String, String>& items); - - // Used to clear a StorageArea and close db before backing db file is deleted. - void clearForOriginDeletion(); - - void sync(); - -private: - StorageAreaImpl(StorageType, PassRefPtr<SecurityOrigin>, PassRefPtr<StorageSyncManager>, unsigned quota); - explicit StorageAreaImpl(StorageAreaImpl*); - - void blockUntilImportComplete() const; - void closeDatabaseTimerFired(Timer<StorageAreaImpl>*); - - void dispatchStorageEvent(const String& key, const String& oldValue, const String& newValue, Frame* sourceFrame); - - StorageType m_storageType; - RefPtr<SecurityOrigin> m_securityOrigin; - RefPtr<StorageMap> m_storageMap; - - RefPtr<StorageAreaSync> m_storageAreaSync; - RefPtr<StorageSyncManager> m_storageSyncManager; - -#ifndef NDEBUG - bool m_isShutdown; -#endif - unsigned m_accessCount; - Timer<StorageAreaImpl> m_closeDatabaseTimer; -}; - -} // namespace WebCore - -#endif // StorageAreaImpl_h diff --git a/Source/WebCore/storage/StorageAreaSync.cpp b/Source/WebCore/storage/StorageAreaSync.cpp deleted file mode 100644 index eea5ebe6f..000000000 --- a/Source/WebCore/storage/StorageAreaSync.cpp +++ /dev/null @@ -1,531 +0,0 @@ -/* - * Copyright (C) 2008, 2009, 2010 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 "StorageAreaSync.h" - -#include "EventNames.h" -#include "FileSystem.h" -#include "HTMLElement.h" -#include "SQLiteDatabaseTracker.h" -#include "SQLiteFileSystem.h" -#include "SQLiteStatement.h" -#include "SQLiteTransaction.h" -#include "SecurityOrigin.h" -#include "StorageAreaImpl.h" -#include "StorageSyncManager.h" -#include "StorageTracker.h" -#include "SuddenTermination.h" -#include <wtf/Functional.h> -#include <wtf/MainThread.h> -#include <wtf/text/CString.h> - -namespace WebCore { - -// If the StorageArea undergoes rapid changes, don't sync each change to disk. -// Instead, queue up a batch of items to sync and actually do the sync at the following interval. -static const double StorageSyncInterval = 1.0; - -// A sane limit on how many items we'll schedule to sync all at once. This makes it -// much harder to starve the rest of LocalStorage and the OS's IO subsystem in general. -static const int MaxiumItemsToSync = 100; - -inline StorageAreaSync::StorageAreaSync(PassRefPtr<StorageSyncManager> storageSyncManager, PassRefPtr<StorageAreaImpl> storageArea, const String& databaseIdentifier) - : m_syncTimer(this, &StorageAreaSync::syncTimerFired) - , m_itemsCleared(false) - , m_finalSyncScheduled(false) - , m_storageArea(storageArea) - , m_syncManager(storageSyncManager) - , m_databaseIdentifier(databaseIdentifier.isolatedCopy()) - , m_clearItemsWhileSyncing(false) - , m_syncScheduled(false) - , m_syncInProgress(false) - , m_databaseOpenFailed(false) - , m_syncCloseDatabase(false) - , m_importComplete(false) -{ - ASSERT(isMainThread()); - ASSERT(m_storageArea); - ASSERT(m_syncManager); - - // FIXME: If it can't import, then the default WebKit behavior should be that of private browsing, - // not silently ignoring it. https://bugs.webkit.org/show_bug.cgi?id=25894 - m_syncManager->dispatch(bind(&StorageAreaSync::performImport, this)); -} - -PassRefPtr<StorageAreaSync> StorageAreaSync::create(PassRefPtr<StorageSyncManager> storageSyncManager, PassRefPtr<StorageAreaImpl> storageArea, const String& databaseIdentifier) -{ - RefPtr<StorageAreaSync> area = adoptRef(new StorageAreaSync(storageSyncManager, storageArea, databaseIdentifier)); - - return area.release(); -} - -StorageAreaSync::~StorageAreaSync() -{ - ASSERT(isMainThread()); - ASSERT(!m_syncTimer.isActive()); - ASSERT(m_finalSyncScheduled); -} - -void StorageAreaSync::scheduleFinalSync() -{ - ASSERT(isMainThread()); - // FIXME: We do this to avoid races, but it'd be better to make things safe without blocking. - blockUntilImportComplete(); - m_storageArea = 0; // This is done in blockUntilImportComplete() but this is here as a form of documentation that we must be absolutely sure the ref count cycle is broken. - - if (m_syncTimer.isActive()) - m_syncTimer.stop(); - else { - // The following is balanced by the call to enableSuddenTermination in the - // syncTimerFired function. - disableSuddenTermination(); - } - // FIXME: This is synchronous. We should do it on the background process, but - // we should do it safely. - m_finalSyncScheduled = true; - syncTimerFired(&m_syncTimer); - - m_syncManager->dispatch(bind(&StorageAreaSync::deleteEmptyDatabase, this)); -} - -void StorageAreaSync::scheduleItemForSync(const String& key, const String& value) -{ - ASSERT(isMainThread()); - ASSERT(!m_finalSyncScheduled); - - m_changedItems.set(key, value); - if (!m_syncTimer.isActive()) { - m_syncTimer.startOneShot(StorageSyncInterval); - - // The following is balanced by the call to enableSuddenTermination in the - // syncTimerFired function. - disableSuddenTermination(); - } -} - -void StorageAreaSync::scheduleClear() -{ - ASSERT(isMainThread()); - ASSERT(!m_finalSyncScheduled); - - m_changedItems.clear(); - m_itemsCleared = true; - if (!m_syncTimer.isActive()) { - m_syncTimer.startOneShot(StorageSyncInterval); - - // The following is balanced by the call to enableSuddenTermination in the - // syncTimerFired function. - disableSuddenTermination(); - } -} - -void StorageAreaSync::scheduleCloseDatabase() -{ - ASSERT(isMainThread()); - ASSERT(!m_finalSyncScheduled); - - if (!m_database.isOpen()) - return; - - m_syncCloseDatabase = true; - - if (!m_syncTimer.isActive()) { - m_syncTimer.startOneShot(StorageSyncInterval); - - // The following is balanced by the call to enableSuddenTermination in the - // syncTimerFired function. - disableSuddenTermination(); - } -} - -void StorageAreaSync::syncTimerFired(Timer<StorageAreaSync>*) -{ - ASSERT(isMainThread()); - - bool partialSync = false; - { - MutexLocker locker(m_syncLock); - - // Do not schedule another sync if we're still trying to complete the - // previous one. But, if we're shutting down, schedule it anyway. - if (m_syncInProgress && !m_finalSyncScheduled) { - ASSERT(!m_syncTimer.isActive()); - m_syncTimer.startOneShot(StorageSyncInterval); - return; - } - - if (m_itemsCleared) { - m_itemsPendingSync.clear(); - m_clearItemsWhileSyncing = true; - m_itemsCleared = false; - } - - HashMap<String, String>::iterator changed_it = m_changedItems.begin(); - HashMap<String, String>::iterator changed_end = m_changedItems.end(); - for (int count = 0; changed_it != changed_end; ++count, ++changed_it) { - if (count >= MaxiumItemsToSync && !m_finalSyncScheduled) { - partialSync = true; - break; - } - m_itemsPendingSync.set(changed_it->key.isolatedCopy(), changed_it->value.isolatedCopy()); - } - - if (partialSync) { - // We can't do the fast path of simply clearing all items, so we'll need to manually - // remove them one by one. Done under lock since m_itemsPendingSync is modified by - // the background thread. - HashMap<String, String>::iterator pending_it = m_itemsPendingSync.begin(); - HashMap<String, String>::iterator pending_end = m_itemsPendingSync.end(); - for (; pending_it != pending_end; ++pending_it) - m_changedItems.remove(pending_it->key); - } - - if (!m_syncScheduled) { - m_syncScheduled = true; - - // The following is balanced by the call to enableSuddenTermination in the - // performSync function. - disableSuddenTermination(); - - m_syncManager->dispatch(bind(&StorageAreaSync::performSync, this)); - } - } - - if (partialSync) { - // If we didn't finish syncing, then we need to finish the job later. - ASSERT(!m_syncTimer.isActive()); - m_syncTimer.startOneShot(StorageSyncInterval); - } else { - // The following is balanced by the calls to disableSuddenTermination in the - // scheduleItemForSync, scheduleClear, and scheduleFinalSync functions. - enableSuddenTermination(); - - m_changedItems.clear(); - } -} - -void StorageAreaSync::openDatabase(OpenDatabaseParamType openingStrategy) -{ - ASSERT(!isMainThread()); - ASSERT(!m_database.isOpen()); - ASSERT(!m_databaseOpenFailed); - - SQLiteTransactionInProgressAutoCounter transactionCounter; - - String databaseFilename = m_syncManager->fullDatabaseFilename(m_databaseIdentifier); - - if (!fileExists(databaseFilename) && openingStrategy == SkipIfNonExistent) - return; - - if (databaseFilename.isEmpty()) { - LOG_ERROR("Filename for local storage database is empty - cannot open for persistent storage"); - markImported(); - m_databaseOpenFailed = true; - return; - } - - // A StorageTracker thread may have been scheduled to delete the db we're - // reopening, so cancel possible deletion. - StorageTracker::tracker().cancelDeletingOrigin(m_databaseIdentifier); - - if (!m_database.open(databaseFilename)) { - LOG_ERROR("Failed to open database file %s for local storage", databaseFilename.utf8().data()); - markImported(); - m_databaseOpenFailed = true; - return; - } - - migrateItemTableIfNeeded(); - - if (!m_database.executeCommand("CREATE TABLE IF NOT EXISTS ItemTable (key TEXT UNIQUE ON CONFLICT REPLACE, value BLOB NOT NULL ON CONFLICT FAIL)")) { - LOG_ERROR("Failed to create table ItemTable for local storage"); - markImported(); - m_databaseOpenFailed = true; - return; - } - - StorageTracker::tracker().setOriginDetails(m_databaseIdentifier, databaseFilename); -} - -void StorageAreaSync::migrateItemTableIfNeeded() -{ - if (!m_database.tableExists("ItemTable")) - return; - - { - SQLiteStatement query(m_database, "SELECT value FROM ItemTable LIMIT 1"); - // this query isn't ever executed. - if (query.isColumnDeclaredAsBlob(0)) - return; - } - - // alter table for backward compliance, change the value type from TEXT to BLOB. - static const char* commands[] = { - "DROP TABLE IF EXISTS ItemTable2", - "CREATE TABLE ItemTable2 (key TEXT UNIQUE ON CONFLICT REPLACE, value BLOB NOT NULL ON CONFLICT FAIL)", - "INSERT INTO ItemTable2 SELECT * from ItemTable", - "DROP TABLE ItemTable", - "ALTER TABLE ItemTable2 RENAME TO ItemTable", - 0, - }; - - SQLiteTransaction transaction(m_database, false); - transaction.begin(); - for (size_t i = 0; commands[i]; ++i) { - if (!m_database.executeCommand(commands[i])) { - LOG_ERROR("Failed to migrate table ItemTable for local storage when executing: %s", commands[i]); - transaction.rollback(); - - // finally it will try to keep a backup of ItemTable for the future restoration. - // NOTICE: this will essentially DELETE the current database, but that's better - // than continually hitting this case and never being able to use the local storage. - // if this is ever hit, it's definitely a bug. - ASSERT_NOT_REACHED(); - if (!m_database.executeCommand("ALTER TABLE ItemTable RENAME TO Backup_ItemTable")) - LOG_ERROR("Failed to save ItemTable after migration job failed."); - - return; - } - } - transaction.commit(); -} - -void StorageAreaSync::performImport() -{ - ASSERT(!isMainThread()); - ASSERT(!m_database.isOpen()); - - openDatabase(SkipIfNonExistent); - if (!m_database.isOpen()) { - markImported(); - return; - } - - SQLiteStatement query(m_database, "SELECT key, value FROM ItemTable"); - if (query.prepare() != SQLResultOk) { - LOG_ERROR("Unable to select items from ItemTable for local storage"); - markImported(); - return; - } - - HashMap<String, String> itemMap; - - int result = query.step(); - while (result == SQLResultRow) { - itemMap.set(query.getColumnText(0), query.getColumnBlobAsString(1)); - result = query.step(); - } - - if (result != SQLResultDone) { - LOG_ERROR("Error reading items from ItemTable for local storage"); - markImported(); - return; - } - - m_storageArea->importItems(itemMap); - - markImported(); -} - -void StorageAreaSync::markImported() -{ - MutexLocker locker(m_importLock); - m_importComplete = true; - m_importCondition.signal(); -} - -// FIXME: In the future, we should allow use of StorageAreas while it's importing (when safe to do so). -// Blocking everything until the import is complete is by far the simplest and safest thing to do, but -// there is certainly room for safe optimization: Key/length will never be able to make use of such an -// optimization (since the order of iteration can change as items are being added). Get can return any -// item currently in the map. Get/remove can work whether or not it's in the map, but we'll need a list -// of items the import should not overwrite. Clear can also work, but it'll need to kill the import -// job first. -void StorageAreaSync::blockUntilImportComplete() -{ - ASSERT(isMainThread()); - - // Fast path. We set m_storageArea to 0 only after m_importComplete being true. - if (!m_storageArea) - return; - - MutexLocker locker(m_importLock); - while (!m_importComplete) - m_importCondition.wait(m_importLock); - m_storageArea = 0; -} - -void StorageAreaSync::sync(bool clearItems, const HashMap<String, String>& items) -{ - ASSERT(!isMainThread()); - - if (items.isEmpty() && !clearItems && !m_syncCloseDatabase) - return; - if (m_databaseOpenFailed) - return; - - if (!m_database.isOpen() && m_syncCloseDatabase) { - m_syncCloseDatabase = false; - return; - } - - if (!m_database.isOpen()) - openDatabase(CreateIfNonExistent); - if (!m_database.isOpen()) - return; - - // Closing this db because it is about to be deleted by StorageTracker. - // The delete will be cancelled if StorageAreaSync needs to reopen the db - // to write new items created after the request to delete the db. - if (m_syncCloseDatabase) { - m_syncCloseDatabase = false; - m_database.close(); - return; - } - - SQLiteTransactionInProgressAutoCounter transactionCounter; - - // If the clear flag is set, then we clear all items out before we write any new ones in. - if (clearItems) { - SQLiteStatement clear(m_database, "DELETE FROM ItemTable"); - if (clear.prepare() != SQLResultOk) { - LOG_ERROR("Failed to prepare clear statement - cannot write to local storage database"); - return; - } - - int result = clear.step(); - if (result != SQLResultDone) { - LOG_ERROR("Failed to clear all items in the local storage database - %i", result); - return; - } - } - - SQLiteStatement insert(m_database, "INSERT INTO ItemTable VALUES (?, ?)"); - if (insert.prepare() != SQLResultOk) { - LOG_ERROR("Failed to prepare insert statement - cannot write to local storage database"); - return; - } - - SQLiteStatement remove(m_database, "DELETE FROM ItemTable WHERE key=?"); - if (remove.prepare() != SQLResultOk) { - LOG_ERROR("Failed to prepare delete statement - cannot write to local storage database"); - return; - } - - HashMap<String, String>::const_iterator end = items.end(); - - SQLiteTransaction transaction(m_database); - transaction.begin(); - for (HashMap<String, String>::const_iterator it = items.begin(); it != end; ++it) { - // Based on the null-ness of the second argument, decide whether this is an insert or a delete. - SQLiteStatement& query = it->value.isNull() ? remove : insert; - - query.bindText(1, it->key); - - // If the second argument is non-null, we're doing an insert, so bind it as the value. - if (!it->value.isNull()) - query.bindBlob(2, it->value); - - int result = query.step(); - if (result != SQLResultDone) { - LOG_ERROR("Failed to update item in the local storage database - %i", result); - break; - } - - query.reset(); - } - transaction.commit(); -} - -void StorageAreaSync::performSync() -{ - ASSERT(!isMainThread()); - - bool clearItems; - HashMap<String, String> items; - { - MutexLocker locker(m_syncLock); - - ASSERT(m_syncScheduled); - - clearItems = m_clearItemsWhileSyncing; - m_itemsPendingSync.swap(items); - - m_clearItemsWhileSyncing = false; - m_syncScheduled = false; - m_syncInProgress = true; - } - - sync(clearItems, items); - - { - MutexLocker locker(m_syncLock); - m_syncInProgress = false; - } - - // The following is balanced by the call to disableSuddenTermination in the - // syncTimerFired function. - enableSuddenTermination(); -} - -void StorageAreaSync::deleteEmptyDatabase() -{ - ASSERT(!isMainThread()); - if (!m_database.isOpen()) - return; - - SQLiteStatement query(m_database, "SELECT COUNT(*) FROM ItemTable"); - if (query.prepare() != SQLResultOk) { - LOG_ERROR("Unable to count number of rows in ItemTable for local storage"); - return; - } - - int result = query.step(); - if (result != SQLResultRow) { - LOG_ERROR("No results when counting number of rows in ItemTable for local storage"); - return; - } - - int count = query.getColumnInt(0); - if (!count) { - query.finalize(); - m_database.close(); - if (StorageTracker::tracker().isActive()) - StorageTracker::tracker().deleteOriginWithIdentifier(m_databaseIdentifier); - else { - String databaseFilename = m_syncManager->fullDatabaseFilename(m_databaseIdentifier); - if (!SQLiteFileSystem::deleteDatabaseFile(databaseFilename)) - LOG_ERROR("Failed to delete database file %s\n", databaseFilename.utf8().data()); - } - } -} - -void StorageAreaSync::scheduleSync() -{ - syncTimerFired(&m_syncTimer); -} - -} // namespace WebCore diff --git a/Source/WebCore/storage/StorageAreaSync.h b/Source/WebCore/storage/StorageAreaSync.h deleted file mode 100644 index a5934b005..000000000 --- a/Source/WebCore/storage/StorageAreaSync.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2008, 2009, 2010 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 StorageAreaSync_h -#define StorageAreaSync_h - -#include "SQLiteDatabase.h" -#include "Timer.h" -#include <wtf/HashMap.h> -#include <wtf/text/StringHash.h> - -namespace WebCore { - -class Frame; -class StorageAreaImpl; -class StorageSyncManager; - -class StorageAreaSync : public ThreadSafeRefCounted<StorageAreaSync> { -public: - static PassRefPtr<StorageAreaSync> create(PassRefPtr<StorageSyncManager>, PassRefPtr<StorageAreaImpl>, const String& databaseIdentifier); - ~StorageAreaSync(); - - void scheduleFinalSync(); - void blockUntilImportComplete(); - - void scheduleItemForSync(const String& key, const String& value); - void scheduleClear(); - void scheduleCloseDatabase(); - - void scheduleSync(); - -private: - StorageAreaSync(PassRefPtr<StorageSyncManager>, PassRefPtr<StorageAreaImpl>, const String& databaseIdentifier); - - void dispatchStorageEvent(const String& key, const String& oldValue, const String& newValue, Frame* sourceFrame); - - Timer<StorageAreaSync> m_syncTimer; - HashMap<String, String> m_changedItems; - bool m_itemsCleared; - - bool m_finalSyncScheduled; - - RefPtr<StorageAreaImpl> m_storageArea; - RefPtr<StorageSyncManager> m_syncManager; - - // The database handle will only ever be opened and used on the background thread. - SQLiteDatabase m_database; - - // The following members are subject to thread synchronization issues. -public: - // Called from the background thread - void performImport(); - void performSync(); - void deleteEmptyDatabase(); - -private: - enum OpenDatabaseParamType { - CreateIfNonExistent, - SkipIfNonExistent - }; - - void syncTimerFired(Timer<StorageAreaSync>*); - void openDatabase(OpenDatabaseParamType openingStrategy); - void sync(bool clearItems, const HashMap<String, String>& items); - - const String m_databaseIdentifier; - - Mutex m_syncLock; - HashMap<String, String> m_itemsPendingSync; - bool m_clearItemsWhileSyncing; - bool m_syncScheduled; - bool m_syncInProgress; - bool m_databaseOpenFailed; - - bool m_syncCloseDatabase; - - mutable Mutex m_importLock; - mutable ThreadCondition m_importCondition; - mutable bool m_importComplete; - void markImported(); - void migrateItemTableIfNeeded(); -}; - -} // namespace WebCore - -#endif // StorageAreaSync_h diff --git a/Source/WebCore/storage/StorageEvent.cpp b/Source/WebCore/storage/StorageEvent.cpp index e7d73d570..4fab01000 100644 --- a/Source/WebCore/storage/StorageEvent.cpp +++ b/Source/WebCore/storage/StorageEvent.cpp @@ -26,18 +26,13 @@ #include "config.h" #include "StorageEvent.h" -#include "EventNames.h" #include "Storage.h" namespace WebCore { -StorageEventInit::StorageEventInit() +Ref<StorageEvent> StorageEvent::createForBindings() { -} - -PassRefPtr<StorageEvent> StorageEvent::create() -{ - return adoptRef(new StorageEvent); + return adoptRef(*new StorageEvent); } StorageEvent::StorageEvent() @@ -48,14 +43,14 @@ StorageEvent::~StorageEvent() { } -PassRefPtr<StorageEvent> StorageEvent::create(const AtomicString& type, const String& key, const String& oldValue, const String& newValue, const String& url, Storage* storageArea) +Ref<StorageEvent> StorageEvent::create(const AtomicString& type, const String& key, const String& oldValue, const String& newValue, const String& url, Storage* storageArea) { - return adoptRef(new StorageEvent(type, key, oldValue, newValue, url, storageArea)); + return adoptRef(*new StorageEvent(type, key, oldValue, newValue, url, storageArea)); } -PassRefPtr<StorageEvent> StorageEvent::create(const AtomicString& type, const StorageEventInit& initializer) +Ref<StorageEvent> StorageEvent::create(const AtomicString& type, const Init& initializer, IsTrusted isTrusted) { - return adoptRef(new StorageEvent(type, initializer)); + return adoptRef(*new StorageEvent(type, initializer, isTrusted)); } StorageEvent::StorageEvent(const AtomicString& type, const String& key, const String& oldValue, const String& newValue, const String& url, Storage* storageArea) @@ -68,8 +63,8 @@ StorageEvent::StorageEvent(const AtomicString& type, const String& key, const St { } -StorageEvent::StorageEvent(const AtomicString& type, const StorageEventInit& initializer) - : Event(type, initializer) +StorageEvent::StorageEvent(const AtomicString& type, const Init& initializer, IsTrusted isTrusted) + : Event(type, initializer, isTrusted) , m_key(initializer.key) , m_oldValue(initializer.oldValue) , m_newValue(initializer.newValue) diff --git a/Source/WebCore/storage/StorageEvent.h b/Source/WebCore/storage/StorageEvent.h index 783a626ce..ac18aac9f 100644 --- a/Source/WebCore/storage/StorageEvent.h +++ b/Source/WebCore/storage/StorageEvent.h @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef StorageEvent_h -#define StorageEvent_h +#pragma once #include "Event.h" #include <wtf/text/WTFString.h> @@ -33,21 +32,20 @@ namespace WebCore { class Storage; -struct StorageEventInit : public EventInit { - StorageEventInit(); - - String key; - String oldValue; - String newValue; - String url; - RefPtr<Storage> storageArea; -}; - class StorageEvent : public Event { public: - static PassRefPtr<StorageEvent> create(); - static PassRefPtr<StorageEvent> create(const AtomicString& type, const String& key, const String& oldValue, const String& newValue, const String& url, Storage* storageArea); - static PassRefPtr<StorageEvent> create(const AtomicString&, const StorageEventInit&); + static Ref<StorageEvent> create(const AtomicString& type, const String& key, const String& oldValue, const String& newValue, const String& url, Storage* storageArea); + static Ref<StorageEvent> createForBindings(); + + struct Init : EventInit { + String key; + String oldValue; + String newValue; + String url; + RefPtr<Storage> storageArea; + }; + + static Ref<StorageEvent> create(const AtomicString&, const Init&, IsTrusted = IsTrusted::No); virtual ~StorageEvent(); const String& key() const { return m_key; } @@ -61,12 +59,12 @@ public: // Needed once we support init<blank>EventNS // void initStorageEventNS(in DOMString namespaceURI, in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMString keyArg, in DOMString oldValueArg, in DOMString newValueArg, in DOMString urlArg, Storage storageAreaArg); - virtual EventInterface eventInterface() const; + EventInterface eventInterface() const override; private: StorageEvent(); StorageEvent(const AtomicString& type, const String& key, const String& oldValue, const String& newValue, const String& url, Storage* storageArea); - StorageEvent(const AtomicString&, const StorageEventInit&); + StorageEvent(const AtomicString&, const Init&, IsTrusted); String m_key; String m_oldValue; @@ -76,5 +74,3 @@ private: }; } // namespace WebCore - -#endif // StorageEvent_h diff --git a/Source/WebCore/storage/StorageEvent.idl b/Source/WebCore/storage/StorageEvent.idl index 742a56402..51dadc0eb 100644 --- a/Source/WebCore/storage/StorageEvent.idl +++ b/Source/WebCore/storage/StorageEvent.idl @@ -24,24 +24,32 @@ */ [ - ConstructorTemplate=Event, + Constructor(DOMString type, optional StorageEventInit eventInitDict) ] interface StorageEvent : Event { - [InitializedByEventConstructor] readonly attribute DOMString key; - [InitializedByEventConstructor, TreatReturnedNullStringAs=Null] readonly attribute DOMString oldValue; - [InitializedByEventConstructor, TreatReturnedNullStringAs=Null] readonly attribute DOMString newValue; - [InitializedByEventConstructor] readonly attribute DOMString url; - [InitializedByEventConstructor] readonly attribute Storage storageArea; + readonly attribute DOMString? key; + readonly attribute DOMString? oldValue; + readonly attribute DOMString? newValue; + readonly attribute USVString url; + readonly attribute Storage? storageArea; - void initStorageEvent([Default=Undefined] optional DOMString typeArg, - [Default=Undefined] optional boolean canBubbleArg, - [Default=Undefined] optional boolean cancelableArg, - [Default=Undefined] optional DOMString keyArg, - [Default=Undefined,TreatNullAs=NullString] optional DOMString oldValueArg, - [Default=Undefined,TreatNullAs=NullString] optional DOMString newValueArg, - [Default=Undefined] optional DOMString urlArg, - [Default=Undefined] optional Storage storageAreaArg); + // FIXME: Using "undefined" as default parameter value is wrong. + void initStorageEvent(optional DOMString typeArg = "undefined", + optional boolean canBubbleArg = false, + optional boolean cancelableArg = false, + optional DOMString keyArg = "undefined", + optional DOMString? oldValueArg = null, + optional DOMString? newValueArg = null, + optional USVString urlArg = "undefined", + optional Storage? storageAreaArg = null); // Needed once we support init<blank>EventNS - // void initStorageEventNS(DOMString namespaceURI, DOMString typeArg, boolean canBubbleArg, boolean cancelableArg, DOMString keyArg, DOMString oldValueArg, DOMString newValueArg, DOMString urlArg, Storage storageAreaArg); + // void initStorageEventNS(DOMString namespaceURI, DOMString typeArg, boolean canBubbleArg, boolean cancelableArg, DOMString keyArg, DOMString oldValueArg, DOMString newValueArg, USVString urlArg, Storage? storageAreaArg); }; +dictionary StorageEventInit : EventInit { + DOMString? key = null; + DOMString? oldValue = null; + DOMString? newValue = null; + USVString url = ""; + Storage? storageArea = null; +}; diff --git a/Source/WebCore/storage/StorageEventDispatcher.cpp b/Source/WebCore/storage/StorageEventDispatcher.cpp index b4de9b857..ab89263d5 100644 --- a/Source/WebCore/storage/StorageEventDispatcher.cpp +++ b/Source/WebCore/storage/StorageEventDispatcher.cpp @@ -34,11 +34,13 @@ #include "Page.h" #include "PageGroup.h" #include "SecurityOrigin.h" +#include "SecurityOriginData.h" #include "StorageEvent.h" +#include "StorageType.h" namespace WebCore { -void StorageEventDispatcher::dispatchSessionStorageEvents(const String& key, const String& oldValue, const String& newValue, SecurityOrigin* securityOrigin, Frame* sourceFrame) +void StorageEventDispatcher::dispatchSessionStorageEvents(const String& key, const String& oldValue, const String& newValue, const SecurityOriginData& securityOrigin, Frame* sourceFrame) { Page* page = sourceFrame->page(); if (!page) @@ -48,14 +50,14 @@ void StorageEventDispatcher::dispatchSessionStorageEvents(const String& key, con // Send events only to our page. for (Frame* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext()) { - if (sourceFrame != frame && frame->document()->securityOrigin()->equal(securityOrigin)) + if (sourceFrame != frame && frame->document()->securityOrigin().equal(securityOrigin.securityOrigin().ptr())) frames.append(frame); } dispatchSessionStorageEventsToFrames(*page, frames, key, oldValue, newValue, sourceFrame->document()->url(), securityOrigin); } -void StorageEventDispatcher::dispatchLocalStorageEvents(const String& key, const String& oldValue, const String& newValue, SecurityOrigin* securityOrigin, Frame* sourceFrame) +void StorageEventDispatcher::dispatchLocalStorageEvents(const String& key, const String& oldValue, const String& newValue, const SecurityOriginData& securityOrigin, Frame* sourceFrame) { Page* page = sourceFrame->page(); if (!page) @@ -64,10 +66,9 @@ void StorageEventDispatcher::dispatchLocalStorageEvents(const String& key, const Vector<RefPtr<Frame>> frames; // Send events to every page. - const HashSet<Page*>& pages = page->group().pages(); - for (HashSet<Page*>::const_iterator it = pages.begin(), end = pages.end(); it != end; ++it) { - for (Frame* frame = &(*it)->mainFrame(); frame; frame = frame->tree().traverseNext()) { - if (sourceFrame != frame && frame->document()->securityOrigin()->equal(securityOrigin)) + for (auto& pageInGroup : page->group().pages()) { + for (Frame* frame = &pageInGroup->mainFrame(); frame; frame = frame->tree().traverseNext()) { + if (sourceFrame != frame && frame->document()->securityOrigin().equal(securityOrigin.securityOrigin().ptr())) frames.append(frame); } } @@ -75,29 +76,26 @@ void StorageEventDispatcher::dispatchLocalStorageEvents(const String& key, const dispatchLocalStorageEventsToFrames(page->group(), frames, key, oldValue, newValue, sourceFrame->document()->url(), securityOrigin); } -void StorageEventDispatcher::dispatchSessionStorageEventsToFrames(Page& page, const Vector<RefPtr<Frame>>& frames, const String& key, const String& oldValue, const String& newValue, const String& url, SecurityOrigin* securityOrigin) +void StorageEventDispatcher::dispatchSessionStorageEventsToFrames(Page& page, const Vector<RefPtr<Frame>>& frames, const String& key, const String& oldValue, const String& newValue, const String& url, const SecurityOriginData& securityOrigin) { - InspectorInstrumentation::didDispatchDOMStorageEvent(key, oldValue, newValue, SessionStorage, securityOrigin, &page); + InspectorInstrumentation::didDispatchDOMStorageEvent(page, key, oldValue, newValue, StorageType::Session, securityOrigin.securityOrigin().ptr()); - for (unsigned i = 0; i < frames.size(); ++i) { - ExceptionCode ec = 0; - Storage* storage = frames[i]->document()->domWindow()->sessionStorage(ec); - if (!ec) - frames[i]->document()->enqueueWindowEvent(StorageEvent::create(eventNames().storageEvent, key, oldValue, newValue, url, storage)); + for (auto& frame : frames) { + auto result = frame->document()->domWindow()->sessionStorage(); + if (!result.hasException()) + frame->document()->enqueueWindowEvent(StorageEvent::create(eventNames().storageEvent, key, oldValue, newValue, url, result.releaseReturnValue())); } } -void StorageEventDispatcher::dispatchLocalStorageEventsToFrames(PageGroup& pageGroup, const Vector<RefPtr<Frame>>& frames, const String& key, const String& oldValue, const String& newValue, const String& url, SecurityOrigin* securityOrigin) +void StorageEventDispatcher::dispatchLocalStorageEventsToFrames(PageGroup& pageGroup, const Vector<RefPtr<Frame>>& frames, const String& key, const String& oldValue, const String& newValue, const String& url, const SecurityOriginData& securityOrigin) { - const HashSet<Page*>& pages = pageGroup.pages(); - for (HashSet<Page*>::const_iterator it = pages.begin(), end = pages.end(); it != end; ++it) - InspectorInstrumentation::didDispatchDOMStorageEvent(key, oldValue, newValue, LocalStorage, securityOrigin, *it); - - for (unsigned i = 0; i < frames.size(); ++i) { - ExceptionCode ec = 0; - Storage* storage = frames[i]->document()->domWindow()->localStorage(ec); - if (!ec) - frames[i]->document()->enqueueWindowEvent(StorageEvent::create(eventNames().storageEvent, key, oldValue, newValue, url, storage)); + for (auto& page : pageGroup.pages()) + InspectorInstrumentation::didDispatchDOMStorageEvent(*page, key, oldValue, newValue, StorageType::Local, securityOrigin.securityOrigin().ptr()); + + for (auto& frame : frames) { + auto result = frame->document()->domWindow()->localStorage(); + if (!result.hasException()) + frame->document()->enqueueWindowEvent(StorageEvent::create(eventNames().storageEvent, key, oldValue, newValue, url, result.releaseReturnValue())); } } diff --git a/Source/WebCore/storage/StorageEventDispatcher.h b/Source/WebCore/storage/StorageEventDispatcher.h index 056a2946c..6fa9510dd 100644 --- a/Source/WebCore/storage/StorageEventDispatcher.h +++ b/Source/WebCore/storage/StorageEventDispatcher.h @@ -11,7 +11,7 @@ * 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. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -27,8 +27,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef StorageEventDispatcher_h -#define StorageEventDispatcher_h +#pragma once #include <wtf/Forward.h> #include <wtf/Vector.h> @@ -38,20 +37,18 @@ namespace WebCore { class Frame; class Page; class PageGroup; -class SecurityOrigin; +struct SecurityOriginData; class StorageEventDispatcher { public: - static void dispatchSessionStorageEvents(const String& key, const String& oldValue, const String& newValue, SecurityOrigin*, Frame* sourceFrame); - static void dispatchLocalStorageEvents(const String& key, const String& oldValue, const String& newValue, SecurityOrigin*, Frame* sourceFrame); + WEBCORE_EXPORT static void dispatchSessionStorageEvents(const String& key, const String& oldValue, const String& newValue, const SecurityOriginData&, Frame* sourceFrame); + WEBCORE_EXPORT static void dispatchLocalStorageEvents(const String& key, const String& oldValue, const String& newValue, const SecurityOriginData&, Frame* sourceFrame); - static void dispatchSessionStorageEventsToFrames(Page&, const Vector<RefPtr<Frame>>& frames, const String& key, const String& oldValue, const String& newValue, const String& url, SecurityOrigin*); - static void dispatchLocalStorageEventsToFrames(PageGroup&, const Vector<RefPtr<Frame>>& frames, const String& key, const String& oldValue, const String& newValue, const String& url, SecurityOrigin*); + WEBCORE_EXPORT static void dispatchSessionStorageEventsToFrames(Page&, const Vector<RefPtr<Frame>>& frames, const String& key, const String& oldValue, const String& newValue, const String& url, const SecurityOriginData&); + WEBCORE_EXPORT static void dispatchLocalStorageEventsToFrames(PageGroup&, const Vector<RefPtr<Frame>>& frames, const String& key, const String& oldValue, const String& newValue, const String& url, const SecurityOriginData&); private: // Do not instantiate. StorageEventDispatcher(); }; } // namespace WebCore - -#endif // StorageEventDispatcher_h diff --git a/Source/WebCore/storage/StorageMap.cpp b/Source/WebCore/storage/StorageMap.cpp index fb7e43571..15598a8de 100644 --- a/Source/WebCore/storage/StorageMap.cpp +++ b/Source/WebCore/storage/StorageMap.cpp @@ -26,13 +26,13 @@ #include "config.h" #include "StorageMap.h" -#include <wtf/TemporaryChange.h> +#include <wtf/SetForScope.h> namespace WebCore { -PassRefPtr<StorageMap> StorageMap::create(unsigned quota) +Ref<StorageMap> StorageMap::create(unsigned quota) { - return adoptRef(new StorageMap(quota)); + return adoptRef(*new StorageMap(quota)); } StorageMap::StorageMap(unsigned quota) @@ -43,12 +43,12 @@ StorageMap::StorageMap(unsigned quota) { } -PassRefPtr<StorageMap> StorageMap::copy() +Ref<StorageMap> StorageMap::copy() { - RefPtr<StorageMap> newMap = create(m_quotaSize); + Ref<StorageMap> newMap = create(m_quotaSize); newMap->m_map = m_map; newMap->m_currentLength = m_currentLength; - return newMap.release(); + return newMap; } void StorageMap::invalidateIterator() @@ -99,7 +99,7 @@ String StorageMap::getItem(const String& key) const return m_map.get(key); } -PassRefPtr<StorageMap> StorageMap::setItem(const String& key, const String& value, String& oldValue, bool& quotaException) +RefPtr<StorageMap> StorageMap::setItem(const String& key, const String& value, String& oldValue, bool& quotaException) { ASSERT(!value.isNull()); quotaException = false; @@ -109,7 +109,7 @@ PassRefPtr<StorageMap> StorageMap::setItem(const String& key, const String& valu if (refCount() > 1) { RefPtr<StorageMap> newStorageMap = copy(); newStorageMap->setItem(key, value, oldValue, quotaException); - return newStorageMap.release(); + return newStorageMap; } // Quota tracking. This is done in a couple of steps to keep the overflow tracking simple. @@ -129,7 +129,7 @@ PassRefPtr<StorageMap> StorageMap::setItem(const String& key, const String& valu bool overQuota = newLength > m_quotaSize / sizeof(UChar); if (m_quotaSize != noQuota && (overflow || overQuota)) { quotaException = true; - return 0; + return nullptr; } m_currentLength = newLength; @@ -139,12 +139,12 @@ PassRefPtr<StorageMap> StorageMap::setItem(const String& key, const String& valu invalidateIterator(); - return 0; + return nullptr; } -PassRefPtr<StorageMap> StorageMap::setItemIgnoringQuota(const String& key, const String& value) +RefPtr<StorageMap> StorageMap::setItemIgnoringQuota(const String& key, const String& value) { - TemporaryChange<unsigned> quotaSizeChange(m_quotaSize, noQuota); + SetForScope<unsigned> quotaSizeChange(m_quotaSize, static_cast<unsigned>(noQuota)); String oldValue; bool quotaException; @@ -152,17 +152,17 @@ PassRefPtr<StorageMap> StorageMap::setItemIgnoringQuota(const String& key, const RefPtr<StorageMap> map = setItem(key, value, oldValue, quotaException); ASSERT(!quotaException); - return map.release(); + return map; } -PassRefPtr<StorageMap> StorageMap::removeItem(const String& key, String& oldValue) +RefPtr<StorageMap> StorageMap::removeItem(const String& key, String& oldValue) { // Implement copy-on-write semantics here. We're guaranteed that the only refs of StorageMaps belong to Storage objects // so if more than one Storage object refs this map, copy it before mutating it. if (refCount() > 1) { RefPtr<StorageMap> newStorage = copy(); newStorage->removeItem(key, oldValue); - return newStorage.release(); + return newStorage; } oldValue = m_map.take(key); @@ -174,7 +174,7 @@ PassRefPtr<StorageMap> StorageMap::removeItem(const String& key, String& oldValu ASSERT(m_currentLength - oldValue.length() <= m_currentLength); m_currentLength -= oldValue.length(); - return 0; + return nullptr; } bool StorageMap::contains(const String& key) const @@ -184,9 +184,9 @@ bool StorageMap::contains(const String& key) const void StorageMap::importItems(const HashMap<String, String>& items) { - for (HashMap<String, String>::const_iterator it = items.begin(), end = items.end(); it != end; ++it) { - const String& key = it->key; - const String& value = it->value; + for (auto& item : items) { + const String& key = item.key; + const String& value = item.value; HashMap<String, String>::AddResult result = m_map.add(key, value); ASSERT_UNUSED(result, result.isNewEntry); // True if the key didn't exist previously. diff --git a/Source/WebCore/storage/StorageMap.h b/Source/WebCore/storage/StorageMap.h index 594c2d8c3..fcdcca434 100644 --- a/Source/WebCore/storage/StorageMap.h +++ b/Source/WebCore/storage/StorageMap.h @@ -23,11 +23,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef StorageMap_h -#define StorageMap_h +#pragma once #include <wtf/HashMap.h> -#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/text/StringHash.h> #include <wtf/text/WTFString.h> @@ -37,27 +35,28 @@ namespace WebCore { class StorageMap : public RefCounted<StorageMap> { public: // Quota size measured in bytes. - static PassRefPtr<StorageMap> create(unsigned quotaSize); + WEBCORE_EXPORT static Ref<StorageMap> create(unsigned quotaSize); - unsigned length() const; - String key(unsigned index); - String getItem(const String&) const; - PassRefPtr<StorageMap> setItem(const String& key, const String& value, String& oldValue, bool& quotaException); - PassRefPtr<StorageMap> setItemIgnoringQuota(const String& key, const String& value); - PassRefPtr<StorageMap> removeItem(const String&, String& oldValue); + WEBCORE_EXPORT unsigned length() const; + WEBCORE_EXPORT String key(unsigned index); + WEBCORE_EXPORT String getItem(const String&) const; + WEBCORE_EXPORT RefPtr<StorageMap> setItem(const String& key, const String& value, String& oldValue, bool& quotaException); + WEBCORE_EXPORT RefPtr<StorageMap> setItemIgnoringQuota(const String& key, const String& value); + WEBCORE_EXPORT RefPtr<StorageMap> removeItem(const String&, String& oldValue); - bool contains(const String& key) const; + WEBCORE_EXPORT bool contains(const String& key) const; - void importItems(const HashMap<String, String>&); + WEBCORE_EXPORT void importItems(const HashMap<String, String>&); const HashMap<String, String>& items() const { return m_map; } unsigned quota() const { return m_quotaSize; } - static const unsigned noQuota = UINT_MAX; + WEBCORE_EXPORT Ref<StorageMap> copy(); + + static const constexpr unsigned noQuota = UINT_MAX; private: explicit StorageMap(unsigned quota); - PassRefPtr<StorageMap> copy(); void invalidateIterator(); void setIteratorToIndex(unsigned); @@ -70,5 +69,3 @@ private: }; } // namespace WebCore - -#endif // StorageMap_h diff --git a/Source/WebCore/storage/StorageNamespace.h b/Source/WebCore/storage/StorageNamespace.h index 1aef9e6fe..ead71a476 100644 --- a/Source/WebCore/storage/StorageNamespace.h +++ b/Source/WebCore/storage/StorageNamespace.h @@ -23,36 +23,22 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef StorageNamespace_h -#define StorageNamespace_h +#pragma once #include <wtf/Forward.h> -#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> namespace WebCore { class Page; -class PageGroup; -class SecurityOrigin; class StorageArea; +struct SecurityOriginData; class StorageNamespace : public RefCounted<StorageNamespace> { public: - static PassRefPtr<StorageNamespace> localStorageNamespace(PageGroup*); - static PassRefPtr<StorageNamespace> transientLocalStorageNamespace(PageGroup*, SecurityOrigin*); - static PassRefPtr<StorageNamespace> sessionStorageNamespace(Page*); - virtual ~StorageNamespace() { } - virtual PassRefPtr<StorageArea> storageArea(PassRefPtr<SecurityOrigin>) = 0; - virtual PassRefPtr<StorageNamespace> copy(Page* newPage) = 0; - virtual void close() = 0; - virtual void clearOriginForDeletion(SecurityOrigin*) = 0; - virtual void clearAllOriginsForDeletion() = 0; - virtual void sync() = 0; - virtual void closeIdleLocalStorageDatabases() { } + virtual RefPtr<StorageArea> storageArea(const SecurityOriginData&) = 0; + virtual RefPtr<StorageNamespace> copy(Page* newPage) = 0; }; } // namespace WebCore - -#endif // StorageNamespace_h diff --git a/Source/WebCore/storage/StorageNamespaceImpl.cpp b/Source/WebCore/storage/StorageNamespaceImpl.cpp deleted file mode 100644 index 2ac5db4a7..000000000 --- a/Source/WebCore/storage/StorageNamespaceImpl.cpp +++ /dev/null @@ -1,195 +0,0 @@ -/* - * 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 "StorageNamespaceImpl.h" - -#include "GroupSettings.h" -#include "Page.h" -#include "PageGroup.h" -#include "SecurityOriginHash.h" -#include "Settings.h" -#include "StorageAreaImpl.h" -#include "StorageMap.h" -#include "StorageSyncManager.h" -#include "StorageTracker.h" -#include <wtf/MainThread.h> -#include <wtf/StdLibExtras.h> -#include <wtf/text/StringHash.h> - -namespace WebCore { - -typedef HashMap<String, StorageNamespace*> LocalStorageNamespaceMap; - -static LocalStorageNamespaceMap& localStorageNamespaceMap() -{ - DEFINE_STATIC_LOCAL(LocalStorageNamespaceMap, localStorageNamespaceMap, ()); - return localStorageNamespaceMap; -} - -PassRefPtr<StorageNamespace> StorageNamespaceImpl::localStorageNamespace(PageGroup* pageGroup) -{ - // Need a page in this page group to query the settings for the local storage database path. - // Having these parameters attached to the page settings is unfortunate since these settings are - // not per-page (and, in fact, we simply grab the settings from some page at random), but - // at this point we're stuck with it. - Page* page = *pageGroup->pages().begin(); - const String& path = page->settings().localStorageDatabasePath(); - unsigned quota = pageGroup->groupSettings().localStorageQuotaBytes(); - const String lookupPath = path.isNull() ? emptyString() : path; - - LocalStorageNamespaceMap::AddResult result = localStorageNamespaceMap().add(lookupPath, nullptr); - if (!result.isNewEntry) - return result.iterator->value; - - RefPtr<StorageNamespace> storageNamespace = adoptRef(new StorageNamespaceImpl(LocalStorage, lookupPath, quota)); - - result.iterator->value = storageNamespace.get(); - return storageNamespace.release(); -} - -PassRefPtr<StorageNamespace> StorageNamespaceImpl::sessionStorageNamespace(Page* page) -{ - return adoptRef(new StorageNamespaceImpl(SessionStorage, String(), page->settings().sessionStorageQuota())); -} - -PassRefPtr<StorageNamespace> StorageNamespaceImpl::transientLocalStorageNamespace(PageGroup* pageGroup, SecurityOrigin*) -{ - // FIXME: A smarter implementation would create a special namespace type instead of just piggy-backing off - // SessionStorageNamespace here. - return StorageNamespaceImpl::sessionStorageNamespace(*pageGroup->pages().begin()); -} - -StorageNamespaceImpl::StorageNamespaceImpl(StorageType storageType, const String& path, unsigned quota) - : m_storageType(storageType) - , m_path(path.isolatedCopy()) - , m_syncManager(0) - , m_quota(quota) - , m_isShutdown(false) -{ - if (m_storageType == LocalStorage && !m_path.isEmpty()) - m_syncManager = StorageSyncManager::create(m_path); -} - -StorageNamespaceImpl::~StorageNamespaceImpl() -{ - ASSERT(isMainThread()); - - if (m_storageType == LocalStorage) { - ASSERT(localStorageNamespaceMap().get(m_path) == this); - localStorageNamespaceMap().remove(m_path); - } - - if (!m_isShutdown) - close(); -} - -PassRefPtr<StorageNamespace> StorageNamespaceImpl::copy(Page*) -{ - ASSERT(isMainThread()); - ASSERT(!m_isShutdown); - ASSERT(m_storageType == SessionStorage); - - RefPtr<StorageNamespaceImpl> newNamespace = adoptRef(new StorageNamespaceImpl(m_storageType, m_path, m_quota)); - - StorageAreaMap::iterator end = m_storageAreaMap.end(); - for (StorageAreaMap::iterator i = m_storageAreaMap.begin(); i != end; ++i) - newNamespace->m_storageAreaMap.set(i->key, i->value->copy()); - return newNamespace.release(); -} - -PassRefPtr<StorageArea> StorageNamespaceImpl::storageArea(PassRefPtr<SecurityOrigin> prpOrigin) -{ - ASSERT(isMainThread()); - ASSERT(!m_isShutdown); - - RefPtr<SecurityOrigin> origin = prpOrigin; - RefPtr<StorageAreaImpl> storageArea; - if ((storageArea = m_storageAreaMap.get(origin))) - return storageArea.release(); - - storageArea = StorageAreaImpl::create(m_storageType, origin, m_syncManager, m_quota); - m_storageAreaMap.set(origin.release(), storageArea); - return storageArea.release(); -} - -void StorageNamespaceImpl::close() -{ - ASSERT(isMainThread()); - - if (m_isShutdown) - return; - - // If we're session storage, we shouldn't need to do any work here. - if (m_storageType == SessionStorage) { - ASSERT(!m_syncManager); - return; - } - - StorageAreaMap::iterator end = m_storageAreaMap.end(); - for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it) - it->value->close(); - - if (m_syncManager) - m_syncManager->close(); - - m_isShutdown = true; -} - -void StorageNamespaceImpl::clearOriginForDeletion(SecurityOrigin* origin) -{ - ASSERT(isMainThread()); - - RefPtr<StorageAreaImpl> storageArea = m_storageAreaMap.get(origin); - if (storageArea) - storageArea->clearForOriginDeletion(); -} - -void StorageNamespaceImpl::clearAllOriginsForDeletion() -{ - ASSERT(isMainThread()); - - StorageAreaMap::iterator end = m_storageAreaMap.end(); - for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it) - it->value->clearForOriginDeletion(); -} - -void StorageNamespaceImpl::sync() -{ - ASSERT(isMainThread()); - StorageAreaMap::iterator end = m_storageAreaMap.end(); - for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it) - it->value->sync(); -} - -void StorageNamespaceImpl::closeIdleLocalStorageDatabases() -{ - ASSERT(isMainThread()); - StorageAreaMap::iterator end = m_storageAreaMap.end(); - for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it) - it->value->closeDatabaseIfIdle(); -} - -} // namespace WebCore diff --git a/Source/WebCore/storage/StorageNamespaceImpl.h b/Source/WebCore/storage/StorageNamespaceImpl.h deleted file mode 100644 index 8e77c338e..000000000 --- a/Source/WebCore/storage/StorageNamespaceImpl.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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 StorageNamespaceImpl_h -#define StorageNamespaceImpl_h - -#include "SecurityOriginHash.h" -#include "StorageArea.h" -#include "StorageNamespace.h" -#include <wtf/HashMap.h> -#include <wtf/RefPtr.h> -#include <wtf/text/WTFString.h> - -namespace WebCore { - -class StorageAreaImpl; - -class StorageNamespaceImpl : public StorageNamespace { -public: - static PassRefPtr<StorageNamespace> localStorageNamespace(PageGroup*); - static PassRefPtr<StorageNamespace> transientLocalStorageNamespace(PageGroup*, SecurityOrigin*); - static PassRefPtr<StorageNamespace> sessionStorageNamespace(Page*); - virtual ~StorageNamespaceImpl(); - - 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*) override; - virtual void clearAllOriginsForDeletion() override; - virtual void sync() override; - virtual void closeIdleLocalStorageDatabases() override; - -private: - StorageNamespaceImpl(StorageType, const String& path, unsigned quota); - - typedef HashMap<RefPtr<SecurityOrigin>, RefPtr<StorageAreaImpl>> StorageAreaMap; - StorageAreaMap m_storageAreaMap; - - StorageType m_storageType; - - // Only used if m_storageType == LocalStorage and the path was not "" in our constructor. - String m_path; - RefPtr<StorageSyncManager> m_syncManager; - - // The default quota for each new storage area. - unsigned m_quota; - - bool m_isShutdown; -}; - -} // namespace WebCore - -#endif // StorageNamespaceImpl_h diff --git a/Source/WebCore/storage/StorageNamespaceProvider.cpp b/Source/WebCore/storage/StorageNamespaceProvider.cpp new file mode 100644 index 000000000..8c4af42f8 --- /dev/null +++ b/Source/WebCore/storage/StorageNamespaceProvider.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2014 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. AND ITS CONTRIBUTORS ``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 ITS 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 "StorageNamespaceProvider.h" + +#include "Document.h" +#include "Page.h" +#include "SecurityOriginData.h" +#include "StorageArea.h" +#include "StorageNamespace.h" + +namespace WebCore { + +// Suggested by the HTML5 spec. +unsigned localStorageDatabaseQuotaInBytes = 5 * 1024 * 1024; + +StorageNamespaceProvider::StorageNamespaceProvider() +{ +} + +StorageNamespaceProvider::~StorageNamespaceProvider() +{ + ASSERT(m_pages.isEmpty()); +} + +void StorageNamespaceProvider::addPage(Page& page) +{ + ASSERT(!m_pages.contains(&page)); + + m_pages.add(&page); +} + +void StorageNamespaceProvider::removePage(Page& page) +{ + ASSERT(m_pages.contains(&page)); + + m_pages.remove(&page); +} + +RefPtr<StorageArea> StorageNamespaceProvider::localStorageArea(Document& document) +{ + // This StorageNamespaceProvider was retrieved from the Document's Page, + // so the Document had better still actually have a Page. + ASSERT(document.page()); + + bool ephemeral = document.page()->usesEphemeralSession(); + bool transient = !document.securityOrigin().canAccessLocalStorage(&document.topOrigin()); + + RefPtr<StorageNamespace> storageNamespace; + + if (transient) + storageNamespace = &transientLocalStorageNamespace(document.topOrigin()); + else if (ephemeral) + storageNamespace = document.page()->ephemeralLocalStorage(); + else + storageNamespace = &localStorageNamespace(); + + return storageNamespace->storageArea(SecurityOriginData::fromSecurityOrigin(document.securityOrigin())); +} + +StorageNamespace& StorageNamespaceProvider::localStorageNamespace() +{ + if (!m_localStorageNamespace) + m_localStorageNamespace = createLocalStorageNamespace(localStorageDatabaseQuotaInBytes); + + return *m_localStorageNamespace; +} + +StorageNamespace& StorageNamespaceProvider::transientLocalStorageNamespace(SecurityOrigin& securityOrigin) +{ + auto& slot = m_transientLocalStorageMap.add(&securityOrigin, nullptr).iterator->value; + if (!slot) + slot = createTransientLocalStorageNamespace(securityOrigin, localStorageDatabaseQuotaInBytes); + + return *slot; +} + +} diff --git a/Source/WebCore/storage/StorageStrategy.h b/Source/WebCore/storage/StorageNamespaceProvider.h index 4edd497df..1916ccb22 100644 --- a/Source/WebCore/storage/StorageStrategy.h +++ b/Source/WebCore/storage/StorageNamespaceProvider.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2014 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,30 +23,49 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef StorageStrategy_h -#define StorageStrategy_h +#pragma once +#include "SecurityOriginHash.h" #include <wtf/Forward.h> +#include <wtf/HashMap.h> +#include <wtf/HashSet.h> +#include <wtf/RefCounted.h> namespace WebCore { +class Document; class Page; -class PageGroup; class SecurityOrigin; +class StorageArea; class StorageNamespace; -class StorageStrategy { +class StorageNamespaceProvider : public RefCounted<StorageNamespaceProvider> { public: - virtual PassRefPtr<StorageNamespace> localStorageNamespace(PageGroup*); - virtual PassRefPtr<StorageNamespace> transientLocalStorageNamespace(PageGroup*, SecurityOrigin*); - virtual PassRefPtr<StorageNamespace> sessionStorageNamespace(Page*); + WEBCORE_EXPORT StorageNamespaceProvider(); + WEBCORE_EXPORT virtual ~StorageNamespaceProvider(); + + virtual RefPtr<StorageNamespace> createSessionStorageNamespace(Page&, unsigned quota) = 0; + virtual RefPtr<StorageNamespace> createEphemeralLocalStorageNamespace(Page&, unsigned quota) = 0; + + RefPtr<StorageArea> localStorageArea(Document&); + + void addPage(Page&); + void removePage(Page&); protected: - virtual ~StorageStrategy() - { - } + StorageNamespace* optionalLocalStorageNamespace() { return m_localStorageNamespace.get(); } + +private: + StorageNamespace& localStorageNamespace(); + StorageNamespace& transientLocalStorageNamespace(SecurityOrigin&); + + virtual RefPtr<StorageNamespace> createLocalStorageNamespace(unsigned quota) = 0; + virtual RefPtr<StorageNamespace> createTransientLocalStorageNamespace(SecurityOrigin&, unsigned quota) = 0; + + HashSet<Page*> m_pages; + + RefPtr<StorageNamespace> m_localStorageNamespace; + HashMap<RefPtr<SecurityOrigin>, RefPtr<StorageNamespace>> m_transientLocalStorageMap; }; } // namespace WebCore - -#endif // StorageStrategy_h diff --git a/Source/WebCore/storage/StorageStrategy.cpp b/Source/WebCore/storage/StorageStrategy.cpp deleted file mode 100644 index 88b84f417..000000000 --- a/Source/WebCore/storage/StorageStrategy.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2013 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. AND ITS CONTRIBUTORS ``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 ITS 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 "StorageStrategy.h" - -#include "StorageNamespaceImpl.h" - -namespace WebCore { - -PassRefPtr<StorageNamespace> StorageStrategy::localStorageNamespace(PageGroup* pageGroup) -{ - return StorageNamespaceImpl::localStorageNamespace(pageGroup); -} - -PassRefPtr<StorageNamespace> StorageStrategy::sessionStorageNamespace(Page* page) -{ - return StorageNamespaceImpl::sessionStorageNamespace(page); -} - -PassRefPtr<StorageNamespace> StorageStrategy::transientLocalStorageNamespace(PageGroup* pageGroup, SecurityOrigin* securityOrigin) -{ - return StorageNamespaceImpl::transientLocalStorageNamespace(pageGroup, securityOrigin); -} - -} // namespace WebCore diff --git a/Source/WebCore/storage/StorageSyncManager.cpp b/Source/WebCore/storage/StorageSyncManager.cpp deleted file mode 100644 index 22197d579..000000000 --- a/Source/WebCore/storage/StorageSyncManager.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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 "StorageSyncManager.h" - -#include "EventNames.h" -#include "FileSystem.h" -#include "Frame.h" -#include "FrameTree.h" -#include "StorageThread.h" -#include "Page.h" -#include "PageGroup.h" -#include "StorageAreaSync.h" -#include <wtf/MainThread.h> -#include <wtf/StdLibExtras.h> -#include <wtf/text/CString.h> - -namespace WebCore { - -PassRefPtr<StorageSyncManager> StorageSyncManager::create(const String& path) -{ - return adoptRef(new StorageSyncManager(path)); -} - -StorageSyncManager::StorageSyncManager(const String& path) - : m_thread(std::make_unique<StorageThread>()) - , m_path(path.isolatedCopy()) -{ - ASSERT(isMainThread()); - ASSERT(!m_path.isEmpty()); - m_thread->start(); -} - -StorageSyncManager::~StorageSyncManager() -{ - ASSERT(isMainThread()); - ASSERT(!m_thread); -} - -// Called on a background thread. -String StorageSyncManager::fullDatabaseFilename(const String& databaseIdentifier) -{ - if (!makeAllDirectories(m_path)) { - LOG_ERROR("Unabled to create LocalStorage database path %s", m_path.utf8().data()); - return String(); - } - - return pathByAppendingComponent(m_path, databaseIdentifier + ".localstorage"); -} - -void StorageSyncManager::dispatch(const Function<void ()>& function) -{ - ASSERT(isMainThread()); - ASSERT(m_thread); - - if (m_thread) - m_thread->dispatch(function); -} - -void StorageSyncManager::close() -{ - ASSERT(isMainThread()); - - if (m_thread) { - m_thread->terminate(); - m_thread = nullptr; - } -} - -} // namespace WebCore diff --git a/Source/WebCore/storage/StorageSyncManager.h b/Source/WebCore/storage/StorageSyncManager.h deleted file mode 100644 index 64d010097..000000000 --- a/Source/WebCore/storage/StorageSyncManager.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 StorageSyncManager_h -#define StorageSyncManager_h - -#include <wtf/Forward.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/text/WTFString.h> - -namespace WebCore { - -class StorageThread; -class StorageAreaSync; - -class StorageSyncManager : public RefCounted<StorageSyncManager> { -public: - static PassRefPtr<StorageSyncManager> create(const String& path); - ~StorageSyncManager(); - - void dispatch(const Function<void ()>&); - void close(); - -private: - explicit StorageSyncManager(const String& path); - - std::unique_ptr<StorageThread> m_thread; - -// The following members are subject to thread synchronization issues -public: - // To be called from the background thread: - String fullDatabaseFilename(const String& databaseIdentifier); - -private: - String m_path; -}; - -} // namespace WebCore - -#endif // StorageSyncManager_h diff --git a/Source/WebCore/storage/StorageThread.cpp b/Source/WebCore/storage/StorageThread.cpp deleted file mode 100644 index 78fbe7032..000000000 --- a/Source/WebCore/storage/StorageThread.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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 "StorageThread.h" - -#include "StorageAreaSync.h" -#include <wtf/AutodrainedPool.h> -#include <wtf/HashSet.h> -#include <wtf/MainThread.h> - -namespace WebCore { - -static HashSet<StorageThread*>& activeStorageThreads() -{ - ASSERT(isMainThread()); - DEFINE_STATIC_LOCAL(HashSet<StorageThread*>, threads, ()); - return threads; -} - -StorageThread::StorageThread() - : m_threadID(0) -{ - ASSERT(isMainThread()); -} - -StorageThread::~StorageThread() -{ - ASSERT(isMainThread()); - ASSERT(!m_threadID); -} - -bool StorageThread::start() -{ - ASSERT(isMainThread()); - if (!m_threadID) - m_threadID = createThread(StorageThread::threadEntryPointCallback, this, "WebCore: LocalStorage"); - activeStorageThreads().add(this); - return m_threadID; -} - -void StorageThread::threadEntryPointCallback(void* thread) -{ - static_cast<StorageThread*>(thread)->threadEntryPoint(); -} - -void StorageThread::threadEntryPoint() -{ - ASSERT(!isMainThread()); - - while (auto function = m_queue.waitForMessage()) { - AutodrainedPool pool; - (*function)(); - } -} - -void StorageThread::dispatch(const Function<void ()>& function) -{ - ASSERT(isMainThread()); - ASSERT(!m_queue.killed() && m_threadID); - m_queue.append(std::make_unique<Function<void ()>>(function)); -} - -void StorageThread::terminate() -{ - ASSERT(isMainThread()); - ASSERT(!m_queue.killed() && m_threadID); - activeStorageThreads().remove(this); - // Even in weird, exceptional cases, don't wait on a nonexistent thread to terminate. - if (!m_threadID) - return; - - m_queue.append(std::make_unique<Function<void ()>>(bind(&StorageThread::performTerminate, this))); - waitForThreadCompletion(m_threadID); - ASSERT(m_queue.killed()); - m_threadID = 0; -} - -void StorageThread::performTerminate() -{ - ASSERT(!isMainThread()); - m_queue.kill(); -} - -void StorageThread::releaseFastMallocFreeMemoryInAllThreads() -{ - HashSet<StorageThread*>& threads = activeStorageThreads(); - - for (HashSet<StorageThread*>::iterator it = threads.begin(), end = threads.end(); it != end; ++it) - (*it)->dispatch(bind(WTF::releaseFastMallocFreeMemory)); -} - -} diff --git a/Source/WebCore/storage/StorageThread.h b/Source/WebCore/storage/StorageThread.h deleted file mode 100644 index 8f092d080..000000000 --- a/Source/WebCore/storage/StorageThread.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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 StorageThread_h -#define StorageThread_h - -#include <wtf/Functional.h> -#include <wtf/HashSet.h> -#include <wtf/MessageQueue.h> -#include <wtf/PassRefPtr.h> -#include <wtf/Threading.h> - -namespace WebCore { - -class StorageAreaSync; -class StorageTask; - -class StorageThread { - WTF_MAKE_NONCOPYABLE(StorageThread); WTF_MAKE_FAST_ALLOCATED; -public: - StorageThread(); - ~StorageThread(); - - bool start(); - void terminate(); - - void dispatch(const Function<void()>&); - - static void releaseFastMallocFreeMemoryInAllThreads(); - -private: - // Called on background thread. - static void threadEntryPointCallback(void*); - void threadEntryPoint(); - - // Background thread part of the terminate procedure. - void performTerminate(); - - ThreadIdentifier m_threadID; - MessageQueue<Function<void ()>> m_queue; -}; - -} // namespace WebCore - -#endif // StorageThread_h diff --git a/Source/WebCore/storage/StorageTracker.cpp b/Source/WebCore/storage/StorageTracker.cpp deleted file mode 100644 index dc236c3f0..000000000 --- a/Source/WebCore/storage/StorageTracker.cpp +++ /dev/null @@ -1,626 +0,0 @@ -/* - * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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 "StorageTracker.h" - -#include "DatabaseThread.h" -#include "FileSystem.h" -#include "Logging.h" -#include "PageGroup.h" -#include "SQLiteDatabaseTracker.h" -#include "SQLiteFileSystem.h" -#include "SQLiteStatement.h" -#include "SecurityOrigin.h" -#include "StorageThread.h" -#include "StorageTrackerClient.h" -#include "TextEncoding.h" -#include <wtf/Functional.h> -#include <wtf/MainThread.h> -#include <wtf/StdLibExtras.h> -#include <wtf/Vector.h> -#include <wtf/text/CString.h> - -namespace WebCore { - -static StorageTracker* storageTracker = 0; - -// If there is no document referencing a storage database, close the underlying database -// after it has been idle for m_StorageDatabaseIdleInterval seconds. -static const double DefaultStorageDatabaseIdleInterval = 300; - -void StorageTracker::initializeTracker(const String& storagePath, StorageTrackerClient* client) -{ - ASSERT(isMainThread()); - ASSERT(!storageTracker || !storageTracker->m_client); - - if (!storageTracker) - storageTracker = new StorageTracker(storagePath); - - storageTracker->m_client = client; - storageTracker->m_needsInitialization = true; -} - -void StorageTracker::internalInitialize() -{ - m_needsInitialization = false; - - ASSERT(isMainThread()); - - // Make sure text encoding maps have been built on the main thread, as the StorageTracker thread might try to do it there instead. - // FIXME (<rdar://problem/9127819>): Is there a more explicit way of doing this besides accessing the UTF8Encoding? - UTF8Encoding(); - - storageTracker->setIsActive(true); - storageTracker->m_thread->start(); - storageTracker->importOriginIdentifiers(); -} - -StorageTracker& StorageTracker::tracker() -{ - if (!storageTracker) - storageTracker = new StorageTracker(""); - if (storageTracker->m_needsInitialization) - storageTracker->internalInitialize(); - - return *storageTracker; -} - -StorageTracker::StorageTracker(const String& storagePath) - : m_storageDirectoryPath(storagePath.isolatedCopy()) - , m_client(0) - , m_thread(std::make_unique<StorageThread>()) - , m_isActive(false) - , m_needsInitialization(false) - , m_StorageDatabaseIdleInterval(DefaultStorageDatabaseIdleInterval) -{ -} - -void StorageTracker::setDatabaseDirectoryPath(const String& path) -{ - MutexLocker locker(m_databaseMutex); - - if (m_database.isOpen()) - m_database.close(); - - m_storageDirectoryPath = path.isolatedCopy(); - - { - MutexLocker locker(m_originSetMutex); - m_originSet.clear(); - } - - if (!m_isActive) - return; - - importOriginIdentifiers(); -} - -String StorageTracker::databaseDirectoryPath() const -{ - return m_storageDirectoryPath.isolatedCopy(); -} - -String StorageTracker::trackerDatabasePath() -{ - ASSERT(!m_databaseMutex.tryLock()); - return SQLiteFileSystem::appendDatabaseFileNameToPath(m_storageDirectoryPath, "StorageTracker.db"); -} - -void StorageTracker::openTrackerDatabase(bool createIfDoesNotExist) -{ - ASSERT(m_isActive); - ASSERT(!isMainThread()); - - SQLiteTransactionInProgressAutoCounter transactionCounter; - - ASSERT(!m_databaseMutex.tryLock()); - - if (m_database.isOpen()) - return; - - String databasePath = trackerDatabasePath(); - - if (!SQLiteFileSystem::ensureDatabaseFileExists(databasePath, createIfDoesNotExist)) { - if (createIfDoesNotExist) - LOG_ERROR("Failed to create database file '%s'", databasePath.ascii().data()); - return; - } - - if (!m_database.open(databasePath)) { - LOG_ERROR("Failed to open databasePath %s.", databasePath.ascii().data()); - return; - } - - m_database.disableThreadingChecks(); - - if (!m_database.tableExists("Origins")) { - if (!m_database.executeCommand("CREATE TABLE Origins (origin TEXT UNIQUE ON CONFLICT REPLACE, path TEXT);")) - LOG_ERROR("Failed to create Origins table."); - } -} - -void StorageTracker::importOriginIdentifiers() -{ - if (!m_isActive) - return; - - ASSERT(isMainThread()); - ASSERT(m_thread); - - m_thread->dispatch(bind(&StorageTracker::syncImportOriginIdentifiers, this)); -} - -void StorageTracker::finishedImportingOriginIdentifiers() -{ - MutexLocker locker(m_databaseMutex); - if (m_client) - m_client->didFinishLoadingOrigins(); -} - -void StorageTracker::syncImportOriginIdentifiers() -{ - ASSERT(m_isActive); - - ASSERT(!isMainThread()); - - { - MutexLocker locker(m_databaseMutex); - - // Don't force creation of StorageTracker's db just because a tracker - // was initialized. It will be created if local storage dbs are found - // by syncFileSystemAndTrackerDatabse() or the next time a local storage - // db is created by StorageAreaSync. - openTrackerDatabase(false); - - if (m_database.isOpen()) { - SQLiteTransactionInProgressAutoCounter transactionCounter; - - SQLiteStatement statement(m_database, "SELECT origin FROM Origins"); - if (statement.prepare() != SQLResultOk) { - LOG_ERROR("Failed to prepare statement."); - return; - } - - int result; - - { - MutexLocker lockOrigins(m_originSetMutex); - while ((result = statement.step()) == SQLResultRow) - m_originSet.add(statement.getColumnText(0).isolatedCopy()); - } - - if (result != SQLResultDone) { - LOG_ERROR("Failed to read in all origins from the database."); - return; - } - } - } - - syncFileSystemAndTrackerDatabase(); - - { - MutexLocker locker(m_clientMutex); - - if (m_client) { - MutexLocker locker(m_originSetMutex); - OriginSet::const_iterator end = m_originSet.end(); - for (OriginSet::const_iterator it = m_originSet.begin(); it != end; ++it) - m_client->dispatchDidModifyOrigin(*it); - } - } - - callOnMainThread(bind(&StorageTracker::finishedImportingOriginIdentifiers, this)); -} - -void StorageTracker::syncFileSystemAndTrackerDatabase() -{ - ASSERT(!isMainThread()); - - SQLiteTransactionInProgressAutoCounter transactionCounter; - - ASSERT(m_isActive); - - Vector<String> paths; - { - MutexLocker locker(m_databaseMutex); - paths = listDirectory(m_storageDirectoryPath, "*.localstorage"); - } - - // Use a copy of m_originSet to find expired entries and to schedule their - // deletions from disk and from m_originSet. - OriginSet originSetCopy; - { - MutexLocker locker(m_originSetMutex); - for (OriginSet::const_iterator it = m_originSet.begin(), end = m_originSet.end(); it != end; ++it) - originSetCopy.add((*it).isolatedCopy()); - } - - // Add missing StorageTracker records. - OriginSet foundOrigins; - String fileExtension = ASCIILiteral(".localstorage"); - - for (Vector<String>::const_iterator it = paths.begin(), end = paths.end(); it != end; ++it) { - const String& path = *it; - - if (path.length() > fileExtension.length() && path.endsWith(fileExtension, true)) { - String file = pathGetFileName(path); - String originIdentifier = file.substring(0, file.length() - fileExtension.length()); - if (!originSetCopy.contains(originIdentifier)) - syncSetOriginDetails(originIdentifier, path); - - foundOrigins.add(originIdentifier); - } - } - - // Delete stale StorageTracker records. - for (OriginSet::const_iterator it = originSetCopy.begin(), end = originSetCopy.end(); it != end; ++it) { - const String& originIdentifier = *it; - if (foundOrigins.contains(originIdentifier)) - continue; - - callOnMainThread(bind(&StorageTracker::deleteOriginWithIdentifier, this, originIdentifier.isolatedCopy())); - } -} - -void StorageTracker::setOriginDetails(const String& originIdentifier, const String& databaseFile) -{ - if (!m_isActive) - return; - - { - MutexLocker locker(m_originSetMutex); - - if (m_originSet.contains(originIdentifier)) - return; - - m_originSet.add(originIdentifier); - } - - Function<void ()> function = bind(&StorageTracker::syncSetOriginDetails, this, originIdentifier.isolatedCopy(), databaseFile.isolatedCopy()); - - if (isMainThread()) { - ASSERT(m_thread); - m_thread->dispatch(function); - } else { - // FIXME: This weird ping-ponging was done to fix a deadlock. We should figure out a cleaner way to avoid it instead. - callOnMainThread(bind(&StorageThread::dispatch, m_thread.get(), function)); - } -} - -void StorageTracker::syncSetOriginDetails(const String& originIdentifier, const String& databaseFile) -{ - ASSERT(!isMainThread()); - - SQLiteTransactionInProgressAutoCounter transactionCounter; - - MutexLocker locker(m_databaseMutex); - - openTrackerDatabase(true); - - if (!m_database.isOpen()) - return; - - SQLiteStatement statement(m_database, "INSERT INTO Origins VALUES (?, ?)"); - if (statement.prepare() != SQLResultOk) { - LOG_ERROR("Unable to establish origin '%s' in the tracker", originIdentifier.ascii().data()); - return; - } - - statement.bindText(1, originIdentifier); - statement.bindText(2, databaseFile); - - if (statement.step() != SQLResultDone) - LOG_ERROR("Unable to establish origin '%s' in the tracker", originIdentifier.ascii().data()); - - { - MutexLocker locker(m_originSetMutex); - if (!m_originSet.contains(originIdentifier)) - m_originSet.add(originIdentifier); - } - - { - MutexLocker locker(m_clientMutex); - if (m_client) - m_client->dispatchDidModifyOrigin(originIdentifier); - } -} - -void StorageTracker::origins(Vector<RefPtr<SecurityOrigin>>& result) -{ - ASSERT(m_isActive); - - if (!m_isActive) - return; - - MutexLocker locker(m_originSetMutex); - - for (OriginSet::const_iterator it = m_originSet.begin(), end = m_originSet.end(); it != end; ++it) - result.append(SecurityOrigin::createFromDatabaseIdentifier(*it)); -} - -void StorageTracker::deleteAllOrigins() -{ - ASSERT(m_isActive); - ASSERT(isMainThread()); - ASSERT(m_thread); - - if (!m_isActive) - return; - - { - MutexLocker locker(m_originSetMutex); - willDeleteAllOrigins(); - m_originSet.clear(); - } - - PageGroup::clearLocalStorageForAllOrigins(); - - m_thread->dispatch(bind(&StorageTracker::syncDeleteAllOrigins, this)); -} - -void StorageTracker::syncDeleteAllOrigins() -{ - ASSERT(!isMainThread()); - - SQLiteTransactionInProgressAutoCounter transactionCounter; - - MutexLocker locker(m_databaseMutex); - - openTrackerDatabase(false); - if (!m_database.isOpen()) - return; - - SQLiteStatement statement(m_database, "SELECT origin, path FROM Origins"); - if (statement.prepare() != SQLResultOk) { - LOG_ERROR("Failed to prepare statement."); - return; - } - - int result; - while ((result = statement.step()) == SQLResultRow) { - if (!canDeleteOrigin(statement.getColumnText(0))) - continue; - - SQLiteFileSystem::deleteDatabaseFile(statement.getColumnText(1)); - - { - MutexLocker locker(m_clientMutex); - if (m_client) - m_client->dispatchDidModifyOrigin(statement.getColumnText(0)); - } - } - - if (result != SQLResultDone) - LOG_ERROR("Failed to read in all origins from the database."); - - if (m_database.isOpen()) { -#if PLATFORM(IOS) - SQLiteFileSystem::truncateDatabaseFile(m_database.sqlite3Handle()); -#endif - m_database.close(); - } - -#if !PLATFORM(IOS) - if (!SQLiteFileSystem::deleteDatabaseFile(trackerDatabasePath())) { - // In the case where it is not possible to delete the database file (e.g some other program - // like a virus scanner is accessing it), make sure to remove all entries. - openTrackerDatabase(false); - if (!m_database.isOpen()) - return; - SQLiteStatement deleteStatement(m_database, "DELETE FROM Origins"); - if (deleteStatement.prepare() != SQLResultOk) { - LOG_ERROR("Unable to prepare deletion of all origins"); - return; - } - if (!deleteStatement.executeCommand()) { - LOG_ERROR("Unable to execute deletion of all origins"); - return; - } - } - SQLiteFileSystem::deleteEmptyDatabaseDirectory(m_storageDirectoryPath); -#endif -} - -void StorageTracker::deleteOriginWithIdentifier(const String& originIdentifier) -{ - deleteOrigin(SecurityOrigin::createFromDatabaseIdentifier(originIdentifier).get()); -} - -void StorageTracker::deleteOrigin(SecurityOrigin* origin) -{ - ASSERT(m_isActive); - ASSERT(isMainThread()); - ASSERT(m_thread); - - if (!m_isActive) - return; - - // Before deleting database, we need to clear in-memory local storage data - // in StorageArea, and to close the StorageArea db. It's possible for an - // item to be added immediately after closing the db and cause StorageAreaSync - // to reopen the db before the db is deleted by a StorageTracker thread. - // In this case, reopening the db in StorageAreaSync will cancel a pending - // StorageTracker db deletion. - PageGroup::clearLocalStorageForOrigin(origin); - - String originId = origin->databaseIdentifier(); - - { - MutexLocker locker(m_originSetMutex); - willDeleteOrigin(originId); - m_originSet.remove(originId); - } - - m_thread->dispatch(bind(&StorageTracker::syncDeleteOrigin, this, originId.isolatedCopy())); -} - -void StorageTracker::syncDeleteOrigin(const String& originIdentifier) -{ - ASSERT(!isMainThread()); - - SQLiteTransactionInProgressAutoCounter transactionCounter; - - MutexLocker locker(m_databaseMutex); - - if (!canDeleteOrigin(originIdentifier)) { - LOG_ERROR("Attempted to delete origin '%s' while it was being created\n", originIdentifier.ascii().data()); - return; - } - - openTrackerDatabase(false); - if (!m_database.isOpen()) - return; - - String path = databasePathForOrigin(originIdentifier); - if (path.isEmpty()) { - // It is possible to get a request from the API to delete the storage for an origin that - // has no such storage. - return; - } - - SQLiteStatement deleteStatement(m_database, "DELETE FROM Origins where origin=?"); - if (deleteStatement.prepare() != SQLResultOk) { - LOG_ERROR("Unable to prepare deletion of origin '%s'", originIdentifier.ascii().data()); - return; - } - deleteStatement.bindText(1, originIdentifier); - if (!deleteStatement.executeCommand()) { - LOG_ERROR("Unable to execute deletion of origin '%s'", originIdentifier.ascii().data()); - return; - } - - SQLiteFileSystem::deleteDatabaseFile(path); - - bool shouldDeleteTrackerFiles = false; - { - MutexLocker locker(m_originSetMutex); - m_originSet.remove(originIdentifier); - shouldDeleteTrackerFiles = m_originSet.isEmpty(); - } - - if (shouldDeleteTrackerFiles) { -#if PLATFORM(IOS) - SQLiteFileSystem::truncateDatabaseFile(m_database.sqlite3Handle()); -#endif - m_database.close(); -#if !PLATFORM(IOS) - SQLiteFileSystem::deleteDatabaseFile(trackerDatabasePath()); - SQLiteFileSystem::deleteEmptyDatabaseDirectory(m_storageDirectoryPath); -#endif - } - - { - MutexLocker locker(m_clientMutex); - if (m_client) - m_client->dispatchDidModifyOrigin(originIdentifier); - } -} - -void StorageTracker::willDeleteAllOrigins() -{ - ASSERT(!m_originSetMutex.tryLock()); - - OriginSet::const_iterator end = m_originSet.end(); - for (OriginSet::const_iterator it = m_originSet.begin(); it != end; ++it) - m_originsBeingDeleted.add((*it).isolatedCopy()); -} - -void StorageTracker::willDeleteOrigin(const String& originIdentifier) -{ - ASSERT(isMainThread()); - ASSERT(!m_originSetMutex.tryLock()); - - m_originsBeingDeleted.add(originIdentifier); -} - -bool StorageTracker::canDeleteOrigin(const String& originIdentifier) -{ - ASSERT(!m_databaseMutex.tryLock()); - MutexLocker locker(m_originSetMutex); - return m_originsBeingDeleted.contains(originIdentifier); -} - -void StorageTracker::cancelDeletingOrigin(const String& originIdentifier) -{ - if (!m_isActive) - return; - - MutexLocker locker(m_databaseMutex); - { - MutexLocker locker(m_originSetMutex); - if (!m_originsBeingDeleted.isEmpty()) - m_originsBeingDeleted.remove(originIdentifier); - } -} - -bool StorageTracker::isActive() -{ - return m_isActive; -} - -void StorageTracker::setIsActive(bool flag) -{ - m_isActive = flag; -} - -String StorageTracker::databasePathForOrigin(const String& originIdentifier) -{ - ASSERT(!m_databaseMutex.tryLock()); - ASSERT(m_isActive); - - if (!m_database.isOpen()) - return String(); - - SQLiteTransactionInProgressAutoCounter transactionCounter; - - SQLiteStatement pathStatement(m_database, "SELECT path FROM Origins WHERE origin=?"); - if (pathStatement.prepare() != SQLResultOk) { - LOG_ERROR("Unable to prepare selection of path for origin '%s'", originIdentifier.ascii().data()); - return String(); - } - pathStatement.bindText(1, originIdentifier); - int result = pathStatement.step(); - if (result != SQLResultRow) - return String(); - - return pathStatement.getColumnText(0); -} - -long long StorageTracker::diskUsageForOrigin(SecurityOrigin* origin) -{ - if (!m_isActive) - return 0; - - MutexLocker locker(m_databaseMutex); - - String path = databasePathForOrigin(origin->databaseIdentifier()); - if (path.isEmpty()) - return 0; - - return SQLiteFileSystem::getDatabaseFileSize(path); -} - -} // namespace WebCore diff --git a/Source/WebCore/storage/StorageTracker.h b/Source/WebCore/storage/StorageTracker.h deleted file mode 100644 index 98b5b5681..000000000 --- a/Source/WebCore/storage/StorageTracker.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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 StorageTracker_h -#define StorageTracker_h - -#include "SQLiteDatabase.h" -#include <wtf/HashSet.h> -#include <wtf/Vector.h> -#include <wtf/text/StringHash.h> -#include <wtf/text/WTFString.h> - -namespace WebCore { - -class StorageTask; -class StorageThread; -class SecurityOrigin; -class StorageTrackerClient; - -class StorageTracker { - WTF_MAKE_NONCOPYABLE(StorageTracker); - WTF_MAKE_FAST_ALLOCATED; -public: - static void initializeTracker(const String& storagePath, StorageTrackerClient*); - static StorageTracker& tracker(); - - void setDatabaseDirectoryPath(const String&); - String databaseDirectoryPath() const; - - void setOriginDetails(const String& originIdentifier, const String& databaseFile); - - void deleteAllOrigins(); - void deleteOrigin(SecurityOrigin*); - void deleteOriginWithIdentifier(const String& originIdentifier); - void origins(Vector<RefPtr<SecurityOrigin>>& result); - long long diskUsageForOrigin(SecurityOrigin*); - - void cancelDeletingOrigin(const String& originIdentifier); - - bool isActive(); - - double storageDatabaseIdleInterval() { return m_StorageDatabaseIdleInterval; } - void setStorageDatabaseIdleInterval(double interval) { m_StorageDatabaseIdleInterval = interval; } - - void syncFileSystemAndTrackerDatabase(); - -private: - explicit StorageTracker(const String& storagePath); - - void internalInitialize(); - - String trackerDatabasePath(); - void openTrackerDatabase(bool createIfDoesNotExist); - - void importOriginIdentifiers(); - void finishedImportingOriginIdentifiers(); - - void deleteTrackerFiles(); - String databasePathForOrigin(const String& originIdentifier); - - bool canDeleteOrigin(const String& originIdentifier); - void willDeleteOrigin(const String& originIdentifier); - void willDeleteAllOrigins(); - - void originFilePaths(Vector<String>& paths); - - void setIsActive(bool); - - // Sync to disk on background thread. - void syncDeleteAllOrigins(); - void syncDeleteOrigin(const String& originIdentifier); - void syncSetOriginDetails(const String& originIdentifier, const String& databaseFile); - void syncImportOriginIdentifiers(); - - // Mutex for m_database and m_storageDirectoryPath. - Mutex m_databaseMutex; - SQLiteDatabase m_database; - String m_storageDirectoryPath; - - Mutex m_clientMutex; - StorageTrackerClient* m_client; - - // Guard for m_originSet and m_originsBeingDeleted. - Mutex m_originSetMutex; - typedef HashSet<String> OriginSet; - OriginSet m_originSet; - OriginSet m_originsBeingDeleted; - - std::unique_ptr<StorageThread> m_thread; - - bool m_isActive; - bool m_needsInitialization; - double m_StorageDatabaseIdleInterval; -}; - -} // namespace WebCore - -#endif // StorageTracker_h diff --git a/Source/WebCore/storage/StorageTrackerClient.h b/Source/WebCore/storage/StorageTrackerClient.h deleted file mode 100644 index 71a6029fa..000000000 --- a/Source/WebCore/storage/StorageTrackerClient.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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 StorageTrackerClient_h -#define StorageTrackerClient_h - -#include <wtf/Forward.h> - -namespace WebCore { - -class StorageTrackerClient { -public: - virtual ~StorageTrackerClient() { } - virtual void dispatchDidModifyOrigin(const String& originIdentifier) = 0; - virtual void didFinishLoadingOrigins() = 0; -}; - -} // namespace WebCore - -#endif // StorageTrackerClient_h diff --git a/Source/WebCore/storage/StorageNamespace.cpp b/Source/WebCore/storage/StorageType.h index 2bbbedc79..58133f89c 100644 --- a/Source/WebCore/storage/StorageNamespace.cpp +++ b/Source/WebCore/storage/StorageType.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,27 +23,25 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "StorageNamespace.h" - -#include "PlatformStrategies.h" -#include "StorageStrategy.h" +#pragma once namespace WebCore { -PassRefPtr<StorageNamespace> StorageNamespace::localStorageNamespace(PageGroup* pageGroup) -{ - return platformStrategies()->storageStrategy()->localStorageNamespace(pageGroup); -} +enum class StorageType { + Session, + Local, + EphemeralLocal, + TransientLocal, +}; -PassRefPtr<StorageNamespace> StorageNamespace::transientLocalStorageNamespace(PageGroup* pageGroup, SecurityOrigin* securityOrigin) +inline bool isLocalStorage(StorageType storageType) { - return platformStrategies()->storageStrategy()->transientLocalStorageNamespace(pageGroup, securityOrigin); + return storageType == StorageType::Local || storageType == StorageType::TransientLocal || storageType == StorageType::EphemeralLocal; } -PassRefPtr<StorageNamespace> StorageNamespace::sessionStorageNamespace(Page* page) +inline bool isPersistentLocalStorage(StorageType storageType) { - return platformStrategies()->storageStrategy()->sessionStorageNamespace(page); + return storageType == StorageType::Local || storageType == StorageType::TransientLocal; } } // namespace WebCore |