Modified: trunk/Source/WebKit/NetworkProcess/WebStorage/StorageManager.cpp (246078 => 246079)
--- trunk/Source/WebKit/NetworkProcess/WebStorage/StorageManager.cpp 2019-06-04 20:42:19 UTC (rev 246078)
+++ trunk/Source/WebKit/NetworkProcess/WebStorage/StorageManager.cpp 2019-06-04 20:54:31 UTC (rev 246079)
@@ -63,7 +63,7 @@
const HashMap<String, String>& items() const;
void clear();
- bool isSessionStorage() const { return !m_localStorageNamespace; }
+ bool isEphemeral() const { return !m_localStorageNamespace; }
private:
explicit StorageArea(LocalStorageNamespace*, const SecurityOriginData&, unsigned quotaInBytes);
@@ -72,7 +72,7 @@
void dispatchEvents(IPC::Connection::UniqueID sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& oldValue, const String& newValue, const String& urlString) const;
- // Will be null if the storage area belongs to a session storage namespace.
+ // Will be null if the storage area belongs to a session storage namespace or the storage area is in an ephemeral session.
LocalStorageNamespace* m_localStorageNamespace;
mutable RefPtr<LocalStorageDatabase> m_localStorageDatabase;
mutable bool m_didImportItemsFromDatabase { false };
@@ -91,12 +91,16 @@
StorageManager* storageManager() const { return &m_storageManager; }
- Ref<StorageArea> getOrCreateStorageArea(SecurityOriginData&&);
+ enum class IsEphemeral : bool { No, Yes };
+ Ref<StorageArea> getOrCreateStorageArea(SecurityOriginData&&, IsEphemeral);
void didDestroyStorageArea(StorageArea*);
void clearStorageAreasMatchingOrigin(const SecurityOriginData&);
void clearAllStorageAreas();
+ Vector<SecurityOriginData> ephemeralOrigins() const;
+ void cloneTo(LocalStorageNamespace& newLocalStorageNamespace);
+
private:
LocalStorageNamespace(StorageManager&, uint64_t storageManagerID);
@@ -104,8 +108,7 @@
uint64_t m_storageNamespaceID;
unsigned m_quotaInBytes;
- // We don't hold an explicit reference to the StorageAreas; they are kept alive by the m_storageAreasByConnection map in StorageManager.
- HashMap<SecurityOriginData, StorageArea*> m_storageAreaMap;
+ HashMap<SecurityOriginData, RefPtr<StorageArea>> m_storageAreaMap;
};
// Suggested by https://www.w3.org/TR/webstorage/#disk-space
@@ -196,7 +199,7 @@
void StorageManager::StorageArea::removeListener(IPC::Connection::UniqueID connectionID, uint64_t storageMapID)
{
- ASSERT(isSessionStorage() || m_eventListeners.contains(std::make_pair(connectionID, storageMapID)));
+ ASSERT(isEphemeral() || m_eventListeners.contains(std::make_pair(connectionID, storageMapID)));
m_eventListeners.remove(std::make_pair(connectionID, storageMapID));
}
@@ -236,7 +239,10 @@
void StorageManager::StorageArea::setItems(const HashMap<String, String>& items)
{
- ASSERT(!m_localStorageDatabase);
+ // Import items from web process if items are not stored on disk.
+ if (!isEphemeral())
+ return;
+
for (auto& item : items) {
String oldValue;
bool quotaException;
@@ -311,9 +317,10 @@
if (!m_localStorageNamespace)
return;
+ ASSERT(m_localStorageNamespace->storageManager()->m_localStorageDatabaseTracker);
// We open the database here even if we've already imported our items to ensure that the database is open if we need to write to it.
if (!m_localStorageDatabase)
- m_localStorageDatabase = LocalStorageDatabase::create(m_localStorageNamespace->storageManager()->m_queue.copyRef(), m_localStorageNamespace->storageManager()->m_localStorageDatabaseTracker.copyRef(), m_securityOrigin);
+ m_localStorageDatabase = LocalStorageDatabase::create(m_localStorageNamespace->storageManager()->m_queue.copyRef(), *m_localStorageNamespace->storageManager()->m_localStorageDatabaseTracker, m_securityOrigin);
if (m_didImportItemsFromDatabase)
return;
@@ -350,14 +357,13 @@
StorageManager::LocalStorageNamespace::~LocalStorageNamespace()
{
- ASSERT(m_storageAreaMap.isEmpty());
}
-auto StorageManager::LocalStorageNamespace::getOrCreateStorageArea(SecurityOriginData&& securityOrigin) -> Ref<StorageArea>
+auto StorageManager::LocalStorageNamespace::getOrCreateStorageArea(SecurityOriginData&& securityOrigin, IsEphemeral isEphemeral) -> Ref<StorageArea>
{
RefPtr<StorageArea> protectedStorageArea;
return *m_storageAreaMap.ensure(securityOrigin, [&]() mutable {
- protectedStorageArea = StorageArea::create(this, WTFMove(securityOrigin), m_quotaInBytes);
+ protectedStorageArea = StorageArea::create(isEphemeral == IsEphemeral::Yes ? nullptr : this, WTFMove(securityOrigin), m_quotaInBytes);
return protectedStorageArea.get();
}).iterator->value;
}
@@ -383,10 +389,26 @@
void StorageManager::LocalStorageNamespace::clearAllStorageAreas()
{
- for (auto* storageArea : m_storageAreaMap.values())
+ for (auto storageArea : m_storageAreaMap.values())
storageArea->clear();
}
+Vector<SecurityOriginData> StorageManager::LocalStorageNamespace::ephemeralOrigins() const
+{
+ Vector<SecurityOriginData> origins;
+ for (const auto& storageArea : m_storageAreaMap.values()) {
+ if (!storageArea->items().isEmpty())
+ origins.append(storageArea->securityOrigin());
+ }
+ return origins;
+}
+
+void StorageManager::LocalStorageNamespace::cloneTo(LocalStorageNamespace& newLocalStorageNamespace)
+{
+ for (auto& pair : m_storageAreaMap)
+ newLocalStorageNamespace.m_storageAreaMap.add(pair.key, pair.value->clone());
+}
+
class StorageManager::SessionStorageNamespace : public ThreadSafeRefCounted<SessionStorageNamespace> {
public:
static Ref<SessionStorageNamespace> create(unsigned quotaInBytes);
@@ -483,11 +505,11 @@
StorageManager::StorageManager(const String& localStorageDirectory)
: m_queue(WorkQueue::create("com.apple.WebKit.StorageManager"))
- , m_localStorageDatabaseTracker(LocalStorageDatabaseTracker::create(m_queue.copyRef(), localStorageDirectory))
- , m_isEphemeral(localStorageDirectory.isNull())
{
// Make sure the encoding is initialized before we start dispatching things to the queue.
UTF8Encoding();
+ if (!localStorageDirectory.isNull())
+ m_localStorageDatabaseTracker = LocalStorageDatabaseTracker::create(m_queue.copyRef(), localStorageDirectory);
}
StorageManager::~StorageManager()
@@ -548,6 +570,13 @@
ASSERT(newSessionStorageNamespace);
sessionStorageNamespace->cloneTo(*newSessionStorageNamespace);
+
+ if (!m_localStorageDatabaseTracker) {
+ if (auto* localStorageNamespace = m_localStorageNamespaces.get(storageNamespaceID)) {
+ LocalStorageNamespace* newlocalStorageNamespace = getOrCreateLocalStorageNamespace(newStorageNamespaceID);
+ localStorageNamespace->cloneTo(*newlocalStorageNamespace);
+ }
+ }
});
}
@@ -629,8 +658,15 @@
m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable {
HashSet<SecurityOriginData> origins;
- for (auto& origin : m_localStorageDatabaseTracker->origins())
- origins.add(origin);
+ if (m_localStorageDatabaseTracker) {
+ for (auto& origin : m_localStorageDatabaseTracker->origins())
+ origins.add(origin);
+ } else {
+ for (const auto& localStorageNameSpace : m_localStorageNamespaces.values()) {
+ for (auto& origin : localStorageNameSpace->ephemeralOrigins())
+ origins.add(origin);
+ }
+ }
for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values()) {
for (auto& origin : transientLocalStorageNamespace->origins())
@@ -646,7 +682,9 @@
void StorageManager::getLocalStorageOriginDetails(Function<void(Vector<LocalStorageDatabaseTracker::OriginDetails>&&)>&& completionHandler)
{
m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable {
- auto originDetails = m_localStorageDatabaseTracker->originDetails();
+ Vector<LocalStorageDatabaseTracker::OriginDetails> originDetails;
+ if (m_localStorageDatabaseTracker)
+ originDetails = m_localStorageDatabaseTracker->originDetails();
RunLoop::main().dispatch([originDetails = WTFMove(originDetails), completionHandler = WTFMove(completionHandler)]() mutable {
completionHandler(WTFMove(originDetails));
@@ -663,7 +701,8 @@
for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values())
transientLocalStorageNamespace->clearStorageAreasMatchingOrigin(copiedOrigin);
- m_localStorageDatabaseTracker->deleteDatabaseWithOrigin(copiedOrigin);
+ if (m_localStorageDatabaseTracker)
+ m_localStorageDatabaseTracker->deleteDatabaseWithOrigin(copiedOrigin);
});
}
@@ -670,16 +709,21 @@
void StorageManager::deleteLocalStorageOriginsModifiedSince(WallTime time, Function<void()>&& completionHandler)
{
m_queue->dispatch([this, protectedThis = makeRef(*this), time, completionHandler = WTFMove(completionHandler)]() mutable {
- auto originsToDelete = m_localStorageDatabaseTracker->databasesModifiedSince(time);
-
- for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values())
- transientLocalStorageNamespace->clearAllStorageAreas();
+ if (m_localStorageDatabaseTracker) {
+ auto originsToDelete = m_localStorageDatabaseTracker->databasesModifiedSince(time);
+
+ for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values())
+ transientLocalStorageNamespace->clearAllStorageAreas();
- for (const auto& origin : originsToDelete) {
+ 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->clearStorageAreasMatchingOrigin(origin);
-
- m_localStorageDatabaseTracker->deleteDatabaseWithOrigin(origin);
+ localStorageNamespace->clearAllStorageAreas();
}
RunLoop::main().dispatch(WTFMove(completionHandler));
@@ -702,7 +746,8 @@
for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values())
transientLocalStorageNamespace->clearStorageAreasMatchingOrigin(origin);
- m_localStorageDatabaseTracker->deleteDatabaseWithOrigin(origin);
+ if (m_localStorageDatabaseTracker)
+ m_localStorageDatabaseTracker->deleteDatabaseWithOrigin(origin);
}
RunLoop::main().dispatch(WTFMove(completionHandler));
@@ -712,7 +757,6 @@
void StorageManager::createLocalStorageMap(IPC::Connection& connection, uint64_t storageMapID, uint64_t storageNamespaceID, SecurityOriginData&& securityOriginData)
{
m_queue->dispatch([this, protectedThis = makeRef(*this), connectionID = connection.uniqueID(), storageMapID, storageNamespaceID, securityOriginData = securityOriginData.isolatedCopy()]() mutable {
- ASSERT(!m_isEphemeral);
std::pair<IPC::Connection::UniqueID, uint64_t> connectionAndStorageMapIDPair(connectionID, storageMapID);
ASSERT((HashMap<std::pair<IPC::Connection::UniqueID, uint64_t>, RefPtr<StorageArea>>::isValidKey(connectionAndStorageMapIDPair)));
@@ -724,7 +768,7 @@
LocalStorageNamespace* localStorageNamespace = getOrCreateLocalStorageNamespace(storageNamespaceID);
ASSERT(localStorageNamespace);
- auto storageArea = localStorageNamespace->getOrCreateStorageArea(WTFMove(securityOriginData));
+ auto storageArea = localStorageNamespace->getOrCreateStorageArea(WTFMove(securityOriginData), m_localStorageDatabaseTracker ? StorageManager::LocalStorageNamespace::IsEphemeral::No : StorageManager::LocalStorageNamespace::IsEphemeral::Yes);
storageArea->addListener(connectionID, storageMapID);
result.iterator->value = WTFMove(storageArea);
@@ -742,7 +786,7 @@
if (it->key.first != connectionID)
continue;
Ref<StorageArea> area = *it->value;
- if (!area->isSessionStorage())
+ if (!area->isEphemeral())
continue;
if (!origin.securityOrigin()->isSameSchemeHostPort(area->securityOrigin().securityOrigin().get()))
continue;
@@ -772,11 +816,6 @@
void StorageManager::createSessionStorageMap(IPC::Connection& connection, uint64_t storageMapID, uint64_t storageNamespaceID, SecurityOriginData&& securityOriginData)
{
m_queue->dispatch([this, protectedThis = makeRef(*this), connectionID = connection.uniqueID(), storageMapID, storageNamespaceID, securityOriginData = securityOriginData.isolatedCopy()]() mutable {
- if (m_isEphemeral) {
- m_ephemeralStorage.add(securityOriginData, WebCore::StorageMap::create(localStorageDatabaseQuotaInBytes));
- return;
- }
-
ASSERT(m_sessionStorageNamespaces.isValidKey(storageNamespaceID));
SessionStorageNamespace* sessionStorageNamespace = m_sessionStorageNamespaces.get(storageNamespaceID);
@@ -814,7 +853,7 @@
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->isSessionStorage())
+ if (it->value->isEphemeral())
return;
m_storageAreasByConnection.remove(connectionAndStorageMapIDPair);
@@ -832,14 +871,11 @@
{
m_queue->dispatch([this, protectedThis = makeRef(*this), connection = makeRef(connection), securityOriginData = securityOriginData.isolatedCopy(), storageMapID, storageMapSeed, completionHandler = WTFMove(completionHandler)]() mutable {
auto* storageArea = findStorageArea(connection.get(), storageMapID);
- if (!storageArea) {
- if (m_isEphemeral) {
- if (auto storageMap = m_ephemeralStorage.get(securityOriginData))
- return didGetValues(connection.get(), storageMapID, storageMap->items(), WTFMove(completionHandler));
- }
- // This is a session storage area for a page that has already been closed. Ignore it.
+
+ // This is a session storage area for a page that has already been closed. Ignore it.
+ if (!storageArea)
return didGetValues(connection.get(), storageMapID, { }, WTFMove(completionHandler));
- }
+
didGetValues(connection.get(), storageMapID, storageArea->items(), WTFMove(completionHandler));
connection->send(Messages::StorageAreaMap::DidGetValues(storageMapSeed), storageMapID);
});
@@ -849,17 +885,10 @@
{
m_queue->dispatch([this, protectedThis = makeRef(*this), connection = makeRef(connection), securityOriginData = securityOriginData.isolatedCopy(), storageMapID, sourceStorageAreaID, storageMapSeed, key = key.isolatedCopy(), value = value.isolatedCopy(), urlString = urlString.isolatedCopy()]() mutable {
auto* storageArea = findStorageArea(connection.get(), storageMapID);
- if (!storageArea) {
- if (m_isEphemeral) {
- if (auto storageMap = m_ephemeralStorage.get(securityOriginData)) {
- String oldValue;
- bool quotaException;
- storageMap->setItem(key, value, oldValue, quotaException);
- }
- }
- // This is a session storage area for a page that has already been closed. Ignore it.
+
+ // 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);
@@ -879,16 +908,10 @@
{
m_queue->dispatch([this, protectedThis = makeRef(*this), connection = makeRef(connection), securityOriginData = securityOriginData.isolatedCopy(), storageMapID, sourceStorageAreaID, storageMapSeed, key = key.isolatedCopy(), urlString = urlString.isolatedCopy()]() mutable {
auto* storageArea = findStorageArea(connection.get(), storageMapID);
- if (!storageArea) {
- if (m_isEphemeral) {
- if (auto storageMap = m_ephemeralStorage.get(securityOriginData)) {
- String oldValue;
- storageMap->removeItem(key, oldValue);
- }
- }
- // This is a session storage area for a page that has already been closed. Ignore it.
+
+ // This is a session storage area for a page that has already been closed. Ignore it.
+ if (!storageArea)
return;
- }
storageArea->removeItem(connection->uniqueID(), sourceStorageAreaID, key, urlString);
connection->send(Messages::StorageAreaMap::DidRemoveItem(storageMapSeed, key), storageMapID);
@@ -899,12 +922,10 @@
{
m_queue->dispatch([this, protectedThis = makeRef(*this), connection = makeRef(connection), securityOriginData = securityOriginData.isolatedCopy(), storageMapID, sourceStorageAreaID, storageMapSeed, urlString = urlString.isolatedCopy()]() mutable {
auto* storageArea = findStorageArea(connection.get(), storageMapID);
- if (!storageArea) {
- if (m_isEphemeral)
- m_ephemeralStorage.remove(securityOriginData);
- // This is a session storage area for a page that has already been closed. Ignore it.
+
+ // 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);
@@ -931,7 +952,7 @@
void StorageManager::suspend(CompletionHandler<void()>&& completionHandler)
{
- if (m_isEphemeral)
+ if (!m_localStorageDatabaseTracker)
return;
Locker<Lock> stateLocker(m_stateLock);
@@ -956,7 +977,7 @@
void StorageManager::resume()
{
- if (m_isEphemeral)
+ if (!m_localStorageDatabaseTracker)
return;
Locker<Lock> stateLocker(m_stateLock);
Modified: trunk/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.cpp (246078 => 246079)
--- trunk/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.cpp 2019-06-04 20:42:19 UTC (rev 246078)
+++ trunk/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.cpp 2019-06-04 20:54:31 UTC (rev 246079)
@@ -294,7 +294,7 @@
applyChange(key, newValue);
}
- if (storageType() == StorageType::Session)
+ if (storageType() == StorageType::Session || storageType() == StorageType::EphemeralLocal)
dispatchSessionStorageEvent(sourceStorageAreaID, key, oldValue, newValue, urlString);
else
dispatchLocalStorageEvent(sourceStorageAreaID, key, oldValue, newValue, urlString);
@@ -307,9 +307,7 @@
void StorageAreaMap::dispatchSessionStorageEvent(uint64_t sourceStorageAreaID, const String& key, const String& oldValue, const String& newValue, const String& urlString)
{
- ASSERT(storageType() == StorageType::Session);
-
- // Namespace IDs for session storage namespaces are equivalent to web page IDs
+ // Namespace IDs for session storage namespaces and ephemeral local 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));
if (!webPage)
@@ -377,6 +375,7 @@
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);
@@ -385,14 +384,10 @@
break;
case StorageType::Session:
WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManager::CreateSessionStorageMap(m_storageMapID, m_storageNamespace->storageNamespaceID(), m_securityOrigin->data()), 0);
- if (m_storageMap)
- WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManager::SetItems(m_storageMapID, m_storageMap->items()), 0);
- break;
- case StorageType::EphemeralLocal:
- ASSERT_NOT_REACHED();
- return;
}
+ if (m_storageMap)
+ WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManager::SetItems(m_storageMapID, m_storageMap->items()), 0);
m_isDisconnected = false;
}