diff options
Diffstat (limited to 'Source/WebKit2/UIProcess/Storage/LocalStorageDatabaseTracker.cpp')
-rw-r--r-- | Source/WebKit2/UIProcess/Storage/LocalStorageDatabaseTracker.cpp | 159 |
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); |