Disable Ad Click Attribution in ephemeral sessions and make sure conversion requests...
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 20 Apr 2019 00:00:26 +0000 (00:00 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 20 Apr 2019 00:00:26 +0000 (00:00 +0000)
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.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244475 268f45cc-cd09-0410-ab3c-d52691b4dbfc

31 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/adClickAttribution/attribution-conversion-through-cross-site-image-redirect.html
LayoutTests/http/tests/adClickAttribution/attribution-conversion-through-image-redirect-with-priority.html
LayoutTests/http/tests/adClickAttribution/attribution-conversion-through-image-redirect-without-priority.html
LayoutTests/http/tests/adClickAttribution/conversion-disabled-in-ephemeral-session-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/adClickAttribution/conversion-disabled-in-ephemeral-session.html [new file with mode: 0644]
LayoutTests/http/tests/adClickAttribution/resources/conversionReport.php
LayoutTests/http/tests/adClickAttribution/resources/util.js [new file with mode: 0644]
LayoutTests/http/tests/adClickAttribution/second-attribution-converted-with-higher-priority.html
LayoutTests/http/tests/adClickAttribution/second-attribution-converted-with-lower-priority.html
LayoutTests/http/tests/adClickAttribution/second-conversion-with-higher-priority.html
LayoutTests/http/tests/adClickAttribution/second-conversion-with-lower-priority.html
LayoutTests/http/tests/adClickAttribution/send-attribution-conversion-request-expected.txt
LayoutTests/http/tests/adClickAttribution/send-attribution-conversion-request.html
LayoutTests/http/tests/adClickAttribution/store-ad-click-attribution.html
LayoutTests/http/tests/adClickAttribution/store-disabled-in-ephemeral-session-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/adClickAttribution/store-disabled-in-ephemeral-session.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/html/HTMLAnchorElement.cpp
Source/WebCore/loader/ResourceLoader.cpp
Source/WebCore/platform/network/StoredCredentialsPolicy.h
Source/WebKit/ChangeLog
Source/WebKit/NetworkProcess/AdClickAttributionManager.cpp
Source/WebKit/NetworkProcess/NetworkLoadChecker.h
Source/WebKit/NetworkProcess/NetworkProcess.h
Source/WebKit/NetworkProcess/NetworkProcess.messages.in
Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp
Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm
Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.h
Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm
Source/WebKit/Shared/WebCoreArgumentCoders.h

index a751bdf..225c576 100644 (file)
@@ -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.
index 3124067..443af87 100644 (file)
@@ -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 {
index c5fb5f5..53d866f 100644 (file)
@@ -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 {
index 97ba52e..fb174b1 100644 (file)
@@ -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 {
diff --git a/LayoutTests/http/tests/adClickAttribution/conversion-disabled-in-ephemeral-session-expected.txt b/LayoutTests/http/tests/adClickAttribution/conversion-disabled-in-ephemeral-session-expected.txt
new file mode 100644 (file)
index 0000000..c34ab5d
--- /dev/null
@@ -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.
diff --git a/LayoutTests/http/tests/adClickAttribution/conversion-disabled-in-ephemeral-session.html b/LayoutTests/http/tests/adClickAttribution/conversion-disabled-in-ephemeral-session.html
new file mode 100644 (file)
index 0000000..c2f5fff
--- /dev/null
@@ -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>
index 3fbd8fb..e384212 100644 (file)
@@ -24,4 +24,8 @@ if (!$cookiesFound) {
 }
 fclose($conversionFile);
 rename($conversionFilePath . ".tmp", $conversionFilePath);
+
+header("HTTP/1.1 200 OK");
+setcookie("cookieSetInConversionReport", "1", 0, "/");
+
 ?>
diff --git a/LayoutTests/http/tests/adClickAttribution/resources/util.js b/LayoutTests/http/tests/adClickAttribution/resources/util.js
new file mode 100644 (file)
index 0000000..3f30c8c
--- /dev/null
@@ -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();
+    }
+}
\ No newline at end of file
index 49200f7..dd383ed 100644 (file)
@@ -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,6 +25,8 @@
         }
     ];
 
+    prepareTest();
+
     function configureLink(index) {
         let linkElement = document.getElementById("targetLink");
         linkElement.setAttribute("href", configuration[index].href);
         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();
             }
         );
     }
                     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.";
index c3e1883..7e81a97 100644 (file)
@@ -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,6 +25,8 @@
         }
     ];
 
+    prepareTest();
+
     function configureLink(index) {
         let linkElement = document.getElementById("targetLink");
         linkElement.setAttribute("href", configuration[index].href);
         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();
             }
         );
     }
                     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.";
index c8efe14..f59e44b 100644 (file)
@@ -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 the attribution is updated if it gets a second conversion with higher priority.</div>
@@ -19,6 +20,8 @@
         }
     ];
 
+    prepareTest();
+
     function configureLink(index) {
         let linkElement = document.getElementById("targetLink");
         linkElement.setAttribute("href", configuration[index].href);
         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;
@@ -41,7 +38,7 @@
             },
             function () {
                 document.getElementById("output").innerText = "FAIL Promise rejected.";
-                testRunner.notifyDone();
+                tearDownAndFinish();
             }
         );
     }
                         testRunner.dumpAdClickAttribution();
                         document.body.removeChild(document.getElementById("targetLink"));
                         document.body.removeChild(document.getElementById("pixel"));
-                        testRunner.notifyDone();
+                        tearDownAndFinish();
                     });
                 });
             } else {
                 document.getElementById("output").innerText = "FAIL Unknown window.location.search == " + window.location.search + ".";
-                testRunner.notifyDone();
+                tearDownAndFinish();
             }
         } else {
             document.getElementById("output").innerText = "FAIL No testRunner.";
index b6efba1..d8a914a 100644 (file)
@@ -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 the attribution is not updated if it gets a second conversion with lower priority.</div>
@@ -19,6 +20,8 @@
         }
     ];
 
+    prepareTest();
+
     function configureLink(index) {
         let linkElement = document.getElementById("targetLink");
         linkElement.setAttribute("href", configuration[index].href);
         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;
@@ -41,7 +38,7 @@
             },
             function () {
                 document.getElementById("output").innerText = "FAIL Promise rejected.";
-                testRunner.notifyDone();
+                tearDownAndFinish();
             }
         );
     }
@@ -72,7 +69,7 @@
                         testRunner.dumpAdClickAttribution();
                         document.body.removeChild(document.getElementById("targetLink"));
                         document.body.removeChild(document.getElementById("pixel"));
-                        testRunner.notifyDone();
+                        tearDownAndFinish();
                     });
                 });
             } else {
index 77e28b0..477b471 100644 (file)
@@ -1,13 +1,24 @@
-Tests sending of ad click attribution requests after a conversion.
+Tests sending of ad click attribution requests after a conversion. Also tests that cookies are not sent in those requests and cookies are not accepted in the responses.
 
 
 
 --------
 Frame: '<!--frame1-->'
 --------
+Cookies are: cookieSetAsFirstParty = 1
+
+--------
+Frame: '<!--frame2-->'
+--------
 Conversion received.
 HTTP_HOST: 127.0.0.1:8000
 REQUEST_URI: /adClickAttribution/resources/conversionReport.php?conversion=12&campaign=3
 No cookies in conversion request.
 
+
+--------
+Frame: '<!--frame3-->'
+--------
+Cookies are: cookieSetAsFirstParty = 1
+
 No stored Ad Click Attribution data.
index ea22698..437577c 100644 (file)
@@ -4,9 +4,10 @@
     <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 sending of ad click attribution requests after a conversion.</div>
+<div id="description">Tests sending of ad click attribution requests after a conversion. Also tests that cookies are not sent in those requests and cookies are not accepted in the responses.</div>
 <a id="targetLink" href="http://localhost:8000/adClickAttribution/send-attribution-conversion-request.html?stepTwo" adcampaignid="3" addestination="http://localhost:8000">Link</a><br>
 <div id="output"></div>
 <script>
     const highEntropyBits = currentTimeMillis - (Math.floor(currentTimeMillis / 1000000) * 1000000);
     const nonce = highEntropyBits + "" + Math.floor(Math.random() * 100);
 
+    prepareTest();
+
     if (window.testRunner) {
-        testRunner.waitUntilDone();
-        testRunner.dumpChildFramesAsText();
-        testRunner.setAllowsAnySSLCertificate(true);
-        testRunner.setAdClickAttributionConversionURLForTesting("http://127.0.0.1:8000/adClickAttribution/resources/conversionReport.php?nonce=" + nonce);
         testRunner.setAdClickAttributionOverrideTimerForTesting(true);
+        testRunner.setAdClickAttributionConversionURLForTesting("http://127.0.0.1:8000/adClickAttribution/resources/conversionReport.php?nonce=" + nonce);
     }
 
     function activateElement(elementID) {
             },
             function () {
                 document.getElementById("output").innerText = "FAIL Promise rejected.";
-                testRunner.notifyDone();
+                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"));
 
-        let iframeElement = document.createElement("iframe");
-        iframeElement.src = "http://127.0.0.1:8000/adClickAttribution/resources/getConversionData.php?endTest=true&timeout_ms=2000&nonce=" + nonce;
-        document.body.appendChild(iframeElement);
+        appendIframe("http://127.0.0.1:8000/cookies/resources/echo-cookies.php");
+        appendIframe("http://127.0.0.1:8000/adClickAttribution/resources/getConversionData.php?timeout_ms=2000&nonce=" + nonce, function() {
+            appendIframe("http://127.0.0.1:8000/cookies/resources/echo-cookies.php", function() {
+                tearDownAndFinish();
+            });
+        });
     }
 
     function runTest() {
@@ -57,6 +68,7 @@
                 };
                 document.body.appendChild(imageElement);
             } else {
+                document.cookie = "cookieSetAsFirstParty=1; path=/";
                 activateElement("targetLink");
             }
         } else {
index f6601d6..c7146d0 100644 (file)
@@ -4,16 +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 storage of ad click attribution.</div>
 <a id="targetLink" href="http://localhost:8000/adClickAttribution/store-ad-click-attribution.html?stepTwo" adcampaignid="3" addestination="http://localhost:8000">Link</a><br>
 <div id="output"></div>
 <script>
-    if (window.testRunner) {
-        testRunner.waitUntilDone();
-        testRunner.dumpAsText();
-    }
+    prepareTest();
 
     function activateElement(elementID) {
         var element = document.getElementById(elementID);
@@ -24,7 +22,7 @@
             },
             function () {
                 document.getElementById("output").innerText = "FAIL Promise rejected.";
-                testRunner.notifyDone();
+                tearDownAndFinish();
             }
         );
     }
@@ -34,7 +32,7 @@
             if (window.location.search === "?stepTwo") {
                 testRunner.dumpAdClickAttribution();
                 document.body.removeChild(document.getElementById("targetLink"));
-                testRunner.notifyDone();
+                tearDownAndFinish();
             } else {
                 activateElement("targetLink");
             }
diff --git a/LayoutTests/http/tests/adClickAttribution/store-disabled-in-ephemeral-session-expected.txt b/LayoutTests/http/tests/adClickAttribution/store-disabled-in-ephemeral-session-expected.txt
new file mode 100644 (file)
index 0000000..0e33b75
--- /dev/null
@@ -0,0 +1,5 @@
+Tests that storage of ad click attribution is disabled in ephemeral sessions.
+
+
+
+No stored Ad Click Attribution data.
diff --git a/LayoutTests/http/tests/adClickAttribution/store-disabled-in-ephemeral-session.html b/LayoutTests/http/tests/adClickAttribution/store-disabled-in-ephemeral-session.html
new file mode 100644 (file)
index 0000000..f575e51
--- /dev/null
@@ -0,0 +1,48 @@
+<!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 storage of ad click attribution is disabled in ephemeral sessions.</div>
+<a id="targetLink" href="http://localhost:8000/adClickAttribution/store-disabled-in-ephemeral-session.html?stepTwo" adcampaignid="3" addestination="http://localhost:8000">Link</a><br>
+<div id="output"></div>
+<script>
+    prepareTest();
+
+    if (window.testRunner)
+        testRunner.setPrivateBrowsingEnabled(true);
+
+    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.dumpAdClickAttribution();
+                document.body.removeChild(document.getElementById("targetLink"));
+                tearDownAndFinish();
+            } else {
+                activateElement("targetLink");
+            }
+        } else {
+            document.getElementById("output").innerText = "FAIL No testRunner.";
+        }
+    }
+</script>
+</body>
+</html>
index ef3ecc4..c86c461 100644 (file)
@@ -1,3 +1,23 @@
+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.
+
+        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.
+
 2019-04-19  Timothy Hatcher  <timothy@apple.com>
 
         Standardize the <meta name="color-scheme"> separator.
index 5a1dce8..65a59b2 100644 (file)
@@ -405,7 +405,9 @@ Optional<AdClickAttribution> HTMLAnchorElement::parseAdClickAttribution() const
     using Source = AdClickAttribution::Source;
     using Destination = AdClickAttribution::Destination;
 
-    if (!RuntimeEnabledFeatures::sharedFeatures().adClickAttributionEnabled() || !UserGestureIndicator::processingUserGesture())
+    if (document().sessionID().isEphemeral()
+        || !RuntimeEnabledFeatures::sharedFeatures().adClickAttributionEnabled()
+        || !UserGestureIndicator::processingUserGesture())
         return WTF::nullopt;
 
     if (!hasAttributeWithoutSynchronization(adcampaignidAttr) && !hasAttributeWithoutSynchronization(addestinationAttr))
index 54898ef..304b219 100644 (file)
@@ -717,7 +717,7 @@ void ResourceLoader::cannotShowURL(ResourceHandle*)
 
 bool ResourceLoader::shouldUseCredentialStorage()
 {
-    if (m_options.storedCredentialsPolicy == StoredCredentialsPolicy::DoNotUse)
+    if (m_options.storedCredentialsPolicy != StoredCredentialsPolicy::Use)
         return false;
 
     Ref<ResourceLoader> protectedThis(*this);
index 136cd71..1495a08 100644 (file)
 
 namespace WebCore {
 
-enum class StoredCredentialsPolicy : bool {
+enum class StoredCredentialsPolicy : uint8_t {
     DoNotUse,
     Use,
+    EphemeralStatelessCookieless
 };
 
 } // namespace WebCore
index 5901241..b7c93bc 100644 (file)
@@ -1,3 +1,44 @@
+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.
+
+        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:
+
 2019-04-19  Daniel Bates  <dabates@apple.com>
 
         Use RetainPtr and rename +autocorrectionRectsWithRects:lastRect: to +autocorrectionRectsWithFirstCGRect:lastCGRect:
index 45358a9..c799799 100644 (file)
@@ -119,9 +119,8 @@ void AdClickAttributionManager::fireConversionRequest(const AdClickAttribution&
     loadParameters.request = request;
     loadParameters.sourceOrigin = SecurityOrigin::create(conversionReferrerURL);
     loadParameters.parentPID = presentingApplicationPID();
-    // FIXME: Switch to the use of an ephemeral, stateless session.
     loadParameters.sessionID = PAL::SessionID::defaultSessionID();
-    loadParameters.storedCredentialsPolicy = StoredCredentialsPolicy::DoNotUse;
+    loadParameters.storedCredentialsPolicy = StoredCredentialsPolicy::EphemeralStatelessCookieless;
     loadParameters.options = options;
     loadParameters.shouldClearReferrerOnHTTPSToHTTPRedirect = true;
     loadParameters.shouldRestrictHTTPResponseAccess = false;
@@ -181,7 +180,7 @@ void AdClickAttributionManager::clear(CompletionHandler<void()>&& completionHand
 void AdClickAttributionManager::toString(CompletionHandler<void(String)>&& completionHandler) const
 {
     if (m_unconvertedAdClickAttributionMap.isEmpty() && m_convertedAdClickAttributionMap.isEmpty())
-        return completionHandler("No stored Ad Click Attribution data.\n"_s);
+        return completionHandler("\nNo stored Ad Click Attribution data.\n"_s);
 
     unsigned unconvertedAttributionNumber = 0;
     StringBuilder builder;
index 829f7c2..31d11c3 100644 (file)
@@ -41,7 +41,7 @@ class ContentSecurityPolicy;
 struct ContentSecurityPolicyClient;
 class SecurityOrigin;
 enum class PreflightPolicy : uint8_t;
-enum class StoredCredentialsPolicy : bool;
+enum class StoredCredentialsPolicy : uint8_t;
 }
 
 namespace WebKit {
index 78cebd4..89c2985 100644 (file)
@@ -77,7 +77,7 @@ class NetworkStorageSession;
 class ResourceError;
 class SWServer;
 enum class IncludeHttpOnlyCookies : bool;
-enum class StoredCredentialsPolicy : bool;
+enum class StoredCredentialsPolicy : uint8_t;
 struct ClientOrigin;
 struct MessageWithMessagePorts;
 struct SecurityOriginData;
index 8764688..1bdd5bd 100644 (file)
@@ -82,7 +82,7 @@ messages -> NetworkProcess LegacyReceiver {
     CancelPrepareToSuspend()
     ProcessDidResume()
 
-    PreconnectTo(URL url, enum:bool WebCore::StoredCredentialsPolicy storedCredentialsPolicy);
+    PreconnectTo(URL url, enum:uint8_t WebCore::StoredCredentialsPolicy storedCredentialsPolicy);
 
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
     ClearPrevalentResource(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain) -> () Async
index f1459d7..cb1794d 100644 (file)
@@ -586,13 +586,15 @@ void NetworkResourceLoader::willSendRedirectedRequest(ResourceRequest&& request,
     ++m_redirectCount;
 
     auto& redirectURL = redirectRequest.url();
-    if (auto adClickConversion = AdClickAttribution::parseConversionRequest(redirectURL)) {
-        RegistrableDomain redirectDomain { redirectURL };
-        auto& firstPartyURL = redirectRequest.firstPartyForCookies();
-        NetworkSession* networkSession;
-        // The redirect has to be done by the same registrable domain and it has to be a third-party request.
-        if (redirectDomain.matches(request.url()) && !redirectDomain.matches(firstPartyURL) && (networkSession = m_connection->networkProcess().networkSession(sessionID())))
-            networkSession->convertAdClickAttribution(AdClickAttribution::Source { WTFMove(redirectDomain) }, AdClickAttribution::Destination { firstPartyURL }, WTFMove(*adClickConversion));
+    if (!sessionID().isEphemeral()) {
+        if (auto adClickConversion = AdClickAttribution::parseConversionRequest(redirectURL)) {
+            RegistrableDomain redirectDomain { redirectURL };
+            auto& firstPartyURL = redirectRequest.firstPartyForCookies();
+            NetworkSession* networkSession = nullptr;
+            // The redirect has to be done by the same registrable domain and it has to be a third-party request.
+            if (redirectDomain.matches(request.url()) && !redirectDomain.matches(firstPartyURL) && (networkSession = m_connection->networkProcess().networkSession(sessionID())))
+                networkSession->convertAdClickAttribution(AdClickAttribution::Source { WTFMove(redirectDomain) }, AdClickAttribution::Destination { firstPartyURL }, WTFMove(*adClickConversion));
+        }
     }
 
     auto maxAgeCap = validateCacheEntryForMaxAgeCapValidation(request, redirectRequest, redirectResponse);
index 1d0a59f..35e443b 100644 (file)
@@ -193,7 +193,7 @@ NetworkDataTaskCocoa::NetworkDataTaskCocoa(NetworkSession& session, NetworkDataT
 
     bool shouldBlockCookies = false;
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
-    shouldBlockCookies = session.networkStorageSession().shouldBlockCookies(request, frameID, pageID);
+    shouldBlockCookies = storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless || session.networkStorageSession().shouldBlockCookies(request, frameID, pageID);
 #endif
     restrictRequestReferrerToOriginIfNeeded(request, shouldBlockCookies);
 
@@ -201,16 +201,27 @@ NetworkDataTaskCocoa::NetworkDataTaskCocoa(NetworkSession& session, NetworkDataT
     applySniffingPoliciesAndBindRequestToInferfaceIfNeeded(nsRequest, shouldContentSniff == WebCore::ContentSniffingPolicy::SniffContent && !url.isLocalFile(), shouldContentEncodingSniff == WebCore::ContentEncodingSniffingPolicy::Sniff);
 
     auto& cocoaSession = static_cast<NetworkSessionCocoa&>(m_session.get());
-    if (storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::Use) {
+    switch (storedCredentialsPolicy) {
+    case WebCore::StoredCredentialsPolicy::Use:
         m_task = [cocoaSession.m_sessionWithCredentialStorage dataTaskWithRequest:nsRequest];
         ASSERT(!cocoaSession.m_dataTaskMapWithCredentials.contains([m_task taskIdentifier]));
         cocoaSession.m_dataTaskMapWithCredentials.add([m_task taskIdentifier], this);
         LOG(NetworkSession, "%llu Creating stateful NetworkDataTask with URL %s", [m_task taskIdentifier], nsRequest.URL.absoluteString.UTF8String);
-    } else {
+        break;
+    case WebCore::StoredCredentialsPolicy::DoNotUse:
         m_task = [cocoaSession.m_statelessSession dataTaskWithRequest:nsRequest];
         ASSERT(!cocoaSession.m_dataTaskMapWithoutState.contains([m_task taskIdentifier]));
         cocoaSession.m_dataTaskMapWithoutState.add([m_task taskIdentifier], this);
         LOG(NetworkSession, "%llu Creating stateless NetworkDataTask with URL %s", [m_task taskIdentifier], nsRequest.URL.absoluteString.UTF8String);
+        break;
+    case WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless:
+        if (!cocoaSession.m_ephemeralStatelessCookielessSession)
+            cocoaSession.initializeEphemeralStatelessCookielessSession();
+        m_task = [cocoaSession.m_ephemeralStatelessCookielessSession dataTaskWithRequest:nsRequest];
+        ASSERT(!cocoaSession.m_dataTaskMapEphemeralStatelessCookieless.contains([m_task taskIdentifier]));
+        cocoaSession.m_dataTaskMapEphemeralStatelessCookieless.add([m_task taskIdentifier], this);
+        LOG(NetworkSession, "%llu Creating ephemeral, stateless, cookieless NetworkDataTask with URL %s", [m_task taskIdentifier], nsRequest.URL.absoluteString.UTF8String);
+        break;
     }
 
     if (shouldPreconnectOnly == PreconnectOnly::Yes) {
@@ -250,12 +261,19 @@ NetworkDataTaskCocoa::~NetworkDataTaskCocoa()
         return;
 
     auto& cocoaSession = static_cast<NetworkSessionCocoa&>(m_session.get());
-    if (m_storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::Use) {
+    switch (m_storedCredentialsPolicy) {
+    case WebCore::StoredCredentialsPolicy::Use:
         ASSERT(cocoaSession.m_dataTaskMapWithCredentials.get([m_task taskIdentifier]) == this);
         cocoaSession.m_dataTaskMapWithCredentials.remove([m_task taskIdentifier]);
-    } else {
+        break;
+    case WebCore::StoredCredentialsPolicy::DoNotUse:
         ASSERT(cocoaSession.m_dataTaskMapWithoutState.get([m_task taskIdentifier]) == this);
         cocoaSession.m_dataTaskMapWithoutState.remove([m_task taskIdentifier]);
+        break;
+    case WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless:
+        ASSERT(cocoaSession.m_dataTaskMapEphemeralStatelessCookieless.get([m_task taskIdentifier]) == this);
+        cocoaSession.m_dataTaskMapEphemeralStatelessCookieless.remove([m_task taskIdentifier]);
+        break;
     }
 }
 
@@ -345,7 +363,7 @@ void NetworkDataTaskCocoa::willPerformHTTPRedirection(WebCore::ResourceResponse&
         request.setFirstPartyForCookies(request.url());
 
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
-    bool shouldBlockCookies = m_session->networkStorageSession().shouldBlockCookies(request, m_frameID, m_pageID);
+    bool shouldBlockCookies = m_storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless || m_session->networkStorageSession().shouldBlockCookies(request, m_frameID, m_pageID);
 #if !RELEASE_LOG_DISABLED
     if (m_session->shouldLogCookieInformation())
         RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), Network, "%p - NetworkDataTaskCocoa::willPerformHTTPRedirection::logCookieInformation: pageID = %llu, frameID = %llu, taskID = %lu: %s cookies for redirect URL %s", this, m_pageID, m_frameID, (unsigned long)[m_task taskIdentifier], (shouldBlockCookies ? "Blocking" : "Not blocking"), request.url().string().utf8().data());
index 4b508cb..3d1a49f 100644 (file)
@@ -47,6 +47,8 @@ public:
     static Ref<NetworkSession> create(NetworkProcess&, NetworkSessionCreationParameters&&);
     ~NetworkSessionCocoa();
 
+    void initializeEphemeralStatelessCookielessSession();
+
     const String& sourceApplicationBundleIdentifier() const;
     const String& sourceApplicationSecondaryIdentifier() const;
     // Must be called before any NetworkSession has been created.
@@ -77,12 +79,15 @@ private:
 
     HashMap<NetworkDataTaskCocoa::TaskIdentifier, NetworkDataTaskCocoa*> m_dataTaskMapWithCredentials;
     HashMap<NetworkDataTaskCocoa::TaskIdentifier, NetworkDataTaskCocoa*> m_dataTaskMapWithoutState;
+    HashMap<NetworkDataTaskCocoa::TaskIdentifier, NetworkDataTaskCocoa*> m_dataTaskMapEphemeralStatelessCookieless;
     HashMap<NetworkDataTaskCocoa::TaskIdentifier, DownloadID> m_downloadMap;
 
     RetainPtr<NSURLSession> m_sessionWithCredentialStorage;
     RetainPtr<WKNetworkSessionDelegate> m_sessionWithCredentialStorageDelegate;
     RetainPtr<NSURLSession> m_statelessSession;
     RetainPtr<WKNetworkSessionDelegate> m_statelessSessionDelegate;
+    RetainPtr<NSURLSession> m_ephemeralStatelessCookielessSession;
+    RetainPtr<WKNetworkSessionDelegate> m_ephemeralStatelessCookielessSessionDelegate;
 
     String m_boundInterfaceIdentifier;
     String m_sourceApplicationBundleIdentifier;
index 24758ff..60bca0b 100644 (file)
@@ -998,14 +998,38 @@ NetworkSessionCocoa::~NetworkSessionCocoa()
 {
 }
 
+void NetworkSessionCocoa::initializeEphemeralStatelessCookielessSession()
+{
+    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
+    NSURLSessionConfiguration *existingConfiguration = m_statelessSession.get().configuration;
+
+    configuration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyNever;
+    configuration.URLCredentialStorage = nil;
+    configuration.URLCache = nil;
+    configuration.allowsCellularAccess = existingConfiguration.allowsCellularAccess;
+    configuration.connectionProxyDictionary = existingConfiguration.connectionProxyDictionary;
+
+    configuration._shouldSkipPreferredClientCertificateLookup = YES;
+    configuration._sourceApplicationAuditTokenData = existingConfiguration._sourceApplicationAuditTokenData;
+    configuration._sourceApplicationSecondaryIdentifier = existingConfiguration._sourceApplicationSecondaryIdentifier;
+#if PLATFORM(IOS_FAMILY)
+    configuration._CTDataConnectionServiceType = existingConfiguration._CTDataConnectionServiceType;
+#endif
+
+    m_ephemeralStatelessCookielessSessionDelegate = adoptNS([[WKNetworkSessionDelegate alloc] initWithNetworkSession:*this withCredentials:false]);
+    m_ephemeralStatelessCookielessSession = [NSURLSession sessionWithConfiguration:configuration delegate:static_cast<id>(m_ephemeralStatelessCookielessSessionDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
+}
+
 void NetworkSessionCocoa::invalidateAndCancel()
 {
     NetworkSession::invalidateAndCancel();
 
     [m_sessionWithCredentialStorage invalidateAndCancel];
     [m_statelessSession invalidateAndCancel];
+    [m_ephemeralStatelessCookielessSession invalidateAndCancel];
     [m_sessionWithCredentialStorageDelegate sessionInvalidated];
     [m_statelessSessionDelegate sessionInvalidated];
+    [m_ephemeralStatelessCookielessSessionDelegate sessionInvalidated];
 }
 
 void NetworkSessionCocoa::clearCredentials()
index ed027eb..d882fb6 100644 (file)
@@ -854,6 +854,15 @@ template <> struct EnumTraits<WebCore::WorkerType> {
     >;
 };
 
+template<> struct EnumTraits<WebCore::StoredCredentialsPolicy> {
+    using values = EnumValues<
+        WebCore::StoredCredentialsPolicy,
+        WebCore::StoredCredentialsPolicy::DoNotUse,
+        WebCore::StoredCredentialsPolicy::Use,
+        WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless
+    >;
+};
+
 #if USE(CURL)
 template <> struct EnumTraits<WebCore::CurlProxySettings::Mode> {
     using values = EnumValues<