Some improvements on web storage
authorsihui_liu@apple.com <sihui_liu@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 15 Aug 2019 18:41:53 +0000 (18:41 +0000)
committersihui_liu@apple.com <sihui_liu@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 15 Aug 2019 18:41:53 +0000 (18:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=200373

Reviewed by Geoffrey Garen.
Source/WebCore:

Remove storage type EphemeralLocalStorage, which is used for localStorage in ephemeral session, and use
LocalStorage instead.

Add SessionID to StorageNamespace to make StorageNamespace session-specific.

No new test, updating existing tests for new behavior.

* loader/EmptyClients.cpp:
(WebCore::EmptyStorageNamespaceProvider::createLocalStorageNamespace):
(WebCore::EmptyStorageNamespaceProvider::createTransientLocalStorageNamespace):
(WebCore::EmptyStorageNamespaceProvider::createEphemeralLocalStorageNamespace): Deleted.

* page/Chrome.cpp:
(WebCore::Chrome::createWindow const): ephemeral localStorage of different windows will connect to the same
StorageArea in network process, so no need to copy from parent window to child window.

* page/DOMWindow.cpp:
(WebCore::DOMWindow::prewarmLocalStorageIfNecessary): localStorage will be prewarmed in network process in the
initialization of StorageAreaMap.

* page/Page.cpp:
(WebCore::m_applicationManifest):
(WebCore::Page::~Page):
(WebCore::Page::setSessionID):
(WebCore::Page::ephemeralLocalStorage): Deleted.
(WebCore::Page::setEphemeralLocalStorage): Deleted.
(WebCore::Page::setStorageNamespaceProvider): Deleted.
* page/Page.h:
(WebCore::Page::storageNamespaceProvider):
* storage/Storage.cpp:
(WebCore::Storage::prewarm): Deleted.
* storage/Storage.h:
* storage/StorageArea.h:
(WebCore::StorageArea::closeDatabaseIfIdle):
(WebCore::StorageArea::prewarm): Deleted.
* storage/StorageNamespace.h:
* storage/StorageNamespaceProvider.cpp:
(WebCore::StorageNamespaceProvider::~StorageNamespaceProvider):
(WebCore::StorageNamespaceProvider::localStorageArea):
(WebCore::StorageNamespaceProvider::localStorageNamespace):
(WebCore::StorageNamespaceProvider::transientLocalStorageNamespace):
(WebCore::StorageNamespaceProvider::enableLegacyPrivateBrowsingForTesting): change SessionID of storageNamespace
and update every StorageArea in this namespace.
(WebCore::StorageNamespaceProvider::addPage): Deleted.
(WebCore::StorageNamespaceProvider::removePage): Deleted.
* storage/StorageNamespaceProvider.h:
* storage/StorageType.h:
(WebCore::isLocalStorage):

Source/WebKit:

Fix some issues in web storage architecture. For example, sessionStorageNameSpace for web page is prepared and
destroyed in the network process when the page comes and goes, even though the page may not use sessionStorage
at all. The messages about page state sent from web process to network process can be waste.

Here are some general ideas of this patch:
1. Network process owns the web storage, and web process keeps a small local copy (based on session and
origins that are visited). There is a virtual connection from the local copy in the web process to the original
copy in the network process. The connection is created by web process when some page asks for web storage.
2. If connection is lost because network process is gone, storage in memory will be lost. The local copy in web
processs will be discarded.
3. (SessionID, StorageNamespaceID, SecurityOrigin) is used to identify a storage area. If session is changed in
web process (like enabling private browsing in layout test now), a re-connection with different sessionID would
suffice to load another copy of storage.
4. localStorage in ephemeral session has the same behavior as localStorage instead of sessionStorage, which
means different pages in the same ephemeral session share the same localStorage.

Also, this patch introduces StorageManagerSet to network process. It handles web storage stuff, including
receiving storage messages from web process, on one background thread. Previously each session has its own
StorageManager and each StorageManager has its own WorkQueue.

* CMakeLists.txt:
* DerivedSources-input.xcfilelist:
* DerivedSources-output.xcfilelist:
* DerivedSources.make:

* NetworkProcess/NetworkConnectionToWebProcess.cpp: remove message handlers that are no longer needed. Network
process no longer needs to know page states from web process.
(WebKit::NetworkConnectionToWebProcess::didClose):
(WebKit::NetworkConnectionToWebProcess::webPageWasAdded): Deleted.
(WebKit::NetworkConnectionToWebProcess::webPageWasRemoved): Deleted.
(WebKit::NetworkConnectionToWebProcess::webProcessSessionChanged): Deleted.
* NetworkProcess/NetworkConnectionToWebProcess.h:
* NetworkProcess/NetworkConnectionToWebProcess.messages.in:

* NetworkProcess/NetworkProcess.cpp: NetworkProcess uses StorageManagerSet instead of StorageManager from
different sessions to deal with web storage.
(WebKit::NetworkProcess::NetworkProcess):
(WebKit::NetworkProcess::initializeNetworkProcess):
(WebKit::NetworkProcess::createNetworkConnectionToWebProcess): StorageManagerSet starts handling
StorageManagerSet messages from the new connection.
(WebKit::NetworkProcess::addWebsiteDataStore):
(WebKit::NetworkProcess::destroySession):
(WebKit::NetworkProcess::hasLocalStorage):
(WebKit::NetworkProcess::fetchWebsiteData):
(WebKit::NetworkProcess::deleteWebsiteData):
(WebKit::NetworkProcess::deleteWebsiteDataForOrigins):
(WebKit::NetworkProcess::deleteWebsiteDataForRegistrableDomains):
(WebKit::NetworkProcess::actualPrepareToSuspend):
(WebKit::NetworkProcess::resume):
(WebKit::NetworkProcess::syncLocalStorage):
(WebKit::NetworkProcess::clearLegacyPrivateBrowsingLocalStorage): added for clearing in-memory ephemeral
localStorage.
(WebKit::NetworkProcess::getLocalStorageOriginDetails):
(WebKit::NetworkProcess::connectionToWebProcessClosed):
(WebKit::NetworkProcess::webPageWasAdded): Deleted.
(WebKit::NetworkProcess::webPageWasRemoved): Deleted.
(WebKit::NetworkProcess::webProcessWasDisconnected): Deleted.
(WebKit::NetworkProcess::webProcessSessionChanged): Deleted.
* NetworkProcess/NetworkProcess.h:
* NetworkProcess/NetworkProcess.messages.in:

* NetworkProcess/NetworkSession.cpp: StorageManager is moved out of NetworkSession. It is now managed by
StorageManagerSet.
(WebKit::NetworkSession::NetworkSession):
(WebKit::NetworkSession::~NetworkSession):
* NetworkProcess/NetworkSession.h:
(WebKit::NetworkSession::storageManager): Deleted.

* NetworkProcess/NetworkSessionCreationParameters.cpp: creation parameters of StorageManager is moved out of
NetworkSessionCreationParameters.
(WebKit::NetworkSessionCreationParameters::privateSessionParameters):
(WebKit::NetworkSessionCreationParameters::encode const):
(WebKit::NetworkSessionCreationParameters::decode):
* NetworkProcess/NetworkSessionCreationParameters.h:

* NetworkProcess/WebStorage/LocalStorageDatabase.cpp:
(WebKit::LocalStorageDatabase::updateDatabase): remove an assertion that is no longer true as we can force an
update with syncLocalStorage now.
* NetworkProcess/WebStorage/LocalStorageDatabase.h: make updateDatabase public for syncLocalStorage.

* NetworkProcess/WebStorage/LocalStorageDatabaseTracker.cpp: LocalStorageDatabaseTracker is created on the
background thread now, so it does not hold WorkQueue to do the file operation.
(WebKit::LocalStorageDatabaseTracker::create):
(WebKit::LocalStorageDatabaseTracker::LocalStorageDatabaseTracker):
(WebKit::LocalStorageDatabaseTracker::~LocalStorageDatabaseTracker):
* NetworkProcess/WebStorage/LocalStorageDatabaseTracker.h:
* NetworkProcess/WebStorage/LocalStorageNamespace.cpp:
(WebKit::LocalStorageNamespace::getOrCreateStorageArea):
(WebKit::LocalStorageNamespace::cloneTo): Deleted.
* NetworkProcess/WebStorage/LocalStorageNamespace.h:
* NetworkProcess/WebStorage/SessionStorageNamespace.cpp:
(WebKit::SessionStorageNamespace::getOrCreateStorageArea):
(WebKit::SessionStorageNamespace::addAllowedConnection): Deleted.
(WebKit::SessionStorageNamespace::removeAllowedConnection): Deleted.
* NetworkProcess/WebStorage/SessionStorageNamespace.h:
(WebKit::SessionStorageNamespace::allowedConnections const): Deleted.

* NetworkProcess/WebStorage/StorageArea.cpp:
(WebKit::generateStorageAreaIdentifier): each StorageArea has an identifier. StorageAreaMap in web process uses
this identifier to indicate which StorageArea it is connecting to.
(WebKit::StorageArea::StorageArea):
(WebKit::StorageArea::~StorageArea): StorageArea may still have listeners because StorageArea should be
destroyed by requests from UI process, and listeners are connections to web processses.
(WebKit::StorageArea::addListener): load localStorageDatabase in advance if there is some connection to this
LocalStorage area.
(WebKit::StorageArea::removeListener):
(WebKit::StorageArea::hasListener const):
(WebKit::StorageArea::clear):
(WebKit::StorageArea::openDatabaseAndImportItemsIfNeeded const):
(WebKit::StorageArea::dispatchEvents const):
(WebKit::StorageArea::syncToDatabase):
(WebKit::StorageArea::setItems): Deleted. Stop syncing from web process to network process after network process
is relaunched.
* NetworkProcess/WebStorage/StorageArea.h:
(WebKit::StorageArea::identifier):
(WebKit::StorageArea::setWorkQueue):

* NetworkProcess/WebStorage/StorageManager.cpp: StorageManager should be accessed by only background thread now.
(WebKit::StorageManager::StorageManager):
(WebKit::StorageManager::~StorageManager):
(WebKit::StorageManager::createSessionStorageNamespace):
(WebKit::StorageManager::destroySessionStorageNamespace): this is not used now but keep it for future
improvement to remove in-memory sessionStorage in network process if we know some web page is gone forever.
(WebKit::StorageManager::cloneSessionStorageNamespace): previously each page had its own ephemeral
localStorageNamespace and now all pages in the same session share one localStorage, so we don't need to clone
localStorageNamespace.
(WebKit::StorageManager::getSessionStorageOrigins):
(WebKit::StorageManager::deleteSessionStorageOrigins):
(WebKit::StorageManager::deleteSessionStorageEntriesForOrigins):
(WebKit::StorageManager::getLocalStorageOrigins):
(WebKit::StorageManager::getLocalStorageOriginDetails):
(WebKit::StorageManager::deleteLocalStorageOriginsModifiedSince):
(WebKit::StorageManager::deleteLocalStorageEntriesForOrigins):
(WebKit::StorageManager::createLocalStorageArea):
(WebKit::StorageManager::createTransientLocalStorageArea):
(WebKit::StorageManager::createSessionStorageArea):
(WebKit::StorageManager::getOrCreateLocalStorageNamespace):
(WebKit::StorageManager::getOrCreateTransientLocalStorageNamespace):
(WebKit::StorageManager::getOrCreateSessionStorageNamespace):
(WebKit::StorageManager::clearStorageNamespaces):
(WebKit::StorageManager::addAllowedSessionStorageNamespaceConnection): Deleted.
(WebKit::StorageManager::removeAllowedSessionStorageNamespaceConnection): Deleted.
(WebKit::StorageManager::processDidCloseConnection): Deleted.
(WebKit::StorageManager::deleteLocalStorageEntriesForOrigin): Deleted.
(WebKit::StorageManager::createLocalStorageMap): Deleted.
(WebKit::StorageManager::createTransientLocalStorageMap): Deleted.
(WebKit::StorageManager::createSessionStorageMap): Deleted.
(WebKit::StorageManager::destroyStorageMap): Deleted.
(WebKit::StorageManager::prewarm): Deleted.
(WebKit::StorageManager::getValues): Deleted.
(WebKit::StorageManager::setItem): Deleted.
(WebKit::StorageManager::setItems): Deleted.
(WebKit::StorageManager::removeItem): Deleted.
(WebKit::StorageManager::clear): Deleted.
(WebKit::StorageManager::waitUntilTasksFinished): Deleted.
(WebKit::StorageManager::suspend): Deleted.
(WebKit::StorageManager::resume): Deleted.
(WebKit::StorageManager::findStorageArea const): Deleted.
* NetworkProcess/WebStorage/StorageManager.h:
(WebKit::StorageManager::workQueue const): Deleted.
(): Deleted.

* NetworkProcess/WebStorage/StorageManager.messages.in: Removed. Moved to StorageManagerSet.messages.in.

* NetworkProcess/WebStorage/StorageManagerSet.cpp: Added.
(WebKit::StorageManagerSet::create):
(WebKit::StorageManagerSet::StorageManagerSet):
(WebKit::StorageManagerSet::~StorageManagerSet):
(WebKit::StorageManagerSet::add):
(WebKit::StorageManagerSet::remove):
(WebKit::StorageManagerSet::contains):
(WebKit::StorageManagerSet::addConnection):
(WebKit::StorageManagerSet::removeConnection):
(WebKit::StorageManagerSet::waitUntilTasksFinished):
(WebKit::StorageManagerSet::waitUntilSyncingLocalStorageFinished):
(WebKit::StorageManagerSet::suspend):
(WebKit::StorageManagerSet::resume):
(WebKit::StorageManagerSet::getSessionStorageOrigins):
(WebKit::StorageManagerSet::deleteSessionStorage):
(WebKit::StorageManagerSet::deleteSessionStorageForOrigins):
(WebKit::StorageManagerSet::getLocalStorageOrigins):
(WebKit::StorageManagerSet::deleteLocalStorageModifiedSince):
(WebKit::StorageManagerSet::deleteLocalStorageForOrigins):
(WebKit::StorageManagerSet::getLocalStorageOriginDetails):
(WebKit::StorageManagerSet::connectToLocalStorageArea):
(WebKit::StorageManagerSet::connectToTransientLocalStorageArea):
(WebKit::StorageManagerSet::connectToSessionStorageArea):
(WebKit::StorageManagerSet::disconnectFromStorageArea):
(WebKit::StorageManagerSet::getValues):
(WebKit::StorageManagerSet::setItem):
(WebKit::StorageManagerSet::removeItem):
(WebKit::StorageManagerSet::clear):
(WebKit::StorageManagerSet::cloneSessionStorageNamespace):
* NetworkProcess/WebStorage/StorageManagerSet.h: Added.
* NetworkProcess/WebStorage/StorageManagerSet.messages.in: Added.

* Shared/WebsiteDataStoreParameters.cpp: creation parameters of StorageManager are moved to
WebsiteDataStoreParameters.
(WebKit::WebsiteDataStoreParameters::encode const):
(WebKit::WebsiteDataStoreParameters::decode):
(WebKit::WebsiteDataStoreParameters::privateSessionParameters):
* Shared/WebsiteDataStoreParameters.h:
* Sources.txt:

* UIProcess/API/C/WKContext.cpp: add SPI for tests.
(WKContextSyncLocalStorage):
(WKContextClearLegacyPrivateBrowsingLocalStorage):
* UIProcess/API/C/WKContextPrivate.h:
* UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
(WKWebsiteDataStoreRemoveLocalStorage):
* UIProcess/API/C/WKWebsiteDataStoreRef.h:
* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::ensureNetworkProcess):
(WebKit::WebProcessPool::syncLocalStorage):
(WebKit::WebProcessPool::clearLegacyPrivateBrowsingLocalStorage):
* UIProcess/WebProcessPool.h:
* UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm:
(WebKit::WebsiteDataStore::parameters):
* UIProcess/WebsiteData/WebsiteDataStore.cpp:
(WebKit::WebsiteDataStore::parameters):
* WebKit.xcodeproj/project.pbxproj:

* WebProcess/InjectedBundle/InjectedBundle.cpp: session change of web storage is done via
WebStorageNamespaceProvider instead of WebProcess now.
(WebKit::InjectedBundle::setPrivateBrowsingEnabled):
* WebProcess/WebProcess.cpp: web process no longer sends messsages about page state to network process.
(WebKit::WebProcess::createWebPage):
(WebKit::WebProcess::removeWebPage):
(WebKit::WebProcess::ensureNetworkProcessConnection):
(WebKit::WebProcess::networkProcessConnectionClosed):
(WebKit::WebProcess::storageAreaMap const):
(WebKit::WebProcess::enablePrivateBrowsingForTesting): Deleted. This was used for changing session via
WebProcess.
* WebProcess/WebProcess.h:
* WebProcess/WebStorage/StorageAreaImpl.cpp:
(WebKit::StorageAreaImpl::StorageAreaImpl):
(WebKit::StorageAreaImpl::length):
(WebKit::StorageAreaImpl::key):
(WebKit::StorageAreaImpl::item):
(WebKit::StorageAreaImpl::setItem):
(WebKit::StorageAreaImpl::removeItem):
(WebKit::StorageAreaImpl::clear):
(WebKit::StorageAreaImpl::contains):
(WebKit::StorageAreaImpl::storageType const):
(WebKit::StorageAreaImpl::incrementAccessCount):
(WebKit::StorageAreaImpl::decrementAccessCount):
(WebKit::StorageAreaImpl::prewarm): Deleted.
(WebKit::StorageAreaImpl::securityOrigin const): Deleted.

* WebProcess/WebStorage/StorageAreaImpl.h: make StorageAreaImpl hold a weak reference to StorageAreaMap and
StorageNamespaceImpl hold a strong reference. In this way lifeime of localStorage StorageAreraMap stays align
with StorageNameSpaceProvider and Page.

* WebProcess/WebStorage/StorageAreaMap.cpp: identifier of StorageAreaMap is the same as identifier of
StorageArea it connects to. If the identifier is 0, it means the StorageAreaMap is disconnected.
(WebKit::StorageAreaMap::StorageAreaMap):
(WebKit::StorageAreaMap::~StorageAreaMap):
(WebKit::StorageAreaMap::setItem):
(WebKit::StorageAreaMap::removeItem):
(WebKit::StorageAreaMap::clear):
(WebKit::StorageAreaMap::resetValues):
(WebKit::StorageAreaMap::loadValuesIfNeeded):
(WebKit::StorageAreaMap::applyChange):
(WebKit::StorageAreaMap::dispatchStorageEvent):
(WebKit::StorageAreaMap::dispatchSessionStorageEvent):
(WebKit::StorageAreaMap::dispatchLocalStorageEvent):
(WebKit::StorageAreaMap::connect):
(WebKit::StorageAreaMap::disconnect):
(WebKit::generateStorageMapID): Deleted.
(WebKit::StorageAreaMap::prewarm): Deleted.
(WebKit::StorageAreaMap::didGetValues): Deleted. This is useless as GetValues is a synchronous operation.
* WebProcess/WebStorage/StorageAreaMap.h:
(): Deleted.

* WebProcess/WebStorage/StorageAreaMap.messages.in: there are two synchronous messages, one for connection and
one for getting values. We may merge them into one in future improvement.
* WebProcess/WebStorage/StorageNamespaceImpl.cpp:
(WebKit::StorageNamespaceImpl::createSessionStorageNamespace):
(WebKit::StorageNamespaceImpl::createLocalStorageNamespace):
(WebKit::StorageNamespaceImpl::createTransientLocalStorageNamespace):
(WebKit::StorageNamespaceImpl::StorageNamespaceImpl):
(WebKit::StorageNamespaceImpl::storageArea):
(WebKit::StorageNamespaceImpl::copy):
(WebKit::StorageNamespaceImpl::setSessionIDForTesting):
(WebKit::StorageNamespaceImpl::createEphemeralLocalStorageNamespace): Deleted.
* WebProcess/WebStorage/StorageNamespaceImpl.h:
* WebProcess/WebStorage/WebStorageNamespaceProvider.cpp:
(WebKit::WebStorageNamespaceProvider::createSessionStorageNamespace):
(WebKit::WebStorageNamespaceProvider::createLocalStorageNamespace):
(WebKit::WebStorageNamespaceProvider::createTransientLocalStorageNamespace):
(WebKit::WebStorageNamespaceProvider::createEphemeralLocalStorageNamespace): Deleted.
* WebProcess/WebStorage/WebStorageNamespaceProvider.h:

Source/WebKitLegacy:

Do some clean-up and add support for session change of web storage in layout tests.

* Storage/StorageAreaImpl.cpp:
(WebKit::StorageAreaImpl::sessionChanged):
* Storage/StorageAreaImpl.h:
(): Deleted.

* Storage/StorageAreaSync.h: make sure StorageAreaSync is destructed on the main thread, as it can be
dereferenced in StorageAreaImpl::sessionChanged and its last reference for final sync could be released on the
background thread.

* Storage/StorageNamespaceImpl.cpp: replace EphemeralLocalStorage with LocalStorage, and store SessionID in
StorageNamespace.
(WebKit::StorageNamespaceImpl::createSessionStorageNamespace):
(WebKit::StorageNamespaceImpl::getOrCreateLocalStorageNamespace):
(WebKit::StorageNamespaceImpl::StorageNamespaceImpl):
(WebKit::StorageNamespaceImpl::copy):
(WebKit::StorageNamespaceImpl::close):
(WebKit::StorageNamespaceImpl::setSessionIDForTesting):
(WebKit::StorageNamespaceImpl::createEphemeralLocalStorageNamespace): Deleted.
* Storage/StorageNamespaceImpl.h:
* Storage/WebStorageNamespaceProvider.cpp:
(WebKit::WebStorageNamespaceProvider::createSessionStorageNamespace):
(WebKit::WebStorageNamespaceProvider::createLocalStorageNamespace):
(WebKit::WebStorageNamespaceProvider::createTransientLocalStorageNamespace):
(WebKit::WebStorageNamespaceProvider::createEphemeralLocalStorageNamespace): Deleted.
* Storage/WebStorageNamespaceProvider.h:

Source/WebKitLegacy/mac:

* WebView/WebView.mm:
(-[WebView _preferencesChanged:]): notify storageNamespaceProvider about session change.

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/LocalStoragePersistence.mm:
(TEST): update expectation for behavior change.

* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl: new SPI to synchronously flush localStorage to
database file.
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::syncLocalStorage):
* WebKitTestRunner/InjectedBundle/TestRunner.h:

* WebKitTestRunner/TestController.cpp: clear local storage between test runs to make each test isolated.
(WTR::TestController::resetStateToConsistentValues):
(WTR::StorageVoidCallbackContext::StorageVoidCallbackContext):
(WTR::StorageVoidCallback):
(WTR::TestController::clearIndexedDatabases):
(WTR::TestController::clearLocalStorage):
(WTR::TestController::syncLocalStorage):
(WTR::RemoveAllIndexedDatabasesCallbackContext::RemoveAllIndexedDatabasesCallbackContext): Deleted. Replaced
with StorageVoidCallbackContext for general usage.
(WTR::RemoveAllIndexedDatabasesCallback): Deleted. Replaced with StorageVoidCallback.
(WTR::TestController::ClearIndexedDatabases): Deleted. Use lowercase for consistent style.
* WebKitTestRunner/TestController.h:

* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle): add handler for new message
SyncLocalStorage.

LayoutTests:

Modify tests for a behavior change: sessionStorage will be lost when network process crashes.

For tests which use sessionStorage to store items, crash network process, then read from sessionStorage and
expect items to be in sessionStorage, replace sessionStorage with localStorage. Also, to make sure localStorage
is stored persistently before network process gets terminated, adopt a newly introduced SPI to
synchronously flush localStorage content to disk before terminating network process.

* platform/ios-simulator-wk2/TestExpectations:
* platform/mac-wk2/TestExpectations:
* storage/domstorage/localstorage/private-browsing-affects-storage-expected.txt:
* storage/indexeddb/IDBObject-leak.html:
* storage/indexeddb/modern/opendatabase-after-storage-crash-expected.txt:
* storage/indexeddb/modern/opendatabase-after-storage-crash.html:

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

93 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/ios-simulator-wk2/TestExpectations
LayoutTests/platform/mac-wk2/TestExpectations
LayoutTests/storage/domstorage/localstorage/private-browsing-affects-storage-expected.txt
LayoutTests/storage/indexeddb/IDBObject-leak.html
LayoutTests/storage/indexeddb/modern/opendatabase-after-storage-crash-expected.txt
LayoutTests/storage/indexeddb/modern/opendatabase-after-storage-crash.html
Source/WebCore/ChangeLog
Source/WebCore/loader/EmptyClients.cpp
Source/WebCore/page/Chrome.cpp
Source/WebCore/page/DOMWindow.cpp
Source/WebCore/page/Page.cpp
Source/WebCore/page/Page.h
Source/WebCore/storage/Storage.cpp
Source/WebCore/storage/Storage.h
Source/WebCore/storage/StorageArea.h
Source/WebCore/storage/StorageNamespace.h
Source/WebCore/storage/StorageNamespaceProvider.cpp
Source/WebCore/storage/StorageNamespaceProvider.h
Source/WebCore/storage/StorageType.h
Source/WebKit/CMakeLists.txt
Source/WebKit/ChangeLog
Source/WebKit/DerivedSources-input.xcfilelist
Source/WebKit/DerivedSources-output.xcfilelist
Source/WebKit/DerivedSources.make
Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp
Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h
Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in
Source/WebKit/NetworkProcess/NetworkProcess.cpp
Source/WebKit/NetworkProcess/NetworkProcess.h
Source/WebKit/NetworkProcess/NetworkProcess.messages.in
Source/WebKit/NetworkProcess/NetworkSession.cpp
Source/WebKit/NetworkProcess/NetworkSession.h
Source/WebKit/NetworkProcess/NetworkSessionCreationParameters.cpp
Source/WebKit/NetworkProcess/NetworkSessionCreationParameters.h
Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabase.cpp
Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabase.h
Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabaseTracker.cpp
Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabaseTracker.h
Source/WebKit/NetworkProcess/WebStorage/LocalStorageNamespace.cpp
Source/WebKit/NetworkProcess/WebStorage/LocalStorageNamespace.h
Source/WebKit/NetworkProcess/WebStorage/SessionStorageNamespace.cpp
Source/WebKit/NetworkProcess/WebStorage/SessionStorageNamespace.h
Source/WebKit/NetworkProcess/WebStorage/StorageArea.cpp
Source/WebKit/NetworkProcess/WebStorage/StorageArea.h
Source/WebKit/NetworkProcess/WebStorage/StorageManager.cpp
Source/WebKit/NetworkProcess/WebStorage/StorageManager.h
Source/WebKit/NetworkProcess/WebStorage/StorageManager.messages.in [deleted file]
Source/WebKit/NetworkProcess/WebStorage/StorageManagerSet.cpp [new file with mode: 0644]
Source/WebKit/NetworkProcess/WebStorage/StorageManagerSet.h [new file with mode: 0644]
Source/WebKit/NetworkProcess/WebStorage/StorageManagerSet.messages.in [new file with mode: 0644]
Source/WebKit/Shared/WebsiteDataStoreParameters.cpp
Source/WebKit/Shared/WebsiteDataStoreParameters.h
Source/WebKit/Sources.txt
Source/WebKit/UIProcess/API/C/WKContext.cpp
Source/WebKit/UIProcess/API/C/WKContextPrivate.h
Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp
Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h
Source/WebKit/UIProcess/WebProcessPool.cpp
Source/WebKit/UIProcess/WebProcessPool.h
Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm
Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
Source/WebKit/WebKit.xcodeproj/project.pbxproj
Source/WebKit/WebProcess/InjectedBundle/InjectedBundle.cpp
Source/WebKit/WebProcess/WebProcess.cpp
Source/WebKit/WebProcess/WebProcess.h
Source/WebKit/WebProcess/WebStorage/StorageAreaImpl.cpp
Source/WebKit/WebProcess/WebStorage/StorageAreaImpl.h
Source/WebKit/WebProcess/WebStorage/StorageAreaMap.cpp
Source/WebKit/WebProcess/WebStorage/StorageAreaMap.h
Source/WebKit/WebProcess/WebStorage/StorageAreaMap.messages.in
Source/WebKit/WebProcess/WebStorage/StorageNamespaceImpl.cpp
Source/WebKit/WebProcess/WebStorage/StorageNamespaceImpl.h
Source/WebKit/WebProcess/WebStorage/WebStorageNamespaceProvider.cpp
Source/WebKit/WebProcess/WebStorage/WebStorageNamespaceProvider.h
Source/WebKitLegacy/ChangeLog
Source/WebKitLegacy/Storage/StorageAreaImpl.cpp
Source/WebKitLegacy/Storage/StorageAreaImpl.h
Source/WebKitLegacy/Storage/StorageAreaSync.h
Source/WebKitLegacy/Storage/StorageNamespaceImpl.cpp
Source/WebKitLegacy/Storage/StorageNamespaceImpl.h
Source/WebKitLegacy/Storage/WebStorageNamespaceProvider.cpp
Source/WebKitLegacy/Storage/WebStorageNamespaceProvider.h
Source/WebKitLegacy/mac/ChangeLog
Source/WebKitLegacy/mac/WebView/WebView.mm
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKitCocoa/LocalStoragePersistence.mm
Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl
Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp
Tools/WebKitTestRunner/InjectedBundle/TestRunner.h
Tools/WebKitTestRunner/TestController.cpp
Tools/WebKitTestRunner/TestController.h
Tools/WebKitTestRunner/TestInvocation.cpp

index 0cf3fb0..39586b9 100644 (file)
@@ -1,3 +1,24 @@
+2019-08-15  Sihui Liu  <sihui_liu@apple.com>
+
+        Some improvements on web storage
+        https://bugs.webkit.org/show_bug.cgi?id=200373
+
+        Reviewed by Geoffrey Garen.
+        Modify tests for a behavior change: sessionStorage will be lost when network process crashes.
+
+        For tests which use sessionStorage to store items, crash network process, then read from sessionStorage and 
+        expect items to be in sessionStorage, replace sessionStorage with localStorage. Also, to make sure localStorage
+        is stored persistently before network process gets terminated, adopt a newly introduced SPI to 
+        synchronously flush localStorage content to disk before terminating network process.
+
+        * platform/ios-simulator-wk2/TestExpectations:
+        * platform/mac-wk2/TestExpectations:
+        * storage/domstorage/localstorage/private-browsing-affects-storage-expected.txt:
+        * storage/indexeddb/IDBObject-leak.html:
+        * storage/indexeddb/modern/opendatabase-after-storage-crash-expected.txt:
+        * storage/indexeddb/modern/opendatabase-after-storage-crash.html:
+
 2019-08-15  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         Occasional hang under -[UIKeyboardTaskQueue lockWhenReadyForMainThread] when long-pressing non-editable text
index 9e8666a..974977a 100644 (file)
@@ -66,7 +66,7 @@ http/wpt/cache-storage/cache-put-keys.https.any.worker.html [ Slow ]
 http/wpt/cache-storage/a-cache-open.https.html [ Slow ]
 http/wpt/cache-storage/cache-quota-add.any.html [ Slow ]
 
-webkit.org/b/196376 [ Debug ] storage/domstorage/localstorage/private-browsing-affects-storage.html [ Pass Failure ]
+webkit.org/b/196376 [ Debug ] storage/domstorage/localstorage/private-browsing-affects-storage.html [ Pass ]
 
 webkit.org/b/196403 imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-stop.html [ Pass Failure ]
 
index 6a8270f..d22d787 100644 (file)
@@ -922,7 +922,7 @@ webkit.org/b/194826 http/tests/resourceLoadStatistics/do-not-block-top-level-nav
 
 webkit.org/b/194916 fast/mediastream/MediaStream-video-element.html [ Pass Failure ]
 
-webkit.org/b/196376 storage/domstorage/localstorage/private-browsing-affects-storage.html [ Pass Failure ]
+webkit.org/b/196376 storage/domstorage/localstorage/private-browsing-affects-storage.html [ Pass ]
 
 webkit.org/b/196400 fast/mediastream/MediaStreamTrack-getSettings.html [ Pass Failure ]
 
index 2ca9557..f9840de 100644 (file)
@@ -8,7 +8,7 @@ ALERT: localStorage's length is: 1
 ALERT: The item in new window starts out as: ChangedValue
 ALERT: The item in new window is now: NewWindowValue
 ALERT: Back in parent window, localStorage's length is: 1
-ALERT: Back in parent window, testItem is: ChangedValue
+ALERT: Back in parent window, testItem is: NewWindowValue
 ALERT: Final window, localStorage's length is: 1
 ALERT: Final window, item is: Persistent item!
 
index e18b68b..6aa8ab6 100644 (file)
@@ -13,7 +13,7 @@ function test() {
         return;
     }
 
-    if (sessionStorage.doneFirstLoad) {
+    if (localStorage.doneFirstLoad) {
         gc();
         shouldBeEqualToNumber("internals.numberOfIDBTransactions()", 0);
         finishJSTest();
@@ -23,16 +23,21 @@ function test() {
     var dbname = setDBNameFromPath() + Date();
     var request =  window.indexedDB.open(dbname);
     request.onupgradeneeded = function(evt) {
-        sessionStorage.doneFirstLoad = true;
+        localStorage.doneFirstLoad = true;
         if (!window.testRunner || !testRunner.terminateNetworkProcess) {
             testFailed('This test requires access to the TestRunner object and terminateNetworkProcess() function');
             finishJSTest();
             return;
         } 
+
+        // Make sure localStorage is flushed to disk before crashing network process.
+        testRunner.syncLocalStorage();
         testRunner.terminateNetworkProcess();
-        setTimeout((()=> {
-            location.reload();
-        }), 0);
+        evt.target.result.onerror = function(e) {
+            setTimeout((()=> {
+                location.reload();
+            }), 0);
+        }
     }
 }
 
index d2458f6..9a0912e 100644 (file)
@@ -20,31 +20,31 @@ function continueTest()
        request.onerror = function(e) {
                // Good, we received an expected error.
                // Now reload to see if a new document connects successfully
-               if (sessionStorage[storageKey]) {
+               if (localStorage[storageKey]) {
                        document.body.innerHTML = "Received error more than once unexpectedly. Database: name " + dbname + ", version 2.";
                        if (window.testRunner)
                                testRunner.notifyDone();
                        return;
                }
 
-               sessionStorage[storageKey] = "Made it";
+               localStorage[storageKey] = "Made it";
                location.reload();
        }
 
        request.onsuccess = function(e) {
-               document.body.innerHTML = "Unexpected upgradeneeded after storage process termination. Database: name " + dbname + ", version 2. SessionStorage value: " + sessionStorage[storageKey] + ".";
+               document.body.innerHTML = "Unexpected upgradeneeded after storage process termination. Database: name " + dbname + ", version 2. localStorage value: " + sessionStorage[storageKey] + ".";
                if (window.testRunner)
                        testRunner.notifyDone();
        }
 }
 
-var versionToOpen = sessionStorage.doneFirstLoad ? 3 : 1;
+var versionToOpen = localStorage.doneFirstLoad ? 3 : 1;
 var request = window.indexedDB.open(dbname, versionToOpen);
 
 request.onupgradeneeded = function(e) {
-       if (sessionStorage.doneFirstLoad) {
+       if (localStorage.doneFirstLoad) {
                document.body.innerHTML = "Successfully opened database with version " + versionToOpen + ".";
-               shouldBeEqualToString('sessionStorage[storageKey]', 'Made it');
+               shouldBeEqualToString('localStorage[storageKey]', 'Made it');
 
                if (window.testRunner) {
                        testRunner.notifyDone();
@@ -52,7 +52,7 @@ request.onupgradeneeded = function(e) {
                }
        }
 
-       sessionStorage.doneFirstLoad = true;
+       localStorage.doneFirstLoad = true;
 
        // Set an error handler on the database connection so once the storage process terminates we know to continue the test
        e.target.result.onerror = function(e) {
@@ -61,6 +61,8 @@ request.onupgradeneeded = function(e) {
 
        if (window.testRunner) {
                testRunner.waitUntilDone();
+               // Make sure localStorage is flushed to disk before crashing network process.
+               testRunner.syncLocalStorage();
                testRunner.terminateNetworkProcess();
        }
 }
index f958e5b..3bb2646 100644 (file)
@@ -1,3 +1,59 @@
+2019-08-15  Sihui Liu  <sihui_liu@apple.com>
+
+        Some improvements on web storage
+        https://bugs.webkit.org/show_bug.cgi?id=200373
+
+        Reviewed by Geoffrey Garen.
+
+        Remove storage type EphemeralLocalStorage, which is used for localStorage in ephemeral session, and use 
+        LocalStorage instead.
+
+        Add SessionID to StorageNamespace to make StorageNamespace session-specific.
+
+        No new test, updating existing tests for new behavior.
+
+        * loader/EmptyClients.cpp:
+        (WebCore::EmptyStorageNamespaceProvider::createLocalStorageNamespace):
+        (WebCore::EmptyStorageNamespaceProvider::createTransientLocalStorageNamespace):
+        (WebCore::EmptyStorageNamespaceProvider::createEphemeralLocalStorageNamespace): Deleted.
+
+        * page/Chrome.cpp:
+        (WebCore::Chrome::createWindow const): ephemeral localStorage of different windows will connect to the same 
+        StorageArea in network process, so no need to copy from parent window to child window.
+
+        * page/DOMWindow.cpp:
+        (WebCore::DOMWindow::prewarmLocalStorageIfNecessary): localStorage will be prewarmed in network process in the
+        initialization of StorageAreaMap.
+
+        * page/Page.cpp:
+        (WebCore::m_applicationManifest):
+        (WebCore::Page::~Page):
+        (WebCore::Page::setSessionID):
+        (WebCore::Page::ephemeralLocalStorage): Deleted.
+        (WebCore::Page::setEphemeralLocalStorage): Deleted.
+        (WebCore::Page::setStorageNamespaceProvider): Deleted.
+        * page/Page.h:
+        (WebCore::Page::storageNamespaceProvider):
+        * storage/Storage.cpp:
+        (WebCore::Storage::prewarm): Deleted.
+        * storage/Storage.h:
+        * storage/StorageArea.h:
+        (WebCore::StorageArea::closeDatabaseIfIdle):
+        (WebCore::StorageArea::prewarm): Deleted.
+        * storage/StorageNamespace.h:
+        * storage/StorageNamespaceProvider.cpp:
+        (WebCore::StorageNamespaceProvider::~StorageNamespaceProvider):
+        (WebCore::StorageNamespaceProvider::localStorageArea):
+        (WebCore::StorageNamespaceProvider::localStorageNamespace):
+        (WebCore::StorageNamespaceProvider::transientLocalStorageNamespace):
+        (WebCore::StorageNamespaceProvider::enableLegacyPrivateBrowsingForTesting): change SessionID of storageNamespace
+        and update every StorageArea in this namespace.
+        (WebCore::StorageNamespaceProvider::addPage): Deleted.
+        (WebCore::StorageNamespaceProvider::removePage): Deleted.
+        * storage/StorageNamespaceProvider.h:
+        * storage/StorageType.h:
+        (WebCore::isLocalStorage):
+
 2019-08-15  Saam Barati  <sbarati@apple.com>
 
         [WHLSL] Make length, clamp, operator+, operator-, operator*, operator/, operator[], operator[]=, operator.xy, operator.xy=, native
index c450c08..0453d7e 100644 (file)
@@ -390,18 +390,19 @@ class EmptyStorageNamespaceProvider final : public StorageNamespaceProvider {
         bool contains(const String&) final { return false; }
         StorageType storageType() const final { return StorageType::Local; }
         size_t memoryBytesUsedByCache() final { return 0; }
-        const SecurityOriginData& securityOrigin() const final { static NeverDestroyed<SecurityOriginData> origin; return origin.get(); }
     };
 
     struct EmptyStorageNamespace final : public StorageNamespace {
         Ref<StorageArea> storageArea(const SecurityOriginData&) final { return adoptRef(*new EmptyStorageArea); }
         Ref<StorageNamespace> copy(Page*) final { return adoptRef(*new EmptyStorageNamespace); }
+        PAL::SessionID sessionID() const { return PAL::SessionID::emptySessionID(); }
+        void setSessionIDForTesting(PAL::SessionID) { };
     };
 
     Ref<StorageNamespace> createSessionStorageNamespace(Page&, unsigned) final;
-    Ref<StorageNamespace> createLocalStorageNamespace(unsigned) final;
-    Ref<StorageNamespace> createEphemeralLocalStorageNamespace(Page&, unsigned) final;
-    Ref<StorageNamespace> createTransientLocalStorageNamespace(SecurityOrigin&, unsigned) final;
+    Ref<StorageNamespace> createLocalStorageNamespace(unsigned, PAL::SessionID) final;
+    Ref<StorageNamespace> createTransientLocalStorageNamespace(SecurityOrigin&, unsigned, PAL::SessionID) final;
+
 };
 
 class EmptyUserContentProvider final : public UserContentProvider {
@@ -525,17 +526,12 @@ Ref<StorageNamespace> EmptyStorageNamespaceProvider::createSessionStorageNamespa
     return adoptRef(*new EmptyStorageNamespace);
 }
 
-Ref<StorageNamespace> EmptyStorageNamespaceProvider::createLocalStorageNamespace(unsigned)
-{
-    return adoptRef(*new EmptyStorageNamespace);
-}
-
-Ref<StorageNamespace> EmptyStorageNamespaceProvider::createEphemeralLocalStorageNamespace(Page&, unsigned)
+Ref<StorageNamespace> EmptyStorageNamespaceProvider::createLocalStorageNamespace(unsigned, PAL::SessionID)
 {
     return adoptRef(*new EmptyStorageNamespace);
 }
 
-Ref<StorageNamespace> EmptyStorageNamespaceProvider::createTransientLocalStorageNamespace(SecurityOrigin&, unsigned)
+Ref<StorageNamespace> EmptyStorageNamespaceProvider::createTransientLocalStorageNamespace(SecurityOrigin&, unsigned, PAL::SessionID)
 {
     return adoptRef(*new EmptyStorageNamespace);
 }
index 9758329..73fee07 100644 (file)
@@ -189,8 +189,6 @@ Page* Chrome::createWindow(Frame& frame, const FrameLoadRequest& request, const
 
     if (auto* oldSessionStorage = m_page.sessionStorage(false))
         newPage->setSessionStorage(oldSessionStorage->copy(newPage));
-    if (auto* oldEphemeralLocalStorage = m_page.ephemeralLocalStorage(false))
-        newPage->setEphemeralLocalStorage(oldEphemeralLocalStorage->copy(newPage));
 
     return newPage;
 }
index 17cba5e..3074b18 100644 (file)
@@ -442,8 +442,7 @@ void DOMWindow::prewarmLocalStorageIfNecessary()
     if (!localStorage)
         return;
 
-    if (localStorage->prewarm())
-        page->mainFrame().didPrewarmLocalStorage();
+    page->mainFrame().didPrewarmLocalStorage();
 }
 
 DOMWindow::~DOMWindow()
index 4d4a49c..395d2f0 100644 (file)
@@ -289,7 +289,6 @@ Page::Page(PageConfiguration&& pageConfiguration)
     updateTimerThrottlingState();
 
     m_pluginInfoProvider->addPage(*this);
-    m_storageNamespaceProvider->addPage(*this);
     m_userContentProvider->addPage(*this);
     m_visitedLinkStore->addPage(*this);
 
@@ -367,7 +366,6 @@ Page::~Page()
 #endif
 
     m_pluginInfoProvider->removePage(*this);
-    m_storageNamespaceProvider->removePage(*this);
     m_userContentProvider->removePage(*this);
     m_visitedLinkStore->removePage(*this);
 }
@@ -1510,19 +1508,6 @@ void Page::setSessionStorage(RefPtr<StorageNamespace>&& newStorage)
     m_sessionStorage = WTFMove(newStorage);
 }
 
-StorageNamespace* Page::ephemeralLocalStorage(bool optionalCreate)
-{
-    if (!m_ephemeralLocalStorage && optionalCreate)
-        m_ephemeralLocalStorage = m_storageNamespaceProvider->createEphemeralLocalStorageNamespace(*this, m_settings->sessionStorageQuota());
-
-    return m_ephemeralLocalStorage.get();
-}
-
-void Page::setEphemeralLocalStorage(RefPtr<StorageNamespace>&& newStorage)
-{
-    m_ephemeralLocalStorage = WTFMove(newStorage);
-}
-
 bool Page::hasCustomHTMLTokenizerTimeDelay() const
 {
     return m_settings->maxParseDuration() != -1;
@@ -2470,15 +2455,6 @@ void Page::setUserContentProvider(Ref<UserContentProvider>&& userContentProvider
     invalidateInjectedStyleSheetCacheInAllFrames();
 }
 
-void Page::setStorageNamespaceProvider(Ref<StorageNamespaceProvider>&& storageNamespaceProvider)
-{
-    m_storageNamespaceProvider->removePage(*this);
-    m_storageNamespaceProvider = WTFMove(storageNamespaceProvider);
-    m_storageNamespaceProvider->addPage(*this);
-
-    // This needs to reset all the local storage namespaces of all the pages.
-}
-
 VisitedLinkStore& Page::visitedLinkStore()
 {
     return m_visitedLinkStore;
@@ -2507,6 +2483,9 @@ void Page::setSessionID(PAL::SessionID sessionID)
         m_idbConnectionToServer = nullptr;
 #endif
 
+    if (sessionID != m_sessionID && m_sessionStorage)
+        m_sessionStorage->setSessionIDForTesting(sessionID);
+
     bool privateBrowsingStateChanged = (sessionID.isEphemeral() != m_sessionID.isEphemeral());
 
     m_sessionID = sessionID;
index c440234..7c86502 100644 (file)
@@ -507,9 +507,6 @@ public:
     StorageNamespace* sessionStorage(bool optionalCreate = true);
     void setSessionStorage(RefPtr<StorageNamespace>&&);
 
-    StorageNamespace* ephemeralLocalStorage(bool optionalCreate = true);
-    void setEphemeralLocalStorage(RefPtr<StorageNamespace>&&);
-
     bool hasCustomHTMLTokenizerTimeDelay() const;
     double customHTMLTokenizerTimeDelay() const;
 
@@ -599,7 +596,6 @@ public:
     CookieJar& cookieJar() { return m_cookieJar.get(); }
 
     StorageNamespaceProvider& storageNamespaceProvider() { return m_storageNamespaceProvider.get(); }
-    void setStorageNamespaceProvider(Ref<StorageNamespaceProvider>&&);
 
     PluginInfoProvider& pluginInfoProvider();
 
@@ -877,7 +873,6 @@ private:
     bool m_canStartMedia { true };
 
     RefPtr<StorageNamespace> m_sessionStorage;
-    RefPtr<StorageNamespace> m_ephemeralLocalStorage;
 
     TimerThrottlingState m_timerThrottlingState { TimerThrottlingState::Disabled };
     MonotonicTime m_timerThrottlingStateLastChangedTime;
index 9197b60..47dbb17 100644 (file)
@@ -97,11 +97,6 @@ ExceptionOr<void> Storage::removeItem(const String& key)
     return { };
 }
 
-bool Storage::prewarm()
-{
-    return m_storageArea->prewarm();
-}
-
 ExceptionOr<void> Storage::clear()
 {
     auto* frame = this->frame();
index 5215f47..28aa9ab 100644 (file)
@@ -46,7 +46,6 @@ public:
     ExceptionOr<void> removeItem(const String& key);
     ExceptionOr<void> clear();
     bool contains(const String& key) const;
-    bool prewarm();
 
     // Bindings support functions.
     bool isSupportedPropertyName(const String&) const;
index f39ccd7..5a9ffff 100644 (file)
@@ -58,9 +58,6 @@ public:
     virtual void incrementAccessCount() { }
     virtual void decrementAccessCount() { }
     virtual void closeDatabaseIfIdle() { }
-    virtual bool prewarm() { return false; }
-
-    virtual const SecurityOriginData& securityOrigin() const = 0;
 };
 
 } // namespace WebCore
index 55c6628..75b8b05 100644 (file)
 #include <wtf/Forward.h>
 #include <wtf/RefCounted.h>
 
+namespace PAL {
+class SessionID;
+}
+
 namespace WebCore {
 
 class Page;
@@ -39,6 +43,9 @@ public:
     virtual ~StorageNamespace() = default;
     virtual Ref<StorageArea> storageArea(const SecurityOriginData&) = 0;
     virtual Ref<StorageNamespace> copy(Page* newPage) = 0;
+
+    virtual PAL::SessionID sessionID() const = 0;
+    virtual void setSessionIDForTesting(PAL::SessionID) = 0;
 };
 
 } // namespace WebCore
index 5939aff..6c5a8de 100644 (file)
@@ -43,21 +43,6 @@ StorageNamespaceProvider::StorageNamespaceProvider()
 
 StorageNamespaceProvider::~StorageNamespaceProvider()
 {
-    ASSERT(m_pages.isEmpty());
-}
-
-void StorageNamespaceProvider::addPage(Page& page)
-{
-    ASSERT(!m_pages.contains(&page));
-
-    m_pages.add(&page);
-}
-
-void StorageNamespaceProvider::removePage(Page& page)
-{
-    ASSERT(m_pages.contains(&page));
-
-    m_pages.remove(&page);
 }
 
 Ref<StorageArea> StorageNamespaceProvider::localStorageArea(Document& document)
@@ -66,36 +51,47 @@ Ref<StorageArea> StorageNamespaceProvider::localStorageArea(Document& document)
     // so the Document had better still actually have a Page.
     ASSERT(document.page());
 
-    bool ephemeral = document.page()->usesEphemeralSession();
     bool transient = !document.securityOrigin().canAccessLocalStorage(&document.topOrigin());
 
     RefPtr<StorageNamespace> storageNamespace;
 
     if (transient)
-        storageNamespace = &transientLocalStorageNamespace(document.topOrigin());
-    else if (ephemeral)
-        storageNamespace = document.page()->ephemeralLocalStorage();
+        storageNamespace = &transientLocalStorageNamespace(document.topOrigin(), document.page()->sessionID());
     else
-        storageNamespace = &localStorageNamespace();
+        storageNamespace = &localStorageNamespace(document.page()->sessionID());
 
     return storageNamespace->storageArea(document.securityOrigin().data());
 }
 
-StorageNamespace& StorageNamespaceProvider::localStorageNamespace()
+StorageNamespace& StorageNamespaceProvider::localStorageNamespace(PAL::SessionID sessionID)
 {
     if (!m_localStorageNamespace)
-        m_localStorageNamespace = createLocalStorageNamespace(localStorageDatabaseQuotaInBytes);
+        m_localStorageNamespace = createLocalStorageNamespace(localStorageDatabaseQuotaInBytes, sessionID);
 
+    ASSERT(m_localStorageNamespace->sessionID() == sessionID);
     return *m_localStorageNamespace;
 }
 
-StorageNamespace& StorageNamespaceProvider::transientLocalStorageNamespace(SecurityOrigin& securityOrigin)
+StorageNamespace& StorageNamespaceProvider::transientLocalStorageNamespace(SecurityOrigin& securityOrigin, PAL::SessionID sessionID)
 {
-    auto& slot = m_transientLocalStorageMap.add(&securityOrigin, nullptr).iterator->value;
+    auto& slot = m_transientLocalStorageNamespaces.add(securityOrigin.data(), nullptr).iterator->value;
     if (!slot)
-        slot = createTransientLocalStorageNamespace(securityOrigin, localStorageDatabaseQuotaInBytes);
+        slot = createTransientLocalStorageNamespace(securityOrigin, localStorageDatabaseQuotaInBytes, sessionID);
 
+    ASSERT(slot->sessionID() == sessionID);
     return *slot;
 }
 
+void StorageNamespaceProvider::enableLegacyPrivateBrowsingForTesting(bool enabled)
+{
+    auto newSessionID = enabled ? PAL::SessionID::legacyPrivateSessionID() : PAL::SessionID::defaultSessionID();
+    if (m_localStorageNamespace && newSessionID != m_localStorageNamespace->sessionID())
+        m_localStorageNamespace->setSessionIDForTesting(newSessionID);
+    
+    for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values()) {
+        if (newSessionID != transientLocalStorageNamespace->sessionID())
+            m_localStorageNamespace->setSessionIDForTesting(newSessionID);
+    }
+}
+
 }
index dd7f9a4..01d064b 100644 (file)
 #include <wtf/HashSet.h>
 #include <wtf/RefCounted.h>
 
+namespace PAL {
+class SessionID;
+}
+
 namespace WebCore {
 
 class Document;
@@ -45,27 +49,23 @@ public:
     WEBCORE_EXPORT virtual ~StorageNamespaceProvider();
 
     virtual Ref<StorageNamespace> createSessionStorageNamespace(Page&, unsigned quota) = 0;
-    virtual Ref<StorageNamespace> createEphemeralLocalStorageNamespace(Page&, unsigned quota) = 0;
 
     Ref<StorageArea> localStorageArea(Document&);
 
-    void addPage(Page&);
-    void removePage(Page&);
+    WEBCORE_EXPORT void enableLegacyPrivateBrowsingForTesting(bool enabled);
 
 protected:
     StorageNamespace* optionalLocalStorageNamespace() { return m_localStorageNamespace.get(); }
 
 private:
-    StorageNamespace& localStorageNamespace();
-    StorageNamespace& transientLocalStorageNamespace(SecurityOrigin&);
-
-    virtual Ref<StorageNamespace> createLocalStorageNamespace(unsigned quota) = 0;
-    virtual Ref<StorageNamespace> createTransientLocalStorageNamespace(SecurityOrigin&, unsigned quota) = 0;
+    StorageNamespace& localStorageNamespace(PAL::SessionID);
+    StorageNamespace& transientLocalStorageNamespace(SecurityOrigin&, PAL::SessionID);
 
-    HashSet<Page*> m_pages;
+    virtual Ref<StorageNamespace> createLocalStorageNamespace(unsigned quota, PAL::SessionID) = 0;
+    virtual Ref<StorageNamespace> createTransientLocalStorageNamespace(SecurityOrigin&, unsigned quota, PAL::SessionID) = 0;
 
     RefPtr<StorageNamespace> m_localStorageNamespace;
-    HashMap<RefPtr<SecurityOrigin>, RefPtr<StorageNamespace>> m_transientLocalStorageMap;
+    HashMap<SecurityOriginData, RefPtr<StorageNamespace>> m_transientLocalStorageNamespaces;
 };
 
 } // namespace WebCore
index 58133f8..fe70025 100644 (file)
@@ -30,13 +30,12 @@ namespace WebCore {
 enum class StorageType {
     Session,
     Local,
-    EphemeralLocal,
     TransientLocal,
 };
 
 inline bool isLocalStorage(StorageType storageType)
 {
-    return storageType == StorageType::Local || storageType == StorageType::TransientLocal || storageType == StorageType::EphemeralLocal;
+    return storageType == StorageType::Local || storageType == StorageType::TransientLocal;
 }
 
 inline bool isPersistentLocalStorage(StorageType storageType)
index 6f79c86..d88aa83 100644 (file)
@@ -118,7 +118,7 @@ set(WebKit_MESSAGES_IN_FILES
     NetworkProcess/ServiceWorker/WebSWServerConnection.messages.in
     NetworkProcess/ServiceWorker/WebSWServerToContextConnection.messages.in
 
-    NetworkProcess/WebStorage/StorageManager.messages.in
+    NetworkProcess/WebStorage/StorageManagerSet.messages.in
 
     NetworkProcess/cache/CacheStorageEngineConnection.messages.in
 
index 780ec25..fd5ee7a 100644 (file)
@@ -1,3 +1,303 @@
+2019-08-15  Sihui Liu  <sihui_liu@apple.com>
+
+        Some improvements on web storage
+        https://bugs.webkit.org/show_bug.cgi?id=200373
+
+        Reviewed by Geoffrey Garen.
+
+        Fix some issues in web storage architecture. For example, sessionStorageNameSpace for web page is prepared and 
+        destroyed in the network process when the page comes and goes, even though the page may not use sessionStorage 
+        at all. The messages about page state sent from web process to network process can be waste.
+
+        Here are some general ideas of this patch:
+        1. Network process owns the web storage, and web process keeps a small local copy (based on session and 
+        origins that are visited). There is a virtual connection from the local copy in the web process to the original
+        copy in the network process. The connection is created by web process when some page asks for web storage.
+        2. If connection is lost because network process is gone, storage in memory will be lost. The local copy in web
+        processs will be discarded.
+        3. (SessionID, StorageNamespaceID, SecurityOrigin) is used to identify a storage area. If session is changed in
+        web process (like enabling private browsing in layout test now), a re-connection with different sessionID would 
+        suffice to load another copy of storage.
+        4. localStorage in ephemeral session has the same behavior as localStorage instead of sessionStorage, which
+        means different pages in the same ephemeral session share the same localStorage.
+
+        Also, this patch introduces StorageManagerSet to network process. It handles web storage stuff, including
+        receiving storage messages from web process, on one background thread. Previously each session has its own
+        StorageManager and each StorageManager has its own WorkQueue.
+
+        * CMakeLists.txt:
+        * DerivedSources-input.xcfilelist:
+        * DerivedSources-output.xcfilelist:
+        * DerivedSources.make:
+
+        * NetworkProcess/NetworkConnectionToWebProcess.cpp: remove message handlers that are no longer needed. Network
+        process no longer needs to know page states from web process.
+        (WebKit::NetworkConnectionToWebProcess::didClose):
+        (WebKit::NetworkConnectionToWebProcess::webPageWasAdded): Deleted.
+        (WebKit::NetworkConnectionToWebProcess::webPageWasRemoved): Deleted.
+        (WebKit::NetworkConnectionToWebProcess::webProcessSessionChanged): Deleted.
+        * NetworkProcess/NetworkConnectionToWebProcess.h:
+        * NetworkProcess/NetworkConnectionToWebProcess.messages.in:
+
+        * NetworkProcess/NetworkProcess.cpp: NetworkProcess uses StorageManagerSet instead of StorageManager from 
+        different sessions to deal with web storage.
+        (WebKit::NetworkProcess::NetworkProcess):
+        (WebKit::NetworkProcess::initializeNetworkProcess):
+        (WebKit::NetworkProcess::createNetworkConnectionToWebProcess): StorageManagerSet starts handling 
+        StorageManagerSet messages from the new connection.
+        (WebKit::NetworkProcess::addWebsiteDataStore):
+        (WebKit::NetworkProcess::destroySession):
+        (WebKit::NetworkProcess::hasLocalStorage):
+        (WebKit::NetworkProcess::fetchWebsiteData):
+        (WebKit::NetworkProcess::deleteWebsiteData):
+        (WebKit::NetworkProcess::deleteWebsiteDataForOrigins):
+        (WebKit::NetworkProcess::deleteWebsiteDataForRegistrableDomains):
+        (WebKit::NetworkProcess::actualPrepareToSuspend):
+        (WebKit::NetworkProcess::resume):
+        (WebKit::NetworkProcess::syncLocalStorage):
+        (WebKit::NetworkProcess::clearLegacyPrivateBrowsingLocalStorage): added for clearing in-memory ephemeral
+        localStorage.
+        (WebKit::NetworkProcess::getLocalStorageOriginDetails):
+        (WebKit::NetworkProcess::connectionToWebProcessClosed):
+        (WebKit::NetworkProcess::webPageWasAdded): Deleted.
+        (WebKit::NetworkProcess::webPageWasRemoved): Deleted.
+        (WebKit::NetworkProcess::webProcessWasDisconnected): Deleted.
+        (WebKit::NetworkProcess::webProcessSessionChanged): Deleted.
+        * NetworkProcess/NetworkProcess.h:
+        * NetworkProcess/NetworkProcess.messages.in:
+
+        * NetworkProcess/NetworkSession.cpp: StorageManager is moved out of NetworkSession. It is now managed by 
+        StorageManagerSet.
+        (WebKit::NetworkSession::NetworkSession):
+        (WebKit::NetworkSession::~NetworkSession):
+        * NetworkProcess/NetworkSession.h:
+        (WebKit::NetworkSession::storageManager): Deleted.
+
+        * NetworkProcess/NetworkSessionCreationParameters.cpp: creation parameters of StorageManager is moved out of
+        NetworkSessionCreationParameters.
+        (WebKit::NetworkSessionCreationParameters::privateSessionParameters):
+        (WebKit::NetworkSessionCreationParameters::encode const):
+        (WebKit::NetworkSessionCreationParameters::decode):
+        * NetworkProcess/NetworkSessionCreationParameters.h:
+
+        * NetworkProcess/WebStorage/LocalStorageDatabase.cpp:
+        (WebKit::LocalStorageDatabase::updateDatabase): remove an assertion that is no longer true as we can force an
+        update with syncLocalStorage now.
+        * NetworkProcess/WebStorage/LocalStorageDatabase.h: make updateDatabase public for syncLocalStorage.
+
+        * NetworkProcess/WebStorage/LocalStorageDatabaseTracker.cpp: LocalStorageDatabaseTracker is created on the
+        background thread now, so it does not hold WorkQueue to do the file operation.
+        (WebKit::LocalStorageDatabaseTracker::create):
+        (WebKit::LocalStorageDatabaseTracker::LocalStorageDatabaseTracker):
+        (WebKit::LocalStorageDatabaseTracker::~LocalStorageDatabaseTracker):
+        * NetworkProcess/WebStorage/LocalStorageDatabaseTracker.h:
+        * NetworkProcess/WebStorage/LocalStorageNamespace.cpp:
+        (WebKit::LocalStorageNamespace::getOrCreateStorageArea):
+        (WebKit::LocalStorageNamespace::cloneTo): Deleted.
+        * NetworkProcess/WebStorage/LocalStorageNamespace.h:
+        * NetworkProcess/WebStorage/SessionStorageNamespace.cpp:
+        (WebKit::SessionStorageNamespace::getOrCreateStorageArea):
+        (WebKit::SessionStorageNamespace::addAllowedConnection): Deleted.
+        (WebKit::SessionStorageNamespace::removeAllowedConnection): Deleted.
+        * NetworkProcess/WebStorage/SessionStorageNamespace.h:
+        (WebKit::SessionStorageNamespace::allowedConnections const): Deleted.
+
+        * NetworkProcess/WebStorage/StorageArea.cpp:
+        (WebKit::generateStorageAreaIdentifier): each StorageArea has an identifier. StorageAreaMap in web process uses
+        this identifier to indicate which StorageArea it is connecting to.
+        (WebKit::StorageArea::StorageArea):
+        (WebKit::StorageArea::~StorageArea): StorageArea may still have listeners because StorageArea should be 
+        destroyed by requests from UI process, and listeners are connections to web processses.
+        (WebKit::StorageArea::addListener): load localStorageDatabase in advance if there is some connection to this 
+        LocalStorage area.
+        (WebKit::StorageArea::removeListener):
+        (WebKit::StorageArea::hasListener const):
+        (WebKit::StorageArea::clear):
+        (WebKit::StorageArea::openDatabaseAndImportItemsIfNeeded const):
+        (WebKit::StorageArea::dispatchEvents const):
+        (WebKit::StorageArea::syncToDatabase):
+        (WebKit::StorageArea::setItems): Deleted. Stop syncing from web process to network process after network process
+        is relaunched.
+        * NetworkProcess/WebStorage/StorageArea.h:
+        (WebKit::StorageArea::identifier):
+        (WebKit::StorageArea::setWorkQueue):
+
+        * NetworkProcess/WebStorage/StorageManager.cpp: StorageManager should be accessed by only background thread now.
+        (WebKit::StorageManager::StorageManager):
+        (WebKit::StorageManager::~StorageManager):
+        (WebKit::StorageManager::createSessionStorageNamespace):
+        (WebKit::StorageManager::destroySessionStorageNamespace): this is not used now but keep it for future 
+        improvement to remove in-memory sessionStorage in network process if we know some web page is gone forever.
+        (WebKit::StorageManager::cloneSessionStorageNamespace): previously each page had its own ephemeral 
+        localStorageNamespace and now all pages in the same session share one localStorage, so we don't need to clone
+        localStorageNamespace.
+        (WebKit::StorageManager::getSessionStorageOrigins):
+        (WebKit::StorageManager::deleteSessionStorageOrigins):
+        (WebKit::StorageManager::deleteSessionStorageEntriesForOrigins):
+        (WebKit::StorageManager::getLocalStorageOrigins):
+        (WebKit::StorageManager::getLocalStorageOriginDetails):
+        (WebKit::StorageManager::deleteLocalStorageOriginsModifiedSince):
+        (WebKit::StorageManager::deleteLocalStorageEntriesForOrigins):
+        (WebKit::StorageManager::createLocalStorageArea):
+        (WebKit::StorageManager::createTransientLocalStorageArea):
+        (WebKit::StorageManager::createSessionStorageArea):
+        (WebKit::StorageManager::getOrCreateLocalStorageNamespace):
+        (WebKit::StorageManager::getOrCreateTransientLocalStorageNamespace):
+        (WebKit::StorageManager::getOrCreateSessionStorageNamespace):
+        (WebKit::StorageManager::clearStorageNamespaces):
+        (WebKit::StorageManager::addAllowedSessionStorageNamespaceConnection): Deleted.
+        (WebKit::StorageManager::removeAllowedSessionStorageNamespaceConnection): Deleted.
+        (WebKit::StorageManager::processDidCloseConnection): Deleted.
+        (WebKit::StorageManager::deleteLocalStorageEntriesForOrigin): Deleted.
+        (WebKit::StorageManager::createLocalStorageMap): Deleted.
+        (WebKit::StorageManager::createTransientLocalStorageMap): Deleted.
+        (WebKit::StorageManager::createSessionStorageMap): Deleted.
+        (WebKit::StorageManager::destroyStorageMap): Deleted.
+        (WebKit::StorageManager::prewarm): Deleted.
+        (WebKit::StorageManager::getValues): Deleted.
+        (WebKit::StorageManager::setItem): Deleted.
+        (WebKit::StorageManager::setItems): Deleted.
+        (WebKit::StorageManager::removeItem): Deleted.
+        (WebKit::StorageManager::clear): Deleted.
+        (WebKit::StorageManager::waitUntilTasksFinished): Deleted.
+        (WebKit::StorageManager::suspend): Deleted.
+        (WebKit::StorageManager::resume): Deleted.
+        (WebKit::StorageManager::findStorageArea const): Deleted.
+        * NetworkProcess/WebStorage/StorageManager.h:
+        (WebKit::StorageManager::workQueue const): Deleted.
+        (): Deleted.
+
+        * NetworkProcess/WebStorage/StorageManager.messages.in: Removed. Moved to StorageManagerSet.messages.in.
+
+        * NetworkProcess/WebStorage/StorageManagerSet.cpp: Added.
+        (WebKit::StorageManagerSet::create):
+        (WebKit::StorageManagerSet::StorageManagerSet):
+        (WebKit::StorageManagerSet::~StorageManagerSet):
+        (WebKit::StorageManagerSet::add):
+        (WebKit::StorageManagerSet::remove):
+        (WebKit::StorageManagerSet::contains):
+        (WebKit::StorageManagerSet::addConnection):
+        (WebKit::StorageManagerSet::removeConnection):
+        (WebKit::StorageManagerSet::waitUntilTasksFinished):
+        (WebKit::StorageManagerSet::waitUntilSyncingLocalStorageFinished):
+        (WebKit::StorageManagerSet::suspend):
+        (WebKit::StorageManagerSet::resume):
+        (WebKit::StorageManagerSet::getSessionStorageOrigins):
+        (WebKit::StorageManagerSet::deleteSessionStorage):
+        (WebKit::StorageManagerSet::deleteSessionStorageForOrigins):
+        (WebKit::StorageManagerSet::getLocalStorageOrigins):
+        (WebKit::StorageManagerSet::deleteLocalStorageModifiedSince):
+        (WebKit::StorageManagerSet::deleteLocalStorageForOrigins):
+        (WebKit::StorageManagerSet::getLocalStorageOriginDetails):
+        (WebKit::StorageManagerSet::connectToLocalStorageArea):
+        (WebKit::StorageManagerSet::connectToTransientLocalStorageArea):
+        (WebKit::StorageManagerSet::connectToSessionStorageArea):
+        (WebKit::StorageManagerSet::disconnectFromStorageArea):
+        (WebKit::StorageManagerSet::getValues):
+        (WebKit::StorageManagerSet::setItem):
+        (WebKit::StorageManagerSet::removeItem):
+        (WebKit::StorageManagerSet::clear):
+        (WebKit::StorageManagerSet::cloneSessionStorageNamespace):
+        * NetworkProcess/WebStorage/StorageManagerSet.h: Added.
+        * NetworkProcess/WebStorage/StorageManagerSet.messages.in: Added.
+
+        * Shared/WebsiteDataStoreParameters.cpp: creation parameters of StorageManager are moved to 
+        WebsiteDataStoreParameters.
+        (WebKit::WebsiteDataStoreParameters::encode const):
+        (WebKit::WebsiteDataStoreParameters::decode):
+        (WebKit::WebsiteDataStoreParameters::privateSessionParameters):
+        * Shared/WebsiteDataStoreParameters.h:
+        * Sources.txt:
+
+        * UIProcess/API/C/WKContext.cpp: add SPI for tests.
+        (WKContextSyncLocalStorage):
+        (WKContextClearLegacyPrivateBrowsingLocalStorage):
+        * UIProcess/API/C/WKContextPrivate.h:
+        * UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
+        (WKWebsiteDataStoreRemoveLocalStorage):
+        * UIProcess/API/C/WKWebsiteDataStoreRef.h:
+        * UIProcess/WebProcessPool.cpp:
+        (WebKit::WebProcessPool::ensureNetworkProcess):
+        (WebKit::WebProcessPool::syncLocalStorage):
+        (WebKit::WebProcessPool::clearLegacyPrivateBrowsingLocalStorage):
+        * UIProcess/WebProcessPool.h:
+        * UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm:
+        (WebKit::WebsiteDataStore::parameters):
+        * UIProcess/WebsiteData/WebsiteDataStore.cpp:
+        (WebKit::WebsiteDataStore::parameters):
+        * WebKit.xcodeproj/project.pbxproj:
+
+        * WebProcess/InjectedBundle/InjectedBundle.cpp: session change of web storage is done via 
+        WebStorageNamespaceProvider instead of WebProcess now.
+        (WebKit::InjectedBundle::setPrivateBrowsingEnabled):
+        * WebProcess/WebProcess.cpp: web process no longer sends messsages about page state to network process.
+        (WebKit::WebProcess::createWebPage):
+        (WebKit::WebProcess::removeWebPage):
+        (WebKit::WebProcess::ensureNetworkProcessConnection):
+        (WebKit::WebProcess::networkProcessConnectionClosed):
+        (WebKit::WebProcess::storageAreaMap const):
+        (WebKit::WebProcess::enablePrivateBrowsingForTesting): Deleted. This was used for changing session via 
+        WebProcess.
+        * WebProcess/WebProcess.h:
+        * WebProcess/WebStorage/StorageAreaImpl.cpp:
+        (WebKit::StorageAreaImpl::StorageAreaImpl):
+        (WebKit::StorageAreaImpl::length):
+        (WebKit::StorageAreaImpl::key):
+        (WebKit::StorageAreaImpl::item):
+        (WebKit::StorageAreaImpl::setItem):
+        (WebKit::StorageAreaImpl::removeItem):
+        (WebKit::StorageAreaImpl::clear):
+        (WebKit::StorageAreaImpl::contains):
+        (WebKit::StorageAreaImpl::storageType const):
+        (WebKit::StorageAreaImpl::incrementAccessCount):
+        (WebKit::StorageAreaImpl::decrementAccessCount):
+        (WebKit::StorageAreaImpl::prewarm): Deleted.
+        (WebKit::StorageAreaImpl::securityOrigin const): Deleted.
+
+        * WebProcess/WebStorage/StorageAreaImpl.h: make StorageAreaImpl hold a weak reference to StorageAreaMap and 
+        StorageNamespaceImpl hold a strong reference. In this way lifeime of localStorage StorageAreraMap stays align 
+        with StorageNameSpaceProvider and Page.
+
+        * WebProcess/WebStorage/StorageAreaMap.cpp: identifier of StorageAreaMap is the same as identifier of 
+        StorageArea it connects to. If the identifier is 0, it means the StorageAreaMap is disconnected.
+        (WebKit::StorageAreaMap::StorageAreaMap):
+        (WebKit::StorageAreaMap::~StorageAreaMap):
+        (WebKit::StorageAreaMap::setItem):
+        (WebKit::StorageAreaMap::removeItem):
+        (WebKit::StorageAreaMap::clear):
+        (WebKit::StorageAreaMap::resetValues):
+        (WebKit::StorageAreaMap::loadValuesIfNeeded):
+        (WebKit::StorageAreaMap::applyChange):
+        (WebKit::StorageAreaMap::dispatchStorageEvent):
+        (WebKit::StorageAreaMap::dispatchSessionStorageEvent):
+        (WebKit::StorageAreaMap::dispatchLocalStorageEvent):
+        (WebKit::StorageAreaMap::connect):
+        (WebKit::StorageAreaMap::disconnect):
+        (WebKit::generateStorageMapID): Deleted.
+        (WebKit::StorageAreaMap::prewarm): Deleted.
+        (WebKit::StorageAreaMap::didGetValues): Deleted. This is useless as GetValues is a synchronous operation.
+        * WebProcess/WebStorage/StorageAreaMap.h:
+        (): Deleted.
+
+        * WebProcess/WebStorage/StorageAreaMap.messages.in: there are two synchronous messages, one for connection and 
+        one for getting values. We may merge them into one in future improvement.
+        * WebProcess/WebStorage/StorageNamespaceImpl.cpp:
+        (WebKit::StorageNamespaceImpl::createSessionStorageNamespace):
+        (WebKit::StorageNamespaceImpl::createLocalStorageNamespace):
+        (WebKit::StorageNamespaceImpl::createTransientLocalStorageNamespace):
+        (WebKit::StorageNamespaceImpl::StorageNamespaceImpl):
+        (WebKit::StorageNamespaceImpl::storageArea):
+        (WebKit::StorageNamespaceImpl::copy):
+        (WebKit::StorageNamespaceImpl::setSessionIDForTesting):
+        (WebKit::StorageNamespaceImpl::createEphemeralLocalStorageNamespace): Deleted.
+        * WebProcess/WebStorage/StorageNamespaceImpl.h:
+        * WebProcess/WebStorage/WebStorageNamespaceProvider.cpp:
+        (WebKit::WebStorageNamespaceProvider::createSessionStorageNamespace):
+        (WebKit::WebStorageNamespaceProvider::createLocalStorageNamespace):
+        (WebKit::WebStorageNamespaceProvider::createTransientLocalStorageNamespace):
+        (WebKit::WebStorageNamespaceProvider::createEphemeralLocalStorageNamespace): Deleted.
+        * WebProcess/WebStorage/WebStorageNamespaceProvider.h:
+
 2019-08-15  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         Occasional hang under -[UIKeyboardTaskQueue lockWhenReadyForMainThread] when long-pressing non-editable text
index 0fb8423..2e47660 100644 (file)
@@ -25,7 +25,7 @@ $(PROJECT_DIR)/NetworkProcess/NetworkSocketStream.messages.in
 $(PROJECT_DIR)/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.messages.in
 $(PROJECT_DIR)/NetworkProcess/ServiceWorker/WebSWServerConnection.messages.in
 $(PROJECT_DIR)/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.messages.in
-$(PROJECT_DIR)/NetworkProcess/WebStorage/StorageManager.messages.in
+$(PROJECT_DIR)/NetworkProcess/WebStorage/StorageManagerSet.messages.in
 $(PROJECT_DIR)/NetworkProcess/cache/CacheStorageEngineConnection.messages.in
 $(PROJECT_DIR)/NetworkProcess/mac/com.apple.WebKit.NetworkProcess.sb.in
 $(PROJECT_DIR)/NetworkProcess/webrtc/NetworkMDNSRegister.messages.in
@@ -83,7 +83,6 @@ $(PROJECT_DIR)/UIProcess/WebPageProxy.messages.in
 $(PROJECT_DIR)/UIProcess/WebPasteboardProxy.messages.in
 $(PROJECT_DIR)/UIProcess/WebProcessPool.messages.in
 $(PROJECT_DIR)/UIProcess/WebProcessProxy.messages.in
-$(PROJECT_DIR)/UIProcess/WebStorage/StorageManager.messages.in
 $(PROJECT_DIR)/UIProcess/ios/EditableImageController.messages.in
 $(PROJECT_DIR)/UIProcess/ios/SmartMagnificationController.messages.in
 $(PROJECT_DIR)/UIProcess/mac/SecItemShimProxy.messages.in
index fe0a6c0..bd9dd7f 100644 (file)
@@ -88,8 +88,8 @@ $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/SmartMagnificationControllerMessage
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/SmartMagnificationControllerMessages.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/StorageAreaMapMessageReceiver.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/StorageAreaMapMessages.h
-$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/StorageManagerMessageReceiver.cpp
-$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/StorageManagerMessages.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/StorageManagerSetMessageReceiver.cpp
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/StorageManagerSetMessages.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/TextCheckingControllerProxyMessageReceiver.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/TextCheckingControllerProxyMessages.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/UserMediaCaptureManagerMessageReceiver.cpp
index 5393c5b..9de7042 100644 (file)
@@ -136,7 +136,7 @@ MESSAGE_RECEIVERS = \
     ServiceWorkerFetchTask \
     SmartMagnificationController \
     StorageAreaMap \
-    StorageManager \
+    StorageManagerSet \
     TextCheckingControllerProxy \
     UserMediaCaptureManager \
     UserMediaCaptureManagerProxy \
index 0c2c976..bbe9a9a 100644 (file)
@@ -49,7 +49,6 @@
 #include "PingLoad.h"
 #include "PreconnectTask.h"
 #include "ServiceWorkerFetchTaskMessages.h"
-#include "StorageManager.h"
 #include "WebCoreArgumentCoders.h"
 #include "WebErrors.h"
 #include "WebIDBConnectionToClient.h"
@@ -299,7 +298,7 @@ void NetworkConnectionToWebProcess::didClose(IPC::Connection& connection)
     // root activity trackers.
     stopAllNetworkActivityTracking();
 
-    m_networkProcess->webProcessWasDisconnected(connection);
+    m_networkProcess->connectionToWebProcessClosed(connection);
 
     m_networkProcess->removeNetworkConnectionToWebProcess(*this);
 
@@ -915,19 +914,4 @@ void NetworkConnectionToWebProcess::establishSWServerConnection(PAL::SessionID s
 }
 #endif
 
-void NetworkConnectionToWebProcess::webPageWasAdded(PAL::SessionID sessionID, PageIdentifier pageID, WebCore::PageIdentifier oldPageID)
-{
-    m_networkProcess->webPageWasAdded(m_connection.get(), sessionID, pageID, oldPageID);
-}
-
-void NetworkConnectionToWebProcess::webPageWasRemoved(PAL::SessionID sessionID, PageIdentifier pageID)
-{
-    m_networkProcess->webPageWasRemoved(m_connection.get(), sessionID, pageID);
-}
-
-void NetworkConnectionToWebProcess::webProcessSessionChanged(PAL::SessionID newSessionID, const Vector<PageIdentifier>& pages)
-{
-    m_networkProcess->webProcessSessionChanged(m_connection.get(), newSessionID, pages);
-}
-
 } // namespace WebKit
index 255084f..0aa02d3 100644 (file)
@@ -141,10 +141,6 @@ public:
 
     Vector<RefPtr<WebCore::BlobDataFileReference>> resolveBlobReferences(const NetworkResourceLoadParameters&);
 
-    void webPageWasAdded(PAL::SessionID, WebCore::PageIdentifier, WebCore::PageIdentifier oldPageID);
-    void webPageWasRemoved(PAL::SessionID, WebCore::PageIdentifier);
-    void webProcessSessionChanged(PAL::SessionID newSessionID, const Vector<WebCore::PageIdentifier>& pages);
-
     void removeSocketChannel(uint64_t identifier);
 
 private:
index 99abd07..fd4b248 100644 (file)
@@ -86,8 +86,4 @@ messages -> NetworkConnectionToWebProcess LegacyReceiver {
 #if ENABLE(SERVICE_WORKER)
     EstablishSWServerConnection(PAL::SessionID sessionID) -> (WebCore::SWServerConnectionIdentifier serverConnectionIdentifier) Synchronous
 #endif
-
-    WebPageWasAdded(PAL::SessionID sessionID, WebCore::PageIdentifier pageID, WebCore::PageIdentifier oldPageID)
-    WebPageWasRemoved(PAL::SessionID sessionID, WebCore::PageIdentifier pageID)
-    WebProcessSessionChanged(PAL::SessionID newSessionID, Vector<WebCore::PageIdentifier> pages)
 }
index e820b29..fbe8e68 100644 (file)
@@ -53,8 +53,7 @@
 #include "ShouldGrandfatherStatistics.h"
 #include "StatisticsData.h"
 #include "StorageAccessStatus.h"
-#include "StorageManager.h"
-#include "StorageManagerMessages.h"
+#include "StorageManagerSet.h"
 #include "WebCookieManager.h"
 #include "WebPageProxyMessages.h"
 #include "WebProcessPoolMessages.h"
@@ -133,6 +132,7 @@ static void callExitSoon(IPC::Connection*)
 
 NetworkProcess::NetworkProcess(AuxiliaryProcessInitializationParameters&& parameters)
     : m_downloadManager(*this)
+    , m_storageManagerSet(StorageManagerSet::create())
 #if ENABLE(CONTENT_EXTENSIONS)
     , m_networkContentRuleListManager(*this)
 #endif
@@ -336,6 +336,8 @@ void NetworkProcess::initializeNetworkProcess(NetworkProcessCreationParameters&&
 #endif
     initializeStorageQuota(parameters.defaultDataStoreParameters);
 
+    m_storageManagerSet->add(sessionID, parameters.defaultDataStoreParameters.localStorageDirectory, parameters.defaultDataStoreParameters.localStorageDirectoryExtensionHandle);
+
     auto* defaultSession = networkSession(PAL::SessionID::defaultSessionID());
     auto* defaultStorageSession = defaultSession->networkStorageSession();
     for (const auto& cookie : parameters.defaultDataStoreParameters.pendingCookies)
@@ -447,6 +449,8 @@ void NetworkProcess::createNetworkConnectionToWebProcess(bool isServiceWorkerPro
     UNUSED_PARAM(isServiceWorkerProcess);
     UNUSED_PARAM(registrableDomain);
 #endif
+
+    m_storageManagerSet->addConnection(m_webProcessConnections.last()->connection());
 }
 
 void NetworkProcess::clearCachedCredentials()
@@ -469,6 +473,8 @@ void NetworkProcess::addWebsiteDataStore(WebsiteDataStoreParameters&& parameters
         addServiceWorkerSession(parameters.networkSessionParameters.sessionID, parameters.serviceWorkerRegistrationDirectory, parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
 #endif
 
+    m_storageManagerSet->add(parameters.networkSessionParameters.sessionID, parameters.localStorageDirectory, parameters.localStorageDirectoryExtensionHandle);
+
     initializeStorageQuota(parameters);
 
     RemoteNetworkingContext::ensureWebsiteDataStoreSession(*this, WTFMove(parameters));
@@ -609,6 +615,8 @@ void NetworkProcess::destroySession(const PAL::SessionID& sessionID)
     m_swDatabasePaths.remove(sessionID);
 #endif
 
+    m_storageManagerSet->remove(sessionID);
+
     m_storageQuotaManagers.remove(sessionID);
 }
 
@@ -1050,8 +1058,8 @@ void NetworkProcess::clearUserInteraction(PAL::SessionID sessionID, const Regist
 
 void NetworkProcess::hasLocalStorage(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
 {
-    if (auto* session = networkSession(sessionID)) {
-        session->storageManager().getLocalStorageOrigins([domain, completionHandler = WTFMove(completionHandler)](auto&& origins) mutable {
+    if (m_storageManagerSet->contains(sessionID)) {
+        m_storageManagerSet->getLocalStorageOrigins(sessionID, [domain, completionHandler = WTFMove(completionHandler)](auto&& origins) mutable {
             completionHandler(WTF::anyOf(origins, [&domain](auto& origin) {
                 return domain.matches(origin);
             }));
@@ -1340,16 +1348,15 @@ void NetworkProcess::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<Websit
         });
     }
 
-    auto* session = networkSession(sessionID);
-    if (websiteDataTypes.contains(WebsiteDataType::SessionStorage) && session) {
-        session->storageManager().getSessionStorageOrigins([callbackAggregator = callbackAggregator.copyRef()](auto&& origins) {
+    if (websiteDataTypes.contains(WebsiteDataType::SessionStorage) && m_storageManagerSet->contains(sessionID)) {
+        m_storageManagerSet->getSessionStorageOrigins(sessionID, [callbackAggregator = callbackAggregator.copyRef()](auto&& origins) {
             while (!origins.isEmpty())
                 callbackAggregator->m_websiteData.entries.append(WebsiteData::Entry { origins.takeAny(), WebsiteDataType::SessionStorage, 0 });
         });
     }
 
-    if (websiteDataTypes.contains(WebsiteDataType::LocalStorage) && session) {
-        session->storageManager().getLocalStorageOrigins([callbackAggregator = callbackAggregator.copyRef()](auto&& origins) {
+    if (websiteDataTypes.contains(WebsiteDataType::LocalStorage) && m_storageManagerSet->contains(sessionID)) {
+        m_storageManagerSet->getLocalStorageOrigins(sessionID, [callbackAggregator = callbackAggregator.copyRef()](auto&& origins) {
             while (!origins.isEmpty())
                 callbackAggregator->m_websiteData.entries.append(WebsiteData::Entry { origins.takeAny(), WebsiteDataType::LocalStorage, 0 });
         });
@@ -1424,12 +1431,11 @@ void NetworkProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<Websi
     if (websiteDataTypes.contains(WebsiteDataType::DOMCache))
         CacheStorage::Engine::clearAllCaches(*this, sessionID, [clearTasksHandler = clearTasksHandler.copyRef()] { });
 
-    auto* session = networkSession(sessionID);
-    if (websiteDataTypes.contains(WebsiteDataType::SessionStorage) && session)
-        session->storageManager().deleteSessionStorageOrigins([clearTasksHandler = clearTasksHandler.copyRef()] { });
+    if (websiteDataTypes.contains(WebsiteDataType::SessionStorage) && m_storageManagerSet->contains(sessionID))
+        m_storageManagerSet->deleteSessionStorage(sessionID, [clearTasksHandler = clearTasksHandler.copyRef()] { });
 
-    if (websiteDataTypes.contains(WebsiteDataType::LocalStorage) && session)
-        session->storageManager().deleteLocalStorageOriginsModifiedSince(modifiedSince, [clearTasksHandler = clearTasksHandler.copyRef()] { });
+    if (websiteDataTypes.contains(WebsiteDataType::LocalStorage) && m_storageManagerSet->contains(sessionID))
+        m_storageManagerSet->deleteLocalStorageModifiedSince(sessionID, modifiedSince, [clearTasksHandler = clearTasksHandler.copyRef()] { });
 
 #if ENABLE(INDEXED_DATABASE)
     if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !sessionID.isEphemeral())
@@ -1524,12 +1530,11 @@ void NetworkProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, Optio
             CacheStorage::Engine::clearCachesForOrigin(*this, sessionID, SecurityOriginData { originData }, [clearTasksHandler = clearTasksHandler.copyRef()] { });
     }
 
-    auto* session = networkSession(sessionID);
-    if (websiteDataTypes.contains(WebsiteDataType::SessionStorage) && session)
-        session->storageManager().deleteSessionStorageEntriesForOrigins(originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { });
+    if (websiteDataTypes.contains(WebsiteDataType::SessionStorage) && m_storageManagerSet->contains(sessionID))
+        m_storageManagerSet->deleteSessionStorageForOrigins(sessionID, originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { });
 
-    if (websiteDataTypes.contains(WebsiteDataType::LocalStorage) && session)
-        session->storageManager().deleteLocalStorageEntriesForOrigins(originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { });
+    if (websiteDataTypes.contains(WebsiteDataType::LocalStorage) && m_storageManagerSet->contains(sessionID))
+        m_storageManagerSet->deleteLocalStorageForOrigins(sessionID, originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { });
 
 #if ENABLE(INDEXED_DATABASE)
     if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !sessionID.isEphemeral())
@@ -1726,20 +1731,18 @@ void NetworkProcess::deleteWebsiteDataForRegistrableDomains(PAL::SessionID sessi
         });
     }
 
-    auto* session = networkSession(sessionID);
-    if (session) {
-        auto& storageManager = session->storageManager();
+    if (m_storageManagerSet->contains(sessionID)) {
         if (websiteDataTypes.contains(WebsiteDataType::SessionStorage)) {
-            storageManager.getSessionStorageOrigins([storageManager = makeRefPtr(storageManager), callbackAggregator = callbackAggregator.copyRef(), domainsToDeleteAllButCookiesFor](auto&& origins) {
+            m_storageManagerSet->getSessionStorageOrigins(sessionID, [protectedThis = makeRef(*this), this, sessionID, callbackAggregator = callbackAggregator.copyRef(), domainsToDeleteAllButCookiesFor](auto&& origins) {
                 auto originsToDelete = filterForRegistrableDomains(origins, domainsToDeleteAllButCookiesFor, callbackAggregator->m_domains);
-                storageManager->deleteSessionStorageEntriesForOrigins(originsToDelete, [callbackAggregator = callbackAggregator.copyRef()] { });
+                m_storageManagerSet->deleteSessionStorageForOrigins(sessionID, originsToDelete, [callbackAggregator = callbackAggregator.copyRef()] { });
             });
         }
 
         if (websiteDataTypes.contains(WebsiteDataType::LocalStorage)) {
-            storageManager.getLocalStorageOrigins([storageManager = makeRefPtr(storageManager), callbackAggregator = callbackAggregator.copyRef(), domainsToDeleteAllButCookiesFor](auto&& origins) {
+            m_storageManagerSet->getLocalStorageOrigins(sessionID, [protectedThis = makeRef(*this), this, sessionID, callbackAggregator = callbackAggregator.copyRef(), domainsToDeleteAllButCookiesFor](auto&& origins) {
                 auto originsToDelete = filterForRegistrableDomains(origins, domainsToDeleteAllButCookiesFor, callbackAggregator->m_domains);
-                storageManager->deleteLocalStorageEntriesForOrigins(originsToDelete, [callbackAggregator = callbackAggregator.copyRef()] { });
+                m_storageManagerSet->deleteLocalStorageForOrigins(sessionID, originsToDelete, [callbackAggregator = callbackAggregator.copyRef()] { });
             });
         }
     }
@@ -2111,9 +2114,7 @@ void NetworkProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend
     }
 #endif
 
-    forEachNetworkSession([&callbackAggregator](auto& session) {
-        session.storageManager().suspend([callbackAggregator] { });
-    });
+    m_storageManagerSet->suspend([callbackAggregator] { });
 }
 
 void NetworkProcess::processWillSuspendImminently()
@@ -2189,9 +2190,7 @@ void NetworkProcess::resume()
         server->resume();
 #endif
 
-    forEachNetworkSession([](auto& session) {
-        session.storageManager().resume();
-    });
+    m_storageManagerSet->resume();
 }
 
 void NetworkProcess::prefetchDNS(const String& hostname)
@@ -2396,6 +2395,18 @@ void NetworkProcess::setIDBPerOriginQuota(uint64_t quota)
 }
 #endif // ENABLE(INDEXED_DATABASE)
 
+void NetworkProcess::syncLocalStorage(CompletionHandler<void()>&& completionHandler)
+{
+    m_storageManagerSet->waitUntilSyncingLocalStorageFinished();
+    completionHandler();
+}
+
+void NetworkProcess::clearLegacyPrivateBrowsingLocalStorage()
+{
+    if (m_storageManagerSet->contains(PAL::SessionID::legacyPrivateSessionID()))
+        m_storageManagerSet->deleteLocalStorageModifiedSince(PAL::SessionID::legacyPrivateSessionID(), -WallTime::infinity(), []() { });
+}
+
 void NetworkProcess::updateQuotaBasedOnSpaceUsageForTesting(PAL::SessionID sessionID, const ClientOrigin& origin)
 {
     auto& manager = storageQuotaManager(sessionID, origin);
@@ -2703,80 +2714,21 @@ void NetworkProcess::removeKeptAliveLoad(NetworkResourceLoader& loader)
         session->removeKeptAliveLoad(loader);
 }
 
-void NetworkProcess::webPageWasAdded(IPC::Connection& connection, PAL::SessionID sessionID, PageIdentifier pageID, PageIdentifier oldPageID)
-{
-    if (!pageID || !oldPageID) {
-        LOG_ERROR("Cannot add page with invalid id");
-        return;
-    }
-
-    auto* session = networkSession(sessionID);
-    if (!session) {
-        LOG_ERROR("Cannot add page to an unknown session");
-        return;
-    }
-    auto& storageManager = session->storageManager();
-
-    auto addResult = m_sessionByConnection.add(connection.uniqueID(), sessionID);
-    ASSERT_UNUSED(addResult, addResult.iterator->value == sessionID);
-
-    storageManager.createSessionStorageNamespace(pageID.toUInt64(), std::numeric_limits<unsigned>::max());
-    storageManager.addAllowedSessionStorageNamespaceConnection(pageID.toUInt64(), connection);
-    if (pageID != oldPageID)
-        storageManager.cloneSessionStorageNamespace(oldPageID.toUInt64(), pageID.toUInt64());
-}
-
-void NetworkProcess::webPageWasRemoved(IPC::Connection& connection, PAL::SessionID sessionID, PageIdentifier pageID)
-{
-    if (!pageID) {
-        LOG_ERROR("Cannot remove page with invalid id");
-        return;
-    }
-
-    auto* session = networkSession(sessionID);
-    // Session can be destroyed before page gets removed.
-    if (!session)
-        return;
-
-    auto& storageManager = session->storageManager();
-    storageManager.removeAllowedSessionStorageNamespaceConnection(pageID.toUInt64(), connection);
-    storageManager.destroySessionStorageNamespace(pageID.toUInt64());
-}
-
-void NetworkProcess::webProcessWasDisconnected(IPC::Connection& connection)
-{
-    auto sessionID = m_sessionByConnection.take(connection.uniqueID());
-    if (!sessionID.isValid())
-        return;
-
-    if (auto* session = networkSession(sessionID))
-        session->storageManager().processDidCloseConnection(connection);
-}
-
-void NetworkProcess::webProcessSessionChanged(IPC::Connection& connection, PAL::SessionID newSessionID, const Vector<PageIdentifier>& 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)
 {
-    auto* session = networkSession(sessionID);
-    if (!session) {
+    if (!m_storageManagerSet->contains(sessionID)) {
         LOG_ERROR("Cannot get local storage information for an unknown session");
         return;
     }
 
-    auto& storageManager = session->storageManager();
-    storageManager.getLocalStorageOriginDetails([completionHandler = WTFMove(completionHandler)](auto&& details) mutable {
+    m_storageManagerSet->getLocalStorageOriginDetails(sessionID, [completionHandler = WTFMove(completionHandler)](auto&& details) mutable {
         completionHandler(WTFMove(details));
     });
 }
 
+void NetworkProcess::connectionToWebProcessClosed(IPC::Connection& connection)
+{
+    m_storageManagerSet->removeConnection(connection);
+}
+
 } // namespace WebKit
index 6121bad..3211e90 100644 (file)
@@ -97,6 +97,7 @@ class NetworkConnectionToWebProcess;
 class NetworkProcessSupplement;
 class NetworkProximityManager;
 class NetworkResourceLoader;
+class StorageManagerSet;
 class WebSWServerConnection;
 class WebSWServerToContextConnection;
 enum class ShouldGrandfatherStatistics : bool;
@@ -269,10 +270,7 @@ public:
     void setSessionIsControlledByAutomation(PAL::SessionID, bool);
     bool sessionIsControlledByAutomation(PAL::SessionID) const;
 
-    void webPageWasAdded(IPC::Connection&, PAL::SessionID, WebCore::PageIdentifier, WebCore::PageIdentifier);
-    void webPageWasRemoved(IPC::Connection&, PAL::SessionID, WebCore::PageIdentifier);
-    void webProcessWasDisconnected(IPC::Connection&);
-    void webProcessSessionChanged(IPC::Connection&, PAL::SessionID, const Vector<WebCore::PageIdentifier>&);
+    void connectionToWebProcessClosed(IPC::Connection&);
     void getLocalStorageOriginDetails(PAL::SessionID, CompletionHandler<void(Vector<LocalStorageDatabaseTracker::OriginDetails>&&)>&&);
 
 #if ENABLE(CONTENT_EXTENSIONS)
@@ -285,6 +283,10 @@ public:
     void accessToTemporaryFileComplete(const String& path) final;
     void setIDBPerOriginQuota(uint64_t);
 #endif
+
+    void syncLocalStorage(CompletionHandler<void()>&&);
+    void clearLegacyPrivateBrowsingLocalStorage();
+
     void updateQuotaBasedOnSpaceUsageForTesting(PAL::SessionID, const WebCore::ClientOrigin&);
 
 #if ENABLE(SANDBOX_EXTENSIONS)
@@ -499,6 +501,8 @@ private:
     HashMap<PAL::SessionID, std::unique_ptr<WebCore::NetworkStorageSession>> m_networkStorageSessions;
     mutable std::unique_ptr<WebCore::NetworkStorageSession> m_defaultNetworkStorageSession;
 
+    RefPtr<StorageManagerSet> m_storageManagerSet;
+
 #if PLATFORM(COCOA)
     void platformInitializeNetworkProcessCocoa(const NetworkProcessCreationParameters&);
     void setStorageAccessAPIEnabled(bool);
index b76daa1..c553a88 100644 (file)
@@ -163,6 +163,10 @@ messages -> NetworkProcess LegacyReceiver {
 #if ENABLE(INDEXED_DATABASE)
     SetIDBPerOriginQuota(uint64_t quota)
 #endif
+
+    SyncLocalStorage() -> () Synchronous
+    ClearLegacyPrivateBrowsingLocalStorage()
+
     UpdateQuotaBasedOnSpaceUsageForTesting(PAL::SessionID sessionID, struct WebCore::ClientOrigin origin)
 
     StoreAdClickAttribution(PAL::SessionID sessionID, WebCore::AdClickAttribution adClickAttribution)
index 488b929..1a13962 100644 (file)
@@ -33,7 +33,6 @@
 #include "NetworkResourceLoadParameters.h"
 #include "NetworkResourceLoader.h"
 #include "PingLoad.h"
-#include "StorageManager.h"
 #include "WebPageProxy.h"
 #include "WebPageProxyMessages.h"
 #include "WebProcessProxy.h"
@@ -85,7 +84,6 @@ NetworkSession::NetworkSession(NetworkProcess& networkProcess, const NetworkSess
     , m_enableResourceLoadStatisticsLogTestingEvent(parameters.enableResourceLoadStatisticsLogTestingEvent)
 #endif
     , m_adClickAttribution(makeUniqueRef<AdClickAttributionManager>(parameters.sessionID))
-    , m_storageManager(StorageManager::create(String(parameters.localStorageDirectory)))
 {
     if (!m_sessionID.isEphemeral()) {
         String networkCacheDirectory = parameters.networkCacheDirectory;
@@ -99,7 +97,6 @@ NetworkSession::NetworkSession(NetworkProcess& networkProcess, const NetworkSess
             RELEASE_LOG_ERROR(NetworkCache, "Failed to initialize the WebKit network disk cache");
     }
 
-    SandboxExtension::consumePermanently(parameters.localStorageDirectoryExtensionHandle);
     m_adClickAttribution->setPingLoadFunction([this, weakThis = makeWeakPtr(this)](NetworkResourceLoadParameters&& loadParameters, CompletionHandler<void(const WebCore::ResourceError&, const WebCore::ResourceResponse&)>&& completionHandler) {
         if (!weakThis)
             return;
@@ -113,9 +110,6 @@ NetworkSession::~NetworkSession()
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
     destroyResourceLoadStatistics();
 #endif
-
-    m_storageManager->resume();
-    m_storageManager->waitUntilTasksFinished();
 }
 
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
index 506e7ff..6849b30 100644 (file)
@@ -52,7 +52,6 @@ class AdClickAttributionManager;
 class NetworkDataTask;
 class NetworkProcess;
 class NetworkResourceLoader;
-class StorageManager;
 class NetworkSocketChannel;
 class WebResourceLoadStatisticsStore;
 class WebSocketTask;
@@ -81,8 +80,6 @@ public:
     void registerNetworkDataTask(NetworkDataTask& task) { m_dataTaskSet.add(&task); }
     void unregisterNetworkDataTask(NetworkDataTask& task) { m_dataTaskSet.remove(&task); }
 
-    StorageManager& storageManager() { return m_storageManager.get(); }
-
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
     WebResourceLoadStatisticsStore* resourceLoadStatistics() const { return m_resourceLoadStatistics.get(); }
     void setResourceLoadStatisticsEnabled(bool);
@@ -145,7 +142,6 @@ protected:
 
     PrefetchCache m_prefetchCache;
 
-    Ref<StorageManager> m_storageManager;
 #if !ASSERT_DISABLED
     bool m_isInvalidated { false };
 #endif
index c1b977c..b29f493 100644 (file)
@@ -50,7 +50,7 @@ NetworkSessionCreationParameters NetworkSessionCreationParameters::privateSessio
 #if USE(CURL)
         , { }, { }
 #endif
-        , { }, { }, false, false, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }
+        , { }, { }, false, false, { }, { }, { }, { }, { }, { }, { }, { }
     };
 }
 
@@ -86,7 +86,6 @@ void NetworkSessionCreationParameters::encode(IPC::Encoder& encoder) const
     encoder << resourceLoadStatisticsManualPrevalentResource;
     encoder << enableResourceLoadStatisticsNSURLSessionSwitching;
 
-    encoder << localStorageDirectory << localStorageDirectoryExtensionHandle;
     encoder << networkCacheDirectory << networkCacheDirectoryExtensionHandle;
 
     encoder << deviceManagementRestrictionsEnabled;
@@ -214,16 +213,6 @@ Optional<NetworkSessionCreationParameters> NetworkSessionCreationParameters::dec
     decoder >> enableResourceLoadStatisticsNSURLSessionSwitching;
     if (!enableResourceLoadStatisticsNSURLSessionSwitching)
         return WTF::nullopt;
-    
-    Optional<String> localStorageDirectory;
-    decoder >> localStorageDirectory;
-    if (!localStorageDirectory)
-        return WTF::nullopt;
-
-    Optional<SandboxExtension::Handle> localStorageDirectoryExtensionHandle;
-    decoder >> localStorageDirectoryExtensionHandle;
-    if (!localStorageDirectoryExtensionHandle)
-        return WTF::nullopt;
 
     Optional<String> networkCacheDirectory;
     decoder >> networkCacheDirectory;
@@ -277,8 +266,6 @@ Optional<NetworkSessionCreationParameters> NetworkSessionCreationParameters::dec
         , WTFMove(*deviceManagementRestrictionsEnabled)
         , WTFMove(*allLoadsBlockedByDeviceManagementRestrictionsForTesting)
         , WTFMove(*resourceLoadStatisticsManualPrevalentResource)
-        , WTFMove(*localStorageDirectory)
-        , WTFMove(*localStorageDirectoryExtensionHandle)
         , WTFMove(*networkCacheDirectory)
         , WTFMove(*networkCacheDirectoryExtensionHandle)
     }};
index 1833e46..50be30e 100644 (file)
@@ -92,8 +92,6 @@ struct NetworkSessionCreationParameters {
     bool allLoadsBlockedByDeviceManagementRestrictionsForTesting { false };
     WebCore::RegistrableDomain resourceLoadStatisticsManualPrevalentResource { };
 
-    String localStorageDirectory;
-    SandboxExtension::Handle localStorageDirectoryExtensionHandle;
     String networkCacheDirectory;
     SandboxExtension::Handle networkCacheDirectoryExtensionHandle;
 };
index bf51578..8f4763c 100644 (file)
@@ -259,7 +259,6 @@ void LocalStorageDatabase::updateDatabase()
     if (m_isClosed)
         return;
 
-    ASSERT(m_didScheduleDatabaseUpdate);
     m_didScheduleDatabaseUpdate = false;
 
     HashMap<String, String> changedItems;
index 4d6876b..8cfb24b 100644 (file)
@@ -55,6 +55,8 @@ public:
     void removeItem(const String& key);
     void clear();
 
+    void updateDatabase();
+
     // Will block until all pending changes have been written to disk.
     void close();
 
@@ -73,7 +75,6 @@ private:
     void itemDidChange(const String& key, const String& value);
 
     void scheduleDatabaseUpdate();
-    void updateDatabase();
     void updateDatabaseWithChangedItems(const HashMap<String, String>&);
 
     bool databaseIsEmpty();
index 07a633f..6732709 100644 (file)
 namespace WebKit {
 using namespace WebCore;
 
-Ref<LocalStorageDatabaseTracker> LocalStorageDatabaseTracker::create(Ref<WorkQueue>&& queue, String&& localStorageDirectory)
+Ref<LocalStorageDatabaseTracker> LocalStorageDatabaseTracker::create(String&& localStorageDirectory)
 {
-    return adoptRef(*new LocalStorageDatabaseTracker(WTFMove(queue), WTFMove(localStorageDirectory)));
+    return adoptRef(*new LocalStorageDatabaseTracker(WTFMove(localStorageDirectory)));
 }
 
-LocalStorageDatabaseTracker::LocalStorageDatabaseTracker(Ref<WorkQueue>&& queue, String&& localStorageDirectory)
-    : m_queue(WTFMove(queue))
-    , m_localStorageDirectory(WTFMove(localStorageDirectory))
+LocalStorageDatabaseTracker::LocalStorageDatabaseTracker(String&& localStorageDirectory)
+    : m_localStorageDirectory(WTFMove(localStorageDirectory))
 {
-    ASSERT(RunLoop::isMain());
+    ASSERT(!RunLoop::isMain());
 
-    // 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"));
-    });
+    SQLiteFileSystem::deleteDatabaseFile(databasePath("StorageTracker.db"));
 }
 
 String LocalStorageDatabaseTracker::localStorageDirectory() const
@@ -66,7 +59,7 @@ String LocalStorageDatabaseTracker::localStorageDirectory() const
 
 LocalStorageDatabaseTracker::~LocalStorageDatabaseTracker()
 {
-    ASSERT(RunLoop::isMain());
+    ASSERT(!RunLoop::isMain());
 }
 
 String LocalStorageDatabaseTracker::databasePath(const SecurityOriginData& securityOrigin) const
index 5d9d2c2..85b49ee 100644 (file)
@@ -35,9 +35,9 @@
 
 namespace WebKit {
 
-class LocalStorageDatabaseTracker : public ThreadSafeRefCounted<LocalStorageDatabaseTracker, WTF::DestructionThread::MainRunLoop> {
+class LocalStorageDatabaseTracker : public ThreadSafeRefCounted<LocalStorageDatabaseTracker> {
 public:
-    static Ref<LocalStorageDatabaseTracker> create(Ref<WorkQueue>&&, String&& localStorageDirectory);
+    static Ref<LocalStorageDatabaseTracker> create(String&& localStorageDirectory);
     ~LocalStorageDatabaseTracker();
 
     String databasePath(const WebCore::SecurityOriginData&) const;
@@ -64,7 +64,7 @@ public:
     Vector<OriginDetails> originDetails();
 
 private:
-    LocalStorageDatabaseTracker(Ref<WorkQueue>&&, String&& localStorageDirectory);
+    LocalStorageDatabaseTracker(String&& localStorageDirectory);
 
     String databasePath(const String& filename) const;
     String localStorageDirectory() const;
@@ -73,8 +73,6 @@ private:
         CreateIfNonExistent,
         SkipIfNonExistent
     };
-
-    Ref<WorkQueue> m_queue;
     
     // It is not safe to use this member from a background thread, call localStorageDirectory() instead.
     const String m_localStorageDirectory;
index 54dc799..3aec668 100644 (file)
@@ -47,7 +47,7 @@ LocalStorageNamespace::~LocalStorageNamespace()
     ASSERT(!RunLoop::isMain());
 }
 
-auto LocalStorageNamespace::getOrCreateStorageArea(SecurityOriginData&& securityOrigin, IsEphemeral isEphemeral) -> Ref<StorageArea>
+Ref<StorageArea> LocalStorageNamespace::getOrCreateStorageArea(SecurityOriginData&& securityOrigin, IsEphemeral isEphemeral)
 {
     ASSERT(!RunLoop::isMain());
     return *m_storageAreaMap.ensure(securityOrigin, [&]() mutable {
@@ -81,11 +81,4 @@ Vector<SecurityOriginData> LocalStorageNamespace::ephemeralOrigins() const
     return origins;
 }
 
-void LocalStorageNamespace::cloneTo(LocalStorageNamespace& newLocalStorageNamespace)
-{
-    ASSERT(!RunLoop::isMain());
-    for (auto& pair : m_storageAreaMap)
-        newLocalStorageNamespace.m_storageAreaMap.add(pair.key, pair.value->clone());
-}
-
 } // namespace WebKit
index 47190cc..9a76e1c 100644 (file)
@@ -54,7 +54,6 @@ public:
     void clearAllStorageAreas();
 
     Vector<WebCore::SecurityOriginData> ephemeralOrigins() const;
-    void cloneTo(LocalStorageNamespace& newLocalStorageNamespace);
 
 private:
     LocalStorageNamespace(StorageManager&, uint64_t storageManagerID);
index 580a8e6..ddf8212 100644 (file)
@@ -43,20 +43,7 @@ SessionStorageNamespace::~SessionStorageNamespace()
     ASSERT(!RunLoop::isMain());
 }
 
-void SessionStorageNamespace::addAllowedConnection(IPC::Connection::UniqueID allowedConnection)
-{
-    ASSERT(!RunLoop::isMain());
-    m_allowedConnections.add(allowedConnection);
-}
-
-
-void SessionStorageNamespace::removeAllowedConnection(IPC::Connection::UniqueID allowedConnection)
-{
-    ASSERT(!RunLoop::isMain());
-    ASSERT(m_allowedConnections.contains(allowedConnection));
-    m_allowedConnections.remove(allowedConnection);
-}
-auto SessionStorageNamespace::getOrCreateStorageArea(SecurityOriginData&& securityOrigin) -> Ref<StorageArea>
+Ref<StorageArea> SessionStorageNamespace::getOrCreateStorageArea(SecurityOriginData&& securityOrigin)
 {
     ASSERT(!RunLoop::isMain());
     return *m_storageAreaMap.ensure(securityOrigin, [this, &securityOrigin]() mutable {
index 720748f..18f0f09 100644 (file)
@@ -45,10 +45,6 @@ public:
 
     bool isEmpty() const { return m_storageAreaMap.isEmpty(); }
 
-    const HashSet<IPC::Connection::UniqueID>& allowedConnections() const { return m_allowedConnections; }
-    void addAllowedConnection(IPC::Connection::UniqueID);
-    void removeAllowedConnection(IPC::Connection::UniqueID);
-
     Ref<StorageArea> getOrCreateStorageArea(WebCore::SecurityOriginData&&);
 
     void cloneTo(SessionStorageNamespace& newSessionStorageNamespace);
@@ -61,7 +57,6 @@ public:
 private:
     explicit SessionStorageNamespace(unsigned quotaInBytes);
 
-    HashSet<IPC::Connection::UniqueID> m_allowedConnections;
     unsigned m_quotaInBytes { 0 };
 
     HashMap<WebCore::SecurityOriginData, RefPtr<StorageArea>> m_storageAreaMap;
index 349431f..2d12583 100644 (file)
@@ -36,11 +36,18 @@ namespace WebKit {
 
 using namespace WebCore;
 
+static uint64_t generateStorageAreaIdentifier()
+{
+    static uint64_t identifier;
+    return ++identifier;
+}
+
 StorageArea::StorageArea(LocalStorageNamespace* localStorageNamespace, const SecurityOriginData& securityOrigin, unsigned quotaInBytes)
     : m_localStorageNamespace(makeWeakPtr(localStorageNamespace))
     , m_securityOrigin(securityOrigin)
     , m_quotaInBytes(quotaInBytes)
     , m_storageMap(StorageMap::create(m_quotaInBytes))
+    , m_identifier(generateStorageAreaIdentifier())
 {
     ASSERT(!RunLoop::isMain());
 }
@@ -48,30 +55,32 @@ StorageArea::StorageArea(LocalStorageNamespace* localStorageNamespace, const Sec
 StorageArea::~StorageArea()
 {
     ASSERT(!RunLoop::isMain());
-    ASSERT(m_eventListeners.isEmpty());
 
     if (m_localStorageDatabase)
         m_localStorageDatabase->close();
 }
 
-void StorageArea::addListener(IPC::Connection::UniqueID connectionID, uint64_t storageMapID)
+void StorageArea::addListener(IPC::Connection::UniqueID connectionID)
 {
     ASSERT(!RunLoop::isMain());
-    ASSERT(!m_eventListeners.contains(std::make_pair(connectionID, storageMapID)));
-    m_eventListeners.add(std::make_pair(connectionID, storageMapID));
+    ASSERT(!m_eventListeners.contains(connectionID));
+
+    if (m_eventListeners.isEmpty() && !isEphemeral())
+        openDatabaseAndImportItemsIfNeeded();
+
+    m_eventListeners.add(connectionID);
 }
 
-void StorageArea::removeListener(IPC::Connection::UniqueID connectionID, uint64_t storageMapID)
+void StorageArea::removeListener(IPC::Connection::UniqueID connectionID)
 {
     ASSERT(!RunLoop::isMain());
-    ASSERT(isEphemeral() || m_eventListeners.contains(std::make_pair(connectionID, storageMapID)));
-    m_eventListeners.remove(std::make_pair(connectionID, storageMapID));
+    m_eventListeners.remove(connectionID);
 }
 
-bool StorageArea::hasListener(IPC::Connection::UniqueID connectionID, uint64_t storageMapID) const
+bool StorageArea::hasListener(IPC::Connection::UniqueID connectionID) const
 {
     ASSERT(!RunLoop::isMain());
-    return m_eventListeners.contains(std::make_pair(connectionID, storageMapID));
+    return m_eventListeners.contains(connectionID);
 }
 
 Ref<StorageArea> StorageArea::clone() const
@@ -105,25 +114,6 @@ void StorageArea::setItem(IPC::Connection::UniqueID sourceConnection, uint64_t s
     dispatchEvents(sourceConnection, sourceStorageAreaID, key, oldValue, value, urlString);
 }
 
-void StorageArea::setItems(const HashMap<String, String>& items)
-{
-    ASSERT(!RunLoop::isMain());
-    // Import items from web process if items are not stored on disk.
-    if (!isEphemeral())
-        return;
-
-    for (auto& item : items) {
-        String oldValue;
-        bool quotaException;
-        auto newStorageMap = m_storageMap->setItem(item.key, item.value, oldValue, quotaException);
-        if (newStorageMap)
-            m_storageMap = WTFMove(newStorageMap);
-        
-        if (quotaException)
-            return;
-    }
-}
-
 void StorageArea::removeItem(IPC::Connection::UniqueID sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& urlString)
 {
     ASSERT(!RunLoop::isMain());
@@ -178,7 +168,7 @@ void StorageArea::clear()
     }
 
     for (auto it = m_eventListeners.begin(), end = m_eventListeners.end(); it != end; ++it) {
-        RunLoop::main().dispatch([connectionID = it->first, destinationStorageAreaID = it->second] {
+        RunLoop::main().dispatch([connectionID = *it, destinationStorageAreaID = m_identifier] {
             if (auto* connection = IPC::Connection::connection(connectionID))
                 connection->send(Messages::StorageAreaMap::ClearCache(), destinationStorageAreaID);
         });
@@ -192,9 +182,10 @@ void StorageArea::openDatabaseAndImportItemsIfNeeded() const
         return;
 
     ASSERT(m_localStorageNamespace->storageManager()->localStorageDatabaseTracker());
+    ASSERT(m_queue);
     // 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()->workQueue(), *m_localStorageNamespace->storageManager()->localStorageDatabaseTracker(), m_securityOrigin);
+        m_localStorageDatabase = LocalStorageDatabase::create(*m_queue, *m_localStorageNamespace->storageManager()->localStorageDatabaseTracker(), m_securityOrigin);
 
     if (m_didImportItemsFromDatabase)
         return;
@@ -207,13 +198,21 @@ void StorageArea::dispatchEvents(IPC::Connection::UniqueID sourceConnection, uin
 {
     ASSERT(!RunLoop::isMain());
     for (auto it = m_eventListeners.begin(), end = m_eventListeners.end(); it != end; ++it) {
-        sourceStorageAreaID = it->first == sourceConnection ? sourceStorageAreaID : 0;
+        sourceStorageAreaID = *it == 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()] {
+        RunLoop::main().dispatch([connectionID = *it, sourceStorageAreaID, destinationStorageAreaID = m_identifier, 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);
         });
     }
 }
 
+void StorageArea::syncToDatabase()
+{
+    if (!m_localStorageDatabase)
+        return;
+
+    m_localStorageDatabase->updateDatabase();
+}
+
 } // namespace WebKit
index 0001075..4d33c4a 100644 (file)
@@ -49,15 +49,15 @@ public:
     ~StorageArea();
 
     const WebCore::SecurityOriginData& securityOrigin() const { return m_securityOrigin; }
+    uint64_t identifier() { return m_identifier; }
 
-    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;
+    void addListener(IPC::Connection::UniqueID);
+    void removeListener(IPC::Connection::UniqueID);
+    bool hasListener(IPC::Connection::UniqueID connectionID) 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 setItems(const HashMap<String, String>&);
     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);
 
@@ -68,6 +68,10 @@ public:
 
     void openDatabaseAndImportItemsIfNeeded() const;
 
+    void setWorkQueue(RefPtr<WorkQueue>&& queue) { m_queue = WTFMove(queue); }
+
+    void syncToDatabase();
+
 private:
     StorageArea(LocalStorageNamespace*, const WebCore::SecurityOriginData&, unsigned quotaInBytes);
 
@@ -82,7 +86,10 @@ private:
     unsigned m_quotaInBytes { 0 };
 
     RefPtr<WebCore::StorageMap> m_storageMap;
-    HashSet<std::pair<IPC::Connection::UniqueID, uint64_t>> m_eventListeners;
+    HashSet<IPC::Connection::UniqueID> m_eventListeners;
+
+    uint64_t m_identifier;
+    RefPtr<WorkQueue> m_queue;
 };
 
 } // namespace WebKit
index 3e3e0b4..64db494 100644 (file)
@@ -32,7 +32,6 @@
 #include "SessionStorageNamespace.h"
 #include "StorageArea.h"
 #include "StorageAreaMapMessages.h"
-#include "StorageManagerMessages.h"
 #include "TransientLocalStorageNamespace.h"
 #include "WebProcessProxy.h"
 #include <WebCore/SecurityOriginData.h>
@@ -41,7 +40,6 @@
 #include <WebCore/TextEncoding.h>
 #include <memory>
 #include <wtf/WorkQueue.h>
-#include <wtf/threads/BinarySemaphore.h>
 
 namespace WebKit {
 using namespace WebCore;
@@ -50,540 +48,242 @@ using namespace WebCore;
 const unsigned StorageManager::localStorageDatabaseQuotaInBytes = 5 * 1024 * 1024;
 
 StorageManager::StorageManager(String&& localStorageDirectory)
-    : m_queue(WorkQueue::create("com.apple.WebKit.StorageManager"))
 {
-    ASSERT(RunLoop::isMain());
+    ASSERT(!RunLoop::isMain());
 
-    // Make sure the encoding is initialized before we start dispatching things to the queue.
-    UTF8Encoding();
     if (!localStorageDirectory.isNull())
-        m_localStorageDatabaseTracker = LocalStorageDatabaseTracker::create(m_queue.copyRef(), WTFMove(localStorageDirectory));
+        m_localStorageDatabaseTracker = LocalStorageDatabaseTracker::create(WTFMove(localStorageDirectory));
 }
 
 StorageManager::~StorageManager()
 {
-    ASSERT(RunLoop::isMain());
+    ASSERT(!RunLoop::isMain());
 }
 
 void StorageManager::createSessionStorageNamespace(uint64_t storageNamespaceID, unsigned quotaInBytes)
 {
-    ASSERT(RunLoop::isMain());
-    m_queue->dispatch([this, protectedThis = makeRef(*this), storageNamespaceID, quotaInBytes]() mutable {
-        m_sessionStorageNamespaces.ensure(storageNamespaceID, [quotaInBytes] {
-            return SessionStorageNamespace::create(quotaInBytes);
-        });
-    });
-}
+    ASSERT(!RunLoop::isMain());
 
-void StorageManager::destroySessionStorageNamespace(uint64_t storageNamespaceID)
-{
-    ASSERT(RunLoop::isMain());
-    m_queue->dispatch([this, protectedThis = makeRef(*this), storageNamespaceID] {
-        ASSERT(m_sessionStorageNamespaces.contains(storageNamespaceID));
-        if (auto* sessionStorageNamespace = m_sessionStorageNamespaces.get(storageNamespaceID)) {
-            if (sessionStorageNamespace->allowedConnections().isEmpty())
-                m_sessionStorageNamespaces.remove(storageNamespaceID);
-        }
+    m_sessionStorageNamespaces.ensure(storageNamespaceID, [quotaInBytes] {
+        return SessionStorageNamespace::create(quotaInBytes);
     });
 }
 
-void StorageManager::addAllowedSessionStorageNamespaceConnection(uint64_t storageNamespaceID, IPC::Connection& allowedConnection)
+void StorageManager::destroySessionStorageNamespace(uint64_t storageNamespaceID)
 {
-    ASSERT(RunLoop::isMain());
-    auto allowedConnectionID = allowedConnection.uniqueID();
-    auto addResult = m_connections.add(allowedConnectionID);
-    if (addResult.isNewEntry)
-        allowedConnection.addWorkQueueMessageReceiver(Messages::StorageManager::messageReceiverName(), m_queue.get(), this);
-
-    m_queue->dispatch([this, protectedThis = makeRef(*this), allowedConnectionID, storageNamespaceID]() mutable {
-        ASSERT(m_sessionStorageNamespaces.contains(storageNamespaceID));
-
-        m_sessionStorageNamespaces.get(storageNamespaceID)->addAllowedConnection(allowedConnectionID);
-    });
-}
+    ASSERT(!RunLoop::isMain());
 
-void StorageManager::removeAllowedSessionStorageNamespaceConnection(uint64_t storageNamespaceID, IPC::Connection& allowedConnection)
-{
-    ASSERT(RunLoop::isMain());
-    auto allowedConnectionID = allowedConnection.uniqueID();
-    m_queue->dispatch([this, protectedThis = makeRef(*this), allowedConnectionID, storageNamespaceID]() mutable {
-        ASSERT(m_sessionStorageNamespaces.contains(storageNamespaceID));
-        if (auto* sessionStorageNamespace = m_sessionStorageNamespaces.get(storageNamespaceID))
-            sessionStorageNamespace->removeAllowedConnection(allowedConnectionID);
-    });
+    ASSERT(m_sessionStorageNamespaces.contains(storageNamespaceID));
+    if (auto* sessionStorageNamespace = m_sessionStorageNamespaces.get(storageNamespaceID))
+        m_sessionStorageNamespaces.remove(storageNamespaceID);
 }
 
 void StorageManager::cloneSessionStorageNamespace(uint64_t storageNamespaceID, uint64_t newStorageNamespaceID)
 {
-    ASSERT(RunLoop::isMain());
-    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;
-        }
+    ASSERT(!RunLoop::isMain());
 
-        SessionStorageNamespace* newSessionStorageNamespace = m_sessionStorageNamespaces.get(newStorageNamespaceID);
-        ASSERT(newSessionStorageNamespace);
+    SessionStorageNamespace* sessionStorageNamespace = m_sessionStorageNamespaces.get(storageNamespaceID);
+    if (!sessionStorageNamespace)
+        return;
 
-        sessionStorageNamespace->cloneTo(*newSessionStorageNamespace);
+    SessionStorageNamespace* newSessionStorageNamespace = getOrCreateSessionStorageNamespace(newStorageNamespaceID);
+    ASSERT(newSessionStorageNamespace);
 
-        if (!m_localStorageDatabaseTracker) {
-            if (auto* localStorageNamespace = m_localStorageNamespaces.get(storageNamespaceID)) {
-                LocalStorageNamespace* newlocalStorageNamespace = getOrCreateLocalStorageNamespace(newStorageNamespaceID);
-                localStorageNamespace->cloneTo(*newlocalStorageNamespace);
-            }
-        }
-    });
-}
-
-void StorageManager::processDidCloseConnection(IPC::Connection& connection)
-{
-    ASSERT(RunLoop::isMain());
-    if (m_connections.remove(connection.uniqueID()))
-        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);
-
-        Vector<uint64_t> sessionStorageNameSpaceIDsToRemove;
-        for (auto& sessionStorageNamespace : m_sessionStorageNamespaces) {
-            if (sessionStorageNamespace.value->allowedConnections().contains(connectionID))
-                sessionStorageNamespace.value->removeAllowedConnection(connectionID);
-            
-            if (sessionStorageNamespace.value->allowedConnections().isEmpty())
-                sessionStorageNameSpaceIDsToRemove.append(sessionStorageNamespace.key);
-        }
-        
-        for (auto id : sessionStorageNameSpaceIDsToRemove)
-            m_sessionStorageNamespaces.remove(id);
-    });
+    sessionStorageNamespace->cloneTo(*newSessionStorageNamespace);
 }
 
 void StorageManager::getSessionStorageOrigins(Function<void(HashSet<WebCore::SecurityOriginData>&&)>&& completionHandler)
 {
-    ASSERT(RunLoop::isMain());
-    m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable {
-        HashSet<SecurityOriginData> origins;
+    ASSERT(!RunLoop::isMain());
 
-        for (const auto& sessionStorageNamespace : m_sessionStorageNamespaces.values()) {
-            for (auto& origin : sessionStorageNamespace->origins())
-                origins.add(crossThreadCopy(origin));
-        }
+    HashSet<SecurityOriginData> origins;
+    for (const auto& sessionStorageNamespace : m_sessionStorageNamespaces.values()) {
+        for (auto& origin : sessionStorageNamespace->origins())
+        origins.add(crossThreadCopy(origin));
+    }
 
-        RunLoop::main().dispatch([origins = WTFMove(origins), completionHandler = WTFMove(completionHandler)]() mutable {
-            completionHandler(WTFMove(origins));
-        });
+    RunLoop::main().dispatch([origins = WTFMove(origins), completionHandler = WTFMove(completionHandler)]() mutable {
+        completionHandler(WTFMove(origins));
     });
 }
 
 void StorageManager::deleteSessionStorageOrigins(Function<void()>&& completionHandler)
 {
-    ASSERT(RunLoop::isMain());
-    m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable {
-        for (auto& sessionStorageNamespace : m_sessionStorageNamespaces.values())
-            sessionStorageNamespace->clearAllStorageAreas();
+    ASSERT(!RunLoop::isMain());
 
-        RunLoop::main().dispatch(WTFMove(completionHandler));
-    });
+    for (auto& sessionStorageNamespace : m_sessionStorageNamespaces.values())
+        sessionStorageNamespace->clearAllStorageAreas();
+
+    RunLoop::main().dispatch(WTFMove(completionHandler));
 }
 
 void StorageManager::deleteSessionStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>& origins, Function<void()>&& completionHandler)
 {
-    ASSERT(RunLoop::isMain());
-    m_queue->dispatch([this, protectedThis = makeRef(*this), copiedOrigins = crossThreadCopy(origins), completionHandler = WTFMove(completionHandler)]() mutable {
-        for (auto& origin : copiedOrigins) {
-            for (auto& sessionStorageNamespace : m_sessionStorageNamespaces.values())
-                sessionStorageNamespace->clearStorageAreasMatchingOrigin(origin);
-        }
+    ASSERT(!RunLoop::isMain());
 
-        RunLoop::main().dispatch(WTFMove(completionHandler));
-    });
+    for (auto& origin : origins) {
+        for (auto& sessionStorageNamespace : m_sessionStorageNamespaces.values())
+            sessionStorageNamespace->clearStorageAreasMatchingOrigin(origin);
+    }
+
+    RunLoop::main().dispatch(WTFMove(completionHandler));
 }
 
 void StorageManager::getLocalStorageOrigins(Function<void(HashSet<WebCore::SecurityOriginData>&&)>&& completionHandler)
 {
-    ASSERT(RunLoop::isMain());
-    m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable {
-        HashSet<SecurityOriginData> origins;
+    ASSERT(!RunLoop::isMain());
 
-        if (m_localStorageDatabaseTracker) {
-            for (auto& origin : m_localStorageDatabaseTracker->origins())
+    HashSet<SecurityOriginData> origins;
+    if (m_localStorageDatabaseTracker) {
+    for (auto& origin : m_localStorageDatabaseTracker->origins())
+        origins.add(origin.isolatedCopy());
+    } else {
+        for (const auto& localStorageNameSpace : m_localStorageNamespaces.values()) {
+            for (auto& origin : localStorageNameSpace->ephemeralOrigins())
                 origins.add(origin.isolatedCopy());
-        } else {
-            for (const auto& localStorageNameSpace : m_localStorageNamespaces.values()) {
-                for (auto& origin : localStorageNameSpace->ephemeralOrigins())
-                    origins.add(origin.isolatedCopy());
-            }
         }
+    }
 
-        for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values()) {
-            for (auto& origin : transientLocalStorageNamespace->origins())
-                origins.add(origin.isolatedCopy());
-        }
+    for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values()) {
+        for (auto& origin : transientLocalStorageNamespace->origins())
+            origins.add(origin.isolatedCopy());
+    }
 
-        RunLoop::main().dispatch([origins = WTFMove(origins), completionHandler = WTFMove(completionHandler)]() mutable {
-            completionHandler(WTFMove(origins));
-        });
+    RunLoop::main().dispatch([origins = WTFMove(origins), completionHandler = WTFMove(completionHandler)]() mutable {
+        completionHandler(WTFMove(origins));
     });
 }
 
 void StorageManager::getLocalStorageOriginDetails(Function<void(Vector<LocalStorageDatabaseTracker::OriginDetails>&&)>&& completionHandler)
 {
-    ASSERT(RunLoop::isMain());
-    m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable {
-        Vector<LocalStorageDatabaseTracker::OriginDetails> originDetails;
-        if (m_localStorageDatabaseTracker)
-            originDetails = m_localStorageDatabaseTracker->originDetails().isolatedCopy();
-
-        RunLoop::main().dispatch([originDetails = WTFMove(originDetails), completionHandler = WTFMove(completionHandler)]() mutable {
-            completionHandler(WTFMove(originDetails));
-        });
-    });
-}
-
-void StorageManager::deleteLocalStorageEntriesForOrigin(const SecurityOriginData& securityOrigin)
-{
-    ASSERT(RunLoop::isMain());
-    m_queue->dispatch([this, protectedThis = makeRef(*this), copiedOrigin = securityOrigin.isolatedCopy()]() mutable {
-        for (auto& localStorageNamespace : m_localStorageNamespaces.values())
-            localStorageNamespace->clearStorageAreasMatchingOrigin(copiedOrigin);
+    ASSERT(!RunLoop::isMain());
 
-        for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values())
-            transientLocalStorageNamespace->clearStorageAreasMatchingOrigin(copiedOrigin);
+    Vector<LocalStorageDatabaseTracker::OriginDetails> originDetails;
+    if (m_localStorageDatabaseTracker)
+        originDetails = crossThreadCopy(m_localStorageDatabaseTracker->originDetails());
 
-        if (m_localStorageDatabaseTracker)
-            m_localStorageDatabaseTracker->deleteDatabaseWithOrigin(copiedOrigin);
+    RunLoop::main().dispatch([originDetails = WTFMove(originDetails), completionHandler = WTFMove(completionHandler)]() mutable {
+        completionHandler(WTFMove(originDetails));
     });
 }
 
 void StorageManager::deleteLocalStorageOriginsModifiedSince(WallTime time, Function<void()>&& completionHandler)
 {
-    ASSERT(RunLoop::isMain());
-    m_queue->dispatch([this, protectedThis = makeRef(*this), time, completionHandler = WTFMove(completionHandler)]() mutable {
-        if (m_localStorageDatabaseTracker) {
-            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);
-            }
-        } else {
-            for (auto& localStorageNamespace : m_localStorageNamespaces.values())
-                localStorageNamespace->clearAllStorageAreas();
-        }
+    ASSERT(!RunLoop::isMain());
 
-        RunLoop::main().dispatch(WTFMove(completionHandler));
-    });
-}
+    if (m_localStorageDatabaseTracker) {
+        auto originsToDelete = m_localStorageDatabaseTracker->databasesModifiedSince(time);
 
-void StorageManager::deleteLocalStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>& origins, Function<void()>&& completionHandler)
-{
-    ASSERT(RunLoop::isMain());
-    m_queue->dispatch([this, protectedThis = makeRef(*this), copiedOrigins = crossThreadCopy(origins), completionHandler = WTFMove(completionHandler)]() mutable {
-        for (auto& origin : copiedOrigins) {
+        for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values())
+            transientLocalStorageNamespace->clearAllStorageAreas();
+
+        for (const auto& origin : originsToDelete) {
             for (auto& localStorageNamespace : m_localStorageNamespaces.values())
                 localStorageNamespace->clearStorageAreasMatchingOrigin(origin);
-
-            for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values())
-                transientLocalStorageNamespace->clearStorageAreasMatchingOrigin(origin);
-
-            if (m_localStorageDatabaseTracker)
-                m_localStorageDatabaseTracker->deleteDatabaseWithOrigin(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(!RunLoop::isMain());
-    auto connectionID = connection.uniqueID();
-    std::pair<IPC::Connection::UniqueID, uint64_t> connectionAndStorageMapIDPair(connectionID, storageMapID);
-
-    ASSERT((HashMap<std::pair<IPC::Connection::UniqueID, uint64_t>, RefPtr<StorageArea>>::isValidKey(connectionAndStorageMapIDPair)));
-
-    auto result = m_storageAreasByConnection.add(connectionAndStorageMapIDPair, nullptr);
-    ASSERT(result.isNewEntry);
-    ASSERT((HashMap<uint64_t, RefPtr<LocalStorageNamespace>>::isValidKey(storageNamespaceID)));
-
-    LocalStorageNamespace* localStorageNamespace = getOrCreateLocalStorageNamespace(storageNamespaceID);
-    ASSERT(localStorageNamespace);
-
-    auto storageArea = localStorageNamespace->getOrCreateStorageArea(WTFMove(securityOriginData), m_localStorageDatabaseTracker ? LocalStorageNamespace::IsEphemeral::No : LocalStorageNamespace::IsEphemeral::Yes);
-    storageArea->addListener(connectionID, storageMapID);
-
-    result.iterator->value = WTFMove(storageArea);
-}
-
-void StorageManager::createTransientLocalStorageMap(IPC::Connection& connection, uint64_t storageMapID, uint64_t storageNamespaceID, SecurityOriginData&& topLevelOriginData, SecurityOriginData&& origin)
-{
-    ASSERT(!RunLoop::isMain());
-    auto connectionID = connection.uniqueID();
-
-    ASSERT(m_storageAreasByConnection.isValidKey({ connectionID, 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 != connectionID)
-            continue;
-        Ref<StorageArea> area = *it->value;
-        if (!area->isEphemeral())
-            continue;
-        if (!origin.securityOrigin()->isSameSchemeHostPort(area->securityOrigin().securityOrigin().get()))
-            continue;
-        area->addListener(connectionID, 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(connectionID, it->key.second))
-            m_storageAreasByConnection.remove(it);
-        m_storageAreasByConnection.add({ connectionID, storageMapID }, WTFMove(area));
-        return;
+    } else {
+        for (auto& localStorageNamespace : m_localStorageNamespaces.values())
+            localStorageNamespace->clearAllStorageAreas();
     }
 
-    auto& slot = m_storageAreasByConnection.add({ connectionID, storageMapID }, nullptr).iterator->value;
-    ASSERT(!slot);
-
-    auto* transientLocalStorageNamespace = getOrCreateTransientLocalStorageNamespace(storageNamespaceID, WTFMove(topLevelOriginData));
-
-    auto storageArea = transientLocalStorageNamespace->getOrCreateStorageArea(WTFMove(origin));
-    storageArea->addListener(connectionID, storageMapID);
-
-    slot = WTFMove(storageArea);
+    RunLoop::main().dispatch(WTFMove(completionHandler));
 }
 
-void StorageManager::createSessionStorageMap(IPC::Connection& connection, uint64_t storageMapID, uint64_t storageNamespaceID, SecurityOriginData&& securityOriginData)
+void StorageManager::deleteLocalStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>& origins, Function<void()>&& completionHandler)
 {
     ASSERT(!RunLoop::isMain());
-    auto connectionID = connection.uniqueID();
-    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;
-    }
-
-    ASSERT(m_storageAreasByConnection.isValidKey({ connectionID, storageMapID }));
 
-    auto& slot = m_storageAreasByConnection.add({ connectionID, storageMapID }, nullptr).iterator->value;
-    ASSERT(!slot);
-    ASSERT(sessionStorageNamespace->allowedConnections().contains(connectionID));
-
-    auto storageArea = sessionStorageNamespace->getOrCreateStorageArea(WTFMove(securityOriginData));
-    storageArea->addListener(connectionID, storageMapID);
-
-    slot = WTFMove(storageArea);
-}
-
-void StorageManager::destroyStorageMap(IPC::Connection& connection, uint64_t storageMapID)
-{
-    ASSERT(!RunLoop::isMain());
-    auto connectionID = connection.uniqueID();
+    for (auto& origin : origins) {
+        for (auto& localStorageNamespace : m_localStorageNamespaces.values())
+            localStorageNamespace->clearStorageAreasMatchingOrigin(origin);
 
-    std::pair<IPC::Connection::UniqueID, uint64_t> connectionAndStorageMapIDPair(connectionID, storageMapID);
-    ASSERT(m_storageAreasByConnection.isValidKey(connectionAndStorageMapIDPair));
+        for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values())
+            transientLocalStorageNamespace->clearStorageAreasMatchingOrigin(origin);
 
-    auto it = m_storageAreasByConnection.find(connectionAndStorageMapIDPair);
-    if (it == m_storageAreasByConnection.end()) {
-        // The connection has been removed because the last page was closed.
-        return;
+        if (m_localStorageDatabaseTracker)
+            m_localStorageDatabaseTracker->deleteDatabaseWithOrigin(origin);
     }
 
-    it->value->removeListener(connectionID, storageMapID);
-
-    // Don't remove session storage maps. The web process may reconnect and expect the data to still be around.
-    if (it->value->isEphemeral())
-        return;
-
-    m_storageAreasByConnection.remove(connectionAndStorageMapIDPair);
-}
-
-void StorageManager::prewarm(IPC::Connection& connection, uint64_t storageMapID)
-{
-    ASSERT(!RunLoop::isMain());
-    if (auto* storageArea = findStorageArea(connection, storageMapID))
-        storageArea->openDatabaseAndImportItemsIfNeeded();
+    RunLoop::main().dispatch(WTFMove(completionHandler));
 }
 
-void StorageManager::getValues(IPC::Connection& connection, uint64_t storageMapID, uint64_t storageMapSeed, GetValuesCallback&& completionHandler)
+StorageArea* StorageManager::createLocalStorageArea(uint64_t storageNamespaceID, WebCore::SecurityOriginData&& origin)
 {
     ASSERT(!RunLoop::isMain());
-    auto* storageArea = findStorageArea(connection, storageMapID);
 
-    // This is a session storage area for a page that has already been closed. Ignore it.
-    if (!storageArea)
-        return completionHandler({ });
+    if (auto* localStorageNamespace = getOrCreateLocalStorageNamespace(storageNamespaceID))
+        return localStorageNamespace->getOrCreateStorageArea(WTFMove(origin), m_localStorageDatabaseTracker ? LocalStorageNamespace::IsEphemeral::No : LocalStorageNamespace::IsEphemeral::Yes).ptr();
 
-    completionHandler(storageArea->items());
-    connection.send(Messages::StorageAreaMap::DidGetValues(storageMapSeed), storageMapID);
+    return nullptr;
 }
 
-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* StorageManager::createTransientLocalStorageArea(uint64_t storageNamespaceID, WebCore::SecurityOriginData&& topLevelOrigin, WebCore::SecurityOriginData&& origin)
 {
     ASSERT(!RunLoop::isMain());
-    auto* storageArea = findStorageArea(connection, storageMapID);
-
-    // This is a session storage area for a page that has already been closed. Ignore it.
-    if (!storageArea)
-        return;
-
-    bool quotaError;
-    storageArea->setItem(connection.uniqueID(), sourceStorageAreaID, key, value, urlString, quotaError);
-    connection.send(Messages::StorageAreaMap::DidSetItem(storageMapSeed, key, quotaError), storageMapID);
-}
+    ASSERT((HashMap<uint64_t, RefPtr<TransientLocalStorageNamespace>>::isValidKey(storageNamespaceID)));
 
-void StorageManager::setItems(IPC::Connection& connection, uint64_t storageMapID, const HashMap<String, String>& items)
-{
-    ASSERT(!RunLoop::isMain());
-    if (auto* storageArea = findStorageArea(connection, storageMapID))
-        storageArea->setItems(items);
+    if (auto* transientLocalStorageNamespace = getOrCreateTransientLocalStorageNamespace(storageNamespaceID, WTFMove(topLevelOrigin)))
+        return transientLocalStorageNamespace->getOrCreateStorageArea(WTFMove(origin)).ptr();
+    
+    return nullptr;
 }
 
-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* StorageManager::createSessionStorageArea(uint64_t storageNamespaceID, WebCore::SecurityOriginData&& origin)
 {
     ASSERT(!RunLoop::isMain());
-    auto* storageArea = findStorageArea(connection, storageMapID);
-
-    // This is a session storage area for a page that has already been closed. Ignore it.
-    if (!storageArea)
-        return;
+    ASSERT((HashMap<uint64_t, RefPtr<SessionStorageNamespace>>::isValidKey(storageNamespaceID)));
 
-    storageArea->removeItem(connection.uniqueID(), sourceStorageAreaID, key, urlString);
-    connection.send(Messages::StorageAreaMap::DidRemoveItem(storageMapSeed, key), storageMapID);
+    if (auto* sessionStorageNamespace = getOrCreateSessionStorageNamespace(storageNamespaceID))
+        return sessionStorageNamespace->getOrCreateStorageArea(WTFMove(origin)).ptr();
+    
+    return nullptr;
 }
 
-void StorageManager::clear(IPC::Connection& connection, WebCore::SecurityOriginData&& securityOriginData, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& urlString)
+LocalStorageNamespace* StorageManager::getOrCreateLocalStorageNamespace(uint64_t storageNamespaceID)
 {
     ASSERT(!RunLoop::isMain());
-    auto* storageArea = findStorageArea(connection, storageMapID);
-
-    // This is a session storage area for a page that has already been closed. Ignore it.
-    if (!storageArea)
-        return;
-
-    storageArea->clear(connection.uniqueID(), sourceStorageAreaID, urlString);
-    connection.send(Messages::StorageAreaMap::DidClear(storageMapSeed), storageMapID);
-}
 
-void StorageManager::waitUntilTasksFinished()
-{
-    ASSERT(RunLoop::isMain());
-    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);
-
-        m_sessionStorageNamespaces.clear();
-        m_localStorageNamespaces.clear();
-
-        semaphore.signal();
-    });
-    semaphore.wait();
-}
-
-void StorageManager::suspend(CompletionHandler<void()>&& completionHandler)
-{
-    ASSERT(RunLoop::isMain());
-    CompletionHandlerCallingScope completionHandlerCaller(WTFMove(completionHandler));
-    if (!m_localStorageDatabaseTracker)
-        return;
-
-    Locker<Lock> stateLocker(m_stateLock);
-    if (m_state != State::Running)
-        return;
-    m_state = State::WillSuspend;
-
-    m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = completionHandlerCaller.release()] () mutable {
-        Locker<Lock> stateLocker(m_stateLock);
-        ASSERT(m_state != State::Suspended);
-
-        if (m_state != State::WillSuspend) {
-            RunLoop::main().dispatch(WTFMove(completionHandler));
-            return;
-        }
-
-        m_state = State::Suspended;
-        RunLoop::main().dispatch(WTFMove(completionHandler));
-        
-        while (m_state == State::Suspended)
-            m_stateChangeCondition.wait(m_stateLock);
-        ASSERT(m_state == State::Running);
-    });
-}
-
-void StorageManager::resume()
-{
-    ASSERT(RunLoop::isMain());
-    if (!m_localStorageDatabaseTracker)
-        return;
+    if (!m_localStorageNamespaces.isValidKey(storageNamespaceID))
+        return nullptr;
 
-    Locker<Lock> stateLocker(m_stateLock);
-    auto previousState = m_state;
-    m_state = State::Running;
-    if (previousState == State::Suspended)
-        m_stateChangeCondition.notifyOne();
+    return m_localStorageNamespaces.ensure(storageNamespaceID, [this, storageNamespaceID]() {
+        return LocalStorageNamespace::create(*this, storageNamespaceID);
+    }).iterator->value.get();
 }
 
-StorageArea* StorageManager::findStorageArea(IPC::Connection& connection, uint64_t storageMapID) const
+TransientLocalStorageNamespace* StorageManager::getOrCreateTransientLocalStorageNamespace(uint64_t storageNamespaceID, WebCore::SecurityOriginData&& topLevelOrigin)
 {
     ASSERT(!RunLoop::isMain());
-    std::pair<IPC::Connection::UniqueID, uint64_t> connectionAndStorageMapIDPair(connection.uniqueID(), storageMapID);
 
-    if (!m_storageAreasByConnection.isValidKey(connectionAndStorageMapIDPair))
+    if (!m_transientLocalStorageNamespaces.isValidKey({ storageNamespaceID, topLevelOrigin }))
         return nullptr;
 
-    return m_storageAreasByConnection.get(connectionAndStorageMapIDPair);
+    return m_transientLocalStorageNamespaces.ensure({ storageNamespaceID, WTFMove(topLevelOrigin) }, [] {
+        return TransientLocalStorageNamespace::create();
+    }).iterator->value.get();
 }
 
-LocalStorageNamespace* StorageManager::getOrCreateLocalStorageNamespace(uint64_t storageNamespaceID)
+SessionStorageNamespace* StorageManager::getOrCreateSessionStorageNamespace(uint64_t storageNamespaceID)
 {
     ASSERT(!RunLoop::isMain());
-    if (!m_localStorageNamespaces.isValidKey(storageNamespaceID))
+
+    if (!m_sessionStorageNamespaces.isValidKey(storageNamespaceID))
         return nullptr;
 
-    return m_localStorageNamespaces.ensure(storageNamespaceID, [this, storageNamespaceID]() {
-        return LocalStorageNamespace::create(*this, storageNamespaceID);
+    return m_sessionStorageNamespaces.ensure(storageNamespaceID, [] {
+        // We currently have no limit on session storage.
+        return SessionStorageNamespace::create(std::numeric_limits<unsigned>::max());
     }).iterator->value.get();
 }
 
-TransientLocalStorageNamespace* StorageManager::getOrCreateTransientLocalStorageNamespace(uint64_t storageNamespaceID, WebCore::SecurityOriginData&& topLevelOrigin)
+void StorageManager::clearStorageNamespaces()
 {
     ASSERT(!RunLoop::isMain());
-    if (!m_transientLocalStorageNamespaces.isValidKey({ storageNamespaceID, topLevelOrigin }))
-        return nullptr;
 
-    return m_transientLocalStorageNamespaces.ensure({ storageNamespaceID, WTFMove(topLevelOrigin) }, [](){
-        return TransientLocalStorageNamespace::create();
-    }).iterator->value.get();
+    m_localStorageNamespaces.clear();
+    m_transientLocalStorageNamespaces.clear();
+    m_sessionStorageNamespaces.clear();
 }
 
 } // namespace WebKit
index 3199a42..6b53e1b 100644 (file)
@@ -49,7 +49,7 @@ class WebProcessProxy;
 
 using GetValuesCallback = CompletionHandler<void(const HashMap<String, String>&)>;
 
-class StorageManager : public IPC::Connection::WorkQueueMessageReceiver {
+class StorageManager : public RefCounted<StorageManager> {
 public:
     static Ref<StorageManager> create(String&& localStorageDirectory)
     {
@@ -60,78 +60,41 @@ public:
 
     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 processDidCloseConnection(IPC::Connection&);
-    void waitUntilTasksFinished();
-    void suspend(CompletionHandler<void()>&&);
-    void resume();
-
-    void getSessionStorageOrigins(Function<void(HashSet<WebCore::SecurityOriginData>&&)>&& completionHandler);
+    void getSessionStorageOrigins(Function<void(HashSet<WebCore::SecurityOriginData>&&)>&&);
     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 deleteSessionStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>&, Function<void()>&&);
 
-    void deleteLocalStorageOriginsModifiedSince(WallTime, Function<void()>&& completionHandler);
-    void deleteLocalStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>&, Function<void()>&& completionHandler);
+    void getLocalStorageOrigins(Function<void(HashSet<WebCore::SecurityOriginData>&&)>&&);
+    void deleteLocalStorageOriginsModifiedSince(WallTime, Function<void()>&&);
+    void deleteLocalStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>&, Function<void()>&&);
+    void getLocalStorageOriginDetails(Function<void(Vector<LocalStorageDatabaseTracker::OriginDetails>&&)>&&);
 
-    void getLocalStorageOriginDetails(Function<void(Vector<LocalStorageDatabaseTracker::OriginDetails>&&)>&& completionHandler);
+    void clearStorageNamespaces();
 
     void didReceiveMessage(IPC::Connection&, IPC::Decoder&);
     void didReceiveSyncMessage(IPC::Connection&, IPC::Decoder&, std::unique_ptr<IPC::Encoder>& replyEncoder);
     
     LocalStorageDatabaseTracker* localStorageDatabaseTracker() const { return m_localStorageDatabaseTracker.get(); }
     
-    WorkQueue& workQueue() const { return m_queue.get(); }
-    
     static const unsigned localStorageDatabaseQuotaInBytes;
 
+    StorageArea* createLocalStorageArea(uint64_t storageNamespaceID, WebCore::SecurityOriginData&&);
+    StorageArea* createTransientLocalStorageArea(uint64_t storageNamespaceID, WebCore::SecurityOriginData&&, WebCore::SecurityOriginData&&);
+    StorageArea* createSessionStorageArea(uint64_t storageNamespaceID, WebCore::SecurityOriginData&&);
+
 private:
     explicit StorageManager(String&& localStorageDirectory);
 
-    // 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&, uint64_t storageMapID, uint64_t storageMapSeed, GetValuesCallback&&);
-    void prewarm(IPC::Connection&, uint64_t storageMapID);
-    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 setItems(IPC::Connection&, uint64_t storageMapID, const HashMap<String, String>& items);
-    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);
-
-    StorageArea* findStorageArea(IPC::Connection&, uint64_t) const;
-
     LocalStorageNamespace* getOrCreateLocalStorageNamespace(uint64_t storageNamespaceID);
-
     TransientLocalStorageNamespace* getOrCreateTransientLocalStorageNamespace(uint64_t storageNamespaceID, WebCore::SecurityOriginData&& topLevelOrigin);
-
-    Ref<WorkQueue> m_queue;
+    SessionStorageNamespace* getOrCreateSessionStorageNamespace(uint64_t storageNamespaceID);
 
     RefPtr<LocalStorageDatabaseTracker> m_localStorageDatabaseTracker;
     HashMap<uint64_t, RefPtr<LocalStorageNamespace>> m_localStorageNamespaces;
-
     HashMap<std::pair<uint64_t, WebCore::SecurityOriginData>, RefPtr<TransientLocalStorageNamespace>> m_transientLocalStorageNamespaces;
-
     HashMap<uint64_t, RefPtr<SessionStorageNamespace>> m_sessionStorageNamespaces;
-
-    HashMap<std::pair<IPC::Connection::UniqueID, uint64_t>, RefPtr<StorageArea>> m_storageAreasByConnection;
-    HashSet<IPC::Connection::UniqueID> m_connections;
-
-    enum class State {
-        Running,
-        WillSuspend,
-        Suspended
-    };
-    State m_state { State::Running };
-    Lock m_stateLock;
-    Condition m_stateChangeCondition;
 };
 
 } // namespace WebKit
diff --git a/Source/WebKit/NetworkProcess/WebStorage/StorageManager.messages.in b/Source/WebKit/NetworkProcess/WebStorage/StorageManager.messages.in
deleted file mode 100644 (file)
index 78bb6ab..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright (C) 2013-2019 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
-
-    Prewarm(uint64_t storageMapID) WantsConnection
-    GetValues(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
-    SetItems(uint64_t storageMapID, HashMap<String, String> items) 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/StorageManagerSet.cpp b/Source/WebKit/NetworkProcess/WebStorage/StorageManagerSet.cpp
new file mode 100644 (file)
index 0000000..81c7b71
--- /dev/null
@@ -0,0 +1,409 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "StorageManagerSet.h"
+
+#include "StorageAreaMapMessages.h"
+#include "StorageManagerSetMessages.h"
+#include <wtf/threads/BinarySemaphore.h>
+
+namespace WebKit {
+
+const uint64_t invalidStorageAreaID = 0;
+
+Ref<StorageManagerSet> StorageManagerSet::create()
+{
+    return adoptRef(*new StorageManagerSet);
+}
+
+StorageManagerSet::StorageManagerSet()
+    : m_queue(WorkQueue::create("com.apple.WebKit.WebStorage"))
+{
+    ASSERT(RunLoop::isMain());
+
+    // Make sure the encoding is initialized before we start dispatching things to the queue.
+    UTF8Encoding();
+}
+
+StorageManagerSet::~StorageManagerSet()
+{
+    ASSERT(RunLoop::isMain());
+
+    waitUntilTasksFinished();
+}
+
+void StorageManagerSet::add(PAL::SessionID sessionID, const String& localStorageDirectory, SandboxExtension::Handle& localStorageDirectoryHandle)
+{
+    ASSERT(RunLoop::isMain());
+
+    auto[iter, isNewEntry] = m_storageManagerPaths.add(sessionID, localStorageDirectory);
+    if (isNewEntry) {
+        if (!sessionID.isEphemeral())
+            SandboxExtension::consumePermanently(localStorageDirectoryHandle);
+
+        m_queue->dispatch([this, protectedThis = makeRef(*this), sessionID, directory = localStorageDirectory.isolatedCopy()]() mutable {
+            m_storageManagers.ensure(sessionID, [directory]() mutable {
+                return StorageManager::create(WTFMove(directory));
+            });
+        });
+    }
+}
+
+void StorageManagerSet::remove(PAL::SessionID sessionID)
+{
+    ASSERT(RunLoop::isMain());
+
+    if (m_storageManagerPaths.remove(sessionID)) {
+        m_queue->dispatch([this, protectedThis = makeRef(*this), sessionID]() {
+            m_storageManagers.remove(sessionID);
+        });
+    }
+}
+
+bool StorageManagerSet::contains(PAL::SessionID sessionID)
+{
+    ASSERT(RunLoop::isMain());
+
+    return m_storageManagerPaths.contains(sessionID);
+}
+
+void StorageManagerSet::addConnection(IPC::Connection& connection) 
+{
+    ASSERT(RunLoop::isMain());
+
+    auto connectionID = connection.uniqueID();
+    ASSERT(!m_connections.contains(connectionID));
+    if (m_connections.add(connectionID).isNewEntry)
+        connection.addWorkQueueMessageReceiver(Messages::StorageManagerSet::messageReceiverName(), m_queue.get(), this);
+}
+
+void StorageManagerSet::removeConnection(IPC::Connection& connection)
+{
+    ASSERT(RunLoop::isMain());
+
+    auto connectionID = connection.uniqueID();
+    ASSERT(m_connections.contains(connectionID));
+    m_connections.remove(connectionID);
+    connection.removeWorkQueueMessageReceiver(Messages::StorageManagerSet::messageReceiverName());
+
+    m_queue->dispatch([this, protectedThis = makeRef(*this), connectionID]() {
+        for (auto& storageArea : m_storageAreas.values())
+            storageArea->removeListener(connectionID);
+    });
+}
+
+void StorageManagerSet::waitUntilTasksFinished()
+{
+    ASSERT(RunLoop::isMain());
+
+    BinarySemaphore semaphore;
+    m_queue->dispatch([this, &semaphore] {
+        for (auto& [sessionID, storageManager] : m_storageManagers)
+            storageManager->clearStorageNamespaces();
+
+        m_storageManagers.clear();
+        m_storageAreas.clear();
+
+        semaphore.signal();
+    });
+    semaphore.wait();
+}
+
+void StorageManagerSet::waitUntilSyncingLocalStorageFinished()
+{
+    ASSERT(RunLoop::isMain());
+
+    BinarySemaphore semaphore;
+    m_queue->dispatch([this, &semaphore] {
+        for (auto* storageArea : m_storageAreas.values())
+            storageArea->syncToDatabase();
+
+        semaphore.signal();
+    });
+    semaphore.wait();
+}
+
+void StorageManagerSet::suspend(CompletionHandler<void()>&& completionHandler)
+{
+    ASSERT(RunLoop::isMain());
+
+    CompletionHandlerCallingScope completionHandlerCaller(WTFMove(completionHandler));
+    Locker<Lock> stateLocker(m_stateLock);
+    if (m_state != State::Running)
+        return;
+    m_state = State::WillSuspend;
+
+    m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = completionHandlerCaller.release()] () mutable {
+        Locker<Lock> stateLocker(m_stateLock);
+        ASSERT(m_state != State::Suspended);
+
+        if (m_state != State::WillSuspend) {
+            RunLoop::main().dispatch(WTFMove(completionHandler));
+            return;
+        }
+
+        m_state = State::Suspended;
+        RunLoop::main().dispatch(WTFMove(completionHandler));
+
+        while (m_state == State::Suspended)
+            m_stateChangeCondition.wait(m_stateLock);
+        ASSERT(m_state == State::Running);
+    });
+}
+
+void StorageManagerSet::resume()
+{
+    ASSERT(RunLoop::isMain());
+
+    Locker<Lock> stateLocker(m_stateLock);
+    auto previousState = m_state;
+    m_state = State::Running;
+    if (previousState == State::Suspended)
+        m_stateChangeCondition.notifyOne();
+}
+
+void StorageManagerSet::getSessionStorageOrigins(PAL::SessionID sessionID, CompletionHandler<void(HashSet<WebCore::SecurityOriginData>&&)>&& completionHandler)
+{
+    m_queue->dispatch([this, protectedThis = makeRef(*this), sessionID, completionHandler = WTFMove(completionHandler)]() mutable {
+        auto* storageManager = m_storageManagers.get(sessionID);
+        ASSERT(storageManager);
+
+        storageManager->getSessionStorageOrigins(WTFMove(completionHandler));
+    });
+}
+
+void StorageManagerSet::deleteSessionStorage(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
+{
+    m_queue->dispatch([this, protectedThis = makeRef(*this), sessionID, completionHandler = WTFMove(completionHandler)]() mutable {
+        auto* storageManager = m_storageManagers.get(sessionID);
+        ASSERT(storageManager);
+
+        storageManager->deleteSessionStorageOrigins(WTFMove(completionHandler));
+    });
+}
+
+void StorageManagerSet::deleteSessionStorageForOrigins(PAL::SessionID sessionID, const Vector<WebCore::SecurityOriginData>& originDatas, DeleteCallback&& completionHandler)
+{
+    m_queue->dispatch([this, protectedThis = makeRef(*this), sessionID, copiedOriginDatas = crossThreadCopy(originDatas), completionHandler = WTFMove(completionHandler)]() mutable {
+        auto* storageManager = m_storageManagers.get(sessionID);
+        ASSERT(storageManager);
+
+        storageManager->deleteSessionStorageEntriesForOrigins(copiedOriginDatas, WTFMove(completionHandler));
+    });
+}
+
+void StorageManagerSet::getLocalStorageOrigins(PAL::SessionID sessionID, GetOriginsCallback&& completionHandler)
+{
+    m_queue->dispatch([this, protectedThis = makeRef(*this), sessionID, completionHandler = WTFMove(completionHandler)]() mutable {
+        auto* storageManager = m_storageManagers.get(sessionID);
+        ASSERT(storageManager);
+
+        storageManager->getLocalStorageOrigins(WTFMove(completionHandler));
+    });
+}
+
+void StorageManagerSet::deleteLocalStorageModifiedSince(PAL::SessionID sessionID, WallTime time, DeleteCallback&& completionHandler)
+{
+    m_queue->dispatch([this, protectedThis = makeRef(*this), sessionID, time, completionHandler = WTFMove(completionHandler)]() mutable {
+        auto* storageManager = m_storageManagers.get(sessionID);
+        ASSERT(storageManager);
+
+        storageManager->deleteLocalStorageOriginsModifiedSince(time, WTFMove(completionHandler));
+    });
+}
+
+void StorageManagerSet::deleteLocalStorageForOrigins(PAL::SessionID sessionID, const Vector<WebCore::SecurityOriginData>& originDatas, DeleteCallback&& completionHandler)
+{
+    m_queue->dispatch([this, protectedThis = makeRef(*this), sessionID, copiedOriginDatas = crossThreadCopy(originDatas), completionHandler = WTFMove(completionHandler)]() mutable {
+        auto* storageManager = m_storageManagers.get(sessionID);
+        ASSERT(storageManager);
+
+        storageManager->deleteLocalStorageEntriesForOrigins(copiedOriginDatas, WTFMove(completionHandler));
+    });
+}
+
+void StorageManagerSet::getLocalStorageOriginDetails(PAL::SessionID sessionID, CompletionHandler<void(Vector<LocalStorageDatabaseTracker::OriginDetails>&&)>&& completionHandler)
+{
+    m_queue->dispatch([this, protectedThis = makeRef(*this), sessionID, completionHandler = WTFMove(completionHandler)]() mutable {
+        auto* storageManager = m_storageManagers.get(sessionID);
+        ASSERT(storageManager);
+
+        storageManager->getLocalStorageOriginDetails(WTFMove(completionHandler));
+    });
+}
+
+void StorageManagerSet::connectToLocalStorageArea(IPC::Connection& connection, PAL::SessionID sessionID, uint64_t storageNamespaceID, SecurityOriginData&& originData, ConnectToStorageAreaCallback&& completionHandler)
+{
+    ASSERT(!RunLoop::isMain());
+
+    auto* storageManager = m_storageManagers.get(sessionID);
+    if (!storageManager) {
+        completionHandler(invalidStorageAreaID);
+        return;
+    }
+
+    auto* storageArea = storageManager->createLocalStorageArea(storageNamespaceID, WTFMove(originData));
+    if (!storageArea) {
+        completionHandler(invalidStorageAreaID);
+        return;
+    }
+
+    auto storageAreaID = storageArea->identifier();
+    auto[iter, isNewEntry] = m_storageAreas.add(storageAreaID, nullptr);
+    if (isNewEntry) {
+        storageArea->setWorkQueue(m_queue.ptr());
+        iter->value = storageArea;
+    } else
+        ASSERT(storageArea == iter->value);
+
+    completionHandler(storageAreaID);
+
+    storageArea->addListener(connection.uniqueID());
+}
+
+void StorageManagerSet::connectToTransientLocalStorageArea(IPC::Connection& connection, PAL::SessionID sessionID, uint64_t storageNamespaceID, SecurityOriginData&& topLevelOriginData, SecurityOriginData&& originData, ConnectToStorageAreaCallback&& completionHandler)
+{
+    ASSERT(!RunLoop::isMain());
+
+    auto* storageManager = m_storageManagers.get(sessionID);
+    if (!storageManager) {
+        completionHandler(invalidStorageAreaID);
+        return;
+    }
+
+    auto* storageArea = storageManager->createTransientLocalStorageArea(storageNamespaceID, WTFMove(topLevelOriginData), WTFMove(originData));
+    if (!storageArea) {
+        completionHandler(invalidStorageAreaID);
+        return;
+    }
+
+    auto storageAreaID = storageArea->identifier();
+    auto[iter, isNewEntry] = m_storageAreas.add(storageAreaID, nullptr);
+    if (isNewEntry)
+        iter->value = storageArea;
+    else
+        ASSERT(storageArea == iter->value);
+
+    completionHandler(storageAreaID);
+
+    storageArea->addListener(connection.uniqueID());
+}
+
+void StorageManagerSet::connectToSessionStorageArea(IPC::Connection& connection, PAL::SessionID sessionID, uint64_t storageNamespaceID, SecurityOriginData&& originData, ConnectToStorageAreaCallback&& completionHandler)
+{
+    ASSERT(!RunLoop::isMain());
+
+    auto* storageManager = m_storageManagers.get(sessionID);
+    if (!storageManager) {
+        completionHandler(invalidStorageAreaID);
+        return;
+    }
+
+    auto* storageArea = storageManager->createSessionStorageArea(storageNamespaceID, WTFMove(originData));
+    if (!storageArea) {
+        completionHandler(invalidStorageAreaID);
+        return;
+    }
+
+    auto storageAreaID = storageArea->identifier();
+    auto[iter, isNewEntry] = m_storageAreas.add(storageAreaID, nullptr);
+    if (isNewEntry)
+        iter->value = storageArea;
+    else
+        ASSERT(storageArea == iter->value);
+
+    completionHandler(storageAreaID);
+    
+    storageArea->addListener(connection.uniqueID());
+}
+
+void StorageManagerSet::disconnectFromStorageArea(IPC::Connection& connection, uint64_t storageAreaID)
+{
+    ASSERT(!RunLoop::isMain());
+
+    auto* storageArea = m_storageAreas.get(storageAreaID);
+    ASSERT(storageArea);
+    ASSERT(storageArea->hasListener(connection.uniqueID()));
+
+    storageArea->removeListener(connection.uniqueID());
+}
+
+void StorageManagerSet::getValues(IPC::Connection& connection, uint64_t storageAreaID, GetValuesCallback&& completionHandler)
+{
+    ASSERT(!RunLoop::isMain());
+
+    auto* storageArea = m_storageAreas.get(storageAreaID);
+    ASSERT(!storageArea || storageArea->hasListener(connection.uniqueID()));
+
+    completionHandler(storageArea ? storageArea->items() : HashMap<String, String>());
+}
+
+void StorageManagerSet::setItem(IPC::Connection& connection, uint64_t storageAreaID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& value, const String& urlString)
+{
+    ASSERT(!RunLoop::isMain());
+
+    auto* storageArea = m_storageAreas.get(storageAreaID);
+    ASSERT(storageArea);
+
+    bool quotaError;
+    storageArea->setItem(connection.uniqueID(), sourceStorageAreaID, key, value, urlString, quotaError);
+
+    connection.send(Messages::StorageAreaMap::DidSetItem(storageMapSeed, key, quotaError), storageAreaID);
+} 
+
+void StorageManagerSet::removeItem(IPC::Connection& connection, uint64_t storageAreaID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& urlString)
+{
+    ASSERT(!RunLoop::isMain());
+
+    auto* storageArea = m_storageAreas.get(storageAreaID);
+    ASSERT(storageArea);
+
+    storageArea->removeItem(connection.uniqueID(), sourceStorageAreaID, key, urlString);
+
+    connection.send(Messages::StorageAreaMap::DidRemoveItem(storageMapSeed, key), storageAreaID);
+}
+
+void StorageManagerSet::clear(IPC::Connection& connection, uint64_t storageAreaID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& urlString)
+{
+    ASSERT(!RunLoop::isMain());
+
+    auto* storageArea = m_storageAreas.get(storageAreaID);
+    ASSERT(storageArea);
+
+    storageArea->clear(connection.uniqueID(), sourceStorageAreaID, urlString);
+
+    connection.send(Messages::StorageAreaMap::DidClear(storageMapSeed), storageAreaID);
+}
+
+void StorageManagerSet::cloneSessionStorageNamespace(IPC::Connection&, PAL::SessionID sessionID, uint64_t fromStorageNamespaceID, uint64_t toStorageNamespaceID)
+{
+    ASSERT(!RunLoop::isMain());
+
+    if (auto* storageManager = m_storageManagers.get(sessionID))
+        storageManager->cloneSessionStorageNamespace(fromStorageNamespaceID, toStorageNamespaceID);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/NetworkProcess/WebStorage/StorageManagerSet.h b/Source/WebKit/NetworkProcess/WebStorage/StorageManagerSet.h
new file mode 100644 (file)
index 0000000..77032ac
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "SandboxExtension.h"
+#include "StorageManager.h"
+#include <WebCore/SecurityOriginData.h>
+#include <pal/SessionID.h>
+
+using WebCore::SecurityOriginData;
+
+namespace WebKit {
+
+class SandboxExtension;
+
+using ConnectToStorageAreaCallback = CompletionHandler<void(uint64_t)>;
+using GetValuesCallback = CompletionHandler<void(const HashMap<String, String>&)>;
+using GetOriginsCallback = CompletionHandler<void(HashSet<WebCore::SecurityOriginData>&&)>;
+using GetOriginDetailsCallback = CompletionHandler<void(Vector<LocalStorageDatabaseTracker::OriginDetails>&&)>;
+using DeleteCallback = CompletionHandler<void()>;
+
+class StorageManagerSet : public IPC::Connection::WorkQueueMessageReceiver {
+public:
+    static Ref<StorageManagerSet> create();
+    StorageManagerSet();
+    ~StorageManagerSet();
+
+    void add(PAL::SessionID, const String& localStorageDirectory, SandboxExtension::Handle& localStorageDirectoryHandle);
+    void remove(PAL::SessionID);
+    bool contains(PAL::SessionID);
+
+    void addConnection(IPC::Connection&);
+    void removeConnection(IPC::Connection&);
+
+    void waitUntilTasksFinished();
+    void waitUntilSyncingLocalStorageFinished();
+    void suspend(CompletionHandler<void()>&&);
+    void resume();
+
+    void getSessionStorageOrigins(PAL::SessionID, GetOriginsCallback&&);
+    void deleteSessionStorage(PAL::SessionID, DeleteCallback&&);
+    void deleteSessionStorageForOrigins(PAL::SessionID, const Vector<WebCore::SecurityOriginData>&, DeleteCallback&&);
+    void getLocalStorageOrigins(PAL::SessionID, GetOriginsCallback&&);
+    void deleteLocalStorageModifiedSince(PAL::SessionID, WallTime, DeleteCallback&&);
+    void deleteLocalStorageForOrigins(PAL::SessionID, const Vector<WebCore::SecurityOriginData>&, DeleteCallback&&);
+    void getLocalStorageOriginDetails(PAL::SessionID, GetOriginDetailsCallback&&);
+
+    void didReceiveMessage(IPC::Connection&, IPC::Decoder&);
+    void didReceiveSyncMessage(IPC::Connection&, IPC::Decoder&, std::unique_ptr<IPC::Encoder>& replyEncoder);
+
+private:
+    // Message Handlers
+    void connectToLocalStorageArea(IPC::Connection&, PAL::SessionID , uint64_t storageNamespaceID, SecurityOriginData&&, ConnectToStorageAreaCallback&&);
+    void connectToTransientLocalStorageArea(IPC::Connection&, PAL::SessionID , uint64_t storageNamespaceID, SecurityOriginData&&, SecurityOriginData&&, ConnectToStorageAreaCallback&&);
+    void connectToSessionStorageArea(IPC::Connection&, PAL::SessionID, uint64_t storageNamespaceID, SecurityOriginData&&, ConnectToStorageAreaCallback&&);
+    void disconnectFromStorageArea(IPC::Connection&, uint64_t storageAreaID);
+    void getValues(IPC::Connection&, uint64_t storageAreaID, GetValuesCallback&&);
+    void setItem(IPC::Connection&, uint64_t storageAreaID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& value, const String& urlString);
+    void removeItem(IPC::Connection&, uint64_t storageAreaID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& urlString);
+    void clear(IPC::Connection&, uint64_t storageAreaID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& urlString);
+    void cloneSessionStorageNamespace(IPC::Connection&, PAL::SessionID, uint64_t fromStorageNamespaceID, uint64_t toStorageNamespaceID);
+
+    HashMap<PAL::SessionID, RefPtr<StorageManager>> m_storageManagers;
+    HashMap<PAL::SessionID, String> m_storageManagerPaths;
+    HashMap<uint64_t, StorageArea*> m_storageAreas;
+
+    HashSet<IPC::Connection::UniqueID> m_connections;
+    Ref<WorkQueue> m_queue;
+
+    enum class State {
+        Running,
+        WillSuspend,
+        Suspended
+    };
+    State m_state { State::Running };
+    Lock m_stateLock;
+    Condition m_stateChangeCondition;
+};
+
+} // namespace WebKit
diff --git a/Source/WebKit/NetworkProcess/WebStorage/StorageManagerSet.messages.in b/Source/WebKit/NetworkProcess/WebStorage/StorageManagerSet.messages.in
new file mode 100644 (file)
index 0000000..e0c13a0
--- /dev/null
@@ -0,0 +1,34 @@
+# Copyright (C) 2019 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 -> StorageManagerSet {
+    ConnectToLocalStorageArea(PAL::SessionID sessionID, uint64_t storageNamespaceID, struct WebCore::SecurityOriginData securityOriginData) -> (uint64_t storageAreaID) Synchronous WantsConnection
+    ConnectToTransientLocalStorageArea(PAL::SessionID sessionID, uint64_t storageNamespaceID, struct WebCore::SecurityOriginData topLevelSecurityOriginData, struct WebCore::SecurityOriginData securityOriginData) -> (uint64_t storageAreaID) Synchronous WantsConnection
+    ConnectToSessionStorageArea(PAL::SessionID sessionID, uint64_t storageNamespaceID, struct WebCore::SecurityOriginData securityOriginData) -> (uint64_t storageAreaID) Synchronous WantsConnection
+    DisconnectFromStorageArea(uint64_t storageAreaID) WantsConnection
+    GetValues(uint64_t storageAreaID) -> (HashMap<String, String> values) Synchronous WantsConnection
+    CloneSessionStorageNamespace(PAL::SessionID sessionID, uint64_t fromStorageNamespaceID, uint64_t toStorageNamespaceID) WantsConnection
+
+    SetItem(uint64_t storageAreaID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, String key, String value, String urlString) WantsConnection
+    RemoveItem(uint64_t storageAreaID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, String key, String urlString) WantsConnection
+    Clear(uint64_t storageAreaID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, String urlString) WantsConnection
+}
index d91a34f..f18dd16 100644 (file)
@@ -53,6 +53,8 @@ void WebsiteDataStoreParameters::encode(IPC::Encoder& encoder) const
     encoder << serviceWorkerRegistrationDirectory << serviceWorkerRegistrationDirectoryExtensionHandle;
 #endif
 
+    encoder << localStorageDirectory << localStorageDirectoryExtensionHandle;
+
     encoder << perOriginStorageQuota;
     encoder << perThirdPartyOriginStorageQuota;
 }
@@ -121,6 +123,18 @@ Optional<WebsiteDataStoreParameters> WebsiteDataStoreParameters::decode(IPC::Dec
     parameters.serviceWorkerRegistrationDirectoryExtensionHandle = WTFMove(*serviceWorkerRegistrationDirectoryExtensionHandle);
 #endif
 
+    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);
+
     Optional<uint64_t> perOriginStorageQuota;
     decoder >> perOriginStorageQuota;
     if (!perOriginStorageQuota)
@@ -149,6 +163,7 @@ WebsiteDataStoreParameters WebsiteDataStoreParameters::privateSessionParameters(
 #if ENABLE(SERVICE_WORKER)
         , { }, { }
 #endif
+        , { }, { }
     };
 }
 
index 992fee9..6fece3f 100644 (file)
@@ -70,6 +70,9 @@ struct WebsiteDataStoreParameters {
     SandboxExtension::Handle serviceWorkerRegistrationDirectoryExtensionHandle;
 #endif
 
+    String localStorageDirectory;
+    SandboxExtension::Handle localStorageDirectoryExtensionHandle;
+
     uint64_t perOriginStorageQuota { WebCore::StorageQuotaManager::defaultQuota() };
     uint64_t perThirdPartyOriginStorageQuota { WebCore::StorageQuotaManager::defaultThirdPartyQuota() };
 };
index 4bc20fd..b466d2c 100644 (file)
@@ -70,6 +70,7 @@ NetworkProcess/WebStorage/LocalStorageNamespace.cpp
 NetworkProcess/WebStorage/SessionStorageNamespace.cpp
 NetworkProcess/WebStorage/StorageArea.cpp
 NetworkProcess/WebStorage/StorageManager.cpp
+NetworkProcess/WebStorage/StorageManagerSet.cpp
 NetworkProcess/WebStorage/TransientLocalStorageNamespace.cpp
 
 NetworkProcess/cache/CacheStorageEngine.cpp
index d0eb31a..d83c6b8 100644 (file)
@@ -669,3 +669,19 @@ void WKContextClearCurrentModifierStateForTesting(WKContextRef contextRef)
 {
     WebKit::toImpl(contextRef)->clearCurrentModifierStateForTesting();
 }
+
+void WKContextSyncLocalStorage(WKContextRef contextRef, void* context, WKContextSyncLocalStorageCallback callback)
+{
+    WebKit::toImpl(contextRef)->syncLocalStorage([context, callback] {
+        if (callback)
+            callback(context);
+    });
+}
+
+void WKContextClearLegacyPrivateBrowsingLocalStorage(WKContextRef contextRef, void* context, WKContextClearLegacyPrivateBrowsingLocalStorageCallback callback)
+{
+    WebKit::toImpl(contextRef)->clearLegacyPrivateBrowsingLocalStorage([context, callback] {
+        if (callback)
+            callback(context);
+    });
+}
index f9c7d32..58f1a92 100644 (file)
@@ -120,6 +120,12 @@ WK_EXPORT void WKContextSetIDBPerOriginQuota(WKContextRef context, uint64_t quot
 
 WK_EXPORT void WKContextClearCurrentModifierStateForTesting(WKContextRef context);
 
+typedef void (*WKContextSyncLocalStorageCallback)(void* functionContext);
+WK_EXPORT void WKContextSyncLocalStorage(WKContextRef contextRef, void* context, WKContextSyncLocalStorageCallback callback);
+
+typedef void (*WKContextClearLegacyPrivateBrowsingLocalStorageCallback)(void* functionContext);
+WK_EXPORT void WKContextClearLegacyPrivateBrowsingLocalStorage(WKContextRef contextRef, void* context, WKContextClearLegacyPrivateBrowsingLocalStorageCallback callback);
+
 #ifdef __cplusplus
 }
 #endif
index 96b2337..8faa76f 100644 (file)
@@ -531,6 +531,15 @@ void WKWebsiteDataStoreRemoveAllIndexedDatabases(WKWebsiteDataStoreRef dataStore
     });
 }
 
+void WKWebsiteDataStoreRemoveLocalStorage(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreRemoveLocalStorageCallback callback)
+{
+    OptionSet<WebKit::WebsiteDataType> dataTypes = WebKit::WebsiteDataType::LocalStorage;
+    WebKit::toImpl(dataStoreRef)->websiteDataStore().removeData(dataTypes, -WallTime::infinity(), [context, callback] {
+        if (callback)
+            callback(context);
+    });
+}
+
 void WKWebsiteDataStoreRemoveAllServiceWorkerRegistrations(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreRemoveAllServiceWorkerRegistrationsCallback callback)
 {
 #if ENABLE(SERVICE_WORKER)
index cde14ca..7dec92a 100644 (file)
@@ -121,6 +121,9 @@ WK_EXPORT void WKWebsiteDataStoreRemoveAllIndexedDatabases(WKWebsiteDataStoreRef
 typedef void (*WKWebsiteDataStoreGetFetchCacheOriginsFunction)(WKArrayRef, void*);
 WK_EXPORT void WKWebsiteDataStoreGetFetchCacheOrigins(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreGetFetchCacheOriginsFunction function);
 
+typedef void (*WKWebsiteDataStoreRemoveLocalStorageCallback)(void* functionContext);
+WK_EXPORT void WKWebsiteDataStoreRemoveLocalStorage(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreRemoveLocalStorageCallback callback);
+
 typedef void (*WKWebsiteDataStoreGetFetchCacheSizeForOriginFunction)(uint64_t, void*);
 WK_EXPORT void WKWebsiteDataStoreGetFetchCacheSizeForOrigin(WKWebsiteDataStoreRef dataStoreRef, WKStringRef origin, void* context, WKWebsiteDataStoreGetFetchCacheSizeForOriginFunction function);
 
index 36367f0..b976791 100644 (file)
@@ -583,8 +583,8 @@ NetworkProcessProxy& WebProcessPool::ensureNetworkProcess(WebsiteDataStore* with
     auto localStorageDirectory = m_websiteDataStore ? m_websiteDataStore->websiteDataStore().resolvedLocalStorageDirectory() : nullString();
     if (!localStorageDirectory)
         localStorageDirectory = API::WebsiteDataStore::defaultLocalStorageDirectory();
-    parameters.defaultDataStoreParameters.networkSessionParameters.localStorageDirectory = localStorageDirectory;
-    SandboxExtension::createHandleForReadWriteDirectory(localStorageDirectory, parameters.defaultDataStoreParameters.networkSessionParameters.localStorageDirectoryExtensionHandle);
+    parameters.defaultDataStoreParameters.localStorageDirectory = localStorageDirectory;
+    SandboxExtension::createHandleForReadWriteDirectory(localStorageDirectory, parameters.defaultDataStoreParameters.localStorageDirectoryExtensionHandle);
 
     if (m_websiteDataStore)
         parameters.defaultDataStoreParameters.networkSessionParameters.resourceLoadStatisticsDirectory = m_websiteDataStore->websiteDataStore().resolvedResourceLoadStatisticsDirectory();
@@ -1809,6 +1809,19 @@ void WebProcessPool::setIDBPerOriginQuota(uint64_t quota)
 #endif
 }
 
+void WebProcessPool::syncLocalStorage(CompletionHandler<void()>&& completionHandler)
+{
+    sendSyncToNetworkingProcess(Messages::NetworkProcess::SyncLocalStorage(), Messages::NetworkProcess::SyncLocalStorage::Reply());
+    completionHandler();
+}
+
+void WebProcessPool::clearLegacyPrivateBrowsingLocalStorage(CompletionHandler<void()>&& completionHandler)
+{
+    if (m_networkProcess)
+        m_networkProcess->send(Messages::NetworkProcess::ClearLegacyPrivateBrowsingLocalStorage(), 0);
+    completionHandler();
+}
+
 void WebProcessPool::allowSpecificHTTPSCertificateForHost(const WebCertificateInfo* certificate, const String& host)
 {
     ensureNetworkProcess();
index 2ccb47f..ed6c29f 100644 (file)
@@ -317,6 +317,8 @@ public:
     void disableServiceWorkerProcessTerminationDelay();
 
     void syncNetworkProcessCookies();
+    void syncLocalStorage(CompletionHandler<void()>&& callback);
+    void clearLegacyPrivateBrowsingLocalStorage(CompletionHandler<void()>&& callback);
 
     void setIDBPerOriginQuota(uint64_t);
 
index ba9fcce..a0544d0 100644 (file)
@@ -109,11 +109,6 @@ WebsiteDataStoreParameters WebsiteDataStore::parameters()
     if (!resourceLoadStatisticsDirectory.isEmpty())
         SandboxExtension::createHandleForReadWriteDirectory(resourceLoadStatisticsDirectory, resourceLoadStatisticsDirectoryHandle);
 
-    auto localStorageDirectory = resolvedLocalStorageDirectory();
-    SandboxExtension::Handle localStorageDirectoryExtensionHandle;
-    if (!localStorageDirectory.isEmpty())
-        SandboxExtension::createHandleForReadWriteDirectory(localStorageDirectory, localStorageDirectoryExtensionHandle);
-
     auto networkCacheDirectory = resolvedNetworkCacheDirectory();
     SandboxExtension::Handle networkCacheDirectoryExtensionHandle;
     if (!networkCacheDirectory.isEmpty())
@@ -143,8 +138,6 @@ WebsiteDataStoreParameters WebsiteDataStore::parameters()
         m_configuration->deviceManagementRestrictionsEnabled(),
         m_configuration->allLoadsBlockedByDeviceManagementRestrictionsForTesting(),
         WTFMove(resourceLoadStatisticsManualPrevalentResource),
-        WTFMove(localStorageDirectory),
-        WTFMove(localStorageDirectoryExtensionHandle),
         WTFMove(networkCacheDirectory),
         WTFMove(networkCacheDirectoryExtensionHandle),
     };
@@ -180,6 +173,10 @@ WebsiteDataStoreParameters WebsiteDataStore::parameters()
         SandboxExtension::createHandleForReadWriteDirectory(parameters.serviceWorkerRegistrationDirectory, parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
 #endif
 
+    parameters.localStorageDirectory = resolvedLocalStorageDirectory();
+    if (!parameters.localStorageDirectory.isEmpty())
+        SandboxExtension::createHandleForReadWriteDirectory(parameters.localStorageDirectory, parameters.localStorageDirectoryExtensionHandle);
+
     parameters.perOriginStorageQuota = perOriginStorageQuota();
     parameters.perThirdPartyOriginStorageQuota = perThirdPartyOriginStorageQuota();
 
index 02587b1..6ff1bcd 100644 (file)
@@ -1969,8 +1969,8 @@ WebsiteDataStoreParameters WebsiteDataStore::parameters()
 
     auto localStorageDirectory = resolvedLocalStorageDirectory();
     if (!localStorageDirectory.isEmpty()) {
-        parameters.networkSessionParameters.localStorageDirectory = localStorageDirectory;
-        SandboxExtension::createHandleForReadWriteDirectory(localStorageDirectory, parameters.networkSessionParameters.localStorageDirectoryExtensionHandle);
+        parameters.localStorageDirectory = localStorageDirectory;
+        SandboxExtension::createHandleForReadWriteDirectory(localStorageDirectory, parameters.localStorageDirectoryExtensionHandle);
     }
 
 #if ENABLE(INDEXED_DATABASE)
index b13e33d..7e9e9e2 100644 (file)
                1AB1F7971D1B3613007C9BD1 /* WebPaymentCoordinatorMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AB1F7931D1B3613007C9BD1 /* WebPaymentCoordinatorMessages.h */; };
                1AB1F7981D1B3613007C9BD1 /* WebPaymentCoordinatorProxyMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AB1F7941D1B3613007C9BD1 /* WebPaymentCoordinatorProxyMessageReceiver.cpp */; };
                1AB1F7991D1B3613007C9BD1 /* WebPaymentCoordinatorProxyMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AB1F7951D1B3613007C9BD1 /* WebPaymentCoordinatorProxyMessages.h */; };
-               1AB31A9616BC688100F6DBC9 /* StorageManagerMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AB31A9416BC688100F6DBC9 /* StorageManagerMessageReceiver.cpp */; };
-               1AB31A9716BC688100F6DBC9 /* StorageManagerMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AB31A9516BC688100F6DBC9 /* StorageManagerMessages.h */; };
                1AB40EE61BF677E300BA81BE /* WKMenuItemIdentifiersPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AB40EE41BF677E300BA81BE /* WKMenuItemIdentifiersPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
                1AB474D8184D43FD0051B622 /* WKBundlePageLoaderClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AB474D7184D43FD0051B622 /* WKBundlePageLoaderClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
                1AB474DA184D44250051B622 /* WKBundlePageResourceLoadClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AB474D9184D44250051B622 /* WKBundlePageResourceLoadClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
                9356F2E12152B76600E6D5DF /* WebSWServerConnection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93BA04E12151ADF4007F455F /* WebSWServerConnection.cpp */; };
                935EEB9B1277617C003322B8 /* WKBundleBackForwardListItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 935EEB981277616D003322B8 /* WKBundleBackForwardListItem.h */; settings = {ATTRIBUTES = (Private, ); }; };
                935EEB9F127761AC003322B8 /* WKBundleBackForwardList.h in Headers */ = {isa = PBXBuildFile; fileRef = 935EEB961277616D003322B8 /* WKBundleBackForwardList.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               9368EEDE2303A90200BDB11A /* StorageManagerSetMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9368EEDC2303A8D800BDB11A /* StorageManagerSetMessageReceiver.cpp */; };
+               9368EEDF2303A9ED00BDB11A /* StorageManagerSetMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 9368EEDD2303A8D800BDB11A /* StorageManagerSetMessages.h */; };
+               936B059823039097002FC06B /* StorageManagerSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 936B05952303900B002FC06B /* StorageManagerSet.h */; };
                93735EBB1C92986300336FA7 /* WKPreviewActionItemInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 93735EBA1C92986300336FA7 /* WKPreviewActionItemInternal.h */; };
                9391074F1BF6BC65008C17AD /* WKPreviewElementInfoInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 9391074E1BF6BC65008C17AD /* WKPreviewElementInfoInternal.h */; };
                9391F2CB121B67AD00EBF7E8 /* WebFrameNetworkingContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 9391F283121B38F500EBF7E8 /* WebFrameNetworkingContext.h */; };
                        compilerSpec = com.apple.compilers.proxy.script;
                        filePatterns = "*.h";
                        fileType = pattern.proxy;
+                       inputFiles = (
+                       );
                        isEditable = 1;
                        outputFiles = (
                                "$(HEADER_OUTPUT_DIR)/$(INPUT_FILE_NAME)",
                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; };
-               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>"; };
                1AB40EE41BF677E300BA81BE /* WKMenuItemIdentifiersPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKMenuItemIdentifiersPrivate.h; sourceTree = "<group>"; };
                1AB474D7184D43FD0051B622 /* WKBundlePageLoaderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKBundlePageLoaderClient.h; sourceTree = "<group>"; };
                935EEB961277616D003322B8 /* WKBundleBackForwardList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKBundleBackForwardList.h; sourceTree = "<group>"; };
                935EEB971277616D003322B8 /* WKBundleBackForwardListItem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKBundleBackForwardListItem.cpp; sourceTree = "<group>"; };
                935EEB981277616D003322B8 /* WKBundleBackForwardListItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKBundleBackForwardListItem.h; sourceTree = "<group>"; };
+               9368EEDC2303A8D800BDB11A /* StorageManagerSetMessageReceiver.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = StorageManagerSetMessageReceiver.cpp; path = DerivedSources/WebKit2/StorageManagerSetMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
+               9368EEDD2303A8D800BDB11A /* StorageManagerSetMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StorageManagerSetMessages.h; path = DerivedSources/WebKit2/StorageManagerSetMessages.h; sourceTree = BUILT_PRODUCTS_DIR; };
+               936B05952303900B002FC06B /* StorageManagerSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageManagerSet.h; sourceTree = "<group>"; };
+               936B05962303900B002FC06B /* StorageManagerSet.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = StorageManagerSet.messages.in; sourceTree = "<group>"; };
+               936B05972303900B002FC06B /* StorageManagerSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StorageManagerSet.cpp; sourceTree = "<group>"; };
                93735EBA1C92986300336FA7 /* WKPreviewActionItemInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKPreviewActionItemInternal.h; sourceTree = "<group>"; };
                9391074E1BF6BC65008C17AD /* WKPreviewElementInfoInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKPreviewElementInfoInternal.h; sourceTree = "<group>"; };
                9391F283121B38F500EBF7E8 /* WebFrameNetworkingContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebFrameNetworkingContext.h; 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>"; };
                                46BEB6D522FB9BD600269867 /* StorageArea.h */,
                                93B2614A227D147200B97A76 /* StorageManager.cpp */,
                                93B26149227D147200B97A76 /* StorageManager.h */,
-                               93B2614B227D147200B97A76 /* StorageManager.messages.in */,
+                               936B05972303900B002FC06B /* StorageManagerSet.cpp */,
+                               936B05952303900B002FC06B /* StorageManagerSet.h */,
+                               936B05962303900B002FC06B /* StorageManagerSet.messages.in */,
                                46BEB6E222FBB21A00269867 /* TransientLocalStorageNamespace.cpp */,
                                46BEB6E122FBB21A00269867 /* TransientLocalStorageNamespace.h */,
                        );
                                2DE6943C18BD2A68005C15E5 /* SmartMagnificationControllerMessages.h */,
                                1A334DEB16DE8F88006A8E38 /* StorageAreaMapMessageReceiver.cpp */,
                                1A334DEC16DE8F88006A8E38 /* StorageAreaMapMessages.h */,
-                               1AB31A9416BC688100F6DBC9 /* StorageManagerMessageReceiver.cpp */,
-                               1AB31A9516BC688100F6DBC9 /* StorageManagerMessages.h */,
+                               9368EEDC2303A8D800BDB11A /* StorageManagerSetMessageReceiver.cpp */,
+                               9368EEDD2303A8D800BDB11A /* StorageManagerSetMessages.h */,
                                5118E9A51F295963003EF9F5 /* StorageProcessMessageReceiver.cpp */,
                                5118E9A61F295963003EF9F5 /* StorageProcessMessages.h */,
                                5118E9A71F295963003EF9F5 /* StorageProcessProxyMessageReceiver.cpp */,
                                1ACECD2517162DB1001FC9EF /* StorageAreaMap.h in Headers */,
                                1A334DEE16DE8F88006A8E38 /* StorageAreaMapMessages.h in Headers */,
                                93B2614D227D149E00B97A76 /* StorageManager.h in Headers */,
-                               1AB31A9716BC688100F6DBC9 /* StorageManagerMessages.h in Headers */,
+                               936B059823039097002FC06B /* StorageManagerSet.h in Headers */,
+                               9368EEDF2303A9ED00BDB11A /* StorageManagerSetMessages.h in Headers */,
                                1AE00D6C18327C1200087DD7 /* StringReference.h in Headers */,
                                296BD85D15019BC30071F424 /* StringUtilities.h in Headers */,
                                57FD318622B3516C008D0E8B /* SubFrameSOAuthorizationSession.h in Headers */,
                                2D92A787212B6AB100F493FD /* ShareableBitmap.cpp in Sources */,
                                2DE6943D18BD2A68005C15E5 /* SmartMagnificationControllerMessageReceiver.cpp in Sources */,
                                1A334DED16DE8F88006A8E38 /* StorageAreaMapMessageReceiver.cpp in Sources */,
-                               1AB31A9616BC688100F6DBC9 /* StorageManagerMessageReceiver.cpp in Sources */,
+                               9368EEDE2303A90200BDB11A /* StorageManagerSetMessageReceiver.cpp in Sources */,
                                2D92A783212B6A7100F493FD /* StringReference.cpp in Sources */,
                                2D11B7512126A282006F8878 /* UnifiedSource1-mm.mm in Sources */,
                                2D11B7522126A282006F8878 /* UnifiedSource1.cpp in Sources */,
index 20ce559..b0dcb90 100644 (file)
@@ -46,6 +46,7 @@
 #include "WebProcessCreationParameters.h"
 #include "WebProcessMessages.h"
 #include "WebProcessPoolMessages.h"
+#include "WebStorageNamespaceProvider.h"
 #include "WebUserContentController.h"
 #include "WebsiteDataStoreParameters.h"
 #include <JavaScriptCore/APICast.h>
@@ -348,9 +349,13 @@ void InjectedBundle::setJavaScriptCanAccessClipboard(WebPageGroupProxy* pageGrou
 void InjectedBundle::setPrivateBrowsingEnabled(WebPageGroupProxy* pageGroup, bool enabled)
 {
     ASSERT(!hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
-    WebProcess::singleton().enablePrivateBrowsingForTesting(enabled);
+    if (enabled)
+        WebProcess::singleton().ensureLegacyPrivateBrowsingSessionInNetworkProcess();
 
     PageGroup::pageGroup(pageGroup->identifier())->enableLegacyPrivateBrowsingForTesting(enabled);
+
+    auto webStorageNameSpaceProvider = WebStorageNamespaceProvider::getOrCreate(pageGroup->pageGroupID());
+    webStorageNameSpaceProvider->enableLegacyPrivateBrowsingForTesting(enabled);
 }
 
 void InjectedBundle::setPopupBlockingEnabled(WebPageGroupProxy* pageGroup, bool enabled)
index 4eb6def..7600550 100644 (file)
@@ -677,7 +677,6 @@ void WebProcess::createWebPage(PageIdentifier pageID, WebPageCreationParameters&
     // 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. 
     auto 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));
@@ -688,8 +687,6 @@ void WebProcess::createWebPage(PageIdentifier pageID, WebPageCreationParameters&
     } else
         result.iterator->value->reinitializeWebPage(WTFMove(parameters));
 
-    ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::WebPageWasAdded(result.iterator->value->sessionID(), pageID, oldPageID), 0);
-
     ASSERT(result.iterator->value);
 }
 
@@ -697,7 +694,6 @@ void WebProcess::removeWebPage(PAL::SessionID sessionID, PageIdentifier pageID)
 {
     ASSERT(m_pageMap.contains(pageID));
 
-    ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::WebPageWasRemoved(sessionID, pageID), 0);
     pageWillLeaveWindow(pageID);
     m_pageMap.remove(pageID);
 
@@ -1246,16 +1242,6 @@ NetworkProcessConnection& WebProcess::ensureNetworkProcessConnection()
             CRASH();
 
         m_networkProcessConnection = NetworkProcessConnection::create(connectionIdentifier);
-
-        // To recover web storage, network process needs to know active webpages to prepare session storage.
-        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198051.
-        // Webpage should be added when Storage is used, not when connection is re-established.
-        for (auto& page : m_pageMap) {
-            if (!page.value)
-                continue;
-
-            m_networkProcessConnection->connection().send(Messages::NetworkConnectionToWebProcess::WebPageWasAdded(page.value->sessionID(), page.key, page.key), 0);
-        }
     }
     
     return *m_networkProcessConnection;
@@ -1286,7 +1272,7 @@ void WebProcess::networkProcessConnectionClosed(NetworkProcessConnection* connec
     ASSERT(m_networkProcessConnection);
     ASSERT_UNUSED(connection, m_networkProcessConnection == connection);
 
-    for (auto* storageAreaMap : m_storageAreaMaps.values())
+    for (auto* storageAreaMap : copyToVector(m_storageAreaMaps.values()))
         storageAreaMap->disconnect();
 
 #if ENABLE(INDEXED_DATABASE)
@@ -1687,25 +1673,9 @@ void WebProcess::unregisterStorageAreaMap(StorageAreaMap& storageAreaMap)
 
 StorageAreaMap* WebProcess::storageAreaMap(uint64_t identifier) const
 {
-    ASSERT(m_storageAreaMaps.contains(identifier));
     return m_storageAreaMaps.get(identifier);
 }
 
-void WebProcess::enablePrivateBrowsingForTesting(bool enable)
-{
-    if (enable)
-        ensureLegacyPrivateBrowsingSessionInNetworkProcess();
-
-    Vector<PageIdentifier> pageIDs;
-    for (auto& page : m_pageMap) {
-        if (page.value)
-            pageIDs.append(page.key);
-    }
-
-    if (!pageIDs.isEmpty())
-        ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::WebProcessSessionChanged(enable ? PAL::SessionID::legacyPrivateSessionID() : PAL::SessionID::defaultSessionID(), pageIDs), 0);
-}
-
 void WebProcess::setResourceLoadStatisticsEnabled(bool enabled)
 {
     WebCore::DeprecatedGlobalSettings::setResourceLoadStatisticsEnabled(enabled);
index 3cb2c49..c591559 100644 (file)
@@ -215,8 +215,6 @@ public:
     void unregisterStorageAreaMap(StorageAreaMap&);
     StorageAreaMap* storageAreaMap(uint64_t identifier) const;
 
-    void enablePrivateBrowsingForTesting(bool);
-
 #if PLATFORM(COCOA)
     RetainPtr<CFDataRef> sourceApplicationAuditData() const;
     void destroyRenderingResources();
index 740c0db..ecd2b93 100644 (file)
@@ -33,6 +33,7 @@
 #include <WebCore/SchemeRegistry.h>
 #include <WebCore/SecurityOriginData.h>
 #include <WebCore/Settings.h>
+#include <WebCore/StorageType.h>
 
 namespace WebKit {
 using namespace WebCore;
@@ -50,7 +51,7 @@ Ref<StorageAreaImpl> StorageAreaImpl::create(Ref<StorageAreaMap>&& storageAreaMa
 
 StorageAreaImpl::StorageAreaImpl(Ref<StorageAreaMap>&& storageAreaMap)
     : m_storageAreaID(generateStorageAreaID())
-    , m_storageAreaMap(WTFMove(storageAreaMap))
+    , m_storageAreaMap(makeWeakPtr(storageAreaMap.get()))
 {
 }
 
@@ -60,49 +61,54 @@ StorageAreaImpl::~StorageAreaImpl()
 
 unsigned StorageAreaImpl::length()
 {
-    return m_storageAreaMap->length();
+    return m_storageAreaMap ? m_storageAreaMap->length() : 0;
 }
 
 String StorageAreaImpl::key(unsigned index)
 {
-    return m_storageAreaMap->key(index);
+    return m_storageAreaMap ? m_storageAreaMap->key(index) : nullString();
 }
 
 String StorageAreaImpl::item(const String& key)
 {
-    return m_storageAreaMap->item(key);
-}
-
-bool StorageAreaImpl::prewarm()
-{
-    return m_storageAreaMap->prewarm();
+    return m_storageAreaMap ? m_storageAreaMap->item(key) : nullString();
 }
 
 void StorageAreaImpl::setItem(Frame* sourceFrame, const String& key, const String& value, bool& quotaException)
 {
     ASSERT(!value.isNull());
 
-    m_storageAreaMap->setItem(sourceFrame, this, key, value, quotaException);
+    if (m_storageAreaMap)
+        m_storageAreaMap->setItem(sourceFrame, this, key, value, quotaException);
 }
 
 void StorageAreaImpl::removeItem(Frame* sourceFrame, const String& key)
 {
-    m_storageAreaMap->removeItem(sourceFrame, this, key);
+    if (m_storageAreaMap)
+        m_storageAreaMap->removeItem(sourceFrame, this, key);
 }
 
 void StorageAreaImpl::clear(Frame* sourceFrame)
 {
-    m_storageAreaMap->clear(sourceFrame, this);
+    if (m_storageAreaMap)
+        m_storageAreaMap->clear(sourceFrame, this);
 }
 
 bool StorageAreaImpl::contains(const String& key)
 {
-    return m_storageAreaMap->contains(key);
+    if (m_storageAreaMap)
+        return m_storageAreaMap->contains(key);
+
+    return false;
 }
 
 StorageType StorageAreaImpl::storageType() const
 {
-    return m_storageAreaMap->storageType();
+    if (m_storageAreaMap)
+        return m_storageAreaMap->storageType();
+
+    // We probably need an Invalid type.
+    return StorageType::Local;
 }
 
 size_t StorageAreaImpl::memoryBytesUsedByCache()
@@ -112,12 +118,12 @@ size_t StorageAreaImpl::memoryBytesUsedByCache()
 
 void StorageAreaImpl::incrementAccessCount()
 {
-    // Storage access is handled in the UI process, so there's nothing to do here.
+    // Storage access is handled in the network process, so there's nothing to do here.
 }
 
 void StorageAreaImpl::decrementAccessCount()
 {
-    // Storage access is handled in the UI process, so there's nothing to do here.
+    // Storage access is handled in the network process, so there's nothing to do here.
 }
 
 void StorageAreaImpl::closeDatabaseIfIdle()
@@ -126,9 +132,4 @@ void StorageAreaImpl::closeDatabaseIfIdle()
     ASSERT_NOT_REACHED();
 }
 
-const SecurityOriginData& StorageAreaImpl::securityOrigin() const
-{
-    return m_storageAreaMap->securityOrigin().data();
-}
-
 } // namespace WebKit
index b8f16f2..b2a8d50 100644 (file)
@@ -28,6 +28,7 @@
 #include "MessageReceiver.h"
 #include <WebCore/StorageArea.h>
 #include <wtf/HashMap.h>
+#include <wtf/WeakPtr.h>
 
 namespace WebCore {
 class SecurityOrigin;
@@ -60,11 +61,9 @@ private:
     void incrementAccessCount() override;
     void decrementAccessCount() override;
     void closeDatabaseIfIdle() override;
-    const WebCore::SecurityOriginData& securityOrigin() const override;
-    bool prewarm() final;
 
     uint64_t m_storageAreaID;
-    Ref<StorageAreaMap> m_storageAreaMap;
+    WeakPtr<StorageAreaMap> m_storageAreaMap;
 };
 
 } // namespace WebKit
index 3e050df..6665b3f 100644 (file)
@@ -29,7 +29,7 @@
 #include "NetworkProcessConnection.h"
 #include "StorageAreaImpl.h"
 #include "StorageAreaMapMessages.h"
-#include "StorageManagerMessages.h"
+#include "StorageManagerSetMessages.h"
 #include "StorageNamespaceImpl.h"
 #include "WebPage.h"
 #include "WebPageGroupProxy.h"
 namespace WebKit {
 using namespace WebCore;
 
-static uint64_t generateStorageMapID()
-{
-    static uint64_t storageMapID;
-    return ++storageMapID;
-}
-
 Ref<StorageAreaMap> StorageAreaMap::create(StorageNamespaceImpl* storageNamespace, Ref<WebCore::SecurityOrigin>&& securityOrigin)
 {
     return adoptRef(*new StorageAreaMap(storageNamespace, WTFMove(securityOrigin)));
 }
 
 StorageAreaMap::StorageAreaMap(StorageNamespaceImpl* storageNamespace, Ref<WebCore::SecurityOrigin>&& securityOrigin)
-    : m_storageNamespace(*storageNamespace)
-    , m_storageMapID(generateStorageMapID())
+    : m_storageNamespace(storageNamespace)
+    , m_storageMapID(0)
     , m_storageType(storageNamespace->storageType())
-    , m_storageNamespaceID(storageNamespace->storageNamespaceID())
     , m_quotaInBytes(storageNamespace->quotaInBytes())
     , m_securityOrigin(WTFMove(securityOrigin))
     , m_currentSeed(0)
     , m_hasPendingClear(false)
-    , m_hasPendingGetValues(false)
 {
-    WebProcess::singleton().registerStorageAreaMap(*this);
     connect();
 }
 
 StorageAreaMap::~StorageAreaMap()
 {
-    if (m_storageType != StorageType::EphemeralLocal)
-        WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManager::DestroyStorageMap(m_storageMapID), 0);
-
-    m_storageNamespace->didDestroyStorageAreaMap(*this);
-
-    WebProcess::singleton().unregisterStorageAreaMap(*this);
+    disconnect();
 }
 
 unsigned StorageAreaMap::length()
@@ -122,7 +108,7 @@ void StorageAreaMap::setItem(Frame* sourceFrame, StorageAreaImpl* sourceArea, co
 
     m_pendingValueChanges.add(key);
 
-    WebProcess::singleton().ensureNetworkProcessConnection().connection().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::StorageManagerSet::SetItem(m_storageMapID, sourceArea->storageAreaID(), m_currentSeed, key, value, sourceFrame->document()->url()), 0);
 }
 
 void StorageAreaMap::removeItem(WebCore::Frame* sourceFrame, StorageAreaImpl* sourceArea, const String& key)
@@ -138,16 +124,18 @@ void StorageAreaMap::removeItem(WebCore::Frame* sourceFrame, StorageAreaImpl* so
 
     m_pendingValueChanges.add(key);
 
-    WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManager::RemoveItem(m_securityOrigin->data(), m_storageMapID, sourceArea->storageAreaID(), m_currentSeed, key, sourceFrame->document()->url()), 0);
+    WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManagerSet::RemoveItem(m_storageMapID, sourceArea->storageAreaID(), m_currentSeed, key, sourceFrame->document()->url()), 0);
 }
 
 void StorageAreaMap::clear(WebCore::Frame* sourceFrame, StorageAreaImpl* sourceArea)
 {
+    connect();
+
     resetValues();
 
     m_hasPendingClear = true;
     m_storageMap = StorageMap::create(m_quotaInBytes);
-    WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManager::Clear(m_securityOrigin->data(), m_storageMapID, sourceArea->storageAreaID(), m_currentSeed, sourceFrame->document()->url()), 0);
+    WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManagerSet::Clear(m_storageMapID, sourceArea->storageAreaID(), m_currentSeed, sourceFrame->document()->url()), 0);
 }
 
 bool StorageAreaMap::contains(const String& key)
@@ -163,7 +151,6 @@ void StorageAreaMap::resetValues()
 
     m_pendingValueChanges.clear();
     m_hasPendingClear = false;
-    m_hasPendingGetValues = false;
     m_currentSeed++;
 }
 
@@ -178,33 +165,10 @@ 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().ensureNetworkProcessConnection().connection().sendSync(Messages::StorageManager::GetValues(m_storageMapID, m_currentSeed), Messages::StorageManager::GetValues::Reply(values), 0);
+    WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::StorageManagerSet::GetValues(m_storageMapID), Messages::StorageManagerSet::GetValues::Reply(values), 0);
 
     m_storageMap = StorageMap::create(m_quotaInBytes);
     m_storageMap->importItems(WTFMove(values));
-
-    // We want to ignore all changes until we get the DidGetValues message.
-    m_hasPendingGetValues = true;
-}
-
-bool StorageAreaMap::prewarm()
-{
-    if (m_didPrewarm || m_storageMap)
-        return false;
-    m_didPrewarm = true;
-
-    connect();
-    WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManager::Prewarm(m_storageMapID), 0);
-    return true;
-}
-
-void StorageAreaMap::didGetValues(uint64_t storageMapSeed)
-{
-    if (m_currentSeed != storageMapSeed)
-        return;
-
-    ASSERT(m_hasPendingGetValues);
-    m_hasPendingGetValues = false;
 }
 
 void StorageAreaMap::didSetItem(uint64_t storageMapSeed, const String& key, bool quotaError)
@@ -259,8 +223,8 @@ void StorageAreaMap::applyChange(const String& key, const String& newValue)
 {
     ASSERT(!m_storageMap || m_storageMap->hasOneRef());
 
-    // There's a clear pending or getValues pending we don't want to apply any changes until we get the corresponding DidClear/DidGetValues messages.
-    if (m_hasPendingClear || m_hasPendingGetValues)
+    // There is at least one clear pending we don't want to apply any changes until we get the corresponding DidClear messages.
+    if (m_hasPendingClear)
         return;
 
     if (!key) {
@@ -305,7 +269,7 @@ void StorageAreaMap::dispatchStorageEvent(uint64_t sourceStorageAreaID, const St
         applyChange(key, newValue);
     }
 
-    if (storageType() == StorageType::Session || storageType() == StorageType::EphemeralLocal)
+    if (storageType() == StorageType::Session)
         dispatchSessionStorageEvent(sourceStorageAreaID, key, oldValue, newValue, urlString);
     else
         dispatchLocalStorageEvent(sourceStorageAreaID, key, oldValue, newValue, urlString);
@@ -318,9 +282,9 @@ void StorageAreaMap::clearCache()
 
 void StorageAreaMap::dispatchSessionStorageEvent(uint64_t sourceStorageAreaID, const String& key, const String& oldValue, const String& newValue, const String& urlString)
 {
-    // Namespace IDs for session storage namespaces and ephemeral local storage namespaces are equivalent to web page IDs
+    // Namespace IDs for session storage namespaces are equivalent to web page IDs
     // so we can get the right page here.
-    WebPage* webPage = WebProcess::singleton().webPage(makeObjectIdentifier<PageIdentifierType>(m_storageNamespaceID));
+    WebPage* webPage = WebProcess::singleton().webPage(makeObjectIdentifier<PageIdentifierType>(m_storageNamespace->storageNamespaceID()));
     if (!webPage)
         return;
 
@@ -354,7 +318,8 @@ void StorageAreaMap::dispatchLocalStorageEvent(uint64_t sourceStorageAreaID, con
 
     Vector<RefPtr<Frame>> frames;
 
-    PageGroup& pageGroup = *WebProcess::singleton().webPageGroup(m_storageNamespaceID)->corePageGroup();
+    // Namespace IDs for local storage namespaces are equivalent to web page group IDs.
+    PageGroup& pageGroup = *WebProcess::singleton().webPageGroup(m_storageNamespace->storageNamespaceID())->corePageGroup();
     const HashSet<Page*>& pages = pageGroup.pages();
     for (HashSet<Page*>::const_iterator it = pages.begin(), end = pages.end(); it != end; ++it) {
         for (Frame* frame = &(*it)->mainFrame(); frame; frame = frame->tree().traverseNext()) {
@@ -381,35 +346,37 @@ void StorageAreaMap::dispatchLocalStorageEvent(uint64_t sourceStorageAreaID, con
 
 void StorageAreaMap::connect()
 {
-    if (!m_isDisconnected)
+    if (m_storageMapID)
         return;
 
     switch (m_storageType) {
     case StorageType::Local:
-    case StorageType::EphemeralLocal:
     case StorageType::TransientLocal:
         if (SecurityOrigin* topLevelOrigin = m_storageNamespace->topLevelOrigin())
-            WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManager::CreateTransientLocalStorageMap(m_storageMapID, m_storageNamespace->storageNamespaceID(), topLevelOrigin->data(), m_securityOrigin->data()), 0);
+            WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::StorageManagerSet::ConnectToTransientLocalStorageArea(m_storageNamespace->sessionID(), m_storageNamespace->storageNamespaceID(), topLevelOrigin->data(), m_securityOrigin->data()), Messages::StorageManagerSet::ConnectToTransientLocalStorageArea::Reply(m_storageMapID), 0);
         else
-            WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManager::CreateLocalStorageMap(m_storageMapID, m_storageNamespace->storageNamespaceID(), m_securityOrigin->data()), 0);
+            WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::StorageManagerSet::ConnectToLocalStorageArea(m_storageNamespace->sessionID(), m_storageNamespace->storageNamespaceID(), m_securityOrigin->data()), Messages::StorageManagerSet::ConnectToLocalStorageArea::Reply(m_storageMapID), 0);
         break;
     case StorageType::Session:
-        WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManager::CreateSessionStorageMap(m_storageMapID, m_storageNamespace->storageNamespaceID(), m_securityOrigin->data()), 0);
+        WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::StorageManagerSet::ConnectToSessionStorageArea(m_storageNamespace->sessionID(), m_storageNamespace->storageNamespaceID(), m_securityOrigin->data()), Messages::StorageManagerSet::ConnectToSessionStorageArea::Reply(m_storageMapID), 0);
     }
 
-    if (m_storageMap)
-        WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManager::SetItems(m_storageMapID, m_storageMap->items()), 0);
-    m_isDisconnected = false;
+    if (m_storageMapID)
+        WebProcess::singleton().registerStorageAreaMap(*this);
 }
 
 void StorageAreaMap::disconnect()
 {
-    m_isDisconnected = true;
-    if (m_storageType == StorageType::Session && m_storageMap) {
-        m_pendingValueChanges.clear();
-        m_hasPendingClear = false;
-    } else
-        resetValues();
+    if (!m_storageMapID)
+        return;
+
+    resetValues();
+    WebProcess::singleton().unregisterStorageAreaMap(*this);
+
+    if (auto networkProcessConnection = WebProcess::singleton().existingNetworkProcessConnection())
+        networkProcessConnection->connection().send(Messages::StorageManagerSet::DisconnectFromStorageArea(m_storageMapID), 0);
+
+    m_storageMapID = 0;
 }
 
 } // namespace WebKit
index fb91bc9..44ad06f 100644 (file)
@@ -32,6 +32,7 @@
 #include <wtf/HashCountedSet.h>
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
+#include <wtf/WeakPtr.h>
 
 namespace WebCore {
 class SecurityOrigin;
@@ -43,7 +44,7 @@ namespace WebKit {
 class StorageAreaImpl;
 class StorageNamespaceImpl;
 
-class StorageAreaMap : public RefCounted<StorageAreaMap>, private IPC::MessageReceiver {
+class StorageAreaMap : public RefCounted<StorageAreaMap>, private IPC::MessageReceiver, public CanMakeWeakPtr<StorageAreaMap> {
 public:
     static Ref<StorageAreaMap> create(StorageNamespaceImpl*, Ref<WebCore::SecurityOrigin>&&);
     ~StorageAreaMap();
@@ -57,7 +58,6 @@ public:
     void removeItem(WebCore::Frame* sourceFrame, StorageAreaImpl* sourceArea, const String& key);
     void clear(WebCore::Frame* sourceFrame, StorageAreaImpl* sourceArea);
     bool contains(const String& key);
-    bool prewarm();
 
     // IPC::MessageReceiver
     void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
@@ -71,7 +71,6 @@ public:
 private:
     StorageAreaMap(StorageNamespaceImpl*, Ref<WebCore::SecurityOrigin>&&);
 
-    void didGetValues(uint64_t storageMapSeed);
     void didSetItem(uint64_t storageMapSeed, const String& key, bool quotaError);
     void didRemoveItem(uint64_t storageMapSeed, const String& key);
     void didClear(uint64_t storageMapSeed);
@@ -88,12 +87,11 @@ private:
     void dispatchSessionStorageEvent(uint64_t sourceStorageAreaID, const String& key, const String& oldValue, const String& newValue, const String& urlString);
     void dispatchLocalStorageEvent(uint64_t sourceStorageAreaID, const String& key, const String& oldValue, const String& newValue, const String& urlString);
 
-    Ref<StorageNamespaceImpl> m_storageNamespace;
+    StorageNamespaceImpl* m_storageNamespace;
 
     uint64_t m_storageMapID;
 
     WebCore::StorageType m_storageType;
-    uint64_t m_storageNamespaceID;
     unsigned m_quotaInBytes;
     Ref<WebCore::SecurityOrigin> m_securityOrigin;
 
@@ -101,11 +99,7 @@ private:
 
     uint64_t m_currentSeed;
     bool m_hasPendingClear;
-    bool m_hasPendingGetValues;
     HashCountedSet<String> m_pendingValueChanges;
-
-    bool m_isDisconnected { true };
-    bool m_didPrewarm { false };
 };
 
 } // namespace WebKit
index b15904f..7a75d21 100644 (file)
@@ -21,7 +21,6 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 messages -> StorageAreaMap {
-    DidGetValues(uint64_t storageMapSeed)
     DidSetItem(uint64_t storageMapSeed, String key, bool quotaException)
     DidRemoveItem(uint64_t storageMapSeed, String key)
     DidClear(uint64_t storageMapSeed)
index f59c79b..7429618 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "StorageAreaImpl.h"
 #include "StorageAreaMap.h"
+#include "StorageManagerSetMessages.h"
 #include "WebPage.h"
 #include "WebPageGroupProxy.h"
 #include "WebProcess.h"
 namespace WebKit {
 using namespace WebCore;
 
-Ref<StorageNamespaceImpl> StorageNamespaceImpl::createSessionStorageNamespace(uint64_t identifier, unsigned quotaInBytes)
+Ref<StorageNamespaceImpl> StorageNamespaceImpl::createSessionStorageNamespace(uint64_t identifier, unsigned quotaInBytes, PAL::SessionID sessionID)
 {
-    return adoptRef(*new StorageNamespaceImpl(StorageType::Session, identifier, nullptr, quotaInBytes));
+    return adoptRef(*new StorageNamespaceImpl(StorageType::Session, identifier, nullptr, quotaInBytes, sessionID));
 }
 
-Ref<StorageNamespaceImpl> StorageNamespaceImpl::createEphemeralLocalStorageNamespace(uint64_t identifier, unsigned quotaInBytes)
+Ref<StorageNamespaceImpl> StorageNamespaceImpl::createLocalStorageNamespace(uint64_t identifier, unsigned quotaInBytes, PAL::SessionID sessionID)
 {
-    return createLocalStorageNamespace(identifier, quotaInBytes, IsEphemeral::Yes);
+    return adoptRef(*new StorageNamespaceImpl(StorageType::Local, identifier, nullptr, quotaInBytes, sessionID));
 }
 
-Ref<StorageNamespaceImpl> StorageNamespaceImpl::createLocalStorageNamespace(uint64_t identifier, unsigned quotaInBytes, IsEphemeral isEphemeral)
+Ref<StorageNamespaceImpl> StorageNamespaceImpl::createTransientLocalStorageNamespace(uint64_t identifier, WebCore::SecurityOrigin& topLevelOrigin, uint64_t quotaInBytes, PAL::SessionID sessionID)
 {
-    return adoptRef(*new StorageNamespaceImpl(isEphemeral == IsEphemeral::Yes ? StorageType::EphemeralLocal : StorageType::Local, identifier, nullptr, quotaInBytes));
+    return adoptRef(*new StorageNamespaceImpl(StorageType::TransientLocal, identifier, &topLevelOrigin, quotaInBytes, sessionID));
 }
 
-Ref<StorageNamespaceImpl> StorageNamespaceImpl::createTransientLocalStorageNamespace(uint64_t identifier, WebCore::SecurityOrigin& topLevelOrigin, uint64_t quotaInBytes)
-{
-    return adoptRef(*new StorageNamespaceImpl(StorageType::TransientLocal, identifier, &topLevelOrigin, quotaInBytes));
-}
-
-StorageNamespaceImpl::StorageNamespaceImpl(WebCore::StorageType storageType, uint64_t storageNamespaceID, WebCore::SecurityOrigin* topLevelOrigin, unsigned quotaInBytes)
+StorageNamespaceImpl::StorageNamespaceImpl(WebCore::StorageType storageType, uint64_t storageNamespaceID, WebCore::SecurityOrigin* topLevelOrigin, unsigned quotaInBytes, PAL::SessionID sessionID)
     : m_storageType(storageType)
     , m_storageNamespaceID(storageNamespaceID)
     , m_topLevelOrigin(topLevelOrigin)
     , m_quotaInBytes(quotaInBytes)
+    , m_sessionID(sessionID)
 {
 }
 
@@ -77,13 +74,14 @@ void StorageNamespaceImpl::didDestroyStorageAreaMap(StorageAreaMap& map)
     m_storageAreaMaps.remove(map.securityOrigin().data());
 }
 
-Ref<StorageArea> StorageNamespaceImpl::storageArea(const SecurityOriginData& securityOrigin)
+Ref<StorageArea> StorageNamespaceImpl::storageArea(const SecurityOriginData& securityOriginData)
 {
     RefPtr<StorageAreaMap> map;
 
-    auto& slot = m_storageAreaMaps.add(securityOrigin, nullptr).iterator->value;
+    auto securityOrigin = securityOriginData.securityOrigin();
+    auto& slot = m_storageAreaMaps.add(securityOrigin->data(), nullptr).iterator->value;
     if (!slot) {
-        map = StorageAreaMap::create(this, securityOrigin.securityOrigin());
+        map = StorageAreaMap::create(this, WTFMove(securityOrigin));
         slot = map.get();
     } else
         map = slot;
@@ -95,13 +93,17 @@ Ref<StorageNamespace> StorageNamespaceImpl::copy(Page* newPage)
 {
     ASSERT(m_storageNamespaceID);
 
-    if (m_storageType == StorageType::Session)
-        return createSessionStorageNamespace(WebPage::fromCorePage(newPage)->pageID().toUInt64(), m_quotaInBytes);
+    if (auto networkProcessConnection = WebProcess::singleton().existingNetworkProcessConnection())
+        networkProcessConnection->connection().send(Messages::StorageManagerSet::CloneSessionStorageNamespace(newPage->sessionID(), m_storageNamespaceID, WebPage::fromCorePage(newPage)->pageID().toUInt64()), 0);
 
-    ASSERT(m_storageType == StorageType::EphemeralLocal);
-    auto newNamespace = adoptRef(*new StorageNamespaceImpl(m_storageType, m_storageNamespaceID, m_topLevelOrigin.get(), m_quotaInBytes));
+    return adoptRef(*new StorageNamespaceImpl(m_storageType, WebPage::fromCorePage(newPage)->pageID().toUInt64(), m_topLevelOrigin.get(), m_quotaInBytes, newPage->sessionID()));
+}
 
-    return newNamespace;
+void StorageNamespaceImpl::setSessionIDForTesting(PAL::SessionID sessionID)
+{
+    m_sessionID = sessionID;
+    for (auto storageAreaMap : m_storageAreaMaps.values())
+        storageAreaMap->disconnect();
 }
 
 } // namespace WebKit
index ea6d551..5ee89e7 100644 (file)
@@ -39,12 +39,9 @@ class WebPage;
 
 class StorageNamespaceImpl : public WebCore::StorageNamespace {
 public:
-    static Ref<StorageNamespaceImpl> createSessionStorageNamespace(uint64_t identifier, unsigned quotaInBytes);
-    static Ref<StorageNamespaceImpl> createEphemeralLocalStorageNamespace(uint64_t identifier, unsigned quotaInBytes);
-
-    enum class IsEphemeral : bool { No, Yes };
-    static Ref<StorageNamespaceImpl> createLocalStorageNamespace(uint64_t identifier, unsigned quotaInBytes, IsEphemeral isEphemeral);
-    static Ref<StorageNamespaceImpl> createTransientLocalStorageNamespace(uint64_t identifier, WebCore::SecurityOrigin& topLevelOrigin, uint64_t quotaInBytes);
+    static Ref<StorageNamespaceImpl> createSessionStorageNamespace(uint64_t identifier, unsigned quotaInBytes, PAL::SessionID);
+    static Ref<StorageNamespaceImpl> createLocalStorageNamespace(uint64_t identifier, unsigned quotaInBytes, PAL::SessionID);
+    static Ref<StorageNamespaceImpl> createTransientLocalStorageNamespace(uint64_t identifier, WebCore::SecurityOrigin& topLevelOrigin, uint64_t quotaInBytes, PAL::SessionID);
 
     virtual ~StorageNamespaceImpl();
 
@@ -52,11 +49,14 @@ public:
     uint64_t storageNamespaceID() const { return m_storageNamespaceID; }
     WebCore::SecurityOrigin* topLevelOrigin() const { return m_topLevelOrigin.get(); }
     unsigned quotaInBytes() const { return m_quotaInBytes; }
+    PAL::SessionID sessionID() const override { return m_sessionID; }
 
     void didDestroyStorageAreaMap(StorageAreaMap&);
 
+    void setSessionIDForTesting(PAL::SessionID) override;
+
 private:
-    explicit StorageNamespaceImpl(WebCore::StorageType, uint64_t storageNamespaceID, WebCore::SecurityOrigin* topLevelOrigin, unsigned quotaInBytes);
+    explicit StorageNamespaceImpl(WebCore::StorageType, uint64_t storageNamespaceID, WebCore::SecurityOrigin* topLevelOrigin, unsigned quotaInBytes, PAL::SessionID);
 
     Ref<WebCore::StorageArea> storageArea(const WebCore::SecurityOriginData&) override;
     Ref<WebCore::StorageNamespace> copy(WebCore::Page*) override;
@@ -69,7 +69,9 @@ private:
 
     const unsigned m_quotaInBytes;
 
-    HashMap<WebCore::SecurityOriginData, StorageAreaMap*> m_storageAreaMaps;
+    PAL::SessionID m_sessionID;
+
+    HashMap<WebCore::SecurityOriginData, RefPtr<StorageAreaMap>> m_storageAreaMaps;
 };
 
 } // namespace WebKit
index 88a93c5..9e72163 100644 (file)
@@ -67,22 +67,17 @@ WebStorageNamespaceProvider::~WebStorageNamespaceProvider()
 
 Ref<WebCore::StorageNamespace> WebStorageNamespaceProvider::createSessionStorageNamespace(Page& page, unsigned quota)
 {
-    return StorageNamespaceImpl::createSessionStorageNamespace(WebPage::fromCorePage(&page)->pageID().toUInt64(), quota);
+    return StorageNamespaceImpl::createSessionStorageNamespace(WebPage::fromCorePage(&page)->pageID().toUInt64(), quota, page.sessionID());
 }
 
-Ref<WebCore::StorageNamespace> WebStorageNamespaceProvider::createEphemeralLocalStorageNamespace(Page& page, unsigned quota)
+Ref<WebCore::StorageNamespace> WebStorageNamespaceProvider::createLocalStorageNamespace(unsigned quota, PAL::SessionID sessionID)
 {
-    return StorageNamespaceImpl::createEphemeralLocalStorageNamespace(WebPage::fromCorePage(&page)->pageID().toUInt64(), quota);
+    return StorageNamespaceImpl::createLocalStorageNamespace(m_identifier, quota, sessionID);
 }
 
-Ref<WebCore::StorageNamespace> WebStorageNamespaceProvider::createLocalStorageNamespace(unsigned quota)
+Ref<WebCore::StorageNamespace> WebStorageNamespaceProvider::createTransientLocalStorageNamespace(WebCore::SecurityOrigin& topLevelOrigin, unsigned quota, PAL::SessionID sessionID)
 {
-    return StorageNamespaceImpl::createLocalStorageNamespace(m_identifier, quota, StorageNamespaceImpl::IsEphemeral::No);
-}
-
-Ref<WebCore::StorageNamespace> WebStorageNamespaceProvider::createTransientLocalStorageNamespace(WebCore::SecurityOrigin& topLevelOrigin, unsigned quota)
-{
-    return StorageNamespaceImpl::createTransientLocalStorageNamespace(m_identifier, topLevelOrigin, quota);
+    return StorageNamespaceImpl::createTransientLocalStorageNamespace(m_identifier, topLevelOrigin, quota, sessionID);
 }
 
 }
index 3ce6db9..22e42f5 100644 (file)
@@ -38,9 +38,8 @@ private:
     explicit WebStorageNamespaceProvider(uint64_t identifier);
 
     Ref<WebCore::StorageNamespace> createSessionStorageNamespace(WebCore::Page&, unsigned quota) override;
-    Ref<WebCore::StorageNamespace> createEphemeralLocalStorageNamespace(WebCore::Page&, unsigned quota) override;
-    Ref<WebCore::StorageNamespace> createLocalStorageNamespace(unsigned quota) override;
-    Ref<WebCore::StorageNamespace> createTransientLocalStorageNamespace(WebCore::SecurityOrigin&, unsigned quota) override;
+    Ref<WebCore::StorageNamespace> createLocalStorageNamespace(unsigned quota, PAL::SessionID) override;
+    Ref<WebCore::StorageNamespace> createTransientLocalStorageNamespace(WebCore::SecurityOrigin&, unsigned quota, PAL::SessionID) override;
 
     const uint64_t m_identifier;
 };
index d7bffcb..66e5fa3 100644 (file)
@@ -1,3 +1,38 @@
+2019-08-15  Sihui Liu  <sihui_liu@apple.com>
+
+        Some improvements on web storage
+        https://bugs.webkit.org/show_bug.cgi?id=200373
+
+        Reviewed by Geoffrey Garen.
+
+        Do some clean-up and add support for session change of web storage in layout tests.
+
+        * Storage/StorageAreaImpl.cpp:
+        (WebKit::StorageAreaImpl::sessionChanged):
+        * Storage/StorageAreaImpl.h:
+        (): Deleted.
+
+        * Storage/StorageAreaSync.h: make sure StorageAreaSync is destructed on the main thread, as it can be 
+        dereferenced in StorageAreaImpl::sessionChanged and its last reference for final sync could be released on the 
+        background thread.
+
+        * Storage/StorageNamespaceImpl.cpp: replace EphemeralLocalStorage with LocalStorage, and store SessionID in 
+        StorageNamespace.
+        (WebKit::StorageNamespaceImpl::createSessionStorageNamespace):
+        (WebKit::StorageNamespaceImpl::getOrCreateLocalStorageNamespace):
+        (WebKit::StorageNamespaceImpl::StorageNamespaceImpl):
+        (WebKit::StorageNamespaceImpl::copy):
+        (WebKit::StorageNamespaceImpl::close):
+        (WebKit::StorageNamespaceImpl::setSessionIDForTesting):
+        (WebKit::StorageNamespaceImpl::createEphemeralLocalStorageNamespace): Deleted.
+        * Storage/StorageNamespaceImpl.h:
+        * Storage/WebStorageNamespaceProvider.cpp:
+        (WebKit::WebStorageNamespaceProvider::createSessionStorageNamespace):
+        (WebKit::WebStorageNamespaceProvider::createLocalStorageNamespace):
+        (WebKit::WebStorageNamespaceProvider::createTransientLocalStorageNamespace):
+        (WebKit::WebStorageNamespaceProvider::createEphemeralLocalStorageNamespace): Deleted.
+        * Storage/WebStorageNamespaceProvider.h:
+
 2019-08-14  Ryan Haddad  <ryanhaddad@apple.com>
 
         Unreviewed, rolling out r248526.
index 7da5c72..42cc4db 100644 (file)
@@ -292,4 +292,22 @@ void StorageAreaImpl::dispatchStorageEvent(const String& key, const String& oldV
         StorageEventDispatcher::dispatchSessionStorageEvents(key, oldValue, newValue, m_securityOrigin, sourceFrame);
 }
 
+void StorageAreaImpl::sessionChanged(bool isNewSessionPersistent)
+{
+    ASSERT(isMainThread());
+
+    unsigned quota = m_storageMap->quota();
+    m_storageMap = StorageMap::create(quota);
+
+    if (isNewSessionPersistent && !m_storageAreaSync && m_storageSyncManager) {
+        m_storageAreaSync = StorageAreaSync::create(m_storageSyncManager.get(), *this, m_securityOrigin.databaseIdentifier());
+        return;
+    }
+
+    if (!isNewSessionPersistent && m_storageAreaSync) {
+        m_storageAreaSync->scheduleFinalSync();
+        m_storageAreaSync = nullptr;
+    }
+}
+
 } // namespace WebCore
index 58fcba0..b20bef9 100644 (file)
@@ -61,8 +61,6 @@ public:
     void decrementAccessCount() override;
     void closeDatabaseIfIdle() override;
 
-    const WebCore::SecurityOriginData& securityOrigin() const override { return m_securityOrigin; }
-
     Ref<StorageAreaImpl> copy();
     void close();
 
@@ -74,6 +72,8 @@ public:
 
     void sync();
 
+    void sessionChanged(bool isNewSessionPersistent);
+
 private:
     StorageAreaImpl(WebCore::StorageType, const WebCore::SecurityOriginData&, RefPtr<WebCore::StorageSyncManager>&&, unsigned quota);
     explicit StorageAreaImpl(const StorageAreaImpl&);
index c008753..109c7cf 100644 (file)
@@ -39,7 +39,7 @@ namespace WebKit {
 
 class StorageAreaImpl;
 
-class StorageAreaSync : public ThreadSafeRefCounted<StorageAreaSync> {
+class StorageAreaSync : public ThreadSafeRefCounted<StorageAreaSync, WTF::DestructionThread::Main> {
 public:
     static Ref<StorageAreaSync> create(RefPtr<WebCore::StorageSyncManager>&&, Ref<StorageAreaImpl>&&, const String& databaseIdentifier);
     ~StorageAreaSync();
index 4a94a1d..737f5c0 100644 (file)
@@ -45,17 +45,12 @@ static HashMap<String, StorageNamespaceImpl*>& localStorageNamespaceMap()
     return localStorageNamespaceMap;
 }
 
-Ref<StorageNamespaceImpl> StorageNamespaceImpl::createSessionStorageNamespace(unsigned quota)
+Ref<StorageNamespaceImpl> StorageNamespaceImpl::createSessionStorageNamespace(unsigned quota, PAL::SessionID sessionID)
 {
-    return adoptRef(*new StorageNamespaceImpl(StorageType::Session, String(), quota));
+    return adoptRef(*new StorageNamespaceImpl(StorageType::Session, String(), quota, sessionID));
 }
 
-Ref<StorageNamespaceImpl> StorageNamespaceImpl::createEphemeralLocalStorageNamespace(unsigned quota)
-{
-    return adoptRef(*new StorageNamespaceImpl(StorageType::EphemeralLocal, String(), quota));
-}
-
-Ref<StorageNamespaceImpl> StorageNamespaceImpl::getOrCreateLocalStorageNamespace(const String& databasePath, unsigned quota)
+Ref<StorageNamespaceImpl> StorageNamespaceImpl::getOrCreateLocalStorageNamespace(const String& databasePath, unsigned quota, PAL::SessionID sessionID)
 {
     ASSERT(!databasePath.isNull());
 
@@ -63,18 +58,19 @@ Ref<StorageNamespaceImpl> StorageNamespaceImpl::getOrCreateLocalStorageNamespace
     if (slot)
         return *slot;
 
-    Ref<StorageNamespaceImpl> storageNamespace = adoptRef(*new StorageNamespaceImpl(StorageType::Local, databasePath, quota));
+    Ref<StorageNamespaceImpl> storageNamespace = adoptRef(*new StorageNamespaceImpl(StorageType::Local, databasePath, quota, sessionID));
     slot = storageNamespace.ptr();
 
     return storageNamespace;
 }
 
-StorageNamespaceImpl::StorageNamespaceImpl(StorageType storageType, const String& path, unsigned quota)
+StorageNamespaceImpl::StorageNamespaceImpl(StorageType storageType, const String& path, unsigned quota, PAL::SessionID sessionID)
     : m_storageType(storageType)
     , m_path(path.isolatedCopy())
     , m_syncManager(0)
     , m_quota(quota)
     , m_isShutdown(false)
+    , m_sessionID(sessionID)
 {
     if (isPersistentLocalStorage(m_storageType) && !m_path.isEmpty())
         m_syncManager = StorageSyncManager::create(m_path);
@@ -97,9 +93,9 @@ Ref<StorageNamespace> StorageNamespaceImpl::copy(Page*)
 {
     ASSERT(isMainThread());
     ASSERT(!m_isShutdown);
-    ASSERT(m_storageType == StorageType::Session || m_storageType == StorageType::EphemeralLocal);
+    ASSERT(m_storageType == StorageType::Session);
 
-    auto newNamespace = adoptRef(*new StorageNamespaceImpl(m_storageType, m_path, m_quota));
+    auto newNamespace = adoptRef(*new StorageNamespaceImpl(m_storageType, m_path, m_quota, m_sessionID));
     for (auto& iter : m_storageAreaMap)
         newNamespace->m_storageAreaMap.set(iter.key, iter.value->copy());
 
@@ -127,7 +123,7 @@ void StorageNamespaceImpl::close()
         return;
 
     // If we're not a persistent storage, we shouldn't need to do any work here.
-    if (m_storageType == StorageType::Session || m_storageType == StorageType::EphemeralLocal) {
+    if (m_storageType == StorageType::Session) {
         ASSERT(!m_syncManager);
         return;
     }
@@ -176,4 +172,11 @@ void StorageNamespaceImpl::closeIdleLocalStorageDatabases()
         it->value->closeDatabaseIfIdle();
 }
 
+void StorageNamespaceImpl::setSessionIDForTesting(PAL::SessionID sessionID)
+{
+    m_sessionID = sessionID;
+    for (auto storageAreaMap : m_storageAreaMap.values())
+        storageAreaMap->sessionChanged(!sessionID.isEphemeral());
+}
+
 } // namespace WebCore
index c88f061..1203252 100644 (file)
@@ -28,6 +28,7 @@
 #include <WebCore/SecurityOriginData.h>
 #include <WebCore/StorageArea.h>
 #include <WebCore/StorageNamespace.h>
+#include <pal/SessionID.h>
 #include <wtf/HashMap.h>
 #include <wtf/RefPtr.h>
 #include <wtf/text/WTFString.h>
@@ -38,9 +39,8 @@ class StorageAreaImpl;
 
 class StorageNamespaceImpl : public WebCore::StorageNamespace {
 public:
-    static Ref<StorageNamespaceImpl> createSessionStorageNamespace(unsigned quota);
-    static Ref<StorageNamespaceImpl> createEphemeralLocalStorageNamespace(unsigned quota);
-    static Ref<StorageNamespaceImpl> getOrCreateLocalStorageNamespace(const String& databasePath, unsigned quota);
+    static Ref<StorageNamespaceImpl> createSessionStorageNamespace(unsigned quota, PAL::SessionID);
+    static Ref<StorageNamespaceImpl> getOrCreateLocalStorageNamespace(const String& databasePath, unsigned quota, PAL::SessionID);
     virtual ~StorageNamespaceImpl();
 
     void close();
@@ -54,8 +54,11 @@ public:
     void sync();
     void closeIdleLocalStorageDatabases();
 
+    PAL::SessionID sessionID() const override { return m_sessionID; }
+    void setSessionIDForTesting(PAL::SessionID) override;
+
 private:
-    StorageNamespaceImpl(WebCore::StorageType, const String& path, unsigned quota);
+    StorageNamespaceImpl(WebCore::StorageType, const String& path, unsigned quota, PAL::SessionID);
 
     Ref<WebCore::StorageArea> storageArea(const WebCore::SecurityOriginData&) override;
     Ref<StorageNamespace> copy(WebCore::Page* newPage) override;
@@ -73,6 +76,8 @@ private:
     unsigned m_quota;
 
     bool m_isShutdown;
+
+    PAL::SessionID m_sessionID;
 };
 
 } // namespace WebCore
index 8362057..d094691 100644 (file)
@@ -26,6 +26,7 @@
 #include "WebStorageNamespaceProvider.h"
 
 #include "StorageNamespaceImpl.h"
+#include <WebCore/Page.h>
 #include <wtf/NeverDestroyed.h>
 
 using namespace WebCore;
@@ -96,26 +97,21 @@ void WebStorageNamespaceProvider::syncLocalStorage()
     }
 }
 
-Ref<StorageNamespace> WebStorageNamespaceProvider::createSessionStorageNamespace(Page&, unsigned quota)
+Ref<StorageNamespace> WebStorageNamespaceProvider::createSessionStorageNamespace(Page& page, unsigned quota)
 {
-    return StorageNamespaceImpl::createSessionStorageNamespace(quota);
+    return StorageNamespaceImpl::createSessionStorageNamespace(quota, page.sessionID());
 }
 
-Ref<StorageNamespace> WebStorageNamespaceProvider::createEphemeralLocalStorageNamespace(Page&, unsigned quota)
+Ref<StorageNamespace> WebStorageNamespaceProvider::createLocalStorageNamespace(unsigned quota, PAL::SessionID sessionID)
 {
-    return StorageNamespaceImpl::createEphemeralLocalStorageNamespace(quota);
+    return StorageNamespaceImpl::getOrCreateLocalStorageNamespace(m_localStorageDatabasePath, quota, sessionID);
 }
 
-Ref<StorageNamespace> WebStorageNamespaceProvider::createLocalStorageNamespace(unsigned quota)
-{
-    return StorageNamespaceImpl::getOrCreateLocalStorageNamespace(m_localStorageDatabasePath, quota);
-}
-
-Ref<StorageNamespace> WebStorageNamespaceProvider::createTransientLocalStorageNamespace(SecurityOrigin&, unsigned quota)
+Ref<StorageNamespace> WebStorageNamespaceProvider::createTransientLocalStorageNamespace(SecurityOrigin&, unsigned quota, PAL::SessionID sessionID)
 {
     // FIXME: A smarter implementation would create a special namespace type instead of just piggy-backing off
     // SessionStorageNamespace here.
-    return StorageNamespaceImpl::createSessionStorageNamespace(quota);
+    return StorageNamespaceImpl::createSessionStorageNamespace(quota, sessionID);
 }
 
 }
index e589fee..6dbc5c9 100644 (file)
@@ -50,9 +50,8 @@ private:
     explicit WebStorageNamespaceProvider(const String& localStorageDatabasePath);
 
     Ref<WebCore::StorageNamespace> createSessionStorageNamespace(WebCore::Page&, unsigned quota) override;
-    Ref<WebCore::StorageNamespace> createEphemeralLocalStorageNamespace(WebCore::Page&, unsigned quota) override;
-    Ref<WebCore::StorageNamespace> createLocalStorageNamespace(unsigned quota) override;
-    Ref<WebCore::StorageNamespace> createTransientLocalStorageNamespace(WebCore::SecurityOrigin&, unsigned quota) override;
+    Ref<WebCore::StorageNamespace> createLocalStorageNamespace(unsigned quota, PAL::SessionID) override;
+    Ref<WebCore::StorageNamespace> createTransientLocalStorageNamespace(WebCore::SecurityOrigin&, unsigned quota, PAL::SessionID) override;
 
     const String m_localStorageDatabasePath;
 };
index 01d3a59..3ba4950 100644 (file)
@@ -1,3 +1,13 @@
+2019-08-15  Sihui Liu  <sihui_liu@apple.com>
+
+        Some improvements on web storage
+        https://bugs.webkit.org/show_bug.cgi?id=200373
+
+        Reviewed by Geoffrey Garen.
+
+        * WebView/WebView.mm:
+        (-[WebView _preferencesChanged:]): notify storageNamespaceProvider about session change.
+
 2019-08-15  Youenn Fablet  <youenn@apple.com>
 
         Always create a Document with a valid SessionID
index b8d9711..034f0ec 100644 (file)
@@ -2888,6 +2888,7 @@ static bool needsSelfRetainWhileLoadingQuirk()
     settings.setLocalStorageEnabled([preferences localStorageEnabled]);
 
     _private->page->enableLegacyPrivateBrowsing([preferences privateBrowsingEnabled]);
+    _private->group->storageNamespaceProvider().enableLegacyPrivateBrowsingForTesting([preferences privateBrowsingEnabled]);
     settings.setSansSerifFontFamily([preferences sansSerifFontFamily]);
     settings.setSerifFontFamily([preferences serifFontFamily]);
     settings.setStandardFontFamily([preferences standardFontFamily]);
index b165099..e7fbb6a 100644 (file)
@@ -1,3 +1,36 @@
+2019-08-15  Sihui Liu  <sihui_liu@apple.com>
+
+        Some improvements on web storage
+        https://bugs.webkit.org/show_bug.cgi?id=200373
+
+        Reviewed by Geoffrey Garen.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/LocalStoragePersistence.mm:
+        (TEST): update expectation for behavior change.
+
+        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl: new SPI to synchronously flush localStorage to 
+        database file.
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::syncLocalStorage):
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+
+        * WebKitTestRunner/TestController.cpp: clear local storage between test runs to make each test isolated.
+        (WTR::TestController::resetStateToConsistentValues):
+        (WTR::StorageVoidCallbackContext::StorageVoidCallbackContext):
+        (WTR::StorageVoidCallback):
+        (WTR::TestController::clearIndexedDatabases):
+        (WTR::TestController::clearLocalStorage):
+        (WTR::TestController::syncLocalStorage):
+        (WTR::RemoveAllIndexedDatabasesCallbackContext::RemoveAllIndexedDatabasesCallbackContext): Deleted. Replaced
+        with StorageVoidCallbackContext for general usage.
+        (WTR::RemoveAllIndexedDatabasesCallback): Deleted. Replaced with StorageVoidCallback.
+        (WTR::TestController::ClearIndexedDatabases): Deleted. Use lowercase for consistent style.
+        * WebKitTestRunner/TestController.h:
+
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle): add handler for new message 
+        SyncLocalStorage.
+
 2019-08-15  Jonathan Bedard  <jbedard@apple.com>
 
         results.webkit.org: Add content hook to FlaskRequestsResponse
index 11562bb..592bc29 100644 (file)
@@ -104,9 +104,10 @@ TEST(WKWebView, LocalStorageProcessCrashes)
     }];
     TestWebKitAPI::Util::run(&readyToContinue);
 
+    // If network process crashes, sessionStorage would be lost.
     readyToContinue = false;
     [webView evaluateJavaScript:@"window.sessionStorage.getItem('session')" completionHandler:^(id result, NSError *) {
-        EXPECT_TRUE([@"storage" isEqualToString:result]);
+        EXPECT_TRUE([result isEqual:NSNull.null]);
         readyToContinue = true;
     }];
     TestWebKitAPI::Util::run(&readyToContinue);
index 158d2f6..4329ec1 100644 (file)
@@ -142,6 +142,7 @@ interface TestRunner {
     void clearAllDatabases();
     void setDatabaseQuota(unsigned long long quota);
     DOMString pathToLocalResource(DOMString url);
+    void syncLocalStorage();
 
     attribute double databaseDefaultQuota;
     attribute double databaseMaxQuota;
index 1860f16..527566d 100644 (file)
@@ -342,6 +342,13 @@ void TestRunner::setDatabaseQuota(uint64_t quota)
     return WKBundleSetDatabaseQuota(InjectedBundle::singleton().bundle(), quota);
 }
 
+void TestRunner::syncLocalStorage()
+{
+    WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SyncLocalStorage"));
+    WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(true));
+    WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
+}
+
 void TestRunner::clearAllApplicationCaches()
 {
     WKBundlePageClearApplicationCache(InjectedBundle::singleton().page()->page());
index 75093d0..f5736ea 100644 (file)
@@ -159,6 +159,7 @@ public:
     void clearAllDatabases();
     void setDatabaseQuota(uint64_t);
     JSRetainPtr<JSStringRef> pathToLocalResource(JSStringRef);
+    void syncLocalStorage();
 
     // Application Cache
     void clearAllApplicationCaches();
index 8e733be..ea8afb5 100644 (file)
@@ -939,9 +939,11 @@ bool TestController::resetStateToConsistentValues(const TestOptions& options, Re
     auto websiteDataStore = WKContextGetWebsiteDataStore(TestController::singleton().context());
     WKWebsiteDataStoreClearAllDeviceOrientationPermissions(websiteDataStore);
 
-    ClearIndexedDatabases();
     setIDBPerOriginQuota(50 * MB);
 
+    clearIndexedDatabases();
+    clearLocalStorage();
+
     clearServiceWorkerRegistrations();
     clearDOMCaches();
 
@@ -3069,8 +3071,8 @@ void TestController::setIDBPerOriginQuota(uint64_t quota)
     WKContextSetIDBPerOriginQuota(platformContext(), quota);
 }
 
-struct RemoveAllIndexedDatabasesCallbackContext {
-    explicit RemoveAllIndexedDatabasesCallbackContext(TestController& controller)
+struct StorageVoidCallbackContext {
+    explicit StorageVoidCallbackContext(TestController& controller)
         : testController(controller)
     {
     }
@@ -3079,18 +3081,37 @@ struct RemoveAllIndexedDatabasesCallbackContext {
     bool done { false };
 };
 
-static void RemoveAllIndexedDatabasesCallback(void* userData)
+static void StorageVoidCallback(void* userData)
 {
-    auto* context = static_cast<RemoveAllIndexedDatabasesCallbackContext*>(userData);
+    auto* context = static_cast<StorageVoidCallbackContext*>(userData);
     context->done = true;
     context->testController.notifyDone();
 }
 
-void TestController::ClearIndexedDatabases()
+void TestController::clearIndexedDatabases()
+{
+    auto websiteDataStore = WKContextGetWebsiteDataStore(platformContext());
+    StorageVoidCallbackContext context(*this);
+    WKWebsiteDataStoreRemoveAllIndexedDatabases(websiteDataStore, &context, StorageVoidCallback);
+    runUntil(context.done, noTimeout);
+}
+
+void TestController::clearLocalStorage()
 {
     auto websiteDataStore = WKContextGetWebsiteDataStore(platformContext());
-    RemoveAllIndexedDatabasesCallbackContext context(*this);
-    WKWebsiteDataStoreRemoveAllIndexedDatabases(websiteDataStore, &context, RemoveAllIndexedDatabasesCallback);
+    StorageVoidCallbackContext context(*this);
+    WKWebsiteDataStoreRemoveLocalStorage(websiteDataStore, &context, StorageVoidCallback);
+    runUntil(context.done, noTimeout);
+
+    StorageVoidCallbackContext legacyContext(*this);
+    WKContextClearLegacyPrivateBrowsingLocalStorage(platformContext(), &legacyContext, StorageVoidCallback);
+    runUntil(legacyContext.done, noTimeout);
+}
+
+void TestController::syncLocalStorage()
+{
+    StorageVoidCallbackContext context(*this);
+    WKContextSyncLocalStorage(platformContext(), &context, StorageVoidCallback);
     runUntil(context.done, noTimeout);
 }
 
index b95cea3..a5ae56e 100644 (file)
@@ -262,7 +262,9 @@ public:
 
     void removeAllSessionCredentials();
 
-    void ClearIndexedDatabases();
+    void clearIndexedDatabases();
+    void clearLocalStorage();
+    void syncLocalStorage();
 
     void clearServiceWorkerRegistrations();
 
index 28ad1ed..a5aea21 100644 (file)
@@ -1666,6 +1666,11 @@ WKRetainPtr<WKTypeRef> TestInvocation::didReceiveSynchronousMessageFromInjectedB
         return nullptr;
     }
 
+    if (WKStringIsEqualToUTF8CString(messageName, "SyncLocalStorage")) {
+        TestController::singleton().syncLocalStorage();
+        return nullptr;
+    }
+
     ASSERT_NOT_REACHED();
     return nullptr;
 }