void UniqueIDBDatabase::changeDatabaseVersion(const IDBTransactionIdentifier& identifier, uint64_t newVersion, std::function<void(bool)> successCallback) { ASSERT(isMainThread()); if (!m_acceptingNewRequests) { successCallback(false); return; } uint64_t oldVersion = m_metadata->version; m_metadata->version = newVersion; RefPtr<AsyncRequest> request = AsyncRequestImpl<bool>::create([this, oldVersion, successCallback](bool success) { if (!success) m_metadata->version = oldVersion; successCallback(success); }, [this, oldVersion, successCallback]() { m_metadata->version = oldVersion; successCallback(false); }); uint64_t requestID = request->requestID(); m_pendingDatabaseTasks.add(requestID, request.release()); postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::changeDatabaseVersionInBackingStore, requestID, identifier, newVersion)); }
void DatabaseProcess::deleteWebsiteData(WebCore::SessionID, uint64_t websiteDataTypes, std::chrono::system_clock::time_point modifiedSince, uint64_t callbackID) { struct CallbackAggregator final : public ThreadSafeRefCounted<CallbackAggregator> { explicit CallbackAggregator(std::function<void ()> completionHandler) : m_completionHandler(WTFMove(completionHandler)) { } ~CallbackAggregator() { ASSERT(RunLoop::isMain()); RunLoop::main().dispatch(WTFMove(m_completionHandler)); } std::function<void ()> m_completionHandler; }; RefPtr<CallbackAggregator> callbackAggregator = adoptRef(new CallbackAggregator([this, callbackID]() { parentProcessConnection()->send(Messages::DatabaseProcessProxy::DidDeleteWebsiteData(callbackID), 0); })); #if ENABLE(INDEXED_DATABASE) if (websiteDataTypes & WebsiteDataTypeIndexedDBDatabases) { postDatabaseTask(std::make_unique<CrossThreadTask>([this, callbackAggregator, modifiedSince] { deleteIndexedDatabaseEntriesModifiedSince(modifiedSince); RunLoop::main().dispatch([callbackAggregator] { }); })); } #endif }
void UniqueIDBDatabase::postTransactionOperation(const IDBTransactionIdentifier& identifier, std::unique_ptr<AsyncTask> task, std::function<void(bool)> successCallback) { ASSERT(isMainThread()); if (!m_acceptingNewRequests) { successCallback(false); return; } if (m_pendingTransactionRequests.contains(identifier)) { LOG_ERROR("Attempting to queue an operation for a transaction that already has an operation pending. Each transaction should only have one operation pending at a time."); successCallback(false); return; } postDatabaseTask(std::move(task)); RefPtr<AsyncRequest> request = AsyncRequestImpl<bool>::create([successCallback](bool success) { successCallback(success); }, [successCallback]() { successCallback(false); }); m_pendingTransactionRequests.add(identifier, request.release()); }
void UniqueIDBDatabase::getOrEstablishIDBDatabaseMetadata(std::function<void(bool, const IDBDatabaseMetadata&)> completionCallback) { ASSERT(isMainThread()); if (!m_acceptingNewRequests) { completionCallback(false, IDBDatabaseMetadata()); return; } // If we've already retrieved metadata from the backing store, return it now. if (m_didGetMetadataFromBackingStore) { if (m_metadata) completionCallback(true, *m_metadata); else completionCallback(false, IDBDatabaseMetadata()); return; } // If this is the first unanswered metadata request, post a task to open the backing store and get metadata. if (m_pendingMetadataRequests.isEmpty()) postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::openBackingStoreAndReadMetadata, m_identifier, absoluteDatabaseDirectory())); // Then remember this metadata request to be answered later. RefPtr<AsyncRequest> request = AsyncRequestImpl<>::create([completionCallback, this]() { completionCallback(!!m_metadata, m_metadata ? *m_metadata : IDBDatabaseMetadata()); }, [completionCallback]() { // The boolean flag to the completion callback represents whether the // attempt to get/establish metadata succeeded or failed. // Since we're aborting the attempt, it failed, so we always pass in false. completionCallback(false, IDBDatabaseMetadata()); }); m_pendingMetadataRequests.append(request.release()); }
void DatabaseProcess::getOrigins(WKOriginDataTypes types, std::function<void (const Vector<SecurityOriginData>&)> completion) { if (!(types & kWKWebSQLDatabaseOriginData)) { completion(Vector<SecurityOriginData>()); return; } postDatabaseTask(std::make_unique<AsyncTask>([completion, this] { completion(getIndexedDatabaseOrigins()); })); }
void DatabaseProcess::deleteAllEntries(WKOriginDataTypes types, std::function<void ()> completion) { if (!(types & kWKWebSQLDatabaseOriginData)) { completion(); return; } postDatabaseTask(std::make_unique<AsyncTask>([this, completion] { deleteAllIndexedDatabaseEntries(); completion(); })); }
void DatabaseProcess::deleteEntriesModifiedBetweenDates(WKOriginDataTypes types, double startDate, double endDate, std::function<void ()> completion) { if (!(types & kWKWebSQLDatabaseOriginData)) { completion(); return; } postDatabaseTask(std::make_unique<AsyncTask>([this, startDate, endDate, completion] { deleteIndexedDatabaseEntriesModifiedBetweenDates(startDate, endDate); completion(); })); }
void DatabaseProcess::deleteEntriesForOrigin(WKOriginDataTypes types, const SecurityOriginData& origin, std::function<void ()> completion) { if (!(types & kWKWebSQLDatabaseOriginData)) { completion(); return; } postDatabaseTask(std::make_unique<AsyncTask>([this, origin, completion] { deleteIndexedDatabaseEntriesForOrigin(origin); completion(); })); }
void DatabaseProcess::fetchWebsiteData(SessionID, uint64_t websiteDataTypes, uint64_t callbackID) { struct CallbackAggregator final : public ThreadSafeRefCounted<CallbackAggregator> { explicit CallbackAggregator(std::function<void (WebsiteData)> completionHandler) : m_completionHandler(WTFMove(completionHandler)) { } ~CallbackAggregator() { ASSERT(RunLoop::isMain()); auto completionHandler = WTFMove(m_completionHandler); auto websiteData = WTFMove(m_websiteData); RunLoop::main().dispatch([completionHandler, websiteData] { completionHandler(websiteData); }); } std::function<void (WebsiteData)> m_completionHandler; WebsiteData m_websiteData; }; RefPtr<CallbackAggregator> callbackAggregator = adoptRef(new CallbackAggregator([this, callbackID](WebsiteData websiteData) { parentProcessConnection()->send(Messages::DatabaseProcessProxy::DidFetchWebsiteData(callbackID, websiteData), 0); })); #if ENABLE(INDEXED_DATABASE) if (websiteDataTypes & WebsiteDataTypeIndexedDBDatabases) { // FIXME: Pick the right database store based on the session ID. postDatabaseTask(std::make_unique<CrossThreadTask>([callbackAggregator, websiteDataTypes, this] { Vector<RefPtr<SecurityOrigin>> securityOrigins = indexedDatabaseOrigins(); RunLoop::main().dispatch([callbackAggregator, securityOrigins] { for (const auto& securityOrigin : securityOrigins) callbackAggregator->m_websiteData.entries.append(WebsiteData::Entry { securityOrigin, WebsiteDataTypeIndexedDBDatabases }); }); })); } #endif }
void IDBServer::closeAndDeleteDatabasesModifiedSince(std::chrono::system_clock::time_point modificationTime, std::function<void ()> completionHandler) { uint64_t callbackID = generateDeleteCallbackID(); auto addResult = m_deleteDatabaseCompletionHandlers.add(callbackID, WTFMove(completionHandler)); ASSERT_UNUSED(addResult, addResult.isNewEntry); // If the modification time is in the future, don't both doing anything. if (modificationTime > std::chrono::system_clock::now()) { postDatabaseTaskReply(createCrossThreadTask(*this, &IDBServer::didPerformCloseAndDeleteDatabases, callbackID)); return; } HashSet<UniqueIDBDatabase*> openDatabases; for (auto* connection : m_databaseConnections.values()) openDatabases.add(&connection->database()); for (auto* database : openDatabases) database->immediateCloseForUserDelete(); postDatabaseTask(createCrossThreadTask(*this, &IDBServer::performCloseAndDeleteDatabasesModifiedSince, modificationTime, callbackID)); }
void IDBServer::closeAndDeleteDatabasesModifiedSince(WallTime modificationTime, Function<void ()>&& completionHandler) { uint64_t callbackID = generateDeleteCallbackID(); auto addResult = m_deleteDatabaseCompletionHandlers.add(callbackID, WTFMove(completionHandler)); ASSERT_UNUSED(addResult, addResult.isNewEntry); // If the modification time is in the future, don't both doing anything. if (modificationTime > WallTime::now()) { postDatabaseTaskReply(createCrossThreadTask(*this, &IDBServer::didPerformCloseAndDeleteDatabases, callbackID)); return; } HashSet<UniqueIDBDatabase*> openDatabases; for (auto& database : m_uniqueIDBDatabaseMap.values()) openDatabases.add(database.get()); for (auto& database : openDatabases) database->immediateCloseForUserDelete(); postDatabaseTask(createCrossThreadTask(*this, &IDBServer::performCloseAndDeleteDatabasesModifiedSince, modificationTime, callbackID)); }
void IDBServer::closeAndDeleteDatabasesForOrigins(const Vector<SecurityOriginData>& origins, std::function<void ()> completionHandler) { uint64_t callbackID = generateDeleteCallbackID(); auto addResult = m_deleteDatabaseCompletionHandlers.add(callbackID, WTFMove(completionHandler)); ASSERT_UNUSED(addResult, addResult.isNewEntry); HashSet<UniqueIDBDatabase*> openDatabases; for (auto* connection : m_databaseConnections.values()) { const auto& identifier = connection->database().identifier(); for (auto& origin : origins) { if (identifier.isRelatedToOrigin(origin)) { openDatabases.add(&connection->database()); break; } } } for (auto* database : openDatabases) database->immediateCloseForUserDelete(); postDatabaseTask(createCrossThreadTask(*this, &IDBServer::performCloseAndDeleteDatabasesForOrigins, origins, callbackID)); }
void DatabaseProcess::deleteWebsiteDataForOrigins(WebCore::SessionID, uint64_t websiteDataTypes, const Vector<SecurityOriginData>& securityOriginDatas, uint64_t callbackID) { struct CallbackAggregator final : public ThreadSafeRefCounted<CallbackAggregator> { explicit CallbackAggregator(std::function<void ()> completionHandler) : m_completionHandler(WTFMove(completionHandler)) { } ~CallbackAggregator() { ASSERT(RunLoop::isMain()); RunLoop::main().dispatch(WTFMove(m_completionHandler)); } std::function<void ()> m_completionHandler; }; RefPtr<CallbackAggregator> callbackAggregator = adoptRef(new CallbackAggregator([this, callbackID]() { parentProcessConnection()->send(Messages::DatabaseProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0); })); #if ENABLE(INDEXED_DATABASE) if (websiteDataTypes & WebsiteDataTypeIndexedDBDatabases) { Vector<RefPtr<WebCore::SecurityOrigin>> securityOrigins; for (const auto& securityOriginData : securityOriginDatas) securityOrigins.append(securityOriginData.securityOrigin()); postDatabaseTask(std::make_unique<CrossThreadTask>([this, securityOrigins, callbackAggregator] { deleteIndexedDatabaseEntriesForOrigins(securityOrigins); RunLoop::main().dispatch([callbackAggregator] { }); })); } #endif }
void DatabaseProcess::ensureIndexedDatabaseRelativePathExists(const String& relativePath) { postDatabaseTask(createAsyncTask(*this, &DatabaseProcess::ensurePathExists, absoluteIndexedDatabasePathFromDatabaseRelativePath(relativePath))); }
void IDBServer::getAllDatabaseNames(uint64_t serverConnectionIdentifier, const SecurityOriginData& mainFrameOrigin, const SecurityOriginData& openingOrigin, uint64_t callbackID) { postDatabaseTask(createCrossThreadTask(*this, &IDBServer::performGetAllDatabaseNames, serverConnectionIdentifier, mainFrameOrigin, openingOrigin, callbackID)); }