https://bugs.webkit.org/show_bug.cgi?id=197238
<rdar://problem/
50177349>
Reviewed by Chris Dumez.
Source/WebCore:
This patch adds the two functions AdClickAttribution::markAsExpired()
and AdClickAttribution::hasExpired() which make use of the existing
m_timeOfAdClick member.
Test: http/tests/adClickAttribution/expired-attributions-removed.html
* loader/AdClickAttribution.cpp:
(WebCore::AdClickAttribution::markAsExpired):
(WebCore::AdClickAttribution::hasExpired const):
* loader/AdClickAttribution.h:
Source/WebKit:
AdClickAttributionManager::storeUnconverted() and
AdClickAttributionManager::convert() now start by calling the new
AdClickAttributionManager::clearExpired() function to remove any
expired, unconverted attributions before continuing.
The rest of the patch is infrastructure to allow tests to expire
all unconverted attributions early.
* NetworkProcess/AdClickAttributionManager.cpp:
(WebKit::AdClickAttributionManager::storeUnconverted):
(WebKit::AdClickAttributionManager::convert):
(WebKit::AdClickAttributionManager::clearExpired):
(WebKit::AdClickAttributionManager::markAllUnconvertedAsExpiredForTesting):
* NetworkProcess/AdClickAttributionManager.h:
* NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::markAdClickAttributionsAsExpiredForTesting):
* NetworkProcess/NetworkProcess.h:
* NetworkProcess/NetworkProcess.messages.in:
* NetworkProcess/NetworkSession.cpp:
(WebKit::NetworkSession::markAdClickAttributionsAsExpiredForTesting):
* NetworkProcess/NetworkSession.h:
* UIProcess/API/C/WKPage.cpp:
(WKPageSetAdClickAttributionConversionURLForTesting):
(WKPageMarkAdClickAttributionsAsExpiredForTesting):
* UIProcess/API/C/WKPagePrivate.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::markAdClickAttributionsAsExpiredForTesting):
* UIProcess/WebPageProxy.h:
Tools:
This patch adds infrastructure to allow tests to expire all unconverted
attributions early.
* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::markAdClickAttributionsAsExpiredForTesting):
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::markAdClickAttributionsAsExpiredForTesting):
* WebKitTestRunner/TestController.h:
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
LayoutTests:
* http/tests/adClickAttribution/expired-attributions-removed-expected.txt: Added.
* http/tests/adClickAttribution/expired-attributions-removed.html: Added.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244614
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2019-04-24 John Wilander <wilander@apple.com>
+
+ Age out unconverted Ad Click Attributions after one week.
+ https://bugs.webkit.org/show_bug.cgi?id=197238
+ <rdar://problem/50177349>
+
+ Reviewed by Chris Dumez.
+
+ * http/tests/adClickAttribution/expired-attributions-removed-expected.txt: Added.
+ * http/tests/adClickAttribution/expired-attributions-removed.html: Added.
+
2019-04-24 Simon Fraser <simon.fraser@apple.com>
REGRESSION (iOS 12.2): CSS perspective property value can only be set correctly once
--- /dev/null
+Tests expiration of ad click attribution.
+
+
+
+No stored Ad Click Attribution data.
--- /dev/null
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+ <script src="/js-test-resources/ui-helper.js"></script>
+ <script src="resources/util.js"></script>
+</head>
+<body onload="setTimeout(runTest, 0)">
+<div id="description">Tests expiration of ad click attribution.</div>
+<a id="targetLink" href="http://localhost:8000/adClickAttribution/expired-attributions-removed.html?stepTwo" adcampaignid="3" addestination="http://localhost:8000">Link</a><br>
+<div id="output"></div>
+<script>
+ prepareTest();
+
+ function activateElement(elementID) {
+ var element = document.getElementById(elementID);
+ var centerX = element.offsetLeft + element.offsetWidth / 2;
+ var centerY = element.offsetTop + element.offsetHeight / 2;
+ UIHelper.activateAt(centerX, centerY).then(
+ function () {
+ },
+ function () {
+ document.getElementById("output").innerText = "FAIL Promise rejected.";
+ tearDownAndFinish();
+ }
+ );
+ }
+
+ function runTest() {
+ if (window.testRunner) {
+ if (window.location.search === "?stepTwo") {
+ testRunner.markAdClickAttributionsAsExpiredForTesting();
+ let imageElement = document.createElement("img");
+ imageElement.src = "https://127.0.0.1:8443/adClickAttribution/resources/redirectToConversion.php?conversionData=12";
+ imageElement.id = "pixel";
+ imageElement.onerror = function() {
+ testRunner.dumpAdClickAttribution();
+ document.body.removeChild(document.getElementById("targetLink"));
+ document.body.removeChild(document.getElementById("pixel"));
+ tearDownAndFinish();
+ };
+ document.body.appendChild(imageElement);
+ } else {
+ activateElement("targetLink");
+ }
+ } else {
+ document.getElementById("output").innerText = "FAIL No testRunner.";
+ }
+ }
+</script>
+</body>
+</html>
+2019-04-24 John Wilander <wilander@apple.com>
+
+ Age out unconverted Ad Click Attributions after one week.
+ https://bugs.webkit.org/show_bug.cgi?id=197238
+ <rdar://problem/50177349>
+
+ Reviewed by Chris Dumez.
+
+ This patch adds the two functions AdClickAttribution::markAsExpired()
+ and AdClickAttribution::hasExpired() which make use of the existing
+ m_timeOfAdClick member.
+
+ Test: http/tests/adClickAttribution/expired-attributions-removed.html
+
+ * loader/AdClickAttribution.cpp:
+ (WebCore::AdClickAttribution::markAsExpired):
+ (WebCore::AdClickAttribution::hasExpired const):
+ * loader/AdClickAttribution.h:
+
2019-04-24 Simon Fraser <simon.fraser@apple.com>
REGRESSION (iOS 12.2): CSS perspective property value can only be set correctly once
static const char adClickAttributionPathPrefix[] = "/.well-known/ad-click-attribution/";
const size_t adClickConversionDataPathSegmentSize = 2;
const size_t adClickPriorityPathSegmentSize = 2;
+const Seconds maxAge { 24_h * 7 };
bool AdClickAttribution::isValid() const
{
return seconds;
}
+void AdClickAttribution::markAsExpired()
+{
+ m_timeOfAdClick = { };
+}
+
+bool AdClickAttribution::hasExpired() const
+{
+ return WallTime::now() > m_timeOfAdClick + maxAge;
+}
+
bool AdClickAttribution::hasHigherPriorityThan(const AdClickAttribution& other) const
{
if (!other.m_conversion)
const Source& source() const { return m_source; };
const Destination& destination() const { return m_destination; };
Optional<WallTime> earliestTimeToSend() const { return m_earliestTimeToSend; };
+ WEBCORE_EXPORT void markAsExpired();
+ WEBCORE_EXPORT bool hasExpired() const;
WEBCORE_EXPORT void markConversionAsSent();
WEBCORE_EXPORT bool wasConversionSent() const;
+2019-04-24 John Wilander <wilander@apple.com>
+
+ Age out unconverted Ad Click Attributions after one week.
+ https://bugs.webkit.org/show_bug.cgi?id=197238
+ <rdar://problem/50177349>
+
+ Reviewed by Chris Dumez.
+
+ AdClickAttributionManager::storeUnconverted() and
+ AdClickAttributionManager::convert() now start by calling the new
+ AdClickAttributionManager::clearExpired() function to remove any
+ expired, unconverted attributions before continuing.
+
+ The rest of the patch is infrastructure to allow tests to expire
+ all unconverted attributions early.
+
+ * NetworkProcess/AdClickAttributionManager.cpp:
+ (WebKit::AdClickAttributionManager::storeUnconverted):
+ (WebKit::AdClickAttributionManager::convert):
+ (WebKit::AdClickAttributionManager::clearExpired):
+ (WebKit::AdClickAttributionManager::markAllUnconvertedAsExpiredForTesting):
+ * NetworkProcess/AdClickAttributionManager.h:
+ * NetworkProcess/NetworkProcess.cpp:
+ (WebKit::NetworkProcess::markAdClickAttributionsAsExpiredForTesting):
+ * NetworkProcess/NetworkProcess.h:
+ * NetworkProcess/NetworkProcess.messages.in:
+ * NetworkProcess/NetworkSession.cpp:
+ (WebKit::NetworkSession::markAdClickAttributionsAsExpiredForTesting):
+ * NetworkProcess/NetworkSession.h:
+ * UIProcess/API/C/WKPage.cpp:
+ (WKPageSetAdClickAttributionConversionURLForTesting):
+ (WKPageMarkAdClickAttributionsAsExpiredForTesting):
+ * UIProcess/API/C/WKPagePrivate.h:
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::markAdClickAttributionsAsExpiredForTesting):
+ * UIProcess/WebPageProxy.h:
+
2019-04-24 Wenson Hsieh <wenson_hsieh@apple.com>
Plumb the navigation's request when determining recommended compatibility mode
void AdClickAttributionManager::storeUnconverted(AdClickAttribution&& attribution)
{
+ clearExpired();
+
m_unconvertedAdClickAttributionMap.set(std::make_pair(attribution.source(), attribution.destination()), WTFMove(attribution));
}
void AdClickAttributionManager::convert(const Source& source, const Destination& destination, Conversion&& conversion)
{
+ clearExpired();
+
if (!conversion.isValid())
return;
});
}
+void AdClickAttributionManager::clearExpired()
+{
+ m_unconvertedAdClickAttributionMap.removeIf([](auto& keyAndValue) {
+ return keyAndValue.value.hasExpired();
+ });
+}
+
void AdClickAttributionManager::toString(CompletionHandler<void(String)>&& completionHandler) const
{
if (m_unconvertedAdClickAttributionMap.isEmpty() && m_convertedAdClickAttributionMap.isEmpty())
m_conversionBaseURLForTesting = WTFMove(testURL);
}
+void AdClickAttributionManager::markAllUnconvertedAsExpiredForTesting()
+{
+ for (auto& attribution : m_unconvertedAdClickAttributionMap.values())
+ attribution.markAsExpired();
+}
+
} // namespace WebKit
void setPingLoadFunction(Function<void(NetworkResourceLoadParameters&&, CompletionHandler<void(const WebCore::ResourceError&, const WebCore::ResourceResponse&)>&&)>&& pingLoadFunction) { m_pingLoadFunction = WTFMove(pingLoadFunction); }
void setOverrideTimerForTesting(bool value) { m_isRunningTest = value; }
void setConversionURLForTesting(URL&&);
+ void markAllUnconvertedAsExpiredForTesting();
private:
void startTimer(Seconds);
void fireConversionRequest(const AdClickAttribution&);
void firePendingConversionRequests();
+ void clearExpired();
HashMap<std::pair<Source, Destination>, AdClickAttribution> m_unconvertedAdClickAttributionMap;
HashMap<std::pair<Source, Destination>, AdClickAttribution> m_convertedAdClickAttributionMap;
completionHandler();
}
+void NetworkProcess::markAdClickAttributionsAsExpiredForTesting(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
+{
+ if (auto* session = networkSession(sessionID))
+ session->markAdClickAttributionsAsExpiredForTesting();
+
+ completionHandler();
+}
+
} // namespace WebKit
void clearAdClickAttribution(PAL::SessionID, CompletionHandler<void()>&&);
void setAdClickAttributionOverrideTimerForTesting(PAL::SessionID, bool value, CompletionHandler<void()>&&);
void setAdClickAttributionConversionURLForTesting(PAL::SessionID, URL&&, CompletionHandler<void()>&&);
+ void markAdClickAttributionsAsExpiredForTesting(PAL::SessionID, CompletionHandler<void()>&&);
WebCore::StorageQuotaManager& storageQuotaManager(PAL::SessionID, const WebCore::ClientOrigin&);
ClearAdClickAttribution(PAL::SessionID sessionID) -> () Async
SetAdClickAttributionOverrideTimerForTesting(PAL::SessionID sessionID, bool value) -> () Async
SetAdClickAttributionConversionURLForTesting(PAL::SessionID sessionID, URL url) -> () Async
+ MarkAdClickAttributionsAsExpiredForTesting(PAL::SessionID sessionID) -> () Async
RemoveCredential(WebCore::Credential credential, WebCore::ProtectionSpace protectionSpace) -> () Async
}
m_adClickAttribution->setConversionURLForTesting(WTFMove(url));
}
+void NetworkSession::markAdClickAttributionsAsExpiredForTesting()
+{
+ m_adClickAttribution->markAllUnconvertedAsExpiredForTesting();
+}
+
} // namespace WebKit
void clearAdClickAttributionForRegistrableDomain(WebCore::RegistrableDomain&&);
void setAdClickAttributionOverrideTimerForTesting(bool value);
void setAdClickAttributionConversionURLForTesting(URL&&);
+ void markAdClickAttributionsAsExpiredForTesting();
protected:
NetworkSession(NetworkProcess&, PAL::SessionID);
});
}
-void WKPageSetAdClickAttributionConversionURLForTesting(WKPageRef page, WKURLRef URLRef, WKPageSetAdClickAttributionOverrideTimerForTestingFunction callback, void* callbackContext)
+void WKPageSetAdClickAttributionConversionURLForTesting(WKPageRef page, WKURLRef URLRef, WKPageSetAdClickAttributionConversionURLForTestingFunction callback, void* callbackContext)
{
toImpl(page)->setAdClickAttributionConversionURLForTesting(URL(URL(), toWTFString(URLRef)), [callbackContext, callback] () {
callback(callbackContext);
});
}
+
+void WKPageMarkAdClickAttributionsAsExpiredForTesting(WKPageRef page, WKPageMarkAdClickAttributionsAsExpiredForTestingFunction callback, void* callbackContext)
+{
+ toImpl(page)->markAdClickAttributionsAsExpiredForTesting([callbackContext, callback] () {
+ callback(callbackContext);
+ });
+}
WK_EXPORT void WKPageSetAdClickAttributionOverrideTimerForTesting(WKPageRef page, bool value, WKPageSetAdClickAttributionOverrideTimerForTestingFunction callback, void* callbackContext);
typedef void (*WKPageSetAdClickAttributionConversionURLForTestingFunction)(void* functionContext);
WK_EXPORT void WKPageSetAdClickAttributionConversionURLForTesting(WKPageRef page, WKURLRef urlString, WKPageSetAdClickAttributionConversionURLForTestingFunction callback, void* callbackContext);
+typedef void (*WKPageMarkAdClickAttributionsAsExpiredForTestingFunction)(void* functionContext);
+WK_EXPORT void WKPageMarkAdClickAttributionsAsExpiredForTesting(WKPageRef page, WKPageMarkAdClickAttributionsAsExpiredForTestingFunction callback, void* callbackContext);
#ifdef __cplusplus
}
}
}
+void WebPageProxy::markAdClickAttributionsAsExpiredForTesting(CompletionHandler<void()>&& completionHandler)
+{
+ if (auto* networkProcess = m_process->processPool().networkProcess()) {
+ if (!networkProcess->canSendMessage()) {
+ completionHandler();
+ return;
+ }
+ networkProcess->sendWithAsyncReply(Messages::NetworkProcess::MarkAdClickAttributionsAsExpiredForTesting(m_websiteDataStore->sessionID()), WTFMove(completionHandler));
+ }
+}
+
#if ENABLE(SPEECH_SYNTHESIS)
WebPageProxy::SpeechSynthesisData& WebPageProxy::speechSynthesisData()
{
void clearAdClickAttribution(CompletionHandler<void()>&&);
void setAdClickAttributionOverrideTimerForTesting(bool value, CompletionHandler<void()>&&);
void setAdClickAttributionConversionURLForTesting(const URL&, CompletionHandler<void()>&&);
+ void markAdClickAttributionsAsExpiredForTesting(CompletionHandler<void()>&&);
#if ENABLE(SPEECH_SYNTHESIS)
void speechSynthesisVoiceList(CompletionHandler<void(Vector<WebSpeechSynthesisVoice>&&)>&&);
+2019-04-24 John Wilander <wilander@apple.com>
+
+ Age out unconverted Ad Click Attributions after one week.
+ https://bugs.webkit.org/show_bug.cgi?id=197238
+ <rdar://problem/50177349>
+
+ Reviewed by Chris Dumez.
+
+ This patch adds infrastructure to allow tests to expire all unconverted
+ attributions early.
+
+ * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+ * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+ (WTR::TestRunner::markAdClickAttributionsAsExpiredForTesting):
+ * WebKitTestRunner/InjectedBundle/TestRunner.h:
+ * WebKitTestRunner/TestController.cpp:
+ (WTR::TestController::markAdClickAttributionsAsExpiredForTesting):
+ * WebKitTestRunner/TestController.h:
+ * WebKitTestRunner/TestInvocation.cpp:
+ (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
+
2019-04-24 Chris Dumez <cdumez@apple.com>
Fix flaky crashes in a couple of PSON API tests
void clearAdClickAttributionsThroughWebsiteDataRemoval();
void setAdClickAttributionOverrideTimerForTesting(boolean value);
void setAdClickAttributionConversionURLForTesting(DOMString url);
+ void markAdClickAttributionsAsExpiredForTesting();
};
WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), nullptr);
}
+void TestRunner::markAdClickAttributionsAsExpiredForTesting()
+{
+ WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("MarkAdClickAttributionsAsExpiredForTesting"));
+ WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr, nullptr);
+}
+
} // namespace WTR
void clearAdClickAttributionsThroughWebsiteDataRemoval();
void setAdClickAttributionOverrideTimerForTesting(bool value);
void setAdClickAttributionConversionURLForTesting(JSStringRef);
+ void markAdClickAttributionsAsExpiredForTesting();
private:
TestRunner();
runUntil(callbackContext.done, noTimeout);
}
+void TestController::markAdClickAttributionsAsExpiredForTesting()
+{
+ AdClickAttributionVoidCallbackContext callbackContext(*this);
+ WKPageMarkAdClickAttributionsAsExpiredForTesting(m_mainWebView->page(), adClickAttributionVoidCallback, &callbackContext);
+ runUntil(callbackContext.done, noTimeout);
+}
+
} // namespace WTR
void clearAdClickAttributionsThroughWebsiteDataRemoval();
void setAdClickAttributionOverrideTimerForTesting(bool value);
void setAdClickAttributionConversionURLForTesting(WKURLRef);
+ void markAdClickAttributionsAsExpiredForTesting();
private:
WKRetainPtr<WKPageConfigurationRef> generatePageConfiguration(const TestOptions&);
TestController::singleton().setAdClickAttributionConversionURLForTesting(url);
return nullptr;
}
-
+
+ if (WKStringIsEqualToUTF8CString(messageName, "MarkAdClickAttributionsAsExpiredForTesting")) {
+ TestController::singleton().markAdClickAttributionsAsExpiredForTesting();
+ return nullptr;
+ }
+
ASSERT_NOT_REACHED();
return nullptr;
}