Skip to content
Permalink
Browse files
Disable Ad Click Attribution in ephemeral sessions and make sure conv…
…ersion requests use an ephemeral, stateless session

https://bugs.webkit.org/show_bug.cgi?id=197108
<rdar://problem/49918702>

Patch by John Wilander <wilander@apple.com> on 2019-04-19
Reviewed by Alex Christensen.

Source/WebCore:

Tests: http/tests/adClickAttribution/conversion-disabled-in-ephemeral-session.html
       http/tests/adClickAttribution/store-disabled-in-ephemeral-session.html

* html/HTMLAnchorElement.cpp:
(WebCore::HTMLAnchorElement::parseAdClickAttribution const):
    Early return for ephemeral sessions.
* loader/ResourceLoader.cpp:
(WebCore::ResourceLoader::shouldUseCredentialStorage):
    Now returns false for StoredCredentialsPolicy:EphemeralStatelessCookieless.
* platform/network/StoredCredentialsPolicy.h:
    Added enum value EphemeralStatelessCookieless.

Source/WebKit:

This patch introduces a new NSURLSession in WebKit::NetworkSessionCocoa called
m_ephemeralStatelessCookielessSession. As its name implies, it's ephemeral,
stateless, and has a NSHTTPCookieAcceptPolicyNever cookie policy.

The new session can be invoked with the new enum value of
WebCore::StoredCredentialsPolicy called EphemeralStatelessCookieless.

WebKit::AdClickAttributionManager::fireConversionRequest() makes use of
the new session for its conversion requests.

This patch also makes sure that Ad Click Attributions cannot be stored in
ephemeral sessions and already stored attributions cannot be converted in
ephemeral sessions.

* NetworkProcess/AdClickAttributionManager.cpp:
(WebKit::AdClickAttributionManager::fireConversionRequest):
(WebKit::AdClickAttributionManager::toString const):
* NetworkProcess/NetworkLoadChecker.h:
* NetworkProcess/NetworkProcess.h:
* NetworkProcess/NetworkProcess.messages.in:
* NetworkProcess/NetworkResourceLoader.cpp:
(WebKit::NetworkResourceLoader::willSendRedirectedRequest):
* NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
(WebKit::NetworkDataTaskCocoa::NetworkDataTaskCocoa):
    Calls NetworkSessionCocoa::initializeEphemeralStatelessCookielessSession() lazily.
(WebKit::NetworkDataTaskCocoa::~NetworkDataTaskCocoa):
(WebKit::NetworkDataTaskCocoa::willPerformHTTPRedirection):
* NetworkProcess/cocoa/NetworkSessionCocoa.h:
* NetworkProcess/cocoa/NetworkSessionCocoa.mm:
(WebKit::NetworkSessionCocoa::initializeEphemeralStatelessCookielessSession):
(WebKit::NetworkSessionCocoa::invalidateAndCancel):
* Shared/WebCoreArgumentCoders.h:

LayoutTests:

Except for the details below, this patch introduces the utility functions
prepareTest() and tearDownAndFinish() and all applicable tests now make use
of them.

* http/tests/adClickAttribution/attribution-conversion-through-cross-site-image-redirect.html:
* http/tests/adClickAttribution/attribution-conversion-through-image-redirect-with-priority.html:
* http/tests/adClickAttribution/attribution-conversion-through-image-redirect-without-priority.html:
* http/tests/adClickAttribution/conversion-disabled-in-ephemeral-session-expected.txt: Added.
* http/tests/adClickAttribution/conversion-disabled-in-ephemeral-session.html: Copied from LayoutTests/http/tests/adClickAttribution/send-attribution-conversion-request.html.
* http/tests/adClickAttribution/resources/conversionReport.php:
    Now tries to set a cookie in the response.
* http/tests/adClickAttribution/resources/util.js: Added.
(prepareTest):
(tearDownAndFinish):
* http/tests/adClickAttribution/second-attribution-converted-with-higher-priority.html:
* http/tests/adClickAttribution/second-attribution-converted-with-lower-priority.html:
* http/tests/adClickAttribution/second-conversion-with-higher-priority.html:
* http/tests/adClickAttribution/second-conversion-with-lower-priority.html:
* http/tests/adClickAttribution/send-attribution-conversion-request-expected.txt:
* http/tests/adClickAttribution/send-attribution-conversion-request.html:
* http/tests/adClickAttribution/store-ad-click-attribution.html:
    Now sets a cookie which is checked for it in the conversion report.
* http/tests/adClickAttribution/store-disabled-in-ephemeral-session-expected.txt: Added.
* http/tests/adClickAttribution/store-disabled-in-ephemeral-session.html: Copied from LayoutTests/http/tests/adClickAttribution/store-ad-click-attribution.html.

Canonical link: https://commits.webkit.org/211350@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244475 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
johnwilander authored and cdumez committed Apr 20, 2019
1 parent 9cba4d8 commit 4783bc2f0c76eba57a48ce9526524defe033bcb3
Showing 31 changed files with 414 additions and 94 deletions.
@@ -1,3 +1,36 @@
2019-04-19 John Wilander <wilander@apple.com>

Disable Ad Click Attribution in ephemeral sessions and make sure conversion requests use an ephemeral, stateless session
https://bugs.webkit.org/show_bug.cgi?id=197108
<rdar://problem/49918702>

Reviewed by Alex Christensen.

Except for the details below, this patch introduces the utility functions
prepareTest() and tearDownAndFinish() and all applicable tests now make use
of them.

* http/tests/adClickAttribution/attribution-conversion-through-cross-site-image-redirect.html:
* http/tests/adClickAttribution/attribution-conversion-through-image-redirect-with-priority.html:
* http/tests/adClickAttribution/attribution-conversion-through-image-redirect-without-priority.html:
* http/tests/adClickAttribution/conversion-disabled-in-ephemeral-session-expected.txt: Added.
* http/tests/adClickAttribution/conversion-disabled-in-ephemeral-session.html: Copied from LayoutTests/http/tests/adClickAttribution/send-attribution-conversion-request.html.
* http/tests/adClickAttribution/resources/conversionReport.php:
Now tries to set a cookie in the response.
* http/tests/adClickAttribution/resources/util.js: Added.
(prepareTest):
(tearDownAndFinish):
* http/tests/adClickAttribution/second-attribution-converted-with-higher-priority.html:
* http/tests/adClickAttribution/second-attribution-converted-with-lower-priority.html:
* http/tests/adClickAttribution/second-conversion-with-higher-priority.html:
* http/tests/adClickAttribution/second-conversion-with-lower-priority.html:
* http/tests/adClickAttribution/send-attribution-conversion-request-expected.txt:
* http/tests/adClickAttribution/send-attribution-conversion-request.html:
* http/tests/adClickAttribution/store-ad-click-attribution.html:
Now sets a cookie which is checked for it in the conversion report.
* http/tests/adClickAttribution/store-disabled-in-ephemeral-session-expected.txt: Added.
* http/tests/adClickAttribution/store-disabled-in-ephemeral-session.html: Copied from LayoutTests/http/tests/adClickAttribution/store-ad-click-attribution.html.

2019-04-19 Timothy Hatcher <timothy@apple.com>

Standardize the `<meta name="color-scheme">` separator.
@@ -4,17 +4,14 @@
<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 that triggering of ad click attribution conversions through cross-site redirects do not work.</div>
<a id="targetLink" href="http://localhost:8000/adClickAttribution/attribution-conversion-through-cross-site-image-redirect.html?stepTwo" adcampaignid="3" addestination="http://localhost:8000">Link</a><br>
<div id="output"></div>
<script>
if (window.testRunner) {
testRunner.waitUntilDone();
testRunner.dumpAsText();
testRunner.setAllowsAnySSLCertificate(true);
}
prepareTest();

function activateElement(elementID) {
var element = document.getElementById(elementID);
@@ -25,7 +22,7 @@
},
function () {
document.getElementById("output").innerText = "FAIL Promise rejected.";
testRunner.notifyDone();
tearDownAndFinish();
}
);
}
@@ -40,7 +37,7 @@
testRunner.dumpAdClickAttribution();
document.body.removeChild(document.getElementById("targetLink"));
document.body.removeChild(document.getElementById("pixel"));
testRunner.notifyDone();
tearDownAndFinish();
};
document.body.appendChild(imageElement);
} else {
@@ -4,17 +4,14 @@
<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 triggering of ad click attribution conversions with priority.</div>
<a id="targetLink" href="http://localhost:8000/adClickAttribution/attribution-conversion-through-image-redirect-with-priority.html?stepTwo" adcampaignid="3" addestination="http://localhost:8000">Link</a><br>
<div id="output"></div>
<script>
if (window.testRunner) {
testRunner.waitUntilDone();
testRunner.dumpAsText();
testRunner.setAllowsAnySSLCertificate(true);
}
prepareTest();

function activateElement(elementID) {
var element = document.getElementById(elementID);
@@ -25,7 +22,7 @@
},
function () {
document.getElementById("output").innerText = "FAIL Promise rejected.";
testRunner.notifyDone();
tearDownAndFinish();
}
);
}
@@ -40,7 +37,7 @@
testRunner.dumpAdClickAttribution();
document.body.removeChild(document.getElementById("targetLink"));
document.body.removeChild(document.getElementById("pixel"));
testRunner.notifyDone();
tearDownAndFinish();
};
document.body.appendChild(imageElement);
} else {
@@ -4,17 +4,14 @@
<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 triggering of ad click attribution conversions without priority.</div>
<a id="targetLink" href="http://localhost:8000/adClickAttribution/attribution-conversion-through-image-redirect-without-priority.html?stepTwo" adcampaignid="3" addestination="http://localhost:8000">Link</a><br>
<div id="output"></div>
<script>
if (window.testRunner) {
testRunner.waitUntilDone();
testRunner.dumpAsText();
testRunner.setAllowsAnySSLCertificate(true);
}
prepareTest();

function activateElement(elementID) {
var element = document.getElementById(elementID);
@@ -25,7 +22,7 @@
},
function () {
document.getElementById("output").innerText = "FAIL Promise rejected.";
testRunner.notifyDone();
tearDownAndFinish();
}
);
}
@@ -40,7 +37,7 @@
testRunner.dumpAdClickAttribution();
document.body.removeChild(document.getElementById("targetLink"));
document.body.removeChild(document.getElementById("pixel"));
testRunner.notifyDone();
tearDownAndFinish();
};
document.body.appendChild(imageElement);
} else {
@@ -0,0 +1,15 @@
Tests that stored attributions cannot be converted in an ephemeral session.



--------
Frame: '<!--frame1-->'
--------
Conversion not received - timed out.

Unconverted Ad Click Attributions:
WebCore::AdClickAttribution 1
Source: 127.0.0.1
Destination: localhost
Campaign ID: 3
No conversion data.
@@ -0,0 +1,76 @@
<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true internal:AdClickAttributionEnabled=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 that stored attributions cannot be converted in an ephemeral session.</div>
<a id="targetLink" href="http://localhost:8000/adClickAttribution/conversion-disabled-in-ephemeral-session.html?stepTwo" adcampaignid="3" addestination="http://localhost:8000">Link</a><br>
<div id="output"></div>
<script>
const currentTimeMillis = (new Date()).getTime();
const highEntropyBits = currentTimeMillis - (Math.floor(currentTimeMillis / 1000000) * 1000000);
const nonce = highEntropyBits + "" + Math.floor(Math.random() * 100);

prepareTest();

if (window.testRunner)
testRunner.setAdClickAttributionConversionURLForTesting("http://127.0.0.1:8000/adClickAttribution/resources/conversionReport.php?nonce=" + nonce);

function activateElement(elementID) {
var element = document.getElementById(elementID);
var centerX = element.offsetLeft + element.offsetWidth / 2;
var centerY = element.offsetTop + element.offsetHeight / 2;
UIHelper.activateAt(centerX, centerY).then(
function () {
},
function () {
document.getElementById("output").innerText = "FAIL Promise rejected.";
tearDownAndFinish();
}
);
}

function appendIframe(url, onloadCallback) {
let iframeElement = document.createElement("iframe");
iframeElement.src = url;
if (onloadCallback)
iframeElement.onload = onloadCallback;
document.body.appendChild(iframeElement);
}

function appendConversionDataIframeAndFinish() {
testRunner.dumpAdClickAttribution();
document.body.removeChild(document.getElementById("targetLink"));
document.body.removeChild(document.getElementById("pixel"));

appendIframe("http://127.0.0.1:8000/adClickAttribution/resources/getConversionData.php?timeout_ms=1000&nonce=" + nonce, function() {
tearDownAndFinish();
});
}

function runTest() {
if (window.testRunner) {
if (window.location.search === "?stepTwo") {
testRunner.setPrivateBrowsingEnabled(true);
let imageElement = document.createElement("img");
imageElement.src = "https://127.0.0.1:8443/adClickAttribution/resources/redirectToConversion.php?conversionData=12&nonce=" + nonce;
imageElement.id = "pixel";
imageElement.onerror = function() {
appendConversionDataIframeAndFinish();
};
document.body.appendChild(imageElement);
} else {
document.cookie = "cookieSetAsFirstParty=1; path=/";
activateElement("targetLink");
}
} else {
document.getElementById("output").innerText = "FAIL No testRunner.";
}
}
</script>
</body>
</html>
@@ -24,4 +24,8 @@
}
fclose($conversionFile);
rename($conversionFilePath . ".tmp", $conversionFilePath);

header("HTTP/1.1 200 OK");
setcookie("cookieSetInConversionReport", "1", 0, "/");

?>
@@ -0,0 +1,18 @@
function prepareTest() {
if (window.testRunner) {
testRunner.waitUntilDone();
testRunner.dumpChildFramesAsText();
testRunner.dumpAsText();
testRunner.setAllowsAnySSLCertificate(true);
}
}

function tearDownAndFinish() {
if (window.testRunner) {
testRunner.setAllowsAnySSLCertificate(false);
testRunner.setAdClickAttributionOverrideTimerForTesting(false);
testRunner.setAdClickAttributionConversionURLForTesting("");
testRunner.setPrivateBrowsingEnabled(false);
testRunner.notifyDone();
}
}
@@ -4,6 +4,7 @@
<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 that a second attribution conversion with higher priority replaces an older with lower priority.</div>
@@ -24,19 +25,15 @@
}
];

prepareTest();

function configureLink(index) {
let linkElement = document.getElementById("targetLink");
linkElement.setAttribute("href", configuration[index].href);
linkElement.setAttribute("adcampaignid", configuration[index].adcampaignid);
linkElement.setAttribute("addestination", configuration[index].addestination);
}

if (window.testRunner) {
testRunner.waitUntilDone();
testRunner.dumpAsText();
testRunner.setAllowsAnySSLCertificate(true);
}

function activateElement(elementID) {
var element = document.getElementById(elementID);
var centerX = element.offsetLeft + element.offsetWidth / 2;
@@ -46,7 +43,7 @@
},
function () {
document.getElementById("output").innerText = "FAIL Promise rejected.";
testRunner.notifyDone();
tearDownAndFinish();
}
);
}
@@ -79,12 +76,12 @@
testRunner.dumpAdClickAttribution();
document.body.removeChild(document.getElementById("targetLink"));
document.body.removeChild(document.getElementById("pixel"));
testRunner.notifyDone();
tearDownAndFinish();
};
document.body.appendChild(imageElement);
} else {
document.getElementById("output").innerText = "FAIL Unknown window.location.search == " + window.location.search + ".";
testRunner.notifyDone();
tearDownAndFinish();
}
} else {
document.getElementById("output").innerText = "FAIL No testRunner.";
@@ -4,6 +4,7 @@
<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 that a second attribution conversion with lower priority does not replace an older with higher priority.</div>
@@ -24,19 +25,15 @@
}
];

prepareTest();

function configureLink(index) {
let linkElement = document.getElementById("targetLink");
linkElement.setAttribute("href", configuration[index].href);
linkElement.setAttribute("adcampaignid", configuration[index].adcampaignid);
linkElement.setAttribute("addestination", configuration[index].addestination);
}

if (window.testRunner) {
testRunner.waitUntilDone();
testRunner.dumpAsText();
testRunner.setAllowsAnySSLCertificate(true);
}

function activateElement(elementID) {
var element = document.getElementById(elementID);
var centerX = element.offsetLeft + element.offsetWidth / 2;
@@ -46,7 +43,7 @@
},
function () {
document.getElementById("output").innerText = "FAIL Promise rejected.";
testRunner.notifyDone();
tearDownAndFinish();
}
);
}
@@ -79,12 +76,12 @@
testRunner.dumpAdClickAttribution();
document.body.removeChild(document.getElementById("targetLink"));
document.body.removeChild(document.getElementById("pixel"));
testRunner.notifyDone();
tearDownAndFinish();
};
document.body.appendChild(imageElement);
} else {
document.getElementById("output").innerText = "FAIL Unknown window.location.search == " + window.location.search + ".";
testRunner.notifyDone();
tearDownAndFinish();
}
} else {
document.getElementById("output").innerText = "FAIL No testRunner.";

0 comments on commit 4783bc2

Please sign in to comment.