Title: [283316] trunk
Revision
283316
Author
wilan...@apple.com
Date
2021-09-30 09:22:01 -0700 (Thu, 30 Sep 2021)

Log Message

PCM: Take app bundle ID into consideration when matching triggering events with pending clicks
https://bugs.webkit.org/show_bug.cgi?id=230778
<rdar://problem/83516528>

Reviewed by Alex Christensen.

https://commits.webkit.org/r282884 added app bundle IDs to unattributed
and attributed clicks in PCM. This patch makes sure we take those IDs
into consideration in PCM::Database::attributePrivateClickMeasurement().

Source/WebCore:

The WebCore part makes sure that a temporary app bundle ID can be set
on attributions that get stored in PCM's database.

Test: http/tests/privateClickMeasurement/multiple-app-bundle-ids.html

* loader/PrivateClickMeasurement.cpp:
(WebCore::PrivateClickMeasurement::setSourceApplicationBundleIDForTesting):
* loader/PrivateClickMeasurement.h:

Source/WebKit:

A lot of the WebKit part is:
- Piping through app bundle IDs from the network session to the PCM
    database where the ID will be matched against stored app bundle IDs.
- Piping through test configuration for app bundle ID.

The real change is in PCM::Database which is explained below.

Test: http/tests/privateClickMeasurement/multiple-app-bundle-ids.html

* NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::setPrivateClickMeasurementAppBundleIDForTesting):
* NetworkProcess/NetworkProcess.h:
* NetworkProcess/NetworkProcess.messages.in:
* NetworkProcess/NetworkSession.cpp:
(WebKit::NetworkSession::handlePrivateClickMeasurementConversion):
(WebKit::NetworkSession::setPrivateClickMeasurementAppBundleIDForTesting):
* NetworkProcess/NetworkSession.h:
* NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDatabase.cpp:
(WebKit::PCM::Database::findPrivateClickMeasurement):
    Now takes an app bundle ID supplied from the network session and
    includes it in the database query to find matching entries. If and
    attribution was saved with app bundle ID XYZ, it should only be
    be converted in an application with app bundle ID XYZ.
(WebKit::PCM::Database::attributePrivateClickMeasurement):
    This function calls PCM::Database::findPrivateClickMeasurement()
    which needs the app bundle ID so that ID is forwarded through.
(WebKit::PCM::Database::removeUnattributed):
    Also needs to take the app bundle ID into consideration.
(WebKit::PCM::Database::clearSentAttribution):
    Also needs to take the app bundle ID into consideration.
(WebKit::PCM::Database::markReportAsSentToDestination):
    Also needs to take the app bundle ID into consideration.
(WebKit::PCM::Database::markReportAsSentToSource):
    Also needs to take the app bundle ID into consideration.
(WebKit::PCM::Database::earliestTimesToSend):
    Also needs to take the app bundle ID into consideration.
* NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDatabase.h:
* NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManager.cpp:
(WebKit::PrivateClickMeasurementManager::storeUnattributed):
(WebKit::PrivateClickMeasurementManager::handleAttribution):
(WebKit::PrivateClickMeasurementManager::setPrivateClickMeasurementAppBundleIDForTesting):
(WebKit::PrivateClickMeasurementManager::attribute):
(WebKit::PrivateClickMeasurementManager::clear):
    Clears the test setting for app bundle ID.
* NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManager.h:
* NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerInterface.cpp:
(WebKit::PCM::messageTypeSendsReply):
(WebKit::PCM::decodeMessageAndSendToManager):
* NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerInterface.h:
* NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerProxy.cpp:
(WebKit::PCM::ManagerProxy::handleAttribution):
(WebKit::PCM::ManagerProxy::setPrivateClickMeasurementAppBundleIDForTesting):
* NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerProxy.h:
* NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementStore.cpp:
(WebKit::PCM::Store::attributePrivateClickMeasurement):
* NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementStore.h:
* UIProcess/API/C/WKPage.cpp:
(WKPageSetPCMFraudPreventionValuesForTesting):
(WKPageSetPrivateClickMeasurementAppBundleIDForTesting):
* UIProcess/API/C/WKPagePrivate.h:
* UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h:
* UIProcess/API/Cocoa/WKWebViewTesting.mm:
(-[WKWebView _setPrivateClickMeasurementAppBundleIDForTesting:completionHandler:]):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::setPrivateClickMeasurementAppBundleIDForTesting):
* UIProcess/WebPageProxy.h:

Tools:

The TestRunner changes are all test infrastructure to enable different
app bundle IDs in the eyes of PCM. The API test changes are to make use
of the app bundle ID test infrastructure.

* TestWebKitAPI/Tests/WebKitCocoa/EventAttribution.mm:
(TestWebKitAPI::runBasicEventAttributionTest):
(TestWebKitAPI::TEST):
* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::setPrivateClickMeasurementAppBundleIDForTesting):
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::setPrivateClickMeasurementAppBundleIDForTesting):
* WebKitTestRunner/TestController.h:
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):

LayoutTests:

* http/tests/privateClickMeasurement/multiple-app-bundle-ids-expected.txt: Added.
* http/tests/privateClickMeasurement/multiple-app-bundle-ids.html: Added.
* http/tests/privateClickMeasurement/resources/util.js:
(tearDownAndFinish):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (283315 => 283316)


--- trunk/LayoutTests/ChangeLog	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/LayoutTests/ChangeLog	2021-09-30 16:22:01 UTC (rev 283316)
@@ -1,3 +1,20 @@
+2021-09-30  John Wilander  <wilan...@apple.com>
+
+        PCM: Take app bundle ID into consideration when matching triggering events with pending clicks
+        https://bugs.webkit.org/show_bug.cgi?id=230778
+        <rdar://problem/83516528>
+
+        Reviewed by Alex Christensen.
+
+        https://commits.webkit.org/r282884 added app bundle IDs to unattributed
+        and attributed clicks in PCM. This patch makes sure we take those IDs
+        into consideration in PCM::Database::attributePrivateClickMeasurement().
+
+        * http/tests/privateClickMeasurement/multiple-app-bundle-ids-expected.txt: Added.
+        * http/tests/privateClickMeasurement/multiple-app-bundle-ids.html: Added.
+        * http/tests/privateClickMeasurement/resources/util.js:
+        (tearDownAndFinish):
+
 2021-09-30  Alan Bujtas  <za...@apple.com>
 
         (REGRESSION r282150) Missing background-color on inline box while hovering

Added: trunk/LayoutTests/http/tests/privateClickMeasurement/multiple-app-bundle-ids-expected.txt (0 => 283316)


--- trunk/LayoutTests/http/tests/privateClickMeasurement/multiple-app-bundle-ids-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/privateClickMeasurement/multiple-app-bundle-ids-expected.txt	2021-09-30 16:22:01 UTC (rev 283316)
@@ -0,0 +1,35 @@
+Tests private click measurement with multiple app bundle IDs, making sure only the matching ID is considered a match.
+
+
+
+
+--------
+Frame: '<!--frame1-->'
+--------
+Attribution received.
+HTTP_HOST: 127.0.0.1:8000
+Content type: application/json
+REQUEST_URI: /privateClickMeasurement/resources/conversionReport.py?recipient=ClickSource
+No cookies in attribution request.
+Request body:
+{"source_engagement_type":"click","source_site":"127.0.0.1","source_id":33,"attributed_on_site":"localhost","trigger_data":12,"version":2}
+
+
+--------
+Frame: '<!--frame2-->'
+--------
+Attribution received.
+HTTP_HOST: localhost:8000
+Content type: application/json
+REQUEST_URI: /privateClickMeasurement/resources/conversionReport.py?recipient=ClickDestination
+No cookies in attribution request.
+Request body:
+{"source_engagement_type":"click","source_site":"127.0.0.1","source_id":33,"attributed_on_site":"localhost","trigger_data":12,"version":2}
+
+Unattributed Private Click Measurements:
+WebCore::PrivateClickMeasurement 1
+Source site: 127.0.0.1
+Attribute on site: localhost
+Source ID: 23
+No attribution trigger data.
+Application bundle identifier: testBundleID

Added: trunk/LayoutTests/http/tests/privateClickMeasurement/multiple-app-bundle-ids.html (0 => 283316)


--- trunk/LayoutTests/http/tests/privateClickMeasurement/multiple-app-bundle-ids.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/privateClickMeasurement/multiple-app-bundle-ids.html	2021-09-30 16:22:01 UTC (rev 283316)
@@ -0,0 +1,103 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+    <script src=""
+    <script src=""
+</head>
+<body _onload_="setTimeout(runTest, 0)">
+<div id="description">Tests private click measurement with multiple app bundle IDs, making sure only the matching ID is considered a match.</div>
+<a id="targetLink1" href="" attributionsourceid=23 attributiondestination="http://localhost:8000">Link1</a><br>
+<a id="targetLink2" href="" attributionsourceid=33 attributiondestination="http://localhost:8000">Link2</a><br>
+<div id="output"></div>
+<script>
+    const currentTimeMillis = (new Date()).getTime();
+    const highEntropyBits = currentTimeMillis - (Math.floor(currentTimeMillis / 1000000) * 1000000);
+    const nonce = highEntropyBits + "" + Math.floor(Math.random() * 100);
+
+    prepareTest();
+
+    if (window.testRunner) {
+        testRunner.setPrivateClickMeasurementOverrideTimerForTesting(true);
+    }
+
+    function finishTest() {
+        testRunner.dumpPrivateClickMeasurement();
+        tearDownAndFinish();
+    }
+
+    function activateElement(elementID) {
+        var element = document.getElementById(elementID);
+        var centerX = element.offsetLeft + element.offsetWidth / 2;
+        var centerY = element.offsetTop + element.offsetHeight / 2;
+        UIHelper.activateAt(centerX, centerY).then(
+            function () {
+            },
+            function () {
+                document.getElementById("output").innerText = "FAIL Promise rejected.";
+                tearDownAndFinish();
+            }
+        );
+    }
+
+    function appendIframe(url, onloadCallback) {
+        let iframeElement = document.createElement("iframe");
+        iframeElement.src = ""
+        if (onloadCallback)
+            iframeElement._onload_ = onloadCallback;
+        document.body.appendChild(iframeElement);
+    }
+
+    let reportsReceived = 0;
+    function appendConversionDataIframeAndFinish() {
+        document.body.removeChild(document.getElementById("targetLink1"));
+        document.body.removeChild(document.getElementById("targetLink2"));
+        document.body.removeChild(document.getElementById("pixel"));
+
+        // Click source.
+        appendIframe("http://127.0.0.1:8000/privateClickMeasurement/resources/getConversionData.py?timeout_ms=2000&recipient=ClickSource&nonce=" + nonce, function() {
+            reportsReceived++;
+            if (reportsReceived >= 2)
+                finishTest();
+        });
+
+        // Click destination.
+        appendIframe("http://127.0.0.1:8000/privateClickMeasurement/resources/getConversionData.py?timeout_ms=2000&recipient=ClickDestination&nonce=" + nonce, function() {
+            reportsReceived++;
+            if (reportsReceived >= 2)
+                finishTest();
+        });
+    }
+
+    function runTest() {
+        if (window.testRunner) {
+            if (window.location.search === "?stepTwo") {
+                // Step 2: Go back to the source.
+                document.location.href = ""
+            } else if (window.location.search === "?stepThree") {
+                // Step 3: Change the app bundle ID and click the second link.
+                testRunner.setPrivateClickMeasurementAppBundleIDForTesting("");
+                activateElement("targetLink2");
+            } else if (window.location.search === "?stepFour") {
+                // Step 4: Convert.
+                testRunner.setPrivateClickMeasurementAttributionReportURLsForTesting("http://127.0.0.1:8000/privateClickMeasurement/resources/conversionReport.py?recipient=ClickSource&nonce=" + nonce, "http://localhost:8000/privateClickMeasurement/resources/conversionReport.py?recipient=ClickDestination&nonce=" + nonce);
+                let imageElement = document.createElement("img");
+                imageElement.src = "" + nonce;
+                imageElement.id = "pixel";
+                imageElement._onerror_ = function() {
+                    appendConversionDataIframeAndFinish();
+                };
+                document.body.appendChild(imageElement);
+            } else {
+                // Step 1: Change the app bundle ID and click the first link.
+                testRunner.setPrivateClickMeasurementAppBundleIDForTesting("testBundleID");
+                activateElement("targetLink1");
+            }
+        } else {
+            document.getElementById("output").innerText = "FAIL No testRunner.";
+        }
+    }
+</script>
+</body>
+</html>

Modified: trunk/LayoutTests/http/tests/privateClickMeasurement/resources/util.js (283315 => 283316)


--- trunk/LayoutTests/http/tests/privateClickMeasurement/resources/util.js	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/LayoutTests/http/tests/privateClickMeasurement/resources/util.js	2021-09-30 16:22:01 UTC (rev 283316)
@@ -15,6 +15,7 @@
         testRunner.setPrivateClickMeasurementAttributionReportURLsForTesting("", "");
         testRunner.setPrivateClickMeasurementTokenSignatureURLForTesting("");
         testRunner.setPrivateClickMeasurementTokenPublicKeyURLForTesting("");
+        testRunner.setPrivateClickMeasurementAppBundleIDForTesting("");
         testRunner.notifyDone();
     }
 }

Modified: trunk/Source/WebCore/ChangeLog (283315 => 283316)


--- trunk/Source/WebCore/ChangeLog	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebCore/ChangeLog	2021-09-30 16:22:01 UTC (rev 283316)
@@ -1,3 +1,24 @@
+2021-09-30  John Wilander  <wilan...@apple.com>
+
+        PCM: Take app bundle ID into consideration when matching triggering events with pending clicks
+        https://bugs.webkit.org/show_bug.cgi?id=230778
+        <rdar://problem/83516528>
+
+        Reviewed by Alex Christensen.
+
+        https://commits.webkit.org/r282884 added app bundle IDs to unattributed
+        and attributed clicks in PCM. This patch makes sure we take those IDs
+        into consideration in PCM::Database::attributePrivateClickMeasurement().
+
+        The WebCore part makes sure that a temporary app bundle ID can be set
+        on attributions that get stored in PCM's database.
+
+        Test: http/tests/privateClickMeasurement/multiple-app-bundle-ids.html
+
+        * loader/PrivateClickMeasurement.cpp:
+        (WebCore::PrivateClickMeasurement::setSourceApplicationBundleIDForTesting):
+        * loader/PrivateClickMeasurement.h:
+
 2021-09-30  Youenn Fablet  <you...@apple.com>
 
         Support AES GCM ciphers in WebRTC

Modified: trunk/Source/WebCore/loader/PrivateClickMeasurement.cpp (283315 => 283316)


--- trunk/Source/WebCore/loader/PrivateClickMeasurement.cpp	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebCore/loader/PrivateClickMeasurement.cpp	2021-09-30 16:22:01 UTC (rev 283316)
@@ -142,6 +142,11 @@
     return !m_timesToSend.sourceEarliestTimeToSend || !m_timesToSend.destinationEarliestTimeToSend;
 }
 
+void PrivateClickMeasurement::setSourceApplicationBundleIDForTesting(const String& appBundleIDForTesting)
+{
+    m_sourceApplicationBundleID = appBundleIDForTesting;
+}
+
 static Seconds randomlyBetweenTwentyFourAndFortyEightHours()
 {
     return 24_h + Seconds(randomNumber() * (24_h).value());

Modified: trunk/Source/WebCore/loader/PrivateClickMeasurement.h (283315 => 283316)


--- trunk/Source/WebCore/loader/PrivateClickMeasurement.h	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebCore/loader/PrivateClickMeasurement.h	2021-09-30 16:22:01 UTC (rev 283316)
@@ -329,6 +329,7 @@
     const std::optional<AttributionTriggerData>& attributionTriggerData() const { return m_attributionTriggerData; }
     void setAttribution(AttributionTriggerData&& attributionTriggerData) { m_attributionTriggerData = WTFMove(attributionTriggerData); }
     const String& sourceApplicationBundleID() const { return m_sourceApplicationBundleID; }
+    WEBCORE_EXPORT void setSourceApplicationBundleIDForTesting(const String&);
 
     bool isEphemeral() const { return m_isEphemeral == AttributionEphemeral::Yes; }
     void setEphemeral(AttributionEphemeral isEphemeral) { m_isEphemeral = isEphemeral; }

Modified: trunk/Source/WebKit/ChangeLog (283315 => 283316)


--- trunk/Source/WebKit/ChangeLog	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/ChangeLog	2021-09-30 16:22:01 UTC (rev 283316)
@@ -1,3 +1,82 @@
+2021-09-30  John Wilander  <wilan...@apple.com>
+
+        PCM: Take app bundle ID into consideration when matching triggering events with pending clicks
+        https://bugs.webkit.org/show_bug.cgi?id=230778
+        <rdar://problem/83516528>
+
+        Reviewed by Alex Christensen.
+
+        https://commits.webkit.org/r282884 added app bundle IDs to unattributed
+        and attributed clicks in PCM. This patch makes sure we take those IDs
+        into consideration in PCM::Database::attributePrivateClickMeasurement().
+
+        A lot of the WebKit part is:
+        - Piping through app bundle IDs from the network session to the PCM
+            database where the ID will be matched against stored app bundle IDs.
+        - Piping through test configuration for app bundle ID.
+
+        The real change is in PCM::Database which is explained below.
+
+        Test: http/tests/privateClickMeasurement/multiple-app-bundle-ids.html
+
+        * NetworkProcess/NetworkProcess.cpp:
+        (WebKit::NetworkProcess::setPrivateClickMeasurementAppBundleIDForTesting):
+        * NetworkProcess/NetworkProcess.h:
+        * NetworkProcess/NetworkProcess.messages.in:
+        * NetworkProcess/NetworkSession.cpp:
+        (WebKit::NetworkSession::handlePrivateClickMeasurementConversion):
+        (WebKit::NetworkSession::setPrivateClickMeasurementAppBundleIDForTesting):
+        * NetworkProcess/NetworkSession.h:
+        * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDatabase.cpp:
+        (WebKit::PCM::Database::findPrivateClickMeasurement):
+            Now takes an app bundle ID supplied from the network session and
+            includes it in the database query to find matching entries. If and
+            attribution was saved with app bundle ID XYZ, it should only be
+            be converted in an application with app bundle ID XYZ.
+        (WebKit::PCM::Database::attributePrivateClickMeasurement):
+            This function calls PCM::Database::findPrivateClickMeasurement()
+            which needs the app bundle ID so that ID is forwarded through.
+        (WebKit::PCM::Database::removeUnattributed):
+            Also needs to take the app bundle ID into consideration.
+        (WebKit::PCM::Database::clearSentAttribution):
+            Also needs to take the app bundle ID into consideration.
+        (WebKit::PCM::Database::markReportAsSentToDestination):
+            Also needs to take the app bundle ID into consideration.
+        (WebKit::PCM::Database::markReportAsSentToSource):
+            Also needs to take the app bundle ID into consideration.
+        (WebKit::PCM::Database::earliestTimesToSend):
+            Also needs to take the app bundle ID into consideration.
+        * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDatabase.h:
+        * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManager.cpp:
+        (WebKit::PrivateClickMeasurementManager::storeUnattributed):
+        (WebKit::PrivateClickMeasurementManager::handleAttribution):
+        (WebKit::PrivateClickMeasurementManager::setPrivateClickMeasurementAppBundleIDForTesting):
+        (WebKit::PrivateClickMeasurementManager::attribute):
+        (WebKit::PrivateClickMeasurementManager::clear):
+            Clears the test setting for app bundle ID.
+        * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManager.h:
+        * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerInterface.cpp:
+        (WebKit::PCM::messageTypeSendsReply):
+        (WebKit::PCM::decodeMessageAndSendToManager):
+        * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerInterface.h:
+        * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerProxy.cpp:
+        (WebKit::PCM::ManagerProxy::handleAttribution):
+        (WebKit::PCM::ManagerProxy::setPrivateClickMeasurementAppBundleIDForTesting):
+        * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerProxy.h:
+        * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementStore.cpp:
+        (WebKit::PCM::Store::attributePrivateClickMeasurement):
+        * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementStore.h:
+        * UIProcess/API/C/WKPage.cpp:
+        (WKPageSetPCMFraudPreventionValuesForTesting):
+        (WKPageSetPrivateClickMeasurementAppBundleIDForTesting):
+        * UIProcess/API/C/WKPagePrivate.h:
+        * UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h:
+        * UIProcess/API/Cocoa/WKWebViewTesting.mm:
+        (-[WKWebView _setPrivateClickMeasurementAppBundleIDForTesting:completionHandler:]):
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::setPrivateClickMeasurementAppBundleIDForTesting):
+        * UIProcess/WebPageProxy.h:
+
 2021-09-30  Alex Christensen  <achristen...@webkit.org>
 
         Clean up PrivateClickMeasurement

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (283315 => 283316)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2021-09-30 16:22:01 UTC (rev 283316)
@@ -2689,6 +2689,14 @@
     completionHandler();
 }
 
+void NetworkProcess::setPrivateClickMeasurementAppBundleIDForTesting(PAL::SessionID sessionID, String&& appBundleIDForTesting, CompletionHandler<void()>&& completionHandler)
+{
+    if (auto* session = networkSession(sessionID))
+        session->setPrivateClickMeasurementAppBundleIDForTesting(WTFMove(appBundleIDForTesting));
+
+    completionHandler();
+}
+
 void NetworkProcess::addKeptAliveLoad(Ref<NetworkResourceLoader>&& loader)
 {
     if (auto* session = networkSession(loader->sessionID()))

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.h (283315 => 283316)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.h	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.h	2021-09-30 16:22:01 UTC (rev 283316)
@@ -350,6 +350,7 @@
     void setPrivateClickMeasurementAttributionReportURLsForTesting(PAL::SessionID, URL&& sourceURL, URL&& destinationURL, CompletionHandler<void()>&&);
     void markPrivateClickMeasurementsAsExpiredForTesting(PAL::SessionID, CompletionHandler<void()>&&);
     void setPCMFraudPreventionValuesForTesting(PAL::SessionID, String&& unlinkableToken, String&& secretToken, String&& signature, String&& keyID, CompletionHandler<void()>&&);
+    void setPrivateClickMeasurementAppBundleIDForTesting(PAL::SessionID, String&& appBundleIDForTesting, CompletionHandler<void()>&&);
 
     RefPtr<WebCore::StorageQuotaManager> storageQuotaManager(PAL::SessionID, const WebCore::ClientOrigin&);
 

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in (283315 => 283316)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in	2021-09-30 16:22:01 UTC (rev 283316)
@@ -171,6 +171,7 @@
     SetPrivateClickMeasurementAttributionReportURLsForTesting(PAL::SessionID sessionID, URL sourceURL, URL destinationURL) -> () Async
     MarkPrivateClickMeasurementsAsExpiredForTesting(PAL::SessionID sessionID) -> () Async
     SetPCMFraudPreventionValuesForTesting(PAL::SessionID sessionID, String secretToken, String unlinkableToken, String signature, String keyID) -> () Async
+    SetPrivateClickMeasurementAppBundleIDForTesting(PAL::SessionID sessionID, String appBundleIDForTesting) -> () Async
     GetLocalStorageOriginDetails(PAL::SessionID sessionID) -> (Vector<WebKit::LocalStorageDatabaseTracker::OriginDetails> details) Async
 
     SetServiceWorkerFetchTimeoutForTesting(Seconds seconds) -> () Synchronous

Modified: trunk/Source/WebKit/NetworkProcess/NetworkSession.cpp (283315 => 283316)


--- trunk/Source/WebKit/NetworkProcess/NetworkSession.cpp	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/NetworkProcess/NetworkSession.cpp	2021-09-30 16:22:01 UTC (rev 283316)
@@ -44,8 +44,10 @@
 #include "WebSocketTask.h"
 #include <WebCore/CookieJar.h>
 #include <WebCore/ResourceRequest.h>
+#include <WebCore/RuntimeApplicationChecks.h>
 
 #if PLATFORM(COCOA)
+#include "DefaultWebBrowserChecks.h"
 #include "NetworkSessionCocoa.h"
 #endif
 #if USE(SOUP)
@@ -324,7 +326,12 @@
 
 void NetworkSession::handlePrivateClickMeasurementConversion(PrivateClickMeasurement::AttributionTriggerData&& attributionTriggerData, const URL& requestURL, const WebCore::ResourceRequest& redirectRequest)
 {
-    privateClickMeasurement().handleAttribution(WTFMove(attributionTriggerData), requestURL, RegistrableDomain(redirectRequest.url()), redirectRequest.firstPartyForCookies());
+#if PLATFORM(COCOA)
+    auto appBundleID = WebCore::applicationBundleIdentifier();
+#else
+    auto appBundleID = String();
+#endif
+    privateClickMeasurement().handleAttribution(WTFMove(attributionTriggerData), requestURL, RegistrableDomain(redirectRequest.url()), redirectRequest.firstPartyForCookies(), appBundleID);
 }
 
 void NetworkSession::dumpPrivateClickMeasurement(CompletionHandler<void(String)>&& completionHandler)
@@ -393,6 +400,14 @@
     privateClickMeasurement().allowTLSCertificateChainForLocalPCMTesting(certificateInfo);
 }
 
+void NetworkSession::setPrivateClickMeasurementAppBundleIDForTesting(String&& appBundleIDForTesting)
+{
+#if PLATFORM(COCOA)
+    RELEASE_ASSERT(isRunningTest(WebCore::applicationBundleIdentifier()));
+#endif
+    privateClickMeasurement().setPrivateClickMeasurementAppBundleIDForTesting(WTFMove(appBundleIDForTesting));
+}
+
 void NetworkSession::addKeptAliveLoad(Ref<NetworkResourceLoader>&& loader)
 {
     ASSERT(m_sessionID == loader->sessionID());

Modified: trunk/Source/WebKit/NetworkProcess/NetworkSession.h (283315 => 283316)


--- trunk/Source/WebKit/NetworkProcess/NetworkSession.h	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/NetworkProcess/NetworkSession.h	2021-09-30 16:22:01 UTC (rev 283316)
@@ -141,6 +141,7 @@
     void setPCMFraudPreventionValuesForTesting(String&& unlinkableToken, String&& secretToken, String&& signature, String&& keyID);
     void firePrivateClickMeasurementTimerImmediatelyForTesting();
     void allowTLSCertificateChainForLocalPCMTesting(const WebCore::CertificateInfo&);
+    void setPrivateClickMeasurementAppBundleIDForTesting(String&&);
 
     void addKeptAliveLoad(Ref<NetworkResourceLoader>&&);
     void removeKeptAliveLoad(NetworkResourceLoader&);

Modified: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDatabase.cpp (283315 => 283316)


--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDatabase.cpp	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDatabase.cpp	2021-09-30 16:22:01 UTC (rev 283316)
@@ -43,9 +43,9 @@
     "sourceID, timeOfAdClick, token, signature, keyID, sourceApplicationBundleID) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"_s;
 constexpr auto insertAttributedPrivateClickMeasurementQuery = "INSERT OR REPLACE INTO AttributedPrivateClickMeasurement (sourceSiteDomainID, destinationSiteDomainID, "
     "sourceID, attributionTriggerData, priority, timeOfAdClick, earliestTimeToSendToSource, token, signature, keyID, earliestTimeToSendToDestination, sourceApplicationBundleID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"_s;
-constexpr auto findUnattributedQuery = "SELECT * FROM UnattributedPrivateClickMeasurement WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ?"_s;
-constexpr auto findAttributedQuery = "SELECT * FROM AttributedPrivateClickMeasurement WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ?"_s;
-constexpr auto removeUnattributedQuery = "DELETE FROM UnattributedPrivateClickMeasurement WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ?"_s;
+constexpr auto findUnattributedQuery = "SELECT * FROM UnattributedPrivateClickMeasurement WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ? AND sourceApplicationBundleID = ?"_s;
+constexpr auto findAttributedQuery = "SELECT * FROM AttributedPrivateClickMeasurement WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ? AND sourceApplicationBundleID = ?"_s;
+constexpr auto removeUnattributedQuery = "DELETE FROM UnattributedPrivateClickMeasurement WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ? AND sourceApplicationBundleID = ?"_s;
 constexpr auto allAttributedPrivateClickMeasurementQuery = "SELECT *, MIN(earliestTimeToSendToSource, earliestTimeToSendToDestination) as minVal "
     "FROM AttributedPrivateClickMeasurement WHERE earliestTimeToSendToSource IS NOT NULL AND earliestTimeToSendToDestination IS NOT NULL "
     "UNION ALL SELECT *, earliestTimeToSendToSource as minVal FROM AttributedPrivateClickMeasurement WHERE earliestTimeToSendToDestination IS NULL "
@@ -52,9 +52,9 @@
     "UNION ALL SELECT *, earliestTimeToSendToDestination as minVal FROM AttributedPrivateClickMeasurement WHERE earliestTimeToSendToSource IS NULL ORDER BY minVal"_s;
 constexpr auto allUnattributedPrivateClickMeasurementAttributionsQuery = "SELECT * FROM UnattributedPrivateClickMeasurement"_s;
 constexpr auto clearExpiredPrivateClickMeasurementQuery = "DELETE FROM UnattributedPrivateClickMeasurement WHERE ? > timeOfAdClick"_s;
-constexpr auto markReportAsSentToSourceQuery = "UPDATE AttributedPrivateClickMeasurement SET earliestTimeToSendToSource = null WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ?"_s;
-constexpr auto markReportAsSentToDestinationQuery = "UPDATE AttributedPrivateClickMeasurement SET earliestTimeToSendToDestination = null WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ?"_s;
-constexpr auto earliestTimesToSendQuery = "SELECT earliestTimeToSendToSource, earliestTimeToSendToDestination FROM AttributedPrivateClickMeasurement WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ?"_s;
+constexpr auto markReportAsSentToSourceQuery = "UPDATE AttributedPrivateClickMeasurement SET earliestTimeToSendToSource = null WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ? AND sourceApplicationBundleID = ?"_s;
+constexpr auto markReportAsSentToDestinationQuery = "UPDATE AttributedPrivateClickMeasurement SET earliestTimeToSendToDestination = null WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ? AND sourceApplicationBundleID = ?"_s;
+constexpr auto earliestTimesToSendQuery = "SELECT earliestTimeToSendToSource, earliestTimeToSendToDestination FROM AttributedPrivateClickMeasurement WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ? AND sourceApplicationBundleID = ?"_s;
 constexpr auto domainIDFromStringQuery = "SELECT domainID FROM PCMObservedDomains WHERE registrableDomain = ?"_s;
 constexpr auto domainStringFromDomainIDQuery = "SELECT registrableDomain FROM PCMObservedDomains WHERE domainID = ?"_s;
 constexpr auto createUnattributedPrivateClickMeasurement = "CREATE TABLE UnattributedPrivateClickMeasurement ("
@@ -237,7 +237,7 @@
     }
 }
 
-std::pair<std::optional<Database::UnattributedPrivateClickMeasurement>, std::optional<Database::AttributedPrivateClickMeasurement>> Database::findPrivateClickMeasurement(const WebCore::PrivateClickMeasurement::SourceSite& sourceSite, const WebCore::PrivateClickMeasurement::AttributionDestinationSite& destinationSite)
+std::pair<std::optional<Database::UnattributedPrivateClickMeasurement>, std::optional<Database::AttributedPrivateClickMeasurement>> Database::findPrivateClickMeasurement(const WebCore::PrivateClickMeasurement::SourceSite& sourceSite, const WebCore::PrivateClickMeasurement::AttributionDestinationSite& destinationSite, const ApplicationBundleIdentifier& applicationBundleIdentifier)
 {
     ASSERT(!RunLoop::isMain());
     auto sourceSiteDomainID = domainID(sourceSite.registrableDomain);
@@ -248,7 +248,8 @@
     auto findUnattributedScopedStatement = this->scopedStatement(m_findUnattributedStatement, findUnattributedQuery, "findPrivateClickMeasurement"_s);
     if (!findUnattributedScopedStatement
         || findUnattributedScopedStatement->bindInt(1, *sourceSiteDomainID) != SQLITE_OK
-        || findUnattributedScopedStatement->bindInt(2, *destinationSiteDomainID) != SQLITE_OK) {
+        || findUnattributedScopedStatement->bindInt(2, *destinationSiteDomainID) != SQLITE_OK
+        || findUnattributedScopedStatement->bindText(3, applicationBundleIdentifier) != SQLITE_OK) {
         RELEASE_LOG_ERROR(PrivateClickMeasurement, "%p - Database::findPrivateClickMeasurement findUnattributedQuery, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
         ASSERT_NOT_REACHED();
     }
@@ -256,7 +257,8 @@
     auto findAttributedScopedStatement = this->scopedStatement(m_findAttributedStatement, findAttributedQuery, "findPrivateClickMeasurement"_s);
     if (!findAttributedScopedStatement
         || findAttributedScopedStatement->bindInt(1, *sourceSiteDomainID) != SQLITE_OK
-        || findAttributedScopedStatement->bindInt(2, *destinationSiteDomainID) != SQLITE_OK) {
+        || findAttributedScopedStatement->bindInt(2, *destinationSiteDomainID) != SQLITE_OK
+        || findAttributedScopedStatement->bindText(3, applicationBundleIdentifier) != SQLITE_OK) {
         RELEASE_LOG_ERROR(PrivateClickMeasurement, "%p - Database::findPrivateClickMeasurement findAttributedQuery, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
         ASSERT_NOT_REACHED();
     }
@@ -272,7 +274,7 @@
     return std::make_pair(unattributedPrivateClickMeasurement, attributedPrivateClickMeasurement);
 }
 
-std::pair<std::optional<WebCore::PrivateClickMeasurement::AttributionSecondsUntilSendData>, DebugInfo> Database::attributePrivateClickMeasurement(const WebCore::PrivateClickMeasurement::SourceSite& sourceSite, const WebCore::PrivateClickMeasurement::AttributionDestinationSite& destinationSite, WebCore::PrivateClickMeasurement::AttributionTriggerData&& attributionTriggerData)
+std::pair<std::optional<WebCore::PrivateClickMeasurement::AttributionSecondsUntilSendData>, DebugInfo> Database::attributePrivateClickMeasurement(const WebCore::PrivateClickMeasurement::SourceSite& sourceSite, const WebCore::PrivateClickMeasurement::AttributionDestinationSite& destinationSite, const ApplicationBundleIdentifier& applicationBundleIdentifier, WebCore::PrivateClickMeasurement::AttributionTriggerData&& attributionTriggerData)
 {
     ASSERT(!RunLoop::isMain());
 
@@ -291,7 +293,7 @@
 
     WebCore::PrivateClickMeasurement::AttributionSecondsUntilSendData secondsUntilSend { std::nullopt, std::nullopt };
 
-    auto attribution = findPrivateClickMeasurement(sourceSite, destinationSite);
+    auto attribution = findPrivateClickMeasurement(sourceSite, destinationSite, applicationBundleIdentifier);
     auto& previouslyUnattributed = attribution.first;
     auto& previouslyAttributed = attribution.second;
 
@@ -350,6 +352,7 @@
     if (!scopedStatement
         || scopedStatement->bindInt(1, *sourceSiteDomainID) != SQLITE_OK
         || scopedStatement->bindInt(2, *destinationSiteDomainID) != SQLITE_OK
+        || scopedStatement->bindText(3, attribution.sourceApplicationBundleID()) != SQLITE_OK
         || scopedStatement->step() != SQLITE_DONE) {
         RELEASE_LOG_ERROR(PrivateClickMeasurement, "%p - Database::removeUnattributed, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
         ASSERT_NOT_REACHED();
@@ -522,6 +525,7 @@
 
     auto sourceSiteDomainID = domainID(attribution.sourceSite().registrableDomain);
     auto destinationSiteDomainID = domainID(attribution.destinationSite().registrableDomain);
+    auto sourceApplicationBundleID = attribution.sourceApplicationBundleID();
 
     if (!sourceSiteDomainID || !destinationSiteDomainID)
         return;
@@ -532,7 +536,7 @@
             ASSERT_NOT_REACHED();
             return;
         }
-        markReportAsSentToSource(*sourceSiteDomainID, *destinationSiteDomainID);
+        markReportAsSentToSource(*sourceSiteDomainID, *destinationSiteDomainID, sourceApplicationBundleID);
         sourceEarliestTimeToSend = std::nullopt;
         break;
     case WebCore::PrivateClickMeasurement::AttributionReportEndpoint::Destination:
@@ -540,7 +544,7 @@
             ASSERT_NOT_REACHED();
             return;
         }
-        markReportAsSentToDestination(*sourceSiteDomainID, *destinationSiteDomainID);
+        markReportAsSentToDestination(*sourceSiteDomainID, *destinationSiteDomainID, sourceApplicationBundleID);
         destinationEarliestTimeToSend = std::nullopt;
     }
 
@@ -548,10 +552,11 @@
     if (destinationEarliestTimeToSend || sourceEarliestTimeToSend)
         return;
 
-    auto clearAttributedStatement = m_database.prepareStatement("DELETE FROM AttributedPrivateClickMeasurement WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ?"_s);
+    auto clearAttributedStatement = m_database.prepareStatement("DELETE FROM AttributedPrivateClickMeasurement WHERE sourceSiteDomainID = ? AND destinationSiteDomainID = ? AND sourceApplicationBundleID = ?"_s);
     if (!clearAttributedStatement
         || clearAttributedStatement->bindInt(1, *sourceSiteDomainID) != SQLITE_OK
         || clearAttributedStatement->bindInt(2, *destinationSiteDomainID) != SQLITE_OK
+        || clearAttributedStatement->bindText(3, sourceApplicationBundleID) != SQLITE_OK
         || clearAttributedStatement->step() != SQLITE_DONE) {
         RELEASE_LOG_ERROR(PrivateClickMeasurement, "%p - Database::clearSentAttribution failed to step, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
         ASSERT_NOT_REACHED();
@@ -558,7 +563,7 @@
     }
 }
 
-void Database::markReportAsSentToDestination(SourceDomainID sourceSiteDomainID, DestinationDomainID destinationSiteDomainID)
+void Database::markReportAsSentToDestination(SourceDomainID sourceSiteDomainID, DestinationDomainID destinationSiteDomainID, const ApplicationBundleIdentifier& sourceApplicationBundleID)
 {
     ASSERT(!RunLoop::isMain());
     auto scopedStatement = this->scopedStatement(m_markReportAsSentToDestinationStatement, markReportAsSentToDestinationQuery, "markReportAsSentToDestination"_s);
@@ -566,6 +571,7 @@
     if (!scopedStatement
         || scopedStatement->bindInt(1, sourceSiteDomainID) != SQLITE_OK
         || scopedStatement->bindInt(2, destinationSiteDomainID) != SQLITE_OK
+        || scopedStatement->bindText(3, sourceApplicationBundleID) != SQLITE_OK
         || scopedStatement->step() != SQLITE_DONE) {
         RELEASE_LOG_ERROR(PrivateClickMeasurement, "Database::markReportAsSentToDestination, error message: %" PUBLIC_LOG_STRING, m_database.lastErrorMsg());
         ASSERT_NOT_REACHED();
@@ -572,7 +578,7 @@
     }
 }
 
-void Database::markReportAsSentToSource(SourceDomainID sourceSiteDomainID, DestinationDomainID destinationSiteDomainID)
+void Database::markReportAsSentToSource(SourceDomainID sourceSiteDomainID, DestinationDomainID destinationSiteDomainID, const ApplicationBundleIdentifier& sourceApplicationBundleID)
 {
     ASSERT(!RunLoop::isMain());
     auto scopedStatement = this->scopedStatement(m_markReportAsSentToSourceStatement, markReportAsSentToSourceQuery, "markReportAsSentToSource"_s);
@@ -580,6 +586,7 @@
     if (!scopedStatement
         || scopedStatement->bindInt(1, sourceSiteDomainID) != SQLITE_OK
         || scopedStatement->bindInt(2, destinationSiteDomainID) != SQLITE_OK
+        || scopedStatement->bindText(3, sourceApplicationBundleID) != SQLITE_OK
         || scopedStatement->step() != SQLITE_DONE) {
         RELEASE_LOG_ERROR(PrivateClickMeasurement, "Database::markReportAsSentToSource, error message: %" PUBLIC_LOG_STRING, m_database.lastErrorMsg());
         ASSERT_NOT_REACHED();
@@ -600,6 +607,7 @@
     if (!scopedStatement
         || scopedStatement->bindInt(1, *sourceSiteDomainID) != SQLITE_OK
         || scopedStatement->bindInt(2, *destinationSiteDomainID) != SQLITE_OK
+        || scopedStatement->bindText(3, attribution.sourceApplicationBundleID()) != SQLITE_OK
         || scopedStatement->step() != SQLITE_ROW) {
         RELEASE_LOG_ERROR(PrivateClickMeasurement, "Database::earliestTimesToSend, error message: %" PUBLIC_LOG_STRING, m_database.lastErrorMsg());
         ASSERT_NOT_REACHED();

Modified: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDatabase.h (283315 => 283316)


--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDatabase.h	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDatabase.h	2021-09-30 16:22:01 UTC (rev 283316)
@@ -42,10 +42,12 @@
     Database(const String& storageDirectory);
     virtual ~Database();
     
+    using ApplicationBundleIdentifier = String;
+
     static void interruptAllDatabases();
 
     void insertPrivateClickMeasurement(WebCore::PrivateClickMeasurement&&, PrivateClickMeasurementAttributionType);
-    std::pair<std::optional<WebCore::PrivateClickMeasurement::AttributionSecondsUntilSendData>, DebugInfo> attributePrivateClickMeasurement(const WebCore::PrivateClickMeasurement::SourceSite&, const WebCore::PrivateClickMeasurement::AttributionDestinationSite&, WebCore::PrivateClickMeasurement::AttributionTriggerData&&);
+    std::pair<std::optional<WebCore::PrivateClickMeasurement::AttributionSecondsUntilSendData>, DebugInfo> attributePrivateClickMeasurement(const WebCore::PrivateClickMeasurement::SourceSite&, const WebCore::PrivateClickMeasurement::AttributionDestinationSite&, const ApplicationBundleIdentifier&, WebCore::PrivateClickMeasurement::AttributionTriggerData&&);
     Vector<WebCore::PrivateClickMeasurement> allAttributedPrivateClickMeasurement();
     void clearPrivateClickMeasurement(std::optional<WebCore::RegistrableDomain>);
     void clearExpiredPrivateClickMeasurement();
@@ -66,11 +68,11 @@
 
     bool createSchema() final;
     void destroyStatements() final;
-    std::pair<std::optional<UnattributedPrivateClickMeasurement>, std::optional<AttributedPrivateClickMeasurement>> findPrivateClickMeasurement(const WebCore::PrivateClickMeasurement::SourceSite&, const WebCore::PrivateClickMeasurement::AttributionDestinationSite&);
+    std::pair<std::optional<UnattributedPrivateClickMeasurement>, std::optional<AttributedPrivateClickMeasurement>> findPrivateClickMeasurement(const WebCore::PrivateClickMeasurement::SourceSite&, const WebCore::PrivateClickMeasurement::AttributionDestinationSite&, const ApplicationBundleIdentifier&);
     void removeUnattributed(WebCore::PrivateClickMeasurement&);
     String attributionToStringForTesting(const WebCore::PrivateClickMeasurement&) const;
-    void markReportAsSentToDestination(SourceDomainID, DestinationDomainID);
-    void markReportAsSentToSource(SourceDomainID, DestinationDomainID);
+    void markReportAsSentToDestination(SourceDomainID, DestinationDomainID, const ApplicationBundleIdentifier&);
+    void markReportAsSentToSource(SourceDomainID, DestinationDomainID, const ApplicationBundleIdentifier&);
     std::pair<std::optional<SourceEarliestTimeToSend>, std::optional<DestinationEarliestTimeToSend>> earliestTimesToSend(const WebCore::PrivateClickMeasurement&);
     std::optional<DomainID> ensureDomainID(const WebCore::RegistrableDomain&);
     std::optional<DomainID> domainID(const WebCore::RegistrableDomain&);

Modified: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManager.cpp (283315 => 283316)


--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManager.cpp	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManager.cpp	2021-09-30 16:22:01 UTC (rev 283316)
@@ -77,6 +77,9 @@
 
     clearExpired();
 
+    if (m_privateClickMeasurementAppBundleIDForTesting)
+        measurement.setSourceApplicationBundleIDForTesting(*m_privateClickMeasurementAppBundleIDForTesting);
+
     if (measurement.ephemeralSourceNonce()) {
         auto measurementCopy = measurement;
         // This is guaranteed to be close in time to the navigational click which makes it likely to be personally identifiable.
@@ -230,7 +233,7 @@
     store().insertPrivateClickMeasurement(WTFMove(measurement), type);
 }
 
-void PrivateClickMeasurementManager::handleAttribution(AttributionTriggerData&& attributionTriggerData, const URL& requestURL, WebCore::RegistrableDomain&& redirectDomain, const URL& firstPartyURL)
+void PrivateClickMeasurementManager::handleAttribution(AttributionTriggerData&& attributionTriggerData, const URL& requestURL, WebCore::RegistrableDomain&& redirectDomain, const URL& firstPartyURL, const ApplicationBundleIdentifier& applicationBundleIdentifier)
 {
     if (!featureEnabled())
         return;
@@ -247,7 +250,7 @@
 
     m_client->broadcastConsoleMessage(MessageLevel::Log, "[Private Click Measurement] Triggering event accepted."_s);
 
-    attribute(SourceSite { WTFMove(redirectDomain) }, AttributionDestinationSite { firstPartyURL }, WTFMove(attributionTriggerData));
+    attribute(SourceSite { WTFMove(redirectDomain) }, AttributionDestinationSite { firstPartyURL }, WTFMove(attributionTriggerData), m_privateClickMeasurementAppBundleIDForTesting ? *m_privateClickMeasurementAppBundleIDForTesting : applicationBundleIdentifier);
 }
 
 void PrivateClickMeasurementManager::startTimerImmediatelyForTesting()
@@ -255,12 +258,20 @@
     startTimer(0_s);
 }
 
+void PrivateClickMeasurementManager::setPrivateClickMeasurementAppBundleIDForTesting(ApplicationBundleIdentifier&& appBundleID)
+{
+    if (appBundleID.isEmpty())
+        m_privateClickMeasurementAppBundleIDForTesting = std::nullopt;
+    else
+        m_privateClickMeasurementAppBundleIDForTesting = WTFMove(appBundleID);
+}
+
 void PrivateClickMeasurementManager::startTimer(Seconds seconds)
 {
     m_firePendingAttributionRequestsTimer.startOneShot(m_isRunningTest ? 0_s : seconds);
 }
 
-void PrivateClickMeasurementManager::attribute(const SourceSite& sourceSite, const AttributionDestinationSite& destinationSite, AttributionTriggerData&& attributionTriggerData)
+void PrivateClickMeasurementManager::attribute(const SourceSite& sourceSite, const AttributionDestinationSite& destinationSite, AttributionTriggerData&& attributionTriggerData, const ApplicationBundleIdentifier& applicationBundleIdentifier)
 {
     if (!featureEnabled())
         return;
@@ -273,7 +284,7 @@
             return;
     }
         
-    store().attributePrivateClickMeasurement(sourceSite, destinationSite, WTFMove(attributionTriggerData), std::exchange(m_ephemeralMeasurement, std::nullopt), [this, weakThis = makeWeakPtr(*this)] (auto attributionSecondsUntilSendData, auto debugInfo) {
+    store().attributePrivateClickMeasurement(sourceSite, destinationSite, applicationBundleIdentifier, WTFMove(attributionTriggerData), std::exchange(m_ephemeralMeasurement, std::nullopt), [this, weakThis = makeWeakPtr(*this)] (auto attributionSecondsUntilSendData, auto debugInfo) {
         if (!weakThis)
             return;
         
@@ -436,6 +447,7 @@
     m_firePendingAttributionRequestsTimer.stop();
     m_ephemeralMeasurement = std::nullopt;
     m_isRunningEphemeralMeasurementTest = false;
+    m_privateClickMeasurementAppBundleIDForTesting = std::nullopt;
 
     if (!featureEnabled())
         return completionHandler();

Modified: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManager.h (283315 => 283316)


--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManager.h	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManager.h	2021-09-30 16:22:01 UTC (rev 283316)
@@ -45,8 +45,10 @@
     explicit PrivateClickMeasurementManager(UniqueRef<PCM::Client>&&, const String& storageDirectory);
     ~PrivateClickMeasurementManager();
 
+    using ApplicationBundleIdentifier = String;
+
     void storeUnattributed(PrivateClickMeasurement&&) final;
-    void handleAttribution(AttributionTriggerData&&, const URL& requestURL, WebCore::RegistrableDomain&& redirectDomain, const URL& firstPartyURL) final;
+    void handleAttribution(AttributionTriggerData&&, const URL& requestURL, WebCore::RegistrableDomain&& redirectDomain, const URL& firstPartyURL, const ApplicationBundleIdentifier&) final;
     void clear(CompletionHandler<void()>&&) final;
     void clearForRegistrableDomain(const RegistrableDomain&, CompletionHandler<void()>&&) final;
     void migratePrivateClickMeasurementFromLegacyStorage(PrivateClickMeasurement&&, PrivateClickMeasurementAttributionType) final;
@@ -61,6 +63,7 @@
     void setEphemeralMeasurementForTesting(bool value) final { m_isRunningEphemeralMeasurementTest = value; }
     void setPCMFraudPreventionValuesForTesting(String&& unlinkableToken, String&& secretToken, String&& signature, String&& keyID) final;
     void startTimerImmediatelyForTesting() final;
+    void setPrivateClickMeasurementAppBundleIDForTesting(ApplicationBundleIdentifier&&);
     void destroyStoreForTesting(CompletionHandler<void()>&&) final;
     void allowTLSCertificateChainForLocalPCMTesting(const WebCore::CertificateInfo&) final;
 
@@ -72,7 +75,7 @@
     void getSignedUnlinkableToken(PrivateClickMeasurement&&);
     void insertPrivateClickMeasurement(PrivateClickMeasurement&&, PrivateClickMeasurementAttributionType);
     void clearSentAttribution(PrivateClickMeasurement&&, PrivateClickMeasurement::AttributionReportEndpoint);
-    void attribute(const SourceSite&, const AttributionDestinationSite&, AttributionTriggerData&&);
+    void attribute(const SourceSite&, const AttributionDestinationSite&, AttributionTriggerData&&, const ApplicationBundleIdentifier&);
     void fireConversionRequest(const PrivateClickMeasurement&, PrivateClickMeasurement::AttributionReportEndpoint);
     void fireConversionRequestImpl(const PrivateClickMeasurement&, PrivateClickMeasurement::AttributionReportEndpoint);
     void firePendingAttributionRequests();
@@ -86,6 +89,7 @@
     bool m_isRunningEphemeralMeasurementTest { false };
     std::optional<URL> m_tokenPublicKeyURLForTesting;
     std::optional<URL> m_tokenSignatureURLForTesting;
+    std::optional<ApplicationBundleIdentifier> m_privateClickMeasurementAppBundleIDForTesting;
     mutable RefPtr<PCM::Store> m_store;
     String m_storageDirectory;
     UniqueRef<PCM::Client> m_client;

Modified: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerInterface.cpp (283315 => 283316)


--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerInterface.cpp	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerInterface.cpp	2021-09-30 16:22:01 UTC (rev 283316)
@@ -51,7 +51,7 @@
 END
 
 FUNCTION(handleAttribution)
-ARGUMENTS(PrivateClickMeasurementManager::AttributionTriggerData, URL, WebCore::RegistrableDomain, URL)
+ARGUMENTS(PrivateClickMeasurementManager::AttributionTriggerData, URL, WebCore::RegistrableDomain, URL, String)
 END
 
 FUNCTION(clear)
@@ -110,6 +110,10 @@
 ARGUMENTS()
 END
 
+FUNCTION(setPrivateClickMeasurementAppBundleIDForTesting)
+ARGUMENTS(String)
+END
+
 FUNCTION(destroyStoreForTesting)
 ARGUMENTS()
 REPLY()
@@ -154,6 +158,7 @@
     case MessageType::SetEphemeralMeasurementForTesting:
     case MessageType::SetPCMFraudPreventionValuesForTesting:
     case MessageType::StartTimerImmediatelyForTesting:
+    case MessageType::SetPrivateClickMeasurementAppBundleIDForTesting:
     case MessageType::AllowTLSCertificateChainForLocalPCMTesting:
         return false;
     case MessageType::MarkAttributedPrivateClickMeasurementsAsExpiredForTesting:
@@ -264,6 +269,9 @@
     case PCM::MessageType::StartTimerImmediatelyForTesting:
         handlePCMMessage<MessageInfo::startTimerImmediatelyForTesting>(WTFMove(encodedMessage));
         break;
+    case PCM::MessageType::SetPrivateClickMeasurementAppBundleIDForTesting:
+        handlePCMMessage<MessageInfo::setPrivateClickMeasurementAppBundleIDForTesting>(WTFMove(encodedMessage));
+        break;
     case PCM::MessageType::DestroyStoreForTesting:
         handlePCMMessageWithReply<MessageInfo::destroyStoreForTesting>(WTFMove(encodedMessage), WTFMove(replySender));
         break;

Modified: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerInterface.h (283315 => 283316)


--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerInterface.h	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerInterface.h	2021-09-30 16:22:01 UTC (rev 283316)
@@ -50,9 +50,10 @@
     using PrivateClickMeasurement = WebCore::PrivateClickMeasurement;
     using RegistrableDomain = WebCore::RegistrableDomain;
     using SourceSite = WebCore::PrivateClickMeasurement::SourceSite;
+    using ApplicationBundleIdentifier = String;
 
     virtual void storeUnattributed(PrivateClickMeasurement&&) = 0;
-    virtual void handleAttribution(AttributionTriggerData&&, const URL& requestURL, WebCore::RegistrableDomain&& redirectDomain, const URL& firstPartyURL) = 0;
+    virtual void handleAttribution(AttributionTriggerData&&, const URL& requestURL, WebCore::RegistrableDomain&& redirectDomain, const URL& firstPartyURL, const ApplicationBundleIdentifier&) = 0;
     virtual void clear(CompletionHandler<void()>&&) = 0;
     virtual void clearForRegistrableDomain(const RegistrableDomain&, CompletionHandler<void()>&&) = 0;
     virtual void migratePrivateClickMeasurementFromLegacyStorage(PrivateClickMeasurement&&, PrivateClickMeasurementAttributionType) = 0;
@@ -67,6 +68,7 @@
     virtual void setEphemeralMeasurementForTesting(bool) = 0;
     virtual void setPCMFraudPreventionValuesForTesting(String&& unlinkableToken, String&& secretToken, String&& signature, String&& keyID) = 0;
     virtual void startTimerImmediatelyForTesting() = 0;
+    virtual void setPrivateClickMeasurementAppBundleIDForTesting(ApplicationBundleIdentifier&&) = 0;
     virtual void destroyStoreForTesting(CompletionHandler<void()>&&) = 0;
     virtual void allowTLSCertificateChainForLocalPCMTesting(const WebCore::CertificateInfo&) = 0;
 };
@@ -91,6 +93,7 @@
     SetEphemeralMeasurementForTesting,
     SetPCMFraudPreventionValuesForTesting,
     StartTimerImmediatelyForTesting,
+    SetPrivateClickMeasurementAppBundleIDForTesting,
     DestroyStoreForTesting,
     AllowTLSCertificateChainForLocalPCMTesting
 };
@@ -127,6 +130,7 @@
         WebKit::PCM::MessageType::SetEphemeralMeasurementForTesting,
         WebKit::PCM::MessageType::SetPCMFraudPreventionValuesForTesting,
         WebKit::PCM::MessageType::StartTimerImmediatelyForTesting,
+        WebKit::PCM::MessageType::SetPrivateClickMeasurementAppBundleIDForTesting,
         WebKit::PCM::MessageType::DestroyStoreForTesting,
         WebKit::PCM::MessageType::AllowTLSCertificateChainForLocalPCMTesting
     >;

Modified: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerProxy.cpp (283315 => 283316)


--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerProxy.cpp	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerProxy.cpp	2021-09-30 16:22:01 UTC (rev 283316)
@@ -80,9 +80,9 @@
     sendMessage<MessageType::StoreUnattributed>(pcm);
 }
 
-void ManagerProxy::handleAttribution(WebCore::PrivateClickMeasurement::AttributionTriggerData&& triggerData, const URL& requestURL, WebCore::RegistrableDomain&& redirectDomain, const URL& firstPartyURL)
+void ManagerProxy::handleAttribution(WebCore::PrivateClickMeasurement::AttributionTriggerData&& triggerData, const URL& requestURL, WebCore::RegistrableDomain&& redirectDomain, const URL& firstPartyURL, const ApplicationBundleIdentifier& applicationBundleIdentifier)
 {
-    sendMessage<MessageType::HandleAttribution>(triggerData, requestURL, redirectDomain, firstPartyURL);
+    sendMessage<MessageType::HandleAttribution>(triggerData, requestURL, redirectDomain, firstPartyURL, applicationBundleIdentifier);
 }
 
 void ManagerProxy::clear(CompletionHandler<void()>&& completionHandler)
@@ -150,6 +150,11 @@
     sendMessage<MessageType::StartTimerImmediatelyForTesting>();
 }
 
+void ManagerProxy::setPrivateClickMeasurementAppBundleIDForTesting(ApplicationBundleIdentifier&& appBundleID)
+{
+    sendMessage<MessageType::SetPrivateClickMeasurementAppBundleIDForTesting>(appBundleID);
+}
+
 void ManagerProxy::destroyStoreForTesting(CompletionHandler<void()>&& completionHandler)
 {
     sendMessageWithReply<MessageType::DestroyStoreForTesting>(WTFMove(completionHandler));

Modified: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerProxy.h (283315 => 283316)


--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerProxy.h	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerProxy.h	2021-09-30 16:22:01 UTC (rev 283316)
@@ -39,8 +39,10 @@
 public:
     ManagerProxy(const String& machServiceName);
 
+    using ApplicationBundleIdentifier = String;
+
     void storeUnattributed(WebCore::PrivateClickMeasurement&&) final;
-    void handleAttribution(WebCore::PrivateClickMeasurement::AttributionTriggerData&&, const URL& requestURL, WebCore::RegistrableDomain&& redirectDomain, const URL& firstPartyURL) final;
+    void handleAttribution(WebCore::PrivateClickMeasurement::AttributionTriggerData&&, const URL& requestURL, WebCore::RegistrableDomain&& redirectDomain, const URL& firstPartyURL, const ApplicationBundleIdentifier&) final;
     void clear(CompletionHandler<void()>&&) final;
     void clearForRegistrableDomain(const WebCore::RegistrableDomain&, CompletionHandler<void()>&&) final;
     void migratePrivateClickMeasurementFromLegacyStorage(WebCore::PrivateClickMeasurement&&, PrivateClickMeasurementAttributionType) final;
@@ -55,6 +57,7 @@
     void setEphemeralMeasurementForTesting(bool) final;
     void setPCMFraudPreventionValuesForTesting(String&& unlinkableToken, String&& secretToken, String&& signature, String&& keyID) final;
     void startTimerImmediatelyForTesting() final;
+    void setPrivateClickMeasurementAppBundleIDForTesting(ApplicationBundleIdentifier&&) final;
     void destroyStoreForTesting(CompletionHandler<void()>&&) final;
     void allowTLSCertificateChainForLocalPCMTesting(const WebCore::CertificateInfo&) final;
 

Modified: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementStore.cpp (283315 => 283316)


--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementStore.cpp	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementStore.cpp	2021-09-30 16:22:01 UTC (rev 283316)
@@ -95,9 +95,9 @@
     });
 }
 
-void Store::attributePrivateClickMeasurement(const WebCore::PrivateClickMeasurement::SourceSite& sourceSite, const WebCore::PrivateClickMeasurement::AttributionDestinationSite& destinationSite, WebCore::PrivateClickMeasurement::AttributionTriggerData&& attributionTriggerData, std::optional<WebCore::PrivateClickMeasurement>&& ephemeralMeasurement, CompletionHandler<void(std::optional<WebCore::PrivateClickMeasurement::AttributionSecondsUntilSendData>&&, DebugInfo&&)>&& completionHandler)
+void Store::attributePrivateClickMeasurement(const WebCore::PrivateClickMeasurement::SourceSite& sourceSite, const WebCore::PrivateClickMeasurement::AttributionDestinationSite& destinationSite, const ApplicationBundleIdentifier& applicationBundleIdentifier, WebCore::PrivateClickMeasurement::AttributionTriggerData&& attributionTriggerData, std::optional<WebCore::PrivateClickMeasurement>&& ephemeralMeasurement, CompletionHandler<void(std::optional<WebCore::PrivateClickMeasurement::AttributionSecondsUntilSendData>&&, DebugInfo&&)>&& completionHandler)
 {
-    postTask([this, protectedThis = Ref { *this }, sourceSite = sourceSite.isolatedCopy(), destinationSite = destinationSite.isolatedCopy(), attributionTriggerData = WTFMove(attributionTriggerData), ephemeralMeasurement = crossThreadCopy(ephemeralMeasurement), completionHandler = WTFMove(completionHandler)] () mutable {
+    postTask([this, protectedThis = Ref { *this }, sourceSite = sourceSite.isolatedCopy(), destinationSite = destinationSite.isolatedCopy(), applicationBundleIdentifier = applicationBundleIdentifier.isolatedCopy(), attributionTriggerData = WTFMove(attributionTriggerData), ephemeralMeasurement = crossThreadCopy(ephemeralMeasurement), completionHandler = WTFMove(completionHandler)] () mutable {
         if (!m_database) {
             return postTaskReply([completionHandler = WTFMove(completionHandler)] () mutable {
                 completionHandler(std::nullopt, { });
@@ -110,7 +110,7 @@
             m_database->insertPrivateClickMeasurement(WTFMove(*ephemeralMeasurement), PrivateClickMeasurementAttributionType::Unattributed);
         }
 
-        auto [seconds, debugInfo] = m_database->attributePrivateClickMeasurement(sourceSite, destinationSite, WTFMove(attributionTriggerData));
+        auto [seconds, debugInfo] = m_database->attributePrivateClickMeasurement(sourceSite, destinationSite, applicationBundleIdentifier, WTFMove(attributionTriggerData));
 
         postTaskReply([seconds = WTFMove(seconds), debugInfo = debugInfo.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
             completionHandler(WTFMove(seconds), WTFMove(debugInfo));

Modified: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementStore.h (283315 => 283316)


--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementStore.h	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementStore.h	2021-09-30 16:22:01 UTC (rev 283316)
@@ -47,11 +47,13 @@
 
     ~Store();
 
+    using ApplicationBundleIdentifier = String;
+
     static void prepareForProcessToSuspend(CompletionHandler<void()>&&);
     static void processDidResume();
 
     void insertPrivateClickMeasurement(WebCore::PrivateClickMeasurement&&, WebKit::PrivateClickMeasurementAttributionType);
-    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>&&, DebugInfo&&)>&&);
+    void attributePrivateClickMeasurement(const WebCore::PrivateClickMeasurement::SourceSite&, const WebCore::PrivateClickMeasurement::AttributionDestinationSite&, const ApplicationBundleIdentifier&, WebCore::PrivateClickMeasurement::AttributionTriggerData&&, std::optional<WebCore::PrivateClickMeasurement>&& ephemeralMeasurement, CompletionHandler<void(std::optional<WebCore::PrivateClickMeasurement::AttributionSecondsUntilSendData>&&, DebugInfo&&)>&&);
 
     void privateClickMeasurementToStringForTesting(CompletionHandler<void(String)>&&) const;
     void markAllUnattributedPrivateClickMeasurementAsExpiredForTesting();

Modified: trunk/Source/WebKit/UIProcess/API/C/WKPage.cpp (283315 => 283316)


--- trunk/Source/WebKit/UIProcess/API/C/WKPage.cpp	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/UIProcess/API/C/WKPage.cpp	2021-09-30 16:22:01 UTC (rev 283316)
@@ -3138,6 +3138,14 @@
     });
 }
 
+void WKPageSetPrivateClickMeasurementAppBundleIDForTesting(WKPageRef pageRef, WKStringRef appBundleIDForTesting, WKPageSetPrivateClickMeasurementAppBundleIDForTestingFunction callback, void* callbackContext)
+{
+    CRASH_IF_SUSPENDED;
+    toImpl(pageRef)->setPrivateClickMeasurementAppBundleIDForTesting(toWTFString(appBundleIDForTesting), [callbackContext, callback] () {
+        callback(callbackContext);
+    });
+}
+
 void WKPageSetMockCameraOrientation(WKPageRef pageRef, uint64_t orientation)
 {
     CRASH_IF_SUSPENDED;

Modified: trunk/Source/WebKit/UIProcess/API/C/WKPagePrivate.h (283315 => 283316)


--- trunk/Source/WebKit/UIProcess/API/C/WKPagePrivate.h	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/UIProcess/API/C/WKPagePrivate.h	2021-09-30 16:22:01 UTC (rev 283316)
@@ -192,6 +192,8 @@
 WK_EXPORT void WKPageMarkPrivateClickMeasurementsAsExpiredForTesting(WKPageRef page, WKPageMarkPrivateClickMeasurementsAsExpiredForTestingFunction callback, void* callbackContext);
 typedef void (*WKPageSetPCMFraudPreventionValuesForTestingFunction)(void* functionContext);
 WK_EXPORT void WKPageSetPCMFraudPreventionValuesForTesting(WKPageRef page, WKStringRef secretToken, WKStringRef unlinkableToken, WKStringRef signature, WKStringRef keyID, WKPageSetPCMFraudPreventionValuesForTestingFunction callback, void* callbackContext);
+typedef void (*WKPageSetPrivateClickMeasurementAppBundleIDForTestingFunction)(void* functionContext);
+WK_EXPORT void WKPageSetPrivateClickMeasurementAppBundleIDForTesting(WKPageRef pageRef, WKStringRef appBundleIDForTesting, WKPageSetPrivateClickMeasurementAppBundleIDForTestingFunction callback, void* callbackContext);
 
 WK_EXPORT void WKPageSetMockCameraOrientation(WKPageRef page, uint64_t orientation);
 WK_EXPORT bool WKPageIsMockRealtimeMediaSourceCenterEnabled(WKPageRef page);

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h (283315 => 283316)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h	2021-09-30 16:22:01 UTC (rev 283316)
@@ -103,6 +103,7 @@
 - (void)_setPrivateClickMeasurementAttributionReportURLsForTesting:(NSURL *)sourceURL destinationURL:(NSURL *)destinationURL completionHandler:(void(^)(void))completionHandler WK_API_AVAILABLE(macos(12.0), ios(15.0));
 - (void)_setPrivateClickMeasurementAttributionTokenPublicKeyURLForTesting:(NSURL *)url completionHandler:(void(^)(void))completionHandler WK_API_AVAILABLE(macos(12.0), ios(15.0));
 - (void)_setPrivateClickMeasurementAttributionTokenSignatureURLForTesting:(NSURL *)url completionHandler:(void(^)(void))completionHandler WK_API_AVAILABLE(macos(12.0), ios(15.0));
+- (void)_setPrivateClickMeasurementAppBundleIDForTesting:(NSString *)appBundleID completionHandler:(void(^)(void))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 - (void)_dumpPrivateClickMeasurement:(void(^)(NSString *))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 
 - (void)_lastNavigationWasAppInitiated:(void(^)(BOOL))completionHandler;

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm (283315 => 283316)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm	2021-09-30 16:22:01 UTC (rev 283316)
@@ -354,6 +354,13 @@
     });
 }
 
+- (void)_setPrivateClickMeasurementAppBundleIDForTesting:(NSString *)appBundleID completionHandler:(void(^)(void))completionHandler
+{
+    _page->setPrivateClickMeasurementAppBundleIDForTesting(appBundleID, [completionHandler = makeBlockPtr(completionHandler)] {
+        completionHandler();
+    });
+}
+
 - (void)_dumpPrivateClickMeasurement:(void(^)(NSString *))completionHandler
 {
     _page->dumpPrivateClickMeasurement([completionHandler = makeBlockPtr(completionHandler)](const String& privateClickMeasurement) {

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (283315 => 283316)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2021-09-30 16:22:01 UTC (rev 283316)
@@ -10513,6 +10513,11 @@
     websiteDataStore().networkProcess().sendWithAsyncReply(Messages::NetworkProcess::SetPCMFraudPreventionValuesForTesting(m_websiteDataStore->sessionID(), unlinkableToken, secretToken, signature, keyID), WTFMove(completionHandler));
 }
 
+void WebPageProxy::setPrivateClickMeasurementAppBundleIDForTesting(const String& appBundleIDForTesting, CompletionHandler<void()>&& completionHandler)
+{
+    websiteDataStore().networkProcess().sendWithAsyncReply(Messages::NetworkProcess::SetPrivateClickMeasurementAppBundleIDForTesting(m_websiteDataStore->sessionID(), appBundleIDForTesting), WTFMove(completionHandler));
+}
+
 #if ENABLE(SPEECH_SYNTHESIS)
 
 void WebPageProxy::resetSpeechSynthesizer()

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (283315 => 283316)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2021-09-30 16:22:01 UTC (rev 283316)
@@ -1777,6 +1777,7 @@
     void setPrivateClickMeasurementAttributionReportURLsForTesting(const URL& sourceURL, const URL& destinationURL, CompletionHandler<void()>&&);
     void markPrivateClickMeasurementsAsExpiredForTesting(CompletionHandler<void()>&&);
     void setPCMFraudPreventionValuesForTesting(const String& unlinkableToken, const String& secretToken, const String& signature, const String& keyID, CompletionHandler<void()>&&);
+    void setPrivateClickMeasurementAppBundleIDForTesting(const String& appBundleIDForTesting, CompletionHandler<void()>&&);
 
 #if ENABLE(SPEECH_SYNTHESIS)
     void speechSynthesisVoiceList(CompletionHandler<void(Vector<WebSpeechSynthesisVoice>&&)>&&);

Modified: trunk/Tools/ChangeLog (283315 => 283316)


--- trunk/Tools/ChangeLog	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Tools/ChangeLog	2021-09-30 16:22:01 UTC (rev 283316)
@@ -1,3 +1,32 @@
+2021-09-30  John Wilander  <wilan...@apple.com>
+
+        PCM: Take app bundle ID into consideration when matching triggering events with pending clicks
+        https://bugs.webkit.org/show_bug.cgi?id=230778
+        <rdar://problem/83516528>
+
+        Reviewed by Alex Christensen.
+
+        https://commits.webkit.org/r282884 added app bundle IDs to unattributed
+        and attributed clicks in PCM. This patch makes sure we take those IDs
+        into consideration in PCM::Database::attributePrivateClickMeasurement().
+
+        The TestRunner changes are all test infrastructure to enable different
+        app bundle IDs in the eyes of PCM. The API test changes are to make use
+        of the app bundle ID test infrastructure.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/EventAttribution.mm:
+        (TestWebKitAPI::runBasicEventAttributionTest):
+        (TestWebKitAPI::TEST):
+        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::setPrivateClickMeasurementAppBundleIDForTesting):
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::TestController::setPrivateClickMeasurementAppBundleIDForTesting):
+        * WebKitTestRunner/TestController.h:
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
+
 2021-09-30  Alex Christensen  <achristen...@webkit.org>
 
         Clean up PrivateClickMeasurement

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/EventAttribution.mm (283315 => 283316)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/EventAttribution.mm	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/EventAttribution.mm	2021-09-30 16:22:01 UTC (rev 283316)
@@ -153,8 +153,10 @@
     [[webView configuration].websiteDataStore _trustServerForLocalPCMTesting:secTrustFromCertificateChain(@[(id)testCertificate().get()]).get()];
     [webView _setPrivateClickMeasurementAttributionReportURLsForTesting:serverURL destinationURL:exampleURL() completionHandler:^{
         [webView _setPrivateClickMeasurementOverrideTimerForTesting:YES completionHandler:^{
-            NSString *html = [NSString stringWithFormat:@"<script>fetch('%@conversionRequestBeforeRedirect',{mode:'no-cors'})</script>", serverURL];
-            [webView loadHTMLString:html baseURL:exampleURL()];
+            [webView _setPrivateClickMeasurementAppBundleIDForTesting:@"test.bundle.id" completionHandler:^{
+                NSString *html = [NSString stringWithFormat:@"<script>fetch('%@conversionRequestBeforeRedirect',{mode:'no-cors'})</script>", serverURL];
+                [webView loadHTMLString:html baseURL:exampleURL()];
+            }];
         }];
     }];
     Util::run(&done);

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl (283315 => 283316)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl	2021-09-30 16:22:01 UTC (rev 283316)
@@ -416,6 +416,7 @@
     undefined setPrivateClickMeasurementAttributionReportURLsForTesting(DOMString sourceURLString, DOMString destinationURLString);
     undefined markPrivateClickMeasurementsAsExpiredForTesting();
     undefined setPrivateClickMeasurementFraudPreventionValuesForTesting(DOMString unlinkableToken, DOMString secretToken, DOMString signature, DOMString keyID);
+    undefined setPrivateClickMeasurementAppBundleIDForTesting(DOMString appBundleID);
 
     // SpeechRecognition
     undefined setIsSpeechRecognitionPermissionGranted(boolean value);

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp (283315 => 283316)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp	2021-09-30 16:22:01 UTC (rev 283316)
@@ -2114,6 +2114,12 @@
     }));
 }
 
+void TestRunner::setPrivateClickMeasurementAppBundleIDForTesting(JSStringRef appBundleID)
+{
+    postSynchronousPageMessage("SetPrivateClickMeasurementAppBundleIDForTesting",
+        toWK(appBundleID));
+}
+
 bool TestRunner::hasAppBoundSession()
 {
     return postSynchronousPageMessageReturningBoolean("HasAppBoundSession");

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h (283315 => 283316)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h	2021-09-30 16:22:01 UTC (rev 283316)
@@ -532,6 +532,7 @@
     void markAttributedPrivateClickMeasurementsAsExpiredForTesting();
     void setPrivateClickMeasurementEphemeralMeasurementForTesting(bool value);
     void setPrivateClickMeasurementFraudPreventionValuesForTesting(JSStringRef unlinkableToken, JSStringRef secretToken, JSStringRef signature, JSStringRef keyID);
+    void setPrivateClickMeasurementAppBundleIDForTesting(JSStringRef);
     void simulateResourceLoadStatisticsSessionRestart();
 
     void setIsSpeechRecognitionPermissionGranted(bool);

Modified: trunk/Tools/WebKitTestRunner/TestController.cpp (283315 => 283316)


--- trunk/Tools/WebKitTestRunner/TestController.cpp	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Tools/WebKitTestRunner/TestController.cpp	2021-09-30 16:22:01 UTC (rev 283316)
@@ -3749,6 +3749,13 @@
     runUntil(callbackContext.done, noTimeout);
 }
 
+void TestController::setPrivateClickMeasurementAppBundleIDForTesting(WKStringRef appBundleID)
+{
+    PrivateClickMeasurementVoidCallbackContext callbackContext(*this);
+    WKPageSetPrivateClickMeasurementAppBundleIDForTesting(m_mainWebView->page(), appBundleID, privateClickMeasurementVoidCallback, &callbackContext);
+    runUntil(callbackContext.done, noTimeout);
+}
+
 WKURLRef TestController::currentTestURL() const
 {
     return m_currentInvocation ? m_currentInvocation->url() : nullptr;

Modified: trunk/Tools/WebKitTestRunner/TestController.h (283315 => 283316)


--- trunk/Tools/WebKitTestRunner/TestController.h	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Tools/WebKitTestRunner/TestController.h	2021-09-30 16:22:01 UTC (rev 283316)
@@ -355,6 +355,7 @@
     void setPrivateClickMeasurementAttributionReportURLsForTesting(WKURLRef sourceURL, WKURLRef destinationURL);
     void markPrivateClickMeasurementsAsExpiredForTesting();
     void setPCMFraudPreventionValuesForTesting(WKStringRef unlinkableToken, WKStringRef secretToken, WKStringRef signature, WKStringRef keyID);
+    void setPrivateClickMeasurementAppBundleIDForTesting(WKStringRef);
 
     void didSetAppBoundDomains() const;
 

Modified: trunk/Tools/WebKitTestRunner/TestInvocation.cpp (283315 => 283316)


--- trunk/Tools/WebKitTestRunner/TestInvocation.cpp	2021-09-30 16:05:34 UTC (rev 283315)
+++ trunk/Tools/WebKitTestRunner/TestInvocation.cpp	2021-09-30 16:22:01 UTC (rev 283316)
@@ -1423,6 +1423,11 @@
         return nullptr;
     }
 
+    if (WKStringIsEqualToUTF8CString(messageName, "SetPrivateClickMeasurementAppBundleIDForTesting")) {
+        TestController::singleton().setPrivateClickMeasurementAppBundleIDForTesting(stringValue(messageBody));
+        return nullptr;
+    }
+
     if (WKStringIsEqualToUTF8CString(messageName, "SyncLocalStorage")) {
         TestController::singleton().syncLocalStorage();
         return nullptr;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to