summaryrefslogtreecommitdiff
path: root/Source/WebKit2/UIProcess/Storage/LocalStorageDatabaseTracker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit2/UIProcess/Storage/LocalStorageDatabaseTracker.cpp')
-rw-r--r--Source/WebKit2/UIProcess/Storage/LocalStorageDatabaseTracker.cpp159
1 files changed, 112 insertions, 47 deletions
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);