Diff
Modified: trunk/Source/WebKit/ChangeLog (281960 => 281961)
--- trunk/Source/WebKit/ChangeLog 2021-09-02 22:44:04 UTC (rev 281960)
+++ trunk/Source/WebKit/ChangeLog 2021-09-02 23:03:37 UTC (rev 281961)
@@ -1,3 +1,18 @@
+2021-09-02 Alex Christensen <achristen...@webkit.org>
+
+ Move PrivateClickMeasurementManager and PrivateClickMeasurementNetworkLoader into PrivateClickMeasurement directory
+ https://bugs.webkit.org/show_bug.cgi?id=229835
+
+ Reviewed by Tim Horton.
+
+ * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManager.cpp: Renamed from Source/WebKit/NetworkProcess/PrivateClickMeasurementManager.cpp.
+ (WebKit::PrivateClickMeasurementManager::fireConversionRequestImpl):
+ * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManager.h: Renamed from Source/WebKit/NetworkProcess/PrivateClickMeasurementManager.h.
+ * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementNetworkLoader.cpp: Renamed from Source/WebKit/NetworkProcess/PrivateClickMeasurementNetworkLoader.cpp.
+ * NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementNetworkLoader.h: Renamed from Source/WebKit/NetworkProcess/PrivateClickMeasurementNetworkLoader.h.
+ * Sources.txt:
+ * WebKit.xcodeproj/project.pbxproj:
+
2021-09-02 Per Arne <pvol...@apple.com>
[iOS] Gather logs for IOKit class
Added: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManager.cpp (0 => 281961)
--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManager.cpp (rev 0)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManager.cpp 2021-09-02 23:03:37 UTC (rev 281961)
@@ -0,0 +1,567 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PrivateClickMeasurementManager.h"
+
+#include "Logging.h"
+#include "NetworkSession.h"
+#include "PrivateClickMeasurementDebugInfo.h"
+#include <_javascript_Core/ConsoleTypes.h>
+#include <WebCore/FetchOptions.h>
+#include <WebCore/FormData.h>
+#include <WebCore/HTTPHeaderValues.h>
+#include <WebCore/ResourceError.h>
+#include <WebCore/ResourceRequest.h>
+#include <WebCore/ResourceResponse.h>
+#include <WebCore/RuntimeApplicationChecks.h>
+#include <WebCore/RuntimeEnabledFeatures.h>
+#include <pal/crypto/CryptoDigest.h>
+#include <wtf/CryptographicallyRandomNumber.h>
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebKit {
+using namespace WebCore;
+
+using SourceSite = PrivateClickMeasurement::SourceSite;
+using AttributionDestinationSite = PrivateClickMeasurement::AttributionDestinationSite;
+using AttributionTriggerData = PrivateClickMeasurement::AttributionTriggerData;
+using EphemeralSourceNonce = PrivateClickMeasurement::EphemeralSourceNonce;
+
+constexpr Seconds debugModeSecondsUntilSend { 10_s };
+
+PrivateClickMeasurementManager::PrivateClickMeasurementManager(UniqueRef<PCM::Client>&& client, const String& storageDirectory)
+ : m_firePendingAttributionRequestsTimer(*this, &PrivateClickMeasurementManager::firePendingAttributionRequests)
+ , m_storageDirectory(storageDirectory)
+ , m_client(WTFMove(client))
+{
+ // We should send any pending attributions on session-start in case their
+ // send delay has expired while the session was closed. Waiting 5 seconds accounts for the
+ // delay in database startup.
+ startTimer(5_s);
+}
+
+void PrivateClickMeasurementManager::storeUnattributed(PrivateClickMeasurement&& measurement)
+{
+ if (!featureEnabled())
+ return;
+
+ clearExpired();
+
+ 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.
+ getTokenPublicKey(WTFMove(measurementCopy), PrivateClickMeasurement::AttributionReportEndpoint::Source, PrivateClickMeasurement::PcmDataCarried::PersonallyIdentifiable, [weakThis = makeWeakPtr(*this), this] (PrivateClickMeasurement&& measurement, const String& publicKeyBase64URL) {
+ if (!weakThis)
+ return;
+
+ if (publicKeyBase64URL.isEmpty())
+ return;
+
+ if (m_fraudPreventionValuesForTesting)
+ measurement.setSourceUnlinkableTokenValue(m_fraudPreventionValuesForTesting->unlinkableToken);
+#if PLATFORM(COCOA)
+ else {
+ if (auto errorMessage = measurement.calculateAndUpdateSourceUnlinkableToken(publicKeyBase64URL)) {
+ RELEASE_LOG_INFO(PrivateClickMeasurement, "Got the following error in calculateAndUpdateSourceUnlinkableToken(): '%{public}s", errorMessage->utf8().data());
+ m_client->broadcastConsoleMessage(MessageLevel::Error, makeString("[Private Click Measurement] "_s, *errorMessage));
+ return;
+ }
+ }
+#endif
+
+ getSignedUnlinkableToken(WTFMove(measurement));
+ return;
+ });
+ }
+
+ m_client->broadcastConsoleMessage(MessageLevel::Log, "[Private Click Measurement] Storing a click."_s);
+
+ insertPrivateClickMeasurement(WTFMove(measurement), PrivateClickMeasurementAttributionType::Unattributed);
+}
+
+static NetworkLoadParameters generateNetworkLoadParameters(URL&& url, const String& httpMethod, RefPtr<JSON::Object>&& jsonPayload, PrivateClickMeasurement::PcmDataCarried dataTypeCarried, bool isDebugModeEnabled)
+{
+ ResourceRequest request { WTFMove(url) };
+ request.setHTTPMethod(httpMethod);
+ request.setHTTPHeaderField(HTTPHeaderName::CacheControl, WebCore::HTTPHeaderValues::maxAge0());
+ if (jsonPayload) {
+ request.setHTTPContentType(WebCore::HTTPHeaderValues::applicationJSONContentType());
+ request.setHTTPBody(WebCore::FormData::create(jsonPayload->toJSONString().utf8().data()));
+ }
+
+ NetworkLoadParameters loadParameters;
+ loadParameters.request = request;
+ loadParameters.parentPID = presentingApplicationPID();
+ loadParameters.storedCredentialsPolicy = StoredCredentialsPolicy::EphemeralStateless;
+ loadParameters.shouldClearReferrerOnHTTPSToHTTPRedirect = true;
+ loadParameters.pcmDataCarried = UNLIKELY(isDebugModeEnabled) ? PrivateClickMeasurement::PcmDataCarried::PersonallyIdentifiable : dataTypeCarried;
+
+ return loadParameters;
+}
+
+static NetworkLoadParameters generateNetworkLoadParametersForHttpPost(URL&& url, Ref<JSON::Object>&& jsonPayload, PrivateClickMeasurement::PcmDataCarried dataTypeCarried, bool isDebugModeEnabled)
+{
+ return generateNetworkLoadParameters(WTFMove(url), "POST"_s, WTFMove(jsonPayload), dataTypeCarried, isDebugModeEnabled);
+}
+
+static NetworkLoadParameters generateNetworkLoadParametersForHttpGet(URL&& url, PrivateClickMeasurement::PcmDataCarried dataTypeCarried, bool isDebugModeEnabled)
+{
+ return generateNetworkLoadParameters(WTFMove(url), "GET"_s, nullptr, dataTypeCarried, isDebugModeEnabled);
+}
+
+void PrivateClickMeasurementManager::getTokenPublicKey(PrivateClickMeasurement&& attribution, PrivateClickMeasurement::AttributionReportEndpoint attributionReportEndpoint, PrivateClickMeasurement::PcmDataCarried pcmDataCarried, Function<void(PrivateClickMeasurement&& attribution, const String& publicKeyBase64URL)>&& callback)
+{
+ if (!featureEnabled())
+ return;
+
+ auto tokenPublicKeyURL = attribution.tokenPublicKeyURL();
+ if (m_tokenPublicKeyURLForTesting) {
+ if (attributionReportEndpoint == PrivateClickMeasurement::AttributionReportEndpoint::Destination)
+ return;
+ tokenPublicKeyURL = *m_tokenPublicKeyURLForTesting;
+ // FIXME(225364)
+ pcmDataCarried = PrivateClickMeasurement::PcmDataCarried::NonPersonallyIdentifiable;
+ }
+
+ if (tokenPublicKeyURL.isEmpty() || !tokenPublicKeyURL.isValid())
+ return;
+
+ auto loadParameters = generateNetworkLoadParametersForHttpGet(WTFMove(tokenPublicKeyURL), pcmDataCarried, debugModeEnabled());
+
+ RELEASE_LOG_INFO(PrivateClickMeasurement, "About to fire a token public key request.");
+ m_client->broadcastConsoleMessage(MessageLevel::Log, "[Private Click Measurement] About to fire a token public key request."_s);
+
+ m_client->loadFromNetwork(WTFMove(loadParameters), [weakThis = makeWeakPtr(*this), this, attribution = WTFMove(attribution), callback = WTFMove(callback)] (auto& error, auto& response, auto& jsonObject) mutable {
+ if (!weakThis)
+ return;
+
+ if (!error.isNull()) {
+ m_client->broadcastConsoleMessage(MessageLevel::Error, makeString("[Private Click Measurement] Received error: '"_s, error.localizedDescription(), "' for token public key request."_s));
+ return;
+ }
+
+ if (!jsonObject) {
+ m_client->broadcastConsoleMessage(MessageLevel::Error, makeString("[Private Click Measurement] JSON response is empty for token public key request."_s));
+ return;
+ }
+
+ m_client->broadcastConsoleMessage(MessageLevel::Log, makeString("[Private Click Measurement] Got JSON response for token public key request."_s));
+
+ callback(WTFMove(attribution), jsonObject->getString("token_public_key"_s));
+ });
+
+}
+
+void PrivateClickMeasurementManager::getSignedUnlinkableToken(PrivateClickMeasurement&& measurement)
+{
+ if (!featureEnabled())
+ return;
+
+ // This is guaranteed to be close in time to the navigational click which makes it likely to be personally identifiable.
+ auto pcmDataCarried = PrivateClickMeasurement::PcmDataCarried::PersonallyIdentifiable;
+ auto tokenSignatureURL = measurement.tokenSignatureURL();
+ if (m_tokenSignatureURLForTesting) {
+ tokenSignatureURL = *m_tokenSignatureURLForTesting;
+ // FIXME(225364)
+ pcmDataCarried = PrivateClickMeasurement::PcmDataCarried::NonPersonallyIdentifiable;
+ }
+
+ if (tokenSignatureURL.isEmpty() || !tokenSignatureURL.isValid())
+ return;
+
+ auto loadParameters = generateNetworkLoadParametersForHttpPost(WTFMove(tokenSignatureURL), measurement.tokenSignatureJSON(), pcmDataCarried, debugModeEnabled());
+
+ RELEASE_LOG_INFO(PrivateClickMeasurement, "About to fire a unlinkable token signing request.");
+ m_client->broadcastConsoleMessage(MessageLevel::Log, "[Private Click Measurement] About to fire a unlinkable token signing request."_s);
+
+ m_client->loadFromNetwork(WTFMove(loadParameters), [weakThis = makeWeakPtr(*this), this, measurement = WTFMove(measurement)] (auto& error, auto& response, auto& jsonObject) mutable {
+ if (!weakThis)
+ return;
+
+ if (!error.isNull()) {
+ m_client->broadcastConsoleMessage(MessageLevel::Error, makeString("[Private Click Measurement] Received error: '"_s, error.localizedDescription(), "' for secret token signing request."_s));
+ return;
+ }
+
+ if (!jsonObject) {
+ m_client->broadcastConsoleMessage(MessageLevel::Error, makeString("[Private Click Measurement] JSON response is empty for token signing request."_s));
+ return;
+ }
+
+ auto signatureBase64URL = jsonObject->getString("unlinkable_token"_s);
+ if (signatureBase64URL.isEmpty()) {
+ m_client->broadcastConsoleMessage(MessageLevel::Error, makeString("[Private Click Measurement] JSON response doesn't have the key 'unlinkable_token' for token signing request."_s));
+ return;
+ }
+ // FIX NOW!
+ if (m_fraudPreventionValuesForTesting)
+ measurement.setSourceSecretToken({ m_fraudPreventionValuesForTesting->secretToken, m_fraudPreventionValuesForTesting->signature, m_fraudPreventionValuesForTesting->keyID });
+#if PLATFORM(COCOA)
+ else {
+ if (auto errorMessage = measurement.calculateAndUpdateSourceSecretToken(signatureBase64URL)) {
+ RELEASE_LOG_INFO(PrivateClickMeasurement, "Got the following error in calculateAndUpdateSourceSecretToken(): '%{public}s", errorMessage->utf8().data());
+ m_client->broadcastConsoleMessage(MessageLevel::Error, makeString("[Private Click Measurement] "_s, *errorMessage));
+ return;
+ }
+ }
+#endif
+
+ m_client->broadcastConsoleMessage(MessageLevel::Log, "[Private Click Measurement] Storing a secret token."_s);
+
+ insertPrivateClickMeasurement(WTFMove(measurement), PrivateClickMeasurementAttributionType::Unattributed);
+ });
+
+}
+
+void PrivateClickMeasurementManager::insertPrivateClickMeasurement(PrivateClickMeasurement&& measurement, PrivateClickMeasurementAttributionType type)
+{
+ if (m_isRunningEphemeralMeasurementTest)
+ measurement.setEphemeral(PrivateClickMeasurementAttributionEphemeral::Yes);
+ if (measurement.isEphemeral()) {
+ m_ephemeralMeasurement = WTFMove(measurement);
+ return;
+ }
+ store().insertPrivateClickMeasurement(WTFMove(measurement), type);
+}
+
+void PrivateClickMeasurementManager::handleAttribution(AttributionTriggerData&& attributionTriggerData, const URL& requestURL, const WebCore::ResourceRequest& redirectRequest)
+{
+ if (!featureEnabled())
+ return;
+
+ RegistrableDomain redirectDomain { redirectRequest.url() };
+ auto& firstPartyURL = redirectRequest.firstPartyForCookies();
+
+ if (!redirectDomain.matches(requestURL)) {
+ m_client->broadcastConsoleMessage(MessageLevel::Warning, "[Private Click Measurement] Triggering event was not accepted because the HTTP redirect was not same-site."_s);
+ return;
+ }
+
+ if (redirectDomain.matches(firstPartyURL)) {
+ m_client->broadcastConsoleMessage(MessageLevel::Warning, "[Private Click Measurement] Triggering event was not accepted because it was requested in an HTTP redirect that is same-site as the first-party."_s);
+ return;
+ }
+
+ m_client->broadcastConsoleMessage(MessageLevel::Log, "[Private Click Measurement] Triggering event accepted."_s);
+
+ attribute(SourceSite { WTFMove(redirectDomain) }, AttributionDestinationSite { firstPartyURL }, WTFMove(attributionTriggerData));
+}
+
+void PrivateClickMeasurementManager::startTimer(Seconds seconds)
+{
+ m_firePendingAttributionRequestsTimer.startOneShot(m_isRunningTest ? 0_s : seconds);
+}
+
+void PrivateClickMeasurementManager::attribute(const SourceSite& sourceSite, const AttributionDestinationSite& destinationSite, AttributionTriggerData&& attributionTriggerData)
+{
+ if (!featureEnabled())
+ return;
+
+ if (m_ephemeralMeasurement) {
+ // Ephemeral measurement can only have one pending click.
+ if (m_ephemeralMeasurement->sourceSite() != sourceSite)
+ return;
+ if (m_ephemeralMeasurement->destinationSite() != destinationSite)
+ return;
+ }
+
+ store().attributePrivateClickMeasurement(sourceSite, destinationSite, WTFMove(attributionTriggerData), std::exchange(m_ephemeralMeasurement, std::nullopt), [this, weakThis = makeWeakPtr(*this)] (auto attributionSecondsUntilSendData, auto debugInfo) {
+ if (!weakThis)
+ return;
+
+ if (!attributionSecondsUntilSendData)
+ return;
+
+ if (UNLIKELY(debugModeEnabled())) {
+ for (auto& message : debugInfo.messages)
+ m_client->broadcastConsoleMessage(message.messageLevel, message.message);
+ }
+
+ if (attributionSecondsUntilSendData.value().hasValidSecondsUntilSendValues()) {
+ auto minSecondsUntilSend = attributionSecondsUntilSendData.value().minSecondsUntilSend();
+
+ ASSERT(minSecondsUntilSend);
+ if (!minSecondsUntilSend)
+ return;
+
+ if (m_firePendingAttributionRequestsTimer.isActive() && m_firePendingAttributionRequestsTimer.nextFireInterval() < *minSecondsUntilSend)
+ return;
+
+ if (UNLIKELY(debugModeEnabled())) {
+ m_client->broadcastConsoleMessage(MessageLevel::Log, makeString("[Private Click Measurement] Setting timer for firing attribution request to the debug mode timeout of "_s, debugModeSecondsUntilSend.seconds(), " seconds where the regular timeout would have been "_s, minSecondsUntilSend.value().seconds(), " seconds."_s));
+ minSecondsUntilSend = debugModeSecondsUntilSend;
+ } else
+ m_client->broadcastConsoleMessage(MessageLevel::Log, makeString("[Private Click Measurement] Setting timer for firing attribution request to the timeout of "_s, minSecondsUntilSend.value().seconds(), " seconds."_s));
+
+ startTimer(*minSecondsUntilSend);
+ }
+ });
+}
+
+void PrivateClickMeasurementManager::fireConversionRequest(const PrivateClickMeasurement& attribution, PrivateClickMeasurement::AttributionReportEndpoint attributionReportEndpoint)
+{
+ if (!featureEnabled())
+ return;
+
+ if (!attribution.sourceUnlinkableToken()) {
+ fireConversionRequestImpl(attribution, attributionReportEndpoint);
+ return;
+ }
+
+ auto attributionCopy = attribution;
+ // This happens out of webpage context and with a long delay and is thus unlikely to be personally identifiable.
+ getTokenPublicKey(WTFMove(attributionCopy), attributionReportEndpoint, PrivateClickMeasurement::PcmDataCarried::NonPersonallyIdentifiable, [weakThis = makeWeakPtr(*this), this, attributionReportEndpoint] (PrivateClickMeasurement&& attribution, const String& publicKeyBase64URL) {
+ if (!weakThis)
+ return;
+
+ auto publicKeyData = base64URLDecode(publicKeyBase64URL);
+ if (!publicKeyData)
+ return;
+
+ auto crypto = PAL::CryptoDigest::create(PAL::CryptoDigest::Algorithm::SHA_256);
+ crypto->addBytes(publicKeyData->data(), publicKeyData->size());
+ auto publicKeyDataHash = crypto->computeHash();
+
+ auto keyID = base64URLEncodeToString(publicKeyDataHash.data(), publicKeyDataHash.size());
+ if (keyID != attribution.sourceUnlinkableToken()->keyIDBase64URL)
+ return;
+
+ fireConversionRequestImpl(attribution, attributionReportEndpoint);
+ });
+}
+
+void PrivateClickMeasurementManager::fireConversionRequestImpl(const PrivateClickMeasurement& attribution, PrivateClickMeasurement::AttributionReportEndpoint attributionReportEndpoint)
+{
+ URL attributionURL;
+ switch (attributionReportEndpoint) {
+ case PrivateClickMeasurement::AttributionReportEndpoint::Source:
+ attributionURL = m_attributionReportTestConfig ? m_attributionReportTestConfig->attributionReportSourceURL : attribution.attributionReportSourceURL();
+ break;
+ case PrivateClickMeasurement::AttributionReportEndpoint::Destination:
+ attributionURL = m_attributionReportTestConfig ? m_attributionReportTestConfig->attributionReportAttributeOnURL : attribution.attributionReportAttributeOnURL();
+ }
+
+ if (attributionURL.isEmpty() || !attributionURL.isValid())
+ return;
+
+ auto loadParameters = generateNetworkLoadParametersForHttpPost(WTFMove(attributionURL), attribution.attributionReportJSON(), PrivateClickMeasurement::PcmDataCarried::NonPersonallyIdentifiable, debugModeEnabled());
+
+ RELEASE_LOG_INFO(PrivateClickMeasurement, "About to fire an attribution request.");
+ m_client->broadcastConsoleMessage(MessageLevel::Log, "[Private Click Measurement] About to fire an attribution request."_s);
+
+ m_client->loadFromNetwork(WTFMove(loadParameters), [weakThis = makeWeakPtr(*this), this](auto& error, auto& response, auto&) {
+ if (!weakThis)
+ return;
+
+ if (!error.isNull())
+ m_client->broadcastConsoleMessage(MessageLevel::Error, makeString("[Private Click Measurement] Received error: '"_s, error.localizedDescription(), "' for ad click attribution request."_s));
+ });
+}
+
+void PrivateClickMeasurementManager::clearSentAttribution(PrivateClickMeasurement&& sentConversion, PrivateClickMeasurement::AttributionReportEndpoint attributionReportEndpoint)
+{
+ if (!featureEnabled())
+ return;
+
+ store().clearSentAttribution(WTFMove(sentConversion), attributionReportEndpoint);
+}
+
+void PrivateClickMeasurementManager::firePendingAttributionRequests()
+{
+ if (!featureEnabled())
+ return;
+
+ store().allAttributedPrivateClickMeasurement([this, weakThis = makeWeakPtr(*this)] (auto&& attributions) {
+ if (!weakThis)
+ return;
+ auto nextTimeToFire = Seconds::infinity();
+ bool hasSentAttribution = false;
+
+ for (auto& attribution : attributions) {
+ std::optional<WallTime> earliestTimeToSend = attribution.timesToSend().earliestTimeToSend();
+ std::optional<WebCore::PrivateClickMeasurement::AttributionReportEndpoint> attributionReportEndpoint = attribution.timesToSend().attributionReportEndpoint();
+
+ if (!earliestTimeToSend || !attributionReportEndpoint) {
+ ASSERT_NOT_REACHED();
+ continue;
+ }
+
+ auto now = WallTime::now();
+ if (*earliestTimeToSend <= now || m_isRunningTest || debugModeEnabled()) {
+ if (hasSentAttribution) {
+ // We've already sent an attribution this round. We should send additional overdue attributions at
+ // a random time between 15 and 30 minutes to avoid a burst of simultaneous attributions. If debug
+ // mode is enabled, this should be much shorter for easy testing.
+ auto interval = debugModeEnabled() ? debugModeSecondsUntilSend : 15_min + Seconds(cryptographicallyRandomNumber() % 900);
+ startTimer(interval);
+ return;
+ }
+
+ auto laterTimeToSend = attribution.timesToSend().latestTimeToSend();
+ fireConversionRequest(attribution, *attributionReportEndpoint);
+ clearSentAttribution(WTFMove(attribution), *attributionReportEndpoint);
+ hasSentAttribution = true;
+
+ // Update nextTimeToFire in case the later report time for this attribution is sooner than the scheduled next time to fire.
+ // Or, if debug mode is enabled, we should send the second report on a much shorter delay for easy testing.
+ if (laterTimeToSend)
+ nextTimeToFire = debugModeEnabled() ? debugModeSecondsUntilSend : std::min(nextTimeToFire, laterTimeToSend.value().secondsSinceEpoch());
+
+ continue;
+ }
+
+ auto seconds = *earliestTimeToSend - now;
+ nextTimeToFire = std::min(nextTimeToFire, seconds);
+
+ // Attributions are sorted by earliestTimeToSend, so the first time we hit this there can be no further attributions
+ // due for reporting, and nextTimeToFire is the minimum earliestTimeToSend value for any pending attribution.
+ break;
+ }
+
+ if (nextTimeToFire < Seconds::infinity())
+ startTimer(nextTimeToFire);
+ });
+}
+
+void PrivateClickMeasurementManager::clear(CompletionHandler<void()>&& completionHandler)
+{
+ m_firePendingAttributionRequestsTimer.stop();
+ m_ephemeralMeasurement = std::nullopt;
+ m_isRunningEphemeralMeasurementTest = false;
+
+ if (!featureEnabled())
+ return completionHandler();
+
+ store().clearPrivateClickMeasurement(WTFMove(completionHandler));
+}
+
+void PrivateClickMeasurementManager::clearForRegistrableDomain(const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
+{
+ if (!featureEnabled())
+ return completionHandler();
+
+ store().clearPrivateClickMeasurementForRegistrableDomain(domain, WTFMove(completionHandler));
+}
+
+void PrivateClickMeasurementManager::clearExpired()
+{
+ if (!featureEnabled())
+ return;
+
+ store().clearExpiredPrivateClickMeasurement();
+}
+
+void PrivateClickMeasurementManager::toStringForTesting(CompletionHandler<void(String)>&& completionHandler) const
+{
+ if (!featureEnabled())
+ return completionHandler("\nNo stored Private Click Measurement data.\n"_s);
+
+ store().privateClickMeasurementToStringForTesting(WTFMove(completionHandler));
+}
+
+void PrivateClickMeasurementManager::setTokenPublicKeyURLForTesting(URL&& testURL)
+{
+ if (testURL.isEmpty())
+ return;
+ m_tokenPublicKeyURLForTesting = WTFMove(testURL);
+}
+
+void PrivateClickMeasurementManager::setTokenSignatureURLForTesting(URL&& testURL)
+{
+ if (testURL.isEmpty())
+ m_tokenSignatureURLForTesting = { };
+ else
+ m_tokenSignatureURLForTesting = WTFMove(testURL);
+}
+
+void PrivateClickMeasurementManager::setAttributionReportURLsForTesting(URL&& sourceURL, URL&& destinationURL)
+{
+ if (sourceURL.isEmpty() || destinationURL.isEmpty())
+ m_attributionReportTestConfig = std::nullopt;
+ else
+ m_attributionReportTestConfig = AttributionReportTestConfig { WTFMove(sourceURL), WTFMove(destinationURL) };
+}
+
+void PrivateClickMeasurementManager::markAllUnattributedAsExpiredForTesting()
+{
+ if (!featureEnabled())
+ return;
+
+ store().markAllUnattributedPrivateClickMeasurementAsExpiredForTesting();
+}
+
+void PrivateClickMeasurementManager::setPCMFraudPreventionValuesForTesting(String&& unlinkableToken, String&& secretToken, String&& signature, String&& keyID)
+{
+ if (unlinkableToken.isEmpty() || secretToken.isEmpty() || signature.isEmpty() || keyID.isEmpty())
+ return;
+ m_fraudPreventionValuesForTesting = TestingFraudPreventionValues { WTFMove(unlinkableToken), WTFMove(secretToken), WTFMove(signature), WTFMove(keyID) };
+}
+
+bool PrivateClickMeasurementManager::featureEnabled() const
+{
+ return m_client->featureEnabled();
+}
+
+bool PrivateClickMeasurementManager::debugModeEnabled() const
+{
+ return m_client->debugModeEnabled();
+}
+
+void PrivateClickMeasurementManager::markAttributedPrivateClickMeasurementsAsExpiredForTesting(CompletionHandler<void()>&& completionHandler)
+{
+ if (!featureEnabled())
+ return completionHandler();
+
+ store().markAttributedPrivateClickMeasurementsAsExpiredForTesting(WTFMove(completionHandler));
+}
+
+PCM::Store& PrivateClickMeasurementManager::store()
+{
+ if (!m_store)
+ m_store = PCM::Store::create(m_storageDirectory);
+ return *m_store;
+}
+
+const PCM::Store& PrivateClickMeasurementManager::store() const
+{
+ if (!m_store)
+ m_store = PCM::Store::create(m_storageDirectory);
+ return *m_store;
+}
+
+void PrivateClickMeasurementManager::destroyStoreForTesting(CompletionHandler<void()>&& completionHandler)
+{
+ if (!m_store)
+ return completionHandler();
+ m_store->close([weakThis = makeWeakPtr(*this), completionHandler = WTFMove(completionHandler)] () mutable {
+ if (weakThis)
+ weakThis->m_store = nullptr;
+ return completionHandler();
+ });
+}
+
+} // namespace WebKit
Added: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManager.h (0 => 281961)
--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManager.h (rev 0)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManager.h 2021-09-02 23:03:37 UTC (rev 281961)
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "NetworkLoadParameters.h"
+#include "NetworkProcess.h"
+#include "PrivateClickMeasurementClient.h"
+#include "PrivateClickMeasurementStore.h"
+#include <WebCore/PrivateClickMeasurement.h>
+#include <WebCore/RegistrableDomain.h>
+#include <WebCore/ResourceError.h>
+#include <WebCore/ResourceResponse.h>
+#include <WebCore/Timer.h>
+#include <pal/SessionID.h>
+#include <wtf/CompletionHandler.h>
+#include <wtf/JSONValues.h>
+#include <wtf/WeakPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebKit {
+
+enum class PrivateClickMeasurementAttributionType : bool { Unattributed, Attributed };
+
+class PrivateClickMeasurementManager : public CanMakeWeakPtr<PrivateClickMeasurementManager> {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+
+ using AttributionDestinationSite = WebCore::PrivateClickMeasurement::AttributionDestinationSite;
+ using AttributionTriggerData = WebCore::PrivateClickMeasurement::AttributionTriggerData;
+ using PrivateClickMeasurement = WebCore::PrivateClickMeasurement;
+ using RegistrableDomain = WebCore::RegistrableDomain;
+ using SourceSite = WebCore::PrivateClickMeasurement::SourceSite;
+ explicit PrivateClickMeasurementManager(UniqueRef<PCM::Client>&&, const String& storageDirectory);
+
+ void storeUnattributed(PrivateClickMeasurement&&);
+ void handleAttribution(AttributionTriggerData&&, const URL& requestURL, const WebCore::ResourceRequest& redirectRequest);
+ void clear(CompletionHandler<void()>&&);
+ void clearForRegistrableDomain(const RegistrableDomain&, CompletionHandler<void()>&&);
+ void toStringForTesting(CompletionHandler<void(String)>&&) const;
+ void setOverrideTimerForTesting(bool value) { m_isRunningTest = value; }
+ void setTokenPublicKeyURLForTesting(URL&&);
+ void setTokenSignatureURLForTesting(URL&&);
+ void setAttributionReportURLsForTesting(URL&& sourceURL, URL&& destinationURL);
+ void markAllUnattributedAsExpiredForTesting();
+ void markAttributedPrivateClickMeasurementsAsExpiredForTesting(CompletionHandler<void()>&&);
+ void setEphemeralMeasurementForTesting(bool value) { m_isRunningEphemeralMeasurementTest = value; }
+ void setPCMFraudPreventionValuesForTesting(String&& unlinkableToken, String&& secretToken, String&& signature, String&& keyID);
+ void startTimer(Seconds);
+
+ void destroyStoreForTesting(CompletionHandler<void()>&&);
+
+ PCM::Store& store();
+ const PCM::Store& store() const;
+
+private:
+ void getTokenPublicKey(PrivateClickMeasurement&&, PrivateClickMeasurement::AttributionReportEndpoint, PrivateClickMeasurement::PcmDataCarried, Function<void(PrivateClickMeasurement&& attribution, const String& publicKeyBase64URL)>&&);
+ void getSignedUnlinkableToken(PrivateClickMeasurement&&);
+ void insertPrivateClickMeasurement(PrivateClickMeasurement&&, PrivateClickMeasurementAttributionType);
+ void clearSentAttribution(PrivateClickMeasurement&&, PrivateClickMeasurement::AttributionReportEndpoint);
+ void attribute(const SourceSite&, const AttributionDestinationSite&, AttributionTriggerData&&);
+ void fireConversionRequest(const PrivateClickMeasurement&, PrivateClickMeasurement::AttributionReportEndpoint);
+ void fireConversionRequestImpl(const PrivateClickMeasurement&, PrivateClickMeasurement::AttributionReportEndpoint);
+ void firePendingAttributionRequests();
+ void clearExpired();
+ bool featureEnabled() const;
+ bool debugModeEnabled() const;
+
+ std::optional<PrivateClickMeasurement> m_ephemeralMeasurement;
+ WebCore::Timer m_firePendingAttributionRequestsTimer;
+ bool m_isRunningTest { false };
+ bool m_isRunningEphemeralMeasurementTest { false };
+ std::optional<URL> m_tokenPublicKeyURLForTesting;
+ std::optional<URL> m_tokenSignatureURLForTesting;
+ mutable RefPtr<PCM::Store> m_store;
+ String m_storageDirectory;
+ UniqueRef<PCM::Client> m_client;
+
+ struct AttributionReportTestConfig {
+ URL attributionReportSourceURL;
+ URL attributionReportAttributeOnURL;
+ };
+
+ std::optional<AttributionReportTestConfig> m_attributionReportTestConfig;
+
+ struct TestingFraudPreventionValues {
+ String unlinkableToken;
+ String secretToken;
+ String signature;
+ String keyID;
+ };
+
+ std::optional<TestingFraudPreventionValues> m_fraudPreventionValuesForTesting;
+};
+
+} // namespace WebKit
Added: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementNetworkLoader.cpp (0 => 281961)
--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementNetworkLoader.cpp (rev 0)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementNetworkLoader.cpp 2021-09-02 23:03:37 UTC (rev 281961)
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PrivateClickMeasurementNetworkLoader.h"
+
+#include "NetworkLoad.h"
+#include "NetworkSession.h"
+#include <WebCore/MIMETypeRegistry.h>
+#include <WebCore/TextResourceDecoder.h>
+
+#include <wtf/JSONValues.h>
+
+namespace WebKit {
+
+using namespace WebCore;
+
+void PrivateClickMeasurementNetworkLoader::start(NetworkSession& session, NetworkLoadParameters&& parameters, Callback&& completionHandler)
+{
+ auto loader = std::unique_ptr<PrivateClickMeasurementNetworkLoader>(new PrivateClickMeasurementNetworkLoader(session, WTFMove(parameters), WTFMove(completionHandler)));
+ session.addPrivateClickMeasurementNetworkLoader(WTFMove(loader));
+}
+
+PrivateClickMeasurementNetworkLoader::PrivateClickMeasurementNetworkLoader(NetworkSession& session, NetworkLoadParameters&& parameters, Callback&& completionHandler)
+ : m_session(makeWeakPtr(session))
+ , m_completionHandler(WTFMove(completionHandler))
+{
+ m_networkLoad = makeUnique<NetworkLoad>(*this, nullptr, WTFMove(parameters), *m_session);
+ m_networkLoad->start();
+}
+
+PrivateClickMeasurementNetworkLoader::~PrivateClickMeasurementNetworkLoader()
+{
+ cancel();
+}
+
+void PrivateClickMeasurementNetworkLoader::fail(ResourceError&& error)
+{
+ if (!m_completionHandler)
+ return;
+
+ m_completionHandler(WTFMove(error), { }, nullptr);
+ didComplete();
+}
+
+void PrivateClickMeasurementNetworkLoader::cancel()
+{
+ fail(ResourceError { ResourceError::Type::Cancellation });
+}
+
+void PrivateClickMeasurementNetworkLoader::willSendRedirectedRequest(ResourceRequest&&, ResourceRequest&&, ResourceResponse&&)
+{
+ cancel();
+}
+
+void PrivateClickMeasurementNetworkLoader::didReceiveResponse(ResourceResponse&& response, ResponseCompletionHandler&& completionHandler)
+{
+ if (!MIMETypeRegistry::isSupportedJSONMIMEType(response.mimeType())) {
+ fail({ errorDomainWebKitInternal, 0, response.url(), "MIME Type is not a JSON MIME type"_s });
+ completionHandler(PolicyAction::Ignore);
+ return;
+ }
+
+ m_response = WTFMove(response);
+ completionHandler(PolicyAction::Use);
+}
+
+void PrivateClickMeasurementNetworkLoader::didReceiveBuffer(Ref<SharedBuffer>&& buffer, int reportedEncodedDataLength)
+{
+ if (!m_decoder)
+ m_decoder = TextResourceDecoder::create("application/json"_s, m_response.textEncodingName().isEmpty() ? WebCore::TextEncoding("UTF-8") : WebCore::TextEncoding(m_response.textEncodingName()));
+
+ if (auto size = buffer->size())
+ m_jsonString.append(m_decoder->decode(buffer->data(), size));
+}
+
+void PrivateClickMeasurementNetworkLoader::didFinishLoading(const WebCore::NetworkLoadMetrics&)
+{
+ if (m_decoder)
+ m_jsonString.append(m_decoder->flush());
+
+ if (auto jsonValue = JSON::Value::parseJSON(m_jsonString.toString()))
+ m_completionHandler({ }, m_response, jsonValue->asObject());
+ else
+ m_completionHandler({ }, m_response, nullptr);
+
+ didComplete();
+}
+
+void PrivateClickMeasurementNetworkLoader::didFailLoading(const ResourceError& error)
+{
+ fail(ResourceError(error));
+}
+
+void PrivateClickMeasurementNetworkLoader::didComplete()
+{
+ m_networkLoad = nullptr;
+ if (m_session)
+ m_session->removePrivateClickMeasurementNetworkLoader(this);
+}
+
+} // namespace WebKit
Added: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementNetworkLoader.h (0 => 281961)
--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementNetworkLoader.h (rev 0)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementNetworkLoader.h 2021-09-02 23:03:37 UTC (rev 281961)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "NetworkLoad.h"
+#include "NetworkLoadClient.h"
+#include "NetworkLoadParameters.h"
+#include <WebCore/TextResourceDecoder.h>
+#include <wtf/CompletionHandler.h>
+#include <wtf/WeakPtr.h>
+
+namespace WebKit {
+
+class NetworkSession;
+
+class PrivateClickMeasurementNetworkLoader final : public NetworkLoadClient {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ using Callback = CompletionHandler<void(const WebCore::ResourceError&, const WebCore::ResourceResponse&, const RefPtr<JSON::Object>&)>;
+ static void start(NetworkSession&, NetworkLoadParameters&&, Callback&&);
+
+ ~PrivateClickMeasurementNetworkLoader();
+
+private:
+ PrivateClickMeasurementNetworkLoader(NetworkSession&, NetworkLoadParameters&&, Callback&&);
+
+ // NetworkLoadClient.
+ void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) final { }
+ bool isSynchronous() const final { return false; }
+ bool isAllowedToAskUserForCredentials() const final { return false; }
+ void willSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&& redirectResponse) final;
+ void didReceiveResponse(WebCore::ResourceResponse&&, ResponseCompletionHandler&&) final;
+ void didReceiveBuffer(Ref<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) final;
+ void didFinishLoading(const WebCore::NetworkLoadMetrics&) final;
+ void didFailLoading(const WebCore::ResourceError&) final;
+
+ void fail(WebCore::ResourceError&&);
+ void cancel();
+ void didComplete();
+
+ WeakPtr<NetworkSession> m_session;
+ std::unique_ptr<NetworkLoad> m_networkLoad;
+ Callback m_completionHandler;
+
+ WebCore::ResourceResponse m_response;
+ RefPtr<WebCore::TextResourceDecoder> m_decoder;
+ StringBuilder m_jsonString;
+};
+
+} // namespace WebKit
Deleted: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementManager.cpp (281960 => 281961)
--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementManager.cpp 2021-09-02 22:44:04 UTC (rev 281960)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementManager.cpp 2021-09-02 23:03:37 UTC (rev 281961)
@@ -1,568 +0,0 @@
-/*
- * Copyright (C) 2019 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "PrivateClickMeasurementManager.h"
-
-#include "Logging.h"
-#include "NetworkSession.h"
-#include "PrivateClickMeasurementDebugInfo.h"
-#include <_javascript_Core/ConsoleTypes.h>
-#include <WebCore/FetchOptions.h>
-#include <WebCore/FormData.h>
-#include <WebCore/HTTPHeaderValues.h>
-#include <WebCore/ResourceError.h>
-#include <WebCore/ResourceRequest.h>
-#include <WebCore/ResourceResponse.h>
-#include <WebCore/RuntimeApplicationChecks.h>
-#include <WebCore/RuntimeEnabledFeatures.h>
-#include <pal/crypto/CryptoDigest.h>
-#include <wtf/CryptographicallyRandomNumber.h>
-#include <wtf/text/StringBuilder.h>
-#include <wtf/text/StringHash.h>
-
-namespace WebKit {
-using namespace WebCore;
-
-using SourceSite = PrivateClickMeasurement::SourceSite;
-using AttributionDestinationSite = PrivateClickMeasurement::AttributionDestinationSite;
-using AttributionTriggerData = PrivateClickMeasurement::AttributionTriggerData;
-using EphemeralSourceNonce = PrivateClickMeasurement::EphemeralSourceNonce;
-
-constexpr Seconds debugModeSecondsUntilSend { 10_s };
-
-PrivateClickMeasurementManager::PrivateClickMeasurementManager(UniqueRef<PCM::Client>&& client, const String& storageDirectory)
- : m_firePendingAttributionRequestsTimer(*this, &PrivateClickMeasurementManager::firePendingAttributionRequests)
- , m_storageDirectory(storageDirectory)
- , m_client(WTFMove(client))
-{
- // We should send any pending attributions on session-start in case their
- // send delay has expired while the session was closed. Waiting 5 seconds accounts for the
- // delay in database startup.
- startTimer(5_s);
-}
-
-void PrivateClickMeasurementManager::storeUnattributed(PrivateClickMeasurement&& measurement)
-{
- if (!featureEnabled())
- return;
-
- clearExpired();
-
- 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.
- getTokenPublicKey(WTFMove(measurementCopy), PrivateClickMeasurement::AttributionReportEndpoint::Source, PrivateClickMeasurement::PcmDataCarried::PersonallyIdentifiable, [weakThis = makeWeakPtr(*this), this] (PrivateClickMeasurement&& measurement, const String& publicKeyBase64URL) {
- if (!weakThis)
- return;
-
- if (publicKeyBase64URL.isEmpty())
- return;
-
- if (m_fraudPreventionValuesForTesting)
- measurement.setSourceUnlinkableTokenValue(m_fraudPreventionValuesForTesting->unlinkableToken);
-#if PLATFORM(COCOA)
- else {
- if (auto errorMessage = measurement.calculateAndUpdateSourceUnlinkableToken(publicKeyBase64URL)) {
- RELEASE_LOG_INFO(PrivateClickMeasurement, "Got the following error in calculateAndUpdateSourceUnlinkableToken(): '%{public}s", errorMessage->utf8().data());
- m_client->broadcastConsoleMessage(MessageLevel::Error, makeString("[Private Click Measurement] "_s, *errorMessage));
- return;
- }
- }
-#endif
-
- getSignedUnlinkableToken(WTFMove(measurement));
- return;
- });
- }
-
- m_client->broadcastConsoleMessage(MessageLevel::Log, "[Private Click Measurement] Storing a click."_s);
-
- insertPrivateClickMeasurement(WTFMove(measurement), PrivateClickMeasurementAttributionType::Unattributed);
-}
-
-static NetworkLoadParameters generateNetworkLoadParameters(URL&& url, const String& httpMethod, RefPtr<JSON::Object>&& jsonPayload, PrivateClickMeasurement::PcmDataCarried dataTypeCarried, bool isDebugModeEnabled)
-{
- ResourceRequest request { WTFMove(url) };
- request.setHTTPMethod(httpMethod);
- request.setHTTPHeaderField(HTTPHeaderName::CacheControl, WebCore::HTTPHeaderValues::maxAge0());
- if (jsonPayload) {
- request.setHTTPContentType(WebCore::HTTPHeaderValues::applicationJSONContentType());
- request.setHTTPBody(WebCore::FormData::create(jsonPayload->toJSONString().utf8().data()));
- }
-
- NetworkLoadParameters loadParameters;
- loadParameters.request = request;
- loadParameters.parentPID = presentingApplicationPID();
- loadParameters.storedCredentialsPolicy = StoredCredentialsPolicy::EphemeralStateless;
- loadParameters.shouldClearReferrerOnHTTPSToHTTPRedirect = true;
- loadParameters.pcmDataCarried = UNLIKELY(isDebugModeEnabled) ? PrivateClickMeasurement::PcmDataCarried::PersonallyIdentifiable : dataTypeCarried;
-
- return loadParameters;
-}
-
-static NetworkLoadParameters generateNetworkLoadParametersForHttpPost(URL&& url, Ref<JSON::Object>&& jsonPayload, PrivateClickMeasurement::PcmDataCarried dataTypeCarried, bool isDebugModeEnabled)
-{
- return generateNetworkLoadParameters(WTFMove(url), "POST"_s, WTFMove(jsonPayload), dataTypeCarried, isDebugModeEnabled);
-}
-
-static NetworkLoadParameters generateNetworkLoadParametersForHttpGet(URL&& url, PrivateClickMeasurement::PcmDataCarried dataTypeCarried, bool isDebugModeEnabled)
-{
- return generateNetworkLoadParameters(WTFMove(url), "GET"_s, nullptr, dataTypeCarried, isDebugModeEnabled);
-}
-
-void PrivateClickMeasurementManager::getTokenPublicKey(PrivateClickMeasurement&& attribution, PrivateClickMeasurement::AttributionReportEndpoint attributionReportEndpoint, PrivateClickMeasurement::PcmDataCarried pcmDataCarried, Function<void(PrivateClickMeasurement&& attribution, const String& publicKeyBase64URL)>&& callback)
-{
- if (!featureEnabled())
- return;
-
- auto tokenPublicKeyURL = attribution.tokenPublicKeyURL();
- if (m_tokenPublicKeyURLForTesting) {
- if (attributionReportEndpoint == PrivateClickMeasurement::AttributionReportEndpoint::Destination)
- return;
- tokenPublicKeyURL = *m_tokenPublicKeyURLForTesting;
- // FIXME(225364)
- pcmDataCarried = PrivateClickMeasurement::PcmDataCarried::NonPersonallyIdentifiable;
- }
-
- if (tokenPublicKeyURL.isEmpty() || !tokenPublicKeyURL.isValid())
- return;
-
- auto loadParameters = generateNetworkLoadParametersForHttpGet(WTFMove(tokenPublicKeyURL), pcmDataCarried, debugModeEnabled());
-
- RELEASE_LOG_INFO(PrivateClickMeasurement, "About to fire a token public key request.");
- m_client->broadcastConsoleMessage(MessageLevel::Log, "[Private Click Measurement] About to fire a token public key request."_s);
-
- m_client->loadFromNetwork(WTFMove(loadParameters), [weakThis = makeWeakPtr(*this), this, attribution = WTFMove(attribution), callback = WTFMove(callback)] (auto& error, auto& response, auto& jsonObject) mutable {
- if (!weakThis)
- return;
-
- if (!error.isNull()) {
- m_client->broadcastConsoleMessage(MessageLevel::Error, makeString("[Private Click Measurement] Received error: '"_s, error.localizedDescription(), "' for token public key request."_s));
- return;
- }
-
- if (!jsonObject) {
- m_client->broadcastConsoleMessage(MessageLevel::Error, makeString("[Private Click Measurement] JSON response is empty for token public key request."_s));
- return;
- }
-
- m_client->broadcastConsoleMessage(MessageLevel::Log, makeString("[Private Click Measurement] Got JSON response for token public key request."_s));
-
- callback(WTFMove(attribution), jsonObject->getString("token_public_key"_s));
- });
-
-}
-
-void PrivateClickMeasurementManager::getSignedUnlinkableToken(PrivateClickMeasurement&& measurement)
-{
- if (!featureEnabled())
- return;
-
- // This is guaranteed to be close in time to the navigational click which makes it likely to be personally identifiable.
- auto pcmDataCarried = PrivateClickMeasurement::PcmDataCarried::PersonallyIdentifiable;
- auto tokenSignatureURL = measurement.tokenSignatureURL();
- if (m_tokenSignatureURLForTesting) {
- tokenSignatureURL = *m_tokenSignatureURLForTesting;
- // FIXME(225364)
- pcmDataCarried = PrivateClickMeasurement::PcmDataCarried::NonPersonallyIdentifiable;
- }
-
- if (tokenSignatureURL.isEmpty() || !tokenSignatureURL.isValid())
- return;
-
- auto loadParameters = generateNetworkLoadParametersForHttpPost(WTFMove(tokenSignatureURL), measurement.tokenSignatureJSON(), pcmDataCarried, debugModeEnabled());
-
- RELEASE_LOG_INFO(PrivateClickMeasurement, "About to fire a unlinkable token signing request.");
- m_client->broadcastConsoleMessage(MessageLevel::Log, "[Private Click Measurement] About to fire a unlinkable token signing request."_s);
-
- m_client->loadFromNetwork(WTFMove(loadParameters), [weakThis = makeWeakPtr(*this), this, measurement = WTFMove(measurement)] (auto& error, auto& response, auto& jsonObject) mutable {
- if (!weakThis)
- return;
-
- if (!error.isNull()) {
- m_client->broadcastConsoleMessage(MessageLevel::Error, makeString("[Private Click Measurement] Received error: '"_s, error.localizedDescription(), "' for secret token signing request."_s));
- return;
- }
-
- if (!jsonObject) {
- m_client->broadcastConsoleMessage(MessageLevel::Error, makeString("[Private Click Measurement] JSON response is empty for token signing request."_s));
- return;
- }
-
- auto signatureBase64URL = jsonObject->getString("unlinkable_token"_s);
- if (signatureBase64URL.isEmpty()) {
- m_client->broadcastConsoleMessage(MessageLevel::Error, makeString("[Private Click Measurement] JSON response doesn't have the key 'unlinkable_token' for token signing request."_s));
- return;
- }
- // FIX NOW!
- if (m_fraudPreventionValuesForTesting)
- measurement.setSourceSecretToken({ m_fraudPreventionValuesForTesting->secretToken, m_fraudPreventionValuesForTesting->signature, m_fraudPreventionValuesForTesting->keyID });
-#if PLATFORM(COCOA)
- else {
- if (auto errorMessage = measurement.calculateAndUpdateSourceSecretToken(signatureBase64URL)) {
- RELEASE_LOG_INFO(PrivateClickMeasurement, "Got the following error in calculateAndUpdateSourceSecretToken(): '%{public}s", errorMessage->utf8().data());
- m_client->broadcastConsoleMessage(MessageLevel::Error, makeString("[Private Click Measurement] "_s, *errorMessage));
- return;
- }
- }
-#endif
-
- m_client->broadcastConsoleMessage(MessageLevel::Log, "[Private Click Measurement] Storing a secret token."_s);
-
- insertPrivateClickMeasurement(WTFMove(measurement), PrivateClickMeasurementAttributionType::Unattributed);
- });
-
-}
-
-void PrivateClickMeasurementManager::insertPrivateClickMeasurement(PrivateClickMeasurement&& measurement, PrivateClickMeasurementAttributionType type)
-{
- if (m_isRunningEphemeralMeasurementTest)
- measurement.setEphemeral(PrivateClickMeasurementAttributionEphemeral::Yes);
- if (measurement.isEphemeral()) {
- m_ephemeralMeasurement = WTFMove(measurement);
- return;
- }
- store().insertPrivateClickMeasurement(WTFMove(measurement), type);
-}
-
-void PrivateClickMeasurementManager::handleAttribution(AttributionTriggerData&& attributionTriggerData, const URL& requestURL, const WebCore::ResourceRequest& redirectRequest)
-{
- if (!featureEnabled())
- return;
-
- RegistrableDomain redirectDomain { redirectRequest.url() };
- auto& firstPartyURL = redirectRequest.firstPartyForCookies();
-
- if (!redirectDomain.matches(requestURL)) {
- m_client->broadcastConsoleMessage(MessageLevel::Warning, "[Private Click Measurement] Triggering event was not accepted because the HTTP redirect was not same-site."_s);
- return;
- }
-
- if (redirectDomain.matches(firstPartyURL)) {
- m_client->broadcastConsoleMessage(MessageLevel::Warning, "[Private Click Measurement] Triggering event was not accepted because it was requested in an HTTP redirect that is same-site as the first-party."_s);
- return;
- }
-
- m_client->broadcastConsoleMessage(MessageLevel::Log, "[Private Click Measurement] Triggering event accepted."_s);
-
- attribute(SourceSite { WTFMove(redirectDomain) }, AttributionDestinationSite { firstPartyURL }, WTFMove(attributionTriggerData));
-}
-
-void PrivateClickMeasurementManager::startTimer(Seconds seconds)
-{
- m_firePendingAttributionRequestsTimer.startOneShot(m_isRunningTest ? 0_s : seconds);
-}
-
-void PrivateClickMeasurementManager::attribute(const SourceSite& sourceSite, const AttributionDestinationSite& destinationSite, AttributionTriggerData&& attributionTriggerData)
-{
- if (!featureEnabled())
- return;
-
- if (m_ephemeralMeasurement) {
- // Ephemeral measurement can only have one pending click.
- if (m_ephemeralMeasurement->sourceSite() != sourceSite)
- return;
- if (m_ephemeralMeasurement->destinationSite() != destinationSite)
- return;
- }
-
- store().attributePrivateClickMeasurement(sourceSite, destinationSite, WTFMove(attributionTriggerData), std::exchange(m_ephemeralMeasurement, std::nullopt), [this, weakThis = makeWeakPtr(*this)] (auto attributionSecondsUntilSendData, auto debugInfo) {
- if (!weakThis)
- return;
-
- if (!attributionSecondsUntilSendData)
- return;
-
- if (UNLIKELY(debugModeEnabled())) {
- for (auto& message : debugInfo.messages)
- m_client->broadcastConsoleMessage(message.messageLevel, message.message);
- }
-
- if (attributionSecondsUntilSendData.value().hasValidSecondsUntilSendValues()) {
- auto minSecondsUntilSend = attributionSecondsUntilSendData.value().minSecondsUntilSend();
-
- ASSERT(minSecondsUntilSend);
- if (!minSecondsUntilSend)
- return;
-
- if (m_firePendingAttributionRequestsTimer.isActive() && m_firePendingAttributionRequestsTimer.nextFireInterval() < *minSecondsUntilSend)
- return;
-
- if (UNLIKELY(debugModeEnabled())) {
- m_client->broadcastConsoleMessage(MessageLevel::Log, makeString("[Private Click Measurement] Setting timer for firing attribution request to the debug mode timeout of "_s, debugModeSecondsUntilSend.seconds(), " seconds where the regular timeout would have been "_s, minSecondsUntilSend.value().seconds(), " seconds."_s));
- minSecondsUntilSend = debugModeSecondsUntilSend;
- } else
- m_client->broadcastConsoleMessage(MessageLevel::Log, makeString("[Private Click Measurement] Setting timer for firing attribution request to the timeout of "_s, minSecondsUntilSend.value().seconds(), " seconds."_s));
-
- startTimer(*minSecondsUntilSend);
- }
- });
-}
-
-void PrivateClickMeasurementManager::fireConversionRequest(const PrivateClickMeasurement& attribution, PrivateClickMeasurement::AttributionReportEndpoint attributionReportEndpoint)
-{
- if (!featureEnabled())
- return;
-
- if (!attribution.sourceUnlinkableToken()) {
- fireConversionRequestImpl(attribution, attributionReportEndpoint);
- return;
- }
-
- auto attributionCopy = attribution;
- // This happens out of webpage context and with a long delay and is thus unlikely to be personally identifiable.
- getTokenPublicKey(WTFMove(attributionCopy), attributionReportEndpoint, PrivateClickMeasurement::PcmDataCarried::NonPersonallyIdentifiable, [weakThis = makeWeakPtr(*this), this, attributionReportEndpoint] (PrivateClickMeasurement&& attribution, const String& publicKeyBase64URL) {
- if (!weakThis)
- return;
-
- auto publicKeyData = base64URLDecode(publicKeyBase64URL);
- if (!publicKeyData)
- return;
-
- auto crypto = PAL::CryptoDigest::create(PAL::CryptoDigest::Algorithm::SHA_256);
- crypto->addBytes(publicKeyData->data(), publicKeyData->size());
- auto publicKeyDataHash = crypto->computeHash();
-
- auto keyID = base64URLEncodeToString(publicKeyDataHash.data(), publicKeyDataHash.size());
- if (keyID != attribution.sourceUnlinkableToken()->keyIDBase64URL)
- return;
-
- fireConversionRequestImpl(attribution, attributionReportEndpoint);
- });
-}
-
-void PrivateClickMeasurementManager::fireConversionRequestImpl(const PrivateClickMeasurement& attribution, PrivateClickMeasurement::AttributionReportEndpoint attributionReportEndpoint)
-{
- URL attributionURL;
- switch (attributionReportEndpoint) {
- case PrivateClickMeasurement::AttributionReportEndpoint::Source:
- attributionURL = m_attributionReportTestConfig ? m_attributionReportTestConfig->attributionReportSourceURL : attribution.attributionReportSourceURL();
- break;
- case PrivateClickMeasurement::AttributionReportEndpoint::Destination:
- attributionURL = m_attributionReportTestConfig ? m_attributionReportTestConfig->attributionReportAttributeOnURL : attribution.attributionReportAttributeOnURL();
- }
-
- if (attributionURL.isEmpty() || !attributionURL.isValid())
- return;
-
- auto loadParameters = generateNetworkLoadParametersForHttpPost(WTFMove(attributionURL), attribution.attributionReportJSON(), PrivateClickMeasurement::PcmDataCarried::NonPersonallyIdentifiable, debugModeEnabled());
-
- RELEASE_LOG_INFO(PrivateClickMeasurement, "About to fire an attribution request.");
- m_client->broadcastConsoleMessage(MessageLevel::Log, "[Private Click Measurement] About to fire an attribution request."_s);
-
- m_client->loadFromNetwork(WTFMove(loadParameters), [weakThis = makeWeakPtr(*this), this](auto& error, auto& response, auto&) {
- if (!weakThis)
- return;
-
- if (!error.isNull()) {
- m_client->broadcastConsoleMessage(MessageLevel::Error, makeString("[Private Click Measurement] Received error: '"_s, error.localizedDescription(), "' for ad click attribution request."_s));
- }
- });
-}
-
-void PrivateClickMeasurementManager::clearSentAttribution(PrivateClickMeasurement&& sentConversion, PrivateClickMeasurement::AttributionReportEndpoint attributionReportEndpoint)
-{
- if (!featureEnabled())
- return;
-
- store().clearSentAttribution(WTFMove(sentConversion), attributionReportEndpoint);
-}
-
-void PrivateClickMeasurementManager::firePendingAttributionRequests()
-{
- if (!featureEnabled())
- return;
-
- store().allAttributedPrivateClickMeasurement([this, weakThis = makeWeakPtr(*this)] (auto&& attributions) {
- if (!weakThis)
- return;
- auto nextTimeToFire = Seconds::infinity();
- bool hasSentAttribution = false;
-
- for (auto& attribution : attributions) {
- std::optional<WallTime> earliestTimeToSend = attribution.timesToSend().earliestTimeToSend();
- std::optional<WebCore::PrivateClickMeasurement::AttributionReportEndpoint> attributionReportEndpoint = attribution.timesToSend().attributionReportEndpoint();
-
- if (!earliestTimeToSend || !attributionReportEndpoint) {
- ASSERT_NOT_REACHED();
- continue;
- }
-
- auto now = WallTime::now();
- if (*earliestTimeToSend <= now || m_isRunningTest || debugModeEnabled()) {
- if (hasSentAttribution) {
- // We've already sent an attribution this round. We should send additional overdue attributions at
- // a random time between 15 and 30 minutes to avoid a burst of simultaneous attributions. If debug
- // mode is enabled, this should be much shorter for easy testing.
- auto interval = debugModeEnabled() ? debugModeSecondsUntilSend : 15_min + Seconds(cryptographicallyRandomNumber() % 900);
- startTimer(interval);
- return;
- }
-
- auto laterTimeToSend = attribution.timesToSend().latestTimeToSend();
- fireConversionRequest(attribution, *attributionReportEndpoint);
- clearSentAttribution(WTFMove(attribution), *attributionReportEndpoint);
- hasSentAttribution = true;
-
- // Update nextTimeToFire in case the later report time for this attribution is sooner than the scheduled next time to fire.
- // Or, if debug mode is enabled, we should send the second report on a much shorter delay for easy testing.
- if (laterTimeToSend)
- nextTimeToFire = debugModeEnabled() ? debugModeSecondsUntilSend : std::min(nextTimeToFire, laterTimeToSend.value().secondsSinceEpoch());
-
- continue;
- }
-
- auto seconds = *earliestTimeToSend - now;
- nextTimeToFire = std::min(nextTimeToFire, seconds);
-
- // Attributions are sorted by earliestTimeToSend, so the first time we hit this there can be no further attributions
- // due for reporting, and nextTimeToFire is the minimum earliestTimeToSend value for any pending attribution.
- break;
- }
-
- if (nextTimeToFire < Seconds::infinity())
- startTimer(nextTimeToFire);
- });
-}
-
-void PrivateClickMeasurementManager::clear(CompletionHandler<void()>&& completionHandler)
-{
- m_firePendingAttributionRequestsTimer.stop();
- m_ephemeralMeasurement = std::nullopt;
- m_isRunningEphemeralMeasurementTest = false;
-
- if (!featureEnabled())
- return completionHandler();
-
- store().clearPrivateClickMeasurement(WTFMove(completionHandler));
-}
-
-void PrivateClickMeasurementManager::clearForRegistrableDomain(const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
-{
- if (!featureEnabled())
- return completionHandler();
-
- store().clearPrivateClickMeasurementForRegistrableDomain(domain, WTFMove(completionHandler));
-}
-
-void PrivateClickMeasurementManager::clearExpired()
-{
- if (!featureEnabled())
- return;
-
- store().clearExpiredPrivateClickMeasurement();
-}
-
-void PrivateClickMeasurementManager::toStringForTesting(CompletionHandler<void(String)>&& completionHandler) const
-{
- if (!featureEnabled())
- return completionHandler("\nNo stored Private Click Measurement data.\n"_s);
-
- store().privateClickMeasurementToStringForTesting(WTFMove(completionHandler));
-}
-
-void PrivateClickMeasurementManager::setTokenPublicKeyURLForTesting(URL&& testURL)
-{
- if (testURL.isEmpty())
- return;
- m_tokenPublicKeyURLForTesting = WTFMove(testURL);
-}
-
-void PrivateClickMeasurementManager::setTokenSignatureURLForTesting(URL&& testURL)
-{
- if (testURL.isEmpty())
- m_tokenSignatureURLForTesting = { };
- else
- m_tokenSignatureURLForTesting = WTFMove(testURL);
-}
-
-void PrivateClickMeasurementManager::setAttributionReportURLsForTesting(URL&& sourceURL, URL&& destinationURL)
-{
- if (sourceURL.isEmpty() || destinationURL.isEmpty())
- m_attributionReportTestConfig = std::nullopt;
- else
- m_attributionReportTestConfig = AttributionReportTestConfig { WTFMove(sourceURL), WTFMove(destinationURL) };
-}
-
-void PrivateClickMeasurementManager::markAllUnattributedAsExpiredForTesting()
-{
- if (!featureEnabled())
- return;
-
- store().markAllUnattributedPrivateClickMeasurementAsExpiredForTesting();
-}
-
-void PrivateClickMeasurementManager::setPCMFraudPreventionValuesForTesting(String&& unlinkableToken, String&& secretToken, String&& signature, String&& keyID)
-{
- if (unlinkableToken.isEmpty() || secretToken.isEmpty() || signature.isEmpty() || keyID.isEmpty())
- return;
- m_fraudPreventionValuesForTesting = TestingFraudPreventionValues { WTFMove(unlinkableToken), WTFMove(secretToken), WTFMove(signature), WTFMove(keyID) };
-}
-
-bool PrivateClickMeasurementManager::featureEnabled() const
-{
- return m_client->featureEnabled();
-}
-
-bool PrivateClickMeasurementManager::debugModeEnabled() const
-{
- return m_client->debugModeEnabled();
-}
-
-void PrivateClickMeasurementManager::markAttributedPrivateClickMeasurementsAsExpiredForTesting(CompletionHandler<void()>&& completionHandler)
-{
- if (!featureEnabled())
- return completionHandler();
-
- store().markAttributedPrivateClickMeasurementsAsExpiredForTesting(WTFMove(completionHandler));
-}
-
-PCM::Store& PrivateClickMeasurementManager::store()
-{
- if (!m_store)
- m_store = PCM::Store::create(m_storageDirectory);
- return *m_store;
-}
-
-const PCM::Store& PrivateClickMeasurementManager::store() const
-{
- if (!m_store)
- m_store = PCM::Store::create(m_storageDirectory);
- return *m_store;
-}
-
-void PrivateClickMeasurementManager::destroyStoreForTesting(CompletionHandler<void()>&& completionHandler)
-{
- if (!m_store)
- return completionHandler();
- m_store->close([weakThis = makeWeakPtr(*this), completionHandler = WTFMove(completionHandler)] () mutable {
- if (weakThis)
- weakThis->m_store = nullptr;
- return completionHandler();
- });
-}
-
-} // namespace WebKit
Deleted: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementManager.h (281960 => 281961)
--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementManager.h 2021-09-02 22:44:04 UTC (rev 281960)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementManager.h 2021-09-02 23:03:37 UTC (rev 281961)
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2019 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#include "NetworkLoadParameters.h"
-#include "NetworkProcess.h"
-#include "PrivateClickMeasurementClient.h"
-#include "PrivateClickMeasurementStore.h"
-#include <WebCore/PrivateClickMeasurement.h>
-#include <WebCore/RegistrableDomain.h>
-#include <WebCore/ResourceError.h>
-#include <WebCore/ResourceResponse.h>
-#include <WebCore/Timer.h>
-#include <pal/SessionID.h>
-#include <wtf/CompletionHandler.h>
-#include <wtf/JSONValues.h>
-#include <wtf/WeakPtr.h>
-#include <wtf/text/WTFString.h>
-
-namespace WebKit {
-
-enum class PrivateClickMeasurementAttributionType : bool { Unattributed, Attributed };
-
-class PrivateClickMeasurementManager : public CanMakeWeakPtr<PrivateClickMeasurementManager> {
- WTF_MAKE_FAST_ALLOCATED;
-public:
-
- using AttributionDestinationSite = WebCore::PrivateClickMeasurement::AttributionDestinationSite;
- using AttributionTriggerData = WebCore::PrivateClickMeasurement::AttributionTriggerData;
- using PrivateClickMeasurement = WebCore::PrivateClickMeasurement;
- using RegistrableDomain = WebCore::RegistrableDomain;
- using SourceSite = WebCore::PrivateClickMeasurement::SourceSite;
- explicit PrivateClickMeasurementManager(UniqueRef<PCM::Client>&&, const String& storageDirectory);
-
- void storeUnattributed(PrivateClickMeasurement&&);
- void handleAttribution(AttributionTriggerData&&, const URL& requestURL, const WebCore::ResourceRequest& redirectRequest);
- void clear(CompletionHandler<void()>&&);
- void clearForRegistrableDomain(const RegistrableDomain&, CompletionHandler<void()>&&);
- void toStringForTesting(CompletionHandler<void(String)>&&) const;
- void setOverrideTimerForTesting(bool value) { m_isRunningTest = value; }
- void setTokenPublicKeyURLForTesting(URL&&);
- void setTokenSignatureURLForTesting(URL&&);
- void setAttributionReportURLsForTesting(URL&& sourceURL, URL&& destinationURL);
- void markAllUnattributedAsExpiredForTesting();
- void markAttributedPrivateClickMeasurementsAsExpiredForTesting(CompletionHandler<void()>&&);
- void setEphemeralMeasurementForTesting(bool value) { m_isRunningEphemeralMeasurementTest = value; }
- void setPCMFraudPreventionValuesForTesting(String&& unlinkableToken, String&& secretToken, String&& signature, String&& keyID);
- void startTimer(Seconds);
-
- void destroyStoreForTesting(CompletionHandler<void()>&&);
-
- PCM::Store& store();
- const PCM::Store& store() const;
-
-private:
- void getTokenPublicKey(PrivateClickMeasurement&&, PrivateClickMeasurement::AttributionReportEndpoint, PrivateClickMeasurement::PcmDataCarried, Function<void(PrivateClickMeasurement&& attribution, const String& publicKeyBase64URL)>&&);
- void getSignedUnlinkableToken(PrivateClickMeasurement&&);
- void insertPrivateClickMeasurement(PrivateClickMeasurement&&, PrivateClickMeasurementAttributionType);
- void clearSentAttribution(PrivateClickMeasurement&&, PrivateClickMeasurement::AttributionReportEndpoint);
- void attribute(const SourceSite&, const AttributionDestinationSite&, AttributionTriggerData&&);
- void fireConversionRequest(const PrivateClickMeasurement&, PrivateClickMeasurement::AttributionReportEndpoint);
- void fireConversionRequestImpl(const PrivateClickMeasurement&, PrivateClickMeasurement::AttributionReportEndpoint);
- void firePendingAttributionRequests();
- void clearExpired();
- bool featureEnabled() const;
- bool debugModeEnabled() const;
-
- std::optional<PrivateClickMeasurement> m_ephemeralMeasurement;
- WebCore::Timer m_firePendingAttributionRequestsTimer;
- bool m_isRunningTest { false };
- bool m_isRunningEphemeralMeasurementTest { false };
- std::optional<URL> m_tokenPublicKeyURLForTesting;
- std::optional<URL> m_tokenSignatureURLForTesting;
- mutable RefPtr<PCM::Store> m_store;
- String m_storageDirectory;
- UniqueRef<PCM::Client> m_client;
-
- struct AttributionReportTestConfig {
- URL attributionReportSourceURL;
- URL attributionReportAttributeOnURL;
- };
-
- std::optional<AttributionReportTestConfig> m_attributionReportTestConfig;
-
- struct TestingFraudPreventionValues {
- String unlinkableToken;
- String secretToken;
- String signature;
- String keyID;
- };
-
- std::optional<TestingFraudPreventionValues> m_fraudPreventionValuesForTesting;
-};
-
-} // namespace WebKit
Deleted: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementNetworkLoader.cpp (281960 => 281961)
--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementNetworkLoader.cpp 2021-09-02 22:44:04 UTC (rev 281960)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementNetworkLoader.cpp 2021-09-02 23:03:37 UTC (rev 281961)
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2021 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "PrivateClickMeasurementNetworkLoader.h"
-
-#include "NetworkLoad.h"
-#include "NetworkSession.h"
-#include <WebCore/MIMETypeRegistry.h>
-#include <WebCore/TextResourceDecoder.h>
-
-#include <wtf/JSONValues.h>
-
-namespace WebKit {
-
-using namespace WebCore;
-
-void PrivateClickMeasurementNetworkLoader::start(NetworkSession& session, NetworkLoadParameters&& parameters, Callback&& completionHandler)
-{
- auto loader = std::unique_ptr<PrivateClickMeasurementNetworkLoader>(new PrivateClickMeasurementNetworkLoader(session, WTFMove(parameters), WTFMove(completionHandler)));
- session.addPrivateClickMeasurementNetworkLoader(WTFMove(loader));
-}
-
-PrivateClickMeasurementNetworkLoader::PrivateClickMeasurementNetworkLoader(NetworkSession& session, NetworkLoadParameters&& parameters, Callback&& completionHandler)
- : m_session(makeWeakPtr(session))
- , m_completionHandler(WTFMove(completionHandler))
-{
- m_networkLoad = makeUnique<NetworkLoad>(*this, nullptr, WTFMove(parameters), *m_session);
- m_networkLoad->start();
-}
-
-PrivateClickMeasurementNetworkLoader::~PrivateClickMeasurementNetworkLoader()
-{
- cancel();
-}
-
-void PrivateClickMeasurementNetworkLoader::fail(ResourceError&& error)
-{
- if (!m_completionHandler)
- return;
-
- m_completionHandler(WTFMove(error), { }, nullptr);
- didComplete();
-}
-
-void PrivateClickMeasurementNetworkLoader::cancel()
-{
- fail(ResourceError { ResourceError::Type::Cancellation });
-}
-
-void PrivateClickMeasurementNetworkLoader::willSendRedirectedRequest(ResourceRequest&&, ResourceRequest&&, ResourceResponse&&)
-{
- cancel();
-}
-
-void PrivateClickMeasurementNetworkLoader::didReceiveResponse(ResourceResponse&& response, ResponseCompletionHandler&& completionHandler)
-{
- if (!MIMETypeRegistry::isSupportedJSONMIMEType(response.mimeType())) {
- fail({ errorDomainWebKitInternal, 0, response.url(), "MIME Type is not a JSON MIME type"_s });
- completionHandler(PolicyAction::Ignore);
- return;
- }
-
- m_response = WTFMove(response);
- completionHandler(PolicyAction::Use);
-}
-
-void PrivateClickMeasurementNetworkLoader::didReceiveBuffer(Ref<SharedBuffer>&& buffer, int reportedEncodedDataLength)
-{
- if (!m_decoder)
- m_decoder = TextResourceDecoder::create("application/json"_s, m_response.textEncodingName().isEmpty() ? WebCore::TextEncoding("UTF-8") : WebCore::TextEncoding(m_response.textEncodingName()));
-
- if (auto size = buffer->size())
- m_jsonString.append(m_decoder->decode(buffer->data(), size));
-}
-
-void PrivateClickMeasurementNetworkLoader::didFinishLoading(const WebCore::NetworkLoadMetrics&)
-{
- if (m_decoder)
- m_jsonString.append(m_decoder->flush());
-
- if (auto jsonValue = JSON::Value::parseJSON(m_jsonString.toString()))
- m_completionHandler({ }, m_response, jsonValue->asObject());
- else
- m_completionHandler({ }, m_response, nullptr);
-
- didComplete();
-}
-
-void PrivateClickMeasurementNetworkLoader::didFailLoading(const ResourceError& error)
-{
- fail(ResourceError(error));
-}
-
-void PrivateClickMeasurementNetworkLoader::didComplete()
-{
- m_networkLoad = nullptr;
- if (m_session)
- m_session->removePrivateClickMeasurementNetworkLoader(this);
-}
-
-} // namespace WebKit
Deleted: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementNetworkLoader.h (281960 => 281961)
--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementNetworkLoader.h 2021-09-02 22:44:04 UTC (rev 281960)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementNetworkLoader.h 2021-09-02 23:03:37 UTC (rev 281961)
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2021 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#include "NetworkLoad.h"
-#include "NetworkLoadClient.h"
-#include "NetworkLoadParameters.h"
-#include <WebCore/TextResourceDecoder.h>
-#include <wtf/CompletionHandler.h>
-#include <wtf/WeakPtr.h>
-
-namespace WebKit {
-
-class NetworkSession;
-
-class PrivateClickMeasurementNetworkLoader final : public NetworkLoadClient {
- WTF_MAKE_FAST_ALLOCATED;
-public:
- using Callback = CompletionHandler<void(const WebCore::ResourceError&, const WebCore::ResourceResponse&, const RefPtr<JSON::Object>&)>;
- static void start(NetworkSession&, NetworkLoadParameters&&, Callback&&);
-
- ~PrivateClickMeasurementNetworkLoader();
-
-private:
- PrivateClickMeasurementNetworkLoader(NetworkSession&, NetworkLoadParameters&&, Callback&&);
-
- // NetworkLoadClient.
- void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) final { }
- bool isSynchronous() const final { return false; }
- bool isAllowedToAskUserForCredentials() const final { return false; }
- void willSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&& redirectResponse) final;
- void didReceiveResponse(WebCore::ResourceResponse&&, ResponseCompletionHandler&&) final;
- void didReceiveBuffer(Ref<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) final;
- void didFinishLoading(const WebCore::NetworkLoadMetrics&) final;
- void didFailLoading(const WebCore::ResourceError&) final;
-
- void fail(WebCore::ResourceError&&);
- void cancel();
- void didComplete();
-
- WeakPtr<NetworkSession> m_session;
- std::unique_ptr<NetworkLoad> m_networkLoad;
- Callback m_completionHandler;
-
- WebCore::ResourceResponse m_response;
- RefPtr<WebCore::TextResourceDecoder> m_decoder;
- StringBuilder m_jsonString;
-};
-
-} // namespace WebKit
Modified: trunk/Source/WebKit/Sources.txt (281960 => 281961)
--- trunk/Source/WebKit/Sources.txt 2021-09-02 22:44:04 UTC (rev 281960)
+++ trunk/Source/WebKit/Sources.txt 2021-09-02 23:03:37 UTC (rev 281961)
@@ -58,8 +58,6 @@
GPUProcess/webrtc/RemoteSampleBufferDisplayLayerManager.cpp
NetworkProcess/DatabaseUtilities.cpp
-NetworkProcess/PrivateClickMeasurementManager.cpp
-NetworkProcess/PrivateClickMeasurementNetworkLoader.cpp
NetworkProcess/NetworkActivityTracker.cpp
NetworkProcess/NetworkBroadcastChannelRegistry.cpp
NetworkProcess/NetworkCORSPreflightChecker.cpp
@@ -102,6 +100,8 @@
NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementClientImpl.cpp
NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDatabase.cpp
NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDebugInfo.cpp
+NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManager.cpp
+NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementNetworkLoader.cpp
NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementStore.cpp
NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp @no-unify
Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (281960 => 281961)
--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2021-09-02 22:44:04 UTC (rev 281960)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2021-09-02 23:03:37 UTC (rev 281961)
@@ -1074,8 +1074,6 @@
517CF0E3163A486C00C2950E /* NetworkProcessConnectionMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517CF0E1163A486C00C2950E /* NetworkProcessConnectionMessageReceiver.cpp */; };
517CF0E3163A486C00C2950F /* CacheStorageEngineConnectionMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517CF0E1163A486C00C2950F /* CacheStorageEngineConnectionMessageReceiver.cpp */; };
517CF0E4163A486C00C2950E /* NetworkProcessConnectionMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 517CF0E2163A486C00C2950E /* NetworkProcessConnectionMessages.h */; };
- 5183247C26168C62003F239E /* NetworkURLSchemeHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 51832475261599CC003F239E /* NetworkURLSchemeHandler.h */; };
- 5183247D26168FF7003F239E /* NetworkURLSchemeTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 5183247A26168675003F239E /* NetworkURLSchemeTask.h */; };
5183722223CE97410003CF83 /* APIContentWorld.h in Headers */ = {isa = PBXBuildFile; fileRef = 5183722023CE973A0003CF83 /* APIContentWorld.h */; };
51871B5C127CB89D00F76232 /* WebContextMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = 51871B5A127CB89D00F76232 /* WebContextMenu.h */; };
518ACAEA12AEE6BB00B04B83 /* WKProtectionSpaceTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 518ACAE912AEE6BB00B04B83 /* WKProtectionSpaceTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -4112,12 +4110,8 @@
517CF0E1163A486C00C2950E /* NetworkProcessConnectionMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetworkProcessConnectionMessageReceiver.cpp; path = DerivedSources/WebKit2/NetworkProcessConnectionMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
517CF0E1163A486C00C2950F /* CacheStorageEngineConnectionMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CacheStorageEngineConnectionMessageReceiver.cpp; path = DerivedSources/WebKit2/CacheStorageEngineConnectionMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
517CF0E2163A486C00C2950E /* NetworkProcessConnectionMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetworkProcessConnectionMessages.h; path = DerivedSources/WebKit2/NetworkProcessConnectionMessages.h; sourceTree = BUILT_PRODUCTS_DIR; };
- 51832475261599CC003F239E /* NetworkURLSchemeHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkURLSchemeHandler.h; sourceTree = "<group>"; };
- 51832476261599CC003F239E /* NetworkURLSchemeHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkURLSchemeHandler.cpp; sourceTree = "<group>"; };
518324782615B00D003F239E /* NetworkSchemeURLProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkSchemeURLProtocol.h; sourceTree = "<group>"; };
518324792615B00D003F239E /* NetworkSchemeURLProtocol.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkSchemeURLProtocol.mm; sourceTree = "<group>"; };
- 5183247A26168675003F239E /* NetworkURLSchemeTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkURLSchemeTask.h; sourceTree = "<group>"; };
- 5183247B26168675003F239E /* NetworkURLSchemeTask.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkURLSchemeTask.cpp; sourceTree = "<group>"; };
5183722023CE973A0003CF83 /* APIContentWorld.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIContentWorld.h; sourceTree = "<group>"; };
5183722123CE973A0003CF83 /* APIContentWorld.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = APIContentWorld.cpp; sourceTree = "<group>"; };
5183B3931379F85C00E8754E /* Shim.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shim.xcconfig; sourceTree = "<group>"; };
@@ -8747,18 +8741,10 @@
5C0B177E1E7C886700E9123C /* NetworkSocketStream.h */,
5C0B177F1E7C886700E9123C /* NetworkSocketStream.messages.in */,
5C9EF2E721F058F9003BDC56 /* NetworkStorageSessionProvider.h */,
- 51832476261599CC003F239E /* NetworkURLSchemeHandler.cpp */,
- 51832475261599CC003F239E /* NetworkURLSchemeHandler.h */,
- 5183247B26168675003F239E /* NetworkURLSchemeTask.cpp */,
- 5183247A26168675003F239E /* NetworkURLSchemeTask.h */,
462107D71F38DBD300DD7810 /* PingLoad.cpp */,
5CE85B1F1C88E6430070BFCE /* PingLoad.h */,
83A0ED331F747CC7003299EB /* PreconnectTask.cpp */,
83A0ED321F747CC6003299EB /* PreconnectTask.h */,
- 6BD05864220CE8C2000BED5C /* PrivateClickMeasurementManager.cpp */,
- 6BD05863220CE8C2000BED5C /* PrivateClickMeasurementManager.h */,
- 57FE688B260ABB3D00BF45E4 /* PrivateClickMeasurementNetworkLoader.cpp */,
- 57FE688A260ABB3D00BF45E4 /* PrivateClickMeasurementNetworkLoader.h */,
E1B78470163F24690007B692 /* RemoteNetworkingContext.h */,
41287D4D225C161F009A3E26 /* WebSocketTask.h */,
);
@@ -9272,6 +9258,10 @@
5C826D6926D482EA008AEC91 /* PrivateClickMeasurementDatabase.h */,
5CBE909026D7FB7C005A2E95 /* PrivateClickMeasurementDebugInfo.cpp */,
5CBE908F26D7FB62005A2E95 /* PrivateClickMeasurementDebugInfo.h */,
+ 6BD05864220CE8C2000BED5C /* PrivateClickMeasurementManager.cpp */,
+ 6BD05863220CE8C2000BED5C /* PrivateClickMeasurementManager.h */,
+ 57FE688B260ABB3D00BF45E4 /* PrivateClickMeasurementNetworkLoader.cpp */,
+ 57FE688A260ABB3D00BF45E4 /* PrivateClickMeasurementNetworkLoader.h */,
5C826D6726D46B43008AEC91 /* PrivateClickMeasurementStore.cpp */,
5C826D6826D46B44008AEC91 /* PrivateClickMeasurementStore.h */,
);
@@ -12275,8 +12265,6 @@
5C20CBA01BB1ECD800895BB1 /* NetworkSession.h in Headers */,
532159551DBAE7290054AA3C /* NetworkSessionCocoa.h in Headers */,
417915B92257046F00D6F97E /* NetworkSocketChannel.h in Headers */,
- 5183247C26168C62003F239E /* NetworkURLSchemeHandler.h in Headers */,
- 5183247D26168FF7003F239E /* NetworkURLSchemeTask.h in Headers */,
570DAAC22303730300E8FC04 /* NfcConnection.h in Headers */,
570DAAAE23026F5C00E8FC04 /* NfcService.h in Headers */,
31A2EC5614899C0900810D71 /* NotificationPermissionRequest.h in Headers */,