Title: [278916] trunk/Source/WebKit
Revision
278916
Author
cdu...@apple.com
Date
2021-06-15 17:56:03 -0700 (Tue, 15 Jun 2021)

Log Message

Use more SQL transactions in ResourceLoadStatisticsDatabaseStore
https://bugs.webkit.org/show_bug.cgi?id=227034

Reviewed by Kate Cheney.

Use more SQL transactions in ResourceLoadStatisticsDatabaseStore, for performance.

I updated the code so that we start a SQL transaction whenever we do more than one
consecutive "write" statement.

* NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp:
(WebKit::ResourceLoadStatisticsDatabaseStore::addMissingColumnsToTable):
(WebKit::ResourceLoadStatisticsDatabaseStore::addMissingTablesIfNecessary):
(WebKit::ResourceLoadStatisticsDatabaseStore::populateFromMemoryStore):
(WebKit::ResourceLoadStatisticsDatabaseStore::mergeStatistics):
(WebKit::ResourceLoadStatisticsDatabaseStore::reclassifyResources):
(WebKit::ResourceLoadStatisticsDatabaseStore::grandfatherDataForDomains):
(WebKit::ResourceLoadStatisticsDatabaseStore::insertExpiredStatisticForTesting):

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (278915 => 278916)


--- trunk/Source/WebKit/ChangeLog	2021-06-16 00:46:26 UTC (rev 278915)
+++ trunk/Source/WebKit/ChangeLog	2021-06-16 00:56:03 UTC (rev 278916)
@@ -1,5 +1,26 @@
 2021-06-15  Chris Dumez  <cdu...@apple.com>
 
+        Use more SQL transactions in ResourceLoadStatisticsDatabaseStore
+        https://bugs.webkit.org/show_bug.cgi?id=227034
+
+        Reviewed by Kate Cheney.
+
+        Use more SQL transactions in ResourceLoadStatisticsDatabaseStore, for performance.
+
+        I updated the code so that we start a SQL transaction whenever we do more than one
+        consecutive "write" statement.
+
+        * NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp:
+        (WebKit::ResourceLoadStatisticsDatabaseStore::addMissingColumnsToTable):
+        (WebKit::ResourceLoadStatisticsDatabaseStore::addMissingTablesIfNecessary):
+        (WebKit::ResourceLoadStatisticsDatabaseStore::populateFromMemoryStore):
+        (WebKit::ResourceLoadStatisticsDatabaseStore::mergeStatistics):
+        (WebKit::ResourceLoadStatisticsDatabaseStore::reclassifyResources):
+        (WebKit::ResourceLoadStatisticsDatabaseStore::grandfatherDataForDomains):
+        (WebKit::ResourceLoadStatisticsDatabaseStore::insertExpiredStatisticForTesting):
+
+2021-06-15  Chris Dumez  <cdu...@apple.com>
+
         Reloading the view should be able to recover if the GPUProcess or NetworkProcess are hung
         https://bugs.webkit.org/show_bug.cgi?id=227051
 

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp (278915 => 278916)


--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp	2021-06-16 00:46:26 UTC (rev 278915)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp	2021-06-16 00:56:03 UTC (rev 278916)
@@ -51,6 +51,7 @@
 #include <wtf/DateMath.h>
 #include <wtf/MathExtras.h>
 #include <wtf/RobinHoodHashMap.h>
+#include <wtf/Scope.h>
 #include <wtf/StdSet.h>
 #include <wtf/text/StringBuilder.h>
 
@@ -627,10 +628,14 @@
 {
     ASSERT(existingColumns.size() <= expectedColumns.size());
 
+    SQLiteTransaction transaction(m_database);
     for (auto& column : expectedColumns) {
         if (existingColumns.contains(column))
             continue;
         
+        if (!transaction.inProgress())
+            transaction.begin();
+
         auto statement = m_database.prepareStatementSlow(makeString("ALTER TABLE ", tableName, " ADD COLUMN ", column));
         if (!statement) {
             RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::addMissingColumnsToTable Unable to prepare statement to add missing columns to table, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
@@ -644,6 +649,7 @@
         }
         statement->reset();
     }
+    transaction.commit();
 }
 
 void ResourceLoadStatisticsDatabaseStore::addMissingColumnsIfNecessary()
@@ -700,6 +706,8 @@
     if (!missingTables)
         return;
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
     for (auto& table : *missingTables) {
         auto createTableQuery = expectedTableAndIndexQueries().get(table).first;
         if (!m_database.executeCommandSlow(createTableQuery))
@@ -711,6 +719,7 @@
         ASSERT_NOT_REACHED();
         return;
     }
+    transaction.commit();
 }
 
 void ResourceLoadStatisticsDatabaseStore::openAndUpdateSchemaIfNecessary()
@@ -1027,8 +1036,10 @@
     return scopedStatement->columnInt(0);
 }
 
-String ResourceLoadStatisticsDatabaseStore::ensureAndMakeDomainList(const HashSet<RegistrableDomain>& domainList)
+String ResourceLoadStatisticsDatabaseStore::ensureAndMakeDomainList(const SQLiteTransaction&, const HashSet<RegistrableDomain>& domainList)
 {
+    ASSERT(m_database.transactionInProgress());
+
     StringBuilder builder;
     for (auto& topFrameResource : domainList) {
         // Insert query will fail if top frame domain is not already in the database
@@ -1038,9 +1049,9 @@
     return builder.toString();
 }
 
-void ResourceLoadStatisticsDatabaseStore::insertDomainRelationshipList(const String& statement, const HashSet<RegistrableDomain>& domainList, unsigned domainID)
+void ResourceLoadStatisticsDatabaseStore::insertDomainRelationshipList(const SQLiteTransaction& transaction, const String& statement, const HashSet<RegistrableDomain>& domainList, unsigned domainID)
 {
-    auto insertRelationshipStatement = m_database.prepareStatementSlow(makeString(statement, ensureAndMakeDomainList(domainList), " );"));
+    auto insertRelationshipStatement = m_database.prepareStatementSlow(makeString(statement, ensureAndMakeDomainList(transaction, domainList), " );"));
     
     if (!insertRelationshipStatement
         || insertRelationshipStatement->bindInt(1, domainID) != SQLITE_OK) {
@@ -1063,24 +1074,26 @@
     }
 }
 
-void ResourceLoadStatisticsDatabaseStore::insertDomainRelationships(const ResourceLoadStatistics& loadStatistics)
+void ResourceLoadStatisticsDatabaseStore::insertDomainRelationships(const SQLiteTransaction& transaction, const ResourceLoadStatistics& loadStatistics)
 {
     ASSERT(!RunLoop::isMain());
+    ASSERT(m_database.transactionInProgress());
+
     auto registrableDomainID = domainID(loadStatistics.registrableDomain);
     
     if (!registrableDomainID)
         return;
 
-    insertDomainRelationshipList(storageAccessUnderTopFrameDomainsQuery, loadStatistics.storageAccessUnderTopFrameDomains, registrableDomainID.value());
-    insertDomainRelationshipList(topFrameUniqueRedirectsToQuery, loadStatistics.topFrameUniqueRedirectsTo, registrableDomainID.value());
-    insertDomainRelationshipList(topFrameUniqueRedirectsToSinceSameSiteStrictEnforcementQuery, loadStatistics.topFrameUniqueRedirectsToSinceSameSiteStrictEnforcement, registrableDomainID.value());
-    insertDomainRelationshipList(topFrameUniqueRedirectsFromQuery, loadStatistics.topFrameUniqueRedirectsFrom, registrableDomainID.value());
-    insertDomainRelationshipList(subframeUnderTopFrameDomainsQuery, loadStatistics.subframeUnderTopFrameDomains, registrableDomainID.value());
-    insertDomainRelationshipList(subresourceUnderTopFrameDomainsQuery, loadStatistics.subresourceUnderTopFrameDomains, registrableDomainID.value());
-    insertDomainRelationshipList(subresourceUniqueRedirectsToQuery, loadStatistics.subresourceUniqueRedirectsTo, registrableDomainID.value());
-    insertDomainRelationshipList(subresourceUniqueRedirectsFromQuery, loadStatistics.subresourceUniqueRedirectsFrom, registrableDomainID.value());
-    insertDomainRelationshipList(topFrameLinkDecorationsFromQuery, loadStatistics.topFrameLinkDecorationsFrom, registrableDomainID.value());
-    insertDomainRelationshipList(topFrameLoadedThirdPartyScriptsQuery, loadStatistics.topFrameLoadedThirdPartyScripts, registrableDomainID.value());
+    insertDomainRelationshipList(transaction, storageAccessUnderTopFrameDomainsQuery, loadStatistics.storageAccessUnderTopFrameDomains, registrableDomainID.value());
+    insertDomainRelationshipList(transaction, topFrameUniqueRedirectsToQuery, loadStatistics.topFrameUniqueRedirectsTo, registrableDomainID.value());
+    insertDomainRelationshipList(transaction, topFrameUniqueRedirectsToSinceSameSiteStrictEnforcementQuery, loadStatistics.topFrameUniqueRedirectsToSinceSameSiteStrictEnforcement, registrableDomainID.value());
+    insertDomainRelationshipList(transaction, topFrameUniqueRedirectsFromQuery, loadStatistics.topFrameUniqueRedirectsFrom, registrableDomainID.value());
+    insertDomainRelationshipList(transaction, subframeUnderTopFrameDomainsQuery, loadStatistics.subframeUnderTopFrameDomains, registrableDomainID.value());
+    insertDomainRelationshipList(transaction, subresourceUnderTopFrameDomainsQuery, loadStatistics.subresourceUnderTopFrameDomains, registrableDomainID.value());
+    insertDomainRelationshipList(transaction, subresourceUniqueRedirectsToQuery, loadStatistics.subresourceUniqueRedirectsTo, registrableDomainID.value());
+    insertDomainRelationshipList(transaction, subresourceUniqueRedirectsFromQuery, loadStatistics.subresourceUniqueRedirectsFrom, registrableDomainID.value());
+    insertDomainRelationshipList(transaction, topFrameLinkDecorationsFromQuery, loadStatistics.topFrameLinkDecorationsFrom, registrableDomainID.value());
+    insertDomainRelationshipList(transaction, topFrameLoadedThirdPartyScriptsQuery, loadStatistics.topFrameLoadedThirdPartyScripts, registrableDomainID.value());
 }
 
 void ResourceLoadStatisticsDatabaseStore::populateFromMemoryStore(const ResourceLoadStatisticsMemoryStore& memoryStore)
@@ -1090,6 +1103,9 @@
     if (!isEmpty())
         return;
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     auto& statisticsMap = memoryStore.data();
     for (const auto& statistic : statisticsMap.values()) {
         auto result = insertObservedDomain(statistic);
@@ -1103,12 +1119,15 @@
     // Make a separate pass for inter-domain relationships so we
     // can refer to the ObservedDomain table entries
     for (auto& statistic : statisticsMap.values())
-        insertDomainRelationships(statistic);
+        insertDomainRelationships(transaction, statistic);
+
+    transaction.commit();
 }
 
-void ResourceLoadStatisticsDatabaseStore::merge(WebCore::SQLiteStatement* current, const ResourceLoadStatistics& other)
+void ResourceLoadStatisticsDatabaseStore::merge(const SQLiteTransaction& transaction, WebCore::SQLiteStatement* current, const ResourceLoadStatistics& other)
 {
     ASSERT(!RunLoop::isMain());
+    ASSERT(m_database.transactionInProgress());
 
     auto currentRegistrableDomain = current->columnText(RegistrableDomainIndex);
     auto currentLastSeen = current->columnDouble(LastSeenIndex);
@@ -1132,18 +1151,18 @@
         setUserInteraction(other.registrableDomain, true, std::max(WallTime::fromRawSeconds(currentMostRecentUserInteraction), other.mostRecentUserInteractionTime));
 
     if (other.grandfathered && !currentGrandfathered)
-        setGrandfathered(other.registrableDomain, true);
+        setGrandfathered(transaction, other.registrableDomain, true);
     if (other.isPrevalentResource && !currentIsPrevalent)
-        setPrevalentResource(other.registrableDomain);
+        setPrevalentResource(transaction, other.registrableDomain);
     if (other.isVeryPrevalentResource && !currentIsVeryPrevalent)
-        setVeryPrevalentResource(other.registrableDomain);
+        setVeryPrevalentResource(transaction, other.registrableDomain);
     if (other.dataRecordsRemoved > currentDataRecordsRemoved)
         updateDataRecordsRemoved(other.registrableDomain, other.dataRecordsRemoved);
     if (other.gotLinkDecorationFromPrevalentResource && !currentIsScheduledForAllButCookieDataRemoval)
-        setIsScheduledForAllButCookieDataRemoval(other.registrableDomain, true);
+        setIsScheduledForAllButCookieDataRemoval(transaction, other.registrableDomain, true);
 }
 
-void ResourceLoadStatisticsDatabaseStore::mergeStatistic(const ResourceLoadStatistics& statistic)
+void ResourceLoadStatisticsDatabaseStore::mergeStatistic(const SQLiteTransaction& transaction, const ResourceLoadStatistics& statistic)
 {
     ASSERT(!RunLoop::isMain());
 
@@ -1156,13 +1175,18 @@
         return;
     }
 
-    merge(scopedStatement.get(), statistic);
+    merge(transaction, scopedStatement.get(), statistic);
 }
 
 void ResourceLoadStatisticsDatabaseStore::mergeStatistics(Vector<ResourceLoadStatistics>&& statistics)
 {
     ASSERT(!RunLoop::isMain());
+    if (statistics.isEmpty())
+        return;
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     for (auto& statistic : statistics) {
         if (!domainID(statistic.registrableDomain)) {
             auto result = insertObservedDomain(statistic);
@@ -1172,13 +1196,15 @@
                 return;
             }
         } else
-            mergeStatistic(statistic);
+            mergeStatistic(transaction, statistic);
     }
 
     // Make a separate pass for inter-domain relationships so we
     // can refer to the ObservedDomain table entries.
     for (auto& statistic : statistics)
-        insertDomainRelationships(statistic);
+        insertDomainRelationships(transaction, statistic);
+
+    transaction.commit();
 }
 
 static ASCIILiteral joinSubStatisticsForSorting()
@@ -1419,15 +1445,22 @@
     ASSERT(!RunLoop::isMain());
 
     auto notVeryPrevalentResources = findNotVeryPrevalentResources();
+    if (notVeryPrevalentResources.isEmpty())
+        return;
 
+    SQLiteTransaction transaction(m_database);
     for (auto& resourceStatistic : notVeryPrevalentResources.values()) {
         if (shouldSkip(resourceStatistic.registrableDomain))
             continue;
 
         auto newPrevalence = classifier().calculateResourcePrevalence(resourceStatistic.subresourceUnderTopFrameDomainsCount, resourceStatistic.subresourceUniqueRedirectsToCount, resourceStatistic.subframeUnderTopFrameDomainsCount, resourceStatistic.topFrameUniqueRedirectsToCount, resourceStatistic.prevalence);
-        if (newPrevalence != resourceStatistic.prevalence)
-            setPrevalentResource(resourceStatistic.registrableDomain, newPrevalence);
+        if (newPrevalence != resourceStatistic.prevalence) {
+            if (!transaction.inProgress())
+                transaction.begin();
+            setPrevalentResource(transaction, resourceStatistic.registrableDomain, newPrevalence);
+        }
     }
+    transaction.commit();
 }
 
 void ResourceLoadStatisticsDatabaseStore::classifyPrevalentResources()
@@ -1534,6 +1567,9 @@
         }
     }
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     auto incrementStorageAccess = m_database.prepareStatement("UPDATE ObservedDomains SET timesAccessedAsFirstPartyDueToStorageAccessAPI = timesAccessedAsFirstPartyDueToStorageAccessAPI + 1 WHERE domainID = ?"_s);
     if (!incrementStorageAccess
         || incrementStorageAccess->bindInt(1, *subFrameStatus.second) != SQLITE_OK
@@ -1543,9 +1579,11 @@
         return;
     }
     
-    grantStorageAccessInternal(WTFMove(subFrameDomain), WTFMove(topFrameDomain), frameID, pageID, userWasPromptedEarlier, scope, [completionHandler = WTFMove(completionHandler)] (StorageAccessWasGranted wasGranted) mutable {
+    grantStorageAccessInternal(transaction, WTFMove(subFrameDomain), WTFMove(topFrameDomain), frameID, pageID, userWasPromptedEarlier, scope, [completionHandler = WTFMove(completionHandler)] (StorageAccessWasGranted wasGranted) mutable {
         completionHandler(wasGranted == StorageAccessWasGranted::Yes ? StorageAccessStatus::HasAccess : StorageAccessStatus::CannotRequestAccess);
     });
+
+    transaction.commit();
 }
 
 void ResourceLoadStatisticsDatabaseStore::requestStorageAccessUnderOpener(DomainInNeedOfStorageAccess&& domainInNeedOfStorageAccess, PageIdentifier openerPageID, OpenerDomain&& openerDomain)
@@ -1561,7 +1599,10 @@
         debugBroadcastConsoleMessage(MessageSource::ITPDebug, MessageLevel::Info, makeString("[ITP] Storage access was granted for '"_s, domainInNeedOfStorageAccess.string(), "' under opener page from '"_s, openerDomain.string(), "', with user interaction in the opened window."_s));
     }
 
-    grantStorageAccessInternal(WTFMove(domainInNeedOfStorageAccess), WTFMove(openerDomain), std::nullopt, openerPageID, StorageAccessPromptWasShown::No, StorageAccessScope::PerPage, [](StorageAccessWasGranted) { });
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+    grantStorageAccessInternal(transaction, WTFMove(domainInNeedOfStorageAccess), WTFMove(openerDomain), std::nullopt, openerPageID, StorageAccessPromptWasShown::No, StorageAccessScope::PerPage, [](StorageAccessWasGranted) { });
+    transaction.commit();
 }
 
 void ResourceLoadStatisticsDatabaseStore::grantStorageAccess(SubFrameDomain&& subFrameDomain, TopFrameDomain&& topFrameDomain, FrameIdentifier frameID, PageIdentifier pageID, StorageAccessPromptWasShown promptWasShown, StorageAccessScope scope, CompletionHandler<void(StorageAccessWasGranted)>&& completionHandler)
@@ -1568,6 +1609,9 @@
 {
     ASSERT(!RunLoop::isMain());
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     if (promptWasShown == StorageAccessPromptWasShown::Yes) {
         auto subFrameStatus = ensureResourceStatisticsForRegistrableDomain(subFrameDomain);
         if (!subFrameStatus.second) {
@@ -1579,15 +1623,18 @@
         if (!NetworkStorageSession::canRequestStorageAccessForLoginOrCompatibilityPurposesWithoutPriorUserInteraction(subFrameDomain, topFrameDomain))
             ASSERT(hasHadUserInteraction(subFrameDomain, OperatingDatesWindow::Long));
 #endif
-        insertDomainRelationshipList(storageAccessUnderTopFrameDomainsQuery, HashSet<RegistrableDomain>({ topFrameDomain }), *subFrameStatus.second);
+        insertDomainRelationshipList(transaction, storageAccessUnderTopFrameDomainsQuery, HashSet<RegistrableDomain>({ topFrameDomain }), *subFrameStatus.second);
     }
 
-    grantStorageAccessInternal(WTFMove(subFrameDomain), WTFMove(topFrameDomain), frameID, pageID, promptWasShown, scope, WTFMove(completionHandler));
+    grantStorageAccessInternal(transaction, WTFMove(subFrameDomain), WTFMove(topFrameDomain), frameID, pageID, promptWasShown, scope, WTFMove(completionHandler));
+
+    transaction.commit();
 }
 
-void ResourceLoadStatisticsDatabaseStore::grantStorageAccessInternal(SubFrameDomain&& subFrameDomain, TopFrameDomain&& topFrameDomain, std::optional<FrameIdentifier> frameID, PageIdentifier pageID, StorageAccessPromptWasShown promptWasShownNowOrEarlier, StorageAccessScope scope, CompletionHandler<void(StorageAccessWasGranted)>&& completionHandler)
+void ResourceLoadStatisticsDatabaseStore::grantStorageAccessInternal(const SQLiteTransaction& transaction, SubFrameDomain&& subFrameDomain, TopFrameDomain&& topFrameDomain, std::optional<FrameIdentifier> frameID, PageIdentifier pageID, StorageAccessPromptWasShown promptWasShownNowOrEarlier, StorageAccessScope scope, CompletionHandler<void(StorageAccessWasGranted)>&& completionHandler)
 {
     ASSERT(!RunLoop::isMain());
+    ASSERT(m_database.transactionInProgress());
 
     if (subFrameDomain == topFrameDomain) {
         completionHandler(StorageAccessWasGranted::Yes);
@@ -1624,7 +1671,11 @@
 void ResourceLoadStatisticsDatabaseStore::grandfatherDataForDomains(const HashSet<RegistrableDomain>& domains)
 {
     ASSERT(!RunLoop::isMain());
+    if (domains.isEmpty())
+        return;
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
     for (auto& registrableDomain : domains) {
         auto result = ensureResourceStatisticsForRegistrableDomain(registrableDomain);
         if (!result.second)
@@ -1636,6 +1687,7 @@
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::grandfatherDataForDomains failed, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
         ASSERT_NOT_REACHED();
     }
+    transaction.commit();
 }
 
 Vector<RegistrableDomain> ResourceLoadStatisticsDatabaseStore::ensurePrevalentResourcesForDebugMode()
@@ -1648,6 +1700,9 @@
     Vector<RegistrableDomain> primaryDomainsToBlock;
     primaryDomainsToBlock.reserveInitialCapacity(2);
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     auto result = ensureResourceStatisticsForRegistrableDomain(debugStaticPrevalentResource());
     if (!result.second) {
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::ensurePrevalentResourcesForDebugMode was not completed due to failed insert attempt for debugStaticPrevalentResource", this);
@@ -1654,7 +1709,7 @@
         return { };
     }
 
-    setPrevalentResource(debugStaticPrevalentResource(), ResourceLoadPrevalence::High);
+    setPrevalentResource(transaction, debugStaticPrevalentResource(), ResourceLoadPrevalence::High);
     primaryDomainsToBlock.uncheckedAppend(debugStaticPrevalentResource());
 
     if (!debugManualPrevalentResource().isEmpty()) {
@@ -1663,7 +1718,7 @@
             RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::ensurePrevalentResourcesForDebugMode was not completed due to failed insert attempt for debugManualPrevalentResource", this);
             return { };
         }
-        setPrevalentResource(debugManualPrevalentResource(), ResourceLoadPrevalence::High);
+        setPrevalentResource(transaction, debugManualPrevalentResource(), ResourceLoadPrevalence::High);
         primaryDomainsToBlock.uncheckedAppend(debugManualPrevalentResource());
 
         if (debugLoggingEnabled()) {
@@ -1672,6 +1727,8 @@
         }
     }
 
+    transaction.commit();
+
     return primaryDomainsToBlock;
 }
 
@@ -1682,8 +1739,13 @@
     bool areTargetAndTopFrameDomainsSameSite = targetDomain == topFrameDomain;
     bool areTargetAndSourceDomainsSameSite = targetDomain == sourceDomain;
 
+    SQLiteTransaction transaction(m_database);
+
     bool statisticsWereUpdated = false;
     if (!isMainFrame && !(areTargetAndTopFrameDomainsSameSite || areTargetAndSourceDomainsSameSite)) {
+        if (!transaction.inProgress())
+            transaction.begin();
+
         auto targetResult = ensureResourceStatisticsForRegistrableDomain(targetDomain);
         if (!targetResult.second) {
             RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::logFrameNavigation was not completed due to failed insert attempt of target domain", this);
@@ -1690,7 +1752,7 @@
             return;
         }
         updateLastSeen(targetDomain, ResourceLoadStatistics::reduceTimeResolution(WallTime::now()));
-        insertDomainRelationshipList(subframeUnderTopFrameDomainsQuery, HashSet<RegistrableDomain>({ topFrameDomain }), *targetResult.second);
+        insertDomainRelationshipList(transaction, subframeUnderTopFrameDomainsQuery, HashSet<RegistrableDomain>({ topFrameDomain }), *targetResult.second);
         statisticsWereUpdated = true;
     }
 
@@ -1698,6 +1760,9 @@
         if (isMainFrame) {
             bool wasNavigatedAfterShortDelayWithoutUserInteraction = !wasPotentiallyInitiatedByUser && delayAfterMainFrameDocumentLoad < parameters().minDelayAfterMainFrameDocumentLoadToNotBeARedirect;
             if (isRedirect || wasNavigatedAfterShortDelayWithoutUserInteraction) {
+                if (!transaction.inProgress())
+                    transaction.begin();
+
                 auto redirectingDomainResult = ensureResourceStatisticsForRegistrableDomain(sourceDomain);
                 auto targetResult = ensureResourceStatisticsForRegistrableDomain(targetDomain);
                 if (!targetResult.second || !redirectingDomainResult.second) {
@@ -1704,9 +1769,9 @@
                     RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::logFrameNavigation was not completed due to failed insert attempt of target or redirecting domain (isMainFrame)", this);
                     return;
                 }
-                insertDomainRelationshipList(topFrameUniqueRedirectsToQuery, HashSet<RegistrableDomain>({ targetDomain }), *redirectingDomainResult.second);
+                insertDomainRelationshipList(transaction, topFrameUniqueRedirectsToQuery, HashSet<RegistrableDomain>({ targetDomain }), *redirectingDomainResult.second);
                 if (isRedirect) {
-                    insertDomainRelationshipList(topFrameUniqueRedirectsToSinceSameSiteStrictEnforcementQuery, HashSet<RegistrableDomain>({ targetDomain }), *redirectingDomainResult.second);
+                    insertDomainRelationshipList(transaction, topFrameUniqueRedirectsToSinceSameSiteStrictEnforcementQuery, HashSet<RegistrableDomain>({ targetDomain }), *redirectingDomainResult.second);
 
                     if (UNLIKELY(debugLoggingEnabled())) {
                         RELEASE_LOG_INFO(ITPDebug, "Did set %" PUBLIC_LOG_STRING " as making a top frame redirect to %" PUBLIC_LOG_STRING ".", sourceDomain.string().utf8().data(), targetDomain.string().utf8().data());
@@ -1713,10 +1778,13 @@
                         debugBroadcastConsoleMessage(MessageSource::ITPDebug, MessageLevel::Info, makeString("Did set '", sourceDomain.string(), "' as making a top frame redirect to '", targetDomain.string(), "'."));
                     }
                 }
-                insertDomainRelationshipList(topFrameUniqueRedirectsFromQuery, HashSet<RegistrableDomain>({ sourceDomain }), *targetResult.second);
+                insertDomainRelationshipList(transaction, topFrameUniqueRedirectsFromQuery, HashSet<RegistrableDomain>({ sourceDomain }), *targetResult.second);
                 statisticsWereUpdated = true;
             }
         } else if (isRedirect) {
+            if (!transaction.inProgress())
+                transaction.begin();
+
             auto redirectingDomainResult = ensureResourceStatisticsForRegistrableDomain(sourceDomain);
             auto targetResult = ensureResourceStatisticsForRegistrableDomain(targetDomain);
             if (!targetResult.second || !redirectingDomainResult.second) {
@@ -1723,11 +1791,12 @@
                 RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::logFrameNavigation was not completed due to failed insert attempt of target or redirecting domain (isRedirect)", this);
                 return;
             }
-            insertDomainRelationshipList(subresourceUniqueRedirectsToQuery, HashSet<RegistrableDomain>({ targetDomain }), *redirectingDomainResult.second);
-            insertDomainRelationshipList(subresourceUniqueRedirectsFromQuery, HashSet<RegistrableDomain>({ sourceDomain }), *targetResult.second);
+            insertDomainRelationshipList(transaction, subresourceUniqueRedirectsToQuery, HashSet<RegistrableDomain>({ targetDomain }), *redirectingDomainResult.second);
+            insertDomainRelationshipList(transaction, subresourceUniqueRedirectsFromQuery, HashSet<RegistrableDomain>({ sourceDomain }), *targetResult.second);
             statisticsWereUpdated = true;
         }
     }
+    transaction.commit();
 
     if (statisticsWereUpdated)
         scheduleStatisticsProcessingRequestIfNecessary();
@@ -1738,15 +1807,20 @@
     ASSERT(!RunLoop::isMain());
     ASSERT(fromDomain != toDomain);
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     auto toDomainResult = ensureResourceStatisticsForRegistrableDomain(toDomain);
     if (!toDomainResult.second) {
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::logCrossSiteLoadWithLinkDecoration was not completed due to failed insert attempt", this);
         return;
     }
-    insertDomainRelationshipList(topFrameLinkDecorationsFromQuery, HashSet<RegistrableDomain>({ fromDomain }), *toDomainResult.second);
+    insertDomainRelationshipList(transaction, topFrameLinkDecorationsFromQuery, HashSet<RegistrableDomain>({ fromDomain }), *toDomainResult.second);
     
     if (isPrevalentResource(fromDomain))
-        setIsScheduledForAllButCookieDataRemoval(toDomain, true);
+        setIsScheduledForAllButCookieDataRemoval(transaction, toDomain, true);
+
+    transaction.commit();
 }
 
 void ResourceLoadStatisticsDatabaseStore::clearTopFrameUniqueRedirectsToSinceSameSiteStrictEnforcement(const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
@@ -1753,6 +1827,9 @@
 {
     ASSERT(!RunLoop::isMain());
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     auto targetResult = ensureResourceStatisticsForRegistrableDomain(domain);
     if (!targetResult.second) {
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::clearTopFrameUniqueRedirectsToSinceSameSiteStrictEnforcement was not completed due to failed insert attempt", this);
@@ -1767,6 +1844,8 @@
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::clearTopFrameUniqueRedirectsToSinceSameSiteStrictEnforcement failed to bind, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
         ASSERT_NOT_REACHED();
     }
+
+    transaction.commit();
     
     completionHandler();
 }
@@ -1791,6 +1870,9 @@
 {
     ASSERT(!RunLoop::isMain());
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     auto result = ensureResourceStatisticsForRegistrableDomain(domain);
     if (!result.second) {
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::logUserInteraction was not completed due to failed insert attempt", this);
@@ -1798,6 +1880,9 @@
     }
     bool didHavePreviousUserInteraction = hasHadUserInteraction(domain, OperatingDatesWindow::Long);
     setUserInteraction(domain, true, WallTime::now());
+
+    transaction.commit();
+
     if (didHavePreviousUserInteraction) {
         completionHandler();
         return;
@@ -1809,6 +1894,9 @@
 {
     ASSERT(!RunLoop::isMain());
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     auto targetResult = ensureResourceStatisticsForRegistrableDomain(domain);
     if (!targetResult.second) {
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::clearUserInteraction was not completed due to failed insert attempt", this);
@@ -1824,6 +1912,8 @@
         ASSERT_NOT_REACHED();
     }
 
+    transaction.commit();
+
     // Update cookie blocking unconditionally since a call to hasHadUserInteraction()
     // to check the previous user interaction status could call clearUserInteraction(),
     // blowing the call stack.
@@ -1858,9 +1948,11 @@
     return hadUserInteraction;
 }
 
-void ResourceLoadStatisticsDatabaseStore::setPrevalentResource(const RegistrableDomain& domain, ResourceLoadPrevalence newPrevalence)
+void ResourceLoadStatisticsDatabaseStore::setPrevalentResource(const SQLiteTransaction&, const RegistrableDomain& domain, ResourceLoadPrevalence newPrevalence)
 {
     ASSERT(!RunLoop::isMain());
+    ASSERT(m_database.transactionInProgress());
+
     if (shouldSkip(domain))
         return;
 
@@ -2006,6 +2098,9 @@
 {
     ASSERT(!RunLoop::isMain());
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     auto result = ensureResourceStatisticsForRegistrableDomain(domain);
     if (!result.second) {
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::clearPrevalentResource was not completed due to failed insert attempt", this);
@@ -2021,11 +2116,24 @@
         ASSERT_NOT_REACHED();
         return;
     }
+
+    transaction.commit();
 }
 
 void ResourceLoadStatisticsDatabaseStore::setGrandfathered(const RegistrableDomain& domain, bool value)
 {
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
+    setGrandfathered(transaction, domain, value);
+
+    transaction.commit();
+}
+
+void ResourceLoadStatisticsDatabaseStore::setGrandfathered(const WebCore::SQLiteTransaction&, const RegistrableDomain& domain, bool value)
+{
     ASSERT(!RunLoop::isMain());
+    ASSERT(m_database.transactionInProgress());
 
     auto result = ensureResourceStatisticsForRegistrableDomain(domain);
     if (!result.second) {
@@ -2043,9 +2151,10 @@
     }
 }
 
-void ResourceLoadStatisticsDatabaseStore::setIsScheduledForAllButCookieDataRemoval(const RegistrableDomain& domain, bool value)
+void ResourceLoadStatisticsDatabaseStore::setIsScheduledForAllButCookieDataRemoval(const SQLiteTransaction&, const RegistrableDomain& domain, bool value)
 {
     ASSERT(!RunLoop::isMain());
+    ASSERT(m_database.transactionInProgress());
 
     auto result = ensureResourceStatisticsForRegistrableDomain(domain);
     if (!result.second) {
@@ -2105,6 +2214,9 @@
 {
     ASSERT(!RunLoop::isMain());
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     auto result = ensureResourceStatisticsForRegistrableDomain(subFrameDomain);
     if (!result.second) {
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::setSubframeUnderTopFrameDomain was not completed due to failed insert attempt", this);
@@ -2111,7 +2223,9 @@
         return;
     }
     // For consistency, make sure we also have a statistics entry for the top frame domain.
-    insertDomainRelationshipList(subframeUnderTopFrameDomainsQuery, HashSet<RegistrableDomain>({ topFrameDomain }), *result.second);
+    insertDomainRelationshipList(transaction, subframeUnderTopFrameDomainsQuery, HashSet<RegistrableDomain>({ topFrameDomain }), *result.second);
+
+    transaction.commit();
 }
 
 void ResourceLoadStatisticsDatabaseStore::setSubresourceUnderTopFrameDomain(const SubResourceDomain& subresourceDomain, const TopFrameDomain& topFrameDomain)
@@ -2118,6 +2232,9 @@
 {
     ASSERT(!RunLoop::isMain());
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     auto result = ensureResourceStatisticsForRegistrableDomain(subresourceDomain);
     if (!result.second) {
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::setSubresourceUnderTopFrameDomain was not completed due to failed insert attempt", this);
@@ -2124,7 +2241,9 @@
         return;
     }
     // For consistency, make sure we also have a statistics entry for the top frame domain.
-    insertDomainRelationshipList(subresourceUnderTopFrameDomainsQuery, HashSet<RegistrableDomain>({ topFrameDomain }), *result.second);
+    insertDomainRelationshipList(transaction, subresourceUnderTopFrameDomainsQuery, HashSet<RegistrableDomain>({ topFrameDomain }), *result.second);
+
+    transaction.commit();
 }
 
 void ResourceLoadStatisticsDatabaseStore::setSubresourceUniqueRedirectTo(const SubResourceDomain& subresourceDomain, const RedirectDomain& redirectDomain)
@@ -2131,6 +2250,9 @@
 {
     ASSERT(!RunLoop::isMain());
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     auto result = ensureResourceStatisticsForRegistrableDomain(subresourceDomain);
     if (!result.second) {
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::setSubresourceUniqueRedirectTo was not completed due to failed insert attempt", this);
@@ -2137,7 +2259,9 @@
         return;
     }
     // For consistency, make sure we also have a statistics entry for the redirect domain.
-    insertDomainRelationshipList(subresourceUniqueRedirectsToQuery, HashSet<RegistrableDomain>({ redirectDomain }), *result.second);
+    insertDomainRelationshipList(transaction, subresourceUniqueRedirectsToQuery, HashSet<RegistrableDomain>({ redirectDomain }), *result.second);
+
+    transaction.commit();
 }
 
 void ResourceLoadStatisticsDatabaseStore::setSubresourceUniqueRedirectFrom(const SubResourceDomain& subresourceDomain, const RedirectDomain& redirectDomain)
@@ -2144,6 +2268,9 @@
 {
     ASSERT(!RunLoop::isMain());
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     auto result = ensureResourceStatisticsForRegistrableDomain(subresourceDomain);
     if (!result.second) {
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::setSubresourceUniqueRedirectFrom was not completed due to failed insert attempt", this);
@@ -2150,7 +2277,9 @@
         return;
     }
     // For consistency, make sure we also have a statistics entry for the redirect domain.
-    insertDomainRelationshipList(subresourceUniqueRedirectsFromQuery, HashSet<RegistrableDomain>({ redirectDomain }), *result.second);
+    insertDomainRelationshipList(transaction, subresourceUniqueRedirectsFromQuery, HashSet<RegistrableDomain>({ redirectDomain }), *result.second);
+
+    transaction.commit();
 }
 
 void ResourceLoadStatisticsDatabaseStore::setTopFrameUniqueRedirectTo(const TopFrameDomain& topFrameDomain, const RedirectDomain& redirectDomain)
@@ -2157,6 +2286,9 @@
 {
     ASSERT(!RunLoop::isMain());
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     auto result = ensureResourceStatisticsForRegistrableDomain(topFrameDomain);
     if (!result.second) {
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::setTopFrameUniqueRedirectTo was not completed due to failed insert attempt", this);
@@ -2163,8 +2295,10 @@
         return;
     }
 
-    insertDomainRelationshipList(topFrameUniqueRedirectsToQuery, HashSet<RegistrableDomain>({ redirectDomain }), *result.second);
-    insertDomainRelationshipList(topFrameUniqueRedirectsToSinceSameSiteStrictEnforcementQuery, HashSet<RegistrableDomain>({ redirectDomain }), *result.second);
+    insertDomainRelationshipList(transaction, topFrameUniqueRedirectsToQuery, HashSet<RegistrableDomain>({ redirectDomain }), *result.second);
+    insertDomainRelationshipList(transaction, topFrameUniqueRedirectsToSinceSameSiteStrictEnforcementQuery, HashSet<RegistrableDomain>({ redirectDomain }), *result.second);
+
+    transaction.commit();
 }
 
 void ResourceLoadStatisticsDatabaseStore::setTopFrameUniqueRedirectFrom(const TopFrameDomain& topFrameDomain, const RedirectDomain& redirectDomain)
@@ -2171,6 +2305,9 @@
 {
     ASSERT(!RunLoop::isMain());
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     auto result = ensureResourceStatisticsForRegistrableDomain(topFrameDomain);
     if (!result.second) {
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::setTopFrameUniqueRedirectFrom was not completed due to failed insert attempt", this);
@@ -2177,7 +2314,9 @@
         return;
     }
     // For consistency, make sure we also have a statistics entry for the redirect domain.
-    insertDomainRelationshipList(topFrameUniqueRedirectsFromQuery, HashSet<RegistrableDomain>({ redirectDomain }), *result.second);
+    insertDomainRelationshipList(transaction, topFrameUniqueRedirectsFromQuery, HashSet<RegistrableDomain>({ redirectDomain }), *result.second);
+
+    transaction.commit();
 }
 
 std::pair<ResourceLoadStatisticsDatabaseStore::AddedRecord, std::optional<unsigned>> ResourceLoadStatisticsDatabaseStore::ensureResourceStatisticsForRegistrableDomain(const RegistrableDomain& domain)
@@ -2538,6 +2677,8 @@
     auto oldestUserInteraction = now;
     RegistrableDomainsToDeleteOrRestrictWebsiteDataFor toDeleteOrRestrictFor;
 
+    SQLiteTransaction transaction(m_database);
+
     Vector<DomainData> domains = this->domains();
     Vector<unsigned> domainIDsToClearGrandfathering;
     for (auto& statistic : domains) {
@@ -2551,7 +2692,9 @@
         } else {
             if (shouldRemoveAllButCookiesFor(statistic, shouldCheckForGrandfathering)) {
                 toDeleteOrRestrictFor.domainsToDeleteAllNonCookieWebsiteDataFor.append(statistic.registrableDomain);
-                setIsScheduledForAllButCookieDataRemoval(statistic.registrableDomain, false);
+                if (!transaction.inProgress())
+                    transaction.begin();
+                setIsScheduledForAllButCookieDataRemoval(transaction, statistic.registrableDomain, false);
             }
             if (shouldEnforceSameSiteStrictFor(statistic, shouldCheckForGrandfathering)) {
                 toDeleteOrRestrictFor.domainsToEnforceSameSiteStrictFor.append(statistic.registrableDomain);
@@ -2571,6 +2714,8 @@
         toDeleteOrRestrictFor.domainsToDeleteAllNonCookieWebsiteDataFor.clear();
 
     clearGrandfathering(WTFMove(domainIDsToClearGrandfathering));
+
+    transaction.commit();
     
     return toDeleteOrRestrictFor;
 }
@@ -2635,6 +2780,9 @@
 {
     ASSERT(!RunLoop::isMain());
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     auto result = ensureResourceStatisticsForRegistrableDomain(domain);
     if (!result.second) {
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::setLastSeen was not completed due to failed insert attempt", this);
@@ -2642,6 +2790,8 @@
     }
     
     updateLastSeen(domain, WallTime::fromRawSeconds(seconds.seconds()));
+
+    transaction.commit();
 }
 
 void ResourceLoadStatisticsDatabaseStore::setPrevalentResource(const RegistrableDomain& domain)
@@ -2650,7 +2800,21 @@
 
     if (shouldSkip(domain))
         return;
-    
+
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+    setPrevalentResource(transaction, domain);
+    transaction.commit();
+}
+
+void ResourceLoadStatisticsDatabaseStore::setPrevalentResource(const SQLiteTransaction& transaction, const RegistrableDomain& domain)
+{
+    ASSERT(!RunLoop::isMain());
+    ASSERT(m_database.transactionInProgress());
+
+    if (shouldSkip(domain))
+        return;
+
     auto result = ensureResourceStatisticsForRegistrableDomain(domain);
     if (!result.second) {
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::setPrevalentResource was not completed due to failed insert attempt", this);
@@ -2657,7 +2821,7 @@
         return;
     }
 
-    setPrevalentResource(domain, ResourceLoadPrevalence::High);
+    setPrevalentResource(transaction, domain, ResourceLoadPrevalence::High);
 }
 
 void ResourceLoadStatisticsDatabaseStore::setVeryPrevalentResource(const RegistrableDomain& domain)
@@ -2666,7 +2830,23 @@
 
     if (shouldSkip(domain))
         return;
-    
+
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
+    setVeryPrevalentResource(transaction, domain);
+
+    transaction.commit();
+}
+
+void ResourceLoadStatisticsDatabaseStore::setVeryPrevalentResource(const SQLiteTransaction& transaction, const RegistrableDomain& domain)
+{
+    ASSERT(!RunLoop::isMain());
+    ASSERT(m_database.transactionInProgress());
+
+    if (shouldSkip(domain))
+        return;
+
     auto result = ensureResourceStatisticsForRegistrableDomain(domain);
     if (!result.second) {
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::setVeryPrevalentResource was not completed due to failed insert attempt", this);
@@ -2673,7 +2853,7 @@
         return;
     }
 
-    setPrevalentResource(domain, ResourceLoadPrevalence::VeryHigh);
+    setPrevalentResource(transaction, domain, ResourceLoadPrevalence::VeryHigh);
 }
 
 void ResourceLoadStatisticsDatabaseStore::updateDataRecordsRemoved(const RegistrableDomain& domain, int value)
@@ -2971,6 +3151,9 @@
             return;
     }
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     int rowsToPrune = m_operatingDatesSize - operatingDatesWindowLong + 1;
     if (rowsToPrune > 0) {
         auto deleteLeastRecentOperatingDateStatement = m_database.prepareStatement("DELETE FROM OperatingDates ORDER BY year, month, monthDay LIMIT ?;"_s);
@@ -2993,6 +3176,8 @@
     }
 
     updateOperatingDatesParameters();
+
+    transaction.commit();
 }
 
 bool ResourceLoadStatisticsDatabaseStore::hasStatisticsExpired(WallTime mostRecentUserInteractionTime, OperatingDatesWindow operatingDatesWindow) const
@@ -3026,6 +3211,10 @@
 {
     // Populate the Operating Dates table with enough days to require pruning.
     double daysAgoInSeconds = 0;
+
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     for (unsigned i = 1; i <= numberOfOperatingDaysPassed; i++) {
         double daysToSubtract = Seconds::fromHours(24 * i).value();
         daysAgoInSeconds = WallTime::now().secondsSinceEpoch().value() - daysToSubtract;
@@ -3045,6 +3234,8 @@
 
     updateOperatingDatesParameters();
 
+    transaction.commit();
+
     // Make sure mostRecentUserInteractionTime is the least recent of all entries.
     daysAgoInSeconds -= Seconds::fromHours(24).value();
     auto scopedInsertObservedDomainStatement = this->scopedStatement(m_insertObservedDomainStatement, insertObservedDomainQuery, "insertExpiredStatisticForTesting"_s);
@@ -3147,6 +3338,10 @@
 
 void ResourceLoadStatisticsDatabaseStore::insertPrivateClickMeasurement(PrivateClickMeasurement&& attribution, PrivateClickMeasurementAttributionType attributionType)
 {
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+    auto commitTransaction = makeScopeExit([&transaction] { transaction.commit(); });
+
     auto sourceData = ensureResourceStatisticsForRegistrableDomain(attribution.sourceSite().registrableDomain);
     auto attributionDestinationData = ensureResourceStatisticsForRegistrableDomain(attribution.destinationSite().registrableDomain);
 
@@ -3330,6 +3525,9 @@
         bindParameter = String::number(*domainIDToMatch);
     }
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     auto clearUnattributedScopedStatement = this->scopedStatement(m_clearUnattributedPrivateClickMeasurementStatement, clearUnattributedPrivateClickMeasurementQuery, "clearPrivateClickMeasurement"_s);
 
     if (!clearUnattributedScopedStatement
@@ -3349,6 +3547,8 @@
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::clearPrivateClickMeasurement clearAttributedScopedStatement, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
         ASSERT_NOT_REACHED();
     }
+
+    transaction.commit();
 }
 
 void ResourceLoadStatisticsDatabaseStore::clearExpiredPrivateClickMeasurement()
@@ -3544,6 +3744,9 @@
 {
     auto expiredTimeToSend = WallTime::now() - 1_h;
 
+    SQLiteTransaction transaction(m_database);
+    transaction.begin();
+
     auto earliestTimeToSendToSourceStatement = m_database.prepareStatement("UPDATE AttributedPrivateClickMeasurement SET earliestTimeToSendToSource = ?"_s);
     auto earliestTimeToSendToDestinationStatement = m_database.prepareStatement("UPDATE AttributedPrivateClickMeasurement SET earliestTimeToSendToDestination = null"_s);
 
@@ -3559,6 +3762,8 @@
         ASSERT_NOT_REACHED();
     }
 
+    transaction.commit();
+
     return;
 }
 

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h (278915 => 278916)


--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h	2021-06-16 00:46:26 UTC (rev 278915)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h	2021-06-16 00:56:03 UTC (rev 278916)
@@ -108,7 +108,7 @@
     void setGrandfathered(const RegistrableDomain&, bool value) override;
     bool isGrandfathered(const RegistrableDomain&) const override;
 
-    void setIsScheduledForAllButCookieDataRemoval(const RegistrableDomain&, bool value);
+    void setIsScheduledForAllButCookieDataRemoval(const WebCore::SQLiteTransaction&, const RegistrableDomain&, bool value);
     void setSubframeUnderTopFrameDomain(const SubFrameDomain&, const TopFrameDomain&) override;
     void setSubresourceUnderTopFrameDomain(const SubResourceDomain&, const TopFrameDomain&) override;
     void setSubresourceUniqueRedirectTo(const SubResourceDomain&, const RedirectDomain&) override;
@@ -177,6 +177,9 @@
     void destroyStatements();
     WebCore::SQLiteStatementAutoResetScope scopedStatement(std::unique_ptr<WebCore::SQLiteStatement>&, ASCIILiteral, const String&) const;
 
+    void setPrevalentResource(const WebCore::SQLiteTransaction&, const RegistrableDomain&);
+    void setVeryPrevalentResource(const WebCore::SQLiteTransaction&, const RegistrableDomain&);
+    void setGrandfathered(const WebCore::SQLiteTransaction&, const RegistrableDomain&, bool value);
     bool hasStorageAccess(const TopFrameDomain&, const SubFrameDomain&) const;
     Vector<WebResourceLoadStatisticsStore::ThirdPartyDataForSpecificFirstParty> getThirdPartyDataForSpecificFirstPartyDomains(unsigned, const RegistrableDomain&) const;
     void openAndUpdateSchemaIfNecessary();
@@ -183,12 +186,12 @@
     String getDomainStringFromDomainID(unsigned) const;
     ASCIILiteral getSubStatisticStatement(const String&) const;
     void appendSubStatisticList(StringBuilder&, const String& tableName, const String& domain) const;
-    void mergeStatistic(const ResourceLoadStatistics&);
-    void merge(WebCore::SQLiteStatement*, const ResourceLoadStatistics&);
+    void mergeStatistic(const WebCore::SQLiteTransaction&, const ResourceLoadStatistics&);
+    void merge(const WebCore::SQLiteTransaction&, WebCore::SQLiteStatement*, const ResourceLoadStatistics&);
     void clearDatabaseContents();
     bool insertObservedDomain(const ResourceLoadStatistics&) WARN_UNUSED_RETURN;
-    void insertDomainRelationships(const ResourceLoadStatistics&);
-    void insertDomainRelationshipList(const String&, const HashSet<RegistrableDomain>&, unsigned);
+    void insertDomainRelationships(const WebCore::SQLiteTransaction&, const ResourceLoadStatistics&);
+    void insertDomainRelationshipList(const WebCore::SQLiteTransaction&, const String&, const HashSet<RegistrableDomain>&, unsigned);
     bool relationshipExists(WebCore::SQLiteStatementAutoResetScope&, std::optional<unsigned> firstDomainID, const RegistrableDomain& secondDomain) const;
     std::optional<unsigned> domainID(const RegistrableDomain&) const;
     bool domainExists(const RegistrableDomain&) const;
@@ -235,10 +238,10 @@
     bool areAllThirdPartyCookiesBlockedUnder(const TopFrameDomain&) override;
     CookieAccess cookieAccess(const SubResourceDomain&, const TopFrameDomain&);
 
-    void setPrevalentResource(const RegistrableDomain&, ResourceLoadPrevalence);
+    void setPrevalentResource(const WebCore::SQLiteTransaction&, const RegistrableDomain&, ResourceLoadPrevalence);
     unsigned recursivelyFindNonPrevalentDomainsThatRedirectedToThisDomain(unsigned primaryDomainID, StdSet<unsigned>& nonPrevalentRedirectionSources, unsigned numberOfRecursiveCalls);
     void setDomainsAsPrevalent(StdSet<unsigned>&&);
-    void grantStorageAccessInternal(SubFrameDomain&&, TopFrameDomain&&, std::optional<WebCore::FrameIdentifier>, WebCore::PageIdentifier, WebCore::StorageAccessPromptWasShown, WebCore::StorageAccessScope, CompletionHandler<void(WebCore::StorageAccessWasGranted)>&&);
+    void grantStorageAccessInternal(const WebCore::SQLiteTransaction&, SubFrameDomain&&, TopFrameDomain&&, std::optional<WebCore::FrameIdentifier>, WebCore::PageIdentifier, WebCore::StorageAccessPromptWasShown, WebCore::StorageAccessScope, CompletionHandler<void(WebCore::StorageAccessWasGranted)>&&);
     void markAsPrevalentIfHasRedirectedToPrevalent();
     Vector<RegistrableDomain> ensurePrevalentResourcesForDebugMode() override;
     void removeDataRecords(CompletionHandler<void()>&&);
@@ -253,7 +256,7 @@
 
     bool createUniqueIndices();
     bool createSchema();
-    String ensureAndMakeDomainList(const HashSet<RegistrableDomain>&);
+    String ensureAndMakeDomainList(const WebCore::SQLiteTransaction&, const HashSet<RegistrableDomain>&);
     std::optional<WallTime> mostRecentUserInteractionTime(const DomainData&);
     
     void removeUnattributed(WebCore::PrivateClickMeasurement&);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to