WebKit Bugzilla
Attachment 369739 Details for
Bug 197636
: Move Web Storage to Network Process
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-197636-20190513095211.patch (text/plain), 270.24 KB, created by
Sihui Liu
on 2019-05-13 09:52:12 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Sihui Liu
Created:
2019-05-13 09:52:12 PDT
Size:
270.24 KB
patch
obsolete
>Subversion Revision: 245233 >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 244ae3d3f5f8d3b0641a8a3e0286a7752305a161..e8d730a5a93d68166c849cc3d3a236e7e72d75fa 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,224 @@ >+2019-05-13 Sihui Liu <sihui_liu@apple.com> >+ >+ Move Web Storage to Network Process >+ https://bugs.webkit.org/show_bug.cgi?id=197636 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * CMakeLists.txt: >+ * DerivedSources.make: >+ * NetworkProcess/NetworkConnectionToWebProcess.cpp: >+ (WebKit::NetworkConnectionToWebProcess::didClose): >+ (WebKit::NetworkConnectionToWebProcess::webPageWasAdded): >+ (WebKit::NetworkConnectionToWebProcess::webPageWasRemoved): >+ (WebKit::NetworkConnectionToWebProcess::webProcessSessionChanged): >+ * NetworkProcess/NetworkConnectionToWebProcess.h: >+ * NetworkProcess/NetworkConnectionToWebProcess.messages.in: >+ * NetworkProcess/NetworkProcess.cpp: >+ (WebKit::NetworkProcess::~NetworkProcess): >+ (WebKit::NetworkProcess::initializeNetworkProcess): >+ (WebKit::NetworkProcess::addWebsiteDataStore): >+ (WebKit::NetworkProcess::hasLocalStorage): >+ (WebKit::NetworkProcess::fetchWebsiteData): >+ (WebKit::NetworkProcess::deleteWebsiteData): >+ (WebKit::NetworkProcess::deleteWebsiteDataForOrigins): >+ (WebKit::filterForRegistrableDomains): >+ (WebKit::NetworkProcess::deleteWebsiteDataForRegistrableDomains): >+ (WebKit::NetworkProcess::addStorageSession): >+ (WebKit::NetworkProcess::webPageWasAdded): >+ (WebKit::NetworkProcess::webPageWasRemoved): >+ (WebKit::NetworkProcess::webProcessWasDisconnected): >+ (WebKit::NetworkProcess::webProcessSessionChanged): >+ (WebKit::NetworkProcess::getLocalStorageOriginDetails): >+ * NetworkProcess/NetworkProcess.h: >+ * NetworkProcess/NetworkProcess.messages.in: >+ * NetworkProcess/WebStorage/LocalStorageDatabase.cpp: Renamed from Source/WebKit/UIProcess/WebStorage/LocalStorageDatabase.cpp. >+ (WebKit::LocalStorageDatabase::create): >+ (WebKit::LocalStorageDatabase::LocalStorageDatabase): >+ (WebKit::LocalStorageDatabase::~LocalStorageDatabase): >+ (WebKit::LocalStorageDatabase::openDatabase): >+ (WebKit::LocalStorageDatabase::tryToOpenDatabase): >+ (WebKit::LocalStorageDatabase::migrateItemTableIfNeeded): >+ (WebKit::LocalStorageDatabase::importItems): >+ (WebKit::LocalStorageDatabase::setItem): >+ (WebKit::LocalStorageDatabase::removeItem): >+ (WebKit::LocalStorageDatabase::clear): >+ (WebKit::LocalStorageDatabase::close): >+ (WebKit::LocalStorageDatabase::itemDidChange): >+ (WebKit::LocalStorageDatabase::scheduleDatabaseUpdate): >+ (WebKit::LocalStorageDatabase::updateDatabase): >+ (WebKit::LocalStorageDatabase::updateDatabaseWithChangedItems): >+ (WebKit::LocalStorageDatabase::databaseIsEmpty): >+ * NetworkProcess/WebStorage/LocalStorageDatabase.h: Renamed from Source/WebKit/UIProcess/WebStorage/LocalStorageDatabase.h. >+ * NetworkProcess/WebStorage/LocalStorageDatabaseTracker.cpp: Renamed from Source/WebKit/UIProcess/WebStorage/LocalStorageDatabaseTracker.cpp. >+ (WebKit::LocalStorageDatabaseTracker::create): >+ (WebKit::LocalStorageDatabaseTracker::LocalStorageDatabaseTracker): >+ (WebKit::LocalStorageDatabaseTracker::~LocalStorageDatabaseTracker): >+ (WebKit::LocalStorageDatabaseTracker::databasePath const): >+ (WebKit::LocalStorageDatabaseTracker::didOpenDatabaseWithOrigin): >+ (WebKit::LocalStorageDatabaseTracker::deleteDatabaseWithOrigin): >+ (WebKit::LocalStorageDatabaseTracker::deleteAllDatabases): >+ (WebKit::LocalStorageDatabaseTracker::databasesModifiedSince): >+ (WebKit::LocalStorageDatabaseTracker::origins const): >+ (WebKit::LocalStorageDatabaseTracker::originDetails): >+ * NetworkProcess/WebStorage/LocalStorageDatabaseTracker.h: Renamed from Source/WebKit/UIProcess/WebStorage/LocalStorageDatabaseTracker.h. >+ (WebKit::LocalStorageDatabaseTracker::OriginDetails::encode const): >+ (WebKit::LocalStorageDatabaseTracker::OriginDetails::decode): >+ * NetworkProcess/WebStorage/StorageManager.cpp: Renamed from Source/WebKit/UIProcess/WebStorage/StorageManager.cpp. >+ (WebKit::StorageManager::StorageArea::securityOrigin const): >+ (WebKit::StorageManager::StorageArea::isSessionStorage const): >+ (WebKit::StorageManager::LocalStorageNamespace::storageManager const): >+ (WebKit::StorageManager::TransientLocalStorageNamespace::create): >+ (WebKit::StorageManager::TransientLocalStorageNamespace::~TransientLocalStorageNamespace): >+ (WebKit::StorageManager::TransientLocalStorageNamespace::getOrCreateStorageArea): >+ (WebKit::StorageManager::TransientLocalStorageNamespace::origins const): >+ (WebKit::StorageManager::TransientLocalStorageNamespace::clearStorageAreasMatchingOrigin): >+ (WebKit::StorageManager::TransientLocalStorageNamespace::clearAllStorageAreas): >+ (WebKit::StorageManager::TransientLocalStorageNamespace::TransientLocalStorageNamespace): >+ (WebKit::StorageManager::StorageArea::create): >+ (WebKit::StorageManager::StorageArea::StorageArea): >+ (WebKit::StorageManager::StorageArea::~StorageArea): >+ (WebKit::StorageManager::StorageArea::addListener): >+ (WebKit::StorageManager::StorageArea::removeListener): >+ (WebKit::StorageManager::StorageArea::hasListener const): >+ (WebKit::StorageManager::StorageArea::clone const): >+ (WebKit::StorageManager::StorageArea::setItem): >+ (WebKit::StorageManager::StorageArea::removeItem): >+ (WebKit::StorageManager::StorageArea::clear): >+ (WebKit::StorageManager::StorageArea::items const): >+ (WebKit::StorageManager::StorageArea::openDatabaseAndImportItemsIfNeeded const): >+ (WebKit::StorageManager::StorageArea::dispatchEvents const): >+ (WebKit::StorageManager::LocalStorageNamespace::create): >+ (WebKit::StorageManager::LocalStorageNamespace::LocalStorageNamespace): >+ (WebKit::StorageManager::LocalStorageNamespace::~LocalStorageNamespace): >+ (WebKit::StorageManager::LocalStorageNamespace::getOrCreateStorageArea): >+ (WebKit::StorageManager::LocalStorageNamespace::didDestroyStorageArea): >+ (WebKit::StorageManager::LocalStorageNamespace::clearStorageAreasMatchingOrigin): >+ (WebKit::StorageManager::LocalStorageNamespace::clearAllStorageAreas): >+ (WebKit::StorageManager::SessionStorageNamespace::isEmpty const): >+ (WebKit::StorageManager::SessionStorageNamespace::allowedConnections const): >+ (WebKit::StorageManager::SessionStorageNamespace::origins const): >+ (WebKit::StorageManager::SessionStorageNamespace::clearStorageAreasMatchingOrigin): >+ (WebKit::StorageManager::SessionStorageNamespace::clearAllStorageAreas): >+ (WebKit::StorageManager::SessionStorageNamespace::create): >+ (WebKit::StorageManager::SessionStorageNamespace::SessionStorageNamespace): >+ (WebKit::StorageManager::SessionStorageNamespace::~SessionStorageNamespace): >+ (WebKit::StorageManager::SessionStorageNamespace::addAllowedConnection): >+ (WebKit::StorageManager::SessionStorageNamespace::removeAllowedConnection): >+ (WebKit::StorageManager::SessionStorageNamespace::getOrCreateStorageArea): >+ (WebKit::StorageManager::SessionStorageNamespace::cloneTo): >+ (WebKit::StorageManager::create): >+ (WebKit::StorageManager::StorageManager): >+ (WebKit::StorageManager::~StorageManager): >+ (WebKit::StorageManager::createSessionStorageNamespace): >+ (WebKit::StorageManager::destroySessionStorageNamespace): >+ (WebKit::StorageManager::addAllowedSessionStorageNamespaceConnection): >+ (WebKit::StorageManager::removeAllowedSessionStorageNamespaceConnection): >+ (WebKit::StorageManager::cloneSessionStorageNamespace): >+ (WebKit::StorageManager::processWillOpenConnection): >+ (WebKit::StorageManager::processDidCloseConnection): >+ (WebKit::StorageManager::getSessionStorageOrigins): >+ (WebKit::StorageManager::deleteSessionStorageOrigins): >+ (WebKit::StorageManager::deleteSessionStorageEntriesForOrigins): >+ (WebKit::StorageManager::getLocalStorageOrigins): >+ (WebKit::StorageManager::getLocalStorageOriginDetails): >+ (WebKit::StorageManager::deleteLocalStorageEntriesForOrigin): >+ (WebKit::StorageManager::deleteLocalStorageOriginsModifiedSince): >+ (WebKit::StorageManager::deleteLocalStorageEntriesForOrigins): >+ (WebKit::StorageManager::createLocalStorageMap): >+ (WebKit::StorageManager::createTransientLocalStorageMap): >+ (WebKit::StorageManager::createSessionStorageMap): >+ (WebKit::StorageManager::destroyStorageMap): >+ (WebKit::StorageManager::getValues): >+ (WebKit::StorageManager::setItem): >+ (WebKit::StorageManager::removeItem): >+ (WebKit::StorageManager::clear): >+ (WebKit::StorageManager::waitUntilWritesFinished): >+ (WebKit::StorageManager::findStorageArea const): >+ (WebKit::StorageManager::getOrCreateLocalStorageNamespace): >+ (WebKit::StorageManager::getOrCreateTransientLocalStorageNamespace): >+ * NetworkProcess/WebStorage/StorageManager.h: Renamed from Source/WebKit/UIProcess/WebStorage/StorageManager.h. >+ * NetworkProcess/WebStorage/StorageManager.messages.in: Renamed from Source/WebKit/UIProcess/WebStorage/StorageManager.messages.in. >+ * NetworkProcess/WebStorage/ios/LocalStorageDatabaseTrackerIOS.mm: Renamed from Source/WebKit/UIProcess/WebStorage/ios/LocalStorageDatabaseTrackerIOS.mm. >+ (WebKit::LocalStorageDatabaseTracker::platformMaybeExcludeFromBackup const): >+ * Shared/WebPageCreationParameters.cpp: >+ (WebKit::WebPageCreationParameters::encode const): >+ (WebKit::WebPageCreationParameters::decode): >+ * Shared/WebPageCreationParameters.h: >+ * Shared/WebsiteData/WebsiteData.cpp: >+ (WebKit::WebsiteData::ownerProcess): >+ * Shared/WebsiteDataStoreParameters.cpp: >+ (WebKit::WebsiteDataStoreParameters::encode const): >+ (WebKit::WebsiteDataStoreParameters::decode): >+ (WebKit::WebsiteDataStoreParameters::privateSessionParameters): >+ * Shared/WebsiteDataStoreParameters.h: >+ * Sources.txt: >+ * SourcesCocoa.txt: >+ * SourcesGTK.txt: >+ * SourcesWPE.txt: >+ * UIProcess/API/C/WKKeyValueStorageManager.cpp: >+ (WKKeyValueStorageManagerGetKeyValueStorageOrigins): >+ (WKKeyValueStorageManagerGetStorageDetailsByOrigin): >+ (WKKeyValueStorageManagerDeleteEntriesForOrigin): >+ (WKKeyValueStorageManagerDeleteAllEntries): >+ * UIProcess/Network/NetworkProcessProxy.cpp: >+ (WebKit::NetworkProcessProxy::hasLocalStorage): >+ (WebKit::NetworkProcessProxy::getLocalStorageDetails): >+ * UIProcess/Network/NetworkProcessProxy.h: >+ * UIProcess/WebPageProxy.cpp: >+ (WebKit::WebPageProxy::createNewPage): >+ * UIProcess/WebProcessPool.cpp: >+ (WebKit::WebProcessPool::ensureNetworkProcess): >+ * UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm: >+ (WebKit::WebsiteDataStore::parameters): >+ (WebKit::WebsiteDataStore::platformInitialize): >+ (WebKit::WebsiteDataStore::platformDestroy): >+ * UIProcess/WebsiteData/WebsiteDataStore.cpp: >+ (WebKit::WebsiteDataStore::WebsiteDataStore): >+ (WebKit::computeNetworkProcessAccessTypeForDataFetch): >+ (WebKit::WebsiteDataStore::fetchDataAndApply): >+ (WebKit::WebsiteDataStore::removeData): >+ (WebKit::WebsiteDataStore::hasLocalStorageForTesting const): >+ (WebKit::WebsiteDataStore::parameters): >+ (WebKit::WebsiteDataStore::getLocalStorageDetails): >+ (WebKit::m_client): Deleted. >+ (WebKit::WebsiteDataStore::cloneSessionData): Deleted. >+ (WebKit::WebsiteDataStore::webPageWasAdded): Deleted. >+ (WebKit::WebsiteDataStore::webPageWasInvalidated): Deleted. >+ (WebKit::WebsiteDataStore::webProcessWillOpenConnection): Deleted. >+ (WebKit::WebsiteDataStore::webPageWillOpenConnection): Deleted. >+ (WebKit::WebsiteDataStore::webPageDidCloseConnection): Deleted. >+ (WebKit::WebsiteDataStore::webProcessDidCloseConnection): Deleted. >+ * UIProcess/WebsiteData/WebsiteDataStore.h: >+ (WebKit::WebsiteDataStore::resolvedLocalStorageDirectory const): >+ (WebKit::WebsiteDataStore::storageManager): Deleted. >+ * WebKit.xcodeproj/project.pbxproj: >+ * WebProcess/InjectedBundle/InjectedBundle.cpp: >+ (WebKit::InjectedBundle::setPrivateBrowsingEnabled): >+ * WebProcess/Network/NetworkProcessConnection.cpp: >+ (WebKit::NetworkProcessConnection::didReceiveMessage): >+ * WebProcess/WebCoreSupport/WebChromeClient.cpp: >+ (WebKit::WebChromeClient::createWindow): >+ * WebProcess/WebPage/WebPage.cpp: >+ (WebKit::WebPage::close): >+ * WebProcess/WebProcess.cpp: >+ (WebKit::WebProcess::createWebPage): >+ (WebKit::WebProcess::removeWebPage): >+ (WebKit::WebProcess::registerStorageAreaMap): >+ (WebKit::WebProcess::unregisterStorageAreaMap): >+ (WebKit::WebProcess::storageAreaMap const): >+ (WebKit::WebProcess::setPrivateBrowsingEnabled): >+ * WebProcess/WebProcess.h: >+ * WebProcess/WebStorage/StorageAreaMap.cpp: >+ (WebKit::StorageAreaMap::StorageAreaMap): >+ (WebKit::StorageAreaMap::~StorageAreaMap): >+ (WebKit::StorageAreaMap::setItem): >+ (WebKit::StorageAreaMap::removeItem): >+ (WebKit::StorageAreaMap::clear): >+ (WebKit::StorageAreaMap::loadValuesIfNeeded): >+ * WebProcess/WebStorage/StorageAreaMap.h: >+ (WebKit::StorageAreaMap::identifier const): >+ > 2019-05-12 Takashi Komori <Takashi.Komori@sony.com> > > [Curl] Suppress extra didReceiveAuthenticationChallenge call when accessing a server which checks basic auth. >diff --git a/Source/WebKit/CMakeLists.txt b/Source/WebKit/CMakeLists.txt >index 4b0bec7cb80056a8c1eab71123d81eb641c966de..831727c91b52343fb366d19821a2e330a8a2eb56 100644 >--- a/Source/WebKit/CMakeLists.txt >+++ b/Source/WebKit/CMakeLists.txt >@@ -20,6 +20,7 @@ set(WebKit_INCLUDE_DIRECTORIES > "${WEBKIT_DIR}/NetworkProcess/FileAPI" > "${WEBKIT_DIR}/NetworkProcess/IndexedDB" > "${WEBKIT_DIR}/NetworkProcess/ServiceWorker" >+ "${WEBKIT_DIR}/NetworkProcess/WebStorage" > "${WEBKIT_DIR}/NetworkProcess/cache" > "${WEBKIT_DIR}/NetworkProcess/watchos" > "${WEBKIT_DIR}/NetworkProcess/webrtc" >@@ -58,7 +59,6 @@ set(WebKit_INCLUDE_DIRECTORIES > "${WEBKIT_DIR}/UIProcess/UserContent" > "${WEBKIT_DIR}/UIProcess/WebAuthentication" > "${WEBKIT_DIR}/UIProcess/WebAuthentication/Mock" >- "${WEBKIT_DIR}/UIProcess/WebStorage" > "${WEBKIT_DIR}/UIProcess/WebsiteData" > "${WEBKIT_DIR}/WebProcess" > "${WEBKIT_DIR}/WebProcess/ApplePay" >@@ -121,6 +121,8 @@ set(WebKit_MESSAGES_IN_FILES > NetworkProcess/ServiceWorker/WebSWServerConnection.messages.in > NetworkProcess/ServiceWorker/WebSWServerToContextConnection.messages.in > >+ NetworkProcess/WebStorage/StorageManager.messages.in >+ > NetworkProcess/cache/CacheStorageEngineConnection.messages.in > > NetworkProcess/webrtc/NetworkMDNSRegister.messages.in >@@ -161,8 +163,6 @@ set(WebKit_MESSAGES_IN_FILES > > UIProcess/UserContent/WebUserContentControllerProxy.messages.in > >- UIProcess/WebStorage/StorageManager.messages.in >- > WebProcess/WebProcess.messages.in > > WebProcess/Automation/WebAutomationSessionProxy.messages.in >diff --git a/Source/WebKit/DerivedSources.make b/Source/WebKit/DerivedSources.make >index 8fbaf0e358be5dca7081b4579eb435b324143ed4..6ba0c9fd9a5a1ba7a8f17f666615be0386de43d5 100644 >--- a/Source/WebKit/DerivedSources.make >+++ b/Source/WebKit/DerivedSources.make >@@ -30,6 +30,7 @@ VPATH = \ > $(WebKit2)/NetworkProcess/webrtc \ > $(WebKit2)/NetworkProcess/IndexedDB \ > $(WebKit2)/NetworkProcess/ServiceWorker \ >+ $(WebKit2)/NetworkProcess/WebStorage \ > $(WebKit2)/PluginProcess \ > $(WebKit2)/PluginProcess/mac \ > $(WebKit2)/Shared/Plugins \ >@@ -79,7 +80,6 @@ VPATH = \ > $(WebKit2)/UIProcess/Storage \ > $(WebKit2)/UIProcess/UserContent \ > $(WebKit2)/UIProcess/WebAuthentication \ >- $(WebKit2)/UIProcess/WebStorage \ > $(WebKit2)/UIProcess/mac \ > $(WebKit2)/UIProcess/ios \ > $(WEBKITADDITIONS_HEADER_SEARCH_PATHS) \ >diff --git a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp >index e9c98f2e2227fe1c5251770d060d2ed2e3ccde5b..24c917f57ece1e6adabb2a768b295479a517e01a 100644 >--- a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp >+++ b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp >@@ -288,6 +288,8 @@ void NetworkConnectionToWebProcess::didClose(IPC::Connection& connection) > // root activity trackers. > stopAllNetworkActivityTracking(); > >+ m_networkProcess->webProcessWasDisconnected(connection); >+ > m_networkProcess->networkBlobRegistry().connectionToWebProcessDidClose(*this); > m_networkProcess->removeNetworkConnectionToWebProcess(*this); > >@@ -877,4 +879,19 @@ void NetworkConnectionToWebProcess::clearConnectionHasUploads() > m_networkProcess->parentProcessConnection()->send(Messages::WebProcessPool::ClearWebProcessHasUploads(m_webProcessIdentifier), 0); > } > >+void NetworkConnectionToWebProcess::webPageWasAdded(PAL::SessionID sessionID, uint64_t pageID, uint64_t oldPageID) >+{ >+ m_networkProcess->webPageWasAdded(m_connection.get(), sessionID, pageID, oldPageID); >+} >+ >+void NetworkConnectionToWebProcess::webPageWasRemoved(PAL::SessionID sessionID, uint64_t pageID) >+{ >+ m_networkProcess->webPageWasRemoved(m_connection.get(), sessionID, pageID); >+} >+ >+void NetworkConnectionToWebProcess::webProcessSessionChanged(PAL::SessionID newSessionID, Vector<uint64_t> pages) >+{ >+ m_networkProcess->webProcessSessionChanged(m_connection.get(), newSessionID, pages); >+} >+ > } // namespace WebKit >diff --git a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h >index 0903a164589da1954ce63fc31bed20beb21aed87..fb53ef9c0c7a9ea7dde239053e42ecb0fc416fb4 100644 >--- a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h >+++ b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h >@@ -194,6 +194,10 @@ private: > > void ensureLegacyPrivateBrowsingSession(); > >+ void webPageWasAdded(PAL::SessionID, uint64_t pageID, uint64_t oldPageID); >+ void webPageWasRemoved(PAL::SessionID, uint64_t pageID); >+ void webProcessSessionChanged(PAL::SessionID newSessionID, Vector<uint64_t> pages); >+ > #if ENABLE(INDEXED_DATABASE) > // Messages handlers (Modern IDB). > void establishIDBConnectionToServer(PAL::SessionID, CompletionHandler<void(uint64_t serverConnectionIdentifier)>&&); >diff --git a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in >index fd848e3ad046c80c3ae3f46d39015a02f003c951..c43ece393b43abffb6d7147bb85e2f08b3efae10 100644 >--- a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in >+++ b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in >@@ -86,4 +86,8 @@ messages -> NetworkConnectionToWebProcess LegacyReceiver { > #endif > > SetWebProcessIdentifier(WebCore::ProcessIdentifier processIdentifier) >+ >+ WebPageWasAdded(PAL::SessionID sessionID, uint64_t pageID, uint64_t oldPageID) >+ WebPageWasRemoved(PAL::SessionID sessionID, uint64_t pageID) >+ webProcessSessionChanged(PAL::SessionID newSessionID, Vector<uint64_t> pages) > } >diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.cpp b/Source/WebKit/NetworkProcess/NetworkProcess.cpp >index c459e63ed5751039330cc9eeafc49c8de3445bae..a5ca2bcc80a6a62aa67c04bbd3694e7f1d22a572 100644 >--- a/Source/WebKit/NetworkProcess/NetworkProcess.cpp >+++ b/Source/WebKit/NetworkProcess/NetworkProcess.cpp >@@ -53,6 +53,8 @@ > #include "ShouldGrandfatherStatistics.h" > #include "StatisticsData.h" > #include "StorageAccessStatus.h" >+#include "StorageManager.h" >+#include "StorageManagerMessages.h" > #include "WebCookieManager.h" > #include "WebPageProxyMessages.h" > #include "WebProcessPoolMessages.h" >@@ -165,6 +167,9 @@ NetworkProcess::NetworkProcess(AuxiliaryProcessInitializationParameters&& parame > > NetworkProcess::~NetworkProcess() > { >+ for (auto& storageManager : m_storageManagers.values()) >+ storageManager->waitUntilWritesFinished(); >+ > for (auto& callbacks : m_cacheStorageParametersCallbacks.values()) { > for (auto& callback : callbacks) > callback(String { }); >@@ -316,6 +321,8 @@ void NetworkProcess::initializeNetworkProcess(NetworkProcessCreationParameters&& > auto sessionID = parameters.defaultDataStoreParameters.networkSessionParameters.sessionID; > setSession(sessionID, NetworkSession::create(*this, WTFMove(parameters.defaultDataStoreParameters.networkSessionParameters))); > >+ addStorageSession(sessionID, parameters.defaultDataStoreParameters.localStorageDirectory, parameters.defaultDataStoreParameters.localStorageDirectoryExtensionHandle); >+ > #if ENABLE(INDEXED_DATABASE) > addIndexedDatabaseSession(sessionID, parameters.defaultDataStoreParameters.indexedDatabaseDirectory, parameters.defaultDataStoreParameters.indexedDatabaseDirectoryExtensionHandle); > #endif >@@ -455,6 +462,8 @@ void NetworkProcess::clearCachedCredentials() > > void NetworkProcess::addWebsiteDataStore(WebsiteDataStoreParameters&& parameters) > { >+ addStorageSession(parameters.networkSessionParameters.sessionID, parameters.localStorageDirectory, parameters.localStorageDirectoryExtensionHandle); >+ > #if ENABLE(INDEXED_DATABASE) > addIndexedDatabaseSession(parameters.networkSessionParameters.sessionID, parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle); > #endif >@@ -1011,6 +1020,25 @@ void NetworkProcess::clearUserInteraction(PAL::SessionID sessionID, const Regist > } > } > >+void NetworkProcess::hasLocalStorage(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler) >+{ >+ auto storageManager = m_storageManagers.get(sessionID); >+ if (!storageManager) >+ completionHandler(false); >+ >+ storageManager->getLocalStorageOrigins([domain, completionHandler = WTFMove(completionHandler)](HashSet<WebCore::SecurityOriginData>&& origins) mutable { >+ for (auto& origin : origins) { >+ auto originDomain = RegistrableDomain::uncheckedCreateFromHost(origin.host); >+ if (originDomain == domain) { >+ completionHandler(true); >+ return; >+ } >+ } >+ >+ completionHandler(false); >+ }); >+} >+ > void NetworkProcess::removePrevalentDomains(PAL::SessionID sessionID, const Vector<RegistrableDomain>& domains) > { > if (auto* networkStorageSession = storageSession(sessionID)) >@@ -1260,6 +1288,23 @@ void NetworkProcess::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<Websit > }); > } > >+ auto storageManager = m_storageManagers.get(sessionID); >+ if (websiteDataTypes.contains(WebsiteDataType::SessionStorage) && storageManager) { >+ auto storageManager = m_storageManagers.get(sessionID); >+ storageManager->getSessionStorageOrigins([callbackAggregator = callbackAggregator.copyRef()](HashSet<WebCore::SecurityOriginData>&& origins) { >+ while (!origins.isEmpty()) >+ callbackAggregator->m_websiteData.entries.append(WebsiteData::Entry { origins.takeAny(), WebsiteDataType::SessionStorage, 0 }); >+ }); >+ } >+ >+ if (websiteDataTypes.contains(WebsiteDataType::LocalStorage) && storageManager) { >+ storageManager->getLocalStorageOrigins([callbackAggregator = callbackAggregator.copyRef()](HashSet<WebCore::SecurityOriginData>&& origins) { >+ while (!origins.isEmpty()) >+ callbackAggregator->m_websiteData.entries.append(WebsiteData::Entry { origins.takeAny(), WebsiteDataType::LocalStorage, 0 }); >+ }); >+ } >+ >+ > #if PLATFORM(COCOA) > if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) { > if (auto* networkStorageSession = storageSession(sessionID)) >@@ -1323,6 +1368,13 @@ void NetworkProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<Websi > if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) > CacheStorage::Engine::clearAllCaches(*this, sessionID, [clearTasksHandler = clearTasksHandler.copyRef()] { }); > >+ auto storageManager = m_storageManagers.get(sessionID); >+ if (websiteDataTypes.contains(WebsiteDataType::SessionStorage) && storageManager) >+ storageManager->deleteSessionStorageOrigins([clearTasksHandler = clearTasksHandler.copyRef()] { }); >+ >+ if (websiteDataTypes.contains(WebsiteDataType::LocalStorage) && storageManager) >+ storageManager->deleteLocalStorageOriginsModifiedSince(modifiedSince, [clearTasksHandler = clearTasksHandler.copyRef()] { }); >+ > #if ENABLE(INDEXED_DATABASE) > if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !sessionID.isEphemeral()) > idbServer(sessionID).closeAndDeleteDatabasesModifiedSince(modifiedSince, [clearTasksHandler = clearTasksHandler.copyRef()] { }); >@@ -1416,6 +1468,13 @@ void NetworkProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, Optio > CacheStorage::Engine::clearCachesForOrigin(*this, sessionID, SecurityOriginData { originData }, [clearTasksHandler = clearTasksHandler.copyRef()] { }); > } > >+ auto storageManager = m_storageManagers.get(sessionID); >+ if (websiteDataTypes.contains(WebsiteDataType::SessionStorage) && storageManager) >+ storageManager->deleteSessionStorageEntriesForOrigins(originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { }); >+ >+ if (websiteDataTypes.contains(WebsiteDataType::LocalStorage) && storageManager) >+ storageManager->deleteLocalStorageEntriesForOrigins(originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { }); >+ > #if ENABLE(INDEXED_DATABASE) > if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !sessionID.isEphemeral()) > idbServer(sessionID).closeAndDeleteDatabasesForOrigins(originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { }); >@@ -1476,6 +1535,20 @@ static Vector<WebsiteData::Entry> filterForRegistrableDomains(const Vector<Regis > return result; > } > >+static Vector<WebCore::SecurityOriginData> filterForRegistrableDomains(HashSet<WebCore::SecurityOriginData> origins, Vector<RegistrableDomain> domainsToDelete, HashSet<RegistrableDomain>& domainsDeleted) >+{ >+ Vector<SecurityOriginData> originsDeleted; >+ for (const auto& origin : origins) { >+ auto domain = RegistrableDomain::uncheckedCreateFromHost(origin.host); >+ if (!domainsToDelete.contains(domain)) >+ continue; >+ originsDeleted.append(origin); >+ domainsDeleted.add(domain); >+ } >+ >+ return originsDeleted; >+} >+ > void NetworkProcess::deleteWebsiteDataForRegistrableDomains(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, HashMap<RegistrableDomain, WebsiteDataToRemove>&& domains, bool shouldNotifyPage, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&& completionHandler) > { > OptionSet<WebsiteDataFetchOption> fetchOptions = WebsiteDataFetchOption::DoNotCreateProcesses; >@@ -1584,7 +1657,22 @@ void NetworkProcess::deleteWebsiteDataForRegistrableDomains(PAL::SessionID sessi > CacheStorage::Engine::clearCachesForOrigin(*this, sessionID, SecurityOriginData { entry.origin }, [callbackAggregator = callbackAggregator.copyRef()] { }); > }); > } >- >+ >+ auto storageManager = m_storageManagers.get(sessionID); >+ if (websiteDataTypes.contains(WebsiteDataType::SessionStorage) && storageManager) { >+ storageManager->getSessionStorageOrigins([storageManager = makeRefPtr(*storageManager), callbackAggregator = callbackAggregator.copyRef(), domainsToDeleteAllButCookiesFor](HashSet<WebCore::SecurityOriginData>&& origins) { >+ auto originsToDelete = filterForRegistrableDomains(origins, domainsToDeleteAllButCookiesFor, callbackAggregator->m_domains); >+ storageManager->deleteSessionStorageEntriesForOrigins(originsToDelete, [callbackAggregator = callbackAggregator.copyRef()] { }); >+ }); >+ } >+ >+ if (websiteDataTypes.contains(WebsiteDataType::LocalStorage) && storageManager) { >+ storageManager->getLocalStorageOrigins([storageManager = makeRefPtr(*storageManager), callbackAggregator = callbackAggregator.copyRef(), domainsToDeleteAllButCookiesFor](HashSet<WebCore::SecurityOriginData>&& origins) { >+ auto originsToDelete = filterForRegistrableDomains(origins, domainsToDeleteAllButCookiesFor, callbackAggregator->m_domains); >+ storageManager->deleteLocalStorageEntriesForOrigins(originsToDelete, [callbackAggregator = callbackAggregator.copyRef()] { }); >+ }); >+ } >+ > #if ENABLE(INDEXED_DATABASE) > auto path = m_idbDatabasePaths.get(sessionID); > if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases)) { >@@ -2526,4 +2614,68 @@ void NetworkProcess::removeKeptAliveLoad(NetworkResourceLoader& loader) > session->removeKeptAliveLoad(loader); > } > >+void NetworkProcess::addStorageSession(PAL::SessionID sessionID, const String& localStorageDirectory, SandboxExtension::Handle& handle) >+{ >+ m_storageManagers.ensure(sessionID, [&] { >+ SandboxExtension::consumePermanently(handle); >+ return StorageManager::create(localStorageDirectory); >+ }); >+} >+ >+void NetworkProcess::webPageWasAdded(IPC::Connection& connection, PAL::SessionID sessionID, uint64_t pageID, uint64_t oldPageID) >+{ >+ ASSERT(m_storageManagers.contains(sessionID)); >+ auto storageManager = m_storageManagers.get(sessionID); >+ auto connectionID = connection.uniqueID(); >+ >+ m_sessionByConnection.ensure(connectionID, [&]() { >+ storageManager->processWillOpenConnection(connection); >+ return sessionID; >+ }); >+ ASSERT(m_sessionByConnection.get(connectionID) == sessionID); >+ >+ storageManager->createSessionStorageNamespace(pageID, std::numeric_limits<unsigned>::max()); >+ storageManager->addAllowedSessionStorageNamespaceConnection(pageID, connection); >+ if (pageID != oldPageID) >+ storageManager->cloneSessionStorageNamespace(oldPageID, pageID); >+} >+ >+void NetworkProcess::webPageWasRemoved(IPC::Connection& connection, PAL::SessionID sessionID, uint64_t pageID) >+{ >+ ASSERT(m_storageManagers.contains(sessionID)); >+ auto storageManager = m_storageManagers.get(sessionID); >+ storageManager->removeAllowedSessionStorageNamespaceConnection(pageID, connection); >+ storageManager->destroySessionStorageNamespace(pageID); >+} >+ >+void NetworkProcess::webProcessWasDisconnected(IPC::Connection& connection) >+{ >+ auto connectionID = connection.uniqueID(); >+ if (!m_sessionByConnection.contains(connectionID)) >+ return; >+ >+ m_storageManagers.get(m_sessionByConnection.take(connectionID))->processDidCloseConnection(connection); >+} >+ >+void NetworkProcess::webProcessSessionChanged(IPC::Connection& connection, PAL::SessionID newSessionID, Vector<uint64_t> pageIDs) >+{ >+ auto connectionID = connection.uniqueID(); >+ ASSERT(m_sessionByConnection.contains(connectionID)); >+ if (m_sessionByConnection.get(connectionID) == newSessionID) >+ return; >+ >+ webProcessWasDisconnected(connection); >+ for (auto& pageID : pageIDs) >+ webPageWasAdded(connection, newSessionID, pageID, pageID); >+} >+ >+void NetworkProcess::getLocalStorageOriginDetails(PAL::SessionID sessionID, CompletionHandler<void(Vector<LocalStorageDatabaseTracker::OriginDetails>)>&& completionHandler) >+{ >+ ASSERT(m_storageManagers.contains(sessionID)); >+ auto storageManager = m_storageManagers.get(sessionID); >+ storageManager->getLocalStorageOriginDetails([completionHandler = WTFMove(completionHandler)](auto details) mutable { >+ completionHandler(details); >+ }); >+} >+ > } // namespace WebKit >diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.h b/Source/WebKit/NetworkProcess/NetworkProcess.h >index d8563d22ab4f9c31ed5cf1943c53d15bd42abbeb..28667fcea031f609b8ee1a88fdd320f0653b5edd 100644 >--- a/Source/WebKit/NetworkProcess/NetworkProcess.h >+++ b/Source/WebKit/NetworkProcess/NetworkProcess.h >@@ -28,6 +28,7 @@ > #include "AuxiliaryProcess.h" > #include "CacheModel.h" > #include "DownloadManager.h" >+#include "LocalStorageDatabaseTracker.h" > #include "NetworkBlobRegistry.h" > #include "NetworkContentRuleListManager.h" > #include "NetworkHTTPSUpgradeChecker.h" >@@ -95,6 +96,7 @@ class NetworkConnectionToWebProcess; > class NetworkProcessSupplement; > class NetworkProximityManager; > class NetworkResourceLoader; >+class StorageManager; > class WebSWServerConnection; > class WebSWServerToContextConnection; > enum class ShouldGrandfatherStatistics : bool; >@@ -227,6 +229,7 @@ public: > void setVeryPrevalentResource(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void()>&&); > void setPruneEntriesDownTo(PAL::SessionID, uint64_t pruneTargetCount, CompletionHandler<void()>&&); > void hadUserInteraction(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void(bool)>&&); >+ void hasLocalStorage(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void(bool)>&&); > void getAllStorageAccessEntries(PAL::SessionID, CompletionHandler<void(Vector<String> domains)>&&); > void logFrameNavigation(PAL::SessionID, const NavigatedToDomain&, const TopFrameDomain&, const NavigatedFromDomain&, bool isRedirect, bool isMainFrame); > void logUserInteraction(PAL::SessionID, const TopFrameDomain&, CompletionHandler<void()>&&); >@@ -268,6 +271,13 @@ public: > void setSessionIsControlledByAutomation(PAL::SessionID, bool); > bool sessionIsControlledByAutomation(PAL::SessionID) const; > >+ void addStorageSession(PAL::SessionID, const String& localStorageDirectory, SandboxExtension::Handle&); >+ void webPageWasAdded(IPC::Connection&, PAL::SessionID, uint64_t pageID, uint64_t oldPageID); >+ void webPageWasRemoved(IPC::Connection&, PAL::SessionID, uint64_t pageID); >+ void webProcessWasDisconnected(IPC::Connection&); >+ void webProcessSessionChanged(IPC::Connection&, PAL::SessionID, Vector<uint64_t>); >+ void getLocalStorageOriginDetails(PAL::SessionID, CompletionHandler<void(Vector<LocalStorageDatabaseTracker::OriginDetails>)>&&); >+ > #if ENABLE(CONTENT_EXTENSIONS) > NetworkContentRuleListManager& networkContentRuleListManager() { return m_networkContentRuleListManager; } > #endif >@@ -558,6 +568,9 @@ private: > }; > HashMap<PAL::SessionID, StorageQuotaManagers> m_storageQuotaManagers; > uint32_t m_downloadMonitorSpeedMultiplier { 1 }; >+ >+ HashMap<PAL::SessionID, RefPtr<StorageManager>> m_storageManagers; >+ HashMap<IPC::Connection::UniqueID, PAL::SessionID> m_sessionByConnection; > }; > > } // namespace WebKit >diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in >index 35bc82b28f1f7e8e2641a3421f24706de22ac5f9..79581994a23767925a5c6b80759bfe2a73ca9c27 100644 >--- a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in >+++ b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in >@@ -98,6 +98,7 @@ messages -> NetworkProcess LegacyReceiver { > SetPrevalentResource(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain) -> () Async > SetPrevalentResourceForDebugMode(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain) -> () Async > HadUserInteraction(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain) -> (bool hadUserInteraction) Async >+ HasLocalStorage(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain) -> (bool hadUserInteraction) Async > GetAllStorageAccessEntries(PAL::SessionID sessionID) -> (Vector<String> domains) Async > IsRegisteredAsRedirectingTo(PAL::SessionID sessionID, WebCore::RegistrableDomain redirectedFromDomain, WebCore::RegistrableDomain redirectedToDomain) -> (bool isRedirectingTo) Async > IsRegisteredAsSubFrameUnder(PAL::SessionID sessionID, WebCore::RegistrableDomain subFrameDomain, WebCore::RegistrableDomain topFrameDomain) -> (bool isSubframeUnder) Async >@@ -169,4 +170,5 @@ messages -> NetworkProcess LegacyReceiver { > MarkAdClickAttributionsAsExpiredForTesting(PAL::SessionID sessionID) -> () Async > OriginsWithPersistentCredentials() -> (Vector<WebCore::SecurityOriginData> origins) Async > RemoveCredentialsWithOrigins(Vector<WebCore::SecurityOriginData> origins) -> () Async >+ GetLocalStorageOriginDetails(PAL::SessionID sessionID) -> (Vector<WebKit::LocalStorageDatabaseTracker::OriginDetails> details) Async > } >diff --git a/Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabase.cpp b/Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabase.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..46fb6c77294f3c631d4fffdfc24a148f708a44ce >--- /dev/null >+++ b/Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabase.cpp >@@ -0,0 +1,366 @@ >+/* >+ * Copyright (C) 2008, 2009, 2010, 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 "LocalStorageDatabase.h" >+ >+#include "LocalStorageDatabaseTracker.h" >+#include <WebCore/SQLiteStatement.h> >+#include <WebCore/SQLiteTransaction.h> >+#include <WebCore/SecurityOrigin.h> >+#include <WebCore/StorageMap.h> >+#include <WebCore/SuddenTermination.h> >+#include <wtf/FileSystem.h> >+#include <wtf/RefPtr.h> >+#include <wtf/WorkQueue.h> >+#include <wtf/text/StringHash.h> >+#include <wtf/text/WTFString.h> >+ >+static const auto databaseUpdateInterval = 1_s; >+ >+static const int maximumItemsToUpdate = 100; >+ >+namespace WebKit { >+using namespace WebCore; >+ >+Ref<LocalStorageDatabase> LocalStorageDatabase::create(Ref<WorkQueue>&& queue, Ref<LocalStorageDatabaseTracker>&& tracker, const SecurityOriginData& securityOrigin) >+{ >+ return adoptRef(*new LocalStorageDatabase(WTFMove(queue), WTFMove(tracker), securityOrigin)); >+} >+ >+LocalStorageDatabase::LocalStorageDatabase(Ref<WorkQueue>&& queue, Ref<LocalStorageDatabaseTracker>&& tracker, const SecurityOriginData& securityOrigin) >+ : m_queue(WTFMove(queue)) >+ , m_tracker(WTFMove(tracker)) >+ , m_securityOrigin(securityOrigin) >+ , m_databasePath(m_tracker->databasePath(m_securityOrigin)) >+ , m_failedToOpenDatabase(false) >+ , m_didImportItems(false) >+ , m_isClosed(false) >+ , m_didScheduleDatabaseUpdate(false) >+ , m_shouldClearItems(false) >+{ >+} >+ >+LocalStorageDatabase::~LocalStorageDatabase() >+{ >+ ASSERT(m_isClosed); >+} >+ >+void LocalStorageDatabase::openDatabase(DatabaseOpeningStrategy openingStrategy) >+{ >+ ASSERT(!m_database.isOpen()); >+ ASSERT(!m_failedToOpenDatabase); >+ >+ if (!tryToOpenDatabase(openingStrategy)) { >+ m_failedToOpenDatabase = true; >+ return; >+ } >+ >+ if (m_database.isOpen()) >+ m_tracker->didOpenDatabaseWithOrigin(m_securityOrigin); >+} >+ >+bool LocalStorageDatabase::tryToOpenDatabase(DatabaseOpeningStrategy openingStrategy) >+{ >+ if (!FileSystem::fileExists(m_databasePath) && openingStrategy == SkipIfNonExistent) >+ return true; >+ >+ if (m_databasePath.isEmpty()) { >+ LOG_ERROR("Filename for local storage database is empty - cannot open for persistent storage"); >+ return false; >+ } >+ >+ if (!m_database.open(m_databasePath)) { >+ LOG_ERROR("Failed to open database file %s for local storage", m_databasePath.utf8().data()); >+ return false; >+ } >+ >+ // Since a WorkQueue isn't bound to a specific thread, we have to disable threading checks >+ // even though we never access the database from different threads simultaneously. >+ m_database.disableThreadingChecks(); >+ >+ if (!migrateItemTableIfNeeded()) { >+ // We failed to migrate the item table. In order to avoid trying to migrate the table over and over, >+ // just delete it and start from scratch. >+ if (!m_database.executeCommand("DROP TABLE ItemTable")) >+ LOG_ERROR("Failed to delete table ItemTable for local storage"); >+ } >+ >+ 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"); >+ return false; >+ } >+ >+ return true; >+} >+ >+bool LocalStorageDatabase::migrateItemTableIfNeeded() >+{ >+ if (!m_database.tableExists("ItemTable")) >+ return true; >+ >+ SQLiteStatement query(m_database, "SELECT value FROM ItemTable LIMIT 1"); >+ >+ // This query isn't ever executed, it's just used to check the column type. >+ if (query.isColumnDeclaredAsBlob(0)) >+ return true; >+ >+ // Create a new table with the right type, copy all the data over to it and then replace the new table with the old table. >+ 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])) >+ continue; >+ >+ LOG_ERROR("Failed to migrate table ItemTable for local storage when executing: %s", commands[i]); >+ transaction.rollback(); >+ >+ return false; >+ } >+ >+ transaction.commit(); >+ return true; >+} >+ >+void LocalStorageDatabase::importItems(StorageMap& storageMap) >+{ >+ if (m_didImportItems) >+ return; >+ >+ // 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 >+ >+ // We set this to true even if we don't end up importing any items due to failure because >+ // there's really no good way to recover other than not importing anything. >+ m_didImportItems = true; >+ >+ openDatabase(SkipIfNonExistent); >+ if (!m_database.isOpen()) >+ return; >+ >+ SQLiteStatement query(m_database, "SELECT key, value FROM ItemTable"); >+ if (query.prepare() != SQLITE_OK) { >+ LOG_ERROR("Unable to select items from ItemTable for local storage"); >+ return; >+ } >+ >+ HashMap<String, String> items; >+ >+ int result = query.step(); >+ while (result == SQLITE_ROW) { >+ String key = query.getColumnText(0); >+ String value = query.getColumnBlobAsString(1); >+ if (!key.isNull() && !value.isNull()) >+ items.set(key, value); >+ result = query.step(); >+ } >+ >+ if (result != SQLITE_DONE) { >+ LOG_ERROR("Error reading items from ItemTable for local storage"); >+ return; >+ } >+ >+ storageMap.importItems(items); >+} >+ >+void LocalStorageDatabase::setItem(const String& key, const String& value) >+{ >+ itemDidChange(key, value); >+} >+ >+void LocalStorageDatabase::removeItem(const String& key) >+{ >+ itemDidChange(key, String()); >+} >+ >+void LocalStorageDatabase::clear() >+{ >+ m_changedItems.clear(); >+ m_shouldClearItems = true; >+ >+ scheduleDatabaseUpdate(); >+} >+ >+void LocalStorageDatabase::close() >+{ >+ ASSERT(!m_isClosed); >+ m_isClosed = true; >+ >+ if (m_didScheduleDatabaseUpdate) { >+ updateDatabaseWithChangedItems(m_changedItems); >+ m_changedItems.clear(); >+ } >+ >+ bool isEmpty = databaseIsEmpty(); >+ >+ if (m_database.isOpen()) >+ m_database.close(); >+ >+ if (isEmpty) >+ m_tracker->deleteDatabaseWithOrigin(m_securityOrigin); >+} >+ >+void LocalStorageDatabase::itemDidChange(const String& key, const String& value) >+{ >+ m_changedItems.set(key, value); >+ scheduleDatabaseUpdate(); >+} >+ >+void LocalStorageDatabase::scheduleDatabaseUpdate() >+{ >+ if (m_didScheduleDatabaseUpdate) >+ return; >+ >+ if (!m_disableSuddenTerminationWhileWritingToLocalStorage) >+ m_disableSuddenTerminationWhileWritingToLocalStorage = std::make_unique<SuddenTerminationDisabler>(); >+ >+ m_didScheduleDatabaseUpdate = true; >+ >+ m_queue->dispatchAfter(databaseUpdateInterval, [protectedThis = makeRef(*this)] { >+ protectedThis->updateDatabase(); >+ }); >+} >+ >+void LocalStorageDatabase::updateDatabase() >+{ >+ if (m_isClosed) >+ return; >+ >+ ASSERT(m_didScheduleDatabaseUpdate); >+ m_didScheduleDatabaseUpdate = false; >+ >+ HashMap<String, String> changedItems; >+ if (m_changedItems.size() <= maximumItemsToUpdate) { >+ // There are few enough changed items that we can just always write all of them. >+ m_changedItems.swap(changedItems); >+ updateDatabaseWithChangedItems(changedItems); >+ m_disableSuddenTerminationWhileWritingToLocalStorage = nullptr; >+ } else { >+ for (int i = 0; i < maximumItemsToUpdate; ++i) { >+ auto it = m_changedItems.begin(); >+ changedItems.add(it->key, it->value); >+ >+ m_changedItems.remove(it); >+ } >+ >+ ASSERT(changedItems.size() <= maximumItemsToUpdate); >+ >+ // Reschedule the update for the remaining items. >+ scheduleDatabaseUpdate(); >+ updateDatabaseWithChangedItems(changedItems); >+ } >+} >+ >+void LocalStorageDatabase::updateDatabaseWithChangedItems(const HashMap<String, String>& changedItems) >+{ >+ if (!m_database.isOpen()) >+ openDatabase(CreateIfNonExistent); >+ if (!m_database.isOpen()) >+ return; >+ >+ if (m_shouldClearItems) { >+ m_shouldClearItems = false; >+ >+ SQLiteStatement clearStatement(m_database, "DELETE FROM ItemTable"); >+ if (clearStatement.prepare() != SQLITE_OK) { >+ LOG_ERROR("Failed to prepare clear statement - cannot write to local storage database"); >+ return; >+ } >+ >+ int result = clearStatement.step(); >+ if (result != SQLITE_DONE) { >+ LOG_ERROR("Failed to clear all items in the local storage database - %i", result); >+ return; >+ } >+ } >+ >+ SQLiteStatement insertStatement(m_database, "INSERT INTO ItemTable VALUES (?, ?)"); >+ if (insertStatement.prepare() != SQLITE_OK) { >+ LOG_ERROR("Failed to prepare insert statement - cannot write to local storage database"); >+ return; >+ } >+ >+ SQLiteStatement deleteStatement(m_database, "DELETE FROM ItemTable WHERE key=?"); >+ if (deleteStatement.prepare() != SQLITE_OK) { >+ LOG_ERROR("Failed to prepare delete statement - cannot write to local storage database"); >+ return; >+ } >+ >+ SQLiteTransaction transaction(m_database); >+ transaction.begin(); >+ >+ for (auto it = changedItems.begin(), end = changedItems.end(); it != end; ++it) { >+ // A null value means that the key/value pair should be deleted. >+ SQLiteStatement& statement = it->value.isNull() ? deleteStatement : insertStatement; >+ >+ statement.bindText(1, it->key); >+ >+ // If we're inserting a key/value pair, bind the value as well. >+ if (!it->value.isNull()) >+ statement.bindBlob(2, it->value); >+ >+ int result = statement.step(); >+ if (result != SQLITE_DONE) { >+ LOG_ERROR("Failed to update item in the local storage database - %i", result); >+ break; >+ } >+ >+ statement.reset(); >+ } >+ >+ transaction.commit(); >+} >+ >+bool LocalStorageDatabase::databaseIsEmpty() >+{ >+ if (!m_database.isOpen()) >+ return false; >+ >+ SQLiteStatement query(m_database, "SELECT COUNT(*) FROM ItemTable"); >+ if (query.prepare() != SQLITE_OK) { >+ LOG_ERROR("Unable to count number of rows in ItemTable for local storage"); >+ return false; >+ } >+ >+ int result = query.step(); >+ if (result != SQLITE_ROW) { >+ LOG_ERROR("No results when counting number of rows in ItemTable for local storage"); >+ return false; >+ } >+ >+ return !query.getColumnInt(0); >+} >+ >+} // namespace WebKit >diff --git a/Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabase.h b/Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabase.h >new file mode 100644 >index 0000000000000000000000000000000000000000..9992031f448fb3d91580186d8860a12d84859562 >--- /dev/null >+++ b/Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabase.h >@@ -0,0 +1,99 @@ >+/* >+ * Copyright (C) 2008, 2009, 2010, 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. >+ */ >+ >+#pragma once >+ >+#include <WebCore/SQLiteDatabase.h> >+#include <WebCore/SecurityOriginData.h> >+#include <wtf/Forward.h> >+#include <wtf/HashMap.h> >+#include <wtf/RefPtr.h> >+#include <wtf/ThreadSafeRefCounted.h> >+#include <wtf/WorkQueue.h> >+ >+namespace WebCore { >+class SecurityOrigin; >+class StorageMap; >+class SuddenTerminationDisabler; >+} >+ >+namespace WebKit { >+ >+class LocalStorageDatabaseTracker; >+ >+class LocalStorageDatabase : public ThreadSafeRefCounted<LocalStorageDatabase> { >+public: >+ static Ref<LocalStorageDatabase> create(Ref<WorkQueue>&&, Ref<LocalStorageDatabaseTracker>&&, const WebCore::SecurityOriginData&); >+ ~LocalStorageDatabase(); >+ >+ // Will block until the import is complete. >+ void importItems(WebCore::StorageMap&); >+ >+ void setItem(const String& key, const String& value); >+ void removeItem(const String& key); >+ void clear(); >+ >+ // Will block until all pending changes have been written to disk. >+ void close(); >+ >+private: >+ LocalStorageDatabase(Ref<WorkQueue>&&, Ref<LocalStorageDatabaseTracker>&&, const WebCore::SecurityOriginData&); >+ >+ enum DatabaseOpeningStrategy { >+ CreateIfNonExistent, >+ SkipIfNonExistent >+ }; >+ bool tryToOpenDatabase(DatabaseOpeningStrategy); >+ void openDatabase(DatabaseOpeningStrategy); >+ >+ bool migrateItemTableIfNeeded(); >+ >+ void itemDidChange(const String& key, const String& value); >+ >+ void scheduleDatabaseUpdate(); >+ void updateDatabase(); >+ void updateDatabaseWithChangedItems(const HashMap<String, String>&); >+ >+ bool databaseIsEmpty(); >+ >+ Ref<WorkQueue> m_queue; >+ Ref<LocalStorageDatabaseTracker> m_tracker; >+ WebCore::SecurityOriginData m_securityOrigin; >+ >+ String m_databasePath; >+ WebCore::SQLiteDatabase m_database; >+ bool m_failedToOpenDatabase; >+ bool m_didImportItems; >+ bool m_isClosed; >+ >+ bool m_didScheduleDatabaseUpdate; >+ bool m_shouldClearItems; >+ HashMap<String, String> m_changedItems; >+ >+ std::unique_ptr<WebCore::SuddenTerminationDisabler> m_disableSuddenTerminationWhileWritingToLocalStorage; >+}; >+ >+ >+} // namespace WebKit >diff --git a/Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabaseTracker.cpp b/Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabaseTracker.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..9a10cfa76e014f97a6adb36c04bf6f559011176f >--- /dev/null >+++ b/Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabaseTracker.cpp >@@ -0,0 +1,166 @@ >+/* >+ * Copyright (C) 2011, 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 "LocalStorageDatabaseTracker.h" >+ >+#include "Logging.h" >+#include <WebCore/SQLiteFileSystem.h> >+#include <WebCore/SQLiteStatement.h> >+#include <WebCore/TextEncoding.h> >+#include <wtf/FileSystem.h> >+#include <wtf/MainThread.h> >+#include <wtf/RunLoop.h> >+#include <wtf/WorkQueue.h> >+#include <wtf/text/CString.h> >+ >+namespace WebKit { >+using namespace WebCore; >+ >+Ref<LocalStorageDatabaseTracker> LocalStorageDatabaseTracker::create(Ref<WorkQueue>&& queue, const String& localStorageDirectory) >+{ >+ return adoptRef(*new LocalStorageDatabaseTracker(WTFMove(queue), localStorageDirectory)); >+} >+ >+LocalStorageDatabaseTracker::LocalStorageDatabaseTracker(Ref<WorkQueue>&& queue, const String& localStorageDirectory) >+ : m_queue(WTFMove(queue)) >+ , m_localStorageDirectory(localStorageDirectory.isolatedCopy()) >+{ >+ // Make sure the encoding is initialized before we start dispatching things to the queue. >+ UTF8Encoding(); >+ >+#if PLATFORM(IOS_FAMILY) >+ platformMaybeExcludeFromBackup(); >+#endif >+ >+ m_queue->dispatch([protectedThis = makeRef(*this)]() mutable { >+ // Delete legacy storageTracker database file. >+ SQLiteFileSystem::deleteDatabaseFile(protectedThis->databasePath("StorageTracker.db")); >+ }); >+} >+ >+LocalStorageDatabaseTracker::~LocalStorageDatabaseTracker() >+{ >+} >+ >+String LocalStorageDatabaseTracker::databasePath(const SecurityOriginData& securityOrigin) const >+{ >+ return databasePath(securityOrigin.databaseIdentifier() + ".localstorage"); >+} >+ >+void LocalStorageDatabaseTracker::didOpenDatabaseWithOrigin(const SecurityOriginData& securityOrigin) >+{ >+ // FIXME: Tell clients that the origin was added. >+} >+ >+void LocalStorageDatabaseTracker::deleteDatabaseWithOrigin(const SecurityOriginData& securityOrigin) >+{ >+ auto path = databasePath(securityOrigin); >+ if (!path.isEmpty()) >+ SQLiteFileSystem::deleteDatabaseFile(path); >+ >+ // FIXME: Tell clients that the origin was removed. >+} >+ >+void LocalStorageDatabaseTracker::deleteAllDatabases() >+{ >+ auto paths = FileSystem::listDirectory(m_localStorageDirectory, "*.localstorage"); >+ for (const auto& path : paths) { >+ SQLiteFileSystem::deleteDatabaseFile(path); >+ >+ // FIXME: Call out to the client. >+ } >+ >+ SQLiteFileSystem::deleteEmptyDatabaseDirectory(m_localStorageDirectory); >+} >+ >+Vector<SecurityOriginData> LocalStorageDatabaseTracker::databasesModifiedSince(WallTime time) >+{ >+ Vector<SecurityOriginData> databaseOriginsModified; >+ auto databaseOrigins = origins(); >+ >+ for (auto origin : databaseOrigins) { >+ auto path = databasePath(origin); >+ >+ auto modificationTime = SQLiteFileSystem::databaseModificationTime(path); >+ if (!modificationTime) >+ continue; >+ >+ if (modificationTime.value() >= time) >+ databaseOriginsModified.append(origin); >+ } >+ >+ return databaseOriginsModified; >+} >+ >+Vector<SecurityOriginData> LocalStorageDatabaseTracker::origins() const >+{ >+ Vector<SecurityOriginData> databaseOrigins; >+ auto paths = FileSystem::listDirectory(m_localStorageDirectory, "*.localstorage"); >+ >+ for (const auto& path : paths) { >+ auto filename = FileSystem::pathGetFileName(path); >+ auto originIdentifier = filename.substring(0, filename.length() - strlen(".localstorage")); >+ auto origin = SecurityOriginData::fromDatabaseIdentifier(originIdentifier); >+ if (origin) >+ databaseOrigins.append(origin.value()); >+ else >+ RELEASE_LOG_ERROR(LocalStorageDatabaseTracker, "Unable to extract origin from path %s", path.utf8().data()); >+ } >+ >+ return databaseOrigins; >+} >+ >+Vector<LocalStorageDatabaseTracker::OriginDetails> LocalStorageDatabaseTracker::originDetails() >+{ >+ Vector<OriginDetails> result; >+ auto databaseOrigins = origins(); >+ result.reserveInitialCapacity(databaseOrigins.size()); >+ >+ for (const auto& origin : databaseOrigins) { >+ String path = databasePath(origin); >+ >+ OriginDetails details; >+ details.originIdentifier = origin.databaseIdentifier(); >+ details.creationTime = SQLiteFileSystem::databaseCreationTime(path); >+ details.modificationTime = SQLiteFileSystem::databaseModificationTime(path); >+ result.uncheckedAppend(details); >+ } >+ >+ return result; >+} >+ >+String LocalStorageDatabaseTracker::databasePath(const String& filename) const >+{ >+ if (!SQLiteFileSystem::ensureDatabaseDirectoryExists(m_localStorageDirectory)) { >+ if (!m_localStorageDirectory.isNull()) >+ LOG_ERROR("Unable to create LocalStorage database path %s", m_localStorageDirectory.utf8().data()); >+ return String(); >+ } >+ >+ return SQLiteFileSystem::appendDatabaseFileNameToPath(m_localStorageDirectory, filename); >+} >+ >+} // namespace WebKit >diff --git a/Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabaseTracker.h b/Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabaseTracker.h >new file mode 100644 >index 0000000000000000000000000000000000000000..95694d06ff6043136e50fcab909f72654f92ab2c >--- /dev/null >+++ b/Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabaseTracker.h >@@ -0,0 +1,106 @@ >+/* >+ * Copyright (C) 2011, 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. >+ */ >+ >+#pragma once >+ >+#include <WebCore/SecurityOriginData.h> >+#include <wtf/Markable.h> >+#include <wtf/RefPtr.h> >+#include <wtf/ThreadSafeRefCounted.h> >+#include <wtf/WallTime.h> >+#include <wtf/WorkQueue.h> >+#include <wtf/text/WTFString.h> >+ >+namespace WebKit { >+ >+class LocalStorageDatabaseTracker : public ThreadSafeRefCounted<LocalStorageDatabaseTracker> { >+public: >+ static Ref<LocalStorageDatabaseTracker> create(Ref<WorkQueue>&&, const String& localStorageDirectory); >+ ~LocalStorageDatabaseTracker(); >+ >+ String databasePath(const WebCore::SecurityOriginData&) const; >+ >+ void didOpenDatabaseWithOrigin(const WebCore::SecurityOriginData&); >+ void deleteDatabaseWithOrigin(const WebCore::SecurityOriginData&); >+ void deleteAllDatabases(); >+ >+ // Returns a vector of the origins whose databases should be deleted. >+ Vector<WebCore::SecurityOriginData> databasesModifiedSince(WallTime); >+ >+ Vector<WebCore::SecurityOriginData> origins() const; >+ >+ struct OriginDetails { >+ String originIdentifier; >+ Optional<WallTime> creationTime; >+ Optional<WallTime> modificationTime; >+ >+ template<class Encoder> void encode(Encoder&) const; >+ template<class Decoder> static Optional<OriginDetails> decode(Decoder&); >+ }; >+ Vector<OriginDetails> originDetails(); >+ >+private: >+ LocalStorageDatabaseTracker(Ref<WorkQueue>&&, const String& localStorageDirectory); >+ >+ String databasePath(const String& filename) const; >+ >+ enum DatabaseOpeningStrategy { >+ CreateIfNonExistent, >+ SkipIfNonExistent >+ }; >+ >+ RefPtr<WorkQueue> m_queue; >+ String m_localStorageDirectory; >+ >+#if PLATFORM(IOS_FAMILY) >+ void platformMaybeExcludeFromBackup() const; >+ >+ mutable bool m_hasExcludedFromBackup { false }; >+#endif >+}; >+ >+template<class Encoder> >+void LocalStorageDatabaseTracker::OriginDetails::encode(Encoder& encoder) const >+{ >+ encoder << originIdentifier << creationTime << modificationTime; >+} >+ >+template<class Decoder> >+Optional<LocalStorageDatabaseTracker::OriginDetails> LocalStorageDatabaseTracker::OriginDetails::decode(Decoder& decoder) >+{ >+ LocalStorageDatabaseTracker::OriginDetails result; >+ if (!decoder.decode(result.originIdentifier)) >+ return WTF::nullopt; >+ >+ if (!decoder.decode(result.creationTime)) >+ return WTF::nullopt; >+ >+ if (!decoder.decode(result.modificationTime)) >+ return WTF::nullopt; >+ >+ return result; >+} >+ >+} // namespace WebKit >diff --git a/Source/WebKit/NetworkProcess/WebStorage/StorageManager.cpp b/Source/WebKit/NetworkProcess/WebStorage/StorageManager.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..8a684bdc6328ff17a4f523b9da25477083df7c87 >--- /dev/null >+++ b/Source/WebKit/NetworkProcess/WebStorage/StorageManager.cpp >@@ -0,0 +1,936 @@ >+/* >+ * Copyright (C) 2013-2016 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 "StorageManager.h" >+ >+#include "LocalStorageDatabase.h" >+#include "LocalStorageDatabaseTracker.h" >+#include "StorageAreaMapMessages.h" >+#include "StorageManagerMessages.h" >+#include "WebProcessProxy.h" >+#include <WebCore/SecurityOriginData.h> >+#include <WebCore/SecurityOriginHash.h> >+#include <WebCore/StorageMap.h> >+#include <WebCore/TextEncoding.h> >+#include <memory> >+#include <wtf/WorkQueue.h> >+#include <wtf/threads/BinarySemaphore.h> >+ >+namespace WebKit { >+using namespace WebCore; >+ >+class StorageManager::StorageArea : public ThreadSafeRefCounted<StorageManager::StorageArea> { >+public: >+ static Ref<StorageArea> create(LocalStorageNamespace*, const SecurityOriginData&, unsigned quotaInBytes); >+ ~StorageArea(); >+ >+ const WebCore::SecurityOriginData& securityOrigin() const { return m_securityOrigin; } >+ >+ void addListener(IPC::Connection::UniqueID, uint64_t storageMapID); >+ void removeListener(IPC::Connection::UniqueID, uint64_t storageMapID); >+ bool hasListener(IPC::Connection::UniqueID, uint64_t storageMapID) const; >+ >+ Ref<StorageArea> clone() const; >+ >+ void setItem(IPC::Connection::UniqueID sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& value, const String& urlString, bool& quotaException); >+ void removeItem(IPC::Connection::UniqueID sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& urlString); >+ void clear(IPC::Connection::UniqueID sourceConnection, uint64_t sourceStorageAreaID, const String& urlString); >+ >+ const HashMap<String, String>& items() const; >+ void clear(); >+ >+ bool isSessionStorage() const { return !m_localStorageNamespace; } >+ >+private: >+ explicit StorageArea(LocalStorageNamespace*, const SecurityOriginData&, unsigned quotaInBytes); >+ >+ void openDatabaseAndImportItemsIfNeeded() const; >+ >+ void dispatchEvents(IPC::Connection::UniqueID sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& oldValue, const String& newValue, const String& urlString) const; >+ >+ // Will be null if the storage area belongs to a session storage namespace. >+ LocalStorageNamespace* m_localStorageNamespace; >+ mutable RefPtr<LocalStorageDatabase> m_localStorageDatabase; >+ mutable bool m_didImportItemsFromDatabase { false }; >+ >+ SecurityOriginData m_securityOrigin; >+ unsigned m_quotaInBytes; >+ >+ RefPtr<StorageMap> m_storageMap; >+ HashSet<std::pair<IPC::Connection::UniqueID, uint64_t>> m_eventListeners; >+}; >+ >+class StorageManager::LocalStorageNamespace : public ThreadSafeRefCounted<LocalStorageNamespace> { >+public: >+ static Ref<LocalStorageNamespace> create(StorageManager*, uint64_t storageManagerID); >+ ~LocalStorageNamespace(); >+ >+ StorageManager* storageManager() const { return m_storageManager; } >+ >+ Ref<StorageArea> getOrCreateStorageArea(SecurityOriginData&&); >+ void didDestroyStorageArea(StorageArea*); >+ >+ void clearStorageAreasMatchingOrigin(const SecurityOriginData&); >+ void clearAllStorageAreas(); >+ >+private: >+ explicit LocalStorageNamespace(StorageManager*, uint64_t storageManagerID); >+ >+ StorageManager* m_storageManager; >+ uint64_t m_storageNamespaceID; >+ unsigned m_quotaInBytes; >+ >+ // We don't hold an explicit reference to the StorageAreas; they are kept alive by the m_storageAreasByConnection map in StorageManager. >+ HashMap<SecurityOriginData, StorageArea*> m_storageAreaMap; >+}; >+ >+// Suggested by https://www.w3.org/TR/webstorage/#disk-space >+const unsigned localStorageDatabaseQuotaInBytes = 5 * 1024 * 1024; >+ >+class StorageManager::TransientLocalStorageNamespace : public ThreadSafeRefCounted<TransientLocalStorageNamespace> { >+public: >+ static Ref<TransientLocalStorageNamespace> create() >+ { >+ return adoptRef(*new TransientLocalStorageNamespace()); >+ } >+ >+ ~TransientLocalStorageNamespace() >+ { >+ } >+ >+ Ref<StorageArea> getOrCreateStorageArea(SecurityOriginData&& securityOrigin) >+ { >+ return *m_storageAreaMap.ensure(securityOrigin, [this, securityOrigin]() mutable { >+ return StorageArea::create(nullptr, WTFMove(securityOrigin), m_quotaInBytes); >+ }).iterator->value.copyRef(); >+ } >+ >+ Vector<SecurityOriginData> origins() const >+ { >+ Vector<SecurityOriginData> origins; >+ >+ for (const auto& storageArea : m_storageAreaMap.values()) { >+ if (!storageArea->items().isEmpty()) >+ origins.append(storageArea->securityOrigin()); >+ } >+ >+ return origins; >+ } >+ >+ void clearStorageAreasMatchingOrigin(const SecurityOriginData& securityOrigin) >+ { >+ for (auto& storageArea : m_storageAreaMap.values()) { >+ if (storageArea->securityOrigin() == securityOrigin) >+ storageArea->clear(); >+ } >+ } >+ >+ void clearAllStorageAreas() >+ { >+ for (auto& storageArea : m_storageAreaMap.values()) >+ storageArea->clear(); >+ } >+ >+private: >+ explicit TransientLocalStorageNamespace() >+ { >+ } >+ >+ const unsigned m_quotaInBytes = localStorageDatabaseQuotaInBytes; >+ >+ HashMap<SecurityOriginData, RefPtr<StorageArea>> m_storageAreaMap; >+}; >+ >+auto StorageManager::StorageArea::create(LocalStorageNamespace* localStorageNamespace, const SecurityOriginData& securityOrigin, unsigned quotaInBytes) -> Ref<StorageManager::StorageArea> >+{ >+ return adoptRef(*new StorageArea(localStorageNamespace, securityOrigin, quotaInBytes)); >+} >+ >+StorageManager::StorageArea::StorageArea(LocalStorageNamespace* localStorageNamespace, const SecurityOriginData& securityOrigin, unsigned quotaInBytes) >+ : m_localStorageNamespace(localStorageNamespace) >+ , m_securityOrigin(securityOrigin) >+ , m_quotaInBytes(quotaInBytes) >+ , m_storageMap(StorageMap::create(m_quotaInBytes)) >+{ >+} >+ >+StorageManager::StorageArea::~StorageArea() >+{ >+ ASSERT(m_eventListeners.isEmpty()); >+ >+ if (m_localStorageDatabase) >+ m_localStorageDatabase->close(); >+ >+ if (m_localStorageNamespace) >+ m_localStorageNamespace->didDestroyStorageArea(this); >+} >+ >+void StorageManager::StorageArea::addListener(IPC::Connection::UniqueID connectionID, uint64_t storageMapID) >+{ >+ ASSERT(!m_eventListeners.contains(std::make_pair(connectionID, storageMapID))); >+ m_eventListeners.add(std::make_pair(connectionID, storageMapID)); >+} >+ >+void StorageManager::StorageArea::removeListener(IPC::Connection::UniqueID connectionID, uint64_t storageMapID) >+{ >+ ASSERT(isSessionStorage() || m_eventListeners.contains(std::make_pair(connectionID, storageMapID))); >+ m_eventListeners.remove(std::make_pair(connectionID, storageMapID)); >+} >+ >+bool StorageManager::StorageArea::hasListener(IPC::Connection::UniqueID connectionID, uint64_t storageMapID) const >+{ >+ return m_eventListeners.contains(std::make_pair(connectionID, storageMapID)); >+} >+ >+Ref<StorageManager::StorageArea> StorageManager::StorageArea::clone() const >+{ >+ ASSERT(!m_localStorageNamespace); >+ >+ auto storageArea = StorageArea::create(nullptr, m_securityOrigin, m_quotaInBytes); >+ storageArea->m_storageMap = m_storageMap; >+ >+ return storageArea; >+} >+ >+void StorageManager::StorageArea::setItem(IPC::Connection::UniqueID sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& value, const String& urlString, bool& quotaException) >+{ >+ openDatabaseAndImportItemsIfNeeded(); >+ >+ String oldValue; >+ >+ auto newStorageMap = m_storageMap->setItem(key, value, oldValue, quotaException); >+ if (newStorageMap) >+ m_storageMap = WTFMove(newStorageMap); >+ >+ if (quotaException) >+ return; >+ >+ if (m_localStorageDatabase) >+ m_localStorageDatabase->setItem(key, value); >+ >+ dispatchEvents(sourceConnection, sourceStorageAreaID, key, oldValue, value, urlString); >+} >+ >+void StorageManager::StorageArea::removeItem(IPC::Connection::UniqueID sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& urlString) >+{ >+ openDatabaseAndImportItemsIfNeeded(); >+ >+ String oldValue; >+ auto newStorageMap = m_storageMap->removeItem(key, oldValue); >+ if (newStorageMap) >+ m_storageMap = WTFMove(newStorageMap); >+ >+ if (oldValue.isNull()) >+ return; >+ >+ if (m_localStorageDatabase) >+ m_localStorageDatabase->removeItem(key); >+ >+ dispatchEvents(sourceConnection, sourceStorageAreaID, key, oldValue, String(), urlString); >+} >+ >+void StorageManager::StorageArea::clear(IPC::Connection::UniqueID sourceConnection, uint64_t sourceStorageAreaID, const String& urlString) >+{ >+ openDatabaseAndImportItemsIfNeeded(); >+ >+ if (!m_storageMap->length()) >+ return; >+ >+ m_storageMap = StorageMap::create(m_quotaInBytes); >+ >+ if (m_localStorageDatabase) >+ m_localStorageDatabase->clear(); >+ >+ dispatchEvents(sourceConnection, sourceStorageAreaID, String(), String(), String(), urlString); >+} >+ >+const HashMap<String, String>& StorageManager::StorageArea::items() const >+{ >+ openDatabaseAndImportItemsIfNeeded(); >+ >+ return m_storageMap->items(); >+} >+ >+void StorageManager::StorageArea::clear() >+{ >+ m_storageMap = StorageMap::create(m_quotaInBytes); >+ >+ if (m_localStorageDatabase) { >+ m_localStorageDatabase->close(); >+ m_localStorageDatabase = nullptr; >+ } >+ >+ for (auto it = m_eventListeners.begin(), end = m_eventListeners.end(); it != end; ++it) { >+ RunLoop::main().dispatch([connectionID = it->first, destinationStorageAreaID = it->second] { >+ if (auto* connection = IPC::Connection::connection(connectionID)) >+ connection->send(Messages::StorageAreaMap::ClearCache(), destinationStorageAreaID); >+ }); >+ } >+} >+ >+void StorageManager::StorageArea::openDatabaseAndImportItemsIfNeeded() const >+{ >+ if (!m_localStorageNamespace) >+ return; >+ >+ // We open the database here even if we've already imported our items to ensure that the database is open if we need to write to it. >+ if (!m_localStorageDatabase) >+ m_localStorageDatabase = LocalStorageDatabase::create(m_localStorageNamespace->storageManager()->m_queue.copyRef(), m_localStorageNamespace->storageManager()->m_localStorageDatabaseTracker.copyRef(), m_securityOrigin); >+ >+ if (m_didImportItemsFromDatabase) >+ return; >+ >+ m_localStorageDatabase->importItems(*m_storageMap); >+ m_didImportItemsFromDatabase = true; >+} >+ >+void StorageManager::StorageArea::dispatchEvents(IPC::Connection::UniqueID sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& oldValue, const String& newValue, const String& urlString) const >+{ >+ for (auto it = m_eventListeners.begin(), end = m_eventListeners.end(); it != end; ++it) { >+ sourceStorageAreaID = it->first == sourceConnection ? sourceStorageAreaID : 0; >+ >+ RunLoop::main().dispatch([connectionID = it->first, sourceStorageAreaID, destinationStorageAreaID = it->second, key = key.isolatedCopy(), oldValue = oldValue.isolatedCopy(), newValue = newValue.isolatedCopy(), urlString = urlString.isolatedCopy()] { >+ if (auto* connection = IPC::Connection::connection(connectionID)) >+ connection->send(Messages::StorageAreaMap::DispatchStorageEvent(sourceStorageAreaID, key, oldValue, newValue, urlString), destinationStorageAreaID); >+ }); >+ } >+} >+ >+Ref<StorageManager::LocalStorageNamespace> StorageManager::LocalStorageNamespace::create(StorageManager* storageManager, uint64_t storageNamespaceID) >+{ >+ return adoptRef(*new LocalStorageNamespace(storageManager, storageNamespaceID)); >+} >+ >+// FIXME: The quota value is copied from GroupSettings.cpp. >+// We should investigate a way to share it with WebCore. >+StorageManager::LocalStorageNamespace::LocalStorageNamespace(StorageManager* storageManager, uint64_t storageNamespaceID) >+ : m_storageManager(storageManager) >+ , m_storageNamespaceID(storageNamespaceID) >+ , m_quotaInBytes(localStorageDatabaseQuotaInBytes) >+{ >+} >+ >+StorageManager::LocalStorageNamespace::~LocalStorageNamespace() >+{ >+ ASSERT(m_storageAreaMap.isEmpty()); >+} >+ >+auto StorageManager::LocalStorageNamespace::getOrCreateStorageArea(SecurityOriginData&& securityOrigin) -> Ref<StorageArea> >+{ >+ auto& slot = m_storageAreaMap.add(securityOrigin, nullptr).iterator->value; >+ if (slot) >+ return *slot; >+ >+ auto storageArea = StorageArea::create(this, WTFMove(securityOrigin), m_quotaInBytes); >+ slot = &storageArea.get(); >+ >+ return storageArea; >+} >+ >+void StorageManager::LocalStorageNamespace::didDestroyStorageArea(StorageArea* storageArea) >+{ >+ ASSERT(m_storageAreaMap.contains(storageArea->securityOrigin())); >+ >+ m_storageAreaMap.remove(storageArea->securityOrigin()); >+ if (!m_storageAreaMap.isEmpty()) >+ return; >+ >+ ASSERT(m_storageManager->m_localStorageNamespaces.contains(m_storageNamespaceID)); >+ m_storageManager->m_localStorageNamespaces.remove(m_storageNamespaceID); >+} >+ >+void StorageManager::LocalStorageNamespace::clearStorageAreasMatchingOrigin(const SecurityOriginData& securityOrigin) >+{ >+ for (const auto& originAndStorageArea : m_storageAreaMap) { >+ if (originAndStorageArea.key == securityOrigin) >+ originAndStorageArea.value->clear(); >+ } >+} >+ >+void StorageManager::LocalStorageNamespace::clearAllStorageAreas() >+{ >+ for (auto* storageArea : m_storageAreaMap.values()) >+ storageArea->clear(); >+} >+ >+class StorageManager::SessionStorageNamespace : public ThreadSafeRefCounted<SessionStorageNamespace> { >+public: >+ static Ref<SessionStorageNamespace> create(unsigned quotaInBytes); >+ ~SessionStorageNamespace(); >+ >+ bool isEmpty() const { return m_storageAreaMap.isEmpty(); } >+ >+ HashSet<IPC::Connection::UniqueID> allowedConnections() const { return m_allowedConnections; } >+ void addAllowedConnection(IPC::Connection::UniqueID); >+ void removeAllowedConnection(IPC::Connection::UniqueID); >+ >+ Ref<StorageArea> getOrCreateStorageArea(SecurityOriginData&&); >+ >+ void cloneTo(SessionStorageNamespace& newSessionStorageNamespace); >+ >+ Vector<SecurityOriginData> origins() const >+ { >+ Vector<SecurityOriginData> origins; >+ >+ for (const auto& storageArea : m_storageAreaMap.values()) { >+ if (!storageArea->items().isEmpty()) >+ origins.append(storageArea->securityOrigin()); >+ } >+ >+ return origins; >+ } >+ >+ void clearStorageAreasMatchingOrigin(const SecurityOriginData& securityOrigin) >+ { >+ for (auto& storageArea : m_storageAreaMap.values()) { >+ if (storageArea->securityOrigin() == securityOrigin) >+ storageArea->clear(); >+ } >+ } >+ >+ void clearAllStorageAreas() >+ { >+ for (auto& storageArea : m_storageAreaMap.values()) >+ storageArea->clear(); >+ } >+ >+private: >+ explicit SessionStorageNamespace(unsigned quotaInBytes); >+ >+ HashSet<IPC::Connection::UniqueID> m_allowedConnections; >+ unsigned m_quotaInBytes; >+ >+ HashMap<SecurityOriginData, RefPtr<StorageArea>> m_storageAreaMap; >+}; >+ >+Ref<StorageManager::SessionStorageNamespace> StorageManager::SessionStorageNamespace::create(unsigned quotaInBytes) >+{ >+ return adoptRef(*new SessionStorageNamespace(quotaInBytes)); >+} >+ >+StorageManager::SessionStorageNamespace::SessionStorageNamespace(unsigned quotaInBytes) >+ : m_quotaInBytes(quotaInBytes) >+{ >+} >+ >+StorageManager::SessionStorageNamespace::~SessionStorageNamespace() >+{ >+} >+ >+void StorageManager::SessionStorageNamespace::addAllowedConnection(IPC::Connection::UniqueID allowedConnection) >+{ >+ m_allowedConnections.add(allowedConnection); >+} >+ >+ >+void StorageManager::SessionStorageNamespace::removeAllowedConnection(IPC::Connection::UniqueID allowedConnection) >+{ >+ ASSERT(m_allowedConnections.contains(allowedConnection)); >+ m_allowedConnections.remove(allowedConnection); >+} >+auto StorageManager::SessionStorageNamespace::getOrCreateStorageArea(SecurityOriginData&& securityOrigin) -> Ref<StorageArea> >+{ >+ return *m_storageAreaMap.ensure(securityOrigin, [this, securityOrigin]() mutable { >+ return StorageArea::create(nullptr, WTFMove(securityOrigin), m_quotaInBytes); >+ }).iterator->value.copyRef(); >+} >+ >+void StorageManager::SessionStorageNamespace::cloneTo(SessionStorageNamespace& newSessionStorageNamespace) >+{ >+ ASSERT_UNUSED(newSessionStorageNamespace, newSessionStorageNamespace.isEmpty()); >+ >+ for (auto& pair : m_storageAreaMap) >+ newSessionStorageNamespace.m_storageAreaMap.add(pair.key, pair.value->clone()); >+} >+ >+Ref<StorageManager> StorageManager::create(const String& localStorageDirectory) >+{ >+ return adoptRef(*new StorageManager(localStorageDirectory)); >+} >+ >+StorageManager::StorageManager(const String& localStorageDirectory) >+ : m_queue(WorkQueue::create("com.apple.WebKit.StorageManager")) >+ , m_localStorageDatabaseTracker(LocalStorageDatabaseTracker::create(m_queue.copyRef(), localStorageDirectory)) >+ , m_isEphemeral(localStorageDirectory.isNull()) >+{ >+ // Make sure the encoding is initialized before we start dispatching things to the queue. >+ UTF8Encoding(); >+} >+ >+StorageManager::~StorageManager() >+{ >+} >+ >+void StorageManager::createSessionStorageNamespace(uint64_t storageNamespaceID, unsigned quotaInBytes) >+{ >+ m_queue->dispatch([this, protectedThis = makeRef(*this), storageNamespaceID, quotaInBytes]() mutable { >+ if (m_sessionStorageNamespaces.contains(storageNamespaceID)) >+ return; >+ >+ m_sessionStorageNamespaces.set(storageNamespaceID, SessionStorageNamespace::create(quotaInBytes)); >+ }); >+} >+ >+void StorageManager::destroySessionStorageNamespace(uint64_t storageNamespaceID) >+{ >+ m_queue->dispatch([this, protectedThis = makeRef(*this), storageNamespaceID] { >+ ASSERT(m_sessionStorageNamespaces.contains(storageNamespaceID)); >+ if (m_sessionStorageNamespaces.get(storageNamespaceID)->allowedConnections().isEmpty()) >+ m_sessionStorageNamespaces.remove(storageNamespaceID); >+ }); >+} >+ >+void StorageManager::addAllowedSessionStorageNamespaceConnection(uint64_t storageNamespaceID, IPC::Connection& allowedConnection) >+{ >+ auto allowedConnectionID = allowedConnection.uniqueID(); >+ m_queue->dispatch([this, protectedThis = makeRef(*this), allowedConnectionID, storageNamespaceID]() mutable { >+ ASSERT(m_sessionStorageNamespaces.contains(storageNamespaceID)); >+ >+ m_sessionStorageNamespaces.get(storageNamespaceID)->addAllowedConnection(allowedConnectionID); >+ }); >+} >+ >+void StorageManager::removeAllowedSessionStorageNamespaceConnection(uint64_t storageNamespaceID, IPC::Connection& allowedConnection) >+{ >+ auto allowedConnectionID = allowedConnection.uniqueID(); >+ m_queue->dispatch([this, protectedThis = makeRef(*this), allowedConnectionID, storageNamespaceID]() mutable { >+ ASSERT(m_sessionStorageNamespaces.contains(storageNamespaceID)); >+ >+ m_sessionStorageNamespaces.get(storageNamespaceID)->removeAllowedConnection(allowedConnectionID); >+ }); >+} >+ >+void StorageManager::cloneSessionStorageNamespace(uint64_t storageNamespaceID, uint64_t newStorageNamespaceID) >+{ >+ m_queue->dispatch([this, protectedThis = makeRef(*this), storageNamespaceID, newStorageNamespaceID] { >+ SessionStorageNamespace* sessionStorageNamespace = m_sessionStorageNamespaces.get(storageNamespaceID); >+ if (!sessionStorageNamespace) { >+ // FIXME: We can get into this situation if someone closes the originating page from within a >+ // createNewPage callback. We bail for now, but we should really find a way to keep the session storage alive >+ // so we we'll clone the session storage correctly. >+ return; >+ } >+ >+ SessionStorageNamespace* newSessionStorageNamespace = m_sessionStorageNamespaces.get(newStorageNamespaceID); >+ ASSERT(newSessionStorageNamespace); >+ >+ sessionStorageNamespace->cloneTo(*newSessionStorageNamespace); >+ }); >+} >+ >+void StorageManager::processWillOpenConnection(IPC::Connection& connection) >+{ >+ connection.addWorkQueueMessageReceiver(Messages::StorageManager::messageReceiverName(), m_queue.get(), this); >+} >+ >+void StorageManager::processDidCloseConnection(IPC::Connection& connection) >+{ >+ connection.removeWorkQueueMessageReceiver(Messages::StorageManager::messageReceiverName()); >+ >+ m_queue->dispatch([this, protectedThis = makeRef(*this), connectionID = connection.uniqueID()]() mutable { >+ Vector<std::pair<IPC::Connection::UniqueID, uint64_t>> connectionAndStorageMapIDPairsToRemove; >+ for (auto& storageArea : m_storageAreasByConnection) { >+ if (storageArea.key.first != connectionID) >+ continue; >+ >+ storageArea.value->removeListener(storageArea.key.first, storageArea.key.second); >+ connectionAndStorageMapIDPairsToRemove.append(storageArea.key); >+ } >+ >+ for (auto& pair : connectionAndStorageMapIDPairsToRemove) >+ m_storageAreasByConnection.remove(pair); >+ }); >+} >+ >+void StorageManager::getSessionStorageOrigins(Function<void(HashSet<WebCore::SecurityOriginData>&&)>&& completionHandler) >+{ >+ m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable { >+ HashSet<SecurityOriginData> origins; >+ >+ for (const auto& sessionStorageNamespace : m_sessionStorageNamespaces.values()) { >+ for (auto& origin : sessionStorageNamespace->origins()) >+ origins.add(origin); >+ } >+ >+ RunLoop::main().dispatch([origins = WTFMove(origins), completionHandler = WTFMove(completionHandler)]() mutable { >+ completionHandler(WTFMove(origins)); >+ }); >+ }); >+} >+ >+void StorageManager::deleteSessionStorageOrigins(Function<void()>&& completionHandler) >+{ >+ m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable { >+ for (auto& sessionStorageNamespace : m_sessionStorageNamespaces.values()) >+ sessionStorageNamespace->clearAllStorageAreas(); >+ >+ RunLoop::main().dispatch(WTFMove(completionHandler)); >+ }); >+} >+ >+void StorageManager::deleteSessionStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>& origins, Function<void()>&& completionHandler) >+{ >+ Vector<WebCore::SecurityOriginData> copiedOrigins; >+ copiedOrigins.reserveInitialCapacity(origins.size()); >+ >+ for (auto& origin : origins) >+ copiedOrigins.uncheckedAppend(origin.isolatedCopy()); >+ >+ m_queue->dispatch([this, protectedThis = makeRef(*this), copiedOrigins = WTFMove(copiedOrigins), completionHandler = WTFMove(completionHandler)]() mutable { >+ for (auto& origin : copiedOrigins) { >+ for (auto& sessionStorageNamespace : m_sessionStorageNamespaces.values()) >+ sessionStorageNamespace->clearStorageAreasMatchingOrigin(origin); >+ } >+ >+ RunLoop::main().dispatch(WTFMove(completionHandler)); >+ }); >+} >+ >+void StorageManager::getLocalStorageOrigins(Function<void(HashSet<WebCore::SecurityOriginData>&&)>&& completionHandler) >+{ >+ m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable { >+ HashSet<SecurityOriginData> origins; >+ >+ for (auto& origin : m_localStorageDatabaseTracker->origins()) >+ origins.add(origin); >+ >+ for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values()) { >+ for (auto& origin : transientLocalStorageNamespace->origins()) >+ origins.add(origin); >+ } >+ >+ RunLoop::main().dispatch([origins = WTFMove(origins), completionHandler = WTFMove(completionHandler)]() mutable { >+ completionHandler(WTFMove(origins)); >+ }); >+ }); >+} >+ >+void StorageManager::getLocalStorageOriginDetails(Function<void(Vector<LocalStorageDatabaseTracker::OriginDetails>)>&& completionHandler) >+{ >+ m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable { >+ auto originDetails = m_localStorageDatabaseTracker->originDetails(); >+ >+ RunLoop::main().dispatch([originDetails = WTFMove(originDetails), completionHandler = WTFMove(completionHandler)]() mutable { >+ completionHandler(WTFMove(originDetails)); >+ }); >+ }); >+} >+ >+void StorageManager::deleteLocalStorageEntriesForOrigin(const SecurityOriginData& securityOrigin) >+{ >+ m_queue->dispatch([this, protectedThis = makeRef(*this), copiedOrigin = securityOrigin.isolatedCopy()]() mutable { >+ for (auto& localStorageNamespace : m_localStorageNamespaces.values()) >+ localStorageNamespace->clearStorageAreasMatchingOrigin(copiedOrigin); >+ >+ for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values()) >+ transientLocalStorageNamespace->clearStorageAreasMatchingOrigin(copiedOrigin); >+ >+ m_localStorageDatabaseTracker->deleteDatabaseWithOrigin(copiedOrigin); >+ }); >+} >+ >+void StorageManager::deleteLocalStorageOriginsModifiedSince(WallTime time, Function<void()>&& completionHandler) >+{ >+ m_queue->dispatch([this, protectedThis = makeRef(*this), time, completionHandler = WTFMove(completionHandler)]() mutable { >+ auto originsToDelete = m_localStorageDatabaseTracker->databasesModifiedSince(time); >+ >+ for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values()) >+ transientLocalStorageNamespace->clearAllStorageAreas(); >+ >+ for (const auto& origin : originsToDelete) { >+ for (auto& localStorageNamespace : m_localStorageNamespaces.values()) >+ localStorageNamespace->clearStorageAreasMatchingOrigin(origin); >+ >+ m_localStorageDatabaseTracker->deleteDatabaseWithOrigin(origin); >+ } >+ >+ RunLoop::main().dispatch(WTFMove(completionHandler)); >+ }); >+} >+ >+void StorageManager::deleteLocalStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>& origins, Function<void()>&& completionHandler) >+{ >+ Vector<SecurityOriginData> copiedOrigins; >+ copiedOrigins.reserveInitialCapacity(origins.size()); >+ >+ for (auto& origin : origins) >+ copiedOrigins.uncheckedAppend(origin.isolatedCopy()); >+ >+ m_queue->dispatch([this, protectedThis = makeRef(*this), copiedOrigins = WTFMove(copiedOrigins), completionHandler = WTFMove(completionHandler)]() mutable { >+ for (auto& origin : copiedOrigins) { >+ for (auto& localStorageNamespace : m_localStorageNamespaces.values()) >+ localStorageNamespace->clearStorageAreasMatchingOrigin(origin); >+ >+ for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values()) >+ transientLocalStorageNamespace->clearStorageAreasMatchingOrigin(origin); >+ >+ m_localStorageDatabaseTracker->deleteDatabaseWithOrigin(origin); >+ } >+ >+ RunLoop::main().dispatch(WTFMove(completionHandler)); >+ }); >+} >+ >+void StorageManager::createLocalStorageMap(IPC::Connection& connection, uint64_t storageMapID, uint64_t storageNamespaceID, SecurityOriginData&& securityOriginData) >+{ >+ ASSERT(!m_isEphemeral); >+ std::pair<IPC::Connection::UniqueID, uint64_t> connectionAndStorageMapIDPair(connection.uniqueID(), storageMapID); >+ >+ // FIXME: This should be a message check. >+ ASSERT((HashMap<std::pair<IPC::Connection::UniqueID, uint64_t>, RefPtr<StorageArea>>::isValidKey(connectionAndStorageMapIDPair))); >+ >+ auto result = m_storageAreasByConnection.add(connectionAndStorageMapIDPair, nullptr); >+ >+ // FIXME: These should be a message checks. >+ ASSERT(result.isNewEntry); >+ ASSERT((HashMap<uint64_t, RefPtr<LocalStorageNamespace>>::isValidKey(storageNamespaceID))); >+ >+ LocalStorageNamespace* localStorageNamespace = getOrCreateLocalStorageNamespace(storageNamespaceID); >+ >+ // FIXME: This should be a message check. >+ ASSERT(localStorageNamespace); >+ >+ auto storageArea = localStorageNamespace->getOrCreateStorageArea(WTFMove(securityOriginData)); >+ storageArea->addListener(connection.uniqueID(), storageMapID); >+ >+ result.iterator->value = WTFMove(storageArea); >+} >+ >+void StorageManager::createTransientLocalStorageMap(IPC::Connection& connection, uint64_t storageMapID, uint64_t storageNamespaceID, SecurityOriginData&& topLevelOriginData, SecurityOriginData&& origin) >+{ >+ // FIXME: This should be a message check. >+ ASSERT(m_storageAreasByConnection.isValidKey({ connection.uniqueID(), storageMapID })); >+ >+ // See if we already have session storage for this connection/origin combo. >+ // If so, update the map with the new ID, otherwise keep on trucking. >+ for (auto it = m_storageAreasByConnection.begin(), end = m_storageAreasByConnection.end(); it != end; ++it) { >+ if (it->key.first != connection.uniqueID()) >+ continue; >+ Ref<StorageArea> area = *it->value; >+ if (!area->isSessionStorage()) >+ continue; >+ if (!origin.securityOrigin()->isSameSchemeHostPort(area->securityOrigin().securityOrigin().get())) >+ continue; >+ area->addListener(connection.uniqueID(), storageMapID); >+ // If the storageMapID used as key in m_storageAreasByConnection is no longer one of the StorageArea's listeners, then this means >+ // that destroyStorageMap() was already called for that storageMapID but it decided not to remove it from m_storageAreasByConnection >+ // so that we could reuse it later on for the same connection/origin combo. In this case, it is safe to remove the previous >+ // storageMapID from m_storageAreasByConnection. >+ if (!area->hasListener(connection.uniqueID(), it->key.second)) >+ m_storageAreasByConnection.remove(it); >+ m_storageAreasByConnection.add({ connection.uniqueID(), storageMapID }, WTFMove(area)); >+ return; >+ } >+ >+ auto& slot = m_storageAreasByConnection.add({ connection.uniqueID(), storageMapID }, nullptr).iterator->value; >+ >+ // FIXME: This should be a message check. >+ ASSERT(!slot); >+ >+ TransientLocalStorageNamespace* transientLocalStorageNamespace = getOrCreateTransientLocalStorageNamespace(storageNamespaceID, WTFMove(topLevelOriginData)); >+ >+ auto storageArea = transientLocalStorageNamespace->getOrCreateStorageArea(WTFMove(origin)); >+ storageArea->addListener(connection.uniqueID(), storageMapID); >+ >+ slot = WTFMove(storageArea); >+} >+ >+void StorageManager::createSessionStorageMap(IPC::Connection& connection, uint64_t storageMapID, uint64_t storageNamespaceID, SecurityOriginData&& securityOriginData) >+{ >+ if (m_isEphemeral) { >+ m_ephemeralStorage.add(securityOriginData, WebCore::StorageMap::create(localStorageDatabaseQuotaInBytes)); >+ return; >+ } >+ // FIXME: This should be a message check. >+ ASSERT(m_sessionStorageNamespaces.isValidKey(storageNamespaceID)); >+ >+ SessionStorageNamespace* sessionStorageNamespace = m_sessionStorageNamespaces.get(storageNamespaceID); >+ if (!sessionStorageNamespace) { >+ // We're getting an incoming message from the web process that's for session storage for a web page >+ // that has already been closed, just ignore it. >+ return; >+ } >+ >+ // FIXME: This should be a message check. >+ ASSERT(m_storageAreasByConnection.isValidKey({ connection.uniqueID(), storageMapID })); >+ >+ auto& slot = m_storageAreasByConnection.add({ connection.uniqueID(), storageMapID }, nullptr).iterator->value; >+ >+ // FIXME: This should be a message check. >+ ASSERT(!slot); >+ >+ // FIXME: This should be a message check. >+ ASSERT(sessionStorageNamespace->allowedConnections().contains(connection.uniqueID())); >+ >+ auto storageArea = sessionStorageNamespace->getOrCreateStorageArea(WTFMove(securityOriginData)); >+ storageArea->addListener(connection.uniqueID(), storageMapID); >+ >+ slot = WTFMove(storageArea); >+} >+ >+void StorageManager::destroyStorageMap(IPC::Connection& connection, uint64_t storageMapID) >+{ >+ std::pair<IPC::Connection::UniqueID, uint64_t> connectionAndStorageMapIDPair(connection.uniqueID(), storageMapID); >+ >+ // FIXME: This should be a message check. >+ ASSERT(m_storageAreasByConnection.isValidKey(connectionAndStorageMapIDPair)); >+ >+ auto it = m_storageAreasByConnection.find(connectionAndStorageMapIDPair); >+ if (it == m_storageAreasByConnection.end()) { >+ // The connection has been removed because the last page was closed. >+ return; >+ } >+ >+ it->value->removeListener(connection.uniqueID(), storageMapID); >+ >+ // Don't remove session storage maps. The web process may reconnect and expect the data to still be around. >+ if (it->value->isSessionStorage()) >+ return; >+ >+ m_storageAreasByConnection.remove(connectionAndStorageMapIDPair); >+} >+ >+void StorageManager::getValues(IPC::Connection& connection, WebCore::SecurityOriginData&& securityOriginData, uint64_t storageMapID, uint64_t storageMapSeed, CompletionHandler<void(const HashMap<String, String>&)>&& completionHandler) >+{ >+ StorageArea* storageArea = findStorageArea(connection, storageMapID); >+ if (!storageArea) { >+ if (m_isEphemeral) { >+ if (auto storageMap = m_ephemeralStorage.get(securityOriginData)) >+ return completionHandler(storageMap->items()); >+ } >+ // This is a session storage area for a page that has already been closed. Ignore it. >+ return completionHandler({ }); >+ } >+ >+ completionHandler(storageArea->items()); >+ connection.send(Messages::StorageAreaMap::DidGetValues(storageMapSeed), storageMapID); >+} >+ >+void StorageManager::setItem(IPC::Connection& connection, WebCore::SecurityOriginData&& securityOriginData, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& value, const String& urlString) >+{ >+ StorageArea* storageArea = findStorageArea(connection, storageMapID); >+ if (!storageArea) { >+ if (m_isEphemeral) { >+ if (auto storageMap = m_ephemeralStorage.get(securityOriginData)) { >+ String oldValue; >+ bool quotaException; >+ storageMap->setItem(key, value, oldValue, quotaException); >+ } >+ } >+ // This is a session storage area for a page that has already been closed. Ignore it. >+ return; >+ } >+ >+ bool quotaError; >+ storageArea->setItem(connection.uniqueID(), sourceStorageAreaID, key, value, urlString, quotaError); >+ connection.send(Messages::StorageAreaMap::DidSetItem(storageMapSeed, key, quotaError), storageMapID); >+} >+ >+void StorageManager::removeItem(IPC::Connection& connection, WebCore::SecurityOriginData&& securityOriginData, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& urlString) >+{ >+ StorageArea* storageArea = findStorageArea(connection, storageMapID); >+ if (!storageArea) { >+ if (m_isEphemeral) { >+ if (auto storageMap = m_ephemeralStorage.get(securityOriginData)) { >+ String oldValue; >+ storageMap->removeItem(key, oldValue); >+ } >+ } >+ // This is a session storage area for a page that has already been closed. Ignore it. >+ return; >+ } >+ >+ storageArea->removeItem(connection.uniqueID(), sourceStorageAreaID, key, urlString); >+ connection.send(Messages::StorageAreaMap::DidRemoveItem(storageMapSeed, key), storageMapID); >+} >+ >+void StorageManager::clear(IPC::Connection& connection, WebCore::SecurityOriginData&& securityOriginData, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& urlString) >+{ >+ StorageArea* storageArea = findStorageArea(connection, storageMapID); >+ if (!storageArea) { >+ if (m_isEphemeral) >+ m_ephemeralStorage.remove(securityOriginData); >+ // This is a session storage area for a page that has already been closed. Ignore it. >+ return; >+ } >+ >+ storageArea->clear(connection.uniqueID(), sourceStorageAreaID, urlString); >+ connection.send(Messages::StorageAreaMap::DidClear(storageMapSeed), storageMapID); >+} >+ >+void StorageManager::waitUntilWritesFinished() >+{ >+ BinarySemaphore semaphore; >+ m_queue->dispatch([this, &semaphore] { >+ Vector<std::pair<IPC::Connection::UniqueID, uint64_t>> connectionAndStorageMapIDPairsToRemove; >+ for (auto& connectionStorageAreaPair : m_storageAreasByConnection) { >+ connectionStorageAreaPair.value->removeListener(connectionStorageAreaPair.key.first, connectionStorageAreaPair.key.second); >+ connectionAndStorageMapIDPairsToRemove.append(connectionStorageAreaPair.key); >+ } >+ >+ for (auto& connectionStorageAreaPair : connectionAndStorageMapIDPairsToRemove) >+ m_storageAreasByConnection.remove(connectionStorageAreaPair); >+ >+ semaphore.signal(); >+ }); >+ semaphore.wait(); >+} >+ >+StorageManager::StorageArea* StorageManager::findStorageArea(IPC::Connection& connection, uint64_t storageMapID) const >+{ >+ std::pair<IPC::Connection::UniqueID, uint64_t> connectionAndStorageMapIDPair(connection.uniqueID(), storageMapID); >+ >+ if (!m_storageAreasByConnection.isValidKey(connectionAndStorageMapIDPair)) >+ return nullptr; >+ >+ return m_storageAreasByConnection.get(connectionAndStorageMapIDPair); >+} >+ >+StorageManager::LocalStorageNamespace* StorageManager::getOrCreateLocalStorageNamespace(uint64_t storageNamespaceID) >+{ >+ if (!m_localStorageNamespaces.isValidKey(storageNamespaceID)) >+ return nullptr; >+ >+ auto& slot = m_localStorageNamespaces.add(storageNamespaceID, nullptr).iterator->value; >+ if (!slot) >+ slot = LocalStorageNamespace::create(this, storageNamespaceID); >+ >+ return slot.get(); >+} >+ >+StorageManager::TransientLocalStorageNamespace* StorageManager::getOrCreateTransientLocalStorageNamespace(uint64_t storageNamespaceID, WebCore::SecurityOriginData&& topLevelOrigin) >+{ >+ if (!m_transientLocalStorageNamespaces.isValidKey({ storageNamespaceID, topLevelOrigin })) >+ return nullptr; >+ >+ auto& slot = m_transientLocalStorageNamespaces.add({ storageNamespaceID, WTFMove(topLevelOrigin) }, nullptr).iterator->value; >+ if (!slot) >+ slot = TransientLocalStorageNamespace::create(); >+ >+ return slot.get(); >+} >+ >+} // namespace WebKit >diff --git a/Source/WebKit/NetworkProcess/WebStorage/StorageManager.h b/Source/WebKit/NetworkProcess/WebStorage/StorageManager.h >new file mode 100644 >index 0000000000000000000000000000000000000000..8785af48d10abdfd020e834696bf8cd8d152e816 >--- /dev/null >+++ b/Source/WebKit/NetworkProcess/WebStorage/StorageManager.h >@@ -0,0 +1,118 @@ >+/* >+ * 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. >+ */ >+ >+#pragma once >+ >+#include "Connection.h" >+#include "LocalStorageDatabaseTracker.h" >+#include <WebCore/SecurityOriginData.h> >+#include <WebCore/StorageMap.h> >+#include <wtf/Forward.h> >+#include <wtf/Function.h> >+#include <wtf/HashSet.h> >+#include <wtf/ThreadSafeRefCounted.h> >+#include <wtf/text/StringHash.h> >+ >+namespace WebCore { >+class SecurityOrigin; >+} >+ >+namespace WebKit { >+ >+class LocalStorageDatabaseTracker; >+class WebProcessProxy; >+ >+class StorageManager : public IPC::Connection::WorkQueueMessageReceiver { >+public: >+ static Ref<StorageManager> create(const String& localStorageDirectory); >+ ~StorageManager(); >+ >+ void createSessionStorageNamespace(uint64_t storageNamespaceID, unsigned quotaInBytes); >+ void destroySessionStorageNamespace(uint64_t storageNamespaceID); >+ void addAllowedSessionStorageNamespaceConnection(uint64_t storageNamespaceID, IPC::Connection&); >+ void removeAllowedSessionStorageNamespaceConnection(uint64_t storageNamespaceID, IPC::Connection&); >+ void cloneSessionStorageNamespace(uint64_t storageNamespaceID, uint64_t newStorageNamespaceID); >+ >+ void processWillOpenConnection(IPC::Connection&); >+ void processDidCloseConnection(IPC::Connection&); >+ void waitUntilWritesFinished(); >+ >+ void getSessionStorageOrigins(Function<void(HashSet<WebCore::SecurityOriginData>&&)>&& completionHandler); >+ void deleteSessionStorageOrigins(Function<void()>&& completionHandler); >+ void deleteSessionStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>&, Function<void()>&& completionHandler); >+ >+ void getLocalStorageOrigins(Function<void(HashSet<WebCore::SecurityOriginData>&&)>&& completionHandler); >+ void deleteLocalStorageEntriesForOrigin(const WebCore::SecurityOriginData&); >+ >+ void deleteLocalStorageOriginsModifiedSince(WallTime, Function<void()>&& completionHandler); >+ void deleteLocalStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>&, Function<void()>&& completionHandler); >+ >+ void getLocalStorageOriginDetails(Function<void(Vector<LocalStorageDatabaseTracker::OriginDetails>)>&& completionHandler); >+ >+private: >+ explicit StorageManager(const String& localStorageDirectory); >+ >+ // IPC::Connection::WorkQueueMessageReceiver. >+ void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override; >+ void didReceiveSyncMessage(IPC::Connection&, IPC::Decoder&, std::unique_ptr<IPC::Encoder>& replyEncoder) override; >+ >+ // Message handlers. >+ void createLocalStorageMap(IPC::Connection&, uint64_t storageMapID, uint64_t storageNamespaceID, WebCore::SecurityOriginData&&); >+ void createTransientLocalStorageMap(IPC::Connection&, uint64_t storageMapID, uint64_t storageNamespaceID, WebCore::SecurityOriginData&& topLevelOriginData, WebCore::SecurityOriginData&&); >+ void createSessionStorageMap(IPC::Connection&, uint64_t storageMapID, uint64_t storageNamespaceID, WebCore::SecurityOriginData&&); >+ void destroyStorageMap(IPC::Connection&, uint64_t storageMapID); >+ >+ void getValues(IPC::Connection&, WebCore::SecurityOriginData&&, uint64_t storageMapID, uint64_t storageMapSeed, CompletionHandler<void(const HashMap<String, String>&)>&&); >+ void setItem(IPC::Connection&, WebCore::SecurityOriginData&&, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& value, const String& urlString); >+ void removeItem(IPC::Connection&, WebCore::SecurityOriginData&&, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& urlString); >+ void clear(IPC::Connection&, WebCore::SecurityOriginData&&, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& urlString); >+ >+ class StorageArea; >+ StorageArea* findStorageArea(IPC::Connection&, uint64_t) const; >+ >+ class LocalStorageNamespace; >+ LocalStorageNamespace* getOrCreateLocalStorageNamespace(uint64_t storageNamespaceID); >+ >+ class TransientLocalStorageNamespace; >+ TransientLocalStorageNamespace* getOrCreateTransientLocalStorageNamespace(uint64_t storageNamespaceID, WebCore::SecurityOriginData&& topLevelOrigin); >+ >+ Ref<WorkQueue> m_queue; >+ >+ Ref<LocalStorageDatabaseTracker> m_localStorageDatabaseTracker; >+ HashMap<uint64_t, RefPtr<LocalStorageNamespace>> m_localStorageNamespaces; >+ >+ HashMap<std::pair<uint64_t, WebCore::SecurityOriginData>, RefPtr<TransientLocalStorageNamespace>> m_transientLocalStorageNamespaces; >+ >+ class SessionStorageNamespace; >+ HashMap<uint64_t, RefPtr<SessionStorageNamespace>> m_sessionStorageNamespaces; >+ >+ HashMap<std::pair<IPC::Connection::UniqueID, uint64_t>, RefPtr<StorageArea>> m_storageAreasByConnection; >+ >+ HashMap<WebCore::SecurityOriginData, Ref<WebCore::StorageMap>> m_ephemeralStorage; >+ bool m_isEphemeral { false }; >+ >+}; >+ >+} // namespace WebKit >diff --git a/Source/WebKit/NetworkProcess/WebStorage/StorageManager.messages.in b/Source/WebKit/NetworkProcess/WebStorage/StorageManager.messages.in >new file mode 100644 >index 0000000000000000000000000000000000000000..b3b6dbf279803514e535b1e0374db7dbe9969cba >--- /dev/null >+++ b/Source/WebKit/NetworkProcess/WebStorage/StorageManager.messages.in >@@ -0,0 +1,34 @@ >+# 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. >+ >+messages -> StorageManager { >+ CreateLocalStorageMap(uint64_t storageMapID, uint64_t storageNamespaceID, struct WebCore::SecurityOriginData securityOriginData) WantsConnection >+ CreateTransientLocalStorageMap(uint64_t storageMapID, uint64_t storageNamespaceID, struct WebCore::SecurityOriginData topLevelSecurityOriginData, struct WebCore::SecurityOriginData securityOriginData) WantsConnection >+ CreateSessionStorageMap(uint64_t storageMapID, uint64_t storageNamespaceID, struct WebCore::SecurityOriginData securityOriginData) WantsConnection >+ DestroyStorageMap(uint64_t storageMapID) WantsConnection >+ >+ GetValues(struct WebCore::SecurityOriginData securityOriginData, uint64_t storageMapID, uint64_t storageMapSeed) -> (HashMap<String, String> values) Synchronous WantsConnection >+ >+ SetItem(struct WebCore::SecurityOriginData securityOriginData, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, String key, String value, String urlString) WantsConnection >+ RemoveItem(struct WebCore::SecurityOriginData securityOriginData, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, String key, String urlString) WantsConnection >+ Clear(struct WebCore::SecurityOriginData securityOriginData, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, String urlString) WantsConnection >+} >diff --git a/Source/WebKit/NetworkProcess/WebStorage/ios/LocalStorageDatabaseTrackerIOS.mm b/Source/WebKit/NetworkProcess/WebStorage/ios/LocalStorageDatabaseTrackerIOS.mm >new file mode 100644 >index 0000000000000000000000000000000000000000..9b01e896360f42c9f5097ff280b7ff615e65414f >--- /dev/null >+++ b/Source/WebKit/NetworkProcess/WebStorage/ios/LocalStorageDatabaseTrackerIOS.mm >@@ -0,0 +1,48 @@ >+/* >+ * 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 >+ * 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 "LocalStorageDatabaseTracker.h" >+ >+#if PLATFORM(IOS_FAMILY) >+ >+#include "VersionChecks.h" >+ >+namespace WebKit { >+ >+void LocalStorageDatabaseTracker::platformMaybeExcludeFromBackup() const >+{ >+ if (m_hasExcludedFromBackup) >+ return; >+ >+ m_hasExcludedFromBackup = true; >+ >+ if (linkedOnOrAfter(SDKVersion::FirstToExcludeLocalStorageFromBackup)) >+ [[NSURL fileURLWithPath:(NSString *)m_localStorageDirectory isDirectory:YES] setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:nil]; >+} >+ >+} // namespace WebKit >+ >+#endif >diff --git a/Source/WebKit/Shared/WebPageCreationParameters.cpp b/Source/WebKit/Shared/WebPageCreationParameters.cpp >index 89f535d4e299244dca6bbee7c102d6ea39fa42a6..e9da60aeebeff1da691e1e453373577a3a940a25 100644 >--- a/Source/WebKit/Shared/WebPageCreationParameters.cpp >+++ b/Source/WebKit/Shared/WebPageCreationParameters.cpp >@@ -131,6 +131,7 @@ void WebPageCreationParameters::encode(IPC::Encoder& encoder) const > encoder << contentRuleLists; > #endif > encoder << backgroundColor; >+ encoder << oldPageID; > } > > Optional<WebPageCreationParameters> WebPageCreationParameters::decode(IPC::Decoder& decoder) >@@ -391,6 +392,12 @@ Optional<WebPageCreationParameters> WebPageCreationParameters::decode(IPC::Decod > return WTF::nullopt; > parameters.backgroundColor = WTFMove(*backgroundColor); > >+ Optional<Optional<uint64_t>> oldPageID; >+ decoder >> oldPageID; >+ if (!oldPageID) >+ return WTF::nullopt; >+ parameters.oldPageID = WTFMove(*oldPageID); >+ > return parameters; > } > >diff --git a/Source/WebKit/Shared/WebPageCreationParameters.h b/Source/WebKit/Shared/WebPageCreationParameters.h >index 43af461a730c79c563d38f1e6962033995f04e26..c2be84146b34ea756197075ac8b2cbc38bec42e0 100644 >--- a/Source/WebKit/Shared/WebPageCreationParameters.h >+++ b/Source/WebKit/Shared/WebPageCreationParameters.h >@@ -201,6 +201,8 @@ struct WebPageCreationParameters { > #endif > > Optional<WebCore::Color> backgroundColor; >+ >+ Optional<uint64_t> oldPageID; > }; > > } // namespace WebKit >diff --git a/Source/WebKit/Shared/WebsiteData/WebsiteData.cpp b/Source/WebKit/Shared/WebsiteData/WebsiteData.cpp >index 5191cce13c4fccb099bac90b161b1459fdae6f0f..90c7d754580d86a5f417c1c55a9fa874ba9e277a 100644 >--- a/Source/WebKit/Shared/WebsiteData/WebsiteData.cpp >+++ b/Source/WebKit/Shared/WebsiteData/WebsiteData.cpp >@@ -99,9 +99,9 @@ WebsiteDataProcessType WebsiteData::ownerProcess(WebsiteDataType dataType) > case WebsiteDataType::OfflineWebApplicationCache: > return WebsiteDataProcessType::UI; > case WebsiteDataType::SessionStorage: >- return WebsiteDataProcessType::UI; >+ return WebsiteDataProcessType::Network; > case WebsiteDataType::LocalStorage: >- return WebsiteDataProcessType::UI; >+ return WebsiteDataProcessType::Network; > case WebsiteDataType::WebSQLDatabases: > return WebsiteDataProcessType::UI; > case WebsiteDataType::IndexedDBDatabases: >diff --git a/Source/WebKit/Shared/WebsiteDataStoreParameters.cpp b/Source/WebKit/Shared/WebsiteDataStoreParameters.cpp >index d91a34f6a92725c141773f08ab429e7e8e5863c3..860598e36c49543ba0c9e33da86aa7b54cda41ae 100644 >--- a/Source/WebKit/Shared/WebsiteDataStoreParameters.cpp >+++ b/Source/WebKit/Shared/WebsiteDataStoreParameters.cpp >@@ -42,6 +42,8 @@ void WebsiteDataStoreParameters::encode(IPC::Encoder& encoder) const > encoder << cookieStoragePathExtensionHandle; > encoder << pendingCookies; > >+ encoder << localStorageDirectory << localStorageDirectoryExtensionHandle; >+ > #if ENABLE(INDEXED_DATABASE) > encoder << indexedDatabaseDirectory << indexedDatabaseDirectoryExtensionHandle; > #if PLATFORM(IOS_FAMILY) >@@ -85,6 +87,18 @@ Optional<WebsiteDataStoreParameters> WebsiteDataStoreParameters::decode(IPC::Dec > return WTF::nullopt; > parameters.pendingCookies = WTFMove(*pendingCookies); > >+ Optional<String> localStorageDirectory; >+ decoder >> localStorageDirectory; >+ if (!localStorageDirectory) >+ return WTF::nullopt; >+ parameters.localStorageDirectory = WTFMove(*localStorageDirectory); >+ >+ Optional<SandboxExtension::Handle> localStorageDirectoryExtensionHandle; >+ decoder >> localStorageDirectoryExtensionHandle; >+ if (!localStorageDirectoryExtensionHandle) >+ return WTF::nullopt; >+ parameters.localStorageDirectoryExtensionHandle = WTFMove(*localStorageDirectoryExtensionHandle); >+ > #if ENABLE(INDEXED_DATABASE) > Optional<String> indexedDatabaseDirectory; > decoder >> indexedDatabaseDirectory; >@@ -139,7 +153,7 @@ Optional<WebsiteDataStoreParameters> WebsiteDataStoreParameters::decode(IPC::Dec > WebsiteDataStoreParameters WebsiteDataStoreParameters::privateSessionParameters(PAL::SessionID sessionID) > { > ASSERT(sessionID.isEphemeral()); >- return { { }, { }, { }, NetworkSessionCreationParameters::privateSessionParameters(sessionID) >+ return { { }, { }, { }, NetworkSessionCreationParameters::privateSessionParameters(sessionID), { }, { } > #if ENABLE(INDEXED_DATABASE) > , { }, { } > #if PLATFORM(IOS_FAMILY) >diff --git a/Source/WebKit/Shared/WebsiteDataStoreParameters.h b/Source/WebKit/Shared/WebsiteDataStoreParameters.h >index 992fee97d09974c9f347f6c70daa1cebf3e2f24f..921e000d9f40b2c54de6063093c80857ea7f4a56 100644 >--- a/Source/WebKit/Shared/WebsiteDataStoreParameters.h >+++ b/Source/WebKit/Shared/WebsiteDataStoreParameters.h >@@ -57,6 +57,9 @@ struct WebsiteDataStoreParameters { > Vector<WebCore::Cookie> pendingCookies; > NetworkSessionCreationParameters networkSessionParameters; > >+ String localStorageDirectory; >+ SandboxExtension::Handle localStorageDirectoryExtensionHandle; >+ > #if ENABLE(INDEXED_DATABASE) > String indexedDatabaseDirectory; > SandboxExtension::Handle indexedDatabaseDirectoryExtensionHandle; >diff --git a/Source/WebKit/Sources.txt b/Source/WebKit/Sources.txt >index 48f58e3c243b87ad36ff2d84e0d9660cdd4289d9..0393e4eead5c44b0425d0bbb2d1793babf5a30eb 100644 >--- a/Source/WebKit/Sources.txt >+++ b/Source/WebKit/Sources.txt >@@ -65,6 +65,9 @@ NetworkProcess/ServiceWorker/WebSWOriginStore.cpp @no-unify > NetworkProcess/ServiceWorker/WebSWServerConnection.cpp @no-unify > NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp @no-unify > >+NetworkProcess/WebStorage/LocalStorageDatabase.cpp >+NetworkProcess/WebStorage/LocalStorageDatabaseTracker.cpp >+ > NetworkProcess/cache/CacheStorageEngine.cpp > NetworkProcess/cache/CacheStorageEngineCache.cpp > NetworkProcess/cache/CacheStorageEngineCaches.cpp >@@ -410,9 +413,6 @@ UIProcess/WebAuthentication/AuthenticatorTransportService.cpp > UIProcess/WebAuthentication/Authenticator.cpp > UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp > >-UIProcess/WebStorage/LocalStorageDatabase.cpp >-UIProcess/WebStorage/LocalStorageDatabaseTracker.cpp >- > UIProcess/WebsiteData/WebDeviceOrientationAndMotionAccessController.cpp > UIProcess/WebsiteData/WebsiteDataRecord.cpp > UIProcess/WebsiteData/WebsiteDataStore.cpp >diff --git a/Source/WebKit/SourcesCocoa.txt b/Source/WebKit/SourcesCocoa.txt >index 6d2f3753980c814feb786491c53a40e8c6ddaf3a..54eb41f1e0262c1fa57b7d6d26f6910538195fdd 100644 >--- a/Source/WebKit/SourcesCocoa.txt >+++ b/Source/WebKit/SourcesCocoa.txt >@@ -42,6 +42,9 @@ NetworkProcess/Downloads/cocoa/DownloadCocoa.mm > NetworkProcess/EntryPoint/Cocoa/Daemon/DaemonEntryPoint.mm > NetworkProcess/EntryPoint/Cocoa/XPCService/NetworkServiceEntryPoint.mm > >+NetworkProcess/WebStorage/StorageManager.cpp >+NetworkProcess/WebStorage/ios/LocalStorageDatabaseTrackerIOS.mm >+ > NetworkProcess/ios/NetworkConnectionToWebProcessIOS.mm > NetworkProcess/ios/NetworkProcessIOS.mm > >@@ -488,10 +491,6 @@ UIProcess/WebAuthentication/Mock/MockLocalService.mm > > UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm > >-UIProcess/WebStorage/StorageManager.cpp >- >-UIProcess/WebStorage/ios/LocalStorageDatabaseTrackerIOS.mm >- > WebProcess/API/Cocoa/WKWebProcess.cpp > > WebProcess/ApplePay/WebPaymentCoordinator.cpp >diff --git a/Source/WebKit/SourcesGTK.txt b/Source/WebKit/SourcesGTK.txt >index 6b688e6913e030b186a18a12bf7e2019cf6ee711..bf386ce871e4b11e4c3ef69360804c180ecf434c 100644 >--- a/Source/WebKit/SourcesGTK.txt >+++ b/Source/WebKit/SourcesGTK.txt >@@ -34,6 +34,8 @@ NetworkProcess/CustomProtocols/LegacyCustomProtocolManager.cpp > > NetworkProcess/CustomProtocols/soup/LegacyCustomProtocolManagerSoup.cpp > >+NetworkProcess/WebStorage/StorageManager.cpp >+ > NetworkProcess/cache/NetworkCacheDataSoup.cpp > NetworkProcess/cache/NetworkCacheIOChannelSoup.cpp > >@@ -224,8 +226,6 @@ UIProcess/Plugins/gtk/PluginInfoCache.cpp @no-unify > UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp @no-unify > UIProcess/Plugins/unix/PluginProcessProxyUnix.cpp @no-unify > >-UIProcess/WebStorage/StorageManager.cpp >- > UIProcess/WebsiteData/soup/WebsiteDataStoreSoup.cpp > UIProcess/WebsiteData/unix/WebsiteDataStoreUnix.cpp > >diff --git a/Source/WebKit/SourcesWPE.txt b/Source/WebKit/SourcesWPE.txt >index 0bf54164bf842b46ca16f99d684a3d48332105cd..b8920847e7e800e0994398570787a1a6cc667548 100644 >--- a/Source/WebKit/SourcesWPE.txt >+++ b/Source/WebKit/SourcesWPE.txt >@@ -30,6 +30,8 @@ NetworkProcess/CustomProtocols/LegacyCustomProtocolManager.cpp > > NetworkProcess/CustomProtocols/soup/LegacyCustomProtocolManagerSoup.cpp > >+NetworkProcess/WebStorage/StorageManager.cpp >+ > NetworkProcess/cache/NetworkCacheDataSoup.cpp > NetworkProcess/cache/NetworkCacheIOChannelSoup.cpp > >@@ -197,8 +199,6 @@ UIProcess/Network/CustomProtocols/LegacyCustomProtocolManagerProxy.cpp > UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp > UIProcess/Plugins/unix/PluginProcessProxyUnix.cpp > >-UIProcess/WebStorage/StorageManager.cpp >- > UIProcess/WebsiteData/soup/WebsiteDataStoreSoup.cpp > UIProcess/WebsiteData/unix/WebsiteDataStoreUnix.cpp > >diff --git a/Source/WebKit/UIProcess/API/C/WKKeyValueStorageManager.cpp b/Source/WebKit/UIProcess/API/C/WKKeyValueStorageManager.cpp >index efaebf7e66c3b22d3450ac1b9b211949ad0fd340..65ef7d6676833a77aaafab5d103dea3682284e53 100644 >--- a/Source/WebKit/UIProcess/API/C/WKKeyValueStorageManager.cpp >+++ b/Source/WebKit/UIProcess/API/C/WKKeyValueStorageManager.cpp >@@ -31,6 +31,7 @@ > #include "APIWebsiteDataStore.h" > #include "StorageManager.h" > #include "WKAPICast.h" >+#include "WebsiteDataRecord.h" > #include "WebsiteDataStore.h" > #include <wtf/RunLoop.h> > >@@ -62,51 +63,36 @@ WKStringRef WKKeyValueStorageManagerGetModificationTimeKey() > void WKKeyValueStorageManagerGetKeyValueStorageOrigins(WKKeyValueStorageManagerRef keyValueStorageManager, void* context, WKKeyValueStorageManagerGetKeyValueStorageOriginsFunction callback) > > { >- StorageManager* storageManager = toImpl(reinterpret_cast<WKWebsiteDataStoreRef>(keyValueStorageManager))->websiteDataStore().storageManager(); >- if (!storageManager) { >- RunLoop::main().dispatch([context, callback] { >- callback(toAPI(API::Array::create().ptr()), nullptr, context); >- }); >- return; >- } >- >- storageManager->getLocalStorageOrigins([context, callback](auto&& securityOrigins) { >- Vector<RefPtr<API::Object>> webSecurityOrigins; >- webSecurityOrigins.reserveInitialCapacity(securityOrigins.size()); >- for (auto& origin : securityOrigins) >- webSecurityOrigins.uncheckedAppend(API::SecurityOrigin::create(origin.securityOrigin())); >- >- callback(toAPI(API::Array::create(WTFMove(webSecurityOrigins)).ptr()), nullptr, context); >+ auto& websiteDataStore = WebKit::toImpl(reinterpret_cast<WKWebsiteDataStoreRef>(keyValueStorageManager))->websiteDataStore(); >+ websiteDataStore.fetchData({ WebKit::WebsiteDataType::LocalStorage, WebKit::WebsiteDataType::SessionStorage }, { }, [context, callback](auto dataRecords) { >+ Vector<RefPtr<API::Object>> securityOrigins; >+ for (const auto& dataRecord : dataRecords) { >+ for (const auto& origin : dataRecord.origins) >+ securityOrigins.append(API::SecurityOrigin::create(origin.securityOrigin())); >+ } >+ >+ callback(WebKit::toAPI(API::Array::create(WTFMove(securityOrigins)).ptr()), nullptr, context); > }); > } > > void WKKeyValueStorageManagerGetStorageDetailsByOrigin(WKKeyValueStorageManagerRef keyValueStorageManager, void* context, WKKeyValueStorageManagerGetStorageDetailsByOriginFunction callback) > { >- StorageManager* storageManager = toImpl(reinterpret_cast<WKWebsiteDataStoreRef>(keyValueStorageManager))->websiteDataStore().storageManager(); >- if (!storageManager) { >- RunLoop::main().dispatch([context, callback] { >- callback(toAPI(API::Array::create().ptr()), nullptr, context); >- }); >- return; >- } >- >- storageManager->getLocalStorageOriginDetails([context, callback](auto storageDetails) { >- HashMap<String, RefPtr<API::Object>> detailsMap; >+ auto& websiteDataStore = WebKit::toImpl(reinterpret_cast<WKWebsiteDataStoreRef>(keyValueStorageManager))->websiteDataStore(); >+ websiteDataStore.getLocalStorageDetails([context, callback](auto details) { > Vector<RefPtr<API::Object>> result; >- result.reserveInitialCapacity(storageDetails.size()); >- >- for (const auto& originDetails : storageDetails) { >- HashMap<String, RefPtr<API::Object>> detailsMap; >+ result.reserveInitialCapacity(details.size()); > >- RefPtr<API::Object> origin = API::SecurityOrigin::create(WebCore::SecurityOriginData::fromDatabaseIdentifier(originDetails.originIdentifier)->securityOrigin()); >+ for (const auto& detail : details) { >+ HashMap<String, RefPtr<API::Object>> detailMap; >+ RefPtr<API::Object> origin = API::SecurityOrigin::create(WebCore::SecurityOriginData::fromDatabaseIdentifier(detail.originIdentifier)->securityOrigin()); > >- detailsMap.set(toImpl(WKKeyValueStorageManagerGetOriginKey())->string(), origin); >- if (originDetails.creationTime) >- detailsMap.set(toImpl(WKKeyValueStorageManagerGetCreationTimeKey())->string(), API::Double::create(originDetails.creationTime->secondsSinceEpoch().value())); >- if (originDetails.modificationTime) >- detailsMap.set(toImpl(WKKeyValueStorageManagerGetModificationTimeKey())->string(), API::Double::create(originDetails.modificationTime->secondsSinceEpoch().value())); >+ detailMap.set(toImpl(WKKeyValueStorageManagerGetOriginKey())->string(), origin); >+ if (detail.creationTime) >+ detailMap.set(toImpl(WKKeyValueStorageManagerGetCreationTimeKey())->string(), API::Double::create(detail.creationTime->secondsSinceEpoch().value())); >+ if (detail.modificationTime) >+ detailMap.set(toImpl(WKKeyValueStorageManagerGetModificationTimeKey())->string(), API::Double::create(detail.modificationTime->secondsSinceEpoch().value())); > >- result.uncheckedAppend(API::Dictionary::create(WTFMove(detailsMap))); >+ result.uncheckedAppend(API::Dictionary::create(WTFMove(detailMap))); > } > > callback(toAPI(API::Array::create(WTFMove(result)).ptr()), nullptr, context); >@@ -115,18 +101,15 @@ void WKKeyValueStorageManagerGetStorageDetailsByOrigin(WKKeyValueStorageManagerR > > void WKKeyValueStorageManagerDeleteEntriesForOrigin(WKKeyValueStorageManagerRef keyValueStorageManager, WKSecurityOriginRef origin) > { >- StorageManager* storageManager = toImpl(reinterpret_cast<WKWebsiteDataStoreRef>(keyValueStorageManager))->websiteDataStore().storageManager(); >- if (!storageManager) >- return; >- >- storageManager->deleteLocalStorageEntriesForOrigin(toImpl(origin)->securityOrigin().data()); >+ auto& websiteDataStore = WebKit::toImpl(reinterpret_cast<WKWebsiteDataStoreRef>(keyValueStorageManager))->websiteDataStore(); >+ WebKit::WebsiteDataRecord dataRecord; >+ dataRecord.add(WebKit::WebsiteDataType::LocalStorage, WebKit::toImpl(origin)->securityOrigin().data()); >+ dataRecord.add(WebKit::WebsiteDataType::SessionStorage, WebKit::toImpl(origin)->securityOrigin().data()); >+ websiteDataStore.removeData({ WebKit::WebsiteDataType::LocalStorage, WebKit::WebsiteDataType::SessionStorage }, { dataRecord }, [] { }); > } > > void WKKeyValueStorageManagerDeleteAllEntries(WKKeyValueStorageManagerRef keyValueStorageManager) > { >- StorageManager* storageManager = toImpl(reinterpret_cast<WKWebsiteDataStoreRef>(keyValueStorageManager))->websiteDataStore().storageManager(); >- if (!storageManager) >- return; >- >- storageManager->deleteLocalStorageOriginsModifiedSince(-WallTime::infinity(), [] { }); >+ auto& websiteDataStore = WebKit::toImpl(reinterpret_cast<WKWebsiteDataStoreRef>(keyValueStorageManager))->websiteDataStore(); >+ websiteDataStore.removeData({ WebKit::WebsiteDataType::LocalStorage, WebKit::WebsiteDataType::SessionStorage }, -WallTime::infinity(), [] { }); > } >diff --git a/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp b/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp >index af859aec0362e91f930b286b8f42fc20fa883043..09f3d73e36812050f88137f6e5d0659b0ffee488 100644 >--- a/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp >+++ b/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp >@@ -566,6 +566,16 @@ void NetworkProcessProxy::clearUserInteraction(PAL::SessionID sessionID, const R > sendWithAsyncReply(Messages::NetworkProcess::ClearUserInteraction(sessionID, resourceDomain), WTFMove(completionHandler)); > } > >+void NetworkProcessProxy::hasLocalStorage(PAL::SessionID sessionID, const RegistrableDomain& resourceDomain, CompletionHandler<void(bool)>&& completionHandler) >+{ >+ if (!canSendMessage()) { >+ completionHandler(false); >+ return; >+ } >+ >+ sendWithAsyncReply(Messages::NetworkProcess::HasLocalStorage(sessionID, resourceDomain), WTFMove(completionHandler)); >+} >+ > void NetworkProcessProxy::setAgeCapForClientSideCookies(PAL::SessionID sessionID, Optional<Seconds> seconds, CompletionHandler<void()>&& completionHandler) > { > if (!canSendMessage()) { >@@ -1178,6 +1188,16 @@ void NetworkProcessProxy::createSymLinkForFileUpgrade(const String& indexedDatab > } > #endif > >+void NetworkProcessProxy::getLocalStorageDetails(PAL::SessionID sessionID, CompletionHandler<void(Vector<LocalStorageDatabaseTracker::OriginDetails>)>&& completionHandler) >+{ >+ if (!canSendMessage()) { >+ completionHandler({ }); >+ return; >+ } >+ >+ sendWithAsyncReply(Messages::NetworkProcess::GetLocalStorageOriginDetails(sessionID), WTFMove(completionHandler)); >+} >+ > } // namespace WebKit > > #undef MESSAGE_CHECK >diff --git a/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h b/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h >index ac3dd8325955a8b6fa1480808b30fe3bfc613cd7..7d9cb465e3eac2b3fffaf7d974434e21df1ed202 100644 >--- a/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h >+++ b/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h >@@ -96,12 +96,15 @@ public: > void deleteWebsiteData(PAL::SessionID, OptionSet<WebsiteDataType>, WallTime modifiedSince, CompletionHandler<void()>&& completionHandler); > void deleteWebsiteDataForOrigins(PAL::SessionID, OptionSet<WebKit::WebsiteDataType>, const Vector<WebCore::SecurityOriginData>& origins, const Vector<String>& cookieHostNames, const Vector<String>& HSTSCacheHostNames, CompletionHandler<void()>&&); > >+ void getLocalStorageDetails(PAL::SessionID, CompletionHandler<void(Vector<LocalStorageDatabaseTracker::OriginDetails>)>&&); >+ > #if ENABLE(RESOURCE_LOAD_STATISTICS) > void clearPrevalentResource(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void()>&&); > void clearUserInteraction(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void()>&&); > void dumpResourceLoadStatistics(PAL::SessionID, CompletionHandler<void(String)>&&); > void updatePrevalentDomainsToBlockCookiesFor(PAL::SessionID, const Vector<RegistrableDomain>&, CompletionHandler<void()>&&); > void hasHadUserInteraction(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void(bool)>&&); >+ void hasLocalStorage(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void(bool)>&&); > void isGrandfathered(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void(bool)>&&); > void isPrevalentResource(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void(bool)>&&); > void isRegisteredAsRedirectingTo(PAL::SessionID, const RedirectedFromDomain&, const RedirectedToDomain&, CompletionHandler<void(bool)>&&); >diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp >index 1b6b5168609d675d74a8ee1ae991ba5428fa24d1..32920fe870d898e46782917d6a33a3f841de5356 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.cpp >+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp >@@ -5036,7 +5036,6 @@ void WebPageProxy::createNewPage(const FrameInfoData& originatingFrameInfoData, > > reply(newPage->pageID(), newPage->creationParameters(m_process, *newPage->drawingArea())); > >- WebsiteDataStore::cloneSessionData(*this, *newPage); > newPage->m_shouldSuppressAppLinksInNextNavigationPolicyDecision = hostsAreEqual(URL({ }, mainFrameURL), request.url()); > > #if HAVE(LOAD_OPTIMIZER) >diff --git a/Source/WebKit/UIProcess/WebProcessPool.cpp b/Source/WebKit/UIProcess/WebProcessPool.cpp >index 9376da5dab5bd033c2fdee8b20db794bda2bc3f2..f881c0f51b1a4492c0bca026be6d99f1dd4fb6e3 100644 >--- a/Source/WebKit/UIProcess/WebProcessPool.cpp >+++ b/Source/WebKit/UIProcess/WebProcessPool.cpp >@@ -574,6 +574,12 @@ NetworkProcessProxy& WebProcessPool::ensureNetworkProcess(WebsiteDataStore* with > parameters.shouldDisableServiceWorkerProcessTerminationDelay = m_shouldDisableServiceWorkerProcessTerminationDelay; > #endif > >+ if (m_websiteDataStore) >+ parameters.defaultDataStoreParameters.localStorageDirectory = m_websiteDataStore->websiteDataStore().resolvedLocalStorageDirectory(); >+ if (!parameters.defaultDataStoreParameters.localStorageDirectory) >+ parameters.defaultDataStoreParameters.localStorageDirectory = API::WebsiteDataStore::defaultLocalStorageDirectory(); >+ SandboxExtension::createHandleForReadWriteDirectory(parameters.defaultDataStoreParameters.localStorageDirectory, parameters.defaultDataStoreParameters.localStorageDirectoryExtensionHandle); >+ > if (m_websiteDataStore) > parameters.defaultDataStoreParameters.networkSessionParameters.resourceLoadStatisticsDirectory = m_websiteDataStore->websiteDataStore().resolvedResourceLoadStatisticsDirectory(); > if (parameters.defaultDataStoreParameters.networkSessionParameters.resourceLoadStatisticsDirectory.isEmpty()) >diff --git a/Source/WebKit/UIProcess/WebStorage/LocalStorageDatabase.cpp b/Source/WebKit/UIProcess/WebStorage/LocalStorageDatabase.cpp >deleted file mode 100644 >index 46fb6c77294f3c631d4fffdfc24a148f708a44ce..0000000000000000000000000000000000000000 >--- a/Source/WebKit/UIProcess/WebStorage/LocalStorageDatabase.cpp >+++ /dev/null >@@ -1,366 +0,0 @@ >-/* >- * Copyright (C) 2008, 2009, 2010, 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 "LocalStorageDatabase.h" >- >-#include "LocalStorageDatabaseTracker.h" >-#include <WebCore/SQLiteStatement.h> >-#include <WebCore/SQLiteTransaction.h> >-#include <WebCore/SecurityOrigin.h> >-#include <WebCore/StorageMap.h> >-#include <WebCore/SuddenTermination.h> >-#include <wtf/FileSystem.h> >-#include <wtf/RefPtr.h> >-#include <wtf/WorkQueue.h> >-#include <wtf/text/StringHash.h> >-#include <wtf/text/WTFString.h> >- >-static const auto databaseUpdateInterval = 1_s; >- >-static const int maximumItemsToUpdate = 100; >- >-namespace WebKit { >-using namespace WebCore; >- >-Ref<LocalStorageDatabase> LocalStorageDatabase::create(Ref<WorkQueue>&& queue, Ref<LocalStorageDatabaseTracker>&& tracker, const SecurityOriginData& securityOrigin) >-{ >- return adoptRef(*new LocalStorageDatabase(WTFMove(queue), WTFMove(tracker), securityOrigin)); >-} >- >-LocalStorageDatabase::LocalStorageDatabase(Ref<WorkQueue>&& queue, Ref<LocalStorageDatabaseTracker>&& tracker, const SecurityOriginData& securityOrigin) >- : m_queue(WTFMove(queue)) >- , m_tracker(WTFMove(tracker)) >- , m_securityOrigin(securityOrigin) >- , m_databasePath(m_tracker->databasePath(m_securityOrigin)) >- , m_failedToOpenDatabase(false) >- , m_didImportItems(false) >- , m_isClosed(false) >- , m_didScheduleDatabaseUpdate(false) >- , m_shouldClearItems(false) >-{ >-} >- >-LocalStorageDatabase::~LocalStorageDatabase() >-{ >- ASSERT(m_isClosed); >-} >- >-void LocalStorageDatabase::openDatabase(DatabaseOpeningStrategy openingStrategy) >-{ >- ASSERT(!m_database.isOpen()); >- ASSERT(!m_failedToOpenDatabase); >- >- if (!tryToOpenDatabase(openingStrategy)) { >- m_failedToOpenDatabase = true; >- return; >- } >- >- if (m_database.isOpen()) >- m_tracker->didOpenDatabaseWithOrigin(m_securityOrigin); >-} >- >-bool LocalStorageDatabase::tryToOpenDatabase(DatabaseOpeningStrategy openingStrategy) >-{ >- if (!FileSystem::fileExists(m_databasePath) && openingStrategy == SkipIfNonExistent) >- return true; >- >- if (m_databasePath.isEmpty()) { >- LOG_ERROR("Filename for local storage database is empty - cannot open for persistent storage"); >- return false; >- } >- >- if (!m_database.open(m_databasePath)) { >- LOG_ERROR("Failed to open database file %s for local storage", m_databasePath.utf8().data()); >- return false; >- } >- >- // Since a WorkQueue isn't bound to a specific thread, we have to disable threading checks >- // even though we never access the database from different threads simultaneously. >- m_database.disableThreadingChecks(); >- >- if (!migrateItemTableIfNeeded()) { >- // We failed to migrate the item table. In order to avoid trying to migrate the table over and over, >- // just delete it and start from scratch. >- if (!m_database.executeCommand("DROP TABLE ItemTable")) >- LOG_ERROR("Failed to delete table ItemTable for local storage"); >- } >- >- 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"); >- return false; >- } >- >- return true; >-} >- >-bool LocalStorageDatabase::migrateItemTableIfNeeded() >-{ >- if (!m_database.tableExists("ItemTable")) >- return true; >- >- SQLiteStatement query(m_database, "SELECT value FROM ItemTable LIMIT 1"); >- >- // This query isn't ever executed, it's just used to check the column type. >- if (query.isColumnDeclaredAsBlob(0)) >- return true; >- >- // Create a new table with the right type, copy all the data over to it and then replace the new table with the old table. >- 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])) >- continue; >- >- LOG_ERROR("Failed to migrate table ItemTable for local storage when executing: %s", commands[i]); >- transaction.rollback(); >- >- return false; >- } >- >- transaction.commit(); >- return true; >-} >- >-void LocalStorageDatabase::importItems(StorageMap& storageMap) >-{ >- if (m_didImportItems) >- return; >- >- // 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 >- >- // We set this to true even if we don't end up importing any items due to failure because >- // there's really no good way to recover other than not importing anything. >- m_didImportItems = true; >- >- openDatabase(SkipIfNonExistent); >- if (!m_database.isOpen()) >- return; >- >- SQLiteStatement query(m_database, "SELECT key, value FROM ItemTable"); >- if (query.prepare() != SQLITE_OK) { >- LOG_ERROR("Unable to select items from ItemTable for local storage"); >- return; >- } >- >- HashMap<String, String> items; >- >- int result = query.step(); >- while (result == SQLITE_ROW) { >- String key = query.getColumnText(0); >- String value = query.getColumnBlobAsString(1); >- if (!key.isNull() && !value.isNull()) >- items.set(key, value); >- result = query.step(); >- } >- >- if (result != SQLITE_DONE) { >- LOG_ERROR("Error reading items from ItemTable for local storage"); >- return; >- } >- >- storageMap.importItems(items); >-} >- >-void LocalStorageDatabase::setItem(const String& key, const String& value) >-{ >- itemDidChange(key, value); >-} >- >-void LocalStorageDatabase::removeItem(const String& key) >-{ >- itemDidChange(key, String()); >-} >- >-void LocalStorageDatabase::clear() >-{ >- m_changedItems.clear(); >- m_shouldClearItems = true; >- >- scheduleDatabaseUpdate(); >-} >- >-void LocalStorageDatabase::close() >-{ >- ASSERT(!m_isClosed); >- m_isClosed = true; >- >- if (m_didScheduleDatabaseUpdate) { >- updateDatabaseWithChangedItems(m_changedItems); >- m_changedItems.clear(); >- } >- >- bool isEmpty = databaseIsEmpty(); >- >- if (m_database.isOpen()) >- m_database.close(); >- >- if (isEmpty) >- m_tracker->deleteDatabaseWithOrigin(m_securityOrigin); >-} >- >-void LocalStorageDatabase::itemDidChange(const String& key, const String& value) >-{ >- m_changedItems.set(key, value); >- scheduleDatabaseUpdate(); >-} >- >-void LocalStorageDatabase::scheduleDatabaseUpdate() >-{ >- if (m_didScheduleDatabaseUpdate) >- return; >- >- if (!m_disableSuddenTerminationWhileWritingToLocalStorage) >- m_disableSuddenTerminationWhileWritingToLocalStorage = std::make_unique<SuddenTerminationDisabler>(); >- >- m_didScheduleDatabaseUpdate = true; >- >- m_queue->dispatchAfter(databaseUpdateInterval, [protectedThis = makeRef(*this)] { >- protectedThis->updateDatabase(); >- }); >-} >- >-void LocalStorageDatabase::updateDatabase() >-{ >- if (m_isClosed) >- return; >- >- ASSERT(m_didScheduleDatabaseUpdate); >- m_didScheduleDatabaseUpdate = false; >- >- HashMap<String, String> changedItems; >- if (m_changedItems.size() <= maximumItemsToUpdate) { >- // There are few enough changed items that we can just always write all of them. >- m_changedItems.swap(changedItems); >- updateDatabaseWithChangedItems(changedItems); >- m_disableSuddenTerminationWhileWritingToLocalStorage = nullptr; >- } else { >- for (int i = 0; i < maximumItemsToUpdate; ++i) { >- auto it = m_changedItems.begin(); >- changedItems.add(it->key, it->value); >- >- m_changedItems.remove(it); >- } >- >- ASSERT(changedItems.size() <= maximumItemsToUpdate); >- >- // Reschedule the update for the remaining items. >- scheduleDatabaseUpdate(); >- updateDatabaseWithChangedItems(changedItems); >- } >-} >- >-void LocalStorageDatabase::updateDatabaseWithChangedItems(const HashMap<String, String>& changedItems) >-{ >- if (!m_database.isOpen()) >- openDatabase(CreateIfNonExistent); >- if (!m_database.isOpen()) >- return; >- >- if (m_shouldClearItems) { >- m_shouldClearItems = false; >- >- SQLiteStatement clearStatement(m_database, "DELETE FROM ItemTable"); >- if (clearStatement.prepare() != SQLITE_OK) { >- LOG_ERROR("Failed to prepare clear statement - cannot write to local storage database"); >- return; >- } >- >- int result = clearStatement.step(); >- if (result != SQLITE_DONE) { >- LOG_ERROR("Failed to clear all items in the local storage database - %i", result); >- return; >- } >- } >- >- SQLiteStatement insertStatement(m_database, "INSERT INTO ItemTable VALUES (?, ?)"); >- if (insertStatement.prepare() != SQLITE_OK) { >- LOG_ERROR("Failed to prepare insert statement - cannot write to local storage database"); >- return; >- } >- >- SQLiteStatement deleteStatement(m_database, "DELETE FROM ItemTable WHERE key=?"); >- if (deleteStatement.prepare() != SQLITE_OK) { >- LOG_ERROR("Failed to prepare delete statement - cannot write to local storage database"); >- return; >- } >- >- SQLiteTransaction transaction(m_database); >- transaction.begin(); >- >- for (auto it = changedItems.begin(), end = changedItems.end(); it != end; ++it) { >- // A null value means that the key/value pair should be deleted. >- SQLiteStatement& statement = it->value.isNull() ? deleteStatement : insertStatement; >- >- statement.bindText(1, it->key); >- >- // If we're inserting a key/value pair, bind the value as well. >- if (!it->value.isNull()) >- statement.bindBlob(2, it->value); >- >- int result = statement.step(); >- if (result != SQLITE_DONE) { >- LOG_ERROR("Failed to update item in the local storage database - %i", result); >- break; >- } >- >- statement.reset(); >- } >- >- transaction.commit(); >-} >- >-bool LocalStorageDatabase::databaseIsEmpty() >-{ >- if (!m_database.isOpen()) >- return false; >- >- SQLiteStatement query(m_database, "SELECT COUNT(*) FROM ItemTable"); >- if (query.prepare() != SQLITE_OK) { >- LOG_ERROR("Unable to count number of rows in ItemTable for local storage"); >- return false; >- } >- >- int result = query.step(); >- if (result != SQLITE_ROW) { >- LOG_ERROR("No results when counting number of rows in ItemTable for local storage"); >- return false; >- } >- >- return !query.getColumnInt(0); >-} >- >-} // namespace WebKit >diff --git a/Source/WebKit/UIProcess/WebStorage/LocalStorageDatabase.h b/Source/WebKit/UIProcess/WebStorage/LocalStorageDatabase.h >deleted file mode 100644 >index 9992031f448fb3d91580186d8860a12d84859562..0000000000000000000000000000000000000000 >--- a/Source/WebKit/UIProcess/WebStorage/LocalStorageDatabase.h >+++ /dev/null >@@ -1,99 +0,0 @@ >-/* >- * Copyright (C) 2008, 2009, 2010, 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. >- */ >- >-#pragma once >- >-#include <WebCore/SQLiteDatabase.h> >-#include <WebCore/SecurityOriginData.h> >-#include <wtf/Forward.h> >-#include <wtf/HashMap.h> >-#include <wtf/RefPtr.h> >-#include <wtf/ThreadSafeRefCounted.h> >-#include <wtf/WorkQueue.h> >- >-namespace WebCore { >-class SecurityOrigin; >-class StorageMap; >-class SuddenTerminationDisabler; >-} >- >-namespace WebKit { >- >-class LocalStorageDatabaseTracker; >- >-class LocalStorageDatabase : public ThreadSafeRefCounted<LocalStorageDatabase> { >-public: >- static Ref<LocalStorageDatabase> create(Ref<WorkQueue>&&, Ref<LocalStorageDatabaseTracker>&&, const WebCore::SecurityOriginData&); >- ~LocalStorageDatabase(); >- >- // Will block until the import is complete. >- void importItems(WebCore::StorageMap&); >- >- void setItem(const String& key, const String& value); >- void removeItem(const String& key); >- void clear(); >- >- // Will block until all pending changes have been written to disk. >- void close(); >- >-private: >- LocalStorageDatabase(Ref<WorkQueue>&&, Ref<LocalStorageDatabaseTracker>&&, const WebCore::SecurityOriginData&); >- >- enum DatabaseOpeningStrategy { >- CreateIfNonExistent, >- SkipIfNonExistent >- }; >- bool tryToOpenDatabase(DatabaseOpeningStrategy); >- void openDatabase(DatabaseOpeningStrategy); >- >- bool migrateItemTableIfNeeded(); >- >- void itemDidChange(const String& key, const String& value); >- >- void scheduleDatabaseUpdate(); >- void updateDatabase(); >- void updateDatabaseWithChangedItems(const HashMap<String, String>&); >- >- bool databaseIsEmpty(); >- >- Ref<WorkQueue> m_queue; >- Ref<LocalStorageDatabaseTracker> m_tracker; >- WebCore::SecurityOriginData m_securityOrigin; >- >- String m_databasePath; >- WebCore::SQLiteDatabase m_database; >- bool m_failedToOpenDatabase; >- bool m_didImportItems; >- bool m_isClosed; >- >- bool m_didScheduleDatabaseUpdate; >- bool m_shouldClearItems; >- HashMap<String, String> m_changedItems; >- >- std::unique_ptr<WebCore::SuddenTerminationDisabler> m_disableSuddenTerminationWhileWritingToLocalStorage; >-}; >- >- >-} // namespace WebKit >diff --git a/Source/WebKit/UIProcess/WebStorage/LocalStorageDatabaseTracker.cpp b/Source/WebKit/UIProcess/WebStorage/LocalStorageDatabaseTracker.cpp >deleted file mode 100644 >index d084d62877c02269d7addaf5ade3b4fa149741f9..0000000000000000000000000000000000000000 >--- a/Source/WebKit/UIProcess/WebStorage/LocalStorageDatabaseTracker.cpp >+++ /dev/null >@@ -1,166 +0,0 @@ >-/* >- * Copyright (C) 2011, 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 "LocalStorageDatabaseTracker.h" >- >-#include "Logging.h" >-#include <WebCore/SQLiteFileSystem.h> >-#include <WebCore/SQLiteStatement.h> >-#include <WebCore/TextEncoding.h> >-#include <wtf/FileSystem.h> >-#include <wtf/MainThread.h> >-#include <wtf/RunLoop.h> >-#include <wtf/WorkQueue.h> >-#include <wtf/text/CString.h> >- >-namespace WebKit { >-using namespace WebCore; >- >-Ref<LocalStorageDatabaseTracker> LocalStorageDatabaseTracker::create(Ref<WorkQueue>&& queue, const String& localStorageDirectory) >-{ >- return adoptRef(*new LocalStorageDatabaseTracker(WTFMove(queue), localStorageDirectory)); >-} >- >-LocalStorageDatabaseTracker::LocalStorageDatabaseTracker(Ref<WorkQueue>&& queue, const String& localStorageDirectory) >- : m_queue(WTFMove(queue)) >- , m_localStorageDirectory(localStorageDirectory.isolatedCopy()) >-{ >- // Make sure the encoding is initialized before we start dispatching things to the queue. >- UTF8Encoding(); >- >- m_queue->dispatch([protectedThis = makeRef(*this)]() mutable { >- // Delete legacy storageTracker database file. >- SQLiteFileSystem::deleteDatabaseFile(protectedThis->databasePath("StorageTracker.db")); >- }); >-} >- >-LocalStorageDatabaseTracker::~LocalStorageDatabaseTracker() >-{ >-} >- >-String LocalStorageDatabaseTracker::databasePath(const SecurityOriginData& securityOrigin) const >-{ >- return databasePath(securityOrigin.databaseIdentifier() + ".localstorage"); >-} >- >-void LocalStorageDatabaseTracker::didOpenDatabaseWithOrigin(const SecurityOriginData& securityOrigin) >-{ >- // FIXME: Tell clients that the origin was added. >-} >- >-void LocalStorageDatabaseTracker::deleteDatabaseWithOrigin(const SecurityOriginData& securityOrigin) >-{ >- auto path = databasePath(securityOrigin); >- if (!path.isEmpty()) >- SQLiteFileSystem::deleteDatabaseFile(path); >- >- // FIXME: Tell clients that the origin was removed. >-} >- >-void LocalStorageDatabaseTracker::deleteAllDatabases() >-{ >- auto paths = FileSystem::listDirectory(m_localStorageDirectory, "*.localstorage"); >- for (const auto& path : paths) { >- SQLiteFileSystem::deleteDatabaseFile(path); >- >- // FIXME: Call out to the client. >- } >- >- SQLiteFileSystem::deleteEmptyDatabaseDirectory(m_localStorageDirectory); >-} >- >-Vector<SecurityOriginData> LocalStorageDatabaseTracker::databasesModifiedSince(WallTime time) >-{ >- Vector<SecurityOriginData> databaseOriginsModified; >- auto databaseOrigins = origins(); >- >- for (auto origin : databaseOrigins) { >- auto path = databasePath(origin); >- >- auto modificationTime = SQLiteFileSystem::databaseModificationTime(path); >- if (!modificationTime) >- continue; >- >- if (modificationTime.value() >= time) >- databaseOriginsModified.append(origin); >- } >- >- return databaseOriginsModified; >-} >- >-Vector<SecurityOriginData> LocalStorageDatabaseTracker::origins() const >-{ >- Vector<SecurityOriginData> databaseOrigins; >- auto paths = FileSystem::listDirectory(m_localStorageDirectory, "*.localstorage"); >- >- for (const auto& path : paths) { >- auto filename = FileSystem::pathGetFileName(path); >- auto originIdentifier = filename.substring(0, filename.length() - strlen(".localstorage")); >- auto origin = SecurityOriginData::fromDatabaseIdentifier(originIdentifier); >- if (origin) >- databaseOrigins.append(origin.value()); >- else >- RELEASE_LOG_ERROR(LocalStorageDatabaseTracker, "Unable to extract origin from path %s", path.utf8().data()); >- } >- >- return databaseOrigins; >-} >- >-Vector<LocalStorageDatabaseTracker::OriginDetails> LocalStorageDatabaseTracker::originDetails() >-{ >- Vector<OriginDetails> result; >- auto databaseOrigins = origins(); >- result.reserveInitialCapacity(databaseOrigins.size()); >- >- for (const auto& origin : databaseOrigins) { >- String path = databasePath(origin); >- >- OriginDetails details; >- details.originIdentifier = origin.databaseIdentifier(); >- details.creationTime = SQLiteFileSystem::databaseCreationTime(path); >- details.modificationTime = SQLiteFileSystem::databaseModificationTime(path); >- result.uncheckedAppend(details); >- } >- >- return result; >-} >- >-String LocalStorageDatabaseTracker::databasePath(const String& filename) const >-{ >- if (!SQLiteFileSystem::ensureDatabaseDirectoryExists(m_localStorageDirectory)) { >- if (!m_localStorageDirectory.isNull()) >- LOG_ERROR("Unable to create LocalStorage database path %s", m_localStorageDirectory.utf8().data()); >- return String(); >- } >- >-#if PLATFORM(IOS_FAMILY) >- platformMaybeExcludeFromBackup(); >-#endif >- >- return SQLiteFileSystem::appendDatabaseFileNameToPath(m_localStorageDirectory, filename); >-} >- >-} // namespace WebKit >diff --git a/Source/WebKit/UIProcess/WebStorage/LocalStorageDatabaseTracker.h b/Source/WebKit/UIProcess/WebStorage/LocalStorageDatabaseTracker.h >deleted file mode 100644 >index 0991d71272fa094f8baba8423a477b0edd73c522..0000000000000000000000000000000000000000 >--- a/Source/WebKit/UIProcess/WebStorage/LocalStorageDatabaseTracker.h >+++ /dev/null >@@ -1,83 +0,0 @@ >-/* >- * Copyright (C) 2011, 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. >- */ >- >-#pragma once >- >-#include <WebCore/SecurityOriginData.h> >-#include <wtf/Markable.h> >-#include <wtf/RefPtr.h> >-#include <wtf/ThreadSafeRefCounted.h> >-#include <wtf/WallTime.h> >-#include <wtf/WorkQueue.h> >-#include <wtf/text/WTFString.h> >- >-namespace WebKit { >- >-struct LocalStorageDetails; >- >-class LocalStorageDatabaseTracker : public ThreadSafeRefCounted<LocalStorageDatabaseTracker> { >-public: >- static Ref<LocalStorageDatabaseTracker> create(Ref<WorkQueue>&&, const String& localStorageDirectory); >- ~LocalStorageDatabaseTracker(); >- >- String databasePath(const WebCore::SecurityOriginData&) const; >- >- void didOpenDatabaseWithOrigin(const WebCore::SecurityOriginData&); >- void deleteDatabaseWithOrigin(const WebCore::SecurityOriginData&); >- void deleteAllDatabases(); >- >- // Returns a vector of the origins whose databases should be deleted. >- Vector<WebCore::SecurityOriginData> databasesModifiedSince(WallTime); >- >- Vector<WebCore::SecurityOriginData> origins() const; >- >- struct OriginDetails { >- String originIdentifier; >- Markable<WallTime, WallTime::MarkableTraits> creationTime; >- Markable<WallTime, WallTime::MarkableTraits> modificationTime; >- }; >- Vector<OriginDetails> originDetails(); >- >-private: >- LocalStorageDatabaseTracker(Ref<WorkQueue>&&, const String& localStorageDirectory); >- >- String databasePath(const String& filename) const; >- >- enum DatabaseOpeningStrategy { >- CreateIfNonExistent, >- SkipIfNonExistent >- }; >- >- RefPtr<WorkQueue> m_queue; >- String m_localStorageDirectory; >- >-#if PLATFORM(IOS_FAMILY) >- void platformMaybeExcludeFromBackup() const; >- >- mutable bool m_hasExcludedFromBackup { false }; >-#endif >-}; >- >-} // namespace WebKit >diff --git a/Source/WebKit/UIProcess/WebStorage/StorageManager.cpp b/Source/WebKit/UIProcess/WebStorage/StorageManager.cpp >deleted file mode 100644 >index 8cccdc1abd7959e24f499d5bdefe34f8c86f1692..0000000000000000000000000000000000000000 >--- a/Source/WebKit/UIProcess/WebStorage/StorageManager.cpp >+++ /dev/null >@@ -1,935 +0,0 @@ >-/* >- * Copyright (C) 2013-2016 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 "StorageManager.h" >- >-#include "LocalStorageDatabase.h" >-#include "LocalStorageDatabaseTracker.h" >-#include "StorageAreaMapMessages.h" >-#include "StorageManagerMessages.h" >-#include "WebProcessProxy.h" >-#include <WebCore/SecurityOriginData.h> >-#include <WebCore/SecurityOriginHash.h> >-#include <WebCore/StorageMap.h> >-#include <WebCore/TextEncoding.h> >-#include <memory> >-#include <wtf/WorkQueue.h> >-#include <wtf/threads/BinarySemaphore.h> >- >-namespace WebKit { >-using namespace WebCore; >- >-class StorageManager::StorageArea : public ThreadSafeRefCounted<StorageManager::StorageArea> { >-public: >- static Ref<StorageArea> create(LocalStorageNamespace*, const SecurityOriginData&, unsigned quotaInBytes); >- ~StorageArea(); >- >- const WebCore::SecurityOriginData& securityOrigin() const { return m_securityOrigin; } >- >- void addListener(IPC::Connection::UniqueID, uint64_t storageMapID); >- void removeListener(IPC::Connection::UniqueID, uint64_t storageMapID); >- bool hasListener(IPC::Connection::UniqueID, uint64_t storageMapID) const; >- >- Ref<StorageArea> clone() const; >- >- void setItem(IPC::Connection::UniqueID sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& value, const String& urlString, bool& quotaException); >- void removeItem(IPC::Connection::UniqueID sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& urlString); >- void clear(IPC::Connection::UniqueID sourceConnection, uint64_t sourceStorageAreaID, const String& urlString); >- >- const HashMap<String, String>& items() const; >- void clear(); >- >- bool isSessionStorage() const { return !m_localStorageNamespace; } >- >-private: >- explicit StorageArea(LocalStorageNamespace*, const SecurityOriginData&, unsigned quotaInBytes); >- >- void openDatabaseAndImportItemsIfNeeded() const; >- >- void dispatchEvents(IPC::Connection::UniqueID sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& oldValue, const String& newValue, const String& urlString) const; >- >- // Will be null if the storage area belongs to a session storage namespace. >- LocalStorageNamespace* m_localStorageNamespace; >- mutable RefPtr<LocalStorageDatabase> m_localStorageDatabase; >- mutable bool m_didImportItemsFromDatabase { false }; >- >- SecurityOriginData m_securityOrigin; >- unsigned m_quotaInBytes; >- >- RefPtr<StorageMap> m_storageMap; >- HashSet<std::pair<IPC::Connection::UniqueID, uint64_t>> m_eventListeners; >-}; >- >-class StorageManager::LocalStorageNamespace : public ThreadSafeRefCounted<LocalStorageNamespace> { >-public: >- static Ref<LocalStorageNamespace> create(StorageManager*, uint64_t storageManagerID); >- ~LocalStorageNamespace(); >- >- StorageManager* storageManager() const { return m_storageManager; } >- >- Ref<StorageArea> getOrCreateStorageArea(SecurityOriginData&&); >- void didDestroyStorageArea(StorageArea*); >- >- void clearStorageAreasMatchingOrigin(const SecurityOriginData&); >- void clearAllStorageAreas(); >- >-private: >- explicit LocalStorageNamespace(StorageManager*, uint64_t storageManagerID); >- >- StorageManager* m_storageManager; >- uint64_t m_storageNamespaceID; >- unsigned m_quotaInBytes; >- >- // We don't hold an explicit reference to the StorageAreas; they are kept alive by the m_storageAreasByConnection map in StorageManager. >- HashMap<SecurityOriginData, StorageArea*> m_storageAreaMap; >-}; >- >-// Suggested by https://www.w3.org/TR/webstorage/#disk-space >-const unsigned localStorageDatabaseQuotaInBytes = 5 * 1024 * 1024; >- >-class StorageManager::TransientLocalStorageNamespace : public ThreadSafeRefCounted<TransientLocalStorageNamespace> { >-public: >- static Ref<TransientLocalStorageNamespace> create() >- { >- return adoptRef(*new TransientLocalStorageNamespace()); >- } >- >- ~TransientLocalStorageNamespace() >- { >- } >- >- Ref<StorageArea> getOrCreateStorageArea(SecurityOriginData&& securityOrigin) >- { >- return *m_storageAreaMap.ensure(securityOrigin, [this, securityOrigin]() mutable { >- return StorageArea::create(nullptr, WTFMove(securityOrigin), m_quotaInBytes); >- }).iterator->value.copyRef(); >- } >- >- Vector<SecurityOriginData> origins() const >- { >- Vector<SecurityOriginData> origins; >- >- for (const auto& storageArea : m_storageAreaMap.values()) { >- if (!storageArea->items().isEmpty()) >- origins.append(storageArea->securityOrigin()); >- } >- >- return origins; >- } >- >- void clearStorageAreasMatchingOrigin(const SecurityOriginData& securityOrigin) >- { >- for (auto& storageArea : m_storageAreaMap.values()) { >- if (storageArea->securityOrigin() == securityOrigin) >- storageArea->clear(); >- } >- } >- >- void clearAllStorageAreas() >- { >- for (auto& storageArea : m_storageAreaMap.values()) >- storageArea->clear(); >- } >- >-private: >- explicit TransientLocalStorageNamespace() >- { >- } >- >- const unsigned m_quotaInBytes = localStorageDatabaseQuotaInBytes; >- >- HashMap<SecurityOriginData, RefPtr<StorageArea>> m_storageAreaMap; >-}; >- >-auto StorageManager::StorageArea::create(LocalStorageNamespace* localStorageNamespace, const SecurityOriginData& securityOrigin, unsigned quotaInBytes) -> Ref<StorageManager::StorageArea> >-{ >- return adoptRef(*new StorageArea(localStorageNamespace, securityOrigin, quotaInBytes)); >-} >- >-StorageManager::StorageArea::StorageArea(LocalStorageNamespace* localStorageNamespace, const SecurityOriginData& securityOrigin, unsigned quotaInBytes) >- : m_localStorageNamespace(localStorageNamespace) >- , m_securityOrigin(securityOrigin) >- , m_quotaInBytes(quotaInBytes) >- , m_storageMap(StorageMap::create(m_quotaInBytes)) >-{ >-} >- >-StorageManager::StorageArea::~StorageArea() >-{ >- ASSERT(m_eventListeners.isEmpty()); >- >- if (m_localStorageDatabase) >- m_localStorageDatabase->close(); >- >- if (m_localStorageNamespace) >- m_localStorageNamespace->didDestroyStorageArea(this); >-} >- >-void StorageManager::StorageArea::addListener(IPC::Connection::UniqueID connectionID, uint64_t storageMapID) >-{ >- ASSERT(!m_eventListeners.contains(std::make_pair(connectionID, storageMapID))); >- m_eventListeners.add(std::make_pair(connectionID, storageMapID)); >-} >- >-void StorageManager::StorageArea::removeListener(IPC::Connection::UniqueID connectionID, uint64_t storageMapID) >-{ >- ASSERT(isSessionStorage() || m_eventListeners.contains(std::make_pair(connectionID, storageMapID))); >- m_eventListeners.remove(std::make_pair(connectionID, storageMapID)); >-} >- >-bool StorageManager::StorageArea::hasListener(IPC::Connection::UniqueID connectionID, uint64_t storageMapID) const >-{ >- return m_eventListeners.contains(std::make_pair(connectionID, storageMapID)); >-} >- >-Ref<StorageManager::StorageArea> StorageManager::StorageArea::clone() const >-{ >- ASSERT(!m_localStorageNamespace); >- >- auto storageArea = StorageArea::create(nullptr, m_securityOrigin, m_quotaInBytes); >- storageArea->m_storageMap = m_storageMap; >- >- return storageArea; >-} >- >-void StorageManager::StorageArea::setItem(IPC::Connection::UniqueID sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& value, const String& urlString, bool& quotaException) >-{ >- openDatabaseAndImportItemsIfNeeded(); >- >- String oldValue; >- >- auto newStorageMap = m_storageMap->setItem(key, value, oldValue, quotaException); >- if (newStorageMap) >- m_storageMap = WTFMove(newStorageMap); >- >- if (quotaException) >- return; >- >- if (m_localStorageDatabase) >- m_localStorageDatabase->setItem(key, value); >- >- dispatchEvents(sourceConnection, sourceStorageAreaID, key, oldValue, value, urlString); >-} >- >-void StorageManager::StorageArea::removeItem(IPC::Connection::UniqueID sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& urlString) >-{ >- openDatabaseAndImportItemsIfNeeded(); >- >- String oldValue; >- auto newStorageMap = m_storageMap->removeItem(key, oldValue); >- if (newStorageMap) >- m_storageMap = WTFMove(newStorageMap); >- >- if (oldValue.isNull()) >- return; >- >- if (m_localStorageDatabase) >- m_localStorageDatabase->removeItem(key); >- >- dispatchEvents(sourceConnection, sourceStorageAreaID, key, oldValue, String(), urlString); >-} >- >-void StorageManager::StorageArea::clear(IPC::Connection::UniqueID sourceConnection, uint64_t sourceStorageAreaID, const String& urlString) >-{ >- openDatabaseAndImportItemsIfNeeded(); >- >- if (!m_storageMap->length()) >- return; >- >- m_storageMap = StorageMap::create(m_quotaInBytes); >- >- if (m_localStorageDatabase) >- m_localStorageDatabase->clear(); >- >- dispatchEvents(sourceConnection, sourceStorageAreaID, String(), String(), String(), urlString); >-} >- >-const HashMap<String, String>& StorageManager::StorageArea::items() const >-{ >- openDatabaseAndImportItemsIfNeeded(); >- >- return m_storageMap->items(); >-} >- >-void StorageManager::StorageArea::clear() >-{ >- m_storageMap = StorageMap::create(m_quotaInBytes); >- >- if (m_localStorageDatabase) { >- m_localStorageDatabase->close(); >- m_localStorageDatabase = nullptr; >- } >- >- for (auto it = m_eventListeners.begin(), end = m_eventListeners.end(); it != end; ++it) { >- RunLoop::main().dispatch([connectionID = it->first, destinationStorageAreaID = it->second] { >- if (auto* connection = IPC::Connection::connection(connectionID)) >- connection->send(Messages::StorageAreaMap::ClearCache(), destinationStorageAreaID); >- }); >- } >-} >- >-void StorageManager::StorageArea::openDatabaseAndImportItemsIfNeeded() const >-{ >- if (!m_localStorageNamespace) >- return; >- >- // We open the database here even if we've already imported our items to ensure that the database is open if we need to write to it. >- if (!m_localStorageDatabase) >- m_localStorageDatabase = LocalStorageDatabase::create(m_localStorageNamespace->storageManager()->m_queue.copyRef(), m_localStorageNamespace->storageManager()->m_localStorageDatabaseTracker.copyRef(), m_securityOrigin); >- >- if (m_didImportItemsFromDatabase) >- return; >- >- m_localStorageDatabase->importItems(*m_storageMap); >- m_didImportItemsFromDatabase = true; >-} >- >-void StorageManager::StorageArea::dispatchEvents(IPC::Connection::UniqueID sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& oldValue, const String& newValue, const String& urlString) const >-{ >- for (auto it = m_eventListeners.begin(), end = m_eventListeners.end(); it != end; ++it) { >- sourceStorageAreaID = it->first == sourceConnection ? sourceStorageAreaID : 0; >- >- RunLoop::main().dispatch([connectionID = it->first, sourceStorageAreaID, destinationStorageAreaID = it->second, key = key.isolatedCopy(), oldValue = oldValue.isolatedCopy(), newValue = newValue.isolatedCopy(), urlString = urlString.isolatedCopy()] { >- if (auto* connection = IPC::Connection::connection(connectionID)) >- connection->send(Messages::StorageAreaMap::DispatchStorageEvent(sourceStorageAreaID, key, oldValue, newValue, urlString), destinationStorageAreaID); >- }); >- } >-} >- >-Ref<StorageManager::LocalStorageNamespace> StorageManager::LocalStorageNamespace::create(StorageManager* storageManager, uint64_t storageNamespaceID) >-{ >- return adoptRef(*new LocalStorageNamespace(storageManager, storageNamespaceID)); >-} >- >-// FIXME: The quota value is copied from GroupSettings.cpp. >-// We should investigate a way to share it with WebCore. >-StorageManager::LocalStorageNamespace::LocalStorageNamespace(StorageManager* storageManager, uint64_t storageNamespaceID) >- : m_storageManager(storageManager) >- , m_storageNamespaceID(storageNamespaceID) >- , m_quotaInBytes(localStorageDatabaseQuotaInBytes) >-{ >-} >- >-StorageManager::LocalStorageNamespace::~LocalStorageNamespace() >-{ >- ASSERT(m_storageAreaMap.isEmpty()); >-} >- >-auto StorageManager::LocalStorageNamespace::getOrCreateStorageArea(SecurityOriginData&& securityOrigin) -> Ref<StorageArea> >-{ >- auto& slot = m_storageAreaMap.add(securityOrigin, nullptr).iterator->value; >- if (slot) >- return *slot; >- >- auto storageArea = StorageArea::create(this, WTFMove(securityOrigin), m_quotaInBytes); >- slot = &storageArea.get(); >- >- return storageArea; >-} >- >-void StorageManager::LocalStorageNamespace::didDestroyStorageArea(StorageArea* storageArea) >-{ >- ASSERT(m_storageAreaMap.contains(storageArea->securityOrigin())); >- >- m_storageAreaMap.remove(storageArea->securityOrigin()); >- if (!m_storageAreaMap.isEmpty()) >- return; >- >- ASSERT(m_storageManager->m_localStorageNamespaces.contains(m_storageNamespaceID)); >- m_storageManager->m_localStorageNamespaces.remove(m_storageNamespaceID); >-} >- >-void StorageManager::LocalStorageNamespace::clearStorageAreasMatchingOrigin(const SecurityOriginData& securityOrigin) >-{ >- for (const auto& originAndStorageArea : m_storageAreaMap) { >- if (originAndStorageArea.key == securityOrigin) >- originAndStorageArea.value->clear(); >- } >-} >- >-void StorageManager::LocalStorageNamespace::clearAllStorageAreas() >-{ >- for (auto* storageArea : m_storageAreaMap.values()) >- storageArea->clear(); >-} >- >-class StorageManager::SessionStorageNamespace : public ThreadSafeRefCounted<SessionStorageNamespace> { >-public: >- static Ref<SessionStorageNamespace> create(unsigned quotaInBytes); >- ~SessionStorageNamespace(); >- >- bool isEmpty() const { return m_storageAreaMap.isEmpty(); } >- >- Vector<IPC::Connection::UniqueID> allowedConnections() const { return m_allowedConnections; } >- void addAllowedConnection(IPC::Connection::UniqueID); >- void removeAllowedConnection(IPC::Connection::UniqueID); >- >- Ref<StorageArea> getOrCreateStorageArea(SecurityOriginData&&); >- >- void cloneTo(SessionStorageNamespace& newSessionStorageNamespace); >- >- Vector<SecurityOriginData> origins() const >- { >- Vector<SecurityOriginData> origins; >- >- for (const auto& storageArea : m_storageAreaMap.values()) { >- if (!storageArea->items().isEmpty()) >- origins.append(storageArea->securityOrigin()); >- } >- >- return origins; >- } >- >- void clearStorageAreasMatchingOrigin(const SecurityOriginData& securityOrigin) >- { >- for (auto& storageArea : m_storageAreaMap.values()) { >- if (storageArea->securityOrigin() == securityOrigin) >- storageArea->clear(); >- } >- } >- >- void clearAllStorageAreas() >- { >- for (auto& storageArea : m_storageAreaMap.values()) >- storageArea->clear(); >- } >- >-private: >- explicit SessionStorageNamespace(unsigned quotaInBytes); >- >- Vector<IPC::Connection::UniqueID> m_allowedConnections; >- unsigned m_quotaInBytes; >- >- HashMap<SecurityOriginData, RefPtr<StorageArea>> m_storageAreaMap; >-}; >- >-Ref<StorageManager::SessionStorageNamespace> StorageManager::SessionStorageNamespace::create(unsigned quotaInBytes) >-{ >- return adoptRef(*new SessionStorageNamespace(quotaInBytes)); >-} >- >-StorageManager::SessionStorageNamespace::SessionStorageNamespace(unsigned quotaInBytes) >- : m_quotaInBytes(quotaInBytes) >-{ >-} >- >-StorageManager::SessionStorageNamespace::~SessionStorageNamespace() >-{ >-} >- >-void StorageManager::SessionStorageNamespace::addAllowedConnection(IPC::Connection::UniqueID allowedConnection) >-{ >- ASSERT(!m_allowedConnections.contains(allowedConnection)); >- m_allowedConnections.append(allowedConnection); >-} >- >- >-void StorageManager::SessionStorageNamespace::removeAllowedConnection(IPC::Connection::UniqueID allowedConnection) >-{ >- ASSERT(m_allowedConnections.contains(allowedConnection)); >- m_allowedConnections.removeAll(allowedConnection); >-} >-auto StorageManager::SessionStorageNamespace::getOrCreateStorageArea(SecurityOriginData&& securityOrigin) -> Ref<StorageArea> >-{ >- return *m_storageAreaMap.ensure(securityOrigin, [this, securityOrigin]() mutable { >- return StorageArea::create(nullptr, WTFMove(securityOrigin), m_quotaInBytes); >- }).iterator->value.copyRef(); >-} >- >-void StorageManager::SessionStorageNamespace::cloneTo(SessionStorageNamespace& newSessionStorageNamespace) >-{ >- ASSERT_UNUSED(newSessionStorageNamespace, newSessionStorageNamespace.isEmpty()); >- >- for (auto& pair : m_storageAreaMap) >- newSessionStorageNamespace.m_storageAreaMap.add(pair.key, pair.value->clone()); >-} >- >-Ref<StorageManager> StorageManager::create(const String& localStorageDirectory) >-{ >- return adoptRef(*new StorageManager(localStorageDirectory)); >-} >- >-StorageManager::StorageManager(const String& localStorageDirectory) >- : m_queue(WorkQueue::create("com.apple.WebKit.StorageManager")) >- , m_localStorageDatabaseTracker(LocalStorageDatabaseTracker::create(m_queue.copyRef(), localStorageDirectory)) >- , m_isEphemeral(localStorageDirectory.isNull()) >-{ >- // Make sure the encoding is initialized before we start dispatching things to the queue. >- UTF8Encoding(); >-} >- >-StorageManager::~StorageManager() >-{ >-} >- >-void StorageManager::createSessionStorageNamespace(uint64_t storageNamespaceID, unsigned quotaInBytes) >-{ >- m_queue->dispatch([this, protectedThis = makeRef(*this), storageNamespaceID, quotaInBytes]() mutable { >- ASSERT(!m_sessionStorageNamespaces.contains(storageNamespaceID)); >- >- m_sessionStorageNamespaces.set(storageNamespaceID, SessionStorageNamespace::create(quotaInBytes)); >- }); >-} >- >-void StorageManager::destroySessionStorageNamespace(uint64_t storageNamespaceID) >-{ >- m_queue->dispatch([this, protectedThis = makeRef(*this), storageNamespaceID] { >- ASSERT(m_sessionStorageNamespaces.contains(storageNamespaceID)); >- m_sessionStorageNamespaces.remove(storageNamespaceID); >- }); >-} >- >-void StorageManager::addAllowedSessionStorageNamespaceConnection(uint64_t storageNamespaceID, IPC::Connection& allowedConnection) >-{ >- auto allowedConnectionID = allowedConnection.uniqueID(); >- m_queue->dispatch([this, protectedThis = makeRef(*this), allowedConnectionID, storageNamespaceID]() mutable { >- ASSERT(m_sessionStorageNamespaces.contains(storageNamespaceID)); >- >- m_sessionStorageNamespaces.get(storageNamespaceID)->addAllowedConnection(allowedConnectionID); >- }); >-} >- >-void StorageManager::removeAllowedSessionStorageNamespaceConnection(uint64_t storageNamespaceID, IPC::Connection& allowedConnection) >-{ >- auto allowedConnectionID = allowedConnection.uniqueID(); >- m_queue->dispatch([this, protectedThis = makeRef(*this), allowedConnectionID, storageNamespaceID]() mutable { >- ASSERT(m_sessionStorageNamespaces.contains(storageNamespaceID)); >- >- m_sessionStorageNamespaces.get(storageNamespaceID)->removeAllowedConnection(allowedConnectionID); >- }); >-} >- >-void StorageManager::cloneSessionStorageNamespace(uint64_t storageNamespaceID, uint64_t newStorageNamespaceID) >-{ >- m_queue->dispatch([this, protectedThis = makeRef(*this), storageNamespaceID, newStorageNamespaceID] { >- SessionStorageNamespace* sessionStorageNamespace = m_sessionStorageNamespaces.get(storageNamespaceID); >- if (!sessionStorageNamespace) { >- // FIXME: We can get into this situation if someone closes the originating page from within a >- // createNewPage callback. We bail for now, but we should really find a way to keep the session storage alive >- // so we we'll clone the session storage correctly. >- return; >- } >- >- SessionStorageNamespace* newSessionStorageNamespace = m_sessionStorageNamespaces.get(newStorageNamespaceID); >- ASSERT(newSessionStorageNamespace); >- >- sessionStorageNamespace->cloneTo(*newSessionStorageNamespace); >- }); >-} >- >-void StorageManager::processWillOpenConnection(WebProcessProxy& process, IPC::Connection& connection) >-{ >- connection.addWorkQueueMessageReceiver(Messages::StorageManager::messageReceiverName(), m_queue.get(), this); >-} >- >-void StorageManager::processDidCloseConnection(WebProcessProxy& process, IPC::Connection& connection) >-{ >- connection.removeWorkQueueMessageReceiver(Messages::StorageManager::messageReceiverName()); >- >- m_queue->dispatch([this, protectedThis = makeRef(*this), connectionID = connection.uniqueID()]() mutable { >- Vector<std::pair<IPC::Connection::UniqueID, uint64_t>> connectionAndStorageMapIDPairsToRemove; >- for (auto& storageArea : m_storageAreasByConnection) { >- if (storageArea.key.first != connectionID) >- continue; >- >- storageArea.value->removeListener(storageArea.key.first, storageArea.key.second); >- connectionAndStorageMapIDPairsToRemove.append(storageArea.key); >- } >- >- for (auto& pair : connectionAndStorageMapIDPairsToRemove) >- m_storageAreasByConnection.remove(pair); >- }); >-} >- >-void StorageManager::getSessionStorageOrigins(Function<void(HashSet<WebCore::SecurityOriginData>&&)>&& completionHandler) >-{ >- m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable { >- HashSet<SecurityOriginData> origins; >- >- for (const auto& sessionStorageNamespace : m_sessionStorageNamespaces.values()) { >- for (auto& origin : sessionStorageNamespace->origins()) >- origins.add(origin); >- } >- >- RunLoop::main().dispatch([origins = WTFMove(origins), completionHandler = WTFMove(completionHandler)]() mutable { >- completionHandler(WTFMove(origins)); >- }); >- }); >-} >- >-void StorageManager::deleteSessionStorageOrigins(Function<void()>&& completionHandler) >-{ >- m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable { >- for (auto& sessionStorageNamespace : m_sessionStorageNamespaces.values()) >- sessionStorageNamespace->clearAllStorageAreas(); >- >- RunLoop::main().dispatch(WTFMove(completionHandler)); >- }); >-} >- >-void StorageManager::deleteSessionStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>& origins, Function<void()>&& completionHandler) >-{ >- Vector<WebCore::SecurityOriginData> copiedOrigins; >- copiedOrigins.reserveInitialCapacity(origins.size()); >- >- for (auto& origin : origins) >- copiedOrigins.uncheckedAppend(origin.isolatedCopy()); >- >- m_queue->dispatch([this, protectedThis = makeRef(*this), copiedOrigins = WTFMove(copiedOrigins), completionHandler = WTFMove(completionHandler)]() mutable { >- for (auto& origin : copiedOrigins) { >- for (auto& sessionStorageNamespace : m_sessionStorageNamespaces.values()) >- sessionStorageNamespace->clearStorageAreasMatchingOrigin(origin); >- } >- >- RunLoop::main().dispatch(WTFMove(completionHandler)); >- }); >-} >- >-void StorageManager::getLocalStorageOrigins(Function<void(HashSet<WebCore::SecurityOriginData>&&)>&& completionHandler) >-{ >- m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable { >- HashSet<SecurityOriginData> origins; >- >- for (auto& origin : m_localStorageDatabaseTracker->origins()) >- origins.add(origin); >- >- for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values()) { >- for (auto& origin : transientLocalStorageNamespace->origins()) >- origins.add(origin); >- } >- >- RunLoop::main().dispatch([origins = WTFMove(origins), completionHandler = WTFMove(completionHandler)]() mutable { >- completionHandler(WTFMove(origins)); >- }); >- }); >-} >- >-void StorageManager::getLocalStorageOriginDetails(Function<void (Vector<LocalStorageDatabaseTracker::OriginDetails>)>&& completionHandler) >-{ >- m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable { >- auto originDetails = m_localStorageDatabaseTracker->originDetails(); >- >- RunLoop::main().dispatch([originDetails = WTFMove(originDetails), completionHandler = WTFMove(completionHandler)]() mutable { >- completionHandler(WTFMove(originDetails)); >- }); >- }); >-} >- >-void StorageManager::deleteLocalStorageEntriesForOrigin(const SecurityOriginData& securityOrigin) >-{ >- m_queue->dispatch([this, protectedThis = makeRef(*this), copiedOrigin = securityOrigin.isolatedCopy()]() mutable { >- for (auto& localStorageNamespace : m_localStorageNamespaces.values()) >- localStorageNamespace->clearStorageAreasMatchingOrigin(copiedOrigin); >- >- for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values()) >- transientLocalStorageNamespace->clearStorageAreasMatchingOrigin(copiedOrigin); >- >- m_localStorageDatabaseTracker->deleteDatabaseWithOrigin(copiedOrigin); >- }); >-} >- >-void StorageManager::deleteLocalStorageOriginsModifiedSince(WallTime time, Function<void()>&& completionHandler) >-{ >- m_queue->dispatch([this, protectedThis = makeRef(*this), time, completionHandler = WTFMove(completionHandler)]() mutable { >- auto originsToDelete = m_localStorageDatabaseTracker->databasesModifiedSince(time); >- >- for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values()) >- transientLocalStorageNamespace->clearAllStorageAreas(); >- >- for (const auto& origin : originsToDelete) { >- for (auto& localStorageNamespace : m_localStorageNamespaces.values()) >- localStorageNamespace->clearStorageAreasMatchingOrigin(origin); >- >- m_localStorageDatabaseTracker->deleteDatabaseWithOrigin(origin); >- } >- >- RunLoop::main().dispatch(WTFMove(completionHandler)); >- }); >-} >- >-void StorageManager::deleteLocalStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>& origins, Function<void()>&& completionHandler) >-{ >- Vector<SecurityOriginData> copiedOrigins; >- copiedOrigins.reserveInitialCapacity(origins.size()); >- >- for (auto& origin : origins) >- copiedOrigins.uncheckedAppend(origin.isolatedCopy()); >- >- m_queue->dispatch([this, protectedThis = makeRef(*this), copiedOrigins = WTFMove(copiedOrigins), completionHandler = WTFMove(completionHandler)]() mutable { >- for (auto& origin : copiedOrigins) { >- for (auto& localStorageNamespace : m_localStorageNamespaces.values()) >- localStorageNamespace->clearStorageAreasMatchingOrigin(origin); >- >- for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values()) >- transientLocalStorageNamespace->clearStorageAreasMatchingOrigin(origin); >- >- m_localStorageDatabaseTracker->deleteDatabaseWithOrigin(origin); >- } >- >- RunLoop::main().dispatch(WTFMove(completionHandler)); >- }); >-} >- >-void StorageManager::createLocalStorageMap(IPC::Connection& connection, uint64_t storageMapID, uint64_t storageNamespaceID, SecurityOriginData&& securityOriginData) >-{ >- ASSERT(!m_isEphemeral); >- std::pair<IPC::Connection::UniqueID, uint64_t> connectionAndStorageMapIDPair(connection.uniqueID(), storageMapID); >- >- // FIXME: This should be a message check. >- ASSERT((HashMap<std::pair<IPC::Connection::UniqueID, uint64_t>, RefPtr<StorageArea>>::isValidKey(connectionAndStorageMapIDPair))); >- >- auto result = m_storageAreasByConnection.add(connectionAndStorageMapIDPair, nullptr); >- >- // FIXME: These should be a message checks. >- ASSERT(result.isNewEntry); >- ASSERT((HashMap<uint64_t, RefPtr<LocalStorageNamespace>>::isValidKey(storageNamespaceID))); >- >- LocalStorageNamespace* localStorageNamespace = getOrCreateLocalStorageNamespace(storageNamespaceID); >- >- // FIXME: This should be a message check. >- ASSERT(localStorageNamespace); >- >- auto storageArea = localStorageNamespace->getOrCreateStorageArea(WTFMove(securityOriginData)); >- storageArea->addListener(connection.uniqueID(), storageMapID); >- >- result.iterator->value = WTFMove(storageArea); >-} >- >-void StorageManager::createTransientLocalStorageMap(IPC::Connection& connection, uint64_t storageMapID, uint64_t storageNamespaceID, SecurityOriginData&& topLevelOriginData, SecurityOriginData&& origin) >-{ >- // FIXME: This should be a message check. >- ASSERT(m_storageAreasByConnection.isValidKey({ connection.uniqueID(), storageMapID })); >- >- // See if we already have session storage for this connection/origin combo. >- // If so, update the map with the new ID, otherwise keep on trucking. >- for (auto it = m_storageAreasByConnection.begin(), end = m_storageAreasByConnection.end(); it != end; ++it) { >- if (it->key.first != connection.uniqueID()) >- continue; >- Ref<StorageArea> area = *it->value; >- if (!area->isSessionStorage()) >- continue; >- if (!origin.securityOrigin()->isSameSchemeHostPort(area->securityOrigin().securityOrigin().get())) >- continue; >- area->addListener(connection.uniqueID(), storageMapID); >- // If the storageMapID used as key in m_storageAreasByConnection is no longer one of the StorageArea's listeners, then this means >- // that destroyStorageMap() was already called for that storageMapID but it decided not to remove it from m_storageAreasByConnection >- // so that we could reuse it later on for the same connection/origin combo. In this case, it is safe to remove the previous >- // storageMapID from m_storageAreasByConnection. >- if (!area->hasListener(connection.uniqueID(), it->key.second)) >- m_storageAreasByConnection.remove(it); >- m_storageAreasByConnection.add({ connection.uniqueID(), storageMapID }, WTFMove(area)); >- return; >- } >- >- auto& slot = m_storageAreasByConnection.add({ connection.uniqueID(), storageMapID }, nullptr).iterator->value; >- >- // FIXME: This should be a message check. >- ASSERT(!slot); >- >- TransientLocalStorageNamespace* transientLocalStorageNamespace = getOrCreateTransientLocalStorageNamespace(storageNamespaceID, WTFMove(topLevelOriginData)); >- >- auto storageArea = transientLocalStorageNamespace->getOrCreateStorageArea(WTFMove(origin)); >- storageArea->addListener(connection.uniqueID(), storageMapID); >- >- slot = WTFMove(storageArea); >-} >- >-void StorageManager::createSessionStorageMap(IPC::Connection& connection, uint64_t storageMapID, uint64_t storageNamespaceID, SecurityOriginData&& securityOriginData) >-{ >- if (m_isEphemeral) { >- m_ephemeralStorage.add(securityOriginData, WebCore::StorageMap::create(localStorageDatabaseQuotaInBytes)); >- return; >- } >- // FIXME: This should be a message check. >- ASSERT(m_sessionStorageNamespaces.isValidKey(storageNamespaceID)); >- >- SessionStorageNamespace* sessionStorageNamespace = m_sessionStorageNamespaces.get(storageNamespaceID); >- if (!sessionStorageNamespace) { >- // We're getting an incoming message from the web process that's for session storage for a web page >- // that has already been closed, just ignore it. >- return; >- } >- >- // FIXME: This should be a message check. >- ASSERT(m_storageAreasByConnection.isValidKey({ connection.uniqueID(), storageMapID })); >- >- auto& slot = m_storageAreasByConnection.add({ connection.uniqueID(), storageMapID }, nullptr).iterator->value; >- >- // FIXME: This should be a message check. >- ASSERT(!slot); >- >- // FIXME: This should be a message check. >- ASSERT(sessionStorageNamespace->allowedConnections().contains(connection.uniqueID())); >- >- auto storageArea = sessionStorageNamespace->getOrCreateStorageArea(WTFMove(securityOriginData)); >- storageArea->addListener(connection.uniqueID(), storageMapID); >- >- slot = WTFMove(storageArea); >-} >- >-void StorageManager::destroyStorageMap(IPC::Connection& connection, uint64_t storageMapID) >-{ >- std::pair<IPC::Connection::UniqueID, uint64_t> connectionAndStorageMapIDPair(connection.uniqueID(), storageMapID); >- >- // FIXME: This should be a message check. >- ASSERT(m_storageAreasByConnection.isValidKey(connectionAndStorageMapIDPair)); >- >- auto it = m_storageAreasByConnection.find(connectionAndStorageMapIDPair); >- if (it == m_storageAreasByConnection.end()) { >- // The connection has been removed because the last page was closed. >- return; >- } >- >- it->value->removeListener(connection.uniqueID(), storageMapID); >- >- // Don't remove session storage maps. The web process may reconnect and expect the data to still be around. >- if (it->value->isSessionStorage()) >- return; >- >- m_storageAreasByConnection.remove(connectionAndStorageMapIDPair); >-} >- >-void StorageManager::getValues(IPC::Connection& connection, WebCore::SecurityOriginData&& securityOriginData, uint64_t storageMapID, uint64_t storageMapSeed, CompletionHandler<void(const HashMap<String, String>&)>&& completionHandler) >-{ >- StorageArea* storageArea = findStorageArea(connection, storageMapID); >- if (!storageArea) { >- if (m_isEphemeral) { >- if (auto storageMap = m_ephemeralStorage.get(securityOriginData)) >- return completionHandler(storageMap->items()); >- } >- // This is a session storage area for a page that has already been closed. Ignore it. >- return completionHandler({ }); >- } >- >- completionHandler(storageArea->items()); >- connection.send(Messages::StorageAreaMap::DidGetValues(storageMapSeed), storageMapID); >-} >- >-void StorageManager::setItem(IPC::Connection& connection, WebCore::SecurityOriginData&& securityOriginData, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& value, const String& urlString) >-{ >- StorageArea* storageArea = findStorageArea(connection, storageMapID); >- if (!storageArea) { >- if (m_isEphemeral) { >- if (auto storageMap = m_ephemeralStorage.get(securityOriginData)) { >- String oldValue; >- bool quotaException; >- storageMap->setItem(key, value, oldValue, quotaException); >- } >- } >- // This is a session storage area for a page that has already been closed. Ignore it. >- return; >- } >- >- bool quotaError; >- storageArea->setItem(connection.uniqueID(), sourceStorageAreaID, key, value, urlString, quotaError); >- connection.send(Messages::StorageAreaMap::DidSetItem(storageMapSeed, key, quotaError), storageMapID); >-} >- >-void StorageManager::removeItem(IPC::Connection& connection, WebCore::SecurityOriginData&& securityOriginData, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& urlString) >-{ >- StorageArea* storageArea = findStorageArea(connection, storageMapID); >- if (!storageArea) { >- if (m_isEphemeral) { >- if (auto storageMap = m_ephemeralStorage.get(securityOriginData)) { >- String oldValue; >- storageMap->removeItem(key, oldValue); >- } >- } >- // This is a session storage area for a page that has already been closed. Ignore it. >- return; >- } >- >- storageArea->removeItem(connection.uniqueID(), sourceStorageAreaID, key, urlString); >- connection.send(Messages::StorageAreaMap::DidRemoveItem(storageMapSeed, key), storageMapID); >-} >- >-void StorageManager::clear(IPC::Connection& connection, WebCore::SecurityOriginData&& securityOriginData, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& urlString) >-{ >- StorageArea* storageArea = findStorageArea(connection, storageMapID); >- if (!storageArea) { >- if (m_isEphemeral) >- m_ephemeralStorage.remove(securityOriginData); >- // This is a session storage area for a page that has already been closed. Ignore it. >- return; >- } >- >- storageArea->clear(connection.uniqueID(), sourceStorageAreaID, urlString); >- connection.send(Messages::StorageAreaMap::DidClear(storageMapSeed), storageMapID); >-} >- >-void StorageManager::applicationWillTerminate() >-{ >- BinarySemaphore semaphore; >- m_queue->dispatch([this, &semaphore] { >- Vector<std::pair<IPC::Connection::UniqueID, uint64_t>> connectionAndStorageMapIDPairsToRemove; >- for (auto& connectionStorageAreaPair : m_storageAreasByConnection) { >- connectionStorageAreaPair.value->removeListener(connectionStorageAreaPair.key.first, connectionStorageAreaPair.key.second); >- connectionAndStorageMapIDPairsToRemove.append(connectionStorageAreaPair.key); >- } >- >- for (auto& connectionStorageAreaPair : connectionAndStorageMapIDPairsToRemove) >- m_storageAreasByConnection.remove(connectionStorageAreaPair); >- >- semaphore.signal(); >- }); >- semaphore.wait(); >-} >- >-StorageManager::StorageArea* StorageManager::findStorageArea(IPC::Connection& connection, uint64_t storageMapID) const >-{ >- std::pair<IPC::Connection::UniqueID, uint64_t> connectionAndStorageMapIDPair(connection.uniqueID(), storageMapID); >- >- if (!m_storageAreasByConnection.isValidKey(connectionAndStorageMapIDPair)) >- return nullptr; >- >- return m_storageAreasByConnection.get(connectionAndStorageMapIDPair); >-} >- >-StorageManager::LocalStorageNamespace* StorageManager::getOrCreateLocalStorageNamespace(uint64_t storageNamespaceID) >-{ >- if (!m_localStorageNamespaces.isValidKey(storageNamespaceID)) >- return nullptr; >- >- auto& slot = m_localStorageNamespaces.add(storageNamespaceID, nullptr).iterator->value; >- if (!slot) >- slot = LocalStorageNamespace::create(this, storageNamespaceID); >- >- return slot.get(); >-} >- >-StorageManager::TransientLocalStorageNamespace* StorageManager::getOrCreateTransientLocalStorageNamespace(uint64_t storageNamespaceID, WebCore::SecurityOriginData&& topLevelOrigin) >-{ >- if (!m_transientLocalStorageNamespaces.isValidKey({ storageNamespaceID, topLevelOrigin })) >- return nullptr; >- >- auto& slot = m_transientLocalStorageNamespaces.add({ storageNamespaceID, WTFMove(topLevelOrigin) }, nullptr).iterator->value; >- if (!slot) >- slot = TransientLocalStorageNamespace::create(); >- >- return slot.get(); >-} >- >-} // namespace WebKit >diff --git a/Source/WebKit/UIProcess/WebStorage/StorageManager.h b/Source/WebKit/UIProcess/WebStorage/StorageManager.h >deleted file mode 100644 >index d6f62a0f49e6f062f58ddac7a2e123fb45453f1c..0000000000000000000000000000000000000000 >--- a/Source/WebKit/UIProcess/WebStorage/StorageManager.h >+++ /dev/null >@@ -1,117 +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. >- */ >- >-#pragma once >- >-#include "Connection.h" >-#include "LocalStorageDatabaseTracker.h" >-#include <WebCore/SecurityOriginData.h> >-#include <WebCore/StorageMap.h> >-#include <wtf/Forward.h> >-#include <wtf/Function.h> >-#include <wtf/HashSet.h> >-#include <wtf/ThreadSafeRefCounted.h> >-#include <wtf/text/StringHash.h> >- >-namespace WebCore { >-class SecurityOrigin; >-} >- >-namespace WebKit { >- >-class LocalStorageDatabaseTracker; >-class WebProcessProxy; >- >-class StorageManager : public IPC::Connection::WorkQueueMessageReceiver { >-public: >- static Ref<StorageManager> create(const String& localStorageDirectory); >- ~StorageManager(); >- >- void createSessionStorageNamespace(uint64_t storageNamespaceID, unsigned quotaInBytes); >- void destroySessionStorageNamespace(uint64_t storageNamespaceID); >- void addAllowedSessionStorageNamespaceConnection(uint64_t storageNamespaceID, IPC::Connection&); >- void removeAllowedSessionStorageNamespaceConnection(uint64_t storageNamespaceID, IPC::Connection&); >- void cloneSessionStorageNamespace(uint64_t storageNamespaceID, uint64_t newStorageNamespaceID); >- >- void processWillOpenConnection(WebProcessProxy&, IPC::Connection&); >- void processDidCloseConnection(WebProcessProxy&, IPC::Connection&); >- void applicationWillTerminate(); >- >- void getSessionStorageOrigins(Function<void(HashSet<WebCore::SecurityOriginData>&&)>&& completionHandler); >- void deleteSessionStorageOrigins(Function<void()>&& completionHandler); >- void deleteSessionStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>&, Function<void()>&& completionHandler); >- >- void getLocalStorageOrigins(Function<void(HashSet<WebCore::SecurityOriginData>&&)>&& completionHandler); >- void deleteLocalStorageEntriesForOrigin(const WebCore::SecurityOriginData&); >- >- void deleteLocalStorageOriginsModifiedSince(WallTime, Function<void()>&& completionHandler); >- void deleteLocalStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>&, Function<void()>&& completionHandler); >- >- void getLocalStorageOriginDetails(Function<void(Vector<LocalStorageDatabaseTracker::OriginDetails>)>&& completionHandler); >- >-private: >- explicit StorageManager(const String& localStorageDirectory); >- >- // IPC::Connection::WorkQueueMessageReceiver. >- void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override; >- void didReceiveSyncMessage(IPC::Connection&, IPC::Decoder&, std::unique_ptr<IPC::Encoder>& replyEncoder) override; >- >- // Message handlers. >- void createLocalStorageMap(IPC::Connection&, uint64_t storageMapID, uint64_t storageNamespaceID, WebCore::SecurityOriginData&&); >- void createTransientLocalStorageMap(IPC::Connection&, uint64_t storageMapID, uint64_t storageNamespaceID, WebCore::SecurityOriginData&& topLevelOriginData, WebCore::SecurityOriginData&&); >- void createSessionStorageMap(IPC::Connection&, uint64_t storageMapID, uint64_t storageNamespaceID, WebCore::SecurityOriginData&&); >- void destroyStorageMap(IPC::Connection&, uint64_t storageMapID); >- >- void getValues(IPC::Connection&, WebCore::SecurityOriginData&&, uint64_t storageMapID, uint64_t storageMapSeed, CompletionHandler<void(const HashMap<String, String>&)>&&); >- void setItem(IPC::Connection&, WebCore::SecurityOriginData&&, uint64_t storageAreaID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& value, const String& urlString); >- void removeItem(IPC::Connection&, WebCore::SecurityOriginData&&, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& urlString); >- void clear(IPC::Connection&, WebCore::SecurityOriginData&&, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& urlString); >- >- class StorageArea; >- StorageArea* findStorageArea(IPC::Connection&, uint64_t) const; >- >- class LocalStorageNamespace; >- LocalStorageNamespace* getOrCreateLocalStorageNamespace(uint64_t storageNamespaceID); >- >- class TransientLocalStorageNamespace; >- TransientLocalStorageNamespace* getOrCreateTransientLocalStorageNamespace(uint64_t storageNamespaceID, WebCore::SecurityOriginData&& topLevelOrigin); >- >- Ref<WorkQueue> m_queue; >- >- Ref<LocalStorageDatabaseTracker> m_localStorageDatabaseTracker; >- HashMap<uint64_t, RefPtr<LocalStorageNamespace>> m_localStorageNamespaces; >- >- HashMap<std::pair<uint64_t, WebCore::SecurityOriginData>, RefPtr<TransientLocalStorageNamespace>> m_transientLocalStorageNamespaces; >- >- class SessionStorageNamespace; >- HashMap<uint64_t, RefPtr<SessionStorageNamespace>> m_sessionStorageNamespaces; >- >- HashMap<std::pair<IPC::Connection::UniqueID, uint64_t>, RefPtr<StorageArea>> m_storageAreasByConnection; >- >- HashMap<WebCore::SecurityOriginData, Ref<WebCore::StorageMap>> m_ephemeralStorage; >- bool m_isEphemeral { false }; >-}; >- >-} // namespace WebKit >diff --git a/Source/WebKit/UIProcess/WebStorage/StorageManager.messages.in b/Source/WebKit/UIProcess/WebStorage/StorageManager.messages.in >deleted file mode 100644 >index b3b6dbf279803514e535b1e0374db7dbe9969cba..0000000000000000000000000000000000000000 >--- a/Source/WebKit/UIProcess/WebStorage/StorageManager.messages.in >+++ /dev/null >@@ -1,34 +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. >- >-messages -> StorageManager { >- CreateLocalStorageMap(uint64_t storageMapID, uint64_t storageNamespaceID, struct WebCore::SecurityOriginData securityOriginData) WantsConnection >- CreateTransientLocalStorageMap(uint64_t storageMapID, uint64_t storageNamespaceID, struct WebCore::SecurityOriginData topLevelSecurityOriginData, struct WebCore::SecurityOriginData securityOriginData) WantsConnection >- CreateSessionStorageMap(uint64_t storageMapID, uint64_t storageNamespaceID, struct WebCore::SecurityOriginData securityOriginData) WantsConnection >- DestroyStorageMap(uint64_t storageMapID) WantsConnection >- >- GetValues(struct WebCore::SecurityOriginData securityOriginData, uint64_t storageMapID, uint64_t storageMapSeed) -> (HashMap<String, String> values) Synchronous WantsConnection >- >- SetItem(struct WebCore::SecurityOriginData securityOriginData, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, String key, String value, String urlString) WantsConnection >- RemoveItem(struct WebCore::SecurityOriginData securityOriginData, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, String key, String urlString) WantsConnection >- Clear(struct WebCore::SecurityOriginData securityOriginData, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, String urlString) WantsConnection >-} >diff --git a/Source/WebKit/UIProcess/WebStorage/ios/LocalStorageDatabaseTrackerIOS.mm b/Source/WebKit/UIProcess/WebStorage/ios/LocalStorageDatabaseTrackerIOS.mm >deleted file mode 100644 >index 9b01e896360f42c9f5097ff280b7ff615e65414f..0000000000000000000000000000000000000000 >--- a/Source/WebKit/UIProcess/WebStorage/ios/LocalStorageDatabaseTrackerIOS.mm >+++ /dev/null >@@ -1,48 +0,0 @@ >-/* >- * 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 >- * 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 "LocalStorageDatabaseTracker.h" >- >-#if PLATFORM(IOS_FAMILY) >- >-#include "VersionChecks.h" >- >-namespace WebKit { >- >-void LocalStorageDatabaseTracker::platformMaybeExcludeFromBackup() const >-{ >- if (m_hasExcludedFromBackup) >- return; >- >- m_hasExcludedFromBackup = true; >- >- if (linkedOnOrAfter(SDKVersion::FirstToExcludeLocalStorageFromBackup)) >- [[NSURL fileURLWithPath:(NSString *)m_localStorageDirectory isDirectory:YES] setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:nil]; >-} >- >-} // namespace WebKit >- >-#endif >diff --git a/Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm b/Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm >index 716a231883352a08defd667f05375bcb6e947208..c72cdc0f397917ca6c387251867f2a38b3b42e71 100644 >--- a/Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm >+++ b/Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm >@@ -148,6 +148,10 @@ WebsiteDataStoreParameters WebsiteDataStore::parameters() > if (!cookieFile.isEmpty()) > SandboxExtension::createHandleForReadWriteDirectory(FileSystem::directoryName(cookieFile), parameters.cookieStoragePathExtensionHandle); > >+ parameters.localStorageDirectory = resolvedLocalStorageDirectory(); >+ if (!parameters.localStorageDirectory.isEmpty()) >+ SandboxExtension::createHandleForReadWriteDirectory(parameters.localStorageDirectory, parameters.localStorageDirectoryExtensionHandle); >+ > #if ENABLE(INDEXED_DATABASE) > parameters.indexedDatabaseDirectory = resolvedIndexedDatabaseDirectory(); > if (!parameters.indexedDatabaseDirectory.isEmpty()) >@@ -168,9 +172,6 @@ WebsiteDataStoreParameters WebsiteDataStore::parameters() > > void WebsiteDataStore::platformInitialize() > { >- if (!m_storageManager) >- return; >- > if (!terminationObserver) { > ASSERT(dataStoresWithStorageManagers().isEmpty()); > >@@ -181,7 +182,6 @@ void WebsiteDataStore::platformInitialize() > #endif > terminationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:notificationName object:nil queue:nil usingBlock:^(NSNotification *note) { > for (auto& dataStore : dataStoresWithStorageManagers()) { >- dataStore->m_storageManager->applicationWillTerminate(); > #if ENABLE(RESOURCE_LOAD_STATISTICS) > if (dataStore->m_resourceLoadStatistics) > dataStore->m_resourceLoadStatistics->applicationWillTerminate(); >@@ -201,12 +201,6 @@ void WebsiteDataStore::platformDestroy() > m_resourceLoadStatistics->applicationWillTerminate(); > #endif > >- if (!m_storageManager) >- return; >- >- // FIXME: Rename applicationWillTerminate to something that better indicates what StorageManager does (waits for pending writes to finish). >- m_storageManager->applicationWillTerminate(); >- > ASSERT(dataStoresWithStorageManagers().contains(this)); > dataStoresWithStorageManagers().removeFirst(this); > >diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp >index 56e18aaa45abac7c4903b6c8947c7e8f07e9bb2f..4f2d6f5a0f5e6e7f0083b7ed838c5711d7e3174d 100644 >--- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp >+++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp >@@ -35,7 +35,6 @@ > #include "NetworkProcessMessages.h" > #include "ShouldGrandfatherStatistics.h" > #include "StorageAccessStatus.h" >-#include "StorageManager.h" > #include "WebProcessCache.h" > #include "WebProcessMessages.h" > #include "WebProcessPool.h" >@@ -96,7 +95,6 @@ WebsiteDataStore::WebsiteDataStore(Ref<WebsiteDataStoreConfiguration>&& configur > : m_sessionID(sessionID) > , m_resolvedConfiguration(WTFMove(configuration)) > , m_configuration(m_resolvedConfiguration->copy()) >- , m_storageManager(StorageManager::create(m_configuration->localStorageDirectory())) > , m_deviceIdHashSaltStorage(DeviceIdHashSaltStorage::create(isPersistent() ? m_configuration->deviceIdHashSaltsStorageDirectory() : String())) > , m_queue(WorkQueue::create("com.apple.WebKit.WebsiteDataStore")) > , m_sourceApplicationBundleIdentifier(m_configuration->sourceApplicationBundleIdentifier()) >@@ -120,7 +118,6 @@ WebsiteDataStore::WebsiteDataStore(PAL::SessionID sessionID) > : m_sessionID(sessionID) > , m_resolvedConfiguration(WebsiteDataStoreConfiguration::create()) > , m_configuration(m_resolvedConfiguration->copy()) >- , m_storageManager(StorageManager::create({ })) > , m_deviceIdHashSaltStorage(DeviceIdHashSaltStorage::create(isPersistent() ? m_configuration->deviceIdHashSaltsStorageDirectory() : String())) > , m_queue(WorkQueue::create("com.apple.WebKit.WebsiteDataStore")) > #if ENABLE(WEB_AUTHN) >@@ -207,21 +204,6 @@ void WebsiteDataStore::resolveDirectoriesIfNecessary() > } > } > >-void WebsiteDataStore::cloneSessionData(WebPageProxy& sourcePage, WebPageProxy& newPage) >-{ >- auto& sourceDataStore = sourcePage.websiteDataStore(); >- auto& newDataStore = newPage.websiteDataStore(); >- >- // FIXME: Handle this. >- if (&sourceDataStore != &newDataStore) >- return; >- >- if (!sourceDataStore.m_storageManager) >- return; >- >- sourceDataStore.m_storageManager->cloneSessionStorageNamespace(sourcePage.pageID(), newPage.pageID()); >-} >- > enum class ProcessAccessType { > None, > OnlyIfLaunched, >@@ -247,7 +229,17 @@ static ProcessAccessType computeNetworkProcessAccessTypeForDataFetch(OptionSet<W > > if (dataTypes.contains(WebsiteDataType::DOMCache)) > processAccessType = std::max(processAccessType, ProcessAccessType::Launch); >- >+ >+ if (dataTypes.contains(WebsiteDataType::SessionStorage)) >+ processAccessType = std::max(processAccessType, ProcessAccessType::OnlyIfLaunched); >+ >+ if (dataTypes.contains(WebsiteDataType::LocalStorage)) { >+ if (isNonPersistentStore) >+ processAccessType = std::max(processAccessType, ProcessAccessType::OnlyIfLaunched); >+ else >+ processAccessType = std::max(processAccessType, ProcessAccessType::Launch); >+ } >+ > if (dataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !isNonPersistentStore) > processAccessType = std::max(processAccessType, ProcessAccessType::Launch); > >@@ -483,32 +475,6 @@ void WebsiteDataStore::fetchDataAndApply(OptionSet<WebsiteDataType> dataTypes, O > } > } > >- if (dataTypes.contains(WebsiteDataType::SessionStorage) && m_storageManager) { >- callbackAggregator->addPendingCallback(); >- >- m_storageManager->getSessionStorageOrigins([callbackAggregator](HashSet<WebCore::SecurityOriginData>&& origins) { >- WebsiteData websiteData; >- >- while (!origins.isEmpty()) >- websiteData.entries.append(WebsiteData::Entry { origins.takeAny(), WebsiteDataType::SessionStorage, 0 }); >- >- callbackAggregator->removePendingCallback(WTFMove(websiteData)); >- }); >- } >- >- if (dataTypes.contains(WebsiteDataType::LocalStorage) && m_storageManager) { >- callbackAggregator->addPendingCallback(); >- >- m_storageManager->getLocalStorageOrigins([callbackAggregator](HashSet<WebCore::SecurityOriginData>&& origins) { >- WebsiteData websiteData; >- >- while (!origins.isEmpty()) >- websiteData.entries.append(WebsiteData::Entry { origins.takeAny(), WebsiteDataType::LocalStorage, 0 }); >- >- callbackAggregator->removePendingCallback(WTFMove(websiteData)); >- }); >- } >- > if (dataTypes.contains(WebsiteDataType::DeviceIdHashSalt)) { > callbackAggregator->addPendingCallback(); > >@@ -821,22 +787,6 @@ void WebsiteDataStore::removeData(OptionSet<WebsiteDataType> dataTypes, WallTime > } > } > >- if (dataTypes.contains(WebsiteDataType::SessionStorage) && m_storageManager) { >- callbackAggregator->addPendingCallback(); >- >- m_storageManager->deleteSessionStorageOrigins([callbackAggregator] { >- callbackAggregator->removePendingCallback(); >- }); >- } >- >- if (dataTypes.contains(WebsiteDataType::LocalStorage) && m_storageManager) { >- callbackAggregator->addPendingCallback(); >- >- m_storageManager->deleteLocalStorageOriginsModifiedSince(modifiedSince, [callbackAggregator] { >- callbackAggregator->removePendingCallback(); >- }); >- } >- > if (dataTypes.contains(WebsiteDataType::DeviceIdHashSalt) || (dataTypes.contains(WebsiteDataType::Cookies))) { > callbackAggregator->addPendingCallback(); > >@@ -1101,22 +1051,6 @@ void WebsiteDataStore::removeData(OptionSet<WebsiteDataType> dataTypes, const Ve > } > } > >- if (dataTypes.contains(WebsiteDataType::SessionStorage) && m_storageManager) { >- callbackAggregator->addPendingCallback(); >- >- m_storageManager->deleteSessionStorageEntriesForOrigins(origins, [callbackAggregator] { >- callbackAggregator->removePendingCallback(); >- }); >- } >- >- if (dataTypes.contains(WebsiteDataType::LocalStorage) && m_storageManager) { >- callbackAggregator->addPendingCallback(); >- >- m_storageManager->deleteLocalStorageEntriesForOrigins(origins, [callbackAggregator] { >- callbackAggregator->removePendingCallback(); >- }); >- } >- > if (dataTypes.contains(WebsiteDataType::DeviceIdHashSalt) || (dataTypes.contains(WebsiteDataType::Cookies))) { > callbackAggregator->addPendingCallback(); > >@@ -1795,21 +1729,13 @@ void WebsiteDataStore::deleteCookiesForTesting(const URL& url, bool includeHttpO > > void WebsiteDataStore::hasLocalStorageForTesting(const URL& url, CompletionHandler<void(bool)>&& completionHandler) const > { >- if (!m_storageManager) { >- completionHandler(false); >- return; >- } >- >- m_storageManager->getLocalStorageOrigins([url, completionHandler = WTFMove(completionHandler)](HashSet<WebCore::SecurityOriginData>&& origins) mutable { >- for (auto& origin : origins) { >- if (origin.host == url.host()) { >- completionHandler(true); >- return; >- } >+ for (auto& processPool : processPools()) { >+ if (auto* networkProcess = processPool->networkProcess()) { >+ networkProcess->hasLocalStorage(m_sessionID, WebCore::RegistrableDomain { url }, WTFMove(completionHandler)); >+ ASSERT(processPools().size() == 1); >+ break; > } >- >- completionHandler(false); >- }); >+ } > } > #endif // ENABLE(RESOURCE_LOAD_STATISTICS) > >@@ -1840,42 +1766,6 @@ void WebsiteDataStore::resetCacheMaxAgeCapForPrevalentResources(CompletionHandle > #endif > } > >-void WebsiteDataStore::webPageWasAdded(WebPageProxy& webPageProxy) >-{ >- if (m_storageManager) >- m_storageManager->createSessionStorageNamespace(webPageProxy.pageID(), std::numeric_limits<unsigned>::max()); >-} >- >-void WebsiteDataStore::webPageWasInvalidated(WebPageProxy& webPageProxy) >-{ >- if (m_storageManager) >- m_storageManager->destroySessionStorageNamespace(webPageProxy.pageID()); >-} >- >-void WebsiteDataStore::webProcessWillOpenConnection(WebProcessProxy& webProcessProxy, IPC::Connection& connection) >-{ >- if (m_storageManager) >- m_storageManager->processWillOpenConnection(webProcessProxy, connection); >-} >- >-void WebsiteDataStore::webPageWillOpenConnection(WebPageProxy& webPageProxy, IPC::Connection& connection) >-{ >- if (m_storageManager) >- m_storageManager->addAllowedSessionStorageNamespaceConnection(webPageProxy.pageID(), connection); >-} >- >-void WebsiteDataStore::webPageDidCloseConnection(WebPageProxy& webPageProxy, IPC::Connection& connection) >-{ >- if (m_storageManager) >- m_storageManager->removeAllowedSessionStorageNamespaceConnection(webPageProxy.pageID(), connection); >-} >- >-void WebsiteDataStore::webProcessDidCloseConnection(WebProcessProxy& webProcessProxy, IPC::Connection& connection) >-{ >- if (m_storageManager) >- m_storageManager->processDidCloseConnection(webProcessProxy, connection); >-} >- > bool WebsiteDataStore::isAssociatedProcessPool(WebProcessPool& processPool) const > { > if (auto* processPoolDataStore = processPool.websiteDataStore()) >@@ -2107,6 +1997,10 @@ WebsiteDataStoreParameters WebsiteDataStore::parameters() > > resolveDirectoriesIfNecessary(); > >+ parameters.localStorageDirectory = resolvedLocalStorageDirectory(); >+ if (!parameters.localStorageDirectory.isEmpty()) >+ SandboxExtension::createHandleForReadWriteDirectory(parameters.localStorageDirectory, parameters.localStorageDirectoryExtensionHandle); >+ > #if ENABLE(INDEXED_DATABASE) > parameters.indexedDatabaseDirectory = resolvedIndexedDatabaseDirectory(); > if (!parameters.indexedDatabaseDirectory.isEmpty()) >@@ -2182,4 +2076,19 @@ bool WebsiteDataStore::setSourceApplicationBundleIdentifier(String&& identifier) > return true; > } > >+void WebsiteDataStore::getLocalStorageDetails(Function<void(Vector<LocalStorageDatabaseTracker::OriginDetails>)>&& completionHandler) >+{ >+ if (!isPersistent()) { >+ completionHandler({ }); >+ return; >+ } >+ >+ for (auto& processPool : processPools()) { >+ processPool->ensureNetworkProcess(this); >+ processPool->networkProcess()->getLocalStorageDetails(m_sessionID, [completionHandler = WTFMove(completionHandler)](auto details) { >+ completionHandler(details); >+ }); >+ } >+} >+ > } >diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h >index 77f048a454f34e5e0916fa190ad11293069afc6f..df9531c0e75d58640af4d73f70330ede6c7f7009 100644 >--- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h >+++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h >@@ -25,6 +25,7 @@ > > #pragma once > >+#include "LocalStorageDatabaseTracker.h" > #include "NetworkSessionCreationParameters.h" > #include "WebDeviceOrientationAndMotionAccessController.h" > #include "WebProcessLifetimeObserver.h" >@@ -71,7 +72,6 @@ namespace WebKit { > > class AuthenticatorManager; > class SecKeyProxyStore; >-class StorageManager; > class DeviceIdHashSaltStorage; > class WebPageProxy; > class WebProcessPool; >@@ -122,12 +122,12 @@ public: > void clearResourceLoadStatisticsInWebProcesses(CompletionHandler<void()>&&); > #endif > >- static void cloneSessionData(WebPageProxy& sourcePage, WebPageProxy& newPage); >- > void fetchData(OptionSet<WebsiteDataType>, OptionSet<WebsiteDataFetchOption>, Function<void(Vector<WebsiteDataRecord>)>&& completionHandler); > void removeData(OptionSet<WebsiteDataType>, WallTime modifiedSince, Function<void()>&& completionHandler); > void removeData(OptionSet<WebsiteDataType>, const Vector<WebsiteDataRecord>&, Function<void()>&& completionHandler); > >+ void getLocalStorageDetails(Function<void(Vector<LocalStorageDatabaseTracker::OriginDetails>)>&&); >+ > #if ENABLE(RESOURCE_LOAD_STATISTICS) > void fetchDataForRegistrableDomains(OptionSet<WebsiteDataType>, OptionSet<WebsiteDataFetchOption>, const Vector<WebCore::RegistrableDomain>&, CompletionHandler<void(Vector<WebsiteDataRecord>&&, HashSet<WebCore::RegistrableDomain>&&)>&&); > void clearPrevalentResource(const URL&, CompletionHandler<void()>&&); >@@ -179,6 +179,7 @@ public: > void resetCacheMaxAgeCapForPrevalentResources(CompletionHandler<void()>&&); > void resolveDirectoriesIfNecessary(); > const String& resolvedApplicationCacheDirectory() const { return m_resolvedConfiguration->applicationCacheDirectory(); } >+ const String& resolvedLocalStorageDirectory() const { return m_resolvedConfiguration->localStorageDirectory(); } > const String& resolvedMediaCacheDirectory() const { return m_resolvedConfiguration->mediaCacheDirectory(); } > const String& resolvedMediaKeysDirectory() const { return m_resolvedConfiguration->mediaKeysStorageDirectory(); } > const String& resolvedDatabaseDirectory() const { return m_resolvedConfiguration->webSQLDatabaseDirectory(); } >@@ -188,8 +189,6 @@ public: > const String& resolvedServiceWorkerRegistrationDirectory() const { return m_resolvedConfiguration->serviceWorkerRegistrationDirectory(); } > const String& resolvedResourceLoadStatisticsDirectory() const { return m_resolvedConfiguration->resourceLoadStatisticsDirectory(); } > >- StorageManager* storageManager() { return m_storageManager.get(); } >- > DeviceIdHashSaltStorage& deviceIdHashSaltStorage() { return m_deviceIdHashSaltStorage.get(); } > > WebProcessPool* processPoolForCookieStorageOperations(); >@@ -265,14 +264,6 @@ private: > > void fetchDataAndApply(OptionSet<WebsiteDataType>, OptionSet<WebsiteDataFetchOption>, RefPtr<WorkQueue>&&, Function<void(Vector<WebsiteDataRecord>)>&& apply); > >- // WebProcessLifetimeObserver. >- void webPageWasAdded(WebPageProxy&) override; >- void webPageWasInvalidated(WebPageProxy&) override; >- void webProcessWillOpenConnection(WebProcessProxy&, IPC::Connection&) override; >- void webPageWillOpenConnection(WebPageProxy&, IPC::Connection&) override; >- void webPageDidCloseConnection(WebPageProxy&, IPC::Connection&) override; >- void webProcessDidCloseConnection(WebProcessProxy&, IPC::Connection&) override; >- > void platformInitialize(); > void platformDestroy(); > static void platformRemoveRecentSearches(WallTime); >@@ -299,7 +290,6 @@ private: > Ref<const WebsiteDataStoreConfiguration> m_configuration; > bool m_hasResolvedDirectories { false }; > >- const RefPtr<StorageManager> m_storageManager; > const Ref<DeviceIdHashSaltStorage> m_deviceIdHashSaltStorage; > > #if ENABLE(RESOURCE_LOAD_STATISTICS) >diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj >index 26c05c7469e68f7fb24c47086cab523fb42536e0..a0c873b669a7b42d2e0b8c3af49fd2531fa1069a 100644 >--- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj >+++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj >@@ -152,7 +152,6 @@ > 1A179780137EE82C00F97D45 /* PluginCreationParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A17977E137EE82C00F97D45 /* PluginCreationParameters.h */; }; > 1A1B0EB618A424950038481A /* WKNavigationResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A1B0EB418A424950038481A /* WKNavigationResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; > 1A1B0EB818A424CD0038481A /* WKNavigationResponseInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A1B0EB718A424CD0038481A /* WKNavigationResponseInternal.h */; }; >- 1A1D8BA21731A36300141DA4 /* LocalStorageDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A1D8BA01731A36300141DA4 /* LocalStorageDatabase.h */; }; > 1A1DC340196346D700FF7059 /* LegacySessionStateCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 31607F3819627002009B87DA /* LegacySessionStateCoding.h */; }; > 1A1E093418861D3800D2DC49 /* WebProgressTrackerClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A1E093218861D3800D2DC49 /* WebProgressTrackerClient.h */; }; > 1A1EC69E1872092100B951F0 /* ImportanceAssertion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A1EC69D1872092100B951F0 /* ImportanceAssertion.h */; }; >@@ -195,7 +194,6 @@ > 1A445BA1184D5FC1004B3414 /* WKContextHistoryClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A445BA0184D5FC1004B3414 /* WKContextHistoryClient.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 1A445BA3184D5FCF004B3414 /* WKContextDownloadClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A445BA2184D5FCF004B3414 /* WKContextDownloadClient.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 1A445BA5184D5FDA004B3414 /* WKContextConnectionClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A445BA4184D5FDA004B3414 /* WKContextConnectionClient.h */; settings = {ATTRIBUTES = (Private, ); }; }; >- 1A44B95C16B73F9F00B7BBD8 /* StorageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A44B95A16B73F9F00B7BBD8 /* StorageManager.h */; }; > 1A4832CC1A9BC465008B4DFE /* WKWebsiteDataRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A4832CA1A9BC465008B4DFE /* WKWebsiteDataRecord.h */; settings = {ATTRIBUTES = (Public, ); }; }; > 1A4832CE1A9BC484008B4DFE /* WKWebsiteDataRecordInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A4832CD1A9BC484008B4DFE /* WKWebsiteDataRecordInternal.h */; }; > 1A4832D11A9BDC2F008B4DFE /* WebsiteDataRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A4832CF1A9BD821008B4DFE /* WebsiteDataRecord.h */; }; >@@ -245,7 +243,6 @@ > 1A85E4721E303F3700914599 /* WebKit.apinotes in Headers */ = {isa = PBXBuildFile; fileRef = 1A85E4701E303F2400914599 /* WebKit.apinotes */; settings = {ATTRIBUTES = (Public, ); }; }; > 1A8B66B01BC43C860082DF77 /* PageLoadStateObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A8B66AE1BC43C860082DF77 /* PageLoadStateObserver.h */; }; > 1A8B66B41BC45B010082DF77 /* WKBundleMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A8B66B21BC45B010082DF77 /* WKBundleMac.h */; settings = {ATTRIBUTES = (Private, ); }; }; >- 1A8C728D1738477C000A6554 /* LocalStorageDatabaseTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A8C728B1738477C000A6554 /* LocalStorageDatabaseTracker.h */; }; > 1A8E7D3C18C15149005A702A /* VisitedLinkTableControllerMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A8E7D3A18C15149005A702A /* VisitedLinkTableControllerMessageReceiver.cpp */; }; > 1A8E7D3D18C15149005A702A /* VisitedLinkTableControllerMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A8E7D3B18C15149005A702A /* VisitedLinkTableControllerMessages.h */; }; > 1A8EF4CB1252403700F7067F /* PluginControllerProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A8EF4C91252403700F7067F /* PluginControllerProxy.h */; }; >@@ -1257,6 +1254,9 @@ > 93A88B331BC6E9CD00ABA5C2 /* WebHitTestResultData.h in Headers */ = {isa = PBXBuildFile; fileRef = 93A88B311BC6E9C000ABA5C2 /* WebHitTestResultData.h */; }; > 93A88B3B1BC710D900ABA5C2 /* _WKHitTestResultInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 93A88B3A1BC710D900ABA5C2 /* _WKHitTestResultInternal.h */; }; > 93A88B461BC8829300ABA5C2 /* APIHitTestResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 93A88B431BC8828C00ABA5C2 /* APIHitTestResult.h */; }; >+ 93B2614D227D149E00B97A76 /* StorageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 93B26149227D147200B97A76 /* StorageManager.h */; }; >+ 93B2614E227D14B100B97A76 /* LocalStorageDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 93B26145227D147000B97A76 /* LocalStorageDatabase.h */; }; >+ 93B2614F227D14B100B97A76 /* LocalStorageDatabaseTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 93B26146227D147100B97A76 /* LocalStorageDatabaseTracker.h */; }; > 93BDEB01171DD7AF00BFEE1B /* WKPageLoadTypesPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 93BDEB00171DD7AF00BFEE1B /* WKPageLoadTypesPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 93E6A4EE1BC5DD3900F8A0E7 /* _WKHitTestResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 93E6A4ED1BC5DD3900F8A0E7 /* _WKHitTestResult.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 93F549B41E3174B7000E7239 /* WKSnapshotConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 93F549B31E3174B7000E7239 /* WKSnapshotConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; >@@ -2016,8 +2016,6 @@ > 1A1B0EB718A424CD0038481A /* WKNavigationResponseInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKNavigationResponseInternal.h; sourceTree = "<group>"; }; > 1A1D2116191D995C0001619F /* postprocess-framework-headers.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = "postprocess-framework-headers.sh"; path = "mac/postprocess-framework-headers.sh"; sourceTree = "<group>"; }; > 1A1D2117191D996C0001619F /* MigrateHeadersFromWebKitLegacy.make */ = {isa = PBXFileReference; lastKnownFileType = text; name = MigrateHeadersFromWebKitLegacy.make; path = mac/MigrateHeadersFromWebKitLegacy.make; sourceTree = "<group>"; }; >- 1A1D8B9F1731A36300141DA4 /* LocalStorageDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LocalStorageDatabase.cpp; sourceTree = "<group>"; }; >- 1A1D8BA01731A36300141DA4 /* LocalStorageDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalStorageDatabase.h; sourceTree = "<group>"; }; > 1A1E093118861D3800D2DC49 /* WebProgressTrackerClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebProgressTrackerClient.cpp; sourceTree = "<group>"; }; > 1A1E093218861D3800D2DC49 /* WebProgressTrackerClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebProgressTrackerClient.h; sourceTree = "<group>"; }; > 1A1EC69D1872092100B951F0 /* ImportanceAssertion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImportanceAssertion.h; sourceTree = "<group>"; }; >@@ -2094,8 +2092,6 @@ > 1A445BA0184D5FC1004B3414 /* WKContextHistoryClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKContextHistoryClient.h; sourceTree = "<group>"; }; > 1A445BA2184D5FCF004B3414 /* WKContextDownloadClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKContextDownloadClient.h; sourceTree = "<group>"; }; > 1A445BA4184D5FDA004B3414 /* WKContextConnectionClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKContextConnectionClient.h; sourceTree = "<group>"; }; >- 1A44B95916B73F9F00B7BBD8 /* StorageManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StorageManager.cpp; sourceTree = "<group>"; }; >- 1A44B95A16B73F9F00B7BBD8 /* StorageManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageManager.h; sourceTree = "<group>"; }; > 1A4832C11A965A3C008B4DFE /* WebsiteDataStoreCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebsiteDataStoreCocoa.mm; sourceTree = "<group>"; }; > 1A4832C91A9BC465008B4DFE /* WKWebsiteDataRecord.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebsiteDataRecord.mm; sourceTree = "<group>"; }; > 1A4832CA1A9BC465008B4DFE /* WKWebsiteDataRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKWebsiteDataRecord.h; sourceTree = "<group>"; }; >@@ -2182,8 +2178,6 @@ > 1A8B66AE1BC43C860082DF77 /* PageLoadStateObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageLoadStateObserver.h; sourceTree = "<group>"; }; > 1A8B66B11BC45B010082DF77 /* WKBundleMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKBundleMac.mm; sourceTree = "<group>"; }; > 1A8B66B21BC45B010082DF77 /* WKBundleMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKBundleMac.h; sourceTree = "<group>"; }; >- 1A8C728A1738477C000A6554 /* LocalStorageDatabaseTracker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LocalStorageDatabaseTracker.cpp; sourceTree = "<group>"; }; >- 1A8C728B1738477C000A6554 /* LocalStorageDatabaseTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalStorageDatabaseTracker.h; sourceTree = "<group>"; }; > 1A8E7D3818C150BF005A702A /* VisitedLinkTableController.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VisitedLinkTableController.messages.in; sourceTree = "<group>"; }; > 1A8E7D3A18C15149005A702A /* VisitedLinkTableControllerMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VisitedLinkTableControllerMessageReceiver.cpp; path = DerivedSources/WebKit2/VisitedLinkTableControllerMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; > 1A8E7D3B18C15149005A702A /* VisitedLinkTableControllerMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VisitedLinkTableControllerMessages.h; path = DerivedSources/WebKit2/VisitedLinkTableControllerMessages.h; sourceTree = BUILT_PRODUCTS_DIR; }; >@@ -2279,7 +2273,6 @@ > 1AB1F7931D1B3613007C9BD1 /* WebPaymentCoordinatorMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebPaymentCoordinatorMessages.h; path = DerivedSources/WebKit2/WebPaymentCoordinatorMessages.h; sourceTree = BUILT_PRODUCTS_DIR; }; > 1AB1F7941D1B3613007C9BD1 /* WebPaymentCoordinatorProxyMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebPaymentCoordinatorProxyMessageReceiver.cpp; path = DerivedSources/WebKit2/WebPaymentCoordinatorProxyMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; > 1AB1F7951D1B3613007C9BD1 /* WebPaymentCoordinatorProxyMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebPaymentCoordinatorProxyMessages.h; path = DerivedSources/WebKit2/WebPaymentCoordinatorProxyMessages.h; sourceTree = BUILT_PRODUCTS_DIR; }; >- 1AB31A9316BC65AB00F6DBC9 /* StorageManager.messages.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = StorageManager.messages.in; sourceTree = "<group>"; }; > 1AB31A9416BC688100F6DBC9 /* StorageManagerMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StorageManagerMessageReceiver.cpp; path = DerivedSources/WebKit2/StorageManagerMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; > 1AB31A9516BC688100F6DBC9 /* StorageManagerMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StorageManagerMessages.h; path = DerivedSources/WebKit2/StorageManagerMessages.h; sourceTree = BUILT_PRODUCTS_DIR; }; > 1AB40EE31BF677E300BA81BE /* WKMenuItemIdentifiers.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKMenuItemIdentifiers.mm; sourceTree = "<group>"; }; >@@ -3206,7 +3199,6 @@ > 511F7D401EB1BCEE00E47B83 /* WebsiteDataStoreParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebsiteDataStoreParameters.h; sourceTree = "<group>"; }; > 511F8A77138B460900A95F44 /* SecItemShimLibrary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecItemShimLibrary.h; path = ../../WebProcess/mac/SecItemShimLibrary.h; sourceTree = "<group>"; }; > 511F8A78138B460900A95F44 /* SecItemShimLibrary.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = SecItemShimLibrary.mm; path = ../../WebProcess/mac/SecItemShimLibrary.mm; sourceTree = "<group>"; }; >- 5120C8301E54E2650025B250 /* LocalStorageDatabaseTrackerIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LocalStorageDatabaseTrackerIOS.mm; sourceTree = "<group>"; }; > 5120C8331E5B71570025B250 /* _WKWebsiteDataStoreConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKWebsiteDataStoreConfiguration.h; sourceTree = "<group>"; }; > 5120C8341E5B71570025B250 /* _WKWebsiteDataStoreConfiguration.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKWebsiteDataStoreConfiguration.mm; sourceTree = "<group>"; }; > 512127C11908239A00DAF35C /* WebPasteboardOverrides.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebPasteboardOverrides.cpp; sourceTree = "<group>"; }; >@@ -3846,6 +3838,14 @@ > 93A88B3A1BC710D900ABA5C2 /* _WKHitTestResultInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKHitTestResultInternal.h; sourceTree = "<group>"; }; > 93A88B421BC8828C00ABA5C2 /* APIHitTestResult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = APIHitTestResult.cpp; sourceTree = "<group>"; }; > 93A88B431BC8828C00ABA5C2 /* APIHitTestResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIHitTestResult.h; sourceTree = "<group>"; }; >+ 93B26145227D147000B97A76 /* LocalStorageDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalStorageDatabase.h; sourceTree = "<group>"; }; >+ 93B26146227D147100B97A76 /* LocalStorageDatabaseTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalStorageDatabaseTracker.h; sourceTree = "<group>"; }; >+ 93B26147227D147100B97A76 /* LocalStorageDatabaseTracker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LocalStorageDatabaseTracker.cpp; sourceTree = "<group>"; }; >+ 93B26148227D147100B97A76 /* ios */ = {isa = PBXFileReference; lastKnownFileType = folder; path = ios; sourceTree = "<group>"; }; >+ 93B26149227D147200B97A76 /* StorageManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageManager.h; sourceTree = "<group>"; }; >+ 93B2614A227D147200B97A76 /* StorageManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StorageManager.cpp; sourceTree = "<group>"; }; >+ 93B2614B227D147200B97A76 /* StorageManager.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = StorageManager.messages.in; sourceTree = "<group>"; }; >+ 93B2614C227D147200B97A76 /* LocalStorageDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LocalStorageDatabase.cpp; sourceTree = "<group>"; }; > 93BA04DA2151ADF3007F455F /* WebSWServerConnection.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebSWServerConnection.messages.in; sourceTree = "<group>"; }; > 93BA04DB2151ADF3007F455F /* WebSWServerToContextConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSWServerToContextConnection.h; sourceTree = "<group>"; }; > 93BA04DC2151ADF3007F455F /* WebSWServerToContextConnection.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebSWServerToContextConnection.messages.in; sourceTree = "<group>"; }; >@@ -4892,21 +4892,6 @@ > name = Deprecated; > sourceTree = "<group>"; > }; >- 1A44B95816B73F8C00B7BBD8 /* WebStorage */ = { >- isa = PBXGroup; >- children = ( >- 5120C82D1E54E2040025B250 /* ios */, >- 1A1D8B9F1731A36300141DA4 /* LocalStorageDatabase.cpp */, >- 1A1D8BA01731A36300141DA4 /* LocalStorageDatabase.h */, >- 1A8C728A1738477C000A6554 /* LocalStorageDatabaseTracker.cpp */, >- 1A8C728B1738477C000A6554 /* LocalStorageDatabaseTracker.h */, >- 1A44B95916B73F9F00B7BBD8 /* StorageManager.cpp */, >- 1A44B95A16B73F9F00B7BBD8 /* StorageManager.h */, >- 1AB31A9316BC65AB00F6DBC9 /* StorageManager.messages.in */, >- ); >- path = WebStorage; >- sourceTree = "<group>"; >- }; > 1A4832C01A965A33008B4DFE /* Cocoa */ = { > isa = PBXGroup; > children = ( >@@ -6586,6 +6571,7 @@ > 510CC7DC16138E2900D03ED3 /* mac */, > 93BA04D92151ADCD007F455F /* ServiceWorker */, > 413075971DE84ED70039EC69 /* webrtc */, >+ 93B26143227D143100B97A76 /* WebStorage */, > 6BD05864220CE8C2000BED5C /* AdClickAttributionManager.cpp */, > 6BD05863220CE8C2000BED5C /* AdClickAttributionManager.h */, > 53F3CAA5206C443E0086490E /* NetworkActivityTracker.cpp */, >@@ -6696,14 +6682,6 @@ > path = IndexedDB; > sourceTree = "<group>"; > }; >- 5120C82D1E54E2040025B250 /* ios */ = { >- isa = PBXGroup; >- children = ( >- 5120C8301E54E2650025B250 /* LocalStorageDatabaseTrackerIOS.mm */, >- ); >- path = ios; >- sourceTree = "<group>"; >- }; > 5123CF18133D25E60056F800 /* cg */ = { > isa = PBXGroup; > children = ( >@@ -7178,6 +7156,21 @@ > path = mac; > sourceTree = "<group>"; > }; >+ 93B26143227D143100B97A76 /* WebStorage */ = { >+ isa = PBXGroup; >+ children = ( >+ 93B26148227D147100B97A76 /* ios */, >+ 93B2614C227D147200B97A76 /* LocalStorageDatabase.cpp */, >+ 93B26145227D147000B97A76 /* LocalStorageDatabase.h */, >+ 93B26147227D147100B97A76 /* LocalStorageDatabaseTracker.cpp */, >+ 93B26146227D147100B97A76 /* LocalStorageDatabaseTracker.h */, >+ 93B2614A227D147200B97A76 /* StorageManager.cpp */, >+ 93B26149227D147200B97A76 /* StorageManager.h */, >+ 93B2614B227D147200B97A76 /* StorageManager.messages.in */, >+ ); >+ path = WebStorage; >+ sourceTree = "<group>"; >+ }; > 93BA04D92151ADCD007F455F /* ServiceWorker */ = { > isa = PBXGroup; > children = ( >@@ -7512,7 +7505,6 @@ > 1AAF089E192681AC00B6390C /* UserContent */, > 57608294202BD84900116678 /* WebAuthentication */, > 1A53C2A31A325691004E8C70 /* WebsiteData */, >- 1A44B95816B73F8C00B7BBD8 /* WebStorage */, > 7CD102D91866770600ED429D /* AutoCorrectionCallback.h */, > E1513C64166EABB200149FCB /* AuxiliaryProcessProxy.cpp */, > E1513C65166EABB200149FCB /* AuxiliaryProcessProxy.h */, >@@ -9310,8 +9302,8 @@ > 57DCEDAC214C60270016B847 /* LocalAuthenticator.h in Headers */, > 57DCEDAD214C602C0016B847 /* LocalConnection.h in Headers */, > 57DCEDAE214C60330016B847 /* LocalService.h in Headers */, >- 1A1D8BA21731A36300141DA4 /* LocalStorageDatabase.h in Headers */, >- 1A8C728D1738477C000A6554 /* LocalStorageDatabaseTracker.h in Headers */, >+ 93B2614E227D14B100B97A76 /* LocalStorageDatabase.h in Headers */, >+ 93B2614F227D14B100B97A76 /* LocalStorageDatabaseTracker.h in Headers */, > 51A7F2F3125BF820008AEB1D /* Logging.h in Headers */, > 0FDCD7F71D47E92A009F08BC /* LogInitialization.h in Headers */, > 1A6D86C21DF75265007745E8 /* MachMessage.h in Headers */, >@@ -9527,7 +9519,7 @@ > 1AD3306F16B1D991004F60E7 /* StorageAreaImpl.h in Headers */, > 1ACECD2517162DB1001FC9EF /* StorageAreaMap.h in Headers */, > 1A334DEE16DE8F88006A8E38 /* StorageAreaMapMessages.h in Headers */, >- 1A44B95C16B73F9F00B7BBD8 /* StorageManager.h in Headers */, >+ 93B2614D227D149E00B97A76 /* StorageManager.h in Headers */, > 1AB31A9716BC688100F6DBC9 /* StorageManagerMessages.h in Headers */, > 1AE00D6C18327C1200087DD7 /* StringReference.h in Headers */, > 296BD85D15019BC30071F424 /* StringUtilities.h in Headers */, >diff --git a/Source/WebKit/WebProcess/InjectedBundle/InjectedBundle.cpp b/Source/WebKit/WebProcess/InjectedBundle/InjectedBundle.cpp >index 4de6674bc61e4c9db0dcbf68744e1306efa5044f..c541f92b8fa86f11da074415cfb8fd51e660ac03 100644 >--- a/Source/WebKit/WebProcess/InjectedBundle/InjectedBundle.cpp >+++ b/Source/WebKit/WebProcess/InjectedBundle/InjectedBundle.cpp >@@ -348,8 +348,8 @@ void InjectedBundle::setJavaScriptCanAccessClipboard(WebPageGroupProxy* pageGrou > void InjectedBundle::setPrivateBrowsingEnabled(WebPageGroupProxy* pageGroup, bool enabled) > { > ASSERT(!hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies)); >- if (enabled) >- WebProcess::singleton().ensureLegacyPrivateBrowsingSessionInNetworkProcess(); >+ >+ WebProcess::singleton().setPrivateBrowsingEnabled(enabled); > > const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages(); > for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter) >diff --git a/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp b/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp >index 5ea3cd27a426c3d4c1e4abdfe53bed4ac2e2eabd..57edd9275bd60596044874f40101e4e840fa1883 100644 >--- a/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp >+++ b/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp >@@ -30,6 +30,8 @@ > #include "LibWebRTCNetwork.h" > #include "NetworkConnectionToWebProcessMessages.h" > #include "ServiceWorkerClientFetchMessages.h" >+#include "StorageAreaMap.h" >+#include "StorageAreaMapMessages.h" > #include "WebCacheStorageConnection.h" > #include "WebCacheStorageConnectionMessages.h" > #include "WebCacheStorageProvider.h" >@@ -93,6 +95,11 @@ void NetworkProcessConnection::didReceiveMessage(IPC::Connection& connection, IP > webPage->didReceiveWebPageMessage(connection, decoder); > return; > } >+ if (decoder.messageReceiverName() == Messages::StorageAreaMap::messageReceiverName()) { >+ if (auto* stoargeAreaMap = WebProcess::singleton().storageAreaMap(decoder.destinationID())) >+ stoargeAreaMap->didReceiveMessage(connection, decoder); >+ return; >+ } > > #if USE(LIBWEBRTC) > if (decoder.messageReceiverName() == Messages::WebRTCSocket::messageReceiverName()) { >diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp >index 66e53a2d4e07c8b4e0683ec28a2f89189908a7db..6def9c995dc3d9c6f95392d13feeb9a35fa98c80 100644 >--- a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp >+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp >@@ -296,6 +296,8 @@ Page* WebChromeClient::createWindow(Frame& frame, const FrameLoadRequest& reques > if (!newPageID) > return nullptr; > ASSERT(parameters); >+ if (parameters->sessionID == m_page.sessionID()) >+ parameters->oldPageID = m_page.pageID(); > > webProcess.createWebPage(newPageID, WTFMove(*parameters)); > return webProcess.webPage(newPageID)->corePage(); >diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.cpp b/Source/WebKit/WebProcess/WebPage/WebPage.cpp >index 0104e0063f46cadc91071caffa38ee4e3fe35d6f..e7aa39b6925f8a80dd18c603db12cdff9dc28faa 100644 >--- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp >+++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp >@@ -1390,6 +1390,7 @@ void WebPage::close() > m_mainFrame->coreFrame()->loader().detachFromParent(); > m_drawingArea = nullptr; > >+ PAL::SessionID session(sessionID()); > DeferredPageDestructor::createDeferredPageDestructor(WTFMove(m_page), this); > > bool isRunningModal = m_isRunningModal; >@@ -1417,7 +1418,7 @@ void WebPage::close() > #endif > > // The WebPage can be destroyed by this call. >- WebProcess::singleton().removeWebPage(m_pageID); >+ WebProcess::singleton().removeWebPage(session, m_pageID); > > WebProcess::singleton().updateActivePages(); > >diff --git a/Source/WebKit/WebProcess/WebProcess.cpp b/Source/WebKit/WebProcess/WebProcess.cpp >index 2528387ab3b7a226828030be75252d41ca838a0a..43cc5a9f23fb1e72130e4f9357aaeacfaba2719a 100644 >--- a/Source/WebKit/WebProcess/WebProcess.cpp >+++ b/Source/WebKit/WebProcess/WebProcess.cpp >@@ -42,6 +42,7 @@ > #include "NetworkSessionCreationParameters.h" > #include "PluginProcessConnectionManager.h" > #include "StatisticsData.h" >+#include "StorageAreaMap.h" > #include "UserData.h" > #include "WebAutomationSessionProxy.h" > #include "WebCacheStorageProvider.h" >@@ -56,6 +57,7 @@ > #include "WebMemorySampler.h" > #include "WebMessagePortChannelProvider.h" > #include "WebPage.h" >+#include "WebPageCreationParameters.h" > #include "WebPageGroupProxy.h" > #include "WebPaymentCoordinator.h" > #include "WebPlatformStrategies.h" >@@ -674,6 +676,7 @@ void WebProcess::createWebPage(uint64_t pageID, WebPageCreationParameters&& para > // It is necessary to check for page existence here since during a window.open() (or targeted > // link) the WebPage gets created both in the synchronous handler and through the normal way. > HashMap<uint64_t, RefPtr<WebPage>>::AddResult result = m_pageMap.add(pageID, nullptr); >+ auto oldPageID = parameters.oldPageID ? parameters.oldPageID.value() : pageID; > if (result.isNewEntry) { > ASSERT(!result.iterator->value); > result.iterator->value = WebPage::create(pageID, WTFMove(parameters)); >@@ -684,13 +687,16 @@ void WebProcess::createWebPage(uint64_t pageID, WebPageCreationParameters&& para > } else > result.iterator->value->reinitializeWebPage(WTFMove(parameters)); > >+ ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::WebPageWasAdded(result.iterator->value->sessionID(), pageID, oldPageID), 0); >+ > ASSERT(result.iterator->value); > } > >-void WebProcess::removeWebPage(uint64_t pageID) >+void WebProcess::removeWebPage(PAL::SessionID sessionID, uint64_t pageID) > { > ASSERT(m_pageMap.contains(pageID)); > >+ ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::WebPageWasRemoved(sessionID, pageID), 0); > pageWillLeaveWindow(pageID); > m_pageMap.remove(pageID); > >@@ -1639,6 +1645,39 @@ void WebProcess::nonVisibleProcessCleanupTimerFired() > #endif > } > >+void WebProcess::registerStorageAreaMap(StorageAreaMap& storageAreaMap) >+{ >+ ASSERT(!m_storageAreaMaps.contains(storageAreaMap.identifier())); >+ m_storageAreaMaps.set(storageAreaMap.identifier(), &storageAreaMap); >+} >+ >+void WebProcess::unregisterStorageAreaMap(StorageAreaMap& storageAreaMap) >+{ >+ ASSERT(m_storageAreaMaps.contains(storageAreaMap.identifier())); >+ ASSERT(m_storageAreaMaps.get(storageAreaMap.identifier()) == &storageAreaMap); >+ m_storageAreaMaps.remove(storageAreaMap.identifier()); >+} >+ >+StorageAreaMap* WebProcess::storageAreaMap(uint64_t identifier) const >+{ >+ ASSERT(m_storageAreaMaps.contains(identifier)); >+ return m_storageAreaMaps.get(identifier); >+} >+ >+void WebProcess::setPrivateBrowsingEnabled(bool enabled) >+{ >+ if (m_privateBrowsingEnabled == enabled) >+ return; >+ >+ if (enabled) >+ ensureLegacyPrivateBrowsingSessionInNetworkProcess(); >+ >+ if (!m_pageMap.isEmpty()) >+ ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::webProcessSessionChanged(enabled ? PAL::SessionID::legacyPrivateSessionID() : PAL::SessionID::defaultSessionID(), copyToVector(m_pageMap.keys())), 0); >+ >+ m_privateBrowsingEnabled = enabled; >+} >+ > void WebProcess::setResourceLoadStatisticsEnabled(bool enabled) > { > WebCore::DeprecatedGlobalSettings::setResourceLoadStatisticsEnabled(enabled); >diff --git a/Source/WebKit/WebProcess/WebProcess.h b/Source/WebKit/WebProcess/WebProcess.h >index 30bd59a715297470d3e2932959957e6d4e2a60d4..15e0500f513cd5803684d34c2a13eed166f2625b 100644 >--- a/Source/WebKit/WebProcess/WebProcess.h >+++ b/Source/WebKit/WebProcess/WebProcess.h >@@ -97,6 +97,7 @@ class InjectedBundle; > class LibWebRTCNetwork; > class NetworkProcessConnection; > class ObjCObjectGraph; >+class StorageAreaMap; > class UserData; > class WaylandCompositorDisplay; > class WebAutomationSessionProxy; >@@ -146,7 +147,7 @@ public: > > WebPage* webPage(uint64_t pageID) const; > void createWebPage(uint64_t pageID, WebPageCreationParameters&&); >- void removeWebPage(uint64_t pageID); >+ void removeWebPage(PAL::SessionID, uint64_t pageID); > WebPage* focusedWebPage() const; > > InjectedBundle* injectedBundle() const { return m_injectedBundle.get(); } >@@ -203,6 +204,12 @@ public: > > void nonVisibleProcessCleanupTimerFired(); > >+ void registerStorageAreaMap(StorageAreaMap&); >+ void unregisterStorageAreaMap(StorageAreaMap&); >+ StorageAreaMap* storageAreaMap(uint64_t identifier) const; >+ >+ void setPrivateBrowsingEnabled(bool); >+ > #if PLATFORM(COCOA) > RetainPtr<CFDataRef> sourceApplicationAuditData() const; > void destroyRenderingResources(); >@@ -457,6 +464,9 @@ private: > RefPtr<InjectedBundle> m_injectedBundle; > > Ref<EventDispatcher> m_eventDispatcher; >+ >+ HashMap<uint64_t, StorageAreaMap*> m_storageAreaMaps; >+ > #if PLATFORM(IOS_FAMILY) > RefPtr<ViewUpdateDispatcher> m_viewUpdateDispatcher; > #endif >@@ -553,6 +563,8 @@ private: > #if PLATFORM(IOS) > float m_backlightLevel { 0 }; > #endif >+ >+ bool m_privateBrowsingEnabled { false }; > }; > > } // namespace WebKit >diff --git a/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.cpp b/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.cpp >index c3176c7acb59cf81ead021d53032da6f3b542746..fcd3f3d994dfbdc7075c9f41d43bf7764dd5e752 100644 >--- a/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.cpp >+++ b/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.cpp >@@ -26,6 +26,7 @@ > #include "config.h" > #include "StorageAreaMap.h" > >+#include "NetworkProcessConnection.h" > #include "StorageAreaImpl.h" > #include "StorageAreaMapMessages.h" > #include "StorageManagerMessages.h" >@@ -73,14 +74,14 @@ StorageAreaMap::StorageAreaMap(StorageNamespaceImpl* storageNamespace, Ref<WebCo > case StorageType::Local: > case StorageType::TransientLocal: > if (SecurityOrigin* topLevelOrigin = storageNamespace->topLevelOrigin()) >- WebProcess::singleton().parentProcessConnection()->send(Messages::StorageManager::CreateTransientLocalStorageMap(m_storageMapID, storageNamespace->storageNamespaceID(), topLevelOrigin->data(), m_securityOrigin->data()), 0); >+ WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManager::CreateTransientLocalStorageMap(m_storageMapID, storageNamespace->storageNamespaceID(), topLevelOrigin->data(), m_securityOrigin->data()), 0); > else >- WebProcess::singleton().parentProcessConnection()->send(Messages::StorageManager::CreateLocalStorageMap(m_storageMapID, storageNamespace->storageNamespaceID(), m_securityOrigin->data()), 0); >+ WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManager::CreateLocalStorageMap(m_storageMapID, storageNamespace->storageNamespaceID(), m_securityOrigin->data()), 0); > > break; > > case StorageType::Session: >- WebProcess::singleton().parentProcessConnection()->send(Messages::StorageManager::CreateSessionStorageMap(m_storageMapID, storageNamespace->storageNamespaceID(), m_securityOrigin->data()), 0); >+ WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManager::CreateSessionStorageMap(m_storageMapID, storageNamespace->storageNamespaceID(), m_securityOrigin->data()), 0); > break; > > case StorageType::EphemeralLocal: >@@ -88,17 +89,17 @@ StorageAreaMap::StorageAreaMap(StorageNamespaceImpl* storageNamespace, Ref<WebCo > return; > } > >- WebProcess::singleton().addMessageReceiver(Messages::StorageAreaMap::messageReceiverName(), m_storageMapID, *this); >+ WebProcess::singleton().registerStorageAreaMap(*this); > } > > StorageAreaMap::~StorageAreaMap() > { >- if (m_storageType != StorageType::EphemeralLocal) { >- WebProcess::singleton().parentProcessConnection()->send(Messages::StorageManager::DestroyStorageMap(m_storageMapID), 0); >- WebProcess::singleton().removeMessageReceiver(Messages::StorageAreaMap::messageReceiverName(), m_storageMapID); >- } >+ if (m_storageType != StorageType::EphemeralLocal) >+ WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManager::DestroyStorageMap(m_storageMapID), 0); > > m_storageNamespace->didDestroyStorageAreaMap(*this); >+ >+ WebProcess::singleton().unregisterStorageAreaMap(*this); > } > > unsigned StorageAreaMap::length() >@@ -139,7 +140,7 @@ void StorageAreaMap::setItem(Frame* sourceFrame, StorageAreaImpl* sourceArea, co > > m_pendingValueChanges.add(key); > >- WebProcess::singleton().parentProcessConnection()->send(Messages::StorageManager::SetItem(m_securityOrigin->data(), m_storageMapID, sourceArea->storageAreaID(), m_currentSeed, key, value, sourceFrame->document()->url()), 0); >+ WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManager::SetItem(m_securityOrigin->data(), m_storageMapID, sourceArea->storageAreaID(), m_currentSeed, key, value, sourceFrame->document()->url()), 0); > } > > void StorageAreaMap::removeItem(WebCore::Frame* sourceFrame, StorageAreaImpl* sourceArea, const String& key) >@@ -155,7 +156,7 @@ void StorageAreaMap::removeItem(WebCore::Frame* sourceFrame, StorageAreaImpl* so > > m_pendingValueChanges.add(key); > >- WebProcess::singleton().parentProcessConnection()->send(Messages::StorageManager::RemoveItem(m_securityOrigin->data(), m_storageMapID, sourceArea->storageAreaID(), m_currentSeed, key, sourceFrame->document()->url()), 0); >+ WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManager::RemoveItem(m_securityOrigin->data(), m_storageMapID, sourceArea->storageAreaID(), m_currentSeed, key, sourceFrame->document()->url()), 0); > } > > void StorageAreaMap::clear(WebCore::Frame* sourceFrame, StorageAreaImpl* sourceArea) >@@ -164,7 +165,7 @@ void StorageAreaMap::clear(WebCore::Frame* sourceFrame, StorageAreaImpl* sourceA > > m_hasPendingClear = true; > m_storageMap = StorageMap::create(m_quotaInBytes); >- WebProcess::singleton().parentProcessConnection()->send(Messages::StorageManager::Clear(m_securityOrigin->data(), m_storageMapID, sourceArea->storageAreaID(), m_currentSeed, sourceFrame->document()->url()), 0); >+ WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManager::Clear(m_securityOrigin->data(), m_storageMapID, sourceArea->storageAreaID(), m_currentSeed, sourceFrame->document()->url()), 0); > } > > bool StorageAreaMap::contains(const String& key) >@@ -193,7 +194,7 @@ void StorageAreaMap::loadValuesIfNeeded() > // FIXME: This should use a special sendSync flag to indicate that we don't want to process incoming messages while waiting for a reply. > // (This flag does not yet exist). Since loadValuesIfNeeded() ends up being called from within JavaScript code, processing incoming synchronous messages > // could lead to weird reentrency bugs otherwise. >- WebProcess::singleton().parentProcessConnection()->sendSync(Messages::StorageManager::GetValues(m_securityOrigin->data(), m_storageMapID, m_currentSeed), Messages::StorageManager::GetValues::Reply(values), 0); >+ WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::StorageManager::GetValues(m_securityOrigin->data(), m_storageMapID, m_currentSeed), Messages::StorageManager::GetValues::Reply(values), 0); > > m_storageMap = StorageMap::create(m_quotaInBytes); > m_storageMap->importItems(values); >diff --git a/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.h b/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.h >index 637093fbf4764b50178eeac3fe09fcda57b75987..36705cb22768a70649c1aed38d6824575ea1a25a 100644 >--- a/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.h >+++ b/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.h >@@ -58,14 +58,16 @@ public: > void clear(WebCore::Frame* sourceFrame, StorageAreaImpl* sourceArea); > bool contains(const String& key); > >+ // IPC::MessageReceiver >+ void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override; >+ > const WebCore::SecurityOrigin& securityOrigin() const { return m_securityOrigin.get(); } > >+ uint64_t identifier() const { return m_storageMapID; } >+ > private: > StorageAreaMap(StorageNamespaceImpl*, Ref<WebCore::SecurityOrigin>&&); > >- // IPC::MessageReceiver >- void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override; >- > void didGetValues(uint64_t storageMapSeed); > void didSetItem(uint64_t storageMapSeed, const String& key, bool quotaError); > void didRemoveItem(uint64_t storageMapSeed, const String& key); >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index 17d6ca023e23ab60f85b6d0b54b10b8c21716311..c38ed6bd52888fc69336ea8524886568a316feec 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,14 @@ >+2019-05-13 Sihui Liu <sihui_liu@apple.com> >+ >+ Move Web Storage to Network Process >+ https://bugs.webkit.org/show_bug.cgi?id=197636 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * TestWebKitAPI/Tests/WebKitCocoa/LocalStorageDatabaseTracker.mm: >+ (TEST): >+ * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm: Fix a typo and add a test case to cover it. >+ > 2019-05-12 Yusuke Suzuki <ysuzuki@apple.com> > > [JSC] Compress Watchpoint size by using enum type and Packed<> data structure >diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/LocalStorageDatabaseTracker.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/LocalStorageDatabaseTracker.mm >index cf912a3387ff049269eb94e4b5acdde83e5d0c5e..a216f8ccd0531162af5a56052a71a196e738cadc 100644 >--- a/Tools/TestWebKitAPI/Tests/WebKitCocoa/LocalStorageDatabaseTracker.mm >+++ b/Tools/TestWebKitAPI/Tests/WebKitCocoa/LocalStorageDatabaseTracker.mm >@@ -61,7 +61,8 @@ TEST(WKWebView, LocalStorageFetchDataRecords) > TestWebKitAPI::Util::run(&readyToContinue); > > // Local storage database update interval is 1 second. >- TestWebKitAPI::Util::sleep(1); >+ // FetchData will get from local storage database files, so we need to wait a while to make sure write to database file finishes. >+ TestWebKitAPI::Util::sleep(1.5); > > readyToContinue = false; > [[WKWebsiteDataStore defaultDataStore] fetchDataRecordsOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] completionHandler:^(NSArray<WKWebsiteDataRecord *> *dataRecords) { >diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm >index 2e8e8e297eafba8fffb9e0344474ff736828c431..210724d7c85f9fd27d20008a490d705c363c3ca2 100644 >--- a/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm >+++ b/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm >@@ -4999,7 +4999,7 @@ TEST(ProcessSwap, EphemeralWebStorage) > TestWebKitAPI::Util::run(&done); > > done = false; >- [webView evaluateJavaScript:@"window.sessionStorage.setItem('b,'a')" completionHandler:^(id, NSError *) { >+ [webView evaluateJavaScript:@"window.sessionStorage.setItem('b','a')" completionHandler:^(id, NSError *) { > done = true; > }]; > TestWebKitAPI::Util::run(&done); >@@ -5018,6 +5018,13 @@ TEST(ProcessSwap, EphemeralWebStorage) > done = true; > }]; > TestWebKitAPI::Util::run(&done); >+ >+ done = false; >+ [webView evaluateJavaScript:@"window.sessionStorage.getItem('b')" completionHandler:^(id result, NSError *) { >+ EXPECT_TRUE([@"a" isEqualToString:result]); >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); > > done = false; > [webView loadHTMLString:@"<html><iframe src='pson://www.webkit.org/iframe.html'></iframe></html>" baseURL:[NSURL URLWithString:@"http://www.example.com/"]];
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 197636
:
369206
|
369210
|
369215
|
369220
|
369223
|
369252
|
369404
|
369737
|
369739
|
369978
|
369982
|
369986
|
369990
|
370015
|
370047
|
370166
|
370172
|
370187
|
370280