summaryrefslogtreecommitdiff
path: root/Source/WebKit2/UIProcess/Storage
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit2/UIProcess/Storage')
-rw-r--r--Source/WebKit2/UIProcess/Storage/LocalStorageDatabase.cpp58
-rw-r--r--Source/WebKit2/UIProcess/Storage/LocalStorageDatabase.h22
-rw-r--r--Source/WebKit2/UIProcess/Storage/LocalStorageDatabaseTracker.cpp159
-rw-r--r--Source/WebKit2/UIProcess/Storage/LocalStorageDatabaseTracker.h44
-rw-r--r--Source/WebKit2/UIProcess/Storage/StorageManager.cpp612
-rw-r--r--Source/WebKit2/UIProcess/Storage/StorageManager.h82
-rw-r--r--Source/WebKit2/UIProcess/Storage/StorageManager.messages.in5
7 files changed, 643 insertions, 339 deletions
diff --git a/Source/WebKit2/UIProcess/Storage/LocalStorageDatabase.cpp b/Source/WebKit2/UIProcess/Storage/LocalStorageDatabase.cpp
index 2595f074b..67ecb8945 100644
--- a/Source/WebKit2/UIProcess/Storage/LocalStorageDatabase.cpp
+++ b/Source/WebKit2/UIProcess/Storage/LocalStorageDatabase.cpp
@@ -27,13 +27,14 @@
#include "LocalStorageDatabase.h"
#include "LocalStorageDatabaseTracker.h"
-#include "WorkQueue.h"
#include <WebCore/FileSystem.h>
#include <WebCore/SQLiteStatement.h>
#include <WebCore/SQLiteTransaction.h>
#include <WebCore/SecurityOrigin.h>
#include <WebCore/StorageMap.h>
+#include <WebCore/SuddenTermination.h>
#include <wtf/PassRefPtr.h>
+#include <wtf/WorkQueue.h>
#include <wtf/text/StringHash.h>
#include <wtf/text/WTFString.h>
@@ -45,16 +46,16 @@ static const int maximumItemsToUpdate = 100;
namespace WebKit {
-PassRefPtr<LocalStorageDatabase> LocalStorageDatabase::create(PassRefPtr<WorkQueue> queue, PassRefPtr<LocalStorageDatabaseTracker> tracker, PassRefPtr<SecurityOrigin> securityOrigin)
+Ref<LocalStorageDatabase> LocalStorageDatabase::create(Ref<WorkQueue>&& queue, Ref<LocalStorageDatabaseTracker>&& tracker, const SecurityOriginData& securityOrigin)
{
- return adoptRef(new LocalStorageDatabase(queue, tracker, securityOrigin));
+ return adoptRef(*new LocalStorageDatabase(WTFMove(queue), WTFMove(tracker), securityOrigin));
}
-LocalStorageDatabase::LocalStorageDatabase(PassRefPtr<WorkQueue> queue, PassRefPtr<LocalStorageDatabaseTracker> tracker, PassRefPtr<SecurityOrigin> securityOrigin)
- : m_queue(queue)
- , m_tracker(tracker)
+LocalStorageDatabase::LocalStorageDatabase(Ref<WorkQueue>&& queue, Ref<LocalStorageDatabaseTracker>&& tracker, const SecurityOriginData& securityOrigin)
+ : m_queue(WTFMove(queue))
+ , m_tracker(WTFMove(tracker))
, m_securityOrigin(securityOrigin)
- , m_databasePath(m_tracker->databasePath(m_securityOrigin.get()))
+ , m_databasePath(m_tracker->databasePath(m_securityOrigin))
, m_failedToOpenDatabase(false)
, m_didImportItems(false)
, m_isClosed(false)
@@ -79,7 +80,7 @@ void LocalStorageDatabase::openDatabase(DatabaseOpeningStrategy openingStrategy)
}
if (m_database.isOpen())
- m_tracker->didOpenDatabaseWithOrigin(m_securityOrigin.get());
+ m_tracker->didOpenDatabaseWithOrigin(m_securityOrigin);
}
bool LocalStorageDatabase::tryToOpenDatabase(DatabaseOpeningStrategy openingStrategy)
@@ -171,7 +172,7 @@ void LocalStorageDatabase::importItems(StorageMap& storageMap)
return;
SQLiteStatement query(m_database, "SELECT key, value FROM ItemTable");
- if (query.prepare() != SQLResultOk) {
+ if (query.prepare() != SQLITE_OK) {
LOG_ERROR("Unable to select items from ItemTable for local storage");
return;
}
@@ -179,12 +180,15 @@ void LocalStorageDatabase::importItems(StorageMap& storageMap)
HashMap<String, String> items;
int result = query.step();
- while (result == SQLResultRow) {
- items.set(query.getColumnText(0), query.getColumnBlobAsString(1));
+ while (result == SQLITE_ROW) {
+ String key = query.getColumnText(0);
+ String value = query.getColumnBlobAsString(1);
+ if (!key.isNull() && !value.isNull())
+ items.set(key, value);
result = query.step();
}
- if (result != SQLResultDone) {
+ if (result != SQLITE_DONE) {
LOG_ERROR("Error reading items from ItemTable for local storage");
return;
}
@@ -226,7 +230,7 @@ void LocalStorageDatabase::close()
m_database.close();
if (isEmpty)
- m_tracker->deleteDatabaseWithOrigin(m_securityOrigin.get());
+ m_tracker->deleteDatabaseWithOrigin(m_securityOrigin);
}
void LocalStorageDatabase::itemDidChange(const String& key, const String& value)
@@ -240,8 +244,15 @@ void LocalStorageDatabase::scheduleDatabaseUpdate()
if (m_didScheduleDatabaseUpdate)
return;
+ if (!m_disableSuddenTerminationWhileWritingToLocalStorage)
+ m_disableSuddenTerminationWhileWritingToLocalStorage = std::make_unique<SuddenTerminationDisabler>();
+
m_didScheduleDatabaseUpdate = true;
- m_queue->dispatchAfter(databaseUpdateInterval, bind(&LocalStorageDatabase::updateDatabase, this));
+
+ RefPtr<LocalStorageDatabase> localStorageDatabase(this);
+ m_queue->dispatchAfter(databaseUpdateInterval, [localStorageDatabase] {
+ localStorageDatabase->updateDatabase();
+ });
}
void LocalStorageDatabase::updateDatabase()
@@ -256,6 +267,8 @@ void LocalStorageDatabase::updateDatabase()
if (m_changedItems.size() <= maximumItemsToUpdate) {
// There are few enough changed items that we can just always write all of them.
m_changedItems.swap(changedItems);
+ updateDatabaseWithChangedItems(changedItems);
+ m_disableSuddenTerminationWhileWritingToLocalStorage = nullptr;
} else {
for (int i = 0; i < maximumItemsToUpdate; ++i) {
auto it = m_changedItems.begin();
@@ -268,9 +281,8 @@ void LocalStorageDatabase::updateDatabase()
// Reschedule the update for the remaining items.
scheduleDatabaseUpdate();
+ updateDatabaseWithChangedItems(changedItems);
}
-
- updateDatabaseWithChangedItems(changedItems);
}
void LocalStorageDatabase::updateDatabaseWithChangedItems(const HashMap<String, String>& changedItems)
@@ -284,26 +296,26 @@ void LocalStorageDatabase::updateDatabaseWithChangedItems(const HashMap<String,
m_shouldClearItems = false;
SQLiteStatement clearStatement(m_database, "DELETE FROM ItemTable");
- if (clearStatement.prepare() != SQLResultOk) {
+ if (clearStatement.prepare() != SQLITE_OK) {
LOG_ERROR("Failed to prepare clear statement - cannot write to local storage database");
return;
}
int result = clearStatement.step();
- if (result != SQLResultDone) {
+ if (result != SQLITE_DONE) {
LOG_ERROR("Failed to clear all items in the local storage database - %i", result);
return;
}
}
SQLiteStatement insertStatement(m_database, "INSERT INTO ItemTable VALUES (?, ?)");
- if (insertStatement.prepare() != SQLResultOk) {
+ if (insertStatement.prepare() != SQLITE_OK) {
LOG_ERROR("Failed to prepare insert statement - cannot write to local storage database");
return;
}
SQLiteStatement deleteStatement(m_database, "DELETE FROM ItemTable WHERE key=?");
- if (deleteStatement.prepare() != SQLResultOk) {
+ if (deleteStatement.prepare() != SQLITE_OK) {
LOG_ERROR("Failed to prepare delete statement - cannot write to local storage database");
return;
}
@@ -322,7 +334,7 @@ void LocalStorageDatabase::updateDatabaseWithChangedItems(const HashMap<String,
statement.bindBlob(2, it->value);
int result = statement.step();
- if (result != SQLResultDone) {
+ if (result != SQLITE_DONE) {
LOG_ERROR("Failed to update item in the local storage database - %i", result);
break;
}
@@ -339,13 +351,13 @@ bool LocalStorageDatabase::databaseIsEmpty()
return false;
SQLiteStatement query(m_database, "SELECT COUNT(*) FROM ItemTable");
- if (query.prepare() != SQLResultOk) {
+ if (query.prepare() != SQLITE_OK) {
LOG_ERROR("Unable to count number of rows in ItemTable for local storage");
return false;
}
int result = query.step();
- if (result != SQLResultRow) {
+ if (result != SQLITE_ROW) {
LOG_ERROR("No results when counting number of rows in ItemTable for local storage");
return false;
}
diff --git a/Source/WebKit2/UIProcess/Storage/LocalStorageDatabase.h b/Source/WebKit2/UIProcess/Storage/LocalStorageDatabase.h
index 1acd6b253..9992031f4 100644
--- a/Source/WebKit2/UIProcess/Storage/LocalStorageDatabase.h
+++ b/Source/WebKit2/UIProcess/Storage/LocalStorageDatabase.h
@@ -23,20 +23,20 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef LocalStorageDatabase_h
-#define LocalStorageDatabase_h
+#pragma once
#include <WebCore/SQLiteDatabase.h>
+#include <WebCore/SecurityOriginData.h>
#include <wtf/Forward.h>
#include <wtf/HashMap.h>
#include <wtf/RefPtr.h>
#include <wtf/ThreadSafeRefCounted.h>
-
-class WorkQueue;
+#include <wtf/WorkQueue.h>
namespace WebCore {
class SecurityOrigin;
class StorageMap;
+class SuddenTerminationDisabler;
}
namespace WebKit {
@@ -45,7 +45,7 @@ class LocalStorageDatabaseTracker;
class LocalStorageDatabase : public ThreadSafeRefCounted<LocalStorageDatabase> {
public:
- static PassRefPtr<LocalStorageDatabase> create(PassRefPtr<WorkQueue>, PassRefPtr<LocalStorageDatabaseTracker>, PassRefPtr<WebCore::SecurityOrigin>);
+ static Ref<LocalStorageDatabase> create(Ref<WorkQueue>&&, Ref<LocalStorageDatabaseTracker>&&, const WebCore::SecurityOriginData&);
~LocalStorageDatabase();
// Will block until the import is complete.
@@ -59,7 +59,7 @@ public:
void close();
private:
- LocalStorageDatabase(PassRefPtr<WorkQueue>, PassRefPtr<LocalStorageDatabaseTracker>, PassRefPtr<WebCore::SecurityOrigin>);
+ LocalStorageDatabase(Ref<WorkQueue>&&, Ref<LocalStorageDatabaseTracker>&&, const WebCore::SecurityOriginData&);
enum DatabaseOpeningStrategy {
CreateIfNonExistent,
@@ -78,9 +78,9 @@ private:
bool databaseIsEmpty();
- RefPtr<WorkQueue> m_queue;
- RefPtr<LocalStorageDatabaseTracker> m_tracker;
- RefPtr<WebCore::SecurityOrigin> m_securityOrigin;
+ Ref<WorkQueue> m_queue;
+ Ref<LocalStorageDatabaseTracker> m_tracker;
+ WebCore::SecurityOriginData m_securityOrigin;
String m_databasePath;
WebCore::SQLiteDatabase m_database;
@@ -91,9 +91,9 @@ private:
bool m_didScheduleDatabaseUpdate;
bool m_shouldClearItems;
HashMap<String, String> m_changedItems;
+
+ std::unique_ptr<WebCore::SuddenTerminationDisabler> m_disableSuddenTerminationWhileWritingToLocalStorage;
};
} // namespace WebKit
-
-#endif // LocalStorageDatabase_h
diff --git a/Source/WebKit2/UIProcess/Storage/LocalStorageDatabaseTracker.cpp b/Source/WebKit2/UIProcess/Storage/LocalStorageDatabaseTracker.cpp
index d0f771e7c..3e86b05ca 100644
--- a/Source/WebKit2/UIProcess/Storage/LocalStorageDatabaseTracker.cpp
+++ b/Source/WebKit2/UIProcess/Storage/LocalStorageDatabaseTracker.cpp
@@ -26,53 +26,56 @@
#include "config.h"
#include "LocalStorageDatabaseTracker.h"
-#include "WorkQueue.h"
#include <WebCore/FileSystem.h>
+#include <WebCore/SQLiteFileSystem.h>
#include <WebCore/SQLiteStatement.h>
#include <WebCore/SecurityOrigin.h>
+#include <WebCore/SecurityOriginData.h>
+#include <WebCore/TextEncoding.h>
+#include <wtf/MainThread.h>
+#include <wtf/WorkQueue.h>
#include <wtf/text/CString.h>
using namespace WebCore;
namespace WebKit {
-PassRefPtr<LocalStorageDatabaseTracker> LocalStorageDatabaseTracker::create(PassRefPtr<WorkQueue> queue)
+Ref<LocalStorageDatabaseTracker> LocalStorageDatabaseTracker::create(Ref<WorkQueue>&& queue, const String& localStorageDirectory)
{
- return adoptRef(new LocalStorageDatabaseTracker(queue));
+ return adoptRef(*new LocalStorageDatabaseTracker(WTFMove(queue), localStorageDirectory));
}
-LocalStorageDatabaseTracker::LocalStorageDatabaseTracker(PassRefPtr<WorkQueue> queue)
- : m_queue(queue)
+LocalStorageDatabaseTracker::LocalStorageDatabaseTracker(Ref<WorkQueue>&& queue, const String& localStorageDirectory)
+ : m_queue(WTFMove(queue))
+ , m_localStorageDirectory(localStorageDirectory.isolatedCopy())
{
+ ASSERT(!m_localStorageDirectory.isEmpty());
+
+ // Make sure the encoding is initialized before we start dispatching things to the queue.
+ UTF8Encoding();
+
+ m_queue->dispatch([protectedThis = makeRef(*this)]() mutable {
+ protectedThis->importOriginIdentifiers();
+ });
}
LocalStorageDatabaseTracker::~LocalStorageDatabaseTracker()
{
}
-void LocalStorageDatabaseTracker::setLocalStorageDirectory(const String& localStorageDirectory)
+String LocalStorageDatabaseTracker::databasePath(const SecurityOriginData& securityOrigin) const
{
- // FIXME: We should come up with a better idiom for safely copying strings across threads.
- RefPtr<StringImpl> copiedLocalStorageDirectory;
- if (localStorageDirectory.impl())
- copiedLocalStorageDirectory = localStorageDirectory.impl()->isolatedCopy();
-
- m_queue->dispatch(bind(&LocalStorageDatabaseTracker::setLocalStorageDirectoryInternal, this, copiedLocalStorageDirectory.release()));
+ return databasePath(securityOrigin.databaseIdentifier() + ".localstorage");
}
-String LocalStorageDatabaseTracker::databasePath(SecurityOrigin* securityOrigin) const
+void LocalStorageDatabaseTracker::didOpenDatabaseWithOrigin(const SecurityOriginData& securityOrigin)
{
- return databasePath(securityOrigin->databaseIdentifier() + ".localstorage");
+ addDatabaseWithOriginIdentifier(securityOrigin.databaseIdentifier(), databasePath(securityOrigin));
}
-void LocalStorageDatabaseTracker::didOpenDatabaseWithOrigin(SecurityOrigin* securityOrigin)
+void LocalStorageDatabaseTracker::deleteDatabaseWithOrigin(const SecurityOriginData& securityOrigin)
{
- addDatabaseWithOriginIdentifier(securityOrigin->databaseIdentifier(), databasePath(securityOrigin));
-}
-
-void LocalStorageDatabaseTracker::deleteDatabaseWithOrigin(SecurityOrigin* securityOrigin)
-{
- removeDatabaseWithOriginIdentifier(securityOrigin->databaseIdentifier());
+ removeDatabaseWithOriginIdentifier(securityOrigin.databaseIdentifier());
}
void LocalStorageDatabaseTracker::deleteAllDatabases()
@@ -84,19 +87,19 @@ void LocalStorageDatabaseTracker::deleteAllDatabases()
return;
SQLiteStatement statement(m_database, "SELECT origin, path FROM Origins");
- if (statement.prepare() != SQLResultOk) {
+ if (statement.prepare() != SQLITE_OK) {
LOG_ERROR("Failed to prepare statement.");
return;
}
int result;
- while ((result = statement.step()) == SQLResultRow) {
+ while ((result = statement.step()) == SQLITE_ROW) {
deleteFile(statement.getColumnText(1));
// FIXME: Call out to the client.
}
- if (result != SQLResultDone)
+ if (result != SQLITE_DONE)
LOG_ERROR("Failed to read in all origins from the database.");
if (m_database.isOpen())
@@ -110,7 +113,7 @@ void LocalStorageDatabaseTracker::deleteAllDatabases()
return;
SQLiteStatement deleteStatement(m_database, "DELETE FROM Origins");
- if (deleteStatement.prepare() != SQLResultOk) {
+ if (deleteStatement.prepare() != SQLITE_OK) {
LOG_ERROR("Unable to prepare deletion of all origins");
return;
}
@@ -123,35 +126,97 @@ void LocalStorageDatabaseTracker::deleteAllDatabases()
deleteEmptyDirectory(m_localStorageDirectory);
}
-Vector<RefPtr<WebCore::SecurityOrigin>> LocalStorageDatabaseTracker::origins() const
+static std::optional<time_t> fileCreationTime(const String& filePath)
+{
+ time_t time;
+ return getFileCreationTime(filePath, time) ? time : std::optional<time_t>(std::nullopt);
+}
+
+static std::optional<time_t> fileModificationTime(const String& filePath)
+{
+ time_t time;
+ if (!getFileModificationTime(filePath, time))
+ return std::nullopt;
+
+ return time;
+}
+
+Vector<SecurityOriginData> LocalStorageDatabaseTracker::deleteDatabasesModifiedSince(std::chrono::system_clock::time_point time)
+{
+ ASSERT(!isMainThread());
+ importOriginIdentifiers();
+ Vector<String> originIdentifiersToDelete;
+
+ for (const String& origin : m_origins) {
+ String filePath = pathForDatabaseWithOriginIdentifier(origin);
+
+ auto modificationTime = fileModificationTime(filePath);
+ if (!modificationTime)
+ continue;
+
+ if (modificationTime.value() >= std::chrono::system_clock::to_time_t(time))
+ originIdentifiersToDelete.append(origin);
+ }
+
+ Vector<SecurityOriginData> deletedDatabaseOrigins;
+ deletedDatabaseOrigins.reserveInitialCapacity(originIdentifiersToDelete.size());
+
+ for (const auto& originIdentifier : originIdentifiersToDelete) {
+ removeDatabaseWithOriginIdentifier(originIdentifier);
+
+ if (auto origin = SecurityOriginData::fromDatabaseIdentifier(originIdentifier))
+ deletedDatabaseOrigins.uncheckedAppend(*origin);
+ else
+ ASSERT_NOT_REACHED();
+ }
+
+ return deletedDatabaseOrigins;
+}
+
+Vector<SecurityOriginData> LocalStorageDatabaseTracker::origins() const
{
- Vector<RefPtr<SecurityOrigin>> origins;
+ Vector<SecurityOriginData> origins;
origins.reserveInitialCapacity(m_origins.size());
- for (HashSet<String>::const_iterator it = m_origins.begin(), end = m_origins.end(); it != end; ++it)
- origins.uncheckedAppend(SecurityOrigin::createFromDatabaseIdentifier(*it));
+ for (const String& originIdentifier : m_origins) {
+ if (auto origin = SecurityOriginData::fromDatabaseIdentifier(originIdentifier))
+ origins.uncheckedAppend(*origin);
+ else
+ ASSERT_NOT_REACHED();
+ }
return origins;
}
-void LocalStorageDatabaseTracker::setLocalStorageDirectoryInternal(StringImpl* localStorageDirectory)
+Vector<LocalStorageDatabaseTracker::OriginDetails> LocalStorageDatabaseTracker::originDetails()
{
- if (m_database.isOpen())
- m_database.close();
+ Vector<OriginDetails> result;
+ result.reserveInitialCapacity(m_origins.size());
- m_localStorageDirectory = localStorageDirectory;
- m_origins.clear();
+ for (const String& origin : m_origins) {
+ String filePath = pathForDatabaseWithOriginIdentifier(origin);
+
+ OriginDetails details;
+ details.originIdentifier = origin.isolatedCopy();
+ details.creationTime = fileCreationTime(filePath);
+ details.modificationTime = fileModificationTime(filePath);
+ result.uncheckedAppend(details);
+ }
- m_queue->dispatch(bind(&LocalStorageDatabaseTracker::importOriginIdentifiers, this));
+ return result;
}
String LocalStorageDatabaseTracker::databasePath(const String& filename) const
{
if (!makeAllDirectories(m_localStorageDirectory)) {
- LOG_ERROR("Unabled to create LocalStorage database path %s", m_localStorageDirectory.utf8().data());
+ LOG_ERROR("Unable to create LocalStorage database path %s", m_localStorageDirectory.utf8().data());
return String();
}
+#if PLATFORM(IOS)
+ platformMaybeExcludeFromBackup();
+#endif
+
return pathByAppendingComponent(m_localStorageDirectory, filename);
}
@@ -192,17 +257,17 @@ void LocalStorageDatabaseTracker::importOriginIdentifiers()
if (m_database.isOpen()) {
SQLiteStatement statement(m_database, "SELECT origin FROM Origins");
- if (statement.prepare() != SQLResultOk) {
+ if (statement.prepare() != SQLITE_OK) {
LOG_ERROR("Failed to prepare statement.");
return;
}
int result;
- while ((result = statement.step()) == SQLResultRow)
+ while ((result = statement.step()) == SQLITE_ROW)
m_origins.add(statement.getColumnText(0));
- if (result != SQLResultDone) {
+ if (result != SQLITE_DONE) {
LOG_ERROR("Failed to read in all origins from the database.");
return;
}
@@ -250,7 +315,7 @@ void LocalStorageDatabaseTracker::addDatabaseWithOriginIdentifier(const String&
return;
SQLiteStatement statement(m_database, "INSERT INTO Origins VALUES (?, ?)");
- if (statement.prepare() != SQLResultOk) {
+ if (statement.prepare() != SQLITE_OK) {
LOG_ERROR("Unable to establish origin '%s' in the tracker", originIdentifier.utf8().data());
return;
}
@@ -258,7 +323,7 @@ void LocalStorageDatabaseTracker::addDatabaseWithOriginIdentifier(const String&
statement.bindText(1, originIdentifier);
statement.bindText(2, databasePath);
- if (statement.step() != SQLResultDone)
+ if (statement.step() != SQLITE_DONE)
LOG_ERROR("Unable to establish origin '%s' in the tracker", originIdentifier.utf8().data());
m_origins.add(originIdentifier);
@@ -277,7 +342,7 @@ void LocalStorageDatabaseTracker::removeDatabaseWithOriginIdentifier(const Strin
return;
SQLiteStatement deleteStatement(m_database, "DELETE FROM Origins where origin=?");
- if (deleteStatement.prepare() != SQLResultOk) {
+ if (deleteStatement.prepare() != SQLITE_OK) {
LOG_ERROR("Unable to prepare deletion of origin '%s'", originIdentifier.ascii().data());
return;
}
@@ -287,13 +352,13 @@ void LocalStorageDatabaseTracker::removeDatabaseWithOriginIdentifier(const Strin
return;
}
- deleteFile(path);
+ SQLiteFileSystem::deleteDatabaseFile(path);
m_origins.remove(originIdentifier);
if (m_origins.isEmpty()) {
- // There are no origins left, go ahead and delete the tracker database.
+ // There are no origins left; delete the tracker database.
m_database.close();
- deleteFile(trackerDatabasePath());
+ SQLiteFileSystem::deleteDatabaseFile(trackerDatabasePath());
deleteEmptyDirectory(m_localStorageDirectory);
}
@@ -306,7 +371,7 @@ String LocalStorageDatabaseTracker::pathForDatabaseWithOriginIdentifier(const St
return String();
SQLiteStatement pathStatement(m_database, "SELECT path FROM Origins WHERE origin=?");
- if (pathStatement.prepare() != SQLResultOk) {
+ if (pathStatement.prepare() != SQLITE_OK) {
LOG_ERROR("Unable to prepare selection of path for origin '%s'", originIdentifier.utf8().data());
return String();
}
@@ -314,7 +379,7 @@ String LocalStorageDatabaseTracker::pathForDatabaseWithOriginIdentifier(const St
pathStatement.bindText(1, originIdentifier);
int result = pathStatement.step();
- if (result != SQLResultRow)
+ if (result != SQLITE_ROW)
return String();
return pathStatement.getColumnText(0);
diff --git a/Source/WebKit2/UIProcess/Storage/LocalStorageDatabaseTracker.h b/Source/WebKit2/UIProcess/Storage/LocalStorageDatabaseTracker.h
index e16428907..7ceb1916d 100644
--- a/Source/WebKit2/UIProcess/Storage/LocalStorageDatabaseTracker.h
+++ b/Source/WebKit2/UIProcess/Storage/LocalStorageDatabaseTracker.h
@@ -23,43 +23,51 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef LocalStorageDatabaseTracker_h
-#define LocalStorageDatabaseTracker_h
+#pragma once
#include <WebCore/SQLiteDatabase.h>
#include <wtf/HashSet.h>
-#include <wtf/PassRefPtr.h>
+#include <wtf/Optional.h>
#include <wtf/RefPtr.h>
#include <wtf/ThreadSafeRefCounted.h>
+#include <wtf/WorkQueue.h>
#include <wtf/text/StringHash.h>
#include <wtf/text/WTFString.h>
namespace WebCore {
class SecurityOrigin;
+struct SecurityOriginData;
}
-class WorkQueue;
-
namespace WebKit {
+struct LocalStorageDetails;
+
class LocalStorageDatabaseTracker : public ThreadSafeRefCounted<LocalStorageDatabaseTracker> {
public:
- static PassRefPtr<LocalStorageDatabaseTracker> create(PassRefPtr<WorkQueue>);
+ static Ref<LocalStorageDatabaseTracker> create(Ref<WorkQueue>&&, const String& localStorageDirectory);
~LocalStorageDatabaseTracker();
- void setLocalStorageDirectory(const String&);
- String databasePath(WebCore::SecurityOrigin*) const;
+ String databasePath(const WebCore::SecurityOriginData&) const;
- void didOpenDatabaseWithOrigin(WebCore::SecurityOrigin*);
- void deleteDatabaseWithOrigin(WebCore::SecurityOrigin*);
+ void didOpenDatabaseWithOrigin(const WebCore::SecurityOriginData&);
+ void deleteDatabaseWithOrigin(const WebCore::SecurityOriginData&);
void deleteAllDatabases();
- Vector<RefPtr<WebCore::SecurityOrigin>> origins() const;
+ // Returns a vector of the origins whose databases have been deleted.
+ Vector<WebCore::SecurityOriginData> deleteDatabasesModifiedSince(std::chrono::system_clock::time_point);
-private:
- explicit LocalStorageDatabaseTracker(PassRefPtr<WorkQueue>);
+ Vector<WebCore::SecurityOriginData> origins() const;
- void setLocalStorageDirectoryInternal(StringImpl*);
+ struct OriginDetails {
+ String originIdentifier;
+ std::optional<time_t> creationTime;
+ std::optional<time_t> modificationTime;
+ };
+ Vector<OriginDetails> originDetails();
+
+private:
+ LocalStorageDatabaseTracker(Ref<WorkQueue>&&, const String& localStorageDirectory);
String databasePath(const String& filename) const;
String trackerDatabasePath() const;
@@ -82,8 +90,12 @@ private:
WebCore::SQLiteDatabase m_database;
HashSet<String> m_origins;
+
+#if PLATFORM(IOS)
+ void platformMaybeExcludeFromBackup() const;
+
+ mutable bool m_hasExcludedFromBackup { false };
+#endif
};
} // namespace WebKit
-
-#endif // LocalStorageDatabaseTracker_h
diff --git a/Source/WebKit2/UIProcess/Storage/StorageManager.cpp b/Source/WebKit2/UIProcess/Storage/StorageManager.cpp
index c08acc4ad..5803e2cb3 100644
--- a/Source/WebKit2/UIProcess/Storage/StorageManager.cpp
+++ b/Source/WebKit2/UIProcess/Storage/StorageManager.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,14 +28,16 @@
#include "LocalStorageDatabase.h"
#include "LocalStorageDatabaseTracker.h"
-#include "SecurityOriginData.h"
#include "StorageAreaMapMessages.h"
#include "StorageManagerMessages.h"
#include "WebProcessProxy.h"
-#include "WorkQueue.h"
+#include <WebCore/SecurityOriginData.h>
#include <WebCore/SecurityOriginHash.h>
#include <WebCore/StorageMap.h>
#include <WebCore/TextEncoding.h>
+#include <memory>
+#include <wtf/WorkQueue.h>
+#include <wtf/threads/BinarySemaphore.h>
using namespace WebCore;
@@ -43,36 +45,38 @@ namespace WebKit {
class StorageManager::StorageArea : public ThreadSafeRefCounted<StorageManager::StorageArea> {
public:
- static PassRefPtr<StorageArea> create(LocalStorageNamespace*, PassRefPtr<SecurityOrigin>, unsigned quotaInBytes);
+ static Ref<StorageArea> create(LocalStorageNamespace*, const SecurityOriginData&, unsigned quotaInBytes);
~StorageArea();
- SecurityOrigin* securityOrigin() const { return m_securityOrigin.get(); }
+ const WebCore::SecurityOriginData& securityOrigin() const { return m_securityOrigin; }
- void addListener(IPC::Connection*, uint64_t storageMapID);
- void removeListener(IPC::Connection*, uint64_t storageMapID);
+ void addListener(IPC::Connection&, uint64_t storageMapID);
+ void removeListener(IPC::Connection&, uint64_t storageMapID);
- PassRefPtr<StorageArea> clone() const;
+ Ref<StorageArea> clone() const;
void setItem(IPC::Connection* sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& value, const String& urlString, bool& quotaException);
void removeItem(IPC::Connection* sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& urlString);
void clear(IPC::Connection* sourceConnection, uint64_t sourceStorageAreaID, const String& urlString);
- const HashMap<String, String>& items();
+ const HashMap<String, String>& items() const;
void clear();
+ bool isSessionStorage() const { return !m_localStorageNamespace; }
+
private:
- explicit StorageArea(LocalStorageNamespace*, PassRefPtr<SecurityOrigin>, unsigned quotaInBytes);
+ explicit StorageArea(LocalStorageNamespace*, const SecurityOriginData&, unsigned quotaInBytes);
- void openDatabaseAndImportItemsIfNeeded();
+ void openDatabaseAndImportItemsIfNeeded() const;
void dispatchEvents(IPC::Connection* sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& oldValue, const String& newValue, const String& urlString) const;
// Will be null if the storage area belongs to a session storage namespace.
LocalStorageNamespace* m_localStorageNamespace;
- RefPtr<LocalStorageDatabase> m_localStorageDatabase;
- bool m_didImportItemsFromDatabase;
+ mutable RefPtr<LocalStorageDatabase> m_localStorageDatabase;
+ mutable bool m_didImportItemsFromDatabase { false };
- RefPtr<SecurityOrigin> m_securityOrigin;
+ SecurityOriginData m_securityOrigin;
unsigned m_quotaInBytes;
RefPtr<StorageMap> m_storageMap;
@@ -81,15 +85,15 @@ private:
class StorageManager::LocalStorageNamespace : public ThreadSafeRefCounted<LocalStorageNamespace> {
public:
- static PassRefPtr<LocalStorageNamespace> create(StorageManager*, uint64_t storageManagerID);
+ static Ref<LocalStorageNamespace> create(StorageManager*, uint64_t storageManagerID);
~LocalStorageNamespace();
StorageManager* storageManager() const { return m_storageManager; }
- PassRefPtr<StorageArea> getOrCreateStorageArea(PassRefPtr<SecurityOrigin>);
+ Ref<StorageArea> getOrCreateStorageArea(SecurityOriginData&&);
void didDestroyStorageArea(StorageArea*);
- void clearStorageAreasMatchingOrigin(SecurityOrigin*);
+ void clearStorageAreasMatchingOrigin(const SecurityOriginData&);
void clearAllStorageAreas();
private:
@@ -100,17 +104,70 @@ private:
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<RefPtr<SecurityOrigin>, StorageArea*> m_storageAreaMap;
+ HashMap<SecurityOriginData, StorageArea*> m_storageAreaMap;
+};
+
+class StorageManager::TransientLocalStorageNamespace : public ThreadSafeRefCounted<TransientLocalStorageNamespace> {
+public:
+ static Ref<TransientLocalStorageNamespace> create()
+ {
+ return adoptRef(*new TransientLocalStorageNamespace());
+ }
+
+ ~TransientLocalStorageNamespace()
+ {
+ }
+
+ Ref<StorageArea> getOrCreateStorageArea(SecurityOriginData&& securityOrigin)
+ {
+ return *m_storageAreaMap.ensure(securityOrigin, [this, securityOrigin]() mutable {
+ return StorageArea::create(nullptr, WTFMove(securityOrigin), m_quotaInBytes);
+ }).iterator->value.copyRef();
+ }
+
+ Vector<SecurityOriginData> origins() const
+ {
+ Vector<SecurityOriginData> origins;
+
+ for (const auto& storageArea : m_storageAreaMap.values()) {
+ if (!storageArea->items().isEmpty())
+ origins.append(storageArea->securityOrigin());
+ }
+
+ return origins;
+ }
+
+ void clearStorageAreasMatchingOrigin(const SecurityOriginData& securityOrigin)
+ {
+ for (auto& storageArea : m_storageAreaMap.values()) {
+ if (storageArea->securityOrigin() == securityOrigin)
+ storageArea->clear();
+ }
+ }
+
+ void clearAllStorageAreas()
+ {
+ for (auto& storageArea : m_storageAreaMap.values())
+ storageArea->clear();
+ }
+
+private:
+ explicit TransientLocalStorageNamespace()
+ {
+ }
+
+ const unsigned m_quotaInBytes = 5 * 1024 * 1024;
+
+ HashMap<SecurityOriginData, RefPtr<StorageArea>> m_storageAreaMap;
};
-PassRefPtr<StorageManager::StorageArea> StorageManager::StorageArea::create(LocalStorageNamespace* localStorageNamespace, PassRefPtr<SecurityOrigin> securityOrigin, unsigned quotaInBytes)
+auto StorageManager::StorageArea::create(LocalStorageNamespace* localStorageNamespace, const SecurityOriginData& securityOrigin, unsigned quotaInBytes) -> Ref<StorageManager::StorageArea>
{
- return adoptRef(new StorageArea(localStorageNamespace, securityOrigin, quotaInBytes));
+ return adoptRef(*new StorageArea(localStorageNamespace, securityOrigin, quotaInBytes));
}
-StorageManager::StorageArea::StorageArea(LocalStorageNamespace* localStorageNamespace, PassRefPtr<SecurityOrigin> securityOrigin, unsigned quotaInBytes)
+StorageManager::StorageArea::StorageArea(LocalStorageNamespace* localStorageNamespace, const SecurityOriginData& securityOrigin, unsigned quotaInBytes)
: m_localStorageNamespace(localStorageNamespace)
- , m_didImportItemsFromDatabase(false)
, m_securityOrigin(securityOrigin)
, m_quotaInBytes(quotaInBytes)
, m_storageMap(StorageMap::create(m_quotaInBytes))
@@ -128,26 +185,26 @@ StorageManager::StorageArea::~StorageArea()
m_localStorageNamespace->didDestroyStorageArea(this);
}
-void StorageManager::StorageArea::addListener(IPC::Connection* connection, uint64_t storageMapID)
+void StorageManager::StorageArea::addListener(IPC::Connection& connection, uint64_t storageMapID)
{
- ASSERT(!m_eventListeners.contains(std::make_pair(connection, storageMapID)));
- m_eventListeners.add(std::make_pair(connection, storageMapID));
+ ASSERT(!m_eventListeners.contains(std::make_pair(&connection, storageMapID)));
+ m_eventListeners.add(std::make_pair(&connection, storageMapID));
}
-void StorageManager::StorageArea::removeListener(IPC::Connection* connection, uint64_t storageMapID)
+void StorageManager::StorageArea::removeListener(IPC::Connection& connection, uint64_t storageMapID)
{
- ASSERT(m_eventListeners.contains(std::make_pair(connection, storageMapID)));
- m_eventListeners.remove(std::make_pair(connection, storageMapID));
+ ASSERT(isSessionStorage() || m_eventListeners.contains(std::make_pair(&connection, storageMapID)));
+ m_eventListeners.remove(std::make_pair(&connection, storageMapID));
}
-PassRefPtr<StorageManager::StorageArea> StorageManager::StorageArea::clone() const
+Ref<StorageManager::StorageArea> StorageManager::StorageArea::clone() const
{
ASSERT(!m_localStorageNamespace);
- RefPtr<StorageArea> storageArea = StorageArea::create(0, m_securityOrigin, m_quotaInBytes);
+ auto storageArea = StorageArea::create(nullptr, m_securityOrigin, m_quotaInBytes);
storageArea->m_storageMap = m_storageMap;
- return storageArea.release();
+ return storageArea;
}
void StorageManager::StorageArea::setItem(IPC::Connection* sourceConnection, uint64_t sourceStorageAreaID, const String& key, const String& value, const String& urlString, bool& quotaException)
@@ -156,9 +213,9 @@ void StorageManager::StorageArea::setItem(IPC::Connection* sourceConnection, uin
String oldValue;
- RefPtr<StorageMap> newStorageMap = m_storageMap->setItem(key, value, oldValue, quotaException);
+ auto newStorageMap = m_storageMap->setItem(key, value, oldValue, quotaException);
if (newStorageMap)
- m_storageMap = newStorageMap.release();
+ m_storageMap = WTFMove(newStorageMap);
if (quotaException)
return;
@@ -174,9 +231,9 @@ void StorageManager::StorageArea::removeItem(IPC::Connection* sourceConnection,
openDatabaseAndImportItemsIfNeeded();
String oldValue;
- RefPtr<StorageMap> newStorageMap = m_storageMap->removeItem(key, oldValue);
+ auto newStorageMap = m_storageMap->removeItem(key, oldValue);
if (newStorageMap)
- m_storageMap = newStorageMap.release();
+ m_storageMap = WTFMove(newStorageMap);
if (oldValue.isNull())
return;
@@ -202,7 +259,7 @@ void StorageManager::StorageArea::clear(IPC::Connection* sourceConnection, uint6
dispatchEvents(sourceConnection, sourceStorageAreaID, String(), String(), String(), urlString);
}
-const HashMap<String, String>& StorageManager::StorageArea::items()
+const HashMap<String, String>& StorageManager::StorageArea::items() const
{
openDatabaseAndImportItemsIfNeeded();
@@ -222,14 +279,14 @@ void StorageManager::StorageArea::clear()
it->first->send(Messages::StorageAreaMap::ClearCache(), it->second);
}
-void StorageManager::StorageArea::openDatabaseAndImportItemsIfNeeded()
+void StorageManager::StorageArea::openDatabaseAndImportItemsIfNeeded() const
{
if (!m_localStorageNamespace)
return;
// We open the database here even if we've already imported our items to ensure that the database is open if we need to write to it.
if (!m_localStorageDatabase)
- m_localStorageDatabase = LocalStorageDatabase::create(m_localStorageNamespace->storageManager()->m_queue, m_localStorageNamespace->storageManager()->m_localStorageDatabaseTracker, m_securityOrigin.get());
+ m_localStorageDatabase = LocalStorageDatabase::create(m_localStorageNamespace->storageManager()->m_queue.copyRef(), m_localStorageNamespace->storageManager()->m_localStorageDatabaseTracker.copyRef(), m_securityOrigin);
if (m_didImportItemsFromDatabase)
return;
@@ -247,9 +304,9 @@ void StorageManager::StorageArea::dispatchEvents(IPC::Connection* sourceConnecti
}
}
-PassRefPtr<StorageManager::LocalStorageNamespace> StorageManager::LocalStorageNamespace::create(StorageManager* storageManager, uint64_t storageNamespaceID)
+Ref<StorageManager::LocalStorageNamespace> StorageManager::LocalStorageNamespace::create(StorageManager* storageManager, uint64_t storageNamespaceID)
{
- return adoptRef(new LocalStorageNamespace(storageManager, storageNamespaceID));
+ return adoptRef(*new LocalStorageNamespace(storageManager, storageNamespaceID));
}
// FIXME: The quota value is copied from GroupSettings.cpp.
@@ -266,16 +323,16 @@ StorageManager::LocalStorageNamespace::~LocalStorageNamespace()
ASSERT(m_storageAreaMap.isEmpty());
}
-PassRefPtr<StorageManager::StorageArea> StorageManager::LocalStorageNamespace::getOrCreateStorageArea(PassRefPtr<SecurityOrigin> securityOrigin)
+auto StorageManager::LocalStorageNamespace::getOrCreateStorageArea(SecurityOriginData&& securityOrigin) -> Ref<StorageArea>
{
- auto result = m_storageAreaMap.add(securityOrigin, nullptr);
- if (!result.isNewEntry)
- return result.iterator->value;
+ auto& slot = m_storageAreaMap.add(securityOrigin, nullptr).iterator->value;
+ if (slot)
+ return *slot;
- RefPtr<StorageArea> storageArea = StorageArea::create(this, result.iterator->key, m_quotaInBytes);
- result.iterator->value = storageArea.get();
+ auto storageArea = StorageArea::create(this, WTFMove(securityOrigin), m_quotaInBytes);
+ slot = &storageArea.get();
- return storageArea.release();
+ return storageArea;
}
void StorageManager::LocalStorageNamespace::didDestroyStorageArea(StorageArea* storageArea)
@@ -290,23 +347,23 @@ void StorageManager::LocalStorageNamespace::didDestroyStorageArea(StorageArea* s
m_storageManager->m_localStorageNamespaces.remove(m_storageNamespaceID);
}
-void StorageManager::LocalStorageNamespace::clearStorageAreasMatchingOrigin(SecurityOrigin* securityOrigin)
+void StorageManager::LocalStorageNamespace::clearStorageAreasMatchingOrigin(const SecurityOriginData& securityOrigin)
{
- for (auto it = m_storageAreaMap.begin(), end = m_storageAreaMap.end(); it != end; ++it) {
- if (it->key->equal(securityOrigin))
- it->value->clear();
+ for (const auto& originAndStorageArea : m_storageAreaMap) {
+ if (originAndStorageArea.key == securityOrigin)
+ originAndStorageArea.value->clear();
}
}
void StorageManager::LocalStorageNamespace::clearAllStorageAreas()
{
- for (auto it = m_storageAreaMap.begin(), end = m_storageAreaMap.end(); it != end; ++it)
- it->value->clear();
+ for (auto* storageArea : m_storageAreaMap.values())
+ storageArea->clear();
}
class StorageManager::SessionStorageNamespace : public ThreadSafeRefCounted<SessionStorageNamespace> {
public:
- static PassRefPtr<SessionStorageNamespace> create(IPC::Connection* allowedConnection, unsigned quotaInBytes);
+ static Ref<SessionStorageNamespace> create(unsigned quotaInBytes);
~SessionStorageNamespace();
bool isEmpty() const { return m_storageAreaMap.isEmpty(); }
@@ -314,27 +371,52 @@ public:
IPC::Connection* allowedConnection() const { return m_allowedConnection.get(); }
void setAllowedConnection(IPC::Connection*);
- PassRefPtr<StorageArea> getOrCreateStorageArea(PassRefPtr<SecurityOrigin>);
+ Ref<StorageArea> getOrCreateStorageArea(SecurityOriginData&&);
void cloneTo(SessionStorageNamespace& newSessionStorageNamespace);
+ Vector<SecurityOriginData> origins() const
+ {
+ Vector<SecurityOriginData> origins;
+
+ for (const auto& storageArea : m_storageAreaMap.values()) {
+ if (!storageArea->items().isEmpty())
+ origins.append(storageArea->securityOrigin());
+ }
+
+ return origins;
+ }
+
+ void clearStorageAreasMatchingOrigin(const SecurityOriginData& securityOrigin)
+ {
+ for (auto& storageArea : m_storageAreaMap.values()) {
+ if (storageArea->securityOrigin() == securityOrigin)
+ storageArea->clear();
+ }
+ }
+
+ void clearAllStorageAreas()
+ {
+ for (auto& storageArea : m_storageAreaMap.values())
+ storageArea->clear();
+ }
+
private:
- SessionStorageNamespace(IPC::Connection* allowedConnection, unsigned quotaInBytes);
+ explicit SessionStorageNamespace(unsigned quotaInBytes);
RefPtr<IPC::Connection> m_allowedConnection;
unsigned m_quotaInBytes;
- HashMap<RefPtr<SecurityOrigin>, RefPtr<StorageArea>> m_storageAreaMap;
+ HashMap<SecurityOriginData, RefPtr<StorageArea>> m_storageAreaMap;
};
-PassRefPtr<StorageManager::SessionStorageNamespace> StorageManager::SessionStorageNamespace::create(IPC::Connection* allowedConnection, unsigned quotaInBytes)
+Ref<StorageManager::SessionStorageNamespace> StorageManager::SessionStorageNamespace::create(unsigned quotaInBytes)
{
- return adoptRef(new SessionStorageNamespace(allowedConnection, quotaInBytes));
+ return adoptRef(*new SessionStorageNamespace(quotaInBytes));
}
-StorageManager::SessionStorageNamespace::SessionStorageNamespace(IPC::Connection* allowedConnection, unsigned quotaInBytes)
- : m_allowedConnection(allowedConnection)
- , m_quotaInBytes(quotaInBytes)
+StorageManager::SessionStorageNamespace::SessionStorageNamespace(unsigned quotaInBytes)
+ : m_quotaInBytes(quotaInBytes)
{
}
@@ -349,31 +431,29 @@ void StorageManager::SessionStorageNamespace::setAllowedConnection(IPC::Connecti
m_allowedConnection = allowedConnection;
}
-PassRefPtr<StorageManager::StorageArea> StorageManager::SessionStorageNamespace::getOrCreateStorageArea(PassRefPtr<SecurityOrigin> securityOrigin)
+auto StorageManager::SessionStorageNamespace::getOrCreateStorageArea(SecurityOriginData&& securityOrigin) -> Ref<StorageArea>
{
- auto result = m_storageAreaMap.add(securityOrigin, nullptr);
- if (result.isNewEntry)
- result.iterator->value = StorageArea::create(0, result.iterator->key, m_quotaInBytes);
-
- return result.iterator->value;
+ return *m_storageAreaMap.ensure(securityOrigin, [this, securityOrigin]() mutable {
+ return StorageArea::create(nullptr, WTFMove(securityOrigin), m_quotaInBytes);
+ }).iterator->value.copyRef();
}
void StorageManager::SessionStorageNamespace::cloneTo(SessionStorageNamespace& newSessionStorageNamespace)
{
ASSERT_UNUSED(newSessionStorageNamespace, newSessionStorageNamespace.isEmpty());
- for (HashMap<RefPtr<SecurityOrigin>, RefPtr<StorageArea>>::const_iterator it = m_storageAreaMap.begin(), end = m_storageAreaMap.end(); it != end; ++it)
- newSessionStorageNamespace.m_storageAreaMap.add(it->key, it->value->clone());
+ for (auto& pair : m_storageAreaMap)
+ newSessionStorageNamespace.m_storageAreaMap.add(pair.key, pair.value->clone());
}
-PassRefPtr<StorageManager> StorageManager::create()
+Ref<StorageManager> StorageManager::create(const String& localStorageDirectory)
{
- return adoptRef(new StorageManager);
+ return adoptRef(*new StorageManager(localStorageDirectory));
}
-StorageManager::StorageManager()
+StorageManager::StorageManager(const String& localStorageDirectory)
: m_queue(WorkQueue::create("com.apple.WebKit.StorageManager"))
- , m_localStorageDatabaseTracker(LocalStorageDatabaseTracker::create(m_queue))
+ , m_localStorageDatabaseTracker(LocalStorageDatabaseTracker::create(m_queue.copyRef(), localStorageDirectory))
{
// Make sure the encoding is initialized before we start dispatching things to the queue.
UTF8Encoding();
@@ -383,61 +463,204 @@ StorageManager::~StorageManager()
{
}
-void StorageManager::setLocalStorageDirectory(const String& localStorageDirectory)
+void StorageManager::createSessionStorageNamespace(uint64_t storageNamespaceID, unsigned quotaInBytes)
{
- m_localStorageDatabaseTracker->setLocalStorageDirectory(localStorageDirectory);
-}
+ m_queue->dispatch([this, protectedThis = makeRef(*this), storageNamespaceID, quotaInBytes]() mutable {
+ ASSERT(!m_sessionStorageNamespaces.contains(storageNamespaceID));
-void StorageManager::createSessionStorageNamespace(uint64_t storageNamespaceID, IPC::Connection* allowedConnection, unsigned quotaInBytes)
-{
- m_queue->dispatch(bind(&StorageManager::createSessionStorageNamespaceInternal, this, storageNamespaceID, RefPtr<IPC::Connection>(allowedConnection), quotaInBytes));
+ m_sessionStorageNamespaces.set(storageNamespaceID, SessionStorageNamespace::create(quotaInBytes));
+ });
}
void StorageManager::destroySessionStorageNamespace(uint64_t storageNamespaceID)
{
- m_queue->dispatch(bind(&StorageManager::destroySessionStorageNamespaceInternal, this, storageNamespaceID));
+ m_queue->dispatch([this, protectedThis = makeRef(*this), storageNamespaceID] {
+ ASSERT(m_sessionStorageNamespaces.contains(storageNamespaceID));
+ m_sessionStorageNamespaces.remove(storageNamespaceID);
+ });
}
void StorageManager::setAllowedSessionStorageNamespaceConnection(uint64_t storageNamespaceID, IPC::Connection* allowedConnection)
{
- m_queue->dispatch(bind(&StorageManager::setAllowedSessionStorageNamespaceConnectionInternal, this, storageNamespaceID, RefPtr<IPC::Connection>(allowedConnection)));
+ m_queue->dispatch([this, protectedThis = makeRef(*this), connection = RefPtr<IPC::Connection>(allowedConnection), storageNamespaceID]() mutable {
+ ASSERT(m_sessionStorageNamespaces.contains(storageNamespaceID));
+
+ m_sessionStorageNamespaces.get(storageNamespaceID)->setAllowedConnection(connection.get());
+ });
}
void StorageManager::cloneSessionStorageNamespace(uint64_t storageNamespaceID, uint64_t newStorageNamespaceID)
{
- m_queue->dispatch(bind(&StorageManager::cloneSessionStorageNamespaceInternal, this, storageNamespaceID, newStorageNamespaceID));
+ m_queue->dispatch([this, protectedThis = makeRef(*this), storageNamespaceID, newStorageNamespaceID] {
+ SessionStorageNamespace* sessionStorageNamespace = m_sessionStorageNamespaces.get(storageNamespaceID);
+ if (!sessionStorageNamespace) {
+ // FIXME: We can get into this situation if someone closes the originating page from within a
+ // createNewPage callback. We bail for now, but we should really find a way to keep the session storage alive
+ // so we we'll clone the session storage correctly.
+ return;
+ }
+
+ SessionStorageNamespace* newSessionStorageNamespace = m_sessionStorageNamespaces.get(newStorageNamespaceID);
+ ASSERT(newSessionStorageNamespace);
+
+ sessionStorageNamespace->cloneTo(*newSessionStorageNamespace);
+ });
+}
+
+void StorageManager::processWillOpenConnection(WebProcessProxy&, IPC::Connection& connection)
+{
+ connection.addWorkQueueMessageReceiver(Messages::StorageManager::messageReceiverName(), m_queue.get(), this);
+}
+
+void StorageManager::processDidCloseConnection(WebProcessProxy&, IPC::Connection& connection)
+{
+ connection.removeWorkQueueMessageReceiver(Messages::StorageManager::messageReceiverName());
+
+ m_queue->dispatch([this, protectedThis = makeRef(*this), connection = Ref<IPC::Connection>(connection)]() mutable {
+ Vector<std::pair<RefPtr<IPC::Connection>, uint64_t>> connectionAndStorageMapIDPairsToRemove;
+ for (auto& storageArea : m_storageAreasByConnection) {
+ if (storageArea.key.first != connection.ptr())
+ continue;
+
+ storageArea.value->removeListener(*storageArea.key.first, storageArea.key.second);
+ connectionAndStorageMapIDPairsToRemove.append(storageArea.key);
+ }
+
+ for (auto& pair : connectionAndStorageMapIDPairsToRemove)
+ m_storageAreasByConnection.remove(pair);
+ });
+}
+
+void StorageManager::getSessionStorageOrigins(std::function<void(HashSet<WebCore::SecurityOriginData>&&)>&& completionHandler)
+{
+ m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable {
+ HashSet<SecurityOriginData> origins;
+
+ for (const auto& sessionStorageNamespace : m_sessionStorageNamespaces.values()) {
+ for (auto& origin : sessionStorageNamespace->origins())
+ origins.add(origin);
+ }
+
+ RunLoop::main().dispatch([origins = WTFMove(origins), completionHandler = WTFMove(completionHandler)]() mutable {
+ completionHandler(WTFMove(origins));
+ });
+ });
+}
+
+void StorageManager::deleteSessionStorageOrigins(std::function<void()>&& completionHandler)
+{
+ m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable {
+ for (auto& sessionStorageNamespace : m_sessionStorageNamespaces.values())
+ sessionStorageNamespace->clearAllStorageAreas();
+
+ RunLoop::main().dispatch(WTFMove(completionHandler));
+ });
+}
+
+void StorageManager::deleteSessionStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>& origins, std::function<void()>&& completionHandler)
+{
+ Vector<WebCore::SecurityOriginData> copiedOrigins;
+ copiedOrigins.reserveInitialCapacity(origins.size());
+
+ for (auto& origin : origins)
+ copiedOrigins.uncheckedAppend(origin.isolatedCopy());
+
+ m_queue->dispatch([this, protectedThis = makeRef(*this), copiedOrigins = WTFMove(copiedOrigins), completionHandler = WTFMove(completionHandler)]() mutable {
+ for (auto& origin : copiedOrigins) {
+ for (auto& sessionStorageNamespace : m_sessionStorageNamespaces.values())
+ sessionStorageNamespace->clearStorageAreasMatchingOrigin(origin);
+ }
+
+ RunLoop::main().dispatch(WTFMove(completionHandler));
+ });
}
-void StorageManager::processWillOpenConnection(WebProcessProxy* webProcessProxy)
+void StorageManager::getLocalStorageOrigins(std::function<void(HashSet<WebCore::SecurityOriginData>&&)>&& completionHandler)
{
- webProcessProxy->connection()->addWorkQueueMessageReceiver(Messages::StorageManager::messageReceiverName(), m_queue.get(), this);
+ m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable {
+ HashSet<SecurityOriginData> origins;
+
+ for (auto& origin : m_localStorageDatabaseTracker->origins())
+ origins.add(origin);
+
+ for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values()) {
+ for (auto& origin : transientLocalStorageNamespace->origins())
+ origins.add(origin);
+ }
+
+ RunLoop::main().dispatch([origins = WTFMove(origins), completionHandler = WTFMove(completionHandler)]() mutable {
+ completionHandler(WTFMove(origins));
+ });
+ });
}
-void StorageManager::processWillCloseConnection(WebProcessProxy* webProcessProxy)
+void StorageManager::getLocalStorageOriginDetails(std::function<void (Vector<LocalStorageDatabaseTracker::OriginDetails>)>&& completionHandler)
{
- webProcessProxy->connection()->removeWorkQueueMessageReceiver(Messages::StorageManager::messageReceiverName());
+ m_queue->dispatch([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable {
+ auto originDetails = m_localStorageDatabaseTracker->originDetails();
- m_queue->dispatch(bind(&StorageManager::invalidateConnectionInternal, this, RefPtr<IPC::Connection>(webProcessProxy->connection())));
+ RunLoop::main().dispatch([originDetails = WTFMove(originDetails), completionHandler = WTFMove(completionHandler)]() mutable {
+ completionHandler(WTFMove(originDetails));
+ });
+ });
}
-void StorageManager::getOrigins(FunctionDispatcher* callbackDispatcher, void* context, void (*callback)(const Vector<RefPtr<WebCore::SecurityOrigin>>& securityOrigins, void* context))
+void StorageManager::deleteLocalStorageEntriesForOrigin(SecurityOriginData&& securityOrigin)
{
- m_queue->dispatch(bind(&StorageManager::getOriginsInternal, this, RefPtr<FunctionDispatcher>(callbackDispatcher), context, callback));
+ m_queue->dispatch([this, protectedThis = makeRef(*this), copiedOrigin = securityOrigin.isolatedCopy()]() mutable {
+ for (auto& localStorageNamespace : m_localStorageNamespaces.values())
+ localStorageNamespace->clearStorageAreasMatchingOrigin(copiedOrigin);
+
+ for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values())
+ transientLocalStorageNamespace->clearStorageAreasMatchingOrigin(copiedOrigin);
+
+ m_localStorageDatabaseTracker->deleteDatabaseWithOrigin(copiedOrigin);
+ });
}
-void StorageManager::deleteEntriesForOrigin(SecurityOrigin* securityOrigin)
+void StorageManager::deleteLocalStorageOriginsModifiedSince(std::chrono::system_clock::time_point time, std::function<void()>&& completionHandler)
{
- m_queue->dispatch(bind(&StorageManager::deleteEntriesForOriginInternal, this, RefPtr<SecurityOrigin>(securityOrigin)));
+ m_queue->dispatch([this, protectedThis = makeRef(*this), time, completionHandler = WTFMove(completionHandler)]() mutable {
+ auto deletedOrigins = m_localStorageDatabaseTracker->deleteDatabasesModifiedSince(time);
+
+ for (const auto& origin : deletedOrigins) {
+ for (auto& localStorageNamespace : m_localStorageNamespaces.values())
+ localStorageNamespace->clearStorageAreasMatchingOrigin(origin);
+ }
+
+ for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values())
+ transientLocalStorageNamespace->clearAllStorageAreas();
+
+ RunLoop::main().dispatch(WTFMove(completionHandler));
+ });
}
-void StorageManager::deleteAllEntries()
+void StorageManager::deleteLocalStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>& origins, std::function<void()>&& completionHandler)
{
- m_queue->dispatch(bind(&StorageManager::deleteAllEntriesInternal, this));
+ Vector<SecurityOriginData> copiedOrigins;
+ copiedOrigins.reserveInitialCapacity(origins.size());
+
+ for (auto& origin : origins)
+ copiedOrigins.uncheckedAppend(origin.isolatedCopy());
+
+ m_queue->dispatch([this, protectedThis = makeRef(*this), copiedOrigins = WTFMove(copiedOrigins), completionHandler = WTFMove(completionHandler)]() mutable {
+ for (auto& origin : copiedOrigins) {
+ for (auto& localStorageNamespace : m_localStorageNamespaces.values())
+ localStorageNamespace->clearStorageAreasMatchingOrigin(origin);
+
+ for (auto& transientLocalStorageNamespace : m_transientLocalStorageNamespaces.values())
+ transientLocalStorageNamespace->clearStorageAreasMatchingOrigin(origin);
+
+ m_localStorageDatabaseTracker->deleteDatabaseWithOrigin(origin);
+ }
+
+ RunLoop::main().dispatch(WTFMove(completionHandler));
+ });
}
-void StorageManager::createLocalStorageMap(IPC::Connection* connection, uint64_t storageMapID, uint64_t storageNamespaceID, const SecurityOriginData& securityOriginData)
+void StorageManager::createLocalStorageMap(IPC::Connection& connection, uint64_t storageMapID, uint64_t storageNamespaceID, SecurityOriginData&& securityOriginData)
{
- std::pair<RefPtr<IPC::Connection>, uint64_t> connectionAndStorageMapIDPair(connection, storageMapID);
+ std::pair<RefPtr<IPC::Connection>, uint64_t> connectionAndStorageMapIDPair(&connection, storageMapID);
// FIXME: This should be a message check.
ASSERT((HashMap<std::pair<RefPtr<IPC::Connection>, uint64_t>, RefPtr<StorageArea>>::isValidKey(connectionAndStorageMapIDPair)));
@@ -453,16 +676,51 @@ void StorageManager::createLocalStorageMap(IPC::Connection* connection, uint64_t
// FIXME: This should be a message check.
ASSERT(localStorageNamespace);
- RefPtr<StorageArea> storageArea = localStorageNamespace->getOrCreateStorageArea(securityOriginData.securityOrigin());
+ auto storageArea = localStorageNamespace->getOrCreateStorageArea(WTFMove(securityOriginData));
+ storageArea->addListener(connection, storageMapID);
+
+ result.iterator->value = WTFMove(storageArea);
+}
+
+void StorageManager::createTransientLocalStorageMap(IPC::Connection& connection, uint64_t storageMapID, uint64_t storageNamespaceID, SecurityOriginData&& topLevelOriginData, SecurityOriginData&& origin)
+{
+ // FIXME: This should be a message check.
+ ASSERT(m_storageAreasByConnection.isValidKey({ &connection, storageMapID }));
+
+ // See if we already have session storage for this connection/origin combo.
+ // If so, update the map with the new ID, otherwise keep on trucking.
+ for (auto it = m_storageAreasByConnection.begin(), end = m_storageAreasByConnection.end(); it != end; ++it) {
+ if (it->key.first != &connection)
+ continue;
+ Ref<StorageArea> area = *it->value;
+ if (!area->isSessionStorage())
+ continue;
+ if (!origin.securityOrigin()->isSameSchemeHostPort(area->securityOrigin().securityOrigin().get()))
+ continue;
+ area->addListener(connection, storageMapID);
+ m_storageAreasByConnection.remove(it);
+ m_storageAreasByConnection.add({ &connection, storageMapID }, WTFMove(area));
+ return;
+ }
+
+ auto& slot = m_storageAreasByConnection.add({ &connection, storageMapID }, nullptr).iterator->value;
+
+ // FIXME: This should be a message check.
+ ASSERT(!slot);
+
+ TransientLocalStorageNamespace* transientLocalStorageNamespace = getOrCreateTransientLocalStorageNamespace(storageNamespaceID, WTFMove(topLevelOriginData));
+
+ auto storageArea = transientLocalStorageNamespace->getOrCreateStorageArea(WTFMove(origin));
storageArea->addListener(connection, storageMapID);
- result.iterator->value = storageArea.release();
+ slot = WTFMove(storageArea);
}
-void StorageManager::createSessionStorageMap(IPC::Connection* connection, uint64_t storageMapID, uint64_t storageNamespaceID, const SecurityOriginData& securityOriginData)
+void StorageManager::createSessionStorageMap(IPC::Connection& connection, uint64_t storageMapID, uint64_t storageNamespaceID, SecurityOriginData&& securityOriginData)
{
// FIXME: This should be a message check.
- ASSERT((HashMap<uint64_t, RefPtr<SessionStorageNamespace>>::isValidKey(storageNamespaceID)));
+ 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
@@ -470,43 +728,46 @@ void StorageManager::createSessionStorageMap(IPC::Connection* connection, uint64
return;
}
- std::pair<RefPtr<IPC::Connection>, uint64_t> connectionAndStorageMapIDPair(connection, storageMapID);
-
// FIXME: This should be a message check.
- ASSERT((HashMap<std::pair<RefPtr<IPC::Connection>, uint64_t>, RefPtr<StorageArea>>::isValidKey(connectionAndStorageMapIDPair)));
+ ASSERT(m_storageAreasByConnection.isValidKey({ &connection, storageMapID }));
- HashMap<std::pair<RefPtr<IPC::Connection>, uint64_t>, RefPtr<StorageArea>>::AddResult result = m_storageAreasByConnection.add(connectionAndStorageMapIDPair, nullptr);
+ auto& slot = m_storageAreasByConnection.add({ &connection, storageMapID }, nullptr).iterator->value;
// FIXME: This should be a message check.
- ASSERT(result.isNewEntry);
+ ASSERT(!slot);
// FIXME: This should be a message check.
- ASSERT(connection == sessionStorageNamespace->allowedConnection());
+ ASSERT(&connection == sessionStorageNamespace->allowedConnection());
- RefPtr<StorageArea> storageArea = sessionStorageNamespace->getOrCreateStorageArea(securityOriginData.securityOrigin());
+ auto storageArea = sessionStorageNamespace->getOrCreateStorageArea(WTFMove(securityOriginData));
storageArea->addListener(connection, storageMapID);
- result.iterator->value = storageArea.release();
+ slot = WTFMove(storageArea);
}
-void StorageManager::destroyStorageMap(IPC::Connection* connection, uint64_t storageMapID)
+void StorageManager::destroyStorageMap(IPC::Connection& connection, uint64_t storageMapID)
{
- std::pair<RefPtr<IPC::Connection>, uint64_t> connectionAndStorageMapIDPair(connection, storageMapID);
+ std::pair<RefPtr<IPC::Connection>, uint64_t> connectionAndStorageMapIDPair(&connection, storageMapID);
// FIXME: This should be a message check.
- ASSERT((HashMap<std::pair<RefPtr<IPC::Connection>, uint64_t>, RefPtr<StorageArea>>::isValidKey(connectionAndStorageMapIDPair)));
+ ASSERT(m_storageAreasByConnection.isValidKey(connectionAndStorageMapIDPair));
- HashMap<std::pair<RefPtr<IPC::Connection>, uint64_t>, RefPtr<StorageArea>>::iterator it = m_storageAreasByConnection.find(connectionAndStorageMapIDPair);
+ auto it = m_storageAreasByConnection.find(connectionAndStorageMapIDPair);
if (it == m_storageAreasByConnection.end()) {
// The connection has been removed because the last page was closed.
return;
}
it->value->removeListener(connection, storageMapID);
+
+ // Don't remove session storage maps. The web process may reconnect and expect the data to still be around.
+ if (it->value->isSessionStorage())
+ return;
+
m_storageAreasByConnection.remove(connectionAndStorageMapIDPair);
}
-void StorageManager::getValues(IPC::Connection* connection, uint64_t storageMapID, uint64_t storageMapSeed, HashMap<String, String>& values)
+void StorageManager::getValues(IPC::Connection& connection, uint64_t storageMapID, uint64_t storageMapSeed, HashMap<String, String>& values)
{
StorageArea* storageArea = findStorageArea(connection, storageMapID);
if (!storageArea) {
@@ -515,10 +776,10 @@ void StorageManager::getValues(IPC::Connection* connection, uint64_t storageMapI
}
values = storageArea->items();
- connection->send(Messages::StorageAreaMap::DidGetValues(storageMapSeed), storageMapID);
+ connection.send(Messages::StorageAreaMap::DidGetValues(storageMapSeed), storageMapID);
}
-void StorageManager::setItem(IPC::Connection* connection, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& value, const String& urlString)
+void StorageManager::setItem(IPC::Connection& connection, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& value, const String& urlString)
{
StorageArea* storageArea = findStorageArea(connection, storageMapID);
if (!storageArea) {
@@ -527,11 +788,11 @@ void StorageManager::setItem(IPC::Connection* connection, uint64_t storageMapID,
}
bool quotaError;
- storageArea->setItem(connection, sourceStorageAreaID, key, value, urlString, quotaError);
- connection->send(Messages::StorageAreaMap::DidSetItem(storageMapSeed, key, quotaError), storageMapID);
+ storageArea->setItem(&connection, sourceStorageAreaID, key, value, urlString, quotaError);
+ connection.send(Messages::StorageAreaMap::DidSetItem(storageMapSeed, key, quotaError), storageMapID);
}
-void StorageManager::removeItem(IPC::Connection* connection, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& urlString)
+void StorageManager::removeItem(IPC::Connection& connection, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& urlString)
{
StorageArea* storageArea = findStorageArea(connection, storageMapID);
if (!storageArea) {
@@ -539,11 +800,11 @@ void StorageManager::removeItem(IPC::Connection* connection, uint64_t storageMap
return;
}
- storageArea->removeItem(connection, sourceStorageAreaID, key, urlString);
- connection->send(Messages::StorageAreaMap::DidRemoveItem(storageMapSeed, key), storageMapID);
+ storageArea->removeItem(&connection, sourceStorageAreaID, key, urlString);
+ connection.send(Messages::StorageAreaMap::DidRemoveItem(storageMapSeed, key), storageMapID);
}
-void StorageManager::clear(IPC::Connection* connection, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& urlString)
+void StorageManager::clear(IPC::Connection& connection, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& urlString)
{
StorageArea* storageArea = findStorageArea(connection, storageMapID);
if (!storageArea) {
@@ -551,105 +812,60 @@ void StorageManager::clear(IPC::Connection* connection, uint64_t storageMapID, u
return;
}
- storageArea->clear(connection, sourceStorageAreaID, urlString);
- connection->send(Messages::StorageAreaMap::DidClear(storageMapSeed), storageMapID);
-}
-
-void StorageManager::createSessionStorageNamespaceInternal(uint64_t storageNamespaceID, IPC::Connection* allowedConnection, unsigned quotaInBytes)
-{
- ASSERT(!m_sessionStorageNamespaces.contains(storageNamespaceID));
-
- m_sessionStorageNamespaces.set(storageNamespaceID, SessionStorageNamespace::create(allowedConnection, quotaInBytes));
+ storageArea->clear(&connection, sourceStorageAreaID, urlString);
+ connection.send(Messages::StorageAreaMap::DidClear(storageMapSeed), storageMapID);
}
-void StorageManager::destroySessionStorageNamespaceInternal(uint64_t storageNamespaceID)
+void StorageManager::applicationWillTerminate()
{
- ASSERT(m_sessionStorageNamespaces.contains(storageNamespaceID));
- m_sessionStorageNamespaces.remove(storageNamespaceID);
-}
-
-void StorageManager::setAllowedSessionStorageNamespaceConnectionInternal(uint64_t storageNamespaceID, IPC::Connection* allowedConnection)
-{
- ASSERT(m_sessionStorageNamespaces.contains(storageNamespaceID));
-
- m_sessionStorageNamespaces.get(storageNamespaceID)->setAllowedConnection(allowedConnection);
-}
-
-void StorageManager::cloneSessionStorageNamespaceInternal(uint64_t storageNamespaceID, uint64_t newStorageNamespaceID)
-{
- SessionStorageNamespace* sessionStorageNamespace = m_sessionStorageNamespaces.get(storageNamespaceID);
- ASSERT(sessionStorageNamespace);
+ BinarySemaphore semaphore;
+ m_queue->dispatch([this, &semaphore] {
+ Vector<std::pair<RefPtr<IPC::Connection>, uint64_t>> connectionAndStorageMapIDPairsToRemove;
+ for (auto& connectionStorageAreaPair : m_storageAreasByConnection) {
+ connectionStorageAreaPair.value->removeListener(*connectionStorageAreaPair.key.first, connectionStorageAreaPair.key.second);
+ connectionAndStorageMapIDPairsToRemove.append(connectionStorageAreaPair.key);
+ }
- SessionStorageNamespace* newSessionStorageNamespace = m_sessionStorageNamespaces.get(newStorageNamespaceID);
- ASSERT(newSessionStorageNamespace);
+ for (auto& connectionStorageAreaPair : connectionAndStorageMapIDPairsToRemove)
+ m_storageAreasByConnection.remove(connectionStorageAreaPair);
- sessionStorageNamespace->cloneTo(*newSessionStorageNamespace);
+ semaphore.signal();
+ });
+ semaphore.wait(WallTime::infinity());
}
-void StorageManager::invalidateConnectionInternal(IPC::Connection* connection)
+StorageManager::StorageArea* StorageManager::findStorageArea(IPC::Connection& connection, uint64_t storageMapID) const
{
- Vector<std::pair<RefPtr<IPC::Connection>, uint64_t>> connectionAndStorageMapIDPairsToRemove;
- HashMap<std::pair<RefPtr<IPC::Connection>, uint64_t>, RefPtr<StorageArea>> storageAreasByConnection = m_storageAreasByConnection;
- for (HashMap<std::pair<RefPtr<IPC::Connection>, uint64_t>, RefPtr<StorageArea>>::const_iterator it = storageAreasByConnection.begin(), end = storageAreasByConnection.end(); it != end; ++it) {
- if (it->key.first != connection)
- continue;
-
- it->value->removeListener(it->key.first.get(), it->key.second);
- connectionAndStorageMapIDPairsToRemove.append(it->key);
- }
-
- for (size_t i = 0; i < connectionAndStorageMapIDPairsToRemove.size(); ++i)
- m_storageAreasByConnection.remove(connectionAndStorageMapIDPairsToRemove[i]);
-}
+ std::pair<IPC::Connection*, uint64_t> connectionAndStorageMapIDPair(&connection, storageMapID);
-StorageManager::StorageArea* StorageManager::findStorageArea(IPC::Connection* connection, uint64_t storageMapID) const
-{
- std::pair<IPC::Connection*, uint64_t> connectionAndStorageMapIDPair(connection, storageMapID);
- if (!HashMap<std::pair<RefPtr<IPC::Connection>, uint64_t>, RefPtr<StorageArea>>::isValidKey(connectionAndStorageMapIDPair))
- return 0;
+ if (!m_storageAreasByConnection.isValidKey(connectionAndStorageMapIDPair))
+ return nullptr;
return m_storageAreasByConnection.get(connectionAndStorageMapIDPair);
}
StorageManager::LocalStorageNamespace* StorageManager::getOrCreateLocalStorageNamespace(uint64_t storageNamespaceID)
{
- if (!HashMap<uint64_t, RefPtr<LocalStorageNamespace>>::isValidKey(storageNamespaceID))
- return 0;
-
- HashMap<uint64_t, RefPtr<LocalStorageNamespace>>::AddResult result = m_localStorageNamespaces.add(storageNamespaceID, nullptr);
- if (result.isNewEntry)
- result.iterator->value = LocalStorageNamespace::create(this, storageNamespaceID);
-
- return result.iterator->value.get();
-}
+ if (!m_localStorageNamespaces.isValidKey(storageNamespaceID))
+ return nullptr;
-static void callCallbackFunction(void* context, void (*callbackFunction)(const Vector<RefPtr<WebCore::SecurityOrigin>>& securityOrigins, void* context), Vector<RefPtr<WebCore::SecurityOrigin>>* securityOriginsPtr)
-{
- OwnPtr<Vector<RefPtr<WebCore::SecurityOrigin>>> securityOrigins = adoptPtr(securityOriginsPtr);
- callbackFunction(*securityOrigins, context);
-}
+ auto& slot = m_localStorageNamespaces.add(storageNamespaceID, nullptr).iterator->value;
+ if (!slot)
+ slot = LocalStorageNamespace::create(this, storageNamespaceID);
-void StorageManager::getOriginsInternal(FunctionDispatcher* dispatcher, void* context, void (*callbackFunction)(const Vector<RefPtr<WebCore::SecurityOrigin>>& securityOrigins, void* context))
-{
- OwnPtr<Vector<RefPtr<WebCore::SecurityOrigin>>> securityOrigins = adoptPtr(new Vector<RefPtr<WebCore::SecurityOrigin>>(m_localStorageDatabaseTracker->origins()));
- dispatcher->dispatch(bind(callCallbackFunction, context, callbackFunction, securityOrigins.leakPtr()));
+ return slot.get();
}
-void StorageManager::deleteEntriesForOriginInternal(SecurityOrigin* securityOrigin)
+StorageManager::TransientLocalStorageNamespace* StorageManager::getOrCreateTransientLocalStorageNamespace(uint64_t storageNamespaceID, WebCore::SecurityOriginData&& topLevelOrigin)
{
- for (auto it = m_localStorageNamespaces.begin(), end = m_localStorageNamespaces.end(); it != end; ++it)
- it->value->clearStorageAreasMatchingOrigin(securityOrigin);
+ if (!m_transientLocalStorageNamespaces.isValidKey({ storageNamespaceID, topLevelOrigin }))
+ return nullptr;
- m_localStorageDatabaseTracker->deleteDatabaseWithOrigin(securityOrigin);
-}
-
-void StorageManager::deleteAllEntriesInternal()
-{
- for (auto it = m_localStorageNamespaces.begin(), end = m_localStorageNamespaces.end(); it != end; ++it)
- it->value->clearAllStorageAreas();
+ auto& slot = m_transientLocalStorageNamespaces.add({ storageNamespaceID, WTFMove(topLevelOrigin) }, nullptr).iterator->value;
+ if (!slot)
+ slot = TransientLocalStorageNamespace::create();
- m_localStorageDatabaseTracker->deleteAllDatabases();
+ return slot.get();
}
-
} // namespace WebKit
diff --git a/Source/WebKit2/UIProcess/Storage/StorageManager.h b/Source/WebKit2/UIProcess/Storage/StorageManager.h
index 93bb66c55..52f093e01 100644
--- a/Source/WebKit2/UIProcess/Storage/StorageManager.h
+++ b/Source/WebKit2/UIProcess/Storage/StorageManager.h
@@ -23,87 +23,87 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef StorageManager_h
-#define StorageManager_h
+#pragma once
#include "Connection.h"
+#include "LocalStorageDatabaseTracker.h"
+#include <WebCore/SecurityOriginData.h>
+#include <WebCore/SecurityOriginHash.h>
+#include <chrono>
#include <wtf/Forward.h>
-#include <wtf/PassRefPtr.h>
+#include <wtf/HashSet.h>
#include <wtf/ThreadSafeRefCounted.h>
#include <wtf/text/StringHash.h>
-class WorkQueue;
-
namespace WebCore {
class SecurityOrigin;
}
namespace WebKit {
-struct SecurityOriginData;
class LocalStorageDatabaseTracker;
class WebProcessProxy;
class StorageManager : public IPC::Connection::WorkQueueMessageReceiver {
public:
- static PassRefPtr<StorageManager> create();
+ static Ref<StorageManager> create(const String& localStorageDirectory);
~StorageManager();
- void setLocalStorageDirectory(const String&);
-
- void createSessionStorageNamespace(uint64_t storageNamespaceID, IPC::Connection* allowedConnection, unsigned quotaInBytes);
+ void createSessionStorageNamespace(uint64_t storageNamespaceID, unsigned quotaInBytes);
void destroySessionStorageNamespace(uint64_t storageNamespaceID);
void setAllowedSessionStorageNamespaceConnection(uint64_t storageNamespaceID, IPC::Connection* allowedConnection);
void cloneSessionStorageNamespace(uint64_t storageNamespaceID, uint64_t newStorageNamespaceID);
- void processWillOpenConnection(WebProcessProxy*);
- void processWillCloseConnection(WebProcessProxy*);
+ void processWillOpenConnection(WebProcessProxy&, IPC::Connection&);
+ void processDidCloseConnection(WebProcessProxy&, IPC::Connection&);
+ void applicationWillTerminate();
+
+ void getSessionStorageOrigins(std::function<void(HashSet<WebCore::SecurityOriginData>&&)>&& completionHandler);
+ void deleteSessionStorageOrigins(std::function<void()>&& completionHandler);
+ void deleteSessionStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>&, std::function<void()>&& completionHandler);
+
+ void getLocalStorageOrigins(std::function<void(HashSet<WebCore::SecurityOriginData>&&)>&& completionHandler);
+ void deleteLocalStorageEntriesForOrigin(WebCore::SecurityOriginData&&);
+
+ void deleteLocalStorageOriginsModifiedSince(std::chrono::system_clock::time_point, std::function<void()>&& completionHandler);
+ void deleteLocalStorageEntriesForOrigins(const Vector<WebCore::SecurityOriginData>&, std::function<void()>&& completionHandler);
- // FIXME: Instead of a context + C function, this should take a WTF::Function, but we currently don't
- // support arguments in functions.
- void getOrigins(FunctionDispatcher* callbackDispatcher, void* context, void (*callback)(const Vector<RefPtr<WebCore::SecurityOrigin>>& securityOrigins, void* context));
- void deleteEntriesForOrigin(WebCore::SecurityOrigin*);
- void deleteAllEntries();
+ void getLocalStorageOriginDetails(std::function<void(Vector<LocalStorageDatabaseTracker::OriginDetails>)>&& completionHandler);
private:
- StorageManager();
+ explicit StorageManager(const String& localStorageDirectory);
// IPC::Connection::WorkQueueMessageReceiver.
- virtual void didReceiveMessage(IPC::Connection*, IPC::MessageDecoder&) override;
- virtual void didReceiveSyncMessage(IPC::Connection*, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>& replyEncoder) override;
+ void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
+ void didReceiveSyncMessage(IPC::Connection&, IPC::Decoder&, std::unique_ptr<IPC::Encoder>& replyEncoder) override;
// Message handlers.
- void createLocalStorageMap(IPC::Connection*, uint64_t storageMapID, uint64_t storageNamespaceID, const SecurityOriginData&);
- void createSessionStorageMap(IPC::Connection*, uint64_t storageMapID, uint64_t storageNamespaceID, const SecurityOriginData&);
- void destroyStorageMap(IPC::Connection*, uint64_t storageMapID);
+ 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, HashMap<String, String>& values);
- 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 storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& urlString);
- void clear(IPC::Connection*, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& urlString);
-
- void createSessionStorageNamespaceInternal(uint64_t storageNamespaceID, IPC::Connection* allowedConnection, unsigned quotaInBytes);
- void destroySessionStorageNamespaceInternal(uint64_t storageNamespaceID);
- void setAllowedSessionStorageNamespaceConnectionInternal(uint64_t storageNamespaceID, IPC::Connection* allowedConnection);
- void cloneSessionStorageNamespaceInternal(uint64_t storageNamespaceID, uint64_t newStorageNamespaceID);
-
- void invalidateConnectionInternal(IPC::Connection*);
+ void getValues(IPC::Connection&, uint64_t storageMapID, uint64_t storageMapSeed, HashMap<String, String>& values);
+ 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 storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& key, const String& urlString);
+ void clear(IPC::Connection&, uint64_t storageMapID, uint64_t sourceStorageAreaID, uint64_t storageMapSeed, const String& urlString);
class StorageArea;
- StorageArea* findStorageArea(IPC::Connection*, uint64_t) const;
+ StorageArea* findStorageArea(IPC::Connection&, uint64_t) const;
class LocalStorageNamespace;
LocalStorageNamespace* getOrCreateLocalStorageNamespace(uint64_t storageNamespaceID);
- void getOriginsInternal(FunctionDispatcher* callbackDispatcher, void* context, void (*callback)(const Vector<RefPtr<WebCore::SecurityOrigin>>& securityOrigins, void* context));
- void deleteEntriesForOriginInternal(WebCore::SecurityOrigin*);
- void deleteAllEntriesInternal();
+ class TransientLocalStorageNamespace;
+ TransientLocalStorageNamespace* getOrCreateTransientLocalStorageNamespace(uint64_t storageNamespaceID, WebCore::SecurityOriginData&& topLevelOrigin);
- RefPtr<WorkQueue> m_queue;
+ Ref<WorkQueue> m_queue;
- RefPtr<LocalStorageDatabaseTracker> m_localStorageDatabaseTracker;
+ Ref<LocalStorageDatabaseTracker> m_localStorageDatabaseTracker;
HashMap<uint64_t, RefPtr<LocalStorageNamespace>> m_localStorageNamespaces;
+ HashMap<std::pair<uint64_t, WebCore::SecurityOriginData>, RefPtr<TransientLocalStorageNamespace>> m_transientLocalStorageNamespaces;
+
class SessionStorageNamespace;
HashMap<uint64_t, RefPtr<SessionStorageNamespace>> m_sessionStorageNamespaces;
@@ -111,5 +111,3 @@ private:
};
} // namespace WebKit
-
-#endif // StorageManager_h
diff --git a/Source/WebKit2/UIProcess/Storage/StorageManager.messages.in b/Source/WebKit2/UIProcess/Storage/StorageManager.messages.in
index 59b8f3639..25789f74c 100644
--- a/Source/WebKit2/UIProcess/Storage/StorageManager.messages.in
+++ b/Source/WebKit2/UIProcess/Storage/StorageManager.messages.in
@@ -21,8 +21,9 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
messages -> StorageManager {
- CreateLocalStorageMap(uint64_t storageMapID, uint64_t storageNamespaceID, WebKit::SecurityOriginData securityOriginData) WantsConnection
- CreateSessionStorageMap(uint64_t storageMapID, uint64_t storageNamespaceID, WebKit::SecurityOriginData securityOriginData) WantsConnection
+ CreateLocalStorageMap(uint64_t storageMapID, uint64_t storageNamespaceID, struct WebCore::SecurityOriginData securityOriginData) WantsConnection
+ CreateTransientLocalStorageMap(uint64_t storageMapID, uint64_t storageNamespaceID, struct WebCore::SecurityOriginData topLevelSecurityOriginData, struct WebCore::SecurityOriginData securityOriginData) WantsConnection
+ CreateSessionStorageMap(uint64_t storageMapID, uint64_t storageNamespaceID, struct WebCore::SecurityOriginData securityOriginData) WantsConnection
DestroyStorageMap(uint64_t storageMapID) WantsConnection
GetValues(uint64_t storageMapID, uint64_t storageMapSeed) -> (HashMap<String, String> values) WantsConnection