⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 281721 in webkit


Ignore:
Timestamp:
Aug 27, 2021, 2:22:36 PM (5 years ago)
Author:
achristensen@apple.com
Message:

Separate PrivateClickMeasurement database from ResourceLoadStatistics database and add SPI to set its location
https://bugs.webkit.org/show_bug.cgi?id=229527

Reviewed by Kate Cheney.

Source/WebCore:

  • loader/PrivateClickMeasurement.cpp:

(WebCore::PrivateClickMeasurement::SourceSecretToken::isolatedCopy const):
(WebCore::PrivateClickMeasurement::EphemeralSourceNonce::isolatedCopy const):
(WebCore::PrivateClickMeasurement::SourceUnlinkableToken::isolatedCopy const):
(WebCore::PrivateClickMeasurement::isolatedCopy const):

  • loader/PrivateClickMeasurement.h:

Source/WebKit:

This will be used by rdar://80806283

In order to do this, I moved common code to DatabaseUtilities and moved the PCM logic from ResourceLoadStatisticsDatabaseStore
to a new class. It puts the data in a different file in the same directory unless SPI tells it to put it in a different directory.

The biggest functional change I needed to do was to make a PCMObservedDomains table in the new DB instead of an ObservedDomains table,
which contained more information than I needed. I need just an index and a list of domains.

Another slight implementation change is that instead of checking isEphemeral in WebResourceLoadStatisticsStore, I just pass an empty
String to the Store if it's ephemeral, which causes no DB to be created, which causes equivalent behavior.

I also moved the debug message broadcasting to PrivateClickMeasurementManager::attribute in order to make the Database object not
need to know about the NetworkProcess and not need to keep state of whether debug mode is enabled. Database::attributePrivateClickMeasurement
now returns a DebugInfo object and PrivateClickMeasurementManager::attribute checks whether debug mode is enabled and broadcasts the messages.

I added a few calls to PrivateClickMeasurement::isolatedCopy when moving an PrivateClickMeasurement object to another thread.

I added a CompletionHandler to clearPrivateClickMeasurement and clearPrivateClickMeasurementForRegistrableDomain
so that clearing website data doesn't say it's done until it's done.

An even smaller change is I added a "ForTesting" suffix on some function names of functions that are only used in tests.

The rest of this patch just moves code from one location to another.

I still need to implement migrating data from the old DB to the new DB. I'll do that in another patch soon.

  • CMakeLists.txt:
  • NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp:

(WebKit::expectedTableAndIndexQueries):
(WebKit::ResourceLoadStatisticsDatabaseStore::ResourceLoadStatisticsDatabaseStore):
(WebKit::ResourceLoadStatisticsDatabaseStore::openITPDatabase):
(WebKit::ResourceLoadStatisticsDatabaseStore::needsUpdatedSchema):
(WebKit::insertDistinctValuesInTableStatement):
(WebKit::ResourceLoadStatisticsDatabaseStore::openAndUpdateSchemaIfNecessary):
(WebKit::ResourceLoadStatisticsDatabaseStore::interruptAllDatabases):
(WebKit::ResourceLoadStatisticsDatabaseStore::createUniqueIndices):
(WebKit::ResourceLoadStatisticsDatabaseStore::createSchema):
(WebKit::ResourceLoadStatisticsDatabaseStore::destroyStatements):
(WebKit::ResourceLoadStatisticsDatabaseStore::clearDatabaseContents):
(WebKit::expectedUnattributedColumns): Deleted.
(WebKit::expectedAttributedColumns): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::close): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::enableForeignKeys): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::needsUpdatedPrivateClickMeasurementSchema): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::addMissingColumnsToTable): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::addMissingColumnsIfNecessary): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::renameColumnInTable): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::renameColumnsIfNecessary): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::scopedStatement const): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::interrupt): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::buildPrivateClickMeasurementFromDatabase): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::findPrivateClickMeasurement): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::insertPrivateClickMeasurement): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::markAllUnattributedPrivateClickMeasurementAsExpiredForTesting): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::removeUnattributed): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::attributePrivateClickMeasurement): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::allAttributedPrivateClickMeasurement): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::clearPrivateClickMeasurement): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::clearExpiredPrivateClickMeasurement): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::attributionToString): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::privateClickMeasurementToString): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::earliestTimesToSend): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::markReportAsSentToSource): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::markReportAsSentToDestination): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::clearSentAttribution): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::markAttributedPrivateClickMeasurementsAsExpiredForTesting): Deleted.
(WebKit::ResourceLoadStatisticsDatabaseStore::beginTransactionIfNecessary): Deleted.

  • NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h:
  • NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.h:
  • NetworkProcess/Classifier/ResourceLoadStatisticsStore.h:
  • NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:

(WebKit::pcmStoreDirectory):
(WebKit::WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore):
(WebKit::WebResourceLoadStatisticsStore::create):
(WebKit::WebResourceLoadStatisticsStore::didDestroyNetworkSession):
(WebKit::WebResourceLoadStatisticsStore::suspend):
(WebKit::WebResourceLoadStatisticsStore::insertPrivateClickMeasurement): Deleted.
(WebKit::WebResourceLoadStatisticsStore::markAllUnattributedPrivateClickMeasurementAsExpiredForTesting): Deleted.
(WebKit::WebResourceLoadStatisticsStore::attributePrivateClickMeasurement): Deleted.
(WebKit::WebResourceLoadStatisticsStore::allAttributedPrivateClickMeasurement): Deleted.
(WebKit::WebResourceLoadStatisticsStore::clearPrivateClickMeasurement): Deleted.
(WebKit::WebResourceLoadStatisticsStore::clearPrivateClickMeasurementForRegistrableDomain): Deleted.
(WebKit::WebResourceLoadStatisticsStore::clearExpiredPrivateClickMeasurement): Deleted.
(WebKit::WebResourceLoadStatisticsStore::privateClickMeasurementToString): Deleted.
(WebKit::WebResourceLoadStatisticsStore::clearSentAttribution): Deleted.
(WebKit::WebResourceLoadStatisticsStore::markAttributedPrivateClickMeasurementsAsExpiredForTesting): Deleted.

  • NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h:
  • NetworkProcess/DatabaseUtilities.cpp: Added.

(WebKit::DatabaseUtilities::DatabaseUtilities):
(WebKit::DatabaseUtilities::~DatabaseUtilities):
(WebKit::DatabaseUtilities::scopedStatement const):
(WebKit::DatabaseUtilities::beginTransactionIfNecessary):
(WebKit::DatabaseUtilities::openDatabaseAndCreateSchemaIfNecessary):
(WebKit::DatabaseUtilities::enableForeignKeys):
(WebKit::DatabaseUtilities::close):
(WebKit::DatabaseUtilities::interrupt):

  • NetworkProcess/DatabaseUtilities.h: Copied from Source/WebKit/NetworkProcess/webrtc/NetworkRTCResolver.h.
  • NetworkProcess/NetworkProcess.cpp:

(WebKit::NetworkProcess::deleteWebsiteData):
(WebKit::NetworkProcess::deleteWebsiteDataForOrigins):
(WebKit::NetworkProcess::prepareToSuspend):
(WebKit::NetworkProcess::resume):
(WebKit::NetworkProcess::clearPrivateClickMeasurement):

  • NetworkProcess/NetworkResourceLoader.cpp:

(WebKit::NetworkResourceLoader::willSendRedirectedRequest):
(WebKit::NetworkResourceLoader::continueWillSendRedirectedRequest):

  • NetworkProcess/NetworkSession.cpp:

(WebKit::NetworkSession::NetworkSession):
(WebKit::NetworkSession::setResourceLoadStatisticsEnabled):
(WebKit::NetworkSession::recreateResourceLoadStatisticStore):
(WebKit::NetworkSession::dumpPrivateClickMeasurement):
(WebKit::NetworkSession::clearPrivateClickMeasurement):
(WebKit::NetworkSession::clearPrivateClickMeasurementForRegistrableDomain):

  • NetworkProcess/NetworkSession.h:
  • NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDatabase.cpp: Added.

(WebKit::PCM::Database::Database):
(WebKit::PCM::Database::~Database):
(WebKit::PCM::Database::interruptAllDatabases):
(WebKit::PCM::Database::createSchema):
(WebKit::PCM::Database::insertPrivateClickMeasurement):
(WebKit::PCM::Database::markAllUnattributedPrivateClickMeasurementAsExpiredForTesting):
(WebKit::PCM::Database::findPrivateClickMeasurement):
(WebKit::PCM::Database::attributePrivateClickMeasurement):
(WebKit::PCM::Database::buildPrivateClickMeasurementFromDatabase):
(WebKit::PCM::Database::removeUnattributed):
(WebKit::PCM::Database::allAttributedPrivateClickMeasurement):
(WebKit::PCM::Database::privateClickMeasurementToStringForTesting):
(WebKit::PCM::Database::attributionToStringForTesting):
(WebKit::PCM::Database::markAttributedPrivateClickMeasurementsAsExpiredForTesting):
(WebKit::PCM::Database::clearPrivateClickMeasurement):
(WebKit::PCM::Database::clearExpiredPrivateClickMeasurement):
(WebKit::PCM::Database::clearSentAttribution):
(WebKit::PCM::Database::markReportAsSentToDestination):
(WebKit::PCM::Database::markReportAsSentToSource):
(WebKit::PCM::Database::earliestTimesToSend):
(WebKit::PCM::Database::domainID):
(WebKit::PCM::Database::getDomainStringFromDomainID):
(WebKit::PCM::Database::ensureDomainID):
(WebKit::PCM::Database::destroyStatements):

  • NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDatabase.h: Added.
  • NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDebugInfo.cpp: Copied from Source/WebKit/NetworkProcess/webrtc/NetworkRTCResolver.h.

(WebKit::PCM::DebugInfo::isolatedCopy const):
(WebKit::PCM::DebugInfo::Message::isolatedCopy const):

  • NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDebugInfo.h: Copied from Source/WebKit/NetworkProcess/webrtc/NetworkRTCResolver.h.
  • NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementStore.cpp: Added.

(WebKit::PCM::sharedWorkQueue):
(WebKit::PCM::Store::prepareForProcessToSuspend):
(WebKit::PCM::Store::processDidResume):
(WebKit::PCM::Store::Store):
(WebKit::PCM::Store::postTask):
(WebKit::PCM::Store::postTaskReply):
(WebKit::PCM::Store::insertPrivateClickMeasurement):
(WebKit::PCM::Store::markAllUnattributedPrivateClickMeasurementAsExpiredForTesting):
(WebKit::PCM::Store::attributePrivateClickMeasurement):
(WebKit::PCM::Store::privateClickMeasurementToStringForTesting):
(WebKit::PCM::Store::allAttributedPrivateClickMeasurement):
(WebKit::PCM::Store::markAttributedPrivateClickMeasurementsAsExpiredForTesting):
(WebKit::PCM::Store::clearPrivateClickMeasurement):
(WebKit::PCM::Store::clearPrivateClickMeasurementForRegistrableDomain):
(WebKit::PCM::Store::clearExpiredPrivateClickMeasurement):
(WebKit::PCM::Store::clearSentAttribution):
(WebKit::PCM::Store::close):

  • NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementStore.h: Added.

(WebKit::PCM::Store::create):

  • NetworkProcess/PrivateClickMeasurementManager.cpp:

(WebKit::PrivateClickMeasurementManager::insertPrivateClickMeasurement):
(WebKit::PrivateClickMeasurementManager::attribute):
(WebKit::PrivateClickMeasurementManager::clearSentAttribution):
(WebKit::PrivateClickMeasurementManager::firePendingAttributionRequests):
(WebKit::PrivateClickMeasurementManager::clear):
(WebKit::PrivateClickMeasurementManager::clearForRegistrableDomain):
(WebKit::PrivateClickMeasurementManager::clearExpired):
(WebKit::PrivateClickMeasurementManager::toStringForTesting const):
(WebKit::PrivateClickMeasurementManager::markAllUnattributedAsExpiredForTesting):
(WebKit::PrivateClickMeasurementManager::markAttributedPrivateClickMeasurementsAsExpiredForTesting):
(WebKit::PrivateClickMeasurementManager::toString const): Deleted.

  • NetworkProcess/PrivateClickMeasurementManager.h:
  • NetworkProcess/PrivateClickMeasurementNetworkLoader.cpp:

(WebKit::PrivateClickMeasurementNetworkLoader::~PrivateClickMeasurementNetworkLoader):
(WebKit::PrivateClickMeasurementNetworkLoader::cancel):
(WebKit::PrivateClickMeasurementNetworkLoader::willSendRedirectedRequest):

  • NetworkProcess/PrivateClickMeasurementNetworkLoader.h:
  • NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp:
  • NetworkProcess/webrtc/NetworkRTCResolver.h:
  • NetworkProcess/webrtc/NetworkRTCResolverCocoa.cpp:

(WebKit::resolvedName):

  • Shared/ResourceLoadStatisticsParameters.h:

(WebKit::ResourceLoadStatisticsParameters::encode const):
(WebKit::ResourceLoadStatisticsParameters::decode):

  • Sources.txt:
  • UIProcess/API/Cocoa/WKWebsiteDataStore.mm:

(+[WKWebsiteDataStore _setNetworkProcessSuspensionAllowedForTesting:]):
(+[WKWebsiteDataStore _preventNetworkProcessSuspensionForTesting]): Deleted.

  • UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h:
  • UIProcess/API/Cocoa/_WKWebsiteDataStoreConfiguration.h:
  • UIProcess/API/Cocoa/_WKWebsiteDataStoreConfiguration.mm:

(-[_WKWebsiteDataStoreConfiguration privateClickMeasurementStorageDirectory]):
(-[_WKWebsiteDataStoreConfiguration setPrivateClickMeasurementStorageDirectory:]):

  • UIProcess/Network/NetworkProcessProxy.cpp:

(WebKit::NetworkProcessProxy::setSuspensionAllowedForTesting):
(WebKit::NetworkProcessProxy::sendPrepareToSuspend):
(WebKit::NetworkProcessProxy::preventSuspensionForTesting): Deleted.

  • UIProcess/Network/NetworkProcessProxy.h:
  • UIProcess/WebsiteData/WebsiteDataStore.cpp:

(WebKit::WebsiteDataStore::resolveDirectoriesIfNecessary):
(WebKit::WebsiteDataStore::parameters):

  • UIProcess/WebsiteData/WebsiteDataStoreConfiguration.cpp:

(WebKit::WebsiteDataStoreConfiguration::copy const):

  • UIProcess/WebsiteData/WebsiteDataStoreConfiguration.h:

(WebKit::WebsiteDataStoreConfiguration::privateClickMeasurementStorageDirectory const):
(WebKit::WebsiteDataStoreConfiguration::setPrivateClickMeasurementStorageDirectory):

  • WebKit.xcodeproj/project.pbxproj:

Tools:

  • TestWebKitAPI/Tests/WebKitCocoa/EventAttribution.mm:

(TestWebKitAPI::runBasicEventAttributionTest):
(TestWebKitAPI::TEST):

  • TestWebKitAPI/Tests/WebKitCocoa/PrivateClickMeasurement.mm:

(TEST):

Location:
trunk
Files:
9 added
37 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r281714 r281721  
     12021-08-27  Alex Christensen  <achristensen@webkit.org>
     2
     3        Separate PrivateClickMeasurement database from ResourceLoadStatistics database and add SPI to set its location
     4        https://bugs.webkit.org/show_bug.cgi?id=229527
     5
     6        Reviewed by Kate Cheney.
     7
     8        * loader/PrivateClickMeasurement.cpp:
     9        (WebCore::PrivateClickMeasurement::SourceSecretToken::isolatedCopy const):
     10        (WebCore::PrivateClickMeasurement::EphemeralSourceNonce::isolatedCopy const):
     11        (WebCore::PrivateClickMeasurement::SourceUnlinkableToken::isolatedCopy const):
     12        (WebCore::PrivateClickMeasurement::isolatedCopy const):
     13        * loader/PrivateClickMeasurement.h:
     14
    1152021-08-27  Alan Bujtas  <zalan@apple.com>
    216
  • trunk/Source/WebCore/loader/PrivateClickMeasurement.cpp

    r278162 r281721  
    6060}
    6161
     62PrivateClickMeasurement::SourceSecretToken PrivateClickMeasurement::SourceSecretToken::isolatedCopy() const
     63{
     64    return {
     65        tokenBase64URL.isolatedCopy(),
     66        signatureBase64URL.isolatedCopy(),
     67        keyIDBase64URL.isolatedCopy(),
     68    };
     69}
     70
     71PrivateClickMeasurement::EphemeralSourceNonce PrivateClickMeasurement::EphemeralSourceNonce::isolatedCopy() const
     72{
     73    return { nonce.isolatedCopy() };
     74}
     75
     76PrivateClickMeasurement::SourceUnlinkableToken PrivateClickMeasurement::SourceUnlinkableToken::isolatedCopy() const
     77{
     78    return {
     79#if PLATFORM(COCOA)
     80        blinder,
     81        waitingToken,
     82        readyToken,
     83#endif
     84        valueBase64URL.isolatedCopy()
     85    };
     86}
     87
     88PrivateClickMeasurement PrivateClickMeasurement::isolatedCopy() const
     89{
     90    PrivateClickMeasurement copy;
     91    copy.m_sourceID = m_sourceID;
     92    copy.m_sourceSite = m_sourceSite.isolatedCopy();
     93    copy.m_destinationSite = m_destinationSite.isolatedCopy();
     94    copy.m_sourceDescription = m_sourceDescription.isolatedCopy();
     95    copy.m_purchaser = m_purchaser.isolatedCopy();
     96    copy.m_timeOfAdClick = m_timeOfAdClick.isolatedCopy();
     97    copy.m_isEphemeral = m_isEphemeral;
     98    copy.m_attributionTriggerData = m_attributionTriggerData;
     99    copy.m_timesToSend = m_timesToSend;
     100    copy.m_ephemeralSourceNonce = crossThreadCopy(m_ephemeralSourceNonce);
     101    copy.m_sourceUnlinkableToken = m_sourceUnlinkableToken.isolatedCopy();
     102    copy.m_sourceSecretToken = crossThreadCopy(m_sourceSecretToken);
     103    return copy;
     104}
     105
    62106Expected<PrivateClickMeasurement::AttributionTriggerData, String> PrivateClickMeasurement::parseAttributionRequest(const URL& redirectURL)
    63107{
  • trunk/Source/WebCore/loader/PrivateClickMeasurement.h

    r281480 r281721  
    355355        String nonce;
    356356
     357        EphemeralSourceNonce isolatedCopy() const;
     358
    357359        WEBCORE_EXPORT bool isValid() const;
    358360
     
    370372        String keyIDBase64URL;
    371373
     374        SourceSecretToken isolatedCopy() const;
    372375        bool isValid() const;
    373376    };
     
    384387    template<class Encoder> void encode(Encoder&) const;
    385388    template<class Decoder> static std::optional<PrivateClickMeasurement> decode(Decoder&);
     389
     390    WEBCORE_EXPORT PrivateClickMeasurement isolatedCopy() const;
    386391
    387392private:
     
    406411#endif
    407412        String valueBase64URL;
     413
     414        SourceUnlinkableToken isolatedCopy() const;
    408415    };
    409416
  • trunk/Source/WebKit/CMakeLists.txt

    r279971 r281721  
    2424    "${WEBKIT_DIR}/NetworkProcess/FileAPI"
    2525    "${WEBKIT_DIR}/NetworkProcess/IndexedDB"
     26    "${WEBKIT_DIR}/NetworkProcess/PrivateClickMeasurement"
    2627    "${WEBKIT_DIR}/NetworkProcess/ServiceWorker"
    2728    "${WEBKIT_DIR}/NetworkProcess/WebStorage"
  • trunk/Source/WebKit/ChangeLog

    r281706 r281721  
     12021-08-27  Alex Christensen  <achristensen@webkit.org>
     2
     3        Separate PrivateClickMeasurement database from ResourceLoadStatistics database and add SPI to set its location
     4        https://bugs.webkit.org/show_bug.cgi?id=229527
     5
     6        Reviewed by Kate Cheney.
     7
     8        This will be used by rdar://80806283
     9
     10        In order to do this, I moved common code to DatabaseUtilities and moved the PCM logic from ResourceLoadStatisticsDatabaseStore
     11        to a new class.  It puts the data in a different file in the same directory unless SPI tells it to put it in a different directory.
     12
     13        The biggest functional change I needed to do was to make a PCMObservedDomains table in the new DB instead of an ObservedDomains table,
     14        which contained more information than I needed.  I need just an index and a list of domains.
     15
     16        Another slight implementation change is that instead of checking isEphemeral in WebResourceLoadStatisticsStore, I just pass an empty
     17        String to the Store if it's ephemeral, which causes no DB to be created, which causes equivalent behavior.
     18
     19        I also moved the debug message broadcasting to PrivateClickMeasurementManager::attribute in order to make the Database object not
     20        need to know about the NetworkProcess and not need to keep state of whether debug mode is enabled.  Database::attributePrivateClickMeasurement
     21        now returns a DebugInfo object and PrivateClickMeasurementManager::attribute checks whether debug mode is enabled and broadcasts the messages.
     22
     23        I added a few calls to PrivateClickMeasurement::isolatedCopy when moving an PrivateClickMeasurement object to another thread.
     24
     25        I added a CompletionHandler to clearPrivateClickMeasurement and clearPrivateClickMeasurementForRegistrableDomain
     26        so that clearing website data doesn't say it's done until it's done.
     27
     28        An even smaller change is I added a "ForTesting" suffix on some function names of functions that are only used in tests.
     29
     30        The rest of this patch just moves code from one location to another.
     31
     32        I still need to implement migrating data from the old DB to the new DB.  I'll do that in another patch soon.
     33
     34        * CMakeLists.txt:
     35        * NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp:
     36        (WebKit::expectedTableAndIndexQueries):
     37        (WebKit::ResourceLoadStatisticsDatabaseStore::ResourceLoadStatisticsDatabaseStore):
     38        (WebKit::ResourceLoadStatisticsDatabaseStore::openITPDatabase):
     39        (WebKit::ResourceLoadStatisticsDatabaseStore::needsUpdatedSchema):
     40        (WebKit::insertDistinctValuesInTableStatement):
     41        (WebKit::ResourceLoadStatisticsDatabaseStore::openAndUpdateSchemaIfNecessary):
     42        (WebKit::ResourceLoadStatisticsDatabaseStore::interruptAllDatabases):
     43        (WebKit::ResourceLoadStatisticsDatabaseStore::createUniqueIndices):
     44        (WebKit::ResourceLoadStatisticsDatabaseStore::createSchema):
     45        (WebKit::ResourceLoadStatisticsDatabaseStore::destroyStatements):
     46        (WebKit::ResourceLoadStatisticsDatabaseStore::clearDatabaseContents):
     47        (WebKit::expectedUnattributedColumns): Deleted.
     48        (WebKit::expectedAttributedColumns): Deleted.
     49        (WebKit::ResourceLoadStatisticsDatabaseStore::close): Deleted.
     50        (WebKit::ResourceLoadStatisticsDatabaseStore::enableForeignKeys): Deleted.
     51        (WebKit::ResourceLoadStatisticsDatabaseStore::needsUpdatedPrivateClickMeasurementSchema): Deleted.
     52        (WebKit::ResourceLoadStatisticsDatabaseStore::addMissingColumnsToTable): Deleted.
     53        (WebKit::ResourceLoadStatisticsDatabaseStore::addMissingColumnsIfNecessary): Deleted.
     54        (WebKit::ResourceLoadStatisticsDatabaseStore::renameColumnInTable): Deleted.
     55        (WebKit::ResourceLoadStatisticsDatabaseStore::renameColumnsIfNecessary): Deleted.
     56        (WebKit::ResourceLoadStatisticsDatabaseStore::scopedStatement const): Deleted.
     57        (WebKit::ResourceLoadStatisticsDatabaseStore::interrupt): Deleted.
     58        (WebKit::ResourceLoadStatisticsDatabaseStore::buildPrivateClickMeasurementFromDatabase): Deleted.
     59        (WebKit::ResourceLoadStatisticsDatabaseStore::findPrivateClickMeasurement): Deleted.
     60        (WebKit::ResourceLoadStatisticsDatabaseStore::insertPrivateClickMeasurement): Deleted.
     61        (WebKit::ResourceLoadStatisticsDatabaseStore::markAllUnattributedPrivateClickMeasurementAsExpiredForTesting): Deleted.
     62        (WebKit::ResourceLoadStatisticsDatabaseStore::removeUnattributed): Deleted.
     63        (WebKit::ResourceLoadStatisticsDatabaseStore::attributePrivateClickMeasurement): Deleted.
     64        (WebKit::ResourceLoadStatisticsDatabaseStore::allAttributedPrivateClickMeasurement): Deleted.
     65        (WebKit::ResourceLoadStatisticsDatabaseStore::clearPrivateClickMeasurement): Deleted.
     66        (WebKit::ResourceLoadStatisticsDatabaseStore::clearExpiredPrivateClickMeasurement): Deleted.
     67        (WebKit::ResourceLoadStatisticsDatabaseStore::attributionToString): Deleted.
     68        (WebKit::ResourceLoadStatisticsDatabaseStore::privateClickMeasurementToString): Deleted.
     69        (WebKit::ResourceLoadStatisticsDatabaseStore::earliestTimesToSend): Deleted.
     70        (WebKit::ResourceLoadStatisticsDatabaseStore::markReportAsSentToSource): Deleted.
     71        (WebKit::ResourceLoadStatisticsDatabaseStore::markReportAsSentToDestination): Deleted.
     72        (WebKit::ResourceLoadStatisticsDatabaseStore::clearSentAttribution): Deleted.
     73        (WebKit::ResourceLoadStatisticsDatabaseStore::markAttributedPrivateClickMeasurementsAsExpiredForTesting): Deleted.
     74        (WebKit::ResourceLoadStatisticsDatabaseStore::beginTransactionIfNecessary): Deleted.
     75        * NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h:
     76        * NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.h:
     77        * NetworkProcess/Classifier/ResourceLoadStatisticsStore.h:
     78        * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
     79        (WebKit::pcmStoreDirectory):
     80        (WebKit::WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore):
     81        (WebKit::WebResourceLoadStatisticsStore::create):
     82        (WebKit::WebResourceLoadStatisticsStore::didDestroyNetworkSession):
     83        (WebKit::WebResourceLoadStatisticsStore::suspend):
     84        (WebKit::WebResourceLoadStatisticsStore::insertPrivateClickMeasurement): Deleted.
     85        (WebKit::WebResourceLoadStatisticsStore::markAllUnattributedPrivateClickMeasurementAsExpiredForTesting): Deleted.
     86        (WebKit::WebResourceLoadStatisticsStore::attributePrivateClickMeasurement): Deleted.
     87        (WebKit::WebResourceLoadStatisticsStore::allAttributedPrivateClickMeasurement): Deleted.
     88        (WebKit::WebResourceLoadStatisticsStore::clearPrivateClickMeasurement): Deleted.
     89        (WebKit::WebResourceLoadStatisticsStore::clearPrivateClickMeasurementForRegistrableDomain): Deleted.
     90        (WebKit::WebResourceLoadStatisticsStore::clearExpiredPrivateClickMeasurement): Deleted.
     91        (WebKit::WebResourceLoadStatisticsStore::privateClickMeasurementToString): Deleted.
     92        (WebKit::WebResourceLoadStatisticsStore::clearSentAttribution): Deleted.
     93        (WebKit::WebResourceLoadStatisticsStore::markAttributedPrivateClickMeasurementsAsExpiredForTesting): Deleted.
     94        * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h:
     95        * NetworkProcess/DatabaseUtilities.cpp: Added.
     96        (WebKit::DatabaseUtilities::DatabaseUtilities):
     97        (WebKit::DatabaseUtilities::~DatabaseUtilities):
     98        (WebKit::DatabaseUtilities::scopedStatement const):
     99        (WebKit::DatabaseUtilities::beginTransactionIfNecessary):
     100        (WebKit::DatabaseUtilities::openDatabaseAndCreateSchemaIfNecessary):
     101        (WebKit::DatabaseUtilities::enableForeignKeys):
     102        (WebKit::DatabaseUtilities::close):
     103        (WebKit::DatabaseUtilities::interrupt):
     104        * NetworkProcess/DatabaseUtilities.h: Copied from Source/WebKit/NetworkProcess/webrtc/NetworkRTCResolver.h.
     105        * NetworkProcess/NetworkProcess.cpp:
     106        (WebKit::NetworkProcess::deleteWebsiteData):
     107        (WebKit::NetworkProcess::deleteWebsiteDataForOrigins):
     108        (WebKit::NetworkProcess::prepareToSuspend):
     109        (WebKit::NetworkProcess::resume):
     110        (WebKit::NetworkProcess::clearPrivateClickMeasurement):
     111        * NetworkProcess/NetworkResourceLoader.cpp:
     112        (WebKit::NetworkResourceLoader::willSendRedirectedRequest):
     113        (WebKit::NetworkResourceLoader::continueWillSendRedirectedRequest):
     114        * NetworkProcess/NetworkSession.cpp:
     115        (WebKit::NetworkSession::NetworkSession):
     116        (WebKit::NetworkSession::setResourceLoadStatisticsEnabled):
     117        (WebKit::NetworkSession::recreateResourceLoadStatisticStore):
     118        (WebKit::NetworkSession::dumpPrivateClickMeasurement):
     119        (WebKit::NetworkSession::clearPrivateClickMeasurement):
     120        (WebKit::NetworkSession::clearPrivateClickMeasurementForRegistrableDomain):
     121        * NetworkProcess/NetworkSession.h:
     122        * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDatabase.cpp: Added.
     123        (WebKit::PCM::Database::Database):
     124        (WebKit::PCM::Database::~Database):
     125        (WebKit::PCM::Database::interruptAllDatabases):
     126        (WebKit::PCM::Database::createSchema):
     127        (WebKit::PCM::Database::insertPrivateClickMeasurement):
     128        (WebKit::PCM::Database::markAllUnattributedPrivateClickMeasurementAsExpiredForTesting):
     129        (WebKit::PCM::Database::findPrivateClickMeasurement):
     130        (WebKit::PCM::Database::attributePrivateClickMeasurement):
     131        (WebKit::PCM::Database::buildPrivateClickMeasurementFromDatabase):
     132        (WebKit::PCM::Database::removeUnattributed):
     133        (WebKit::PCM::Database::allAttributedPrivateClickMeasurement):
     134        (WebKit::PCM::Database::privateClickMeasurementToStringForTesting):
     135        (WebKit::PCM::Database::attributionToStringForTesting):
     136        (WebKit::PCM::Database::markAttributedPrivateClickMeasurementsAsExpiredForTesting):
     137        (WebKit::PCM::Database::clearPrivateClickMeasurement):
     138        (WebKit::PCM::Database::clearExpiredPrivateClickMeasurement):
     139        (WebKit::PCM::Database::clearSentAttribution):
     140        (WebKit::PCM::Database::markReportAsSentToDestination):
     141        (WebKit::PCM::Database::markReportAsSentToSource):
     142        (WebKit::PCM::Database::earliestTimesToSend):
     143        (WebKit::PCM::Database::domainID):
     144        (WebKit::PCM::Database::getDomainStringFromDomainID):
     145        (WebKit::PCM::Database::ensureDomainID):
     146        (WebKit::PCM::Database::destroyStatements):
     147        * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDatabase.h: Added.
     148        * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDebugInfo.cpp: Copied from Source/WebKit/NetworkProcess/webrtc/NetworkRTCResolver.h.
     149        (WebKit::PCM::DebugInfo::isolatedCopy const):
     150        (WebKit::PCM::DebugInfo::Message::isolatedCopy const):
     151        * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDebugInfo.h: Copied from Source/WebKit/NetworkProcess/webrtc/NetworkRTCResolver.h.
     152        * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementStore.cpp: Added.
     153        (WebKit::PCM::sharedWorkQueue):
     154        (WebKit::PCM::Store::prepareForProcessToSuspend):
     155        (WebKit::PCM::Store::processDidResume):
     156        (WebKit::PCM::Store::Store):
     157        (WebKit::PCM::Store::postTask):
     158        (WebKit::PCM::Store::postTaskReply):
     159        (WebKit::PCM::Store::insertPrivateClickMeasurement):
     160        (WebKit::PCM::Store::markAllUnattributedPrivateClickMeasurementAsExpiredForTesting):
     161        (WebKit::PCM::Store::attributePrivateClickMeasurement):
     162        (WebKit::PCM::Store::privateClickMeasurementToStringForTesting):
     163        (WebKit::PCM::Store::allAttributedPrivateClickMeasurement):
     164        (WebKit::PCM::Store::markAttributedPrivateClickMeasurementsAsExpiredForTesting):
     165        (WebKit::PCM::Store::clearPrivateClickMeasurement):
     166        (WebKit::PCM::Store::clearPrivateClickMeasurementForRegistrableDomain):
     167        (WebKit::PCM::Store::clearExpiredPrivateClickMeasurement):
     168        (WebKit::PCM::Store::clearSentAttribution):
     169        (WebKit::PCM::Store::close):
     170        * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementStore.h: Added.
     171        (WebKit::PCM::Store::create):
     172        * NetworkProcess/PrivateClickMeasurementManager.cpp:
     173        (WebKit::PrivateClickMeasurementManager::insertPrivateClickMeasurement):
     174        (WebKit::PrivateClickMeasurementManager::attribute):
     175        (WebKit::PrivateClickMeasurementManager::clearSentAttribution):
     176        (WebKit::PrivateClickMeasurementManager::firePendingAttributionRequests):
     177        (WebKit::PrivateClickMeasurementManager::clear):
     178        (WebKit::PrivateClickMeasurementManager::clearForRegistrableDomain):
     179        (WebKit::PrivateClickMeasurementManager::clearExpired):
     180        (WebKit::PrivateClickMeasurementManager::toStringForTesting const):
     181        (WebKit::PrivateClickMeasurementManager::markAllUnattributedAsExpiredForTesting):
     182        (WebKit::PrivateClickMeasurementManager::markAttributedPrivateClickMeasurementsAsExpiredForTesting):
     183        (WebKit::PrivateClickMeasurementManager::toString const): Deleted.
     184        * NetworkProcess/PrivateClickMeasurementManager.h:
     185        * NetworkProcess/PrivateClickMeasurementNetworkLoader.cpp:
     186        (WebKit::PrivateClickMeasurementNetworkLoader::~PrivateClickMeasurementNetworkLoader):
     187        (WebKit::PrivateClickMeasurementNetworkLoader::cancel):
     188        (WebKit::PrivateClickMeasurementNetworkLoader::willSendRedirectedRequest):
     189        * NetworkProcess/PrivateClickMeasurementNetworkLoader.h:
     190        * NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp:
     191        * NetworkProcess/webrtc/NetworkRTCResolver.h:
     192        * NetworkProcess/webrtc/NetworkRTCResolverCocoa.cpp:
     193        (WebKit::resolvedName):
     194        * Shared/ResourceLoadStatisticsParameters.h:
     195        (WebKit::ResourceLoadStatisticsParameters::encode const):
     196        (WebKit::ResourceLoadStatisticsParameters::decode):
     197        * Sources.txt:
     198        * UIProcess/API/Cocoa/WKWebsiteDataStore.mm:
     199        (+[WKWebsiteDataStore _setNetworkProcessSuspensionAllowedForTesting:]):
     200        (+[WKWebsiteDataStore _preventNetworkProcessSuspensionForTesting]): Deleted.
     201        * UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h:
     202        * UIProcess/API/Cocoa/_WKWebsiteDataStoreConfiguration.h:
     203        * UIProcess/API/Cocoa/_WKWebsiteDataStoreConfiguration.mm:
     204        (-[_WKWebsiteDataStoreConfiguration privateClickMeasurementStorageDirectory]):
     205        (-[_WKWebsiteDataStoreConfiguration setPrivateClickMeasurementStorageDirectory:]):
     206        * UIProcess/Network/NetworkProcessProxy.cpp:
     207        (WebKit::NetworkProcessProxy::setSuspensionAllowedForTesting):
     208        (WebKit::NetworkProcessProxy::sendPrepareToSuspend):
     209        (WebKit::NetworkProcessProxy::preventSuspensionForTesting): Deleted.
     210        * UIProcess/Network/NetworkProcessProxy.h:
     211        * UIProcess/WebsiteData/WebsiteDataStore.cpp:
     212        (WebKit::WebsiteDataStore::resolveDirectoriesIfNecessary):
     213        (WebKit::WebsiteDataStore::parameters):
     214        * UIProcess/WebsiteData/WebsiteDataStoreConfiguration.cpp:
     215        (WebKit::WebsiteDataStoreConfiguration::copy const):
     216        * UIProcess/WebsiteData/WebsiteDataStoreConfiguration.h:
     217        (WebKit::WebsiteDataStoreConfiguration::privateClickMeasurementStorageDirectory const):
     218        (WebKit::WebsiteDataStoreConfiguration::setPrivateClickMeasurementStorageDirectory):
     219        * WebKit.xcodeproj/project.pbxproj:
     220
    12212021-08-27  Chris Dumez  <cdumez@apple.com>
    2222
  • trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp

    r280934 r281721  
    3333#include "PluginProcessManager.h"
    3434#include "PluginProcessProxy.h"
    35 #include "PrivateClickMeasurementManager.h"
    3635#include "ResourceLoadStatisticsMemoryStore.h"
    3736#include "StorageAccessStatus.h"
     
    4544#include <WebCore/SQLiteDatabase.h>
    4645#include <WebCore/SQLiteStatement.h>
     46#include <WebCore/SQLiteStatementAutoResetScope.h>
    4747#include <WebCore/UserGestureIndicator.h>
    4848#include <wtf/CallbackAggregator.h>
     
    8989constexpr auto subresourceUnderTopFrameDomainsQuery = "INSERT OR REPLACE INTO SubresourceUnderTopFrameDomains (subresourceDomainID, lastUpdated, topFrameDomainID) SELECT ?, ?, domainID FROM ObservedDomains WHERE registrableDomain in ( "_s;
    9090constexpr auto subresourceUniqueRedirectsToQuery = "INSERT OR REPLACE INTO SubresourceUniqueRedirectsTo (subresourceDomainID, lastUpdated, toDomainID) SELECT ?, ?, domainID FROM ObservedDomains WHERE registrableDomain in ( "_s;
    91 constexpr auto insertUnattributedPrivateClickMeasurementQuery = "INSERT OR REPLACE INTO UnattributedPrivateClickMeasurement (sourceSiteDomainID, destinationSiteDomainID, "
    92     "sourceID, timeOfAdClick, token, signature, keyID) VALUES (?, ?, ?, ?, ?, ?, ?)"_s;
    93 constexpr auto insertAttributedPrivateClickMeasurementQuery = "INSERT OR REPLACE INTO AttributedPrivateClickMeasurement (sourceSiteDomainID, destinationSiteDomainID, "
    94     "sourceID, attributionTriggerData, priority, timeOfAdClick, earliestTimeToSendToSource, token, signature, keyID, earliestTimeToSendToDestination) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"_s;
    9591
    9692// EXISTS Queries
     
    117113constexpr auto updateGrandfatheredQuery = "UPDATE ObservedDomains SET grandfathered = ? WHERE registrableDomain = ?"_s;
    118114constexpr auto updateIsScheduledForAllButCookieDataRemovalQuery = "UPDATE ObservedDomains SET isScheduledForAllButCookieDataRemoval = ? WHERE registrableDomain = ?"_s;
    119 constexpr auto setUnattributedPrivateClickMeasurementAsExpiredQuery = "UPDATE UnattributedPrivateClickMeasurement SET timeOfAdClick = -1.0"_s;
    120 constexpr auto markReportAsSentToSourceQuery = "UPDATE AttributedPrivateClickMeasurement SET earliestTimeToSendToSource = null WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ?"_s;
    121 constexpr auto markReportAsSentToDestinationQuery = "UPDATE AttributedPrivateClickMeasurement SET earliestTimeToSendToDestination = null WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ?"_s;
    122115
    123116// SELECT Queries
     
    138131    "UNION ALL SELECT topFrameDomainID FROM SubresourceUnderTopFrameDomains WHERE subresourceDomainID = ?"
    139132    "UNION ALL SELECT toDomainID FROM SubresourceUniqueRedirectsTo WHERE subresourceDomainID = ?"_s;
    140 constexpr auto allUnattributedPrivateClickMeasurementAttributionsQuery = "SELECT * FROM UnattributedPrivateClickMeasurement"_s;
    141 constexpr auto allAttributedPrivateClickMeasurementQuery = "SELECT *, MIN(earliestTimeToSendToSource, earliestTimeToSendToDestination) as minVal "
    142     "FROM AttributedPrivateClickMeasurement WHERE earliestTimeToSendToSource IS NOT NULL AND earliestTimeToSendToDestination IS NOT NULL "
    143     "UNION ALL SELECT *, earliestTimeToSendToSource as minVal FROM AttributedPrivateClickMeasurement WHERE earliestTimeToSendToDestination IS NULL "
    144     "UNION ALL SELECT *, earliestTimeToSendToDestination as minVal FROM AttributedPrivateClickMeasurement WHERE earliestTimeToSendToSource IS NULL ORDER BY minVal"_s;
    145 constexpr auto findUnattributedQuery = "SELECT * FROM UnattributedPrivateClickMeasurement WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ?"_s;
    146 constexpr auto findAttributedQuery = "SELECT * FROM AttributedPrivateClickMeasurement WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ?"_s;
    147 constexpr auto earliestTimesToSendQuery = "SELECT earliestTimeToSendToSource, earliestTimeToSendToDestination FROM AttributedPrivateClickMeasurement WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ?"_s;
    148133
    149134// EXISTS for testing queries
     
    157142// DELETE Queries
    158143constexpr auto removeAllDataQuery = "DELETE FROM ObservedDomains WHERE domainID = ?"_s;
    159 constexpr auto clearUnattributedPrivateClickMeasurementQuery = "DELETE FROM UnattributedPrivateClickMeasurement WHERE sourceSiteDomainID LIKE ? OR destinationSiteDomainID LIKE ?"_s;
    160 constexpr auto clearAttributedPrivateClickMeasurementQuery = "DELETE FROM AttributedPrivateClickMeasurement WHERE sourceSiteDomainID LIKE ? OR destinationSiteDomainID LIKE ?"_s;
    161 constexpr auto clearExpiredPrivateClickMeasurementQuery = "DELETE FROM UnattributedPrivateClickMeasurement WHERE ? > timeOfAdClick"_s;
    162 constexpr auto removeUnattributedQuery = "DELETE FROM UnattributedPrivateClickMeasurement WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ?"_s;
    163144
    164145constexpr auto createObservedDomain = "CREATE TABLE ObservedDomains ("
     
    241222    "year INTEGER NOT NULL, month INTEGER NOT NULL, monthDay INTEGER NOT NULL)"_s;
    242223
    243 constexpr auto createUnattributedPrivateClickMeasurement = "CREATE TABLE UnattributedPrivateClickMeasurement ("
    244     "sourceSiteDomainID INTEGER NOT NULL, destinationSiteDomainID INTEGER NOT NULL, sourceID INTEGER NOT NULL, "
    245     "timeOfAdClick REAL NOT NULL, token TEXT, signature TEXT, keyID TEXT, FOREIGN KEY(sourceSiteDomainID) "
    246     "REFERENCES ObservedDomains(domainID) ON DELETE CASCADE, FOREIGN KEY(destinationSiteDomainID) REFERENCES "
    247     "ObservedDomains(domainID) ON DELETE CASCADE)"_s;
    248 
    249 constexpr auto createAttributedPrivateClickMeasurement = "CREATE TABLE AttributedPrivateClickMeasurement ("
    250     "sourceSiteDomainID INTEGER NOT NULL, destinationSiteDomainID INTEGER NOT NULL, sourceID INTEGER NOT NULL, "
    251     "attributionTriggerData INTEGER NOT NULL, priority INTEGER NOT NULL, timeOfAdClick REAL NOT NULL, "
    252     "earliestTimeToSendToSource REAL, token TEXT, signature TEXT, keyID TEXT, earliestTimeToSendToDestination REAL, "
    253     "FOREIGN KEY(sourceSiteDomainID) REFERENCES ObservedDomains(domainID) ON DELETE CASCADE, FOREIGN KEY(destinationSiteDomainID) REFERENCES "
    254     "ObservedDomains(domainID) ON DELETE CASCADE)"_s;
    255 
    256224// CREATE UNIQUE INDEX Queries.
    257225constexpr auto createUniqueIndexStorageAccessUnderTopFrameDomains = "CREATE UNIQUE INDEX IF NOT EXISTS StorageAccessUnderTopFrameDomains_domainID_topLevelDomainID on StorageAccessUnderTopFrameDomains ( domainID, topLevelDomainID )"_s;
     
    266234constexpr auto createUniqueIndexSubresourceUniqueRedirectsFrom = "CREATE UNIQUE INDEX IF NOT EXISTS SubresourceUniqueRedirectsFrom_subresourceDomainID_fromDomainID on SubresourceUniqueRedirectsFrom ( subresourceDomainID, fromDomainID )"_s;
    267235constexpr auto createUniqueIndexOperatingDates = "CREATE UNIQUE INDEX IF NOT EXISTS OperatingDates_year_month_monthDay on OperatingDates ( year, month, monthDay )"_s;
    268 constexpr auto createUniqueIndexUnattributedPrivateClickMeasurement = "CREATE UNIQUE INDEX IF NOT EXISTS UnattributedPrivateClickMeasurement_sourceSiteDomainID_destinationSiteDomainID on UnattributedPrivateClickMeasurement ( sourceSiteDomainID, destinationSiteDomainID )"_s;
    269 constexpr auto createUniqueIndexAttributedPrivateClickMeasurement = "CREATE UNIQUE INDEX IF NOT EXISTS AttributedPrivateClickMeasurement_sourceSiteDomainID_destinationSiteDomainID on AttributedPrivateClickMeasurement ( sourceSiteDomainID, destinationSiteDomainID )"_s;
    270236
    271237// Add one to the count of the above index queries to account for the ObservedDomains table, which has an index automatically created by SQLite because of its primary key.
    272 const int expectedIndexCount = 14;
     238constexpr int expectedIndexCount = 12;
    273239
    274240static const String ObservedDomainsTableSchemaV1()
     
    280246{
    281247    return "CREATE TABLE \"ObservedDomains\" (domainID INTEGER PRIMARY KEY, registrableDomain TEXT NOT NULL UNIQUE ON CONFLICT FAIL, lastSeen REAL NOT NULL, hadUserInteraction INTEGER NOT NULL, mostRecentUserInteractionTime REAL NOT NULL, grandfathered INTEGER NOT NULL, isPrevalent INTEGER NOT NULL, isVeryPrevalent INTEGER NOT NULL, dataRecordsRemoved INTEGER NOT NULL,timesAccessedAsFirstPartyDueToUserInteraction INTEGER NOT NULL, timesAccessedAsFirstPartyDueToStorageAccessAPI INTEGER NOT NULL,isScheduledForAllButCookieDataRemoval INTEGER NOT NULL)"_s;
    282 }
    283 
    284 static const ExpectedColumns& expectedUnattributedColumns()
    285 {
    286     static const auto columns = makeNeverDestroyed(Vector<String> { "sourceSiteDomainID"_s, "destinationSiteDomainID"_s, "sourceID"_s, "timeOfAdClick"_s, "token"_s, "signature"_s, "keyID"_s });
    287     return columns.get();
    288 }
    289 
    290 static const ExpectedColumns& expectedAttributedColumns()
    291 {
    292     static const auto columns = makeNeverDestroyed(Vector<String> { "sourceSiteDomainID"_s, "destinationSiteDomainID"_s, "sourceID"_s, "attributionTriggerData"_s, "priority"_s, "timeOfAdClick"_s, "earliestTimeToSendToSource"_s, "token"_s, "signature"_s, "keyID"_s, "earliestTimeToSendToDestination"_s });
    293     return columns.get();
    294248}
    295249
     
    320274        { "SubresourceUniqueRedirectsFrom"_s, std::make_pair<String, std::optional<String>>(createSubresourceUniqueRedirectsFrom, stripIndexQueryToMatchStoredValue(createUniqueIndexSubresourceUniqueRedirectsFrom)) },
    321275        { "OperatingDates"_s, std::make_pair<String, std::optional<String>>(createOperatingDates, stripIndexQueryToMatchStoredValue(createUniqueIndexOperatingDates)) },
    322         { "UnattributedPrivateClickMeasurement"_s, std::make_pair<String, std::optional<String>>(createUnattributedPrivateClickMeasurement, stripIndexQueryToMatchStoredValue(createUniqueIndexUnattributedPrivateClickMeasurement)) },
    323         { "AttributedPrivateClickMeasurement"_s, std::make_pair<String, std::optional<String>>(createAttributedPrivateClickMeasurement, stripIndexQueryToMatchStoredValue(createUniqueIndexAttributedPrivateClickMeasurement)) }
    324276    });
    325277   
     
    340292}
    341293
    342 HashSet<ResourceLoadStatisticsDatabaseStore*>& ResourceLoadStatisticsDatabaseStore::allStores()
     294static HashSet<ResourceLoadStatisticsDatabaseStore*>& allStores()
    343295{
    344296    ASSERT(!RunLoop::isMain());
     
    350302ResourceLoadStatisticsDatabaseStore::ResourceLoadStatisticsDatabaseStore(WebResourceLoadStatisticsStore& store, SuspendableWorkQueue& workQueue, ShouldIncludeLocalhost shouldIncludeLocalhost, const String& storageDirectoryPath, PAL::SessionID sessionID)
    351303    : ResourceLoadStatisticsStore(store, workQueue, shouldIncludeLocalhost)
    352     , m_storageDirectoryPath(FileSystem::pathByAppendingComponent(storageDirectoryPath, "observations.db"_s))
    353     , m_transaction(m_database)
     304    , DatabaseUtilities(FileSystem::pathByAppendingComponent(storageDirectoryPath, "observations.db"_s))
    354305    , m_sessionID(sessionID)
    355306{
     
    358309    openAndUpdateSchemaIfNecessary();
    359310    enableForeignKeys();
    360 
    361     // Since we are using a workerQueue, the sequential dispatch blocks may be called by different threads.
    362     m_database.disableThreadingChecks();
    363311   
    364312    if (!m_database.turnOnIncrementalAutoVacuum())
     
    375323}
    376324
    377 void ResourceLoadStatisticsDatabaseStore::close()
    378 {
    379     destroyStatements();
    380     if (m_database.isOpen())
    381         m_database.close();
    382 }
    383 
    384325void ResourceLoadStatisticsDatabaseStore::openITPDatabase()
    385326{
    386     if (!FileSystem::fileExists(m_storageDirectoryPath)) {
    387         if (!FileSystem::makeAllDirectories(FileSystem::parentPath(m_storageDirectoryPath))) {
    388             RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::open failed, error message: Failed to create directory database path: %" PUBLIC_LOG_STRING, this, m_storageDirectoryPath.utf8().data());
    389             return;
    390         }
    391         m_isNewResourceLoadStatisticsDatabaseFile = true;
    392     } else
    393         m_isNewResourceLoadStatisticsDatabaseFile = false;
    394 
    395     if (!m_database.open(m_storageDirectoryPath)) {
    396         RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::open failed, error message: %" PUBLIC_LOG_STRING ", database path: %" PUBLIC_LOG_STRING, this, m_database.lastErrorMsg(), m_storageDirectoryPath.utf8().data());
    397         ASSERT_NOT_REACHED();
    398     }
    399    
    400     auto setBusyTimeout = m_database.prepareStatement("PRAGMA busy_timeout = 5000"_s);
    401     if (!setBusyTimeout || setBusyTimeout->step() != SQLITE_ROW) {
    402         RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::setBusyTimeout failed, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    403         ASSERT_NOT_REACHED();
    404         return;
    405     }
    406 
    407     if (m_isNewResourceLoadStatisticsDatabaseFile) {
    408         if (!createSchema()) {
    409             RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::createSchema failed, error message: %" PUBLIC_LOG_STRING ", database path: %" PUBLIC_LOG_STRING, this, m_database.lastErrorMsg(), m_storageDirectoryPath.utf8().data());
    410             ASSERT_NOT_REACHED();
    411             return;
    412         }
    413     }
     327    m_isNewResourceLoadStatisticsDatabaseFile = openDatabaseAndCreateSchemaIfNecessary() == CreatedNewFile::Yes;
    414328}
    415329
     
    440354}
    441355
    442 void ResourceLoadStatisticsDatabaseStore::enableForeignKeys()
    443 {
    444     auto enableForeignKeys = m_database.prepareStatement("PRAGMA foreign_keys = ON"_s);
    445     if (!enableForeignKeys || enableForeignKeys->step() != SQLITE_DONE) {
    446         RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::enableForeignKeys failed, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    447         ASSERT_NOT_REACHED();
    448         return;
    449     }
    450 }
    451 
    452356TableAndIndexPair ResourceLoadStatisticsDatabaseStore::currentTableAndIndexQueries(const String& tableName)
    453357{
     
    496400}
    497401
    498 bool ResourceLoadStatisticsDatabaseStore::needsUpdatedPrivateClickMeasurementSchema()
    499 {
    500     auto currentSchema = currentTableAndIndexQueries("AttributedPrivateClickMeasurement"_s).first;
    501 
    502     if (!currentSchema.isEmpty() && currentSchema != createAttributedPrivateClickMeasurement)
    503         return true;
    504 
    505     return false;
    506 }
    507 
    508402bool ResourceLoadStatisticsDatabaseStore::missingUniqueIndices()
    509403{
     
    538432    // There are 3 cases where we expect potential schema changes due to upgrades.
    539433    // All other tables should be up-to-date, so we should ASSERT that they are correct.
    540     if (missingReferenceToObservedDomains() || needsUpdatedPrivateClickMeasurementSchema() || missingUniqueIndices())
     434    if (missingReferenceToObservedDomains() || missingUniqueIndices())
    541435        return true;
    542436
     
    562456    if (table == "TopFrameLinkDecorationsFrom")
    563457        return database.prepareStatement("INSERT INTO TopFrameLinkDecorationsFrom SELECT toDomainID, MAX(lastUpdated), fromDomainID FROM _TopFrameLinkDecorationsFrom GROUP BY toDomainID, fromDomainID"_s);
    564 
    565     if (table == "UnattributedPrivateClickMeasurement")
    566         return database.prepareStatement("INSERT INTO UnattributedPrivateClickMeasurement SELECT sourceSiteDomainID, destinationSiteDomainID, sourceID, MAX(timeOfAdClick), token, signature, keyID FROM _UnattributedPrivateClickMeasurement GROUP BY sourceSiteDomainID, destinationSiteDomainID"_s);
    567 
    568     if (table == "AttributedPrivateClickMeasurement")
    569         return database.prepareStatement("INSERT INTO AttributedPrivateClickMeasurement SELECT sourceSiteDomainID, destinationSiteDomainID, sourceID, attributionTriggerData, priority, MAX(timeOfAdClick), earliestTimeToSendToSource, token, signature, keyID, earliestTimeToSendToDestination FROM _AttributedPrivateClickMeasurement GROUP BY sourceSiteDomainID, destinationSiteDomainID"_s);
    570458
    571459    return database.prepareStatementSlow(makeString("INSERT INTO ", table, " SELECT DISTINCT * FROM _", table));
     
    634522
    635523    return columns;
    636 }
    637 
    638 void ResourceLoadStatisticsDatabaseStore::addMissingColumnsToTable(String&& tableName, const ExistingColumns& existingColumns, const ExpectedColumns& expectedColumns)
    639 {
    640     ASSERT(existingColumns.size() <= expectedColumns.size());
    641 
    642     auto transaction = beginTransactionIfNecessary();
    643 
    644     for (auto& column : expectedColumns) {
    645         if (existingColumns.contains(column))
    646             continue;
    647 
    648         auto statement = m_database.prepareStatementSlow(makeString("ALTER TABLE ", tableName, " ADD COLUMN ", column));
    649         if (!statement) {
    650             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());
    651             ASSERT_NOT_REACHED();
    652             return;
    653         }
    654         if (statement->step() != SQLITE_DONE) {
    655             RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::addMissingColumnsToTable error executing statement to add missing columns to table, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    656             ASSERT_NOT_REACHED();
    657             return;
    658         }
    659         statement->reset();
    660     }
    661 }
    662 
    663 void ResourceLoadStatisticsDatabaseStore::addMissingColumnsIfNecessary()
    664 {
    665     const auto unattributedTableName = "UnattributedPrivateClickMeasurement"_s;
    666     const auto attributedTableName = "AttributedPrivateClickMeasurement"_s;
    667 
    668     addMissingColumnsToTable(unattributedTableName, columnsForTable(unattributedTableName), expectedUnattributedColumns());
    669     addMissingColumnsToTable(attributedTableName, columnsForTable(attributedTableName), expectedAttributedColumns());
    670 }
    671 
    672 void ResourceLoadStatisticsDatabaseStore::renameColumnInTable(String&& tableName, ExistingColumnName&& existingColumnName, ExpectedColumnName&& expectedColumnName)
    673 {
    674     auto statement = m_database.prepareStatementSlow(makeString("ALTER TABLE ", tableName, " RENAME COLUMN ", existingColumnName, " TO ", expectedColumnName));
    675     if (!statement) {
    676         RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::addMissingColumnsToTable Unable to prepare statement to rename column in table, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    677         ASSERT_NOT_REACHED();
    678         return;
    679     }
    680     if (statement->step() != SQLITE_DONE) {
    681         RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::addMissingColumnsToTable error executing statement to rename column in table, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    682         ASSERT_NOT_REACHED();
    683         return;
    684     }
    685 }
    686 
    687 void ResourceLoadStatisticsDatabaseStore::renameColumnsIfNecessary()
    688 {
    689     // Attributed Private Click Measurement case.
    690     const auto attributedTableName = "AttributedPrivateClickMeasurement"_s;
    691     const auto oldEarliestTimeToSendColumn = "earliestTimeToSend"_s;
    692     const auto newEarliestTimeToSendColumn = "earliestTimeToSendToSource"_s;
    693     const auto oldAttributionDestinationColumn = "attributeOnSiteDomainID"_s;
    694     const auto newAttributionDestinationColumn = "destinationSiteDomainID"_s;
    695     const auto foundAttributedTableColumns = columnsForTable(attributedTableName);
    696 
    697     if (foundAttributedTableColumns.contains(oldEarliestTimeToSendColumn))
    698         renameColumnInTable(attributedTableName, oldEarliestTimeToSendColumn, newEarliestTimeToSendColumn);
    699 
    700     if (foundAttributedTableColumns.contains(oldAttributionDestinationColumn))
    701         renameColumnInTable(attributedTableName, oldAttributionDestinationColumn, newAttributionDestinationColumn);
    702 
    703     // Unattributed Private Click Measurement case.
    704     auto unattributedTableName = "UnattributedPrivateClickMeasurement"_s;
    705     auto foundUnattributedTableColumns = columnsForTable(unattributedTableName);
    706 
    707     if (foundUnattributedTableColumns.contains(oldAttributionDestinationColumn))
    708         renameColumnInTable(unattributedTableName, oldAttributionDestinationColumn, newAttributionDestinationColumn);
    709524}
    710525
     
    749564            LOG_ERROR("Error executing statement to fetch schema for the Observed Domains table.");
    750565            close();
    751             FileSystem::deleteFile(m_storageDirectoryPath);
     566            FileSystem::deleteFile(m_storageFilePath);
    752567            openITPDatabase();
    753568            return;
     
    763578    if (currentSchema != ObservedDomainsTableSchemaV1() && currentSchema != ObservedDomainsTableSchemaV1Alternate()) {
    764579        close();
    765         FileSystem::deleteFile(m_storageDirectoryPath);
     580        FileSystem::deleteFile(m_storageFilePath);
    766581        openITPDatabase();
    767582        return;
     
    769584
    770585    // Renaming and adding columns should be done before migrating to avoid mismatched or missing columns.
    771     renameColumnsIfNecessary();
    772     addMissingColumnsIfNecessary();
    773586    migrateDataToNewTablesIfNecessary();
    774587}
    775588
    776 SQLiteStatementAutoResetScope ResourceLoadStatisticsDatabaseStore::scopedStatement(std::unique_ptr<WebCore::SQLiteStatement>& statement, ASCIILiteral query, const String& logString) const
    777 {
    778     if (!statement) {
    779         auto statementOrError = m_database.prepareHeapStatement(query);
    780         if (!statementOrError) {
    781             RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::%s failed to prepare statement, error message: %" PUBLIC_LOG_STRING, this, logString.ascii().data(), m_database.lastErrorMsg());
    782             ASSERT_NOT_REACHED();
    783             return SQLiteStatementAutoResetScope { };
    784         }
    785         statement = statementOrError.value().moveToUniquePtr();
    786         ASSERT(m_database.isOpen());
    787     }
    788     return SQLiteStatementAutoResetScope { statement.get() };
    789 }
    790 
    791 void ResourceLoadStatisticsDatabaseStore::interrupt()
    792 {
    793     if (m_database.isOpen())
    794         m_database.interrupt();
     589void ResourceLoadStatisticsDatabaseStore::interruptAllDatabases()
     590{
     591    ASSERT(!RunLoop::isMain());
     592    for (auto store : allStores())
     593        store->interrupt();
    795594}
    796595
     
    822621        || !m_database.executeCommand(createUniqueIndexSubresourceUniqueRedirectsFrom)
    823622        || !m_database.executeCommand(createUniqueIndexSubresourceUnderTopFrameDomains)
    824         || !m_database.executeCommand(createUniqueIndexOperatingDates)
    825         || !m_database.executeCommand(createUniqueIndexUnattributedPrivateClickMeasurement)
    826         || !m_database.executeCommand(createUniqueIndexAttributedPrivateClickMeasurement)) {
     623        || !m_database.executeCommand(createUniqueIndexOperatingDates)) {
    827624        RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::createUniqueIndices failed to execute, error message: %" PUBLIC_LOG_STRING, this, m_database.lastErrorMsg());
    828625        return false;
     
    897694    if (!m_database.executeCommand(createOperatingDates)) {
    898695        LOG_ERROR("Could not create OperatingDates table in database (%i) - %s", m_database.lastError(), m_database.lastErrorMsg());
    899         return false;
    900     }
    901 
    902     if (!m_database.executeCommand(createUnattributedPrivateClickMeasurement)) {
    903         LOG_ERROR("Could not create UnattributedPrivateClickMeasurement table in database (%i) - %s", m_database.lastError(), m_database.lastErrorMsg());
    904         return false;
    905     }
    906 
    907     if (!m_database.executeCommand(createAttributedPrivateClickMeasurement)) {
    908         LOG_ERROR("Could not create AttributedPrivateClickMeasurement table in database (%i) - %s", m_database.lastError(), m_database.lastErrorMsg());
    909696        return false;
    910697    }
     
    957744    m_observedDomainsExistsStatement = nullptr;
    958745    m_removeAllDataStatement = nullptr;
    959     m_insertUnattributedPrivateClickMeasurementStatement = nullptr;
    960     m_insertAttributedPrivateClickMeasurementStatement = nullptr;
    961     m_setUnattributedPrivateClickMeasurementAsExpiredStatement = nullptr;
    962     m_clearUnattributedPrivateClickMeasurementStatement = nullptr;
    963     m_clearAttributedPrivateClickMeasurementStatement = nullptr;
    964     m_clearExpiredPrivateClickMeasurementStatement = nullptr;
    965     m_allUnattributedPrivateClickMeasurementAttributionsStatement = nullptr;
    966     m_allAttributedPrivateClickMeasurementStatement = nullptr;
    967     m_findUnattributedStatement = nullptr;
    968     m_findAttributedStatement = nullptr;
    969     m_updateAttributionsEarliestTimeToSendStatement = nullptr;
    970     m_removeUnattributedStatement = nullptr;
    971     m_markReportAsSentToSourceStatement = nullptr;
    972     m_markReportAsSentToDestinationStatement = nullptr;
    973     m_earliestTimesToSendStatement = nullptr;
    974746}
    975747
     
    22882060
    22892061    if (!createSchema()) {
    2290         RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::clearDatabaseContents failed, error message: %" PRIVATE_LOG_STRING ", database path: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg(), m_storageDirectoryPath.utf8().data());
     2062        RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::clearDatabaseContents failed, error message: %" PRIVATE_LOG_STRING ", database path: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg(), m_storageFilePath.utf8().data());
    22912063        ASSERT_NOT_REACHED();
    22922064        return;
     
    31562928}
    31572929
    3158 PrivateClickMeasurement ResourceLoadStatisticsDatabaseStore::buildPrivateClickMeasurementFromDatabase(WebCore::SQLiteStatement* statement, PrivateClickMeasurementAttributionType attributionType)
    3159 {
    3160     auto sourceSiteDomain = getDomainStringFromDomainID(statement->columnInt(0));
    3161     auto destinationSiteDomain = getDomainStringFromDomainID(statement->columnInt(1));
    3162     auto sourceID = statement->columnInt(2);
    3163     auto timeOfAdClick = attributionType == PrivateClickMeasurementAttributionType::Attributed ? statement->columnDouble(5) : statement->columnDouble(3);
    3164     auto token = attributionType == PrivateClickMeasurementAttributionType::Attributed ? statement->columnText(7) : statement->columnText(4);
    3165     auto signature = attributionType == PrivateClickMeasurementAttributionType::Attributed ? statement->columnText(8) : statement->columnText(5);
    3166     auto keyID = attributionType == PrivateClickMeasurementAttributionType::Attributed ? statement->columnText(9) : statement->columnText(6);
    3167 
    3168     PrivateClickMeasurement attribution(WebCore::PrivateClickMeasurement::SourceID(sourceID), WebCore::PrivateClickMeasurement::SourceSite(RegistrableDomain::uncheckedCreateFromRegistrableDomainString(sourceSiteDomain)), WebCore::PrivateClickMeasurement::AttributionDestinationSite(RegistrableDomain::uncheckedCreateFromRegistrableDomainString(destinationSiteDomain)), { }, { }, WallTime::fromRawSeconds(timeOfAdClick));
    3169    
    3170     if (attributionType == PrivateClickMeasurementAttributionType::Attributed) {
    3171         auto attributionTriggerData = statement->columnInt(3);
    3172         auto priority = statement->columnInt(4);
    3173         auto sourceEarliestTimeToSendValue = statement->columnDouble(6);
    3174         auto destinationEarliestTimeToSendValue = statement->columnDouble(10);
    3175 
    3176         if (attributionTriggerData != -1)
    3177             attribution.setAttribution(WebCore::PrivateClickMeasurement::AttributionTriggerData { static_cast<uint32_t>(attributionTriggerData), WebCore::PrivateClickMeasurement::Priority(priority) });
    3178 
    3179         std::optional<WallTime> sourceEarliestTimeToSend;
    3180         std::optional<WallTime> destinationEarliestTimeToSend;
    3181        
    3182         // A value of 0.0 indicates that the report has been sent to the respective site.
    3183         if (sourceEarliestTimeToSendValue > 0.0)
    3184             sourceEarliestTimeToSend = WallTime::fromRawSeconds(sourceEarliestTimeToSendValue);
    3185 
    3186         if (destinationEarliestTimeToSendValue > 0.0)
    3187             destinationEarliestTimeToSend = WallTime::fromRawSeconds(destinationEarliestTimeToSendValue);
    3188 
    3189         attribution.setTimesToSend({ sourceEarliestTimeToSend, destinationEarliestTimeToSend });
    3190     }
    3191 
    3192     attribution.setSourceSecretToken({ token, signature, keyID });
    3193 
    3194     return attribution;
    3195 }
    3196 
    3197 std::pair<std::optional<UnattributedPrivateClickMeasurement>, std::optional<AttributedPrivateClickMeasurement>> ResourceLoadStatisticsDatabaseStore::findPrivateClickMeasurement(const WebCore::PrivateClickMeasurement::SourceSite& sourceSite, const WebCore::PrivateClickMeasurement::AttributionDestinationSite& destinationSite)
    3198 {
    3199     auto sourceSiteDomainID = domainID(sourceSite.registrableDomain);
    3200     auto destinationSiteDomainID = domainID(destinationSite.registrableDomain);
    3201 
    3202     if (!sourceSiteDomainID || !destinationSiteDomainID)
    3203         return std::make_pair(std::nullopt, std::nullopt);
    3204 
    3205     auto findUnattributedScopedStatement = this->scopedStatement(m_findUnattributedStatement, findUnattributedQuery, "findPrivateClickMeasurement"_s);
    3206     if (!findUnattributedScopedStatement
    3207         || findUnattributedScopedStatement->bindInt(1, *sourceSiteDomainID) != SQLITE_OK
    3208         || findUnattributedScopedStatement->bindInt(2, *destinationSiteDomainID) != SQLITE_OK) {
    3209         ITP_RELEASE_LOG_ERROR(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::findPrivateClickMeasurement findUnattributedQuery, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    3210         ASSERT_NOT_REACHED();
    3211     }
    3212 
    3213     auto findAttributedScopedStatement = this->scopedStatement(m_findAttributedStatement, findAttributedQuery, "findPrivateClickMeasurement"_s);
    3214     if (!findAttributedScopedStatement
    3215         || findAttributedScopedStatement->bindInt(1, *sourceSiteDomainID) != SQLITE_OK
    3216         || findAttributedScopedStatement->bindInt(2, *destinationSiteDomainID) != SQLITE_OK) {
    3217         ITP_RELEASE_LOG_ERROR(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::findPrivateClickMeasurement findAttributedQuery, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    3218         ASSERT_NOT_REACHED();
    3219     }
    3220 
    3221     std::optional<UnattributedPrivateClickMeasurement> unattributedPrivateClickMeasurement;
    3222     if (findUnattributedScopedStatement->step() == SQLITE_ROW)
    3223         unattributedPrivateClickMeasurement = buildPrivateClickMeasurementFromDatabase(findUnattributedScopedStatement.get(), PrivateClickMeasurementAttributionType::Unattributed);
    3224 
    3225     std::optional<AttributedPrivateClickMeasurement> attributedPrivateClickMeasurement;
    3226     if (findAttributedScopedStatement->step() == SQLITE_ROW)
    3227         attributedPrivateClickMeasurement = buildPrivateClickMeasurementFromDatabase(findAttributedScopedStatement.get(), PrivateClickMeasurementAttributionType::Attributed);
    3228 
    3229     return std::make_pair(unattributedPrivateClickMeasurement, attributedPrivateClickMeasurement);
    3230 }
    3231 
    3232 void ResourceLoadStatisticsDatabaseStore::insertPrivateClickMeasurement(PrivateClickMeasurement&& attribution, PrivateClickMeasurementAttributionType attributionType)
    3233 {
    3234     auto transactionScope = beginTransactionIfNecessary();
    3235 
    3236     auto sourceData = ensureResourceStatisticsForRegistrableDomain(attribution.sourceSite().registrableDomain);
    3237     auto attributionDestinationData = ensureResourceStatisticsForRegistrableDomain(attribution.destinationSite().registrableDomain);
    3238 
    3239     if (!sourceData.second || !attributionDestinationData.second)
    3240         return;
    3241 
    3242     auto& sourceUnlinkableToken = attribution.sourceUnlinkableToken();
    3243     if (attributionType == PrivateClickMeasurementAttributionType::Attributed) {
    3244         auto attributionTriggerData = attribution.attributionTriggerData() ? attribution.attributionTriggerData().value().data : -1;
    3245         auto priority = attribution.attributionTriggerData() ? attribution.attributionTriggerData().value().priority : -1;
    3246         auto sourceEarliestTimeToSend = attribution.timesToSend().sourceEarliestTimeToSend ? attribution.timesToSend().sourceEarliestTimeToSend.value().secondsSinceEpoch().value() : -1;
    3247         auto destinationEarliestTimeToSend = attribution.timesToSend().destinationEarliestTimeToSend ? attribution.timesToSend().destinationEarliestTimeToSend.value().secondsSinceEpoch().value() : -1;
    3248 
    3249         // We should never be inserting an attributed private click measurement value into the database without valid report times.
    3250         ASSERT(sourceEarliestTimeToSend != -1 && destinationEarliestTimeToSend != -1);
    3251 
    3252         auto statement = m_database.prepareStatement(insertAttributedPrivateClickMeasurementQuery);
    3253         if (!statement
    3254             || statement->bindInt(1, *sourceData.second) != SQLITE_OK
    3255             || statement->bindInt(2, *attributionDestinationData.second) != SQLITE_OK
    3256             || statement->bindInt(3, attribution.sourceID().id) != SQLITE_OK
    3257             || statement->bindInt(4, attributionTriggerData) != SQLITE_OK
    3258             || statement->bindInt(5, priority) != SQLITE_OK
    3259             || statement->bindDouble(6, attribution.timeOfAdClick().secondsSinceEpoch().value()) != SQLITE_OK
    3260             || statement->bindDouble(7, sourceEarliestTimeToSend) != SQLITE_OK
    3261             || statement->bindText(8, sourceUnlinkableToken ? sourceUnlinkableToken->tokenBase64URL : emptyString()) != SQLITE_OK
    3262             || statement->bindText(9, sourceUnlinkableToken ? sourceUnlinkableToken->signatureBase64URL : emptyString()) != SQLITE_OK
    3263             || statement->bindText(10, sourceUnlinkableToken ? sourceUnlinkableToken->keyIDBase64URL : emptyString()) != SQLITE_OK
    3264             || statement->bindDouble(11, destinationEarliestTimeToSend) != SQLITE_OK
    3265             || statement->step() != SQLITE_DONE) {
    3266             ITP_RELEASE_LOG_ERROR(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::insertPrivateClickMeasurement insertAttributedPrivateClickMeasurementQuery, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    3267             ASSERT_NOT_REACHED();
    3268         }
    3269         return;
    3270     }
    3271 
    3272     auto statement = m_database.prepareStatement(insertUnattributedPrivateClickMeasurementQuery);
    3273     if (!statement
    3274         || statement->bindInt(1, *sourceData.second) != SQLITE_OK
    3275         || statement->bindInt(2, *attributionDestinationData.second) != SQLITE_OK
    3276         || statement->bindInt(3, attribution.sourceID().id) != SQLITE_OK
    3277         || statement->bindDouble(4, attribution.timeOfAdClick().secondsSinceEpoch().value()) != SQLITE_OK
    3278         || statement->bindText(5, sourceUnlinkableToken ? sourceUnlinkableToken->tokenBase64URL : emptyString()) != SQLITE_OK
    3279         || statement->bindText(6, sourceUnlinkableToken ? sourceUnlinkableToken->signatureBase64URL : emptyString()) != SQLITE_OK
    3280         || statement->bindText(7, sourceUnlinkableToken ? sourceUnlinkableToken->keyIDBase64URL : emptyString()) != SQLITE_OK
    3281         || statement->step() != SQLITE_DONE) {
    3282         ITP_RELEASE_LOG_ERROR(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::insertPrivateClickMeasurement insertUnattributedPrivateClickMeasurementQuery, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    3283         ASSERT_NOT_REACHED();
    3284     }
    3285 }
    3286 
    3287 void ResourceLoadStatisticsDatabaseStore::markAllUnattributedPrivateClickMeasurementAsExpiredForTesting()
    3288 {
    3289     auto scopedStatement = this->scopedStatement(m_setUnattributedPrivateClickMeasurementAsExpiredStatement, setUnattributedPrivateClickMeasurementAsExpiredQuery, "markAllUnattributedPrivateClickMeasurementAsExpiredForTesting"_s);
    3290 
    3291     if (!scopedStatement || scopedStatement->step() != SQLITE_DONE) {
    3292         ITP_RELEASE_LOG_ERROR(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::markAllUnattributedPrivateClickMeasurementAsExpiredForTesting, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    3293         ASSERT_NOT_REACHED();
    3294     }
    3295 }
    3296 
    3297 void ResourceLoadStatisticsDatabaseStore::removeUnattributed(PrivateClickMeasurement& attribution)
    3298 {
    3299     auto sourceSiteDomainID = domainID(attribution.sourceSite().registrableDomain);
    3300     auto destinationSiteDomainID = domainID(attribution.destinationSite().registrableDomain);
    3301 
    3302     if (!sourceSiteDomainID || !destinationSiteDomainID)
    3303         return;
    3304    
    3305     auto scopedStatement = this->scopedStatement(m_removeUnattributedStatement, removeUnattributedQuery, "removeUnattributed"_s);
    3306 
    3307     if (!scopedStatement
    3308         || scopedStatement->bindInt(1, *sourceSiteDomainID) != SQLITE_OK
    3309         || scopedStatement->bindInt(2, *destinationSiteDomainID) != SQLITE_OK
    3310         || scopedStatement->step() != SQLITE_DONE) {
    3311         ITP_RELEASE_LOG_ERROR(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::removeUnattributed, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    3312         ASSERT_NOT_REACHED();
    3313     }
    3314 }
    3315 
    3316 std::optional<PrivateClickMeasurement::AttributionSecondsUntilSendData> ResourceLoadStatisticsDatabaseStore::attributePrivateClickMeasurement(const SourceSite& sourceSite, const AttributionDestinationSite& destinationSite, AttributionTriggerData&& attributionTriggerData)
    3317 {
    3318     // We should always clear expired clicks from the database before scheduling an attribution.
    3319     clearExpiredPrivateClickMeasurement();
    3320 
    3321     if (!attributionTriggerData.isValid()) {
    3322         if (UNLIKELY(debugModeEnabled())) {
    3323             RELEASE_LOG_INFO(PrivateClickMeasurement, "Got an invalid attribution.");
    3324             debugBroadcastConsoleMessage(MessageSource::PrivateClickMeasurement, MessageLevel::Error, "[Private Click Measurement] Got an invalid attribution."_s);
    3325         }
    3326         return std::nullopt;
    3327     }
    3328 
    3329     auto data = attributionTriggerData.data;
    3330     auto priority = attributionTriggerData.priority;
    3331 
    3332     if (UNLIKELY(debugModeEnabled())) {
    3333         RELEASE_LOG_INFO(PrivateClickMeasurement, "Got an attribution with attribution trigger data: %{public}u and priority: %{public}u.", data, priority);
    3334         debugBroadcastConsoleMessage(MessageSource::PrivateClickMeasurement, MessageLevel::Info, makeString("[Private Click Measurement] Got an attribution with attribution trigger data: '"_s, data, "' and priority: '"_s, priority, "'."_s));
    3335     }
    3336 
    3337     PrivateClickMeasurement::AttributionSecondsUntilSendData secondsUntilSend { std::nullopt, std::nullopt };
    3338 
    3339     auto attribution = findPrivateClickMeasurement(sourceSite, destinationSite);
    3340     auto& previouslyUnattributed = attribution.first;
    3341     auto& previouslyAttributed = attribution.second;
    3342 
    3343     if (previouslyUnattributed) {
    3344         // Always convert the pending attribution and remove it from the unattributed map.
    3345         removeUnattributed(*previouslyUnattributed);
    3346         secondsUntilSend = previouslyUnattributed.value().attributeAndGetEarliestTimeToSend(WTFMove(attributionTriggerData));
    3347 
    3348         // We should always have a valid secondsUntilSend value for a previouslyUnattributed value because there can be no previous attribution with a higher priority.
    3349         if (!secondsUntilSend.hasValidSecondsUntilSendValues()) {
    3350             ASSERT_NOT_REACHED();
    3351             return std::nullopt;
    3352         }
    3353 
    3354         if (UNLIKELY(debugModeEnabled())) {
    3355             RELEASE_LOG_INFO(PrivateClickMeasurement, "Converted a stored ad click with attribution trigger data: %{public}u and priority: %{public}u.", data, priority);
    3356             debugBroadcastConsoleMessage(MessageSource::PrivateClickMeasurement, MessageLevel::Info, makeString("[Private Click Measurement] Converted a stored ad click with attribution trigger data: '"_s, data, "' and priority: '"_s, priority, "'."_s));
    3357         }
    3358 
    3359         // If there is no previous attribution, or the new attribution has higher priority, insert/update the database.
    3360         if (!previouslyAttributed || previouslyUnattributed.value().hasHigherPriorityThan(*previouslyAttributed)) {
    3361             insertPrivateClickMeasurement(WTFMove(*previouslyUnattributed), PrivateClickMeasurementAttributionType::Attributed);
    3362 
    3363             if (UNLIKELY(debugModeEnabled())) {
    3364                 RELEASE_LOG_INFO(PrivateClickMeasurement, "Replaced a previously converted ad click with a new one with attribution data: %{public}u and priority: %{public}u because it had higher priority.", data, priority);
    3365                 debugBroadcastConsoleMessage(MessageSource::PrivateClickMeasurement, MessageLevel::Info, makeString("[Private Click Measurement] Replaced a previously converted ad click with a new one with attribution trigger data: '"_s, data, "' and priority: '"_s, priority, "' because it had higher priority."_s));
    3366             }
    3367         }
    3368     } else if (previouslyAttributed) {
    3369         // If we have no new attribution, re-attribute the old one to respect the new priority, but only if this report has
    3370         // not been sent to the source or destination site yet.
    3371         if (!previouslyAttributed.value().hasPreviouslyBeenReported()) {
    3372             auto secondsUntilSend = previouslyAttributed.value().attributeAndGetEarliestTimeToSend(WTFMove(attributionTriggerData));
    3373             if (!secondsUntilSend.hasValidSecondsUntilSendValues())
    3374                 return std::nullopt;
    3375 
    3376             insertPrivateClickMeasurement(WTFMove(*previouslyAttributed), PrivateClickMeasurementAttributionType::Attributed);
    3377 
    3378             if (UNLIKELY(debugModeEnabled())) {
    3379                 RELEASE_LOG_INFO(PrivateClickMeasurement, "Re-converted an ad click with a new one with attribution trigger data: %{public}u and priority: %{public}u because it had higher priority.", data, priority);
    3380                 debugBroadcastConsoleMessage(MessageSource::PrivateClickMeasurement, MessageLevel::Info, makeString("[Private Click Measurement] Re-converted an ad click with a new one with attribution trigger data: '"_s, data, "' and priority: '"_s, priority, "'' because it had higher priority."_s));
    3381             }
    3382         }
    3383     }
    3384 
    3385     if (!secondsUntilSend.hasValidSecondsUntilSendValues())
    3386         return std::nullopt;
    3387 
    3388     return secondsUntilSend;
    3389 }
    3390 
    3391 Vector<WebCore::PrivateClickMeasurement> ResourceLoadStatisticsDatabaseStore::allAttributedPrivateClickMeasurement()
    3392 {
    3393     auto attributedScopedStatement = this->scopedStatement(m_allAttributedPrivateClickMeasurementStatement, allAttributedPrivateClickMeasurementQuery, "privateClickMeasurementToString"_s);
    3394 
    3395     if (!attributedScopedStatement) {
    3396         ITP_RELEASE_LOG_ERROR(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::privateClickMeasurementToString, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    3397         ASSERT_NOT_REACHED();
    3398         return { };
    3399     }
    3400 
    3401     Vector<WebCore::PrivateClickMeasurement> attributions;
    3402     while (attributedScopedStatement->step() == SQLITE_ROW)
    3403         attributions.append(buildPrivateClickMeasurementFromDatabase(attributedScopedStatement.get(), PrivateClickMeasurementAttributionType::Attributed));
    3404 
    3405     return attributions;
    3406 }
    3407 
    3408 void ResourceLoadStatisticsDatabaseStore::clearPrivateClickMeasurement(std::optional<RegistrableDomain> domain)
    3409 {
    3410     // Default to clear all entries if no domain is specified.
    3411     String bindParameter = "%";
    3412     if (domain) {
    3413         auto domainIDToMatch = domainID(*domain);
    3414         if (!domainIDToMatch)
    3415             return;
    3416 
    3417         bindParameter = String::number(*domainIDToMatch);
    3418     }
    3419 
    3420     auto transactionScope = beginTransactionIfNecessary();
    3421 
    3422     auto clearUnattributedScopedStatement = this->scopedStatement(m_clearUnattributedPrivateClickMeasurementStatement, clearUnattributedPrivateClickMeasurementQuery, "clearPrivateClickMeasurement"_s);
    3423 
    3424     if (!clearUnattributedScopedStatement
    3425         || clearUnattributedScopedStatement->bindText(1, bindParameter) != SQLITE_OK
    3426         || clearUnattributedScopedStatement->bindText(2, bindParameter) != SQLITE_OK
    3427         || clearUnattributedScopedStatement->step() != SQLITE_DONE) {
    3428         ITP_RELEASE_LOG_ERROR(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::clearPrivateClickMeasurement clearUnattributedScopedStatement, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    3429         ASSERT_NOT_REACHED();
    3430     }
    3431 
    3432     auto clearAttributedScopedStatement = this->scopedStatement(m_clearAttributedPrivateClickMeasurementStatement, clearAttributedPrivateClickMeasurementQuery, "clearPrivateClickMeasurement"_s);
    3433 
    3434     if (!clearAttributedScopedStatement
    3435         || clearAttributedScopedStatement->bindText(1, bindParameter) != SQLITE_OK
    3436         || clearAttributedScopedStatement->bindText(2, bindParameter) != SQLITE_OK
    3437         || clearAttributedScopedStatement->step() != SQLITE_DONE) {
    3438         ITP_RELEASE_LOG_ERROR(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::clearPrivateClickMeasurement clearAttributedScopedStatement, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    3439         ASSERT_NOT_REACHED();
    3440     }
    3441 }
    3442 
    3443 void ResourceLoadStatisticsDatabaseStore::clearExpiredPrivateClickMeasurement()
    3444 {
    3445     auto expirationTimeFrame = WallTime::now() - WebCore::PrivateClickMeasurement::maxAge();
    3446     auto scopedStatement = this->scopedStatement(m_clearExpiredPrivateClickMeasurementStatement, clearExpiredPrivateClickMeasurementQuery, "clearExpiredPrivateClickMeasurement"_s);
    3447 
    3448     if (!scopedStatement
    3449         || scopedStatement->bindDouble(1, expirationTimeFrame.secondsSinceEpoch().value()) != SQLITE_OK
    3450         || scopedStatement->step() != SQLITE_DONE) {
    3451         ITP_RELEASE_LOG_ERROR(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::clearExpiredPrivateClickMeasurement, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    3452         ASSERT_NOT_REACHED();
    3453     }
    3454 }
    3455 
    3456 String ResourceLoadStatisticsDatabaseStore::attributionToString(WebCore::SQLiteStatement* statement, PrivateClickMeasurementAttributionType attributionType)
    3457 {
    3458     auto sourceSiteDomain = getDomainStringFromDomainID(statement->columnInt(0));
    3459     auto destinationSiteDomain = getDomainStringFromDomainID(statement->columnInt(1));
    3460     auto sourceID = statement->columnInt(2);
    3461 
    3462     StringBuilder builder;
    3463     builder.append("Source site: ", sourceSiteDomain, "\nAttribute on site: ", destinationSiteDomain, "\nSource ID: ", sourceID);
    3464 
    3465     if (attributionType == PrivateClickMeasurementAttributionType::Attributed) {
    3466         auto attributionTriggerData = statement->columnInt(3);
    3467         auto priority = statement->columnInt(4);
    3468         auto earliestTimeToSend = statement->columnInt(6);
    3469 
    3470         if (attributionTriggerData != -1) {
    3471             builder.append("\nAttribution trigger data: ", attributionTriggerData, "\nAttribution priority: ", priority, "\nAttribution earliest time to send: ");
    3472             if (earliestTimeToSend == -1)
    3473                 builder.append("Not set");
    3474             else {
    3475                 auto secondsUntilSend = WallTime::fromRawSeconds(earliestTimeToSend) - WallTime::now();
    3476                 builder.append((secondsUntilSend >= 24_h && secondsUntilSend <= 48_h) ? "Within 24-48 hours" : "Outside 24-48 hours");
    3477             }
    3478         } else
    3479             builder.append("\nNo attribution trigger data.");
    3480     } else
    3481         builder.append("\nNo attribution trigger data.");
    3482     builder.append('\n');
    3483 
    3484     return builder.toString();
    3485 }
    3486 
    3487 String ResourceLoadStatisticsDatabaseStore::privateClickMeasurementToString()
    3488 {
    3489     auto privateClickMeasurementDataExists = m_database.prepareStatement("SELECT (SELECT COUNT(*) FROM UnattributedPrivateClickMeasurement) as cnt1, (SELECT COUNT(*) FROM AttributedPrivateClickMeasurement) as cnt2"_s);
    3490     if (!privateClickMeasurementDataExists || privateClickMeasurementDataExists->step() != SQLITE_ROW) {
    3491         RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::privateClickMeasurementToString failed, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    3492         ASSERT_NOT_REACHED();
    3493         return { };
    3494     }
    3495 
    3496     if (!privateClickMeasurementDataExists->columnInt(0) && !privateClickMeasurementDataExists->columnInt(1))
    3497         return "\nNo stored Private Click Measurement data.\n"_s;
    3498 
    3499     auto unattributedScopedStatement = this->scopedStatement(m_allUnattributedPrivateClickMeasurementAttributionsStatement, allUnattributedPrivateClickMeasurementAttributionsQuery, "privateClickMeasurementToString"_s);
    3500 
    3501     if (!unattributedScopedStatement) {
    3502         ITP_RELEASE_LOG_ERROR(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::privateClickMeasurementToString, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    3503         ASSERT_NOT_REACHED();
    3504     }
    3505 
    3506     unsigned unattributedNumber = 0;
    3507     StringBuilder builder;
    3508     while (unattributedScopedStatement->step() == SQLITE_ROW) {
    3509         const char* prefix = unattributedNumber ? "" : "Unattributed Private Click Measurements:";
    3510         builder.append(prefix, "\nWebCore::PrivateClickMeasurement ", ++unattributedNumber, '\n',
    3511             attributionToString(unattributedScopedStatement.get(), PrivateClickMeasurementAttributionType::Unattributed));
    3512     }
    3513 
    3514     auto attributedScopedStatement = this->scopedStatement(m_allAttributedPrivateClickMeasurementStatement, allAttributedPrivateClickMeasurementQuery, "privateClickMeasurementToString"_s);
    3515 
    3516     if (!attributedScopedStatement) {
    3517         ITP_RELEASE_LOG_ERROR(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::privateClickMeasurementToString, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    3518         ASSERT_NOT_REACHED();
    3519     }
    3520 
    3521     unsigned attributedNumber = 0;
    3522     while (attributedScopedStatement->step() == SQLITE_ROW) {
    3523         if (!attributedNumber)
    3524             builder.append(unattributedNumber ? "\n" : "", "Attributed Private Click Measurements:");
    3525         builder.append("\nWebCore::PrivateClickMeasurement ", ++attributedNumber + unattributedNumber, '\n',
    3526             attributionToString(attributedScopedStatement.get(), PrivateClickMeasurementAttributionType::Attributed));
    3527     }
    3528     return builder.toString();
    3529 }
    3530 
    3531 std::pair<std::optional<SourceEarliestTimeToSend>, std::optional<DestinationEarliestTimeToSend>> ResourceLoadStatisticsDatabaseStore::earliestTimesToSend(const WebCore::PrivateClickMeasurement& attribution)
    3532 {
    3533     auto sourceSiteDomainID = domainID(attribution.sourceSite().registrableDomain);
    3534     auto destinationSiteDomainID = domainID(attribution.destinationSite().registrableDomain);
    3535 
    3536     if (!sourceSiteDomainID || !destinationSiteDomainID)
    3537         return std::make_pair(std::nullopt, std::nullopt);
    3538 
    3539     auto scopedStatement = this->scopedStatement(m_earliestTimesToSendStatement, earliestTimesToSendQuery, "earliestTimesToSend"_s);
    3540 
    3541     if (!scopedStatement
    3542         || scopedStatement->bindInt(1, *sourceSiteDomainID) != SQLITE_OK
    3543         || scopedStatement->bindInt(2, *destinationSiteDomainID) != SQLITE_OK
    3544         || scopedStatement->step() != SQLITE_ROW) {
    3545         RELEASE_LOG_ERROR(Network, "ResourceLoadStatisticsDatabaseStore::earliestTimesToSend, error message: %" PUBLIC_LOG_STRING, m_database.lastErrorMsg());
    3546         ASSERT_NOT_REACHED();
    3547     }
    3548 
    3549     std::optional<SourceEarliestTimeToSend> earliestTimeToSendToSource;
    3550     std::optional<DestinationEarliestTimeToSend> earliestTimeToSendToDestination;
    3551    
    3552     // A value of 0.0 indicates that the report has been sent to the respective site.
    3553     if (scopedStatement->columnDouble(0) > 0.0)
    3554         earliestTimeToSendToSource = scopedStatement->columnDouble(0);
    3555    
    3556     if (scopedStatement->columnDouble(1) > 0.0)
    3557         earliestTimeToSendToDestination = scopedStatement->columnDouble(1);
    3558    
    3559     return std::make_pair(earliestTimeToSendToSource, earliestTimeToSendToDestination);
    3560 }
    3561 
    3562 void ResourceLoadStatisticsDatabaseStore::markReportAsSentToSource(SourceDomainID sourceSiteDomainID, DestinationDomainID destinationSiteDomainID)
    3563 {
    3564     auto scopedStatement = this->scopedStatement(m_markReportAsSentToSourceStatement, markReportAsSentToSourceQuery, "markReportAsSentToSource"_s);
    3565 
    3566     if (!scopedStatement
    3567         || scopedStatement->bindInt(1, sourceSiteDomainID) != SQLITE_OK
    3568         || scopedStatement->bindInt(2, destinationSiteDomainID) != SQLITE_OK
    3569         || scopedStatement->step() != SQLITE_DONE) {
    3570         RELEASE_LOG_ERROR(Network, "ResourceLoadStatisticsDatabaseStore::markReportAsSentToSource, error message: %" PUBLIC_LOG_STRING, m_database.lastErrorMsg());
    3571         ASSERT_NOT_REACHED();
    3572     }
    3573 }
    3574 
    3575 void ResourceLoadStatisticsDatabaseStore::markReportAsSentToDestination(SourceDomainID sourceSiteDomainID, DestinationDomainID destinationSiteDomainID)
    3576 {
    3577     auto scopedStatement = this->scopedStatement(m_markReportAsSentToDestinationStatement, markReportAsSentToDestinationQuery, "markReportAsSentToDestination"_s);
    3578 
    3579     if (!scopedStatement
    3580         || scopedStatement->bindInt(1, sourceSiteDomainID) != SQLITE_OK
    3581         || scopedStatement->bindInt(2, destinationSiteDomainID) != SQLITE_OK
    3582         || scopedStatement->step() != SQLITE_DONE) {
    3583         RELEASE_LOG_ERROR(Network, "ResourceLoadStatisticsDatabaseStore::markReportAsSentToDestination, error message: %" PUBLIC_LOG_STRING, m_database.lastErrorMsg());
    3584         ASSERT_NOT_REACHED();
    3585     }
    3586 }
    3587 
    3588 void ResourceLoadStatisticsDatabaseStore::clearSentAttribution(WebCore::PrivateClickMeasurement&& attribution, PrivateClickMeasurement::AttributionReportEndpoint attributionReportEndpoint)
    3589 {   
    3590     auto timesToSend = earliestTimesToSend(attribution);
    3591     auto sourceEarliestTimeToSend = timesToSend.first;
    3592     auto destinationEarliestTimeToSend = timesToSend.second;
    3593 
    3594     auto sourceSiteDomainID = domainID(attribution.sourceSite().registrableDomain);
    3595     auto destinationSiteDomainID = domainID(attribution.destinationSite().registrableDomain);
    3596 
    3597     if (!sourceSiteDomainID || !destinationSiteDomainID)
    3598         return;
    3599 
    3600     switch (attributionReportEndpoint) {
    3601     case PrivateClickMeasurement::AttributionReportEndpoint::Source:
    3602         if (!sourceEarliestTimeToSend) {
    3603             ASSERT_NOT_REACHED();
    3604             return;
    3605         }
    3606         markReportAsSentToSource(*sourceSiteDomainID, *destinationSiteDomainID);
    3607         sourceEarliestTimeToSend = std::nullopt;
    3608         break;
    3609     case PrivateClickMeasurement::AttributionReportEndpoint::Destination:
    3610         if (!destinationEarliestTimeToSend) {
    3611             ASSERT_NOT_REACHED();
    3612             return;
    3613         }
    3614         markReportAsSentToDestination(*sourceSiteDomainID, *destinationSiteDomainID);
    3615         destinationEarliestTimeToSend = std::nullopt;
    3616     }
    3617 
    3618     // Don't clear the attribute from the database unless it has been reported both to the source and destination site.
    3619     if (destinationEarliestTimeToSend || sourceEarliestTimeToSend)
    3620         return;
    3621 
    3622     auto clearAttributedStatement = m_database.prepareStatement("DELETE FROM AttributedPrivateClickMeasurement WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ?"_s);
    3623     if (!clearAttributedStatement
    3624         || clearAttributedStatement->bindInt(1, *sourceSiteDomainID) != SQLITE_OK
    3625         || clearAttributedStatement->bindInt(2, *destinationSiteDomainID) != SQLITE_OK
    3626         || clearAttributedStatement->step() != SQLITE_DONE) {
    3627         ITP_RELEASE_LOG_ERROR(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::clearSentAttribution failed to step, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    3628         ASSERT_NOT_REACHED();
    3629     }
    3630 }
    3631 
    3632 void ResourceLoadStatisticsDatabaseStore::markAttributedPrivateClickMeasurementsAsExpiredForTesting()
    3633 {
    3634     auto expiredTimeToSend = WallTime::now() - 1_h;
    3635 
    3636     auto transactionScope = beginTransactionIfNecessary();
    3637 
    3638     auto earliestTimeToSendToSourceStatement = m_database.prepareStatement("UPDATE AttributedPrivateClickMeasurement SET earliestTimeToSendToSource = ?"_s);
    3639     auto earliestTimeToSendToDestinationStatement = m_database.prepareStatement("UPDATE AttributedPrivateClickMeasurement SET earliestTimeToSendToDestination = null"_s);
    3640 
    3641     if (!earliestTimeToSendToSourceStatement
    3642         || earliestTimeToSendToSourceStatement->bindInt(1, expiredTimeToSend.secondsSinceEpoch().value()) != SQLITE_OK
    3643         || earliestTimeToSendToSourceStatement->step() != SQLITE_DONE) {
    3644         ITP_RELEASE_LOG_ERROR(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::markAttributedPrivateClickMeasurementsAsExpiredForTesting, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    3645         ASSERT_NOT_REACHED();
    3646     }
    3647 
    3648     if (!earliestTimeToSendToDestinationStatement || earliestTimeToSendToDestinationStatement->step() != SQLITE_DONE) {
    3649         ITP_RELEASE_LOG_ERROR(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::markAttributedPrivateClickMeasurementsAsExpiredForTesting, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
    3650         ASSERT_NOT_REACHED();
    3651     }
    3652 }
    3653 
    3654 ScopeExit<Function<void()>> ResourceLoadStatisticsDatabaseStore::beginTransactionIfNecessary()
    3655 {
    3656     if (m_transaction.inProgress())
    3657         return makeScopeExit(Function<void()> { [] { } });
    3658 
    3659     m_transaction.begin();
    3660     return makeScopeExit(Function<void()> { [this] {
    3661         m_transaction.commit();
    3662     } });
    3663 }
    3664 
    36652930} // namespace WebKit
    36662931
  • trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h

    r280934 r281721  
    2828#if ENABLE(RESOURCE_LOAD_STATISTICS)
    2929
     30#include "DatabaseUtilities.h"
    3031#include "ResourceLoadStatisticsStore.h"
    3132#include "WebResourceLoadStatisticsStore.h"
    32 #include <WebCore/SQLiteDatabase.h>
    3333#include <WebCore/SQLiteStatement.h>
    34 #include <WebCore/SQLiteStatementAutoResetScope.h>
    35 #include <WebCore/SQLiteTransaction.h>
    3634#include <pal/SessionID.h>
    3735#include <wtf/CompletionHandler.h>
    38 #include <wtf/Scope.h>
    3936#include <wtf/StdSet.h>
    4037#include <wtf/Vector.h>
    4138
    4239namespace WebCore {
    43 class SQLiteDatabase;
    44 class SQLiteStatement;
    4540enum class StorageAccessPromptWasShown : bool;
    4641enum class StorageAccessWasGranted : bool;
     
    5752class PrivateClickMeasurementManager;
    5853
    59 using AttributedPrivateClickMeasurement = WebCore::PrivateClickMeasurement;
    60 using UnattributedPrivateClickMeasurement = WebCore::PrivateClickMeasurement;
    6154using SourceSite = WebCore::PrivateClickMeasurement::SourceSite;
    6255using AttributionDestinationSite = WebCore::PrivateClickMeasurement::AttributionDestinationSite;
    6356using AttributionTriggerData = WebCore::PrivateClickMeasurement::AttributionTriggerData;
    64 using ExistingColumns = Vector<String>;
    65 using ExpectedColumns = Vector<String>;
    66 using ExistingColumnName = String;
    67 using ExpectedColumnName = String;
    68 using SourceEarliestTimeToSend = double;
    69 using DestinationEarliestTimeToSend = double;
    70 using SourceDomainID = unsigned;
    71 using DestinationDomainID = unsigned;
    7257
    7358typedef std::pair<String, std::optional<String>> TableAndIndexPair;
    7459
    7560// This is always constructed / used / destroyed on the WebResourceLoadStatisticsStore's statistics queue.
    76 class ResourceLoadStatisticsDatabaseStore final : public ResourceLoadStatisticsStore {
     61class ResourceLoadStatisticsDatabaseStore final : public ResourceLoadStatisticsStore, public DatabaseUtilities {
    7762public:
    7863    ResourceLoadStatisticsDatabaseStore(WebResourceLoadStatisticsStore&, SuspendableWorkQueue&, ShouldIncludeLocalhost, const String& storageDirectoryPath, PAL::SessionID);
    7964    ~ResourceLoadStatisticsDatabaseStore();
    8065
    81     static HashSet<ResourceLoadStatisticsDatabaseStore*>& allStores();
    8266    void populateFromMemoryStore(const ResourceLoadStatisticsMemoryStore&);
    8367    void mergeStatistics(Vector<ResourceLoadStatistics>&&) override;
    8468    void clear(CompletionHandler<void()>&&) override;
    8569    bool isEmpty() const override;
    86     void close();
    8770
    8871    Vector<WebResourceLoadStatisticsStore::ThirdPartyData> aggregatedThirdPartyData() const override;
     
    141124    std::optional<Vector<String>> checkForMissingTablesInSchema();
    142125    void insertExpiredStatisticForTesting(const RegistrableDomain&, unsigned numberOfOperatingDaysPassed, bool hasUserInteraction, bool isScheduledForAllButCookieDataRemoval, bool isPrevalent) override;
    143     void interrupt();
    144 
    145     // Private Click Measurement.
    146     void insertPrivateClickMeasurement(WebCore::PrivateClickMeasurement&&, PrivateClickMeasurementAttributionType) override;
    147     void markAllUnattributedPrivateClickMeasurementAsExpiredForTesting() override;
    148     std::optional<WebCore::PrivateClickMeasurement::AttributionSecondsUntilSendData> attributePrivateClickMeasurement(const WebCore::PrivateClickMeasurement::SourceSite&, const WebCore::PrivateClickMeasurement::AttributionDestinationSite&, WebCore::PrivateClickMeasurement::AttributionTriggerData&&) override;
    149     Vector<WebCore::PrivateClickMeasurement> allAttributedPrivateClickMeasurement() override;
    150     void clearPrivateClickMeasurement(std::optional<RegistrableDomain>) override;
    151     void clearExpiredPrivateClickMeasurement() override;
    152     String privateClickMeasurementToString() override;
    153     void clearSentAttribution(WebCore::PrivateClickMeasurement&&, WebCore::PrivateClickMeasurement::AttributionReportEndpoint) override;
    154     void markAttributedPrivateClickMeasurementsAsExpiredForTesting() override;
     126    static void interruptAllDatabases();
     127
    155128    Vector<String> columnsForTable(const String&);
    156129
     
    165138    bool missingUniqueIndices();
    166139    bool needsUpdatedSchema();
    167     bool needsUpdatedPrivateClickMeasurementSchema();
    168     void renameColumnInTable(String&&, ExistingColumnName&&, ExpectedColumnName&&);
    169     void addMissingColumnsToTable(String&&, const ExistingColumns&, const ExpectedColumns&);
    170     void addMissingColumnsIfNecessary();
    171     void renameColumnsIfNecessary();
    172     void renameColumnInTable();
    173140    TableAndIndexPair currentTableAndIndexQueries(const String&);
    174     void updatePrivateClickMeasurementSchemaIfNecessary();
    175     void enableForeignKeys();
    176141    bool missingReferenceToObservedDomains();
    177142    void migrateDataToNewTablesIfNecessary();
    178     void destroyStatements();
    179     WebCore::SQLiteStatementAutoResetScope scopedStatement(std::unique_ptr<WebCore::SQLiteStatement>&, ASCIILiteral, const String&) const;
     143    void destroyStatements() final;
    180144
    181145    bool hasStorageAccess(const TopFrameDomain&, const SubFrameDomain&) const;
     
    202166    HashMap<TopFrameDomain, SubResourceDomain> domainsWithStorageAccess() const;
    203167
    204     void markReportAsSentToDestination(SourceDomainID, DestinationDomainID);
    205     void markReportAsSentToSource(SourceDomainID, DestinationDomainID);
    206     std::pair<std::optional<SourceEarliestTimeToSend>, std::optional<DestinationEarliestTimeToSend>> earliestTimesToSend(const WebCore::PrivateClickMeasurement&);
    207 
    208168    struct DomainData {
    209169        unsigned domainID;
     
    254214
    255215    bool createUniqueIndices();
    256     bool createSchema();
     216    bool createSchema() final;
    257217    String ensureAndMakeDomainList(const HashSet<RegistrableDomain>&);
    258218    std::optional<WallTime> mostRecentUserInteractionTime(const DomainData&);
    259    
    260     void removeUnattributed(WebCore::PrivateClickMeasurement&);
    261     WebCore::PrivateClickMeasurement buildPrivateClickMeasurementFromDatabase(WebCore::SQLiteStatement*, PrivateClickMeasurementAttributionType);
    262     String attributionToString(WebCore::SQLiteStatement*, PrivateClickMeasurementAttributionType);
    263     std::pair<std::optional<UnattributedPrivateClickMeasurement>, std::optional<AttributedPrivateClickMeasurement>> findPrivateClickMeasurement(const WebCore::PrivateClickMeasurement::SourceSite&, const WebCore::PrivateClickMeasurement::AttributionDestinationSite&);
    264 
    265     ScopeExit<Function<void()>> WARN_UNUSED_RETURN beginTransactionIfNecessary();
    266 
    267     const String m_storageDirectoryPath;
    268     mutable WebCore::SQLiteDatabase m_database;
    269     mutable WebCore::SQLiteTransaction m_transaction;
     219
    270220    mutable std::unique_ptr<WebCore::SQLiteStatement> m_observedDomainCountStatement;
    271221    std::unique_ptr<WebCore::SQLiteStatement> m_insertObservedDomainStatement;
     
    305255    mutable std::unique_ptr<WebCore::SQLiteStatement> m_observedDomainsExistsStatement;
    306256    mutable std::unique_ptr<WebCore::SQLiteStatement> m_removeAllDataStatement;
    307     mutable std::unique_ptr<WebCore::SQLiteStatement> m_earliestTimesToSendStatement;
    308     std::unique_ptr<WebCore::SQLiteStatement> m_insertUnattributedPrivateClickMeasurementStatement;
    309     std::unique_ptr<WebCore::SQLiteStatement> m_insertAttributedPrivateClickMeasurementStatement;
    310     std::unique_ptr<WebCore::SQLiteStatement> m_setUnattributedPrivateClickMeasurementAsExpiredStatement;
    311     std::unique_ptr<WebCore::SQLiteStatement> m_clearUnattributedPrivateClickMeasurementStatement;
    312     std::unique_ptr<WebCore::SQLiteStatement> m_clearAttributedPrivateClickMeasurementStatement;
    313     std::unique_ptr<WebCore::SQLiteStatement> m_clearExpiredPrivateClickMeasurementStatement;
    314     std::unique_ptr<WebCore::SQLiteStatement> m_allUnattributedPrivateClickMeasurementAttributionsStatement;
    315     std::unique_ptr<WebCore::SQLiteStatement> m_allAttributedPrivateClickMeasurementStatement;
    316     std::unique_ptr<WebCore::SQLiteStatement> m_findUnattributedStatement;
    317     std::unique_ptr<WebCore::SQLiteStatement> m_findAttributedStatement;
    318     std::unique_ptr<WebCore::SQLiteStatement> m_updateAttributionsEarliestTimeToSendStatement;
    319     std::unique_ptr<WebCore::SQLiteStatement> m_removeUnattributedStatement;
    320     std::unique_ptr<WebCore::SQLiteStatement> m_markReportAsSentToSourceStatement;
    321     std::unique_ptr<WebCore::SQLiteStatement> m_markReportAsSentToDestinationStatement;
    322257
    323258    PAL::SessionID m_sessionID;
  • trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.h

    r280934 r281721  
    108108    void insertExpiredStatisticForTesting(const RegistrableDomain&, unsigned numberOfOperatingDaysPassed, bool hasUserInteraction, bool isScheduledForAllButCookieDataRemoval, bool isPrevalent) override;
    109109
    110     // Private Click Measurement is not implemented in the ITP memory store.
    111     void insertPrivateClickMeasurement(WebCore::PrivateClickMeasurement&&, PrivateClickMeasurementAttributionType) override { };
    112     void markAllUnattributedPrivateClickMeasurementAsExpiredForTesting() override { };
    113     std::optional<WebCore::PrivateClickMeasurement::AttributionSecondsUntilSendData>attributePrivateClickMeasurement(const WebCore::PrivateClickMeasurement::SourceSite&, const WebCore::PrivateClickMeasurement::AttributionDestinationSite&, WebCore::PrivateClickMeasurement::AttributionTriggerData&&) override { return { }; };
    114     Vector<WebCore::PrivateClickMeasurement> allAttributedPrivateClickMeasurement() override { return { }; };
    115     void clearPrivateClickMeasurement(std::optional<RegistrableDomain>) override { };
    116     void clearExpiredPrivateClickMeasurement() override { };
    117     String privateClickMeasurementToString() override { return String(); };
    118     void clearSentAttribution(WebCore::PrivateClickMeasurement&&, WebCore::PrivateClickMeasurement::AttributionReportEndpoint) override { };
    119     void markAttributedPrivateClickMeasurementsAsExpiredForTesting() override { };
    120 
    121110private:
    122111    void includeTodayAsOperatingDateIfNecessary() override;
  • trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsStore.h

    r280934 r281721  
    203203    virtual bool hasStatisticsExpired(WallTime mostRecentUserInteractionTime, OperatingDatesWindow) const = 0;
    204204    virtual void insertExpiredStatisticForTesting(const RegistrableDomain&, unsigned numberOfOperatingDaysPassed, bool hasUserInteraction, bool isScheduledForAllButCookieDataRemoval, bool) = 0;
    205    
    206     // Private Click Measurement.
    207     virtual void insertPrivateClickMeasurement(WebCore::PrivateClickMeasurement&&, PrivateClickMeasurementAttributionType) = 0;
    208     virtual void markAllUnattributedPrivateClickMeasurementAsExpiredForTesting() = 0;
    209     virtual std::optional<WebCore::PrivateClickMeasurement::AttributionSecondsUntilSendData> attributePrivateClickMeasurement(const WebCore::PrivateClickMeasurement::SourceSite&, const WebCore::PrivateClickMeasurement::AttributionDestinationSite&, WebCore::PrivateClickMeasurement::AttributionTriggerData&&) = 0;
    210     virtual Vector<WebCore::PrivateClickMeasurement> allAttributedPrivateClickMeasurement() = 0;
    211     virtual void clearPrivateClickMeasurement(std::optional<RegistrableDomain>) = 0;
    212     virtual void clearExpiredPrivateClickMeasurement() = 0;
    213     virtual String privateClickMeasurementToString() = 0;
    214     virtual void clearSentAttribution(WebCore::PrivateClickMeasurement&&, WebCore::PrivateClickMeasurement::AttributionReportEndpoint) = 0;
    215     virtual void markAttributedPrivateClickMeasurementsAsExpiredForTesting() = 0;
    216205
    217206protected:
  • trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp

    r281480 r281721  
    151151}
    152152
    153 WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore(NetworkSession& networkSession, const String& resourceLoadStatisticsDirectory, ShouldIncludeLocalhost shouldIncludeLocalhost, ResourceLoadStatistics::IsEphemeral isEphemeral)
     153static String pcmStoreDirectory(const NetworkSession& session, const String& resourceLoadStatisticsDirectory, const String& privateClickMeasurementStorageDirectory)
     154{
     155    if (session.sessionID().isEphemeral())
     156        return { };
     157
     158    if (!privateClickMeasurementStorageDirectory.isEmpty())
     159        return privateClickMeasurementStorageDirectory;
     160
     161    return resourceLoadStatisticsDirectory;
     162}
     163
     164WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore(NetworkSession& networkSession, const String& resourceLoadStatisticsDirectory, const String& privateClickMeasurementStorageDirectory, ShouldIncludeLocalhost shouldIncludeLocalhost, ResourceLoadStatistics::IsEphemeral isEphemeral)
    154165    : m_networkSession(makeWeakPtr(networkSession))
    155166    , m_statisticsQueue(sharedStatisticsQueue())
    156167    , m_dailyTasksTimer(RunLoop::main(), this, &WebResourceLoadStatisticsStore::performDailyTasks)
    157168    , m_isEphemeral(isEphemeral)
     169    , m_pcmStore(PCM::Store::create(pcmStoreDirectory(networkSession, resourceLoadStatisticsDirectory, privateClickMeasurementStorageDirectory)))
    158170{
    159171    RELEASE_ASSERT(RunLoop::isMain());
     
    187199}
    188200
    189 Ref<WebResourceLoadStatisticsStore> WebResourceLoadStatisticsStore::create(NetworkSession& networkSession, const String& resourceLoadStatisticsDirectory, ShouldIncludeLocalhost shouldIncludeLocalhost, WebCore::ResourceLoadStatistics::IsEphemeral isEphemeral)
    190 {
    191     return adoptRef(*new WebResourceLoadStatisticsStore(networkSession, resourceLoadStatisticsDirectory, shouldIncludeLocalhost, isEphemeral));
     201Ref<WebResourceLoadStatisticsStore> WebResourceLoadStatisticsStore::create(NetworkSession& networkSession, const String& resourceLoadStatisticsDirectory, const String& privateClickMeasurementStorageDirectory, ShouldIncludeLocalhost shouldIncludeLocalhost, WebCore::ResourceLoadStatistics::IsEphemeral isEphemeral)
     202{
     203    return adoptRef(*new WebResourceLoadStatisticsStore(networkSession, resourceLoadStatisticsDirectory, privateClickMeasurementStorageDirectory, shouldIncludeLocalhost, isEphemeral));
    192204}
    193205
     
    202214    m_networkSession = nullptr;
    203215    destroyResourceLoadStatisticsStore([callbackAggregator] { });
     216    privateClickMeasurementStore().close([callbackAggregator] { });
    204217}
    205218
     
    14471460{
    14481461    ASSERT(RunLoop::isMain());
    1449 
    1450     sharedStatisticsQueue()->suspend([]() mutable {
    1451         for (auto& databaseStore : ResourceLoadStatisticsDatabaseStore::allStores())
    1452             databaseStore->interrupt();
    1453     }, WTFMove(completionHandler));
     1462    sharedStatisticsQueue()->suspend(ResourceLoadStatisticsDatabaseStore::interruptAllDatabases, WTFMove(completionHandler));
    14541463}
    14551464
     
    14681477        if (m_statisticsStore)
    14691478            m_statisticsStore->insertExpiredStatisticForTesting(WTFMove(domain), numberOfOperatingDaysPassed, hadUserInteraction, isScheduledForAllButCookieDataRemoval, isPrevalent);
    1470         postTaskReply(WTFMove(completionHandler));
    1471     });
    1472 }
    1473 
    1474 void WebResourceLoadStatisticsStore::insertPrivateClickMeasurement(PrivateClickMeasurement&& attribution, PrivateClickMeasurementAttributionType attributionType)
    1475 {
    1476     ASSERT(RunLoop::isMain());
    1477 
    1478     if (isEphemeral())
    1479         return;
    1480 
    1481     postTask([this, attribution = WTFMove(attribution), attributionType]() mutable {
    1482         if (!m_statisticsStore)
    1483             return;
    1484 
    1485         m_statisticsStore->insertPrivateClickMeasurement(WTFMove(attribution), attributionType);
    1486     });
    1487 }
    1488 
    1489 void WebResourceLoadStatisticsStore::markAllUnattributedPrivateClickMeasurementAsExpiredForTesting()
    1490 {
    1491     ASSERT(RunLoop::isMain());
    1492 
    1493     if (isEphemeral())
    1494         return;
    1495 
    1496     postTask([this]() {
    1497         if (!m_statisticsStore)
    1498             return;
    1499 
    1500         m_statisticsStore->markAllUnattributedPrivateClickMeasurementAsExpiredForTesting();
    1501     });
    1502 }
    1503 
    1504 void WebResourceLoadStatisticsStore::attributePrivateClickMeasurement(const PrivateClickMeasurement::SourceSite& sourceSite, const PrivateClickMeasurement::AttributionDestinationSite& destinationSite, PrivateClickMeasurement::AttributionTriggerData&& attributionTriggerData, std::optional<PrivateClickMeasurement>&& ephemeralMeasurement, CompletionHandler<void(std::optional<WebCore::PrivateClickMeasurement::AttributionSecondsUntilSendData>)>&& completionHandler)
    1505 {
    1506     ASSERT(RunLoop::isMain());
    1507 
    1508     if (isEphemeral()) {
    1509         completionHandler({ });
    1510         return;
    1511     }
    1512 
    1513     postTask([this, sourceSite = sourceSite.isolatedCopy(), destinationSite = destinationSite.isolatedCopy(), attributionTriggerData = WTFMove(attributionTriggerData), ephemeralMeasurement = WTFMove(ephemeralMeasurement), completionHandler = WTFMove(completionHandler)]() mutable {
    1514         if (!m_statisticsStore) {
    1515             postTaskReply([completionHandler = WTFMove(completionHandler)]() mutable {
    1516                 completionHandler(std::nullopt);
    1517             });
    1518             return;
    1519         }
    1520 
    1521         // Insert ephemeral measurement right before attribution.
    1522         if (ephemeralMeasurement) {
    1523             RELEASE_ASSERT(ephemeralMeasurement->isEphemeral());
    1524             m_statisticsStore->insertPrivateClickMeasurement(WTFMove(*ephemeralMeasurement), PrivateClickMeasurementAttributionType::Unattributed);
    1525         }
    1526 
    1527         auto seconds = m_statisticsStore->attributePrivateClickMeasurement(sourceSite, destinationSite, WTFMove(attributionTriggerData));
    1528         postTaskReply([seconds, completionHandler = WTFMove(completionHandler)]() mutable {
    1529             completionHandler(seconds);
    1530         });
    1531     });
    1532 }
    1533 
    1534 void WebResourceLoadStatisticsStore::allAttributedPrivateClickMeasurement(CompletionHandler<void(Vector<PrivateClickMeasurement>&&)>&& completionHandler)
    1535 {
    1536     ASSERT(RunLoop::isMain());
    1537 
    1538     if (isEphemeral()) {
    1539         completionHandler({ });
    1540         return;
    1541     }
    1542 
    1543     postTask([this, completionHandler = WTFMove(completionHandler)]() mutable {
    1544         if (!m_statisticsStore) {
    1545             postTaskReply([completionHandler = WTFMove(completionHandler)]() mutable {
    1546                 completionHandler({ });
    1547             });
    1548             return;
    1549         }
    1550 
    1551         auto convertedAttributions = m_statisticsStore->allAttributedPrivateClickMeasurement();
    1552         postTaskReply([convertedAttributions = WTFMove(convertedAttributions), completionHandler = WTFMove(completionHandler)]() mutable {
    1553             completionHandler(WTFMove(convertedAttributions));
    1554         });
    1555     });
    1556 }
    1557 
    1558 void WebResourceLoadStatisticsStore::clearPrivateClickMeasurement()
    1559 {
    1560     ASSERT(RunLoop::isMain());
    1561 
    1562     if (isEphemeral())
    1563         return;
    1564 
    1565     postTask([this]() {
    1566         if (!m_statisticsStore)
    1567             return;
    1568 
    1569         m_statisticsStore->clearPrivateClickMeasurement(std::nullopt);
    1570     });
    1571 }
    1572    
    1573 void WebResourceLoadStatisticsStore::clearPrivateClickMeasurementForRegistrableDomain(const RegistrableDomain& domain)
    1574 {
    1575     ASSERT(RunLoop::isMain());
    1576 
    1577     if (isEphemeral())
    1578         return;
    1579 
    1580     postTask([this, domain = domain.isolatedCopy()]() mutable {
    1581         if (!m_statisticsStore)
    1582             return;
    1583 
    1584         m_statisticsStore->clearPrivateClickMeasurement(domain);
    1585     });
    1586 }
    1587 
    1588 void WebResourceLoadStatisticsStore::clearExpiredPrivateClickMeasurement()
    1589 {
    1590     ASSERT(RunLoop::isMain());
    1591 
    1592     if (isEphemeral())
    1593         return;
    1594 
    1595     postTask([this]() {
    1596         if (!m_statisticsStore)
    1597             return;
    1598 
    1599         m_statisticsStore->clearExpiredPrivateClickMeasurement();
    1600     });
    1601 }
    1602 
    1603 void WebResourceLoadStatisticsStore::privateClickMeasurementToString(CompletionHandler<void(String)>&& completionHandler)
    1604 {
    1605     ASSERT(RunLoop::isMain());
    1606 
    1607     if (isEphemeral()) {
    1608         completionHandler("\nNo stored Private Click Measurement data.\n"_s);
    1609         return;
    1610     }
    1611 
    1612     postTask([this, completionHandler = WTFMove(completionHandler)]() mutable {
    1613         if (!m_statisticsStore) {
    1614             postTaskReply([completionHandler = WTFMove(completionHandler)]() mutable {
    1615                 completionHandler({ });
    1616             });
    1617             return;
    1618         }
    1619 
    1620         auto result = m_statisticsStore->privateClickMeasurementToString();
    1621         postTaskReply([result = result.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
    1622             completionHandler(result);
    1623         });
    1624     });
    1625 }
    1626 
    1627 void WebResourceLoadStatisticsStore::clearSentAttribution(WebCore::PrivateClickMeasurement&& attributionToClear, PrivateClickMeasurement::AttributionReportEndpoint attributionReportEndpoint)
    1628 {
    1629     ASSERT(RunLoop::isMain());
    1630 
    1631     if (isEphemeral())
    1632         return;
    1633 
    1634     postTask([this, attributionToClear = WTFMove(attributionToClear), attributionReportEndpoint]() mutable {
    1635         if (!m_statisticsStore)
    1636             return;
    1637 
    1638         m_statisticsStore->clearSentAttribution(WTFMove(attributionToClear), attributionReportEndpoint);
    1639     });
    1640 }
    1641 
    1642 void WebResourceLoadStatisticsStore::markAttributedPrivateClickMeasurementsAsExpiredForTesting(CompletionHandler<void()>&& completionHandler)
    1643 {
    1644     ASSERT(RunLoop::isMain());
    1645 
    1646     if (isEphemeral()) {
    1647         completionHandler();
    1648         return;
    1649     }
    1650 
    1651     postTask([this, completionHandler = WTFMove(completionHandler)]() mutable {
    1652         if (m_statisticsStore)
    1653             m_statisticsStore->markAttributedPrivateClickMeasurementsAsExpiredForTesting();
    1654 
    16551479        postTaskReply(WTFMove(completionHandler));
    16561480    });
  • trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h

    r281480 r281721  
    3131#include "Decoder.h"
    3232#include "Encoder.h"
     33#include "PrivateClickMeasurementStore.h"
    3334#include "StorageAccessStatus.h"
    3435#include "WebPageProxyIdentifier.h"
     
    109110    using RequestStorageAccessResult = WebCore::RequestStorageAccessResult;
    110111
    111     static Ref<WebResourceLoadStatisticsStore> create(NetworkSession&, const String& resourceLoadStatisticsDirectory, ShouldIncludeLocalhost, ResourceLoadStatistics::IsEphemeral);
     112    static Ref<WebResourceLoadStatisticsStore> create(NetworkSession&, const String& resourceLoadStatisticsDirectory, const String& privateClickMeasurementStorageDirectory, ShouldIncludeLocalhost, ResourceLoadStatistics::IsEphemeral);
    112113
    113114    ~WebResourceLoadStatisticsStore();
     
    240241    void insertExpiredStatisticForTesting(const RegistrableDomain&, unsigned numberOfOperatingDaysPassed, bool hadUserInteraction, bool isScheduledForAllButCookieDataRemoval, bool isPrevalent, CompletionHandler<void()>&&);
    241242
    242     // Private Click Measurement.
    243     void insertPrivateClickMeasurement(WebCore::PrivateClickMeasurement&&, PrivateClickMeasurementAttributionType);
    244     void markAllUnattributedPrivateClickMeasurementAsExpiredForTesting();
    245     void attributePrivateClickMeasurement(const WebCore::PrivateClickMeasurement::SourceSite&, const WebCore::PrivateClickMeasurement::AttributionDestinationSite&, WebCore::PrivateClickMeasurement::AttributionTriggerData&&, std::optional<WebCore::PrivateClickMeasurement>&& ephemeralMeasurement, CompletionHandler<void(std::optional<WebCore::PrivateClickMeasurement::AttributionSecondsUntilSendData>)>&&);
    246     void allAttributedPrivateClickMeasurement(CompletionHandler<void(Vector<WebCore::PrivateClickMeasurement>&&)>&&);
    247     void clearPrivateClickMeasurement();
    248     void clearPrivateClickMeasurementForRegistrableDomain(const WebCore::RegistrableDomain&);
    249     void clearExpiredPrivateClickMeasurement();
    250     void privateClickMeasurementToString(CompletionHandler<void(String)>&&);
    251     void clearSentAttribution(WebCore::PrivateClickMeasurement&&, WebCore::PrivateClickMeasurement::AttributionReportEndpoint);
    252     void markAttributedPrivateClickMeasurementsAsExpiredForTesting(CompletionHandler<void()>&&);
    253 
     243    PCM::Store& privateClickMeasurementStore() { return m_pcmStore.get(); }
    254244private:
    255     explicit WebResourceLoadStatisticsStore(NetworkSession&, const String&, ShouldIncludeLocalhost, WebCore::ResourceLoadStatistics::IsEphemeral);
     245    explicit WebResourceLoadStatisticsStore(NetworkSession&, const String&, const String&, ShouldIncludeLocalhost, WebCore::ResourceLoadStatistics::IsEphemeral);
    256246
    257247    void postTask(WTF::Function<void()>&&);
     
    288278
    289279    bool m_firstNetworkProcessCreated { false };
     280   
     281    Ref<PCM::Store> m_pcmStore;
    290282};
    291283
  • trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp

    r281706 r281721  
    4949#include "NetworkSessionCreationParameters.h"
    5050#include "PreconnectTask.h"
     51#include "PrivateClickMeasurementStore.h"
    5152#include "RemoteNetworkingContext.h"
    5253#include "ShouldGrandfatherStatistics.h"
     
    16151616
    16161617    if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
    1617         clearDiskCache(modifiedSince, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
     1618        clearDiskCache(modifiedSince, [clearTasksHandler] { });
    16181619
    16191620    if (websiteDataTypes.contains(WebsiteDataType::PrivateClickMeasurements)) {
    16201621        if (auto* networkSession = this->networkSession(sessionID))
    1621             networkSession->clearPrivateClickMeasurement();
     1622            networkSession->clearPrivateClickMeasurement([clearTasksHandler] { });
    16221623    }
    16231624
     
    16781679#endif
    16791680
     1681    auto clearTasksHandler = WTF::CallbackAggregator::create(WTFMove(completionHandler));
     1682
    16801683    if (websiteDataTypes.contains(WebsiteDataType::PrivateClickMeasurements)) {
    16811684        if (auto* networkSession = this->networkSession(sessionID)) {
    16821685            for (auto& originData : originDatas)
    1683                 networkSession->clearPrivateClickMeasurementForRegistrableDomain(RegistrableDomain::uncheckedCreateFromHost(originData.host));
     1686                networkSession->clearPrivateClickMeasurementForRegistrableDomain(RegistrableDomain::uncheckedCreateFromHost(originData.host), [clearTasksHandler] { });
    16841687        }
    16851688    }
    1686    
    1687     auto clearTasksHandler = WTF::CallbackAggregator::create(WTFMove(completionHandler));
    16881689
    16891690    if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
     
    22462247    WebResourceLoadStatisticsStore::suspend([callbackAggregator] { });
    22472248#endif
     2249    PCM::Store::prepareForProcessToSuspend([callbackAggregator] { });
    22482250
    22492251    forEachNetworkSession([&] (auto& networkSession) {
     
    22882290    WebResourceLoadStatisticsStore::resume();
    22892291#endif
    2290    
     2292    PCM::Store::processDidResume();
     2293
    22912294#if ENABLE(SERVICE_WORKER)
    22922295    for (auto& server : m_swServers.values())
     
    25702573{
    25712574    if (auto* session = networkSession(sessionID))
    2572         session->clearPrivateClickMeasurement();
    2573    
    2574     completionHandler();
     2575        session->clearPrivateClickMeasurement(WTFMove(completionHandler));
     2576    else
     2577        completionHandler();
    25752578}
    25762579
  • trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp

    r281706 r281721  
    878878    m_redirectResponse = redirectResponse;
    879879
    880     std::optional<PrivateClickMeasurement::AttributionTriggerData> privateClickMeasurementAttributionTriggerData;
     880    std::optional<WebCore::PrivateClickMeasurement::AttributionTriggerData> privateClickMeasurementAttributionTriggerData;
    881881    if (!sessionID().isEphemeral()) {
    882         if (auto result = PrivateClickMeasurement::parseAttributionRequest(redirectRequest.url()))
     882        if (auto result = WebCore::PrivateClickMeasurement::parseAttributionRequest(redirectRequest.url()))
    883883            privateClickMeasurementAttributionTriggerData = result.value();
    884884        else if (!result.error().isEmpty())
     
    941941}
    942942
    943 void NetworkResourceLoader::continueWillSendRedirectedRequest(ResourceRequest&& request, ResourceRequest&& redirectRequest, ResourceResponse&& redirectResponse, std::optional<PrivateClickMeasurement::AttributionTriggerData>&& privateClickMeasurementAttributionTriggerData)
     943void NetworkResourceLoader::continueWillSendRedirectedRequest(ResourceRequest&& request, ResourceRequest&& redirectRequest, ResourceResponse&& redirectResponse, std::optional<WebCore::PrivateClickMeasurement::AttributionTriggerData>&& privateClickMeasurementAttributionTriggerData)
    944944{
    945945    redirectRequest.setIsAppInitiated(request.isAppInitiated());
  • trunk/Source/WebKit/NetworkProcess/NetworkSession.cpp

    r281706 r281721  
    8585    , m_networkProcess(networkProcess)
    8686#if ENABLE(RESOURCE_LOAD_STATISTICS)
     87    , m_privateClickMeasurementStorageDirectory(parameters.resourceLoadStatisticsParameters.privateClickMeasurementStorageDirectory)
    8788    , m_resourceLoadStatisticsDirectory(parameters.resourceLoadStatisticsParameters.directory)
    8889    , m_shouldIncludeLocalhostInResourceLoadStatistics(parameters.resourceLoadStatisticsParameters.shouldIncludeLocalhost ? ShouldIncludeLocalhost::Yes : ShouldIncludeLocalhost::No)
     
    120121        if (!parameters.resourceLoadStatisticsParameters.directory.isEmpty())
    121122            SandboxExtension::consumePermanently(parameters.resourceLoadStatisticsParameters.directoryExtensionHandle);
     123        if (!parameters.resourceLoadStatisticsParameters.privateClickMeasurementStorageDirectory.isEmpty())
     124            SandboxExtension::consumePermanently(parameters.resourceLoadStatisticsParameters.privateClickMeasurementStorageDirectoryExtensionHandle);
    122125    }
    123126
     
    128131    m_privateClickMeasurement = makeUnique<PrivateClickMeasurementManager>(*this, networkProcess, parameters.sessionID, [weakThis = makeWeakPtr(this)] (auto&& loadParameters, auto&& completionHandler) {
    129132        if (!weakThis)
    130             return;
     133            return completionHandler(ResourceError(ResourceError::Type::Cancellation), { }, { });
    131134
    132135        PrivateClickMeasurementNetworkLoader::start(*weakThis, WTFMove(loadParameters), WTFMove(completionHandler));
     
    182185        return;
    183186
    184     m_resourceLoadStatistics = WebResourceLoadStatisticsStore::create(*this, m_resourceLoadStatisticsDirectory, m_shouldIncludeLocalhostInResourceLoadStatistics, (m_sessionID.isEphemeral() ? ResourceLoadStatistics::IsEphemeral::Yes : ResourceLoadStatistics::IsEphemeral::No));
     187    m_resourceLoadStatistics = WebResourceLoadStatisticsStore::create(*this, m_resourceLoadStatisticsDirectory, m_privateClickMeasurementStorageDirectory, m_shouldIncludeLocalhostInResourceLoadStatistics, (m_sessionID.isEphemeral() ? ResourceLoadStatistics::IsEphemeral::Yes : ResourceLoadStatistics::IsEphemeral::No));
    185188    if (!m_sessionID.isEphemeral())
    186189        m_resourceLoadStatistics->populateMemoryStoreFromDisk([] { });
     
    199202        if (!weakThis)
    200203            return completionHandler();
    201         m_resourceLoadStatistics = WebResourceLoadStatisticsStore::create(*this, m_resourceLoadStatisticsDirectory, m_shouldIncludeLocalhostInResourceLoadStatistics, (m_sessionID.isEphemeral() ? ResourceLoadStatistics::IsEphemeral::Yes : ResourceLoadStatistics::IsEphemeral::No));
     204        m_resourceLoadStatistics = WebResourceLoadStatisticsStore::create(*this, m_resourceLoadStatisticsDirectory, m_privateClickMeasurementStorageDirectory,  m_shouldIncludeLocalhostInResourceLoadStatistics, (m_sessionID.isEphemeral() ? ResourceLoadStatistics::IsEphemeral::Yes : ResourceLoadStatistics::IsEphemeral::No));
    202205        forwardResourceLoadStatisticsSettings();
    203206        if (!m_sessionID.isEphemeral())
     
    321324void NetworkSession::dumpPrivateClickMeasurement(CompletionHandler<void(String)>&& completionHandler)
    322325{
    323     privateClickMeasurement().toString(WTFMove(completionHandler));
    324 }
    325 
    326 void NetworkSession::clearPrivateClickMeasurement()
    327 {
    328     privateClickMeasurement().clear();
    329 }
    330 
    331 void NetworkSession::clearPrivateClickMeasurementForRegistrableDomain(WebCore::RegistrableDomain&& domain)
    332 {
    333     privateClickMeasurement().clearForRegistrableDomain(WTFMove(domain));
     326    privateClickMeasurement().toStringForTesting(WTFMove(completionHandler));
     327}
     328
     329void NetworkSession::clearPrivateClickMeasurement(CompletionHandler<void()>&& completionHandler)
     330{
     331    privateClickMeasurement().clear(WTFMove(completionHandler));
     332}
     333
     334void NetworkSession::clearPrivateClickMeasurementForRegistrableDomain(WebCore::RegistrableDomain&& domain, CompletionHandler<void()>&& completionHandler)
     335{
     336    privateClickMeasurement().clearForRegistrableDomain(WTFMove(domain), WTFMove(completionHandler));
    334337}
    335338
  • trunk/Source/WebKit/NetworkProcess/NetworkSession.h

    r281706 r281721  
    127127    void handlePrivateClickMeasurementConversion(WebCore::PrivateClickMeasurement::AttributionTriggerData&&, const URL& requestURL, const WebCore::ResourceRequest& redirectRequest);
    128128    void dumpPrivateClickMeasurement(CompletionHandler<void(String)>&&);
    129     void clearPrivateClickMeasurement();
    130     void clearPrivateClickMeasurementForRegistrableDomain(WebCore::RegistrableDomain&&);
     129    void clearPrivateClickMeasurement(CompletionHandler<void()>&&);
     130    void clearPrivateClickMeasurementForRegistrableDomain(WebCore::RegistrableDomain&&, CompletionHandler<void()>&&);
    131131    void setPrivateClickMeasurementOverrideTimerForTesting(bool value);
    132132    void markAttributedPrivateClickMeasurementsAsExpiredForTesting(CompletionHandler<void()>&&);
     
    196196    WeakHashSet<NetworkDataTask> m_dataTaskSet;
    197197#if ENABLE(RESOURCE_LOAD_STATISTICS)
     198    String m_privateClickMeasurementStorageDirectory;
    198199    String m_resourceLoadStatisticsDirectory;
    199200    RefPtr<WebResourceLoadStatisticsStore> m_resourceLoadStatistics;
  • trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementManager.cpp

    r281480 r281721  
    2929#include "Logging.h"
    3030#include "NetworkSession.h"
     31#include "PrivateClickMeasurementDebugInfo.h"
    3132#include <JavaScriptCore/ConsoleTypes.h>
    3233#include <WebCore/FetchOptions.h>
     
    251252#if ENABLE(RESOURCE_LOAD_STATISTICS)
    252253        if (auto* resourceLoadStatistics = m_networkSession->resourceLoadStatistics())
    253             resourceLoadStatistics->insertPrivateClickMeasurement(WTFMove(measurement), type);
     254            resourceLoadStatistics->privateClickMeasurementStore().insertPrivateClickMeasurement(WTFMove(measurement), type);
    254255#endif
    255256}
     
    298299       
    299300    if (auto* resourceLoadStatistics = m_networkSession->resourceLoadStatistics()) {
    300         resourceLoadStatistics->attributePrivateClickMeasurement(sourceSite, destinationSite, WTFMove(attributionTriggerData), std::exchange(m_ephemeralMeasurement, std::nullopt), [this, weakThis = makeWeakPtr(*this)] (auto attributionSecondsUntilSendData) {
     301        resourceLoadStatistics->privateClickMeasurementStore().attributePrivateClickMeasurement(sourceSite, destinationSite, WTFMove(attributionTriggerData), std::exchange(m_ephemeralMeasurement, std::nullopt), [this, weakThis = makeWeakPtr(*this)] (auto attributionSecondsUntilSendData, auto debugInfo) {
    301302            if (!weakThis)
    302303                return;
     
    304305            if (!attributionSecondsUntilSendData)
    305306                return;
     307
     308            if (UNLIKELY(debugModeEnabled())) {
     309                for (auto& message : debugInfo.messages)
     310                    m_networkProcess->broadcastConsoleMessage(m_sessionID, MessageSource::PrivateClickMeasurement, message.messageLevel, message.message);
     311            }
    306312
    307313            if (attributionSecondsUntilSendData.value().hasValidSecondsUntilSendValues()) {
     
    396402
    397403    if (auto* resourceLoadStatistics = m_networkSession->resourceLoadStatistics())
    398         resourceLoadStatistics->clearSentAttribution(WTFMove(sentConversion), attributionReportEndpoint);
     404        resourceLoadStatistics->privateClickMeasurementStore().clearSentAttribution(WTFMove(sentConversion), attributionReportEndpoint);
    399405#endif
    400406}
     
    410416        return;
    411417
    412     resourceLoadStatistics->allAttributedPrivateClickMeasurement([this, weakThis = makeWeakPtr(*this)] (auto&& attributions) {
     418    resourceLoadStatistics->privateClickMeasurementStore().allAttributedPrivateClickMeasurement([this, weakThis = makeWeakPtr(*this)] (auto&& attributions) {
    413419        if (!weakThis)
    414420            return;
     
    463469}
    464470
    465 void PrivateClickMeasurementManager::clear()
     471void PrivateClickMeasurementManager::clear(CompletionHandler<void()>&& completionHandler)
    466472{
    467473    m_firePendingAttributionRequestsTimer.stop();
     
    471477#if ENABLE(RESOURCE_LOAD_STATISTICS)
    472478    if (!featureEnabled())
    473         return;
     479        return completionHandler();
    474480
    475481    if (auto* resourceLoadStatistics = m_networkSession->resourceLoadStatistics())
    476         resourceLoadStatistics->clearPrivateClickMeasurement();
    477 #endif
    478 }
    479 
    480 void PrivateClickMeasurementManager::clearForRegistrableDomain(const RegistrableDomain& domain)
    481 {
    482 #if ENABLE(RESOURCE_LOAD_STATISTICS)
    483     if (!featureEnabled())
    484         return;
     482        return resourceLoadStatistics->privateClickMeasurementStore().clearPrivateClickMeasurement(WTFMove(completionHandler));
     483#endif
     484    completionHandler();
     485}
     486
     487void PrivateClickMeasurementManager::clearForRegistrableDomain(const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
     488{
     489#if ENABLE(RESOURCE_LOAD_STATISTICS)
     490    if (!featureEnabled())
     491        return completionHandler();
    485492
    486493    if (auto* resourceLoadStatistics = m_networkSession->resourceLoadStatistics())
    487         resourceLoadStatistics->clearPrivateClickMeasurementForRegistrableDomain(domain);
    488 #endif
     494        return resourceLoadStatistics->privateClickMeasurementStore().clearPrivateClickMeasurementForRegistrableDomain(domain, WTFMove(completionHandler));
     495#endif
     496    completionHandler();
    489497}
    490498
     
    496504
    497505    if (auto* resourceLoadStatistics = m_networkSession->resourceLoadStatistics())
    498         resourceLoadStatistics->clearExpiredPrivateClickMeasurement();
    499 #endif
    500 }
    501 
    502 void PrivateClickMeasurementManager::toString(CompletionHandler<void(String)>&& completionHandler) const
     506        resourceLoadStatistics->privateClickMeasurementStore().clearExpiredPrivateClickMeasurement();
     507#endif
     508}
     509
     510void PrivateClickMeasurementManager::toStringForTesting(CompletionHandler<void(String)>&& completionHandler) const
    503511{
    504512#if ENABLE(RESOURCE_LOAD_STATISTICS)
     
    509517
    510518    if (auto* resourceLoadStatistics = m_networkSession->resourceLoadStatistics()) {
    511         resourceLoadStatistics->privateClickMeasurementToString(WTFMove(completionHandler));
     519        resourceLoadStatistics->privateClickMeasurementStore().privateClickMeasurementToStringForTesting(WTFMove(completionHandler));
    512520        return;
    513521    }
     
    546554
    547555    if (auto* resourceLoadStatistics = m_networkSession->resourceLoadStatistics())
    548         resourceLoadStatistics->markAllUnattributedPrivateClickMeasurementAsExpiredForTesting();
     556        resourceLoadStatistics->privateClickMeasurementStore().markAllUnattributedPrivateClickMeasurementAsExpiredForTesting();
    549557#endif
    550558}
     
    576584
    577585    if (auto* resourceLoadStatistics = m_networkSession->resourceLoadStatistics()) {
    578         resourceLoadStatistics->markAttributedPrivateClickMeasurementsAsExpiredForTesting(WTFMove(completionHandler));
     586        resourceLoadStatistics->privateClickMeasurementStore().markAttributedPrivateClickMeasurementsAsExpiredForTesting(WTFMove(completionHandler));
    579587        return;
    580588    }
  • trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementManager.h

    r281480 r281721  
    5757    void storeUnattributed(PrivateClickMeasurement&&);
    5858    void handleAttribution(AttributionTriggerData&&, const URL& requestURL, const WebCore::ResourceRequest& redirectRequest);
    59     void clear();
    60     void clearForRegistrableDomain(const RegistrableDomain&);
    61     void toString(CompletionHandler<void(String)>&&) const;
     59    void clear(CompletionHandler<void()>&&);
     60    void clearForRegistrableDomain(const RegistrableDomain&, CompletionHandler<void()>&&);
     61    void toStringForTesting(CompletionHandler<void(String)>&&) const;
    6262    void setOverrideTimerForTesting(bool value) { m_isRunningTest = value; }
    6363    void setTokenPublicKeyURLForTesting(URL&&);
  • trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementNetworkLoader.cpp

    r275484 r281721  
    5252}
    5353
     54PrivateClickMeasurementNetworkLoader::~PrivateClickMeasurementNetworkLoader()
     55{
     56    cancel();
     57}
     58
    5459void PrivateClickMeasurementNetworkLoader::fail(ResourceError&& error)
    5560{
     
    6166}
    6267
     68void PrivateClickMeasurementNetworkLoader::cancel()
     69{
     70    fail(ResourceError { ResourceError::Type::Cancellation });
     71}
     72
    6373void PrivateClickMeasurementNetworkLoader::willSendRedirectedRequest(ResourceRequest&&, ResourceRequest&&, ResourceResponse&&)
    6474{
    65     fail(ResourceError { ResourceError::Type::Cancellation });
     75    cancel();
    6676}
    6777
  • trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementNetworkLoader.h

    r275260 r281721  
    4343    static void start(NetworkSession&, NetworkLoadParameters&&, Callback&&);
    4444
     45    ~PrivateClickMeasurementNetworkLoader();
     46
    4547private:
    4648    PrivateClickMeasurementNetworkLoader(NetworkSession&, NetworkLoadParameters&&, Callback&&);
     
    5759
    5860    void fail(WebCore::ResourceError&&);
     61    void cancel();
    5962    void didComplete();
    6063
  • trunk/Source/WebKit/NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp

    r279750 r281721  
    3333#include "NetworkCacheSpeculativeLoad.h"
    3434#include "NetworkCacheSubresourcesEntry.h"
     35#include "NetworkLoadParameters.h"
    3536#include "NetworkProcess.h"
    3637#include "PreconnectTask.h"
  • trunk/Source/WebKit/NetworkProcess/webrtc/NetworkRTCResolver.h

    r256185 r281721  
    2828#if USE(LIBWEBRTC)
    2929
     30#include "LibWebRTCResolverIdentifier.h"
    3031#include "RTCNetwork.h"
    3132#include <WebCore/DNS.h>
  • trunk/Source/WebKit/NetworkProcess/webrtc/NetworkRTCResolverCocoa.cpp

    r259338 r281721  
    5656    for (size_t index = 0; index < count; ++index) {
    5757        CFDataRef data = (CFDataRef)CFArrayGetValueAtIndex(resolvedAddresses, index);
    58         if (auto address = IPAddress::fromSockAddrIn6(*reinterpret_cast<const struct sockaddr_in6*>(CFDataGetBytePtr(data))))
     58        if (auto address = WebCore::IPAddress::fromSockAddrIn6(*reinterpret_cast<const struct sockaddr_in6*>(CFDataGetBytePtr(data))))
    5959            addresses.uncheckedAppend(*address);
    6060    }
  • trunk/Source/WebKit/Shared/ResourceLoadStatisticsParameters.h

    r278253 r281721  
    3838    String directory;
    3939    SandboxExtension::Handle directoryExtensionHandle;
     40    String privateClickMeasurementStorageDirectory;
     41    SandboxExtension::Handle privateClickMeasurementStorageDirectoryExtensionHandle;
    4042    bool enabled { false };
    4143    bool isItpStateExplicitlySet { false };
     
    5658        encoder << directory;
    5759        encoder << directoryExtensionHandle;
     60        encoder << privateClickMeasurementStorageDirectory;
     61        encoder << privateClickMeasurementStorageDirectoryExtensionHandle;
    5862        encoder << enabled;
    5963        encoder << isItpStateExplicitlySet;
     
    8286        if (!directoryExtensionHandle)
    8387            return std::nullopt;
     88
     89        std::optional<String> privateClickMeasurementStorageDirectory;
     90        decoder >> privateClickMeasurementStorageDirectory;
     91        if (!privateClickMeasurementStorageDirectory)
     92            return std::nullopt;
    8493       
     94        std::optional<SandboxExtension::Handle> privateClickMeasurementStorageDirectoryExtensionHandle;
     95        decoder >> privateClickMeasurementStorageDirectoryExtensionHandle;
     96        if (!privateClickMeasurementStorageDirectoryExtensionHandle)
     97            return std::nullopt;
     98
    8599        std::optional<bool> enabled;
    86100        decoder >> enabled;
     
    143157            WTFMove(*directory),
    144158            WTFMove(*directoryExtensionHandle),
     159            WTFMove(*privateClickMeasurementStorageDirectory),
     160            WTFMove(*privateClickMeasurementStorageDirectoryExtensionHandle),
    145161            WTFMove(*enabled),
    146162            WTFMove(*isItpStateExplicitlySet),
  • trunk/Source/WebKit/Sources.txt

    r281365 r281721  
    5858GPUProcess/webrtc/RemoteSampleBufferDisplayLayerManager.cpp
    5959
     60NetworkProcess/DatabaseUtilities.cpp
    6061NetworkProcess/PrivateClickMeasurementManager.cpp
    6162NetworkProcess/PrivateClickMeasurementNetworkLoader.cpp
     
    9899NetworkProcess/IndexedDB/WebIDBConnectionToClient.cpp
    99100NetworkProcess/IndexedDB/WebIDBServer.cpp
     101
     102NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDatabase.cpp
     103NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDebugInfo.cpp
     104NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementStore.cpp
    100105
    101106NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp @no-unify
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm

    r281349 r281721  
    732732}
    733733
    734 + (void)_preventNetworkProcessSuspensionForTesting
    735 {
    736     WebKit::NetworkProcessProxy::preventSuspensionForTesting();
     734+ (void)_setNetworkProcessSuspensionAllowedForTesting:(BOOL)allowed
     735{
     736    WebKit::NetworkProcessProxy::setSuspensionAllowedForTesting(allowed);
    737737}
    738738
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h

    r281349 r281721  
    9696- (void)_sendNetworkProcessWillSuspendImminently WK_API_AVAILABLE(macos(12.0), ios(15.0));
    9797- (void)_sendNetworkProcessDidResume WK_API_AVAILABLE(macos(12.0), ios(15.0));
    98 + (void)_preventNetworkProcessSuspensionForTesting WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
     98+ (void)_setNetworkProcessSuspensionAllowedForTesting:(BOOL)allowed WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
    9999- (void)_synthesizeAppIsBackground:(BOOL)background WK_API_AVAILABLE(macos(12.0), ios(15.0));
    100100- (pid_t)_networkProcessIdentifier WK_API_AVAILABLE(macos(12.0), ios(15.0));
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebsiteDataStoreConfiguration.h

    r280015 r281721  
    6161@property (nonatomic, copy, setter=_setCookieStorageFile:) NSURL *_cookieStorageFile;
    6262@property (nonatomic, copy, setter=_setResourceLoadStatisticsDirectory:) NSURL *_resourceLoadStatisticsDirectory WK_API_AVAILABLE(macos(10.13.4), ios(11.3));
     63@property (nonatomic, nullable, copy) NSURL *privateClickMeasurementStorageDirectory WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
    6364@property (nonatomic, copy, setter=_setCacheStorageDirectory:) NSURL *_cacheStorageDirectory WK_API_AVAILABLE(macos(10.13.4), ios(11.3));
    6465@property (nonatomic, copy, setter=_setServiceWorkerRegistrationDirectory:) NSURL *_serviceWorkerRegistrationDirectory WK_API_AVAILABLE(macos(10.13.4), ios(11.3));
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebsiteDataStoreConfiguration.mm

    r280015 r281721  
    187187}
    188188
     189- (NSURL *)privateClickMeasurementStorageDirectory
     190{
     191    auto& directory = _configuration->privateClickMeasurementStorageDirectory();
     192    if (directory.isNull())
     193        return nil;
     194    return [NSURL fileURLWithPath:directory isDirectory:YES];
     195}
     196
     197- (void)setPrivateClickMeasurementStorageDirectory:(NSURL *)url
     198{
     199    if (!_configuration->isPersistent())
     200        [NSException raise:NSInvalidArgumentException format:@"Cannot set privateClickMeasurementStorageDirectory on a non-persistent _WKWebsiteDataStoreConfiguration."];
     201    checkURLArgument(url);
     202    _configuration->setPrivateClickMeasurementStorageDirectory(url.path);
     203}
     204
    189205- (NSURL *)_cacheStorageDirectory
    190206{
  • trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp

    r281706 r281721  
    12631263}
    12641264
    1265 static bool s_suspensionPreventedForTesting { false };
    1266 void NetworkProcessProxy::preventSuspensionForTesting()
    1267 {
    1268     s_suspensionPreventedForTesting = true;
     1265static bool s_suspensionAllowedForTesting { true };
     1266void NetworkProcessProxy::setSuspensionAllowedForTesting(bool allowed)
     1267{
     1268    s_suspensionAllowedForTesting = allowed;
    12691269}
    12701270
    12711271void NetworkProcessProxy::sendPrepareToSuspend(IsSuspensionImminent isSuspensionImminent, CompletionHandler<void()>&& completionHandler)
    12721272{
    1273     if (s_suspensionPreventedForTesting)
     1273    if (!s_suspensionAllowedForTesting)
    12741274        return completionHandler();
    12751275    sendWithAsyncReply(Messages::NetworkProcess::PrepareToSuspend(isSuspensionImminent == IsSuspensionImminent::Yes), WTFMove(completionHandler), 0, { }, ShouldStartProcessThrottlerActivity::No);
  • trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h

    r281706 r281721  
    235235    ASCIILiteral clientName() const final { return "NetworkProcess"_s; }
    236236   
    237     static void preventSuspensionForTesting();
     237    static void setSuspensionAllowedForTesting(bool);
    238238    void sendProcessWillSuspendImminentlyForTesting();
    239239
  • trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp

    r281199 r281721  
    262262    if (!m_configuration->resourceLoadStatisticsDirectory().isEmpty())
    263263        m_resolvedConfiguration->setResourceLoadStatisticsDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->resourceLoadStatisticsDirectory()));
     264    if (!m_configuration->privateClickMeasurementStorageDirectory().isEmpty())
     265        m_resolvedConfiguration->setPrivateClickMeasurementStorageDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->privateClickMeasurementStorageDirectory()));
    264266    if (!m_configuration->serviceWorkerRegistrationDirectory().isEmpty() && m_resolvedConfiguration->serviceWorkerRegistrationDirectory().isEmpty())
    265267        m_resolvedConfiguration->setServiceWorkerRegistrationDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->serviceWorkerRegistrationDirectory()));
     
    19651967    resolveDirectoriesIfNecessary();
    19661968
    1967     auto resourceLoadStatisticsDirectory = m_configuration->resourceLoadStatisticsDirectory();
     1969    auto resourceLoadStatisticsDirectory = m_resolvedConfiguration->resourceLoadStatisticsDirectory();
    19681970    SandboxExtension::Handle resourceLoadStatisticsDirectoryHandle;
    19691971    if (!resourceLoadStatisticsDirectory.isEmpty()) {
    19701972        if (auto handle = SandboxExtension::createHandleForReadWriteDirectory(resourceLoadStatisticsDirectory))
    19711973            resourceLoadStatisticsDirectoryHandle = WTFMove(*handle);
     1974    }
     1975
     1976    auto privateClickMeasurementStorageDirectory = m_resolvedConfiguration->privateClickMeasurementStorageDirectory();
     1977    SandboxExtension::Handle privateClickMeasurementStorageDirectoryHandle;
     1978    if (!privateClickMeasurementStorageDirectory.isEmpty()) {
     1979        if (auto handle = SandboxExtension::createHandleForReadWriteDirectory(privateClickMeasurementStorageDirectory))
     1980            privateClickMeasurementStorageDirectoryHandle = WTFMove(*handle);
    19721981    }
    19731982
     
    20012010        WTFMove(resourceLoadStatisticsDirectory),
    20022011        WTFMove(resourceLoadStatisticsDirectoryHandle),
     2012        WTFMove(privateClickMeasurementStorageDirectory),
     2013        WTFMove(privateClickMeasurementStorageDirectoryHandle),
    20032014        resourceLoadStatisticsEnabled(),
    20042015#if ENABLE(RESOURCE_LOAD_STATISTICS)
  • trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStoreConfiguration.cpp

    r280015 r281721  
    7777    copy->m_deviceIdHashSaltsStorageDirectory = this->m_deviceIdHashSaltsStorageDirectory;
    7878    copy->m_resourceLoadStatisticsDirectory = this->m_resourceLoadStatisticsDirectory;
     79    copy->m_privateClickMeasurementStorageDirectory = this->m_privateClickMeasurementStorageDirectory;
    7980    copy->m_javaScriptConfigurationDirectory = this->m_javaScriptConfigurationDirectory;
    8081    copy->m_cookieStorageFile = this->m_cookieStorageFile;
  • trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStoreConfiguration.h

    r280015 r281721  
    118118    void setResourceLoadStatisticsDirectory(String&& directory) { m_resourceLoadStatisticsDirectory = WTFMove(directory); }
    119119
     120    const String& privateClickMeasurementStorageDirectory() const { return m_privateClickMeasurementStorageDirectory; }
     121    void setPrivateClickMeasurementStorageDirectory(String&& directory) { m_privateClickMeasurementStorageDirectory = WTFMove(directory); }
     122
    120123    const String& networkCacheDirectory() const { return m_networkCacheDirectory; }
    121124    void setNetworkCacheDirectory(String&& directory) { m_networkCacheDirectory = WTFMove(directory); }
     
    202205    String m_deviceIdHashSaltsStorageDirectory;
    203206    String m_resourceLoadStatisticsDirectory;
     207    String m_privateClickMeasurementStorageDirectory;
    204208    String m_javaScriptConfigurationDirectory;
    205209    String m_cookieStorageFile;
  • trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj

    r281365 r281721  
    12721272                5C795D71229F3757003FF1C4 /* WKContextMenuElementInfoPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CE0C36A229F2D4A003695F0 /* WKContextMenuElementInfoPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
    12731273                5C7FB47021E97DC5009E3241 /* WebCookieJar.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C7FB46F21E97C0C009E3241 /* WebCookieJar.h */; };
     1274                5C826D6B26D482EF008AEC91 /* PrivateClickMeasurementStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C826D6826D46B44008AEC91 /* PrivateClickMeasurementStore.h */; };
     1275                5C826D6C26D482F2008AEC91 /* PrivateClickMeasurementDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C826D6926D482EA008AEC91 /* PrivateClickMeasurementDatabase.h */; };
    12741276                5C8BC797218CBB4800813886 /* SafeBrowsing.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5C8BC796218CB58A00813886 /* SafeBrowsing.xcassets */; };
    12751277                5C8DD3801FE4521600F2A556 /* WebsiteAutoplayPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C8DD37F1FE4519200F2A556 /* WebsiteAutoplayPolicy.h */; };
     
    45104512                5C80B3DB23690D8D0086E6DE /* ServiceWorkerInitializationData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServiceWorkerInitializationData.h; sourceTree = "<group>"; };
    45114513                5C80B3DD23690F100086E6DE /* ServiceWorkerInitializationData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ServiceWorkerInitializationData.cpp; sourceTree = "<group>"; };
     4514                5C826D6726D46B43008AEC91 /* PrivateClickMeasurementStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PrivateClickMeasurementStore.cpp; sourceTree = "<group>"; };
     4515                5C826D6826D46B44008AEC91 /* PrivateClickMeasurementStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrivateClickMeasurementStore.h; sourceTree = "<group>"; };
     4516                5C826D6926D482EA008AEC91 /* PrivateClickMeasurementDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrivateClickMeasurementDatabase.h; sourceTree = "<group>"; };
     4517                5C826D6A26D482EA008AEC91 /* PrivateClickMeasurementDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PrivateClickMeasurementDatabase.cpp; sourceTree = "<group>"; };
     4518                5C826D6E26D58A16008AEC91 /* DatabaseUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseUtilities.cpp; sourceTree = "<group>"; };
     4519                5C826D6F26D58A16008AEC91 /* DatabaseUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseUtilities.h; sourceTree = "<group>"; };
    45124520                5C84CF901F96AC4E00B6705A /* NetworkSessionCreationParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkSessionCreationParameters.h; sourceTree = "<group>"; };
    45134521                5C85C7861C3F23C50061A4FA /* PendingDownload.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PendingDownload.cpp; sourceTree = "<group>"; };
     
    45474555                5CBC9B891C6524A500A8FDCF /* NetworkDataTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkDataTask.h; sourceTree = "<group>"; };
    45484556                5CBC9B8B1C65257300A8FDCF /* NetworkDataTaskCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkDataTaskCocoa.mm; sourceTree = "<group>"; };
     4557                5CBE908F26D7FB62005A2E95 /* PrivateClickMeasurementDebugInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrivateClickMeasurementDebugInfo.h; sourceTree = "<group>"; };
     4558                5CBE909026D7FB7C005A2E95 /* PrivateClickMeasurementDebugInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PrivateClickMeasurementDebugInfo.cpp; sourceTree = "<group>"; };
    45494559                5CC5DB9121488E16006CB8A8 /* SharedBufferCopy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SharedBufferCopy.h; sourceTree = "<group>"; };
    45504560                5CD286491E722F440094FDC8 /* _WKUserContentFilterPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKUserContentFilterPrivate.h; sourceTree = "<group>"; };
     
    86738683                                2DA944BB188511DD00ED86DB /* ios */,
    86748684                                510CC7DC16138E2900D03ED3 /* mac */,
     8685                                5C01BC3526D46AD400FEB42F /* PrivateClickMeasurement */,
    86758686                                93BA04D92151ADCD007F455F /* ServiceWorker */,
    86768687                                413075971DE84ED70039EC69 /* webrtc */,
    86778688                                93B26143227D143100B97A76 /* WebStorage */,
     8689                                5C826D6E26D58A16008AEC91 /* DatabaseUtilities.cpp */,
     8690                                5C826D6F26D58A16008AEC91 /* DatabaseUtilities.h */,
    86788691                                53F3CAA5206C443E0086490E /* NetworkActivityTracker.cpp */,
    86798692                                535BCB902069C49C00CCCE02 /* NetworkActivityTracker.h */,
     
    92429255                        );
    92439256                        path = SOAuthorization;
     9257                        sourceTree = "<group>";
     9258                };
     9259                5C01BC3526D46AD400FEB42F /* PrivateClickMeasurement */ = {
     9260                        isa = PBXGroup;
     9261                        children = (
     9262                                5C826D6A26D482EA008AEC91 /* PrivateClickMeasurementDatabase.cpp */,
     9263                                5C826D6926D482EA008AEC91 /* PrivateClickMeasurementDatabase.h */,
     9264                                5CBE909026D7FB7C005A2E95 /* PrivateClickMeasurementDebugInfo.cpp */,
     9265                                5CBE908F26D7FB62005A2E95 /* PrivateClickMeasurementDebugInfo.h */,
     9266                                5C826D6726D46B43008AEC91 /* PrivateClickMeasurementStore.cpp */,
     9267                                5C826D6826D46B44008AEC91 /* PrivateClickMeasurementStore.h */,
     9268                        );
     9269                        path = PrivateClickMeasurement;
    92449270                        sourceTree = "<group>";
    92459271                };
     
    1230712333                                AAB145E6223F931200E489D8 /* PrefetchCache.h in Headers */,
    1230812334                                E1CC1B9012D7EADF00625838 /* PrintInfo.h in Headers */,
     12335                                5C826D6C26D482F2008AEC91 /* PrivateClickMeasurementDatabase.h in Headers */,
    1230912336                                6BD05865220CE8C2000BED5C /* PrivateClickMeasurementManager.h in Headers */,
    1231012337                                57FE688C260ABB3D00BF45E4 /* PrivateClickMeasurementNetworkLoader.h in Headers */,
     12338                                5C826D6B26D482EF008AEC91 /* PrivateClickMeasurementStore.h in Headers */,
    1231112339                                86F9536518FF58F5001DB2EF /* ProcessAssertion.h in Headers */,
    1231212340                                BC1A7C581136E19C00FB7167 /* ProcessLauncher.h in Headers */,
  • trunk/Tools/ChangeLog

    r281709 r281721  
     12021-08-27  Alex Christensen  <achristensen@webkit.org>
     2
     3        Separate PrivateClickMeasurement database from ResourceLoadStatistics database and add SPI to set its location
     4        https://bugs.webkit.org/show_bug.cgi?id=229527
     5
     6        Reviewed by Kate Cheney.
     7
     8        * TestWebKitAPI/Tests/WebKitCocoa/EventAttribution.mm:
     9        (TestWebKitAPI::runBasicEventAttributionTest):
     10        (TestWebKitAPI::TEST):
     11        * TestWebKitAPI/Tests/WebKitCocoa/PrivateClickMeasurement.mm:
     12        (TEST):
     13
    1142021-08-27  Chris Dumez  <cdumez@apple.com>
    215
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/EventAttribution.mm

    r281349 r281721  
    2929#import "PlatformUtilities.h"
    3030#import "TestNavigationDelegate.h"
     31#import "TestWKWebView.h"
    3132#import "Utilities.h"
    3233#import <WebKit/WKWebViewPrivate.h>
    3334#import <WebKit/WKWebViewPrivateForTesting.h>
    3435#import <WebKit/WKWebsiteDataStorePrivate.h>
     36#import <WebKit/_WKWebsiteDataStoreConfiguration.h>
    3537
    3638#if HAVE(RSA_BSSA)
     
    7981}
    8082
    81 void runBasicEventAttributionTest(Function<void(WKWebView *, const HTTPServer&)>&& addAttributionToWebView)
    82 {
    83     [WKWebsiteDataStore _preventNetworkProcessSuspensionForTesting];
     83void runBasicEventAttributionTest(WKWebViewConfiguration *configuration, Function<void(WKWebView *, const HTTPServer&)>&& addAttributionToWebView)
     84{
     85    [WKWebsiteDataStore _setNetworkProcessSuspensionAllowedForTesting:NO];
    8486    bool done = false;
    8587    HTTPServer server([&done, connectionCount = 0] (Connection connection) mutable {
     
    114116    NSURL *serverURL = server.request().URL;
    115117
    116     auto webView = adoptNS([WKWebView new]);
     118    auto webView = configuration ? adoptNS([[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration]) : adoptNS([WKWebView new]);
    117119    addAttributionToWebView(webView.get(), server);
    118120    [[webView configuration].websiteDataStore _setResourceLoadStatisticsEnabled:YES];
     
    130132TEST(EventAttribution, FraudPrevention)
    131133{
    132     [WKWebsiteDataStore _preventNetworkProcessSuspensionForTesting];
     134    [WKWebsiteDataStore _setNetworkProcessSuspensionAllowedForTesting:NO];
    133135    bool done = false;
    134136
     
    283285TEST(EventAttribution, Basic)
    284286{
    285     runBasicEventAttributionTest([](WKWebView *webView, const HTTPServer& server) {
     287    runBasicEventAttributionTest(nil, [](WKWebView *webView, const HTTPServer& server) {
    286288        [webView _addEventAttributionWithSourceID:42 destinationURL:exampleURL() sourceDescription:@"test source description" purchaser:@"test purchaser" reportEndpoint:server.request().URL optionalNonce:nil];
    287289    });
    288290}
    289291
     292TEST(EventAttribution, DatabaseLocation)
     293{
     294    NSFileManager *fileManager = [NSFileManager defaultManager];
     295    NSURL *tempDir = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"EventAttributionDatabaseLocationTest"] isDirectory:YES];
     296    if ([fileManager fileExistsAtPath:tempDir.path])
     297        [fileManager removeItemAtURL:tempDir error:nil];
     298
     299    auto webViewToKeepNetworkProcessAlive = adoptNS([TestWKWebView new]);
     300    [webViewToKeepNetworkProcessAlive synchronouslyLoadHTMLString:@"start network process"];
     301
     302    pid_t originalNetworkProcessPid = 0;
     303    @autoreleasepool {
     304        auto dataStoreConfiguration = adoptNS([_WKWebsiteDataStoreConfiguration new]);
     305        dataStoreConfiguration.get().privateClickMeasurementStorageDirectory = tempDir;
     306        auto viewConfiguration = adoptNS([WKWebViewConfiguration new]);
     307        auto dataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:dataStoreConfiguration.get()]);
     308        viewConfiguration.get().websiteDataStore = dataStore.get();
     309        runBasicEventAttributionTest(viewConfiguration.get(), [](WKWebView *webView, const HTTPServer& server) {
     310            [webView _addEventAttributionWithSourceID:42 destinationURL:exampleURL() sourceDescription:@"test source description" purchaser:@"test purchaser" reportEndpoint:server.request().URL optionalNonce:nil];
     311        });
     312        originalNetworkProcessPid = [dataStore _networkProcessIdentifier];
     313        EXPECT_GT(originalNetworkProcessPid, 0);
     314
     315        __block bool suspended = false;
     316        [WKWebsiteDataStore _setNetworkProcessSuspensionAllowedForTesting:YES];
     317        [dataStore _sendNetworkProcessPrepareToSuspend:^{
     318            suspended = true;
     319            [dataStore _sendNetworkProcessDidResume];
     320        }];
     321        Util::run(&suspended);
     322        Util::spinRunLoop(10);
     323    }
     324    Util::spinRunLoop(10);
     325    usleep(100000);
     326    Util::spinRunLoop(10);
     327
     328    EXPECT_TRUE([fileManager fileExistsAtPath:tempDir.path]);
     329    EXPECT_TRUE([fileManager fileExistsAtPath:[tempDir.path stringByAppendingPathComponent:@"pcm.db"]]);
     330
     331    [webViewToKeepNetworkProcessAlive synchronouslyLoadHTMLString:@"start network process again if it crashed during teardown"];
     332    EXPECT_EQ(webViewToKeepNetworkProcessAlive.get().configuration.websiteDataStore._networkProcessIdentifier, originalNetworkProcessPid);
     333}
     334
     335// FIXME: Write a test that verifies that data is migrated from old ResourceLoadStatistics databases to the new PCM database.
     336
    290337#if HAVE(UI_EVENT_ATTRIBUTION)
    291338
    292339TEST(EventAttribution, BasicWithIOSSPI)
    293340{
    294     runBasicEventAttributionTest([](WKWebView *webView, const HTTPServer& server) {
     341    runBasicEventAttributionTest(nil, [](WKWebView *webView, const HTTPServer& server) {
    295342        auto attribution = adoptNS([[MockEventAttribution alloc] initWithReportEndpoint:server.request().URL destinationURL:exampleURL()]);
    296343        webView._uiEventAttribution = (UIEventAttribution *)attribution.get();
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PrivateClickMeasurement.mm

    r275106 r281721  
    3333#import <wtf/RetainPtr.h>
    3434
     35// FIXME: Implement migration from older databases and get these tests working as they should again.
     36
    3537TEST(PrivateClickMeasurement, AddMissingPCMFraudPreventionColumns)
    3638{
     
    6365    __block bool doneFlag = false;
    6466    [dataStore _statisticsDatabaseColumnsForTable:@"UnattributedPrivateClickMeasurement" completionHandler:^(NSArray<NSString *> *tableSchema) {
    65         EXPECT_TRUE([tableSchema containsObject:@"token"]);
    66         EXPECT_TRUE([tableSchema containsObject:@"keyID"]);
    67         EXPECT_TRUE([tableSchema containsObject:@"signature"]);
     67        EXPECT_FALSE([tableSchema containsObject:@"token"]);
     68        EXPECT_FALSE([tableSchema containsObject:@"keyID"]);
     69        EXPECT_FALSE([tableSchema containsObject:@"signature"]);
    6870        doneFlag = true;
    6971    }];
     
    7375    doneFlag = false;
    7476    [dataStore _statisticsDatabaseColumnsForTable:@"AttributedPrivateClickMeasurement" completionHandler:^(NSArray<NSString *> *tableSchema) {
    75         EXPECT_TRUE([tableSchema containsObject:@"token"]);
    76         EXPECT_TRUE([tableSchema containsObject:@"keyID"]);
    77         EXPECT_TRUE([tableSchema containsObject:@"signature"]);
     77        EXPECT_FALSE([tableSchema containsObject:@"token"]);
     78        EXPECT_FALSE([tableSchema containsObject:@"keyID"]);
     79        EXPECT_FALSE([tableSchema containsObject:@"signature"]);
    7880        doneFlag = true;
    7981    }];
     
    112114    __block bool doneFlag = false;
    113115    [dataStore _statisticsDatabaseColumnsForTable:@"AttributedPrivateClickMeasurement" completionHandler:^(NSArray<NSString *> *tableSchema) {
    114         EXPECT_TRUE([tableSchema containsObject:@"earliestTimeToSendToSource"]);
    115         EXPECT_TRUE([tableSchema containsObject:@"earliestTimeToSendToDestination"]);
     116        EXPECT_FALSE([tableSchema containsObject:@"earliestTimeToSendToSource"]);
     117        EXPECT_FALSE([tableSchema containsObject:@"earliestTimeToSendToDestination"]);
    116118        doneFlag = true;
    117119    }];
     
    150152    __block bool doneFlag = false;
    151153    [dataStore _statisticsDatabaseColumnsForTable:@"AttributedPrivateClickMeasurement" completionHandler:^(NSArray<NSString *> *tableSchema) {
    152         EXPECT_TRUE([tableSchema containsObject:@"destinationSiteDomainID"]);
     154        EXPECT_FALSE([tableSchema containsObject:@"destinationSiteDomainID"]);
    153155        doneFlag = true;
    154156    }];
Note: See TracChangeset for help on using the changeset viewer.