Changeset 273209 in webkit


Ignore:
Timestamp:
Feb 20, 2021 3:17:32 PM (3 years ago)
Author:
jiewen_tan@apple.com
Message:

PCM: Store and report source unlinkable tokens
https://bugs.webkit.org/show_bug.cgi?id=222208
<rdar://problem/73582032>

Reviewed by John Wilander.

Source/WebCore:

This patch hooks up the network process with the PCM fraud prevention feature to
enable the generation, storing and reporting the source unlinkable token.

Existing tests updated.

  • loader/PrivateClickMeasurement.h:

(WebCore::PrivateClickMeasurement::setSourceSecretTokenValue):
Adds infrastructure to mock the crypto operations such that layout tests can be
conducted without the server side crypto support.

  • loader/PrivateClickMeasurement.cpp:

(WebCore::PrivateClickMeasurement::attributionReportJSON const):
(WebCore::PrivateClickMeasurement::tokenSignatureJSON const):
(WebCore::PrivateClickMeasurement::setSourceUnlinkableToken):
(WebCore::PrivateClickMeasurement::tokenSignatureJSON): Deleted.

  • loader/PrivateClickMeasurement.h:

(WebCore::PrivateClickMeasurement::sourceUnlinkableToken const):

  • loader/cocoa/PrivateClickMeasurementCocoa.mm:

(WebCore::PrivateClickMeasurement::calculateAndUpdateSourceSecretToken):
(WebCore::PrivateClickMeasurement::calculateAndUpdateSourceUnlinkableToken):
(WebCore::PrivateClickMeasurement::sourceSecretToken): Deleted.
(WebCore::PrivateClickMeasurement::calculateSourceUnlinkableToken): Deleted.
Update interfaces to service the use cases in the Networking process better.

Source/WebKit:

  • NetworkProcess/NetworkProcess.cpp:

(WebKit::NetworkProcess::setFraudPreventionValuesForTesting):

  • NetworkProcess/NetworkProcess.h:
  • NetworkProcess/NetworkProcess.messages.in:
  • NetworkProcess/NetworkSession.cpp:

(WebKit::NetworkSession::setFraudPreventionValuesForTesting):

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

(WebKit::PrivateClickMeasurementManager::storeUnattributed):
(WebKit::PrivateClickMeasurementManager::getSignedSecretToken):
(WebKit::PrivateClickMeasurementManager::setFraudPreventionValuesForTesting):

  • NetworkProcess/PrivateClickMeasurementManager.h:
  • UIProcess/API/C/WKPage.cpp:

(WKPageSetFraudPreventionValuesForTesting):

  • UIProcess/API/C/WKPagePrivate.h:
  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::markPrivateClickMeasurementsAsExpiredForTesting):
(WebKit::WebPageProxy::setFraudPreventionValuesForTesting):

  • UIProcess/WebPageProxy.h:

Adds infrastructure to mock the crypto operations such that layout tests can be
conducted without the server side crypto support.

  • NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp:

(WebKit::ResourceLoadStatisticsDatabaseStore::buildPrivateClickMeasurementFromDatabase):
(WebKit::ResourceLoadStatisticsDatabaseStore::insertPrivateClickMeasurement):

  • NetworkProcess/PrivateClickMeasurementManager.cpp:

(WebKit::PrivateClickMeasurementManager::storeUnattributed):
(WebKit::PrivateClickMeasurementManager::getTokenPublicKey):
(WebKit::PrivateClickMeasurementManager::getSignedSecretToken):
(WebKit::PrivateClickMeasurementManager::fireConversionRequest):
(WebKit::PrivateClickMeasurementManager::fireConversionRequestImpl):

  • NetworkProcess/PrivateClickMeasurementManager.h:

Connects the fraud prevention feature in PCM to generate, store, and report the unlinkable token.

Tools:

  • TestWebKitAPI/Tests/WebCore/PrivateClickMeasurement.cpp:

(TestWebKitAPI::TEST):

  • WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
  • WebKitTestRunner/InjectedBundle/TestRunner.cpp:

(WTR::TestRunner::setFraudPreventionValuesForTesting):

  • WebKitTestRunner/InjectedBundle/TestRunner.h:
  • WebKitTestRunner/TestController.cpp:

(WTR::TestController::setFraudPreventionValuesForTesting):

  • WebKitTestRunner/TestController.h:
  • WebKitTestRunner/TestInvocation.cpp:

(WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
Rebases some test cases.

LayoutTests:

  • http/tests/privateClickMeasurement/expired-attribution-report-gets-sent-on-session-start-expected.txt:
  • http/tests/privateClickMeasurement/resources/signToken.php:
  • http/tests/privateClickMeasurement/send-attribution-conversion-request-expected.txt:
  • http/tests/privateClickMeasurement/store-private-click-measurement-with-source-nonce-expected.txt:
  • http/tests/privateClickMeasurement/store-private-click-measurement-with-source-nonce.html:

Modifies the test to mock the whole round trip.

Location:
trunk
Files:
32 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r273206 r273209  
     12021-02-20  Jiewen Tan  <jiewen_tan@apple.com>
     2
     3        PCM: Store and report source unlinkable tokens
     4        https://bugs.webkit.org/show_bug.cgi?id=222208
     5        <rdar://problem/73582032>
     6
     7        Reviewed by John Wilander.
     8
     9        * http/tests/privateClickMeasurement/expired-attribution-report-gets-sent-on-session-start-expected.txt:
     10        * http/tests/privateClickMeasurement/resources/signToken.php:
     11        * http/tests/privateClickMeasurement/send-attribution-conversion-request-expected.txt:
     12        * http/tests/privateClickMeasurement/store-private-click-measurement-with-source-nonce-expected.txt:
     13        * http/tests/privateClickMeasurement/store-private-click-measurement-with-source-nonce.html:
     14        Modifies the test to mock the whole round trip.
     15
    1162021-02-20  Rob Buis  <rbuis@igalia.com>
    217
  • trunk/LayoutTests/http/tests/privateClickMeasurement/expired-attribution-report-gets-sent-on-session-start-expected.txt

    r270598 r273209  
    1212No cookies in attribution request.
    1313Request body:
    14 {"source_engagement_type":"click","source_site":"127.0.0.1","source_id":3,"attributed_on_site":"localhost","trigger_data":12,"version":1}
     14{"source_engagement_type":"click","source_site":"127.0.0.1","source_id":3,"attributed_on_site":"localhost","trigger_data":12,"version":2}
    1515
    1616
  • trunk/LayoutTests/http/tests/privateClickMeasurement/resources/signToken.php

    r273133 r273209  
    55$httpHeaders = $_SERVER;
    66$cookiesFound = false;
    7 // This php will respond to two consecutive server requests.
    8 // It will only complete the transaction when the second request finishes.
    9 $isSecondRequest = false;
     7// This php will respond to four consecutive server requests.
     8// It will only complete the transaction when the last request finishes.
     9$isLastRequest = false;
    1010
    1111if ($value = $httpHeaders["REQUEST_METHOD"]) {
     
    3535    fwrite($tokenSigningFile, "REQUEST_URI: $outputURL\n");
    3636
    37     $positionOfDummy = strpos($value, "&second=");
     37    $positionOfDummy = strpos($value, "&last=");
    3838    if ($positionOfDummy != false)
    39         $isSecondRequest = true;
     39        $isLastRequest = true;
    4040}
    4141
     
    4949fclose($tokenSigningFile);
    5050// Complete the transaction.
    51 if ($isSecondRequest)
     51if ($isLastRequest)
    5252    rename($tokenSigningFilePath . ".tmp", $tokenSigningFilePath);
    5353
    5454header("HTTP/1.1 201 Created");
     55header("unlinkable_token_public_key: ABCD");
     56header("secret_token_signature: ABCD");
    5557setcookie("cookieSetInTokenSigningResponse", "1", 0, "/");
    5658
  • trunk/LayoutTests/http/tests/privateClickMeasurement/send-attribution-conversion-request-expected.txt

    r270598 r273209  
    1717No cookies in attribution request.
    1818Request body:
    19 {"source_engagement_type":"click","source_site":"127.0.0.1","source_id":3,"attributed_on_site":"localhost","trigger_data":12,"version":1}
     19{"source_engagement_type":"click","source_site":"127.0.0.1","source_id":3,"attributed_on_site":"localhost","trigger_data":12,"version":2}
    2020
    2121
  • trunk/LayoutTests/http/tests/privateClickMeasurement/store-private-click-measurement-with-source-nonce-expected.txt

    r273167 r273209  
    1919No cookies in token signing request.
    2020Request body:
    21 {}
     21{"source_engagement_type":"click","source_nonce":"ABCDEFabcdef0123456789","source_secret_token":"secretToken","version":2}
     22REQUEST_METHOD: GET
     23HTTP_HOST: 127.0.0.1:8000
     24REQUEST_URI: /privateClickMeasurement/resources/signToken.php
     25No cookies in token signing request.
     26Request body:
    2227
    23 Unattributed Private Click Measurements:
    24 WebCore::PrivateClickMeasurement 1
    25 Source site: 127.0.0.1
    26 Attribute on site: localhost
    27 Source ID: 3
    28 No attribution trigger data.
     28REQUEST_METHOD: POST
     29HTTP_HOST: 127.0.0.1:8000
     30Content type: application/json
     31REQUEST_URI: /privateClickMeasurement/resources/signToken.php
     32No cookies in token signing request.
     33Request body:
     34{"source_engagement_type":"click","source_site":"127.0.0.1","source_id":3,"attributed_on_site":"localhost","trigger_data":12,"version":2,"source_unlinkable_token":"unlinkableToken","source_unlinkable_token_signature":"signature"}
     35
     36
     37No stored Private Click Measurement data.
  • trunk/LayoutTests/http/tests/privateClickMeasurement/store-private-click-measurement-with-source-nonce.html

    r273133 r273209  
    1212<div id="output"></div>
    1313<script>
     14    const currentTimeMillis = (new Date()).getTime();
     15    const highEntropyBits = currentTimeMillis - (Math.floor(currentTimeMillis / 1000000) * 1000000);
     16    const dummy = highEntropyBits + "" + Math.floor(Math.random() * 100);
     17
    1418    if (!window.location.search)
    1519        prepareTest();
     
    4852        if (window.testRunner) {
    4953            if (!window.location.search) {
    50                 const currentTimeMillis = (new Date()).getTime();
    51                 const highEntropyBits = currentTimeMillis - (Math.floor(currentTimeMillis / 1000000) * 1000000);
    52                 const dummy = highEntropyBits + "" + Math.floor(Math.random() * 100);
    5354                testRunner.setPrivateClickMeasurementTokenPublicKeyURLForTesting("http://127.0.0.1:8000/privateClickMeasurement/resources/signToken.php?dummy=" + dummy);
    54                 testRunner.setPrivateClickMeasurementTokenSignatureURLForTesting("http://127.0.0.1:8000/privateClickMeasurement/resources/signToken.php?dummy=" + dummy + "&second=true");
     55                testRunner.setPrivateClickMeasurementTokenSignatureURLForTesting("http://127.0.0.1:8000/privateClickMeasurement/resources/signToken.php?dummy=" + dummy);
     56                testRunner.setPrivateClickMeasurementAttributionReportURLForTesting("http://127.0.0.1:8000/privateClickMeasurement/resources/signToken.php?dummy=" + dummy + "&last=true");
     57                testRunner.setPrivateClickMeasurementOverrideTimerForTesting(true);
     58                testRunner.setFraudPreventionValuesForTesting("secretToken", "unlinkableToken", "signature", "WF3Ugg");
     59
    5560                targetLink.href = "http://localhost:8000/privateClickMeasurement/store-private-click-measurement-with-source-nonce.html?dummy=" + dummy;
    5661                activateElement("targetLink");
    5762            } else {
    5863                let params = new URLSearchParams(window.location.search);
    59                 appendTokenSignatureIframeAndFinish(params.get("dummy"));
     64
     65                let imageElement = document.createElement("img");
     66                imageElement.src = "https://127.0.0.1:8443/privateClickMeasurement/resources/redirectToConversion.php?conversionData=12&nonce=" + dummy + "&delay_ms=500";
     67                imageElement.id = "pixel";
     68                imageElement.onerror = function() {
     69                    appendTokenSignatureIframeAndFinish(params.get("dummy"));
     70                };
     71                document.body.appendChild(imageElement);
    6072            }
    6173        } else {
  • trunk/Source/WebCore/ChangeLog

    r273206 r273209  
     12021-02-20  Jiewen Tan  <jiewen_tan@apple.com>
     2
     3        PCM: Store and report source unlinkable tokens
     4        https://bugs.webkit.org/show_bug.cgi?id=222208
     5        <rdar://problem/73582032>
     6
     7        Reviewed by John Wilander.
     8
     9        This patch hooks up the network process with the PCM fraud prevention feature to
     10        enable the generation, storing and reporting the source unlinkable token.
     11
     12        Existing tests updated.
     13
     14        * loader/PrivateClickMeasurement.h:
     15        (WebCore::PrivateClickMeasurement::setSourceSecretTokenValue):
     16        Adds infrastructure to mock the crypto operations such that layout tests can be
     17        conducted without the server side crypto support.
     18
     19        * loader/PrivateClickMeasurement.cpp:
     20        (WebCore::PrivateClickMeasurement::attributionReportJSON const):
     21        (WebCore::PrivateClickMeasurement::tokenSignatureJSON const):
     22        (WebCore::PrivateClickMeasurement::setSourceUnlinkableToken):
     23        (WebCore::PrivateClickMeasurement::tokenSignatureJSON): Deleted.
     24        * loader/PrivateClickMeasurement.h:
     25        (WebCore::PrivateClickMeasurement::sourceUnlinkableToken const):
     26        * loader/cocoa/PrivateClickMeasurementCocoa.mm:
     27        (WebCore::PrivateClickMeasurement::calculateAndUpdateSourceSecretToken):
     28        (WebCore::PrivateClickMeasurement::calculateAndUpdateSourceUnlinkableToken):
     29        (WebCore::PrivateClickMeasurement::sourceSecretToken): Deleted.
     30        (WebCore::PrivateClickMeasurement::calculateSourceUnlinkableToken): Deleted.
     31        Update interfaces to service the use cases in the Networking process better.
     32
    1332021-02-20  Rob Buis  <rbuis@igalia.com>
    234
  • trunk/Source/WebCore/loader/PrivateClickMeasurement.cpp

    r273167 r273209  
    145145    reportDetails->setString("attributed_on_site"_s, m_attributeOnSite.registrableDomain.string());
    146146    reportDetails->setInteger("trigger_data"_s, m_attributionTriggerData->data);
    147     reportDetails->setInteger("version"_s, 1);
     147    reportDetails->setInteger("version"_s, 2);
     148
     149    if (m_sourceUnlinkableToken) {
     150        reportDetails->setString("source_unlinkable_token"_s, m_sourceUnlinkableToken->tokenBase64URL);
     151        reportDetails->setString("source_unlinkable_token_signature"_s, m_sourceUnlinkableToken->signatureBase64URL);
     152    }
     153
    148154    return reportDetails;
    149155}
     
    201207}
    202208
    203 Ref<JSON::Object> PrivateClickMeasurement::tokenSignatureJSON(const String& serverPublicKeyBase64URL)
     209Ref<JSON::Object> PrivateClickMeasurement::tokenSignatureJSON() const
    204210{
    205211    auto reportDetails = JSON::Object::create();
     
    207213        return reportDetails;
    208214
    209     String token;
    210 #if PLATFORM(COCOA)
    211     token = sourceSecretToken(serverPublicKeyBase64URL);
    212 #endif
    213     if (token.isEmpty())
     215    if (m_sourceSecretToken.valueBase64URL.isEmpty())
    214216        return reportDetails;
    215217
    216218    reportDetails->setString("source_engagement_type"_s, "click"_s);
    217219    reportDetails->setString("source_nonce"_s, m_ephemeralSourceNonce->nonce);
    218     reportDetails->setString("source_secret_token"_s, token);
     220    reportDetails->setString("source_secret_token"_s, m_sourceSecretToken.valueBase64URL);
    219221    reportDetails->setInteger("version"_s, 2);
    220222    return reportDetails;
    221223}
    222224
     225void PrivateClickMeasurement::setSourceUnlinkableToken(SourceUnlinkableToken&& token)
     226{
     227    if (!token.isValid())
     228        return;
     229    m_sourceUnlinkableToken = WTFMove(token);
     230}
     231
     232bool PrivateClickMeasurement::SourceUnlinkableToken::isValid() const
     233{
     234    return !(tokenBase64URL.isEmpty() || signatureBase64URL.isEmpty() || keyIDBase64URL.isEmpty());
     235}
     236
    223237} // namespace WebCore
  • trunk/Source/WebCore/loader/PrivateClickMeasurement.h

    r273167 r273209  
    278278
    279279    // MARK: - Fraud Prevention
     280    WEBCORE_EXPORT URL tokenPublicKeyURL() const;
     281    WEBCORE_EXPORT URL tokenSignatureURL() const;
     282
     283    WEBCORE_EXPORT Ref<JSON::Object> tokenSignatureJSON() const;
     284
    280285    struct EphemeralSourceNonce {
    281286        String nonce;
     
    293298    struct SourceUnlinkableToken {
    294299        String tokenBase64URL;
     300        String signatureBase64URL;
    295301        String keyIDBase64URL;
    296         String signatureBase64URL;
    297     };
    298 
    299     WEBCORE_EXPORT URL tokenPublicKeyURL() const;
    300     WEBCORE_EXPORT URL tokenSignatureURL() const;
    301 
    302     WEBCORE_EXPORT Ref<JSON::Object> tokenSignatureJSON(const String& serverPublicKeyBase64URL);
    303     WEBCORE_EXPORT Optional<SourceUnlinkableToken> calculateSourceUnlinkableToken(const String& serverResponseBase64URL);
     302
     303        bool isValid() const;
     304    };
     305
     306#if PLATFORM(COCOA)
     307    WEBCORE_EXPORT bool calculateAndUpdateSourceSecretToken(const String& serverPublicKeyBase64URL);
     308    WEBCORE_EXPORT bool calculateAndUpdateSourceUnlinkableToken(const String& serverResponseBase64URL);
     309#endif
     310
     311    void setSourceSecretTokenValue(const String& value) { m_sourceSecretToken.valueBase64URL = value; }
     312    const Optional<SourceUnlinkableToken>& sourceUnlinkableToken() const { return m_sourceUnlinkableToken; }
     313    WEBCORE_EXPORT void setSourceUnlinkableToken(SourceUnlinkableToken&&);
    304314
    305315    template<class Encoder> void encode(Encoder&) const;
     
    308318private:
    309319    bool isValid() const;
    310 #if PLATFORM(COCOA)
    311     String sourceSecretToken(const String& serverPublicKeyBase64URL);
    312 #endif
    313320
    314321    SourceID m_sourceID;
     
    328335        RetainPtr<RSABSSATokenReady> readyToken;
    329336#endif
     337        String valueBase64URL;
    330338    };
    331339
    332340    Optional<EphemeralSourceNonce> m_ephemeralSourceNonce;
    333341    SourceSecretToken m_sourceSecretToken;
     342    Optional<SourceUnlinkableToken> m_sourceUnlinkableToken;
    334343};
    335344
  • trunk/Source/WebCore/loader/cocoa/PrivateClickMeasurementCocoa.mm

    r273167 r273209  
    3131namespace WebCore {
    3232
    33 String PrivateClickMeasurement::sourceSecretToken(const String& serverPublicKeyBase64URL)
     33bool PrivateClickMeasurement::calculateAndUpdateSourceSecretToken(const String& serverPublicKeyBase64URL)
    3434{
    3535#if HAVE(RSA_BSSA)
     
    3737        Vector<uint8_t> serverPublicKeyData;
    3838        if (!base64URLDecode(serverPublicKeyBase64URL, serverPublicKeyData))
    39             return emptyString();
     39            return false;
    4040        auto serverPublicKey = adoptNS([[NSData alloc] initWithBytes:serverPublicKeyData.data() length:serverPublicKeyData.size()]);
    4141
     
    4343        m_sourceSecretToken.blinder = adoptNS([PAL::allocRSABSSATokenBlinderInstance() initWithPublicKey:serverPublicKey.get() error:nullptr]);
    4444        if (!m_sourceSecretToken.blinder)
    45             return emptyString();
     45            return false;
    4646    }
    4747
     
    4949    m_sourceSecretToken.waitingToken = [m_sourceSecretToken.blinder tokenWaitingActivationWithContent:nullptr error:nullptr];
    5050    if (!m_sourceSecretToken.waitingToken)
    51         return emptyString();
     51        return false;
    5252
    53     return WTF::base64URLEncode([m_sourceSecretToken.waitingToken blindedMessage].bytes, [m_sourceSecretToken.waitingToken blindedMessage].length);
     53    m_sourceSecretToken.valueBase64URL = WTF::base64URLEncode([m_sourceSecretToken.waitingToken blindedMessage].bytes, [m_sourceSecretToken.waitingToken blindedMessage].length);
     54    return true;
    5455#else
    5556    UNUSED_PARAM(serverPublicKeyBase64URL);
    56     return emptyString();
     57    return false;
    5758#endif // HAVE(RSA_BSSA)
    5859}
    5960
    60 auto PrivateClickMeasurement::calculateSourceUnlinkableToken(const String& serverResponseBase64URL) -> Optional<SourceUnlinkableToken>
     61bool PrivateClickMeasurement::calculateAndUpdateSourceUnlinkableToken(const String& serverResponseBase64URL)
    6162{
    6263#if HAVE(RSA_BSSA)
    6364    if (!m_sourceSecretToken.waitingToken)
    64         return WTF::nullopt;
     65        return false;
    6566
    6667    {
    6768        Vector<uint8_t> serverResponseData;
    6869        if (!base64URLDecode(serverResponseBase64URL, serverResponseData))
    69             return WTF::nullopt;
     70            return false;
    7071        auto serverResponse = adoptNS([[NSData alloc] initWithBytes:serverResponseData.data() length:serverResponseData.size()]);
    7172
     
    7374        m_sourceSecretToken.readyToken = [m_sourceSecretToken.waitingToken activateTokenWithServerResponse:serverResponse.get() error:nullptr];
    7475        if (!m_sourceSecretToken.readyToken)
    75             return WTF::nullopt;
     76            return false;
    7677    }
    7778
     
    8182    token.signatureBase64URL = WTF::base64URLEncode([m_sourceSecretToken.readyToken signature].bytes, [m_sourceSecretToken.readyToken signature].length);
    8283
    83     return token;
     84    m_sourceUnlinkableToken = WTFMove(token);
     85    return true;
    8486#else
    8587    UNUSED_PARAM(serverResponseBase64URL);
    86     return WTF::nullopt;
     88    return false;
    8789#endif // HAVE(RSA_BSSA)
    8890}
  • trunk/Source/WebKit/ChangeLog

    r273204 r273209  
     12021-02-20  Jiewen Tan  <jiewen_tan@apple.com>
     2
     3        PCM: Store and report source unlinkable tokens
     4        https://bugs.webkit.org/show_bug.cgi?id=222208
     5        <rdar://problem/73582032>
     6
     7        Reviewed by John Wilander.
     8
     9        * NetworkProcess/NetworkProcess.cpp:
     10        (WebKit::NetworkProcess::setFraudPreventionValuesForTesting):
     11        * NetworkProcess/NetworkProcess.h:
     12        * NetworkProcess/NetworkProcess.messages.in:
     13        * NetworkProcess/NetworkSession.cpp:
     14        (WebKit::NetworkSession::setFraudPreventionValuesForTesting):
     15        * NetworkProcess/NetworkSession.h:
     16        * NetworkProcess/PrivateClickMeasurementManager.cpp:
     17        (WebKit::PrivateClickMeasurementManager::storeUnattributed):
     18        (WebKit::PrivateClickMeasurementManager::getSignedSecretToken):
     19        (WebKit::PrivateClickMeasurementManager::setFraudPreventionValuesForTesting):
     20        * NetworkProcess/PrivateClickMeasurementManager.h:
     21        * UIProcess/API/C/WKPage.cpp:
     22        (WKPageSetFraudPreventionValuesForTesting):
     23        * UIProcess/API/C/WKPagePrivate.h:
     24        * UIProcess/WebPageProxy.cpp:
     25        (WebKit::WebPageProxy::markPrivateClickMeasurementsAsExpiredForTesting):
     26        (WebKit::WebPageProxy::setFraudPreventionValuesForTesting):
     27        * UIProcess/WebPageProxy.h:
     28        Adds infrastructure to mock the crypto operations such that layout tests can be
     29        conducted without the server side crypto support.
     30
     31        * NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp:
     32        (WebKit::ResourceLoadStatisticsDatabaseStore::buildPrivateClickMeasurementFromDatabase):
     33        (WebKit::ResourceLoadStatisticsDatabaseStore::insertPrivateClickMeasurement):
     34        * NetworkProcess/PrivateClickMeasurementManager.cpp:
     35        (WebKit::PrivateClickMeasurementManager::storeUnattributed):
     36        (WebKit::PrivateClickMeasurementManager::getTokenPublicKey):
     37        (WebKit::PrivateClickMeasurementManager::getSignedSecretToken):
     38        (WebKit::PrivateClickMeasurementManager::fireConversionRequest):
     39        (WebKit::PrivateClickMeasurementManager::fireConversionRequestImpl):
     40        * NetworkProcess/PrivateClickMeasurementManager.h:
     41        Connects the fraud prevention feature in PCM to generate, store, and report the unlinkable token.
     42
    1432021-02-20  Kimmo Kinnunen  <kkinnunen@apple.com>
    244
  • trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp

    r273144 r273209  
    29692969    }
    29702970
    2971     // FIXME(<rdar://problem/73582032>): Store these in the attribution object once PCM fraud prevention is in place.
    2972     UNUSED_PARAM(token);
    2973     UNUSED_PARAM(signature);
    2974     UNUSED_PARAM(keyID);
     2971    attribution.setSourceUnlinkableToken({ token, signature, keyID });
    29752972
    29762973    return attribution;
     
    30203017        return;
    30213018
    3022     // FIXME(<rdar://problem/73582032>): Use real values from the attribution object once PCM fraud prevention is in place.
    3023     String token;
    3024     String signature;
    3025     String keyID;
    3026 
     3019    auto& sourceUnlinkableToken = attribution.sourceUnlinkableToken();
    30273020    if (attributionType == PrivateClickMeasurementAttributionType::Attributed) {
    30283021        auto attributionTriggerData = attribution.attributionTriggerData() ? attribution.attributionTriggerData().value().data : -1;
     
    30393032            || statement.bindDouble(6, attribution.timeOfAdClick().secondsSinceEpoch().value()) != SQLITE_OK
    30403033            || statement.bindDouble(7, earliestTimeToSend) != SQLITE_OK
    3041             || statement.bindText(8, token) != SQLITE_OK
    3042             || statement.bindText(9, signature) != SQLITE_OK
    3043             || statement.bindText(10, keyID) != SQLITE_OK
     3034            || statement.bindText(8, sourceUnlinkableToken ? sourceUnlinkableToken->tokenBase64URL : emptyString()) != SQLITE_OK
     3035            || statement.bindText(9, sourceUnlinkableToken ? sourceUnlinkableToken->signatureBase64URL : emptyString()) != SQLITE_OK
     3036            || statement.bindText(10, sourceUnlinkableToken ? sourceUnlinkableToken->keyIDBase64URL : emptyString()) != SQLITE_OK
    30443037            || statement.step() != SQLITE_DONE) {
    30453038            RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::insertPrivateClickMeasurement insertAttributedPrivateClickMeasurementQuery, error message: %{private}s", this, m_database.lastErrorMsg());
     
    30553048        || statement.bindInt(3, attribution.sourceID().id) != SQLITE_OK
    30563049        || statement.bindDouble(4, attribution.timeOfAdClick().secondsSinceEpoch().value()) != SQLITE_OK
    3057         || statement.bindText(5, token) != SQLITE_OK
    3058         || statement.bindText(6, signature) != SQLITE_OK
    3059         || statement.bindText(7, keyID) != SQLITE_OK
     3050        || statement.bindText(5, sourceUnlinkableToken ? sourceUnlinkableToken->tokenBase64URL : emptyString()) != SQLITE_OK
     3051        || statement.bindText(6, sourceUnlinkableToken ? sourceUnlinkableToken->signatureBase64URL : emptyString()) != SQLITE_OK
     3052        || statement.bindText(7, sourceUnlinkableToken ? sourceUnlinkableToken->keyIDBase64URL : emptyString()) != SQLITE_OK
    30603053        || statement.step() != SQLITE_DONE) {
    30613054        RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::insertPrivateClickMeasurement insertUnattributedPrivateClickMeasurementQuery, error message: %{private}s", this, m_database.lastErrorMsg());
  • trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp

    r273183 r273209  
    26412641}
    26422642
     2643void NetworkProcess::setFraudPreventionValuesForTesting(PAL::SessionID sessionID, String&& secretToken, String&& unlinkableToken, String&& signature, String&& keyID, CompletionHandler<void()>&& completionHandler)
     2644{
     2645    if (auto* session = networkSession(sessionID))
     2646        session->setFraudPreventionValuesForTesting(WTFMove(secretToken), WTFMove(unlinkableToken), WTFMove(signature), WTFMove(keyID));
     2647
     2648    completionHandler();
     2649}
     2650
    26432651void NetworkProcess::addKeptAliveLoad(Ref<NetworkResourceLoader>&& loader)
    26442652{
  • trunk/Source/WebKit/NetworkProcess/NetworkProcess.h

    r273133 r273209  
    347347    void setPrivateClickMeasurementAttributionReportURLForTesting(PAL::SessionID, URL&&, CompletionHandler<void()>&&);
    348348    void markPrivateClickMeasurementsAsExpiredForTesting(PAL::SessionID, CompletionHandler<void()>&&);
     349    void setFraudPreventionValuesForTesting(PAL::SessionID, String&& secretToken, String&& unlinkableToken, String&& signature, String&& keyID, CompletionHandler<void()>&&);
    349350
    350351    RefPtr<WebCore::StorageQuotaManager> storageQuotaManager(PAL::SessionID, const WebCore::ClientOrigin&);
  • trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in

    r273133 r273209  
    172172    SetPrivateClickMeasurementAttributionReportURLForTesting(PAL::SessionID sessionID, URL url) -> () Async
    173173    MarkPrivateClickMeasurementsAsExpiredForTesting(PAL::SessionID sessionID) -> () Async
     174    SetFraudPreventionValuesForTesting(PAL::SessionID sessionID, String secretToken, String unlinkableToken, String signature, String keyID) -> () Async
    174175    GetLocalStorageOriginDetails(PAL::SessionID sessionID) -> (Vector<WebKit::LocalStorageDatabaseTracker::OriginDetails> details) Async
    175176
  • trunk/Source/WebKit/NetworkProcess/NetworkSession.cpp

    r273133 r273209  
    359359}
    360360
     361// FIXME: Switch to non-mocked test data once the right cryptography library is available in open source.
     362void NetworkSession::setFraudPreventionValuesForTesting(String&& secretToken, String&& unlinkableToken, String&& signature, String&& keyID)
     363{
     364    privateClickMeasurement().setFraudPreventionValuesForTesting(WTFMove(secretToken), WTFMove(unlinkableToken), WTFMove(signature), WTFMove(keyID));
     365}
     366
    361367void NetworkSession::firePrivateClickMeasurementTimerImmediately()
    362368{
  • trunk/Source/WebKit/NetworkProcess/NetworkSession.h

    r273133 r273209  
    128128    void setPrivateClickMeasurementAttributionReportURLForTesting(URL&&);
    129129    void markPrivateClickMeasurementsAsExpiredForTesting();
     130    void setFraudPreventionValuesForTesting(String&& secretToken, String&& unlinkableToken, String&& signature, String&& keyID);
    130131    void firePrivateClickMeasurementTimerImmediately();
    131132
  • trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementManager.cpp

    r273180 r273209  
    3838#include <WebCore/RuntimeApplicationChecks.h>
    3939#include <WebCore/RuntimeEnabledFeatures.h>
     40#include <pal/crypto/CryptoDigest.h>
    4041#include <wtf/CryptographicallyRandomNumber.h>
    4142#include <wtf/text/StringBuilder.h>
     
    7778    if (attribution.ephemeralSourceNonce()) {
    7879        auto attributionCopy = attribution;
    79         getTokenPublicKey(WTFMove(attributionCopy));
     80        getTokenPublicKey(WTFMove(attributionCopy), [weakThis = makeWeakPtr(*this), this] (PrivateClickMeasurement&& attribution, const String& publicKeyBase64URL) {
     81            if (!weakThis)
     82                return;
     83
     84            if (publicKeyBase64URL.isEmpty())
     85                return;
     86
     87            if (m_fraudPreventionValuesForTesting)
     88                attribution.setSourceSecretTokenValue(m_fraudPreventionValuesForTesting->secretToken);
     89#if PLATFORM(COCOA)
     90            else {
     91                if (!attribution.calculateAndUpdateSourceSecretToken(publicKeyBase64URL))
     92                    return;
     93            }
     94#endif
     95
     96            getSignedSecretToken(WTFMove(attribution));
     97        });
    8098    }
    8199
     
    127145}
    128146
    129 void PrivateClickMeasurementManager::getTokenPublicKey(PrivateClickMeasurement&& attribution)
     147void PrivateClickMeasurementManager::getTokenPublicKey(PrivateClickMeasurement&& attribution, Function<void(PrivateClickMeasurement&& attribution, const String& publicKeyBase64URL)>&& callback)
    130148{
    131149    if (!featureEnabled())
     
    148166    m_networkProcess->broadcastConsoleMessage(m_sessionID, MessageSource::PrivateClickMeasurement, MessageLevel::Log, "[Private Click Measurement] About to fire a unlinkable token public key request."_s);
    149167
    150     m_pingLoadFunction(WTFMove(loadParameters), [weakThis = makeWeakPtr(*this), attribution = WTFMove(attribution), this] (const WebCore::ResourceError& error, const WebCore::ResourceResponse& response) mutable {
     168    m_pingLoadFunction(WTFMove(loadParameters), [weakThis = makeWeakPtr(*this), this, attribution = WTFMove(attribution), callback = WTFMove(callback)] (const WebCore::ResourceError& error, const WebCore::ResourceResponse& response) mutable {
    151169        if (!weakThis)
    152170            return;
     
    157175        }
    158176
    159         // FIXME: Receive and extra the server public key, rdar://73582032.
    160         getSignedSecretToken(WTFMove(attribution), emptyString());
     177        // FIXME(222217): Retrieve the public key from the content instead of the header.
     178        callback(WTFMove(attribution), response.httpHeaderFields().get("unlinkable_token_public_key"_s));
    161179    });
    162180
    163181}
    164182
    165 void PrivateClickMeasurementManager::getSignedSecretToken(PrivateClickMeasurement&& attribution, const String& tokenPublicKeyBase64URL)
     183void PrivateClickMeasurementManager::getSignedSecretToken(PrivateClickMeasurement&& attribution)
    166184{
    167185    if (!featureEnabled())
     
    179197        return;
    180198
    181     auto loadParameters = generateNetworkResourceLoadParametersForHttpPost(WTFMove(tokenSignatureURL), attribution.tokenSignatureJSON(tokenPublicKeyBase64URL), pcmDataCarried);
     199    auto loadParameters = generateNetworkResourceLoadParametersForHttpPost(WTFMove(tokenSignatureURL), attribution.tokenSignatureJSON(), pcmDataCarried);
    182200
    183201    RELEASE_LOG_INFO(PrivateClickMeasurement, "About to fire a secret token signing request.");
    184202    m_networkProcess->broadcastConsoleMessage(m_sessionID, MessageSource::PrivateClickMeasurement, MessageLevel::Log, "[Private Click Measurement] About to fire a secret token signing request."_s);
    185203
    186     m_pingLoadFunction(WTFMove(loadParameters), [weakThis = makeWeakPtr(*this)](const WebCore::ResourceError& error, const WebCore::ResourceResponse& response) {
     204    m_pingLoadFunction(WTFMove(loadParameters), [weakThis = makeWeakPtr(*this), this, attribution = WTFMove(attribution)] (const WebCore::ResourceError& error, const WebCore::ResourceResponse& response) mutable {
    187205        if (!weakThis)
    188206            return;
    189207
    190208        if (!error.isNull()) {
    191             weakThis->m_networkProcess->broadcastConsoleMessage(weakThis->m_sessionID, MessageSource::PrivateClickMeasurement, MessageLevel::Error, makeString("[Private Click Measurement] Received error: '"_s, error.localizedDescription(), "' for secret token signing request."_s));
     209            m_networkProcess->broadcastConsoleMessage(weakThis->m_sessionID, MessageSource::PrivateClickMeasurement, MessageLevel::Error, makeString("[Private Click Measurement] Received error: '"_s, error.localizedDescription(), "' for secret token signing request."_s));
    192210            return;
    193211        }
    194        
    195         // FIXME: Receive and store the signed secret token, rdar://73582032.
     212
     213        // FIXME(222217): Retrieve the signature from the content instead of the header.
     214        auto signatureBase64URL = response.httpHeaderFields().get("secret_token_signature"_s);
     215        if (signatureBase64URL.isEmpty())
     216            return;
     217
     218        if (m_fraudPreventionValuesForTesting)
     219            attribution.setSourceUnlinkableToken({ m_fraudPreventionValuesForTesting->unlinkableToken, m_fraudPreventionValuesForTesting->signature, m_fraudPreventionValuesForTesting->keyID });
     220#if PLATFORM(COCOA)
     221        else {
     222            if (!attribution.calculateAndUpdateSourceUnlinkableToken(signatureBase64URL))
     223                return;
     224        }
     225#endif
     226
     227        m_networkProcess->broadcastConsoleMessage(m_sessionID, MessageSource::PrivateClickMeasurement, MessageLevel::Log, "[Private Click Measurement] Storing an unlinkable token."_s);
     228
     229#if ENABLE(RESOURCE_LOAD_STATISTICS)
     230        if (auto* resourceLoadStatistics = m_networkSession->resourceLoadStatistics())
     231            resourceLoadStatistics->insertPrivateClickMeasurement(WTFMove(attribution), PrivateClickMeasurementAttributionType::Unattributed);
     232#endif
    196233    });
    197234
     
    257294        return;
    258295
     296    if (!attribution.sourceUnlinkableToken()) {
     297        fireConversionRequestImpl(attribution);
     298        return;
     299    }
     300
     301    auto attributionCopy = attribution;
     302    getTokenPublicKey(WTFMove(attributionCopy), [weakThis = makeWeakPtr(*this), this] (PrivateClickMeasurement&& attribution, const String& publicKeyBase64URL) {
     303        if (!weakThis)
     304            return;
     305
     306        Vector<uint8_t> publicKeyData;
     307        WTF::base64URLDecode(publicKeyBase64URL, publicKeyData);
     308
     309        auto crypto = PAL::CryptoDigest::create(PAL::CryptoDigest::Algorithm::SHA_256);
     310        crypto->addBytes(publicKeyData.data(), publicKeyData.size());
     311        auto publicKeyDataHash = crypto->computeHash();
     312
     313        static const size_t keyIDSize = 4;
     314        auto keyID = WTF::base64URLEncode(publicKeyDataHash.data(), keyIDSize);
     315        if (keyID != attribution.sourceUnlinkableToken()->keyIDBase64URL)
     316            return;
     317
     318        fireConversionRequestImpl(attribution);
     319    });
     320}
     321
     322void PrivateClickMeasurementManager::fireConversionRequestImpl(const PrivateClickMeasurement& attribution)
     323{
    259324    auto attributionURL = m_attributionReportBaseURLForTesting ? *m_attributionReportBaseURLForTesting : attribution.attributionReportURL();
    260325    if (attributionURL.isEmpty() || !attributionURL.isValid())
     
    426491}
    427492
     493void PrivateClickMeasurementManager::setFraudPreventionValuesForTesting(String&& secretToken, String&& unlinkableToken, String&& signature, String&& keyID)
     494{
     495    if (secretToken.isEmpty() || unlinkableToken.isEmpty() || signature.isEmpty() || keyID.isEmpty())
     496        return;
     497    m_fraudPreventionValuesForTesting = TestingFraudPreventionValues { WTFMove(secretToken), WTFMove(unlinkableToken), WTFMove(signature), WTFMove(keyID) };
     498}
     499
    428500bool PrivateClickMeasurementManager::featureEnabled() const
    429501{
  • trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementManager.h

    r273167 r273209  
    6767    void markAllUnattributedAsExpiredForTesting();
    6868    void markAttributedPrivateClickMeasurementsAsExpiredForTesting(CompletionHandler<void()>&&);
     69    void setFraudPreventionValuesForTesting(String&& secretToken, String&& unlinkableToken, String&& signature, String&& keyID);
    6970    void startTimer(Seconds);
    7071
    7172private:
    72     void getTokenPublicKey(PrivateClickMeasurement&&);
    73     void getSignedSecretToken(PrivateClickMeasurement&&, const String& tokenPublicKeyBase64URL);
     73    void getTokenPublicKey(PrivateClickMeasurement&&, Function<void(PrivateClickMeasurement&& attribution, const String& publicKeyBase64URL)>&&);
     74    void getSignedSecretToken(PrivateClickMeasurement&&);
    7475    void clearSentAttribution(PrivateClickMeasurement&&);
    7576    void attribute(const SourceSite&, const AttributeOnSite&, AttributionTriggerData&&);
    7677    void fireConversionRequest(const PrivateClickMeasurement&);
     78    void fireConversionRequestImpl(const PrivateClickMeasurement&);
    7779    void firePendingAttributionRequests();
    7880    void clearExpired();
     
    8991    PAL::SessionID m_sessionID;
    9092    Function<void(NetworkResourceLoadParameters&&, CompletionHandler<void(const WebCore::ResourceError&, const WebCore::ResourceResponse&)>&&)> m_pingLoadFunction;
     93
     94    struct TestingFraudPreventionValues {
     95        String secretToken;
     96        String unlinkableToken;
     97        String signature;
     98        String keyID;
     99    };
     100
     101    Optional<TestingFraudPreventionValues> m_fraudPreventionValuesForTesting;
    91102};
    92103   
  • trunk/Source/WebKit/UIProcess/API/C/WKPage.cpp

    r273133 r273209  
    29742974}
    29752975
     2976void WKPageSetFraudPreventionValuesForTesting(WKPageRef page, WKStringRef secretToken, WKStringRef unlinkableToken, WKStringRef signature, WKStringRef keyID, WKPageSetFraudPreventionValuesForTestingFunction callback, void* callbackContext)
     2977{
     2978    toImpl(page)->setFraudPreventionValuesForTesting(toWTFString(secretToken), toWTFString(unlinkableToken), toWTFString(signature), toWTFString(keyID), [callbackContext, callback] () {
     2979        callback(callbackContext);
     2980    });
     2981}
     2982
    29762983void WKPageSetMockCameraOrientation(WKPageRef page, uint64_t orientation)
    29772984{
  • trunk/Source/WebKit/UIProcess/API/C/WKPagePrivate.h

    r273133 r273209  
    188188typedef void (*WKPageMarkPrivateClickMeasurementsAsExpiredForTestingFunction)(void* functionContext);
    189189WK_EXPORT void WKPageMarkPrivateClickMeasurementsAsExpiredForTesting(WKPageRef page, WKPageMarkPrivateClickMeasurementsAsExpiredForTestingFunction callback, void* callbackContext);
     190typedef void (*WKPageSetFraudPreventionValuesForTestingFunction)(void* functionContext);
     191WK_EXPORT void WKPageSetFraudPreventionValuesForTesting(WKPageRef page, WKStringRef secretToken, WKStringRef unlinkableToken, WKStringRef signature, WKStringRef keyID, WKPageSetFraudPreventionValuesForTestingFunction callback, void* callbackContext);
    190192
    191193WK_EXPORT void WKPageSetMockCameraOrientation(WKPageRef page, uint64_t orientation);
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r273184 r273209  
    1005310053}
    1005410054
     10055void WebPageProxy::setFraudPreventionValuesForTesting(const String& secretToken, const String& unlinkableToken, const String& signature, const String& keyID, CompletionHandler<void()>&& completionHandler)
     10056{
     10057    websiteDataStore().networkProcess().sendWithAsyncReply(Messages::NetworkProcess::SetFraudPreventionValuesForTesting(m_websiteDataStore->sessionID(), secretToken, unlinkableToken, signature, keyID), WTFMove(completionHandler));
     10058}
     10059
    1005510060#if ENABLE(SPEECH_SYNTHESIS)
    1005610061
  • trunk/Source/WebKit/UIProcess/WebPageProxy.h

    r273184 r273209  
    17051705    void setPrivateClickMeasurementAttributionReportURLForTesting(const URL&, CompletionHandler<void()>&&);
    17061706    void markPrivateClickMeasurementsAsExpiredForTesting(CompletionHandler<void()>&&);
     1707    void setFraudPreventionValuesForTesting(const String& secretToken, const String& unlinkableToken, const String& signature, const String& keyID, CompletionHandler<void()>&&);
    17071708
    17081709#if ENABLE(SPEECH_SYNTHESIS)
  • trunk/Tools/ChangeLog

    r273204 r273209  
     12021-02-20  Jiewen Tan  <jiewen_tan@apple.com>
     2
     3        PCM: Store and report source unlinkable tokens
     4        https://bugs.webkit.org/show_bug.cgi?id=222208
     5        <rdar://problem/73582032>
     6
     7        Reviewed by John Wilander.
     8
     9        * TestWebKitAPI/Tests/WebCore/PrivateClickMeasurement.cpp:
     10        (TestWebKitAPI::TEST):
     11        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
     12        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
     13        (WTR::TestRunner::setFraudPreventionValuesForTesting):
     14        * WebKitTestRunner/InjectedBundle/TestRunner.h:
     15        * WebKitTestRunner/TestController.cpp:
     16        (WTR::TestController::setFraudPreventionValuesForTesting):
     17        * WebKitTestRunner/TestController.h:
     18        * WebKitTestRunner/TestInvocation.cpp:
     19        (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
     20        Rebases some test cases.
     21
    1222021-02-20  Kimmo Kinnunen  <kkinnunen@apple.com>
    223
  • trunk/Tools/TestWebKitAPI/Tests/WebCore/PrivateClickMeasurement.cpp

    r273167 r273209  
    5252    ASSERT_EQ(attributionURL.string(), "https://webkit.org/.well-known/private-click-measurement/report-attribution/");
    5353
    54     ASSERT_EQ(attribution.attributionReportJSON()->toJSONString(), "{\"source_engagement_type\":\"click\",\"source_site\":\"webkit.org\",\"source_id\":0,\"attributed_on_site\":\"example.com\",\"trigger_data\":0,\"version\":1}");
     54    ASSERT_EQ(attribution.attributionReportJSON()->toJSONString(), "{\"source_engagement_type\":\"click\",\"source_site\":\"webkit.org\",\"source_id\":0,\"attributed_on_site\":\"example.com\",\"trigger_data\":0,\"version\":2}");
    5555}
    5656
     
    6464    ASSERT_EQ(attributionURL.string(), "https://webkit.org/.well-known/private-click-measurement/report-attribution/");
    6565
    66     ASSERT_EQ(attribution.attributionReportJSON()->toJSONString(), "{\"source_engagement_type\":\"click\",\"source_site\":\"webkit.org\",\"source_id\":192,\"attributed_on_site\":\"example.com\",\"trigger_data\":9,\"version\":1}");
     66    ASSERT_EQ(attribution.attributionReportJSON()->toJSONString(), "{\"source_engagement_type\":\"click\",\"source_site\":\"webkit.org\",\"source_id\":192,\"attributed_on_site\":\"example.com\",\"trigger_data\":9,\"version\":2}");
    6767}
    6868
     
    7676    ASSERT_EQ(attributionURL.string(), "https://webkit.org/.well-known/private-click-measurement/report-attribution/");
    7777
    78     ASSERT_EQ(attribution.attributionReportJSON()->toJSONString(), "{\"source_engagement_type\":\"click\",\"source_site\":\"webkit.org\",\"source_id\":255,\"attributed_on_site\":\"example.com\",\"trigger_data\":15,\"version\":1}");
     78    ASSERT_EQ(attribution.attributionReportJSON()->toJSONString(), "{\"source_engagement_type\":\"click\",\"source_site\":\"webkit.org\",\"source_id\":255,\"attributed_on_site\":\"example.com\",\"trigger_data\":15,\"version\":2}");
    7979}
    8080
     
    308308
    309309    PrivateClickMeasurement pcm;
    310     auto sourceSecretToken = pcm.tokenSignatureJSON(serverPublicKeyBase64URL);
     310    auto sourceSecretToken = pcm.tokenSignatureJSON();
    311311    EXPECT_EQ(sourceSecretToken->asObject()->size(), 0ul);
    312312
     
    315315    pcm.setEphemeralSourceNonce(WTFMove(ephemeralNonce));
    316316
    317     sourceSecretToken = pcm.tokenSignatureJSON(serverPublicKeyBase64URL);
     317    EXPECT_TRUE(pcm.calculateAndUpdateSourceSecretToken(serverPublicKeyBase64URL));
     318    sourceSecretToken = pcm.tokenSignatureJSON();
    318319    EXPECT_EQ(sourceSecretToken->asObject()->size(), 4ul);
    319320
    320     auto persistentToken = pcm.calculateSourceUnlinkableToken(emptyString());
    321     EXPECT_FALSE(persistentToken);
     321    EXPECT_FALSE(pcm.calculateAndUpdateSourceUnlinkableToken(emptyString()));
    322322}
    323323#endif
  • trunk/Tools/TestWebKitAPI/Tests/WebCore/cocoa/PrivateClickMeasurementCocoa.mm

    r273167 r273209  
    8282
    8383    // Continue the test.
    84     auto sourceSecretToken = pcm.tokenSignatureJSON(WTF::base64URLEncode(nsSpkiData.bytes, nsSpkiData.length));
     84    EXPECT_TRUE(pcm.calculateAndUpdateSourceSecretToken(WTF::base64URLEncode(nsSpkiData.bytes, nsSpkiData.length)));
     85    auto sourceSecretToken = pcm.tokenSignatureJSON();
    8586    EXPECT_EQ(sourceSecretToken->asObject()->size(), 4ul);
    8687    EXPECT_STREQ(sourceSecretToken->getString("source_engagement_type"_s).utf8().data(), "click");
     
    9798
    9899    // Continue the test.
    99     auto persistentToken = pcm.calculateSourceUnlinkableToken(WTF::base64URLEncode([blindedSignature bytes], [blindedSignature length]));
     100    EXPECT_TRUE(pcm.calculateAndUpdateSourceUnlinkableToken(WTF::base64URLEncode([blindedSignature bytes], [blindedSignature length])));
     101    auto& persistentToken = pcm.sourceUnlinkableToken();
    100102    EXPECT_TRUE(persistentToken);
    101103    EXPECT_FALSE(persistentToken->tokenBase64URL.isEmpty());
  • trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl

    r273133 r273209  
    408408    undefined setPrivateClickMeasurementAttributionReportURLForTesting(DOMString url);
    409409    undefined markPrivateClickMeasurementsAsExpiredForTesting();
     410    undefined setFraudPreventionValuesForTesting(DOMString secretToken, DOMString unlinkableToken, DOMString signature, DOMString keyID);
    410411
    411412    // SpeechRecognition
  • trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp

    r273133 r273209  
    20492049}
    20502050
     2051void TestRunner::setFraudPreventionValuesForTesting(JSStringRef secretToken, JSStringRef unlinkableToken, JSStringRef signature, JSStringRef keyID)
     2052{
     2053    postSynchronousMessage("SetFraudPreventionValuesForTesting", createWKDictionary({
     2054        { "SecretToken", toWK(secretToken) },
     2055        { "UnlinkableToken", toWK(unlinkableToken) },
     2056        { "Signature", toWK(signature) },
     2057        { "KeyID", toWK(keyID) },
     2058    }));
     2059}
     2060
    20512061bool TestRunner::hasAppBoundSession()
    20522062{
  • trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h

    r273133 r273209  
    518518    void markPrivateClickMeasurementsAsExpiredForTesting();
    519519    void markAttributedPrivateClickMeasurementsAsExpiredForTesting();
     520    void setFraudPreventionValuesForTesting(JSStringRef secretToken, JSStringRef unlinkableToken, JSStringRef signature, JSStringRef keyID);
    520521    void simulateResourceLoadStatisticsSessionRestart();
    521522
  • trunk/Tools/WebKitTestRunner/TestController.cpp

    r273133 r273209  
    36593659}
    36603660
     3661void TestController::setFraudPreventionValuesForTesting(WKStringRef secretToken, WKStringRef unlinkableToken, WKStringRef signature, WKStringRef keyID)
     3662{
     3663    PrivateClickMeasurementVoidCallbackContext callbackContext(*this);
     3664    WKPageSetFraudPreventionValuesForTesting(m_mainWebView->page(), secretToken, unlinkableToken, signature, keyID, privateClickMeasurementVoidCallback, &callbackContext);
     3665    runUntil(callbackContext.done, noTimeout);
     3666}
     3667
    36613668WKURLRef TestController::currentTestURL() const
    36623669{
  • trunk/Tools/WebKitTestRunner/TestController.h

    r273133 r273209  
    351351    void setPrivateClickMeasurementAttributionReportURLForTesting(WKURLRef);
    352352    void markPrivateClickMeasurementsAsExpiredForTesting();
     353    void setFraudPreventionValuesForTesting(WKStringRef secretToken, WKStringRef unlinkableToken, WKStringRef signature, WKStringRef keyID);
    353354
    354355    void didSetAppBoundDomains() const;
  • trunk/Tools/WebKitTestRunner/TestInvocation.cpp

    r273133 r273209  
    13631363    }
    13641364
     1365    if (WKStringIsEqualToUTF8CString(messageName, "SetFraudPreventionValuesForTesting")) {
     1366        auto testDictionary = dictionaryValue(messageBody);
     1367        auto secretToken = stringValue(testDictionary, "SecretToken");
     1368        auto unlinkableToken = stringValue(testDictionary, "UnlinkableToken");
     1369        auto signature = stringValue(testDictionary, "Signature");
     1370        auto keyID = stringValue(testDictionary, "KeyID");
     1371
     1372        TestController::singleton().setFraudPreventionValuesForTesting(secretToken, unlinkableToken, signature, keyID);
     1373        return nullptr;
     1374    }
     1375
    13651376    if (WKStringIsEqualToUTF8CString(messageName, "SyncLocalStorage")) {
    13661377        TestController::singleton().syncLocalStorage();
Note: See TracChangeset for help on using the changeset viewer.