Diff
Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/capped-lifetime-for-cookie-set-in-js-24-hours.html (0 => 295391)
--- trunk/LayoutTests/http/tests/resourceLoadStatistics/capped-lifetime-for-cookie-set-in-js-24-hours.html (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/capped-lifetime-for-cookie-set-in-js-24-hours.html 2022-06-08 19:06:03 UTC (rev 295391)
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src=""
+ <script src=""
+</head>
+<body>
+<script>
+ description("Check that cookies created by _javascript_ with max-age or expiry longer than a week get capped to a week.");
+ jsTestIsAsync = true;
+
+ if (internals)
+ internals.setResourceLoadStatisticsEnabled(true);
+
+ let passedTests = 0;
+ function checkThatCookieDoesNotExpireAfter(cookieData, maxAgeInSeconds) {
+ let now = new Date();
+ let maxExpiryDateInMilliseconds = now.getTime() + (maxAgeInSeconds * 1000);
+
+ if (maxExpiryDateInMilliseconds > cookieData["expires"])
+ ++passedTests;
+ else
+ testFailed("Cookie named " + cookieData["name"] + " expires in more than " + maxAgeInSeconds + " seconds.");
+ }
+
+ const twoDaysInSeconds = 2 * 24 * 60 * 60;
+ const shortLivedCookieMaxAge = { name : "shortLivedCookieMaxAge", lifetime : "Max-Age=" + twoDaysInSeconds + ";" };
+ document.cookie = shortLivedCookieMaxAge.name + "=foobar; " + shortLivedCookieMaxAge.lifetime + " path=/";
+
+ const twoDaysAsExpiresDate = createExpiresDateFromMaxAge(twoDaysInSeconds);
+ const shortLivedCookieExpires = { name : "shortLivedCookieExpires", lifetime : "Expires=" + twoDaysAsExpiresDate + ";" };
+ document.cookie = shortLivedCookieExpires.name + "=foobar; " + shortLivedCookieExpires.lifetime + " path=/";
+
+ const _oneWeekInSeconds_ = 7 * 24 * 60 * 60;
+ const twoWeeksInSeconds = 2 * oneWeekInSeconds;
+ const longLivedCookieMaxAge = { name : "longLivedCookieMaxAge", lifetime : "Max-Age=" + twoWeeksInSeconds + ";" };
+ document.cookie = longLivedCookieMaxAge.name + "=foobar; " + longLivedCookieMaxAge.lifetime + " path=/";
+
+ const twoWeeksAsExpiresDate = createExpiresDateFromMaxAge(twoWeeksInSeconds);
+ const longLivedCookieExpires = { name : "longLivedCookieExpires", lifetime : "Expires=" + twoWeeksAsExpiresDate + ";" };
+ document.cookie = longLivedCookieExpires.name + "=foobar; " + longLivedCookieExpires.lifetime + " path=/";
+
+ const overTwoDaysInSeconds = twoDaysInSeconds + 30;
+ const overTwoWeeksInSeconds = twoWeeksInSeconds + 30;
+ if (internals) {
+ let cookies = internals.getCookies();
+ if (!cookies.length)
+ testFailed("No cookies found.");
+ for (let cookie of cookies) {
+ switch (cookie.name) {
+ case shortLivedCookieMaxAge.name:
+ checkThatCookieDoesNotExpireAfter(cookie, overTwoDaysInSeconds);
+ break;
+ case shortLivedCookieExpires.name:
+ checkThatCookieDoesNotExpireAfter(cookie, overTwoDaysInSeconds);
+ break;
+ case longLivedCookieMaxAge.name:
+ checkThatCookieDoesNotExpireAfter(cookie, overTwoWeeksInSeconds);
+ break;
+ case longLivedCookieExpires.name:
+ checkThatCookieDoesNotExpireAfter(cookie, overTwoWeeksInSeconds);
+ break;
+ }
+ }
+
+ resetCookiesForCurrentOrigin();
+
+ if (passedTests === 4) {
+ testPassed("The two short-lived cookies don't expire after more than " + overTwoDaysInSeconds + " seconds.");
+ testPassed("The two long-lived cookies don't expire after more than " + overTwoWeeksInSeconds + " seconds.");
+ } else
+ testFailed("At least one cookie's expiry attribute was beyond the test thresholds.");
+ } else
+ testFailed("No internals object.");
+
+ if (internals)
+ internals.setResourceLoadStatisticsEnabled(false);
+
+ finishJSTest();
+</script>
+</body>
+</html>
Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/website-data-removal-for-site-navigated-to-with-link-decoration-js-cookie-checking.html (0 => 295391)
--- trunk/LayoutTests/http/tests/resourceLoadStatistics/website-data-removal-for-site-navigated-to-with-link-decoration-js-cookie-checking.html (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/website-data-removal-for-site-navigated-to-with-link-decoration-js-cookie-checking.html 2022-06-08 19:06:03 UTC (rev 295391)
@@ -0,0 +1,254 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src=""
+ <script src=""
+</head>
+<body _onload_="setTimeout('runTest()', 0)">
+<div id="description">Check that non-cookie website data gets removed after a navigation with link decoration from a prevalent resource.</div>
+<br>
+<div id="output"></div>
+<br>
+<script>
+ testRunner.waitUntilDone();
+ testRunner.dumpAsText();
+
+ const httpOnlyCookieName = "http-only-cookie";
+ const serverSideCookieName = "server-side-cookie";
+ const clientSideCookieName = "client-side-cookie";
+
+ function sortStringArray(a, b) {
+ a = a.toLowerCase();
+ b = b.toLowerCase();
+
+ return a > b ? 1 : b > a ? -1 : 0;
+ }
+
+ function addLinebreakToOutput() {
+ let element = document.createElement("br");
+ output.appendChild(element);
+ }
+
+ function addOutput(message) {
+ let element = document.createElement("div");
+ element.innerText = message;
+ output.appendChild(element);
+ }
+
+ function checkCookies(isAfterDeletion) {
+ let unsortedTestPassedMessages = [];
+ let cookies = internals.getCookies();
+ if (!cookies.length)
+ testFailed((isAfterDeletion ? "After" : "Before") + " script-accessible deletion: No cookies found.");
+ for (let cookie of cookies) {
+ switch (cookie.name) {
+ case httpOnlyCookieName:
+ unsortedTestPassedMessages.push((isAfterDeletion ? "After" : "Before") + " deletion: " + (isAfterDeletion ? " " : "") + "HttpOnly cookie exists.");
+ break;
+ case serverSideCookieName:
+ unsortedTestPassedMessages.push((isAfterDeletion ? "After" : "Before") + " deletion: Regular server-side cookie exists.");
+ break;
+ case clientSideCookieName:
+ unsortedTestPassedMessages.push((isAfterDeletion ? "After" : "Before") + " deletion: Client-side cookie exists.");
+ break;
+ }
+ }
+
+ if (!cookies.includes(clientSideCookieName) && isAfterDeletion)
+ unsortedTestPassedMessages.push("After deletion: Client-side cookie does not exist.");
+
+ let sortedTestPassedMessages = unsortedTestPassedMessages.sort(sortStringArray);
+ for (let testPassedMessage of sortedTestPassedMessages) {
+ addOutput(testPassedMessage);
+ }
+ }
+
+ const dbName = "TestDatabase";
+
+ function createIDBDataStore(callback) {
+ let request = indexedDB.open(dbName);
+ request._onerror_ = function() {
+ addOutput("Couldn't create indexedDB.");
+ finishTest();
+ };
+ request._onupgradeneeded_ = function(event) {
+ let db = event.target.result;
+ let objStore = db.createObjectStore("test", {autoIncrement: true});
+ objStore.add("value");
+ callback();
+ }
+ }
+
+ const maxIntervals = 20;
+
+ let intervalCounterIDB;
+ let checkIDBCallback;
+ let checkIDBIntervalID;
+ let semaphoreIDBCheck = false;
+ function checkIDBDataStoreExists(isAfterDeletion, callback) {
+ let request;
+ intervalCounterIDB = 0;
+ checkIDBCallback = callback;
+ if (!isAfterDeletion) {
+ // Check until there is a IDB.
+ checkIDBIntervalID = setInterval(function() {
+ if (semaphoreIDBCheck)
+ return;
+ semaphoreIDBCheck = true;
+
+ if (++intervalCounterIDB >= maxIntervals) {
+ clearInterval(checkIDBIntervalID);
+ addOutput("Before deletion: IDB entry does not exist.");
+ semaphoreIDBCheck = false;
+ checkIDBCallback();
+ } else {
+ request = indexedDB.open(dbName);
+ request._onerror_ = function () {
+ clearInterval(checkIDBIntervalID);
+ addOutput("Couldn't open indexedDB.");
+ semaphoreIDBCheck = false;
+ finishTest();
+ };
+ request._onupgradeneeded_ = function () {
+ // Let the next interval check again.
+ semaphoreIDBCheck = false;
+ };
+ request._onsuccess_ = function () {
+ clearInterval(checkIDBIntervalID);
+ addOutput("Before deletion: IDB entry does exist.");
+ semaphoreIDBCheck = false;
+ checkIDBCallback();
+ };
+ }
+ }, 200);
+ } else {
+ // Check until there is no IDB.
+ checkIDBIntervalID = setInterval(function () {
+ if (semaphoreIDBCheck)
+ return;
+ semaphoreIDBCheck = true;
+
+ if (++intervalCounterIDB >= maxIntervals) {
+ clearInterval(checkIDBIntervalID);
+ addOutput("After deletion: IDB entry checks exhausted.");
+ semaphoreIDBCheck = false;
+ checkIDBCallback();
+ } else {
+ request = indexedDB.open(dbName);
+ request._onerror_ = function () {
+ clearInterval(checkIDBIntervalID);
+ addOutput("Couldn't open indexedDB.");
+ semaphoreIDBCheck = false;
+ finishTest();
+ };
+ request._onupgradeneeded_ = function () {
+ clearInterval(checkIDBIntervalID);
+ addOutput("After deletion: IDB entry does not exist.");
+ semaphoreIDBCheck = false;
+ checkIDBCallback();
+ };
+ request._onsuccess_ = function () {
+ // Let the next interval check again.
+ semaphoreIDBCheck = false;
+ };
+ }
+ }, 200);
+ }
+ }
+
+ let intervalCounterLocalStorage;
+ let checkLocalStorageCallback;
+ let checkLocalStorageIntervalID;
+ const localStorageName = "test";
+ const localStorageValue = "value";
+ function checkLocalStorageExists(isAfterDeletion, callback) {
+ intervalCounterLocalStorage = 0;
+ checkLocalStorageCallback = callback;
+ if (!isAfterDeletion) {
+ // Check until there is LocalStorage.
+ checkLocalStorageIntervalID = setInterval(function() {
+ if (++intervalCounterLocalStorage >= maxIntervals) {
+ clearInterval(checkLocalStorageIntervalID);
+ let value = localStorage.getItem(localStorageName);
+ addOutput("Before deletion: LocalStorage entry " + (value === localStorageValue ? "does" : "does not") + " exist.");
+ checkLocalStorageCallback();
+ } else if (testRunner.isStatisticsHasLocalStorage(destinationOrigin)) {
+ clearInterval(checkLocalStorageIntervalID);
+ let value = localStorage.getItem(localStorageName);
+ addOutput("Before deletion: LocalStorage entry " + (value === localStorageValue ? "does" : "does not") + " exist.");
+ checkLocalStorageCallback();
+ }
+ }, 100);
+ } else {
+ // Check until there is no LocalStorage.
+ checkLocalStorageIntervalID = setInterval(function() {
+ if (++intervalCounterLocalStorage >= maxIntervals) {
+ clearInterval(checkLocalStorageIntervalID);
+ let value = localStorage.getItem(localStorageName);
+ addOutput("After deletion: LocalStorage entry " + (value === localStorageValue ? "does" : "does not") + " exist.");
+ checkLocalStorageCallback();
+ } else if (!testRunner.isStatisticsHasLocalStorage(destinationOrigin)) {
+ clearInterval(checkLocalStorageIntervalID);
+ let value = localStorage.getItem(localStorageName);
+ addOutput("After deletion: LocalStorage entry " + (value === localStorageValue ? "does" : "does not") + " exist.");
+ checkLocalStorageCallback();
+ }
+ }, 100);
+ }
+ }
+
+ async function writeWebsiteDataAndContinue() {
+ // Write cookies.
+ await fetch("/cookies/resources/set-http-only-cookie.py?cookieName=" + httpOnlyCookieName, { credentials: "same-origin" });
+ await fetch("/cookies/resources/setCookies.cgi", { headers: { "Set-Cookie": serverSideCookieName + "=1; path=/;" }, credentials: "same-origin" });
+ document.cookie = clientSideCookieName + "=1";
+
+ checkCookies(false);
+
+ // Write LocalStorage
+ localStorage.setItem(localStorageName, localStorageValue);
+ checkLocalStorageExists(false, function() {
+
+ // Write IndexedDB.
+ createIDBDataStore(function () {
+ checkIDBDataStoreExists(false, function() {
+ addLinebreakToOutput();
+ processWebsiteDataAndContinue();
+ });
+ });
+ });
+ }
+
+ function processWebsiteDataAndContinue() {
+ testRunner.installStatisticsDidScanDataRecordsCallback(checkWebsiteDataAndContinue);
+ testRunner.statisticsProcessStatisticsAndDataRecords();
+ }
+
+ function checkWebsiteDataAndContinue() {
+ checkCookies(true);
+ checkLocalStorageExists(true, function () {
+ checkIDBDataStoreExists(true, finishTest);
+ });
+ }
+
+ async function finishTest() {
+ await resetCookiesITP();
+ testRunner.dumpResourceLoadStatistics();
+ setEnableFeature(false, function() {
+ testRunner.notifyDone();
+ });
+ }
+
+ const prevalentResourceOrigin = "http://localhost:8000";
+ const destinationOrigin = "http://127.0.0.1:8000";
+ function runTest() {
+ setEnableFeature(true, function () {
+ testRunner.setStatisticsPrevalentResource(prevalentResourceOrigin, true, function() {
+ testRunner.setStatisticsCrossSiteLoadWithLinkDecoration(prevalentResourceOrigin, destinationOrigin);
+ writeWebsiteDataAndContinue();
+ });
+ });
+ }
+</script>
+</body>
+</html>
Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/website-data-removal-for-site-without-user-interaction-js-cookie-checking.html (0 => 295391)
--- trunk/LayoutTests/http/tests/resourceLoadStatistics/website-data-removal-for-site-without-user-interaction-js-cookie-checking.html (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/website-data-removal-for-site-without-user-interaction-js-cookie-checking.html 2022-06-08 19:06:03 UTC (rev 295391)
@@ -0,0 +1,257 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src=""
+ <script src=""
+</head>
+<body _onload_="setTimeout('runTest()', 0)">
+<div id="description">Check that non-cookie website data gets removed after a period of no user interaction.</div>
+<br>
+<div id="output"></div>
+<br>
+<script>
+ testRunner.waitUntilDone();
+ testRunner.dumpAsText();
+
+ const httpOnlyCookieName = "http-only-cookie";
+ const serverSideCookieName = "server-side-cookie";
+ const clientSideCookieName = "client-side-cookie";
+
+ function sortStringArray(a, b) {
+ a = a.toLowerCase();
+ b = b.toLowerCase();
+
+ return a > b ? 1 : b > a ? -1 : 0;
+ }
+
+ function addLinebreakToOutput() {
+ let element = document.createElement("br");
+ output.appendChild(element);
+ }
+
+ function addOutput(message) {
+ let element = document.createElement("div");
+ element.innerText = message;
+ output.appendChild(element);
+ }
+
+ function checkCookies(isAfterDeletion) {
+ let unsortedTestPassedMessages = [];
+ let cookies = internals.getCookies();
+ if (!cookies.length)
+ testFailed((isAfterDeletion ? "After" : "Before") + " script-accessible deletion: No cookies found.");
+ for (let cookie of cookies) {
+ switch (cookie.name) {
+ case httpOnlyCookieName:
+ unsortedTestPassedMessages.push((isAfterDeletion ? "After" : "Before") + " deletion: " + (isAfterDeletion ? " " : "") + "HttpOnly cookie exists.");
+ break;
+ case serverSideCookieName:
+ unsortedTestPassedMessages.push((isAfterDeletion ? "After" : "Before") + " deletion: Regular server-side cookie exists.");
+ break;
+ case clientSideCookieName:
+ unsortedTestPassedMessages.push((isAfterDeletion ? "After" : "Before") + " deletion: Client-side cookie exists.");
+ break;
+ }
+ }
+
+ if (!cookies.includes(clientSideCookieName) && isAfterDeletion)
+ unsortedTestPassedMessages.push("After deletion: Client-side cookie does not exist.");
+
+ let sortedTestPassedMessages = unsortedTestPassedMessages.sort(sortStringArray);
+ for (let testPassedMessage of sortedTestPassedMessages) {
+ addOutput(testPassedMessage);
+ }
+ }
+
+ const dbName = "TestDatabase";
+
+ function createIDBDataStore(callback) {
+ let request = indexedDB.open(dbName);
+ request._onerror_ = function() {
+ addOutput("Couldn't create indexedDB.");
+ finishTest();
+ };
+ request._onupgradeneeded_ = function(event) {
+ let db = event.target.result;
+ let objStore = db.createObjectStore("test", {autoIncrement: true});
+ objStore.add("value");
+ callback();
+ }
+ }
+
+ const maxIntervals = 20;
+
+ let intervalCounterIDB;
+ let checkIDBCallback;
+ let checkIDBIntervalID;
+ let semaphoreIDBCheck = false;
+ function checkIDBDataStoreExists(isAfterDeletion, callback) {
+ let request;
+ intervalCounterIDB = 0;
+ checkIDBCallback = callback;
+ if (!isAfterDeletion) {
+ // Check until there is a IDB.
+ checkIDBIntervalID = setInterval(function() {
+ if (semaphoreIDBCheck)
+ return;
+ semaphoreIDBCheck = true;
+
+ if (++intervalCounterIDB >= maxIntervals) {
+ clearInterval(checkIDBIntervalID);
+ addOutput("Before deletion: IDB entry does not exist.");
+ semaphoreIDBCheck = false;
+ checkIDBCallback();
+ } else {
+ request = indexedDB.open(dbName);
+ request._onerror_ = function () {
+ clearInterval(checkIDBIntervalID);
+ addOutput("Couldn't open indexedDB.");
+ semaphoreIDBCheck = false;
+ finishTest();
+ };
+ request._onupgradeneeded_ = function () {
+ // Let the next interval check again.
+ semaphoreIDBCheck = false;
+ };
+ request._onsuccess_ = function () {
+ clearInterval(checkIDBIntervalID);
+ addOutput("Before deletion: IDB entry does exist.");
+ semaphoreIDBCheck = false;
+ checkIDBCallback();
+ };
+ }
+ }, 200);
+ } else {
+ // Check until there is no IDB.
+ checkIDBIntervalID = setInterval(function () {
+ if (semaphoreIDBCheck)
+ return;
+ semaphoreIDBCheck = true;
+
+ if (++intervalCounterIDB >= maxIntervals) {
+ clearInterval(checkIDBIntervalID);
+ addOutput("After deletion: IDB entry checks exhausted.");
+ semaphoreIDBCheck = false;
+ checkIDBCallback();
+ } else {
+ request = indexedDB.open(dbName);
+ request._onerror_ = function () {
+ clearInterval(checkIDBIntervalID);
+ addOutput("Couldn't open indexedDB.");
+ semaphoreIDBCheck = false;
+ finishTest();
+ };
+ request._onupgradeneeded_ = function () {
+ clearInterval(checkIDBIntervalID);
+ addOutput("After deletion: IDB entry does not exist.");
+ semaphoreIDBCheck = false;
+ checkIDBCallback();
+ };
+ request._onsuccess_ = function () {
+ // Let the next interval check again.
+ semaphoreIDBCheck = false;
+ };
+ }
+ }, 200);
+ }
+ }
+
+ let intervalCounterLocalStorage;
+ let checkLocalStorageCallback;
+ let checkLocalStorageIntervalID;
+ const localStorageName = "test";
+ const localStorageValue = "value";
+ function checkLocalStorageExists(isAfterDeletion, callback) {
+ intervalCounterLocalStorage = 0;
+ checkLocalStorageCallback = callback;
+ if (!isAfterDeletion) {
+ // Check until there is LocalStorage.
+ checkLocalStorageIntervalID = setInterval(function() {
+ if (++intervalCounterLocalStorage >= maxIntervals) {
+ clearInterval(checkLocalStorageIntervalID);
+ let value = localStorage.getItem(localStorageName);
+ addOutput("Before deletion: LocalStorage entry " + (value === localStorageValue ? "does" : "does not") + " exist.");
+ checkLocalStorageCallback();
+ } else if (testRunner.isStatisticsHasLocalStorage(originUnderTest)) {
+ clearInterval(checkLocalStorageIntervalID);
+ let value = localStorage.getItem(localStorageName);
+ addOutput("Before deletion: LocalStorage entry " + (value === localStorageValue ? "does" : "does not") + " exist.");
+ checkLocalStorageCallback();
+ }
+ }, 100);
+ } else {
+ // Check until there is no LocalStorage.
+ checkLocalStorageIntervalID = setInterval(function() {
+ if (++intervalCounterLocalStorage >= maxIntervals) {
+ clearInterval(checkLocalStorageIntervalID);
+ let value = localStorage.getItem(localStorageName);
+ addOutput("After deletion: LocalStorage entry " + (value === localStorageValue ? "does" : "does not") + " exist.");
+ checkLocalStorageCallback();
+ } else if (!testRunner.isStatisticsHasLocalStorage(originUnderTest)) {
+ clearInterval(checkLocalStorageIntervalID);
+ let value = localStorage.getItem(localStorageName);
+ addOutput("After deletion: LocalStorage entry " + (value === localStorageValue ? "does" : "does not") + " exist.");
+ checkLocalStorageCallback();
+ }
+ }, 100);
+ }
+ }
+
+ async function writeWebsiteDataAndContinue() {
+ // Write cookies.
+ await fetch("/cookies/resources/set-http-only-cookie.py?cookieName=" + httpOnlyCookieName, { credentials: "same-origin" });
+ await fetch("/cookies/resources/setCookies.cgi", { headers: { "Set-Cookie": serverSideCookieName + "=1; path=/;" }, credentials: "same-origin" });
+ document.cookie = clientSideCookieName + "=1";
+
+ checkCookies(false);
+
+ // Write LocalStorage
+ localStorage.setItem(localStorageName, localStorageValue);
+ checkLocalStorageExists(false, function() {
+
+ // Write IndexedDB.
+ createIDBDataStore(function () {
+ checkIDBDataStoreExists(false, function() {
+ addLinebreakToOutput();
+ processWebsiteDataAndContinue();
+ });
+ });
+ });
+ }
+
+ function processWebsiteDataAndContinue() {
+ testRunner.installStatisticsDidScanDataRecordsCallback(checkWebsiteDataAndContinue);
+ testRunner.statisticsProcessStatisticsAndDataRecords();
+ }
+
+ function checkWebsiteDataAndContinue() {
+ checkCookies(true);
+ checkLocalStorageExists(true, function () {
+ checkIDBDataStoreExists(true, finishTest);
+ });
+ }
+
+ async function finishTest() {
+ await resetCookiesITP();
+ testRunner.setStatisticsFirstPartyWebsiteDataRemovalMode(false, function() {
+ setEnableFeature(false, function() {
+ testRunner.notifyDone();
+ });
+ });
+ }
+
+ const originUnderTest = "http://127.0.0.1:8000";
+ function runTest() {
+ setEnableFeature(true, function () {
+ testRunner.setStatisticsFirstPartyWebsiteDataRemovalMode(true, function() {
+ testRunner.setStatisticsHasHadUserInteraction(originUnderTest, false, function() {
+ if (testRunner.isStatisticsHasHadUserInteraction(originUnderTest))
+ addOutput("FAIL: " + originUnderTest + " got logged for user interaction.");
+ writeWebsiteDataAndContinue();
+ });
+ });
+ });
+ }
+</script>
+</body>
+</html>
Modified: trunk/LayoutTests/platform/mac-wk2/TestExpectations (295390 => 295391)
--- trunk/LayoutTests/platform/mac-wk2/TestExpectations 2022-06-08 18:37:33 UTC (rev 295390)
+++ trunk/LayoutTests/platform/mac-wk2/TestExpectations 2022-06-08 19:06:03 UTC (rev 295391)
@@ -1583,8 +1583,6 @@
webkit.org/b/231386 [ BigSur ] http/tests/resourceLoadStatistics/website-data-removal-for-site-with-user-interaction.html [ Pass Timeout ]
-webkit.org/b/231765 [ Release ] http/tests/resourceLoadStatistics/website-data-removal-for-site-navigated-to-with-link-decoration.html [ Pass Timeout ]
-
webkit.org/b/231780 [ Debug ] imported/w3c/web-platform-tests/webrtc/simulcast/basic.https.html [ Pass Failure ]
webkit.org/b/235605 [ arm64 ] fast/scrolling/mac/j-shaped-scroll-rubberband.html [ Failure ]
Modified: trunk/LayoutTests/platform/wk2/TestExpectations (295390 => 295391)
--- trunk/LayoutTests/platform/wk2/TestExpectations 2022-06-08 18:37:33 UTC (rev 295390)
+++ trunk/LayoutTests/platform/wk2/TestExpectations 2022-06-08 19:06:03 UTC (rev 295391)
@@ -742,6 +742,11 @@
http/tests/resourceLoadStatistics/prune-statistics.html [ Pass ]
http/tests/resourceLoadStatistics [ Pass ]
+# Tests rely on behavior in iOS 16 and macOS Ventura.
+http/tests/resourceLoadStatistics/capped-lifetime-for-cookie-set-in-js-24-hours.html [ Skip ]
+http/tests/resourceLoadStatistics/website-data-removal-for-site-navigated-to-with-link-decoration-js-cookie-checking.html [ Skip ]
+http/tests/resourceLoadStatistics/website-data-removal-for-site-without-user-interaction-js-cookie-checking.html [ Skip ]
+
# App Bound Domains is for iOS only, so we should skip
# them here and enable them in the iOS platform specific file.
http/tests/resourceLoadStatistics/exemptDomains/ [ Skip ]
Modified: trunk/Source/WTF/wtf/PlatformEnableCocoa.h (295390 => 295391)
--- trunk/Source/WTF/wtf/PlatformEnableCocoa.h 2022-06-08 18:37:33 UTC (rev 295390)
+++ trunk/Source/WTF/wtf/PlatformEnableCocoa.h 2022-06-08 19:06:03 UTC (rev 295391)
@@ -501,6 +501,12 @@
#define ENABLE_INTELLIGENT_TRACKING_PREVENTION 1
#endif
+#if ((PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 130000) \
+ || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 160000) \
+ || (PLATFORM(MACCATALYST) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 160000))
+#define ENABLE_JS_COOKIE_CHECKING 1
+#endif
+
#if !defined(ENABLE_SPEECH_SYNTHESIS) && !PLATFORM(MACCATALYST)
#define ENABLE_SPEECH_SYNTHESIS 1
#endif
Modified: trunk/Source/WebCore/platform/network/NetworkStorageSession.cpp (295390 => 295391)
--- trunk/Source/WebCore/platform/network/NetworkStorageSession.cpp 2022-06-08 18:37:33 UTC (rev 295390)
+++ trunk/Source/WebCore/platform/network/NetworkStorageSession.cpp 2022-06-08 19:06:03 UTC (rev 295391)
@@ -190,6 +190,9 @@
{
m_ageCapForClientSideCookies = seconds;
m_ageCapForClientSideCookiesShort = seconds ? Seconds { seconds->seconds() / 7. } : seconds;
+#if ENABLE(JS_COOKIE_CHECKING)
+ m_ageCapForClientSideCookiesForLinkDecorationTargetPage = seconds;
+#endif
}
void NetworkStorageSession::setPrevalentDomainsToBlockAndDeleteCookiesFor(const Vector<RegistrableDomain>& domains)
@@ -369,10 +372,16 @@
std::optional<Seconds> NetworkStorageSession::clientSideCookieCap(const RegistrableDomain& firstParty, std::optional<PageIdentifier> pageID) const
{
+ auto domainIterator = m_navigatedToWithLinkDecorationByPrevalentResource.find(*pageID);
+#if ENABLE(JS_COOKIE_CHECKING)
+ if (domainIterator != m_navigatedToWithLinkDecorationByPrevalentResource.end() && domainIterator->value == firstParty)
+ return m_ageCapForClientSideCookiesForLinkDecorationTargetPage;
+
+ return std::nullopt;
+#else
if (!m_ageCapForClientSideCookies || !pageID || m_navigatedToWithLinkDecorationByPrevalentResource.isEmpty())
return m_ageCapForClientSideCookies;
- auto domainIterator = m_navigatedToWithLinkDecorationByPrevalentResource.find(*pageID);
if (domainIterator == m_navigatedToWithLinkDecorationByPrevalentResource.end())
return m_ageCapForClientSideCookies;
@@ -380,6 +389,7 @@
return m_ageCapForClientSideCookiesShort;
return m_ageCapForClientSideCookies;
+#endif
}
const HashMap<RegistrableDomain, HashSet<RegistrableDomain>>& NetworkStorageSession::storageAccessQuirks()
@@ -434,7 +444,7 @@
void NetworkStorageSession::deleteCookiesForHostnames(const Vector<String>& cookieHostNames, CompletionHandler<void()>&& completionHandler)
{
- deleteCookiesForHostnames(cookieHostNames, IncludeHttpOnlyCookies::Yes, WTFMove(completionHandler));
+ deleteCookiesForHostnames(cookieHostNames, IncludeHttpOnlyCookies::Yes, ScriptWrittenCookiesOnly::No, WTFMove(completionHandler));
}
}
Modified: trunk/Source/WebCore/platform/network/NetworkStorageSession.h (295390 => 295391)
--- trunk/Source/WebCore/platform/network/NetworkStorageSession.h 2022-06-08 18:37:33 UTC (rev 295390)
+++ trunk/Source/WebCore/platform/network/NetworkStorageSession.h 2022-06-08 19:06:03 UTC (rev 295391)
@@ -88,6 +88,7 @@
enum class SameSiteStrictEnforcementEnabled : bool { Yes, No };
enum class FirstPartyWebsiteDataRemovalMode : uint8_t { AllButCookies, None, AllButCookiesLiveOnTestingTimeout, AllButCookiesReproTestingTimeout };
enum class ShouldAskITP : bool { No, Yes };
+enum class ScriptWrittenCookiesOnly : bool { No, Yes };
#if HAVE(COOKIE_CHANGE_LISTENER_API)
class CookieChangeObserver {
@@ -164,7 +165,7 @@
WEBCORE_EXPORT void deleteAllCookies(CompletionHandler<void()>&&);
WEBCORE_EXPORT void deleteAllCookiesModifiedSince(WallTime, CompletionHandler<void()>&&);
WEBCORE_EXPORT void deleteCookiesForHostnames(const Vector<String>& cookieHostNames, CompletionHandler<void()>&&);
- WEBCORE_EXPORT void deleteCookiesForHostnames(const Vector<String>& cookieHostNames, IncludeHttpOnlyCookies, CompletionHandler<void()>&&);
+ WEBCORE_EXPORT void deleteCookiesForHostnames(const Vector<String>& cookieHostNames, IncludeHttpOnlyCookies, ScriptWrittenCookiesOnly, CompletionHandler<void()>&&);
WEBCORE_EXPORT Vector<Cookie> getAllCookies();
WEBCORE_EXPORT Vector<Cookie> getCookies(const URL&);
WEBCORE_EXPORT void hasCookies(const RegistrableDomain&, CompletionHandler<void(bool)>&&) const;
@@ -281,9 +282,12 @@
HashMap<PageIdentifier, HashMap<FrameIdentifier, RegistrableDomain>> m_framesGrantedStorageAccess;
HashMap<PageIdentifier, HashMap<RegistrableDomain, RegistrableDomain>> m_pagesGrantedStorageAccess;
HashMap<TopFrameDomain, HashSet<SubResourceDomain>> m_pairsGrantedCrossPageStorageAccess;
- std::optional<Seconds> m_cacheMaxAgeCapForPrevalentResources { };
- std::optional<Seconds> m_ageCapForClientSideCookies { };
- std::optional<Seconds> m_ageCapForClientSideCookiesShort { };
+ std::optional<Seconds> m_cacheMaxAgeCapForPrevalentResources;
+ std::optional<Seconds> m_ageCapForClientSideCookies;
+ std::optional<Seconds> m_ageCapForClientSideCookiesShort;
+#if ENABLE(JS_COOKIE_CHECKING)
+ std::optional<Seconds> m_ageCapForClientSideCookiesForLinkDecorationTargetPage;
+#endif
HashMap<WebCore::PageIdentifier, RegistrableDomain> m_navigatedToWithLinkDecorationByPrevalentResource;
bool m_navigationWithLinkDecorationTestMode = false;
ThirdPartyCookieBlockingMode m_thirdPartyCookieBlockingMode { ThirdPartyCookieBlockingMode::All };
Modified: trunk/Source/WebCore/platform/network/cf/NetworkStorageSessionCFNetWin.cpp (295390 => 295391)
--- trunk/Source/WebCore/platform/network/cf/NetworkStorageSessionCFNetWin.cpp 2022-06-08 18:37:33 UTC (rev 295390)
+++ trunk/Source/WebCore/platform/network/cf/NetworkStorageSessionCFNetWin.cpp 2022-06-08 19:06:03 UTC (rev 295391)
@@ -387,7 +387,7 @@
completionHandler();
}
-void NetworkStorageSession::deleteCookiesForHostnames(const Vector<String>&, IncludeHttpOnlyCookies, CompletionHandler<void()>&& completionHandler)
+void NetworkStorageSession::deleteCookiesForHostnames(const Vector<String>&, IncludeHttpOnlyCookies, ScriptWrittenCookiesOnly, CompletionHandler<void()>&& completionHandler)
{
completionHandler();
}
Modified: trunk/Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm (295390 => 295391)
--- trunk/Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm 2022-06-08 18:37:33 UTC (rev 295390)
+++ trunk/Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm 2022-06-08 19:06:03 UTC (rev 295391)
@@ -419,10 +419,18 @@
// cookiesWithResponseHeaderFields doesn't parse cookies without a value
cookieString = cookieString.contains('=') ? cookieString : cookieString + "=";
- NSHTTPCookie *cookie = [NSHTTPCookie _cookieForSetCookieString:cookieString forURL:cookieURL partition:nil];
- if (!cookie)
+ NSHTTPCookie *initialCookie = [NSHTTPCookie _cookieForSetCookieString:cookieString forURL:cookieURL partition:nil];
+ if (!initialCookie)
return nil;
+#if ENABLE(JS_COOKIE_CHECKING)
+ auto mutableProperties = adoptNS([[initialCookie properties] mutableCopy]);
+ [mutableProperties.get() setValue:@1 forKey:@"SetInJavaScript"];
+ NSHTTPCookie* cookie = [NSHTTPCookie cookieWithProperties:mutableProperties.get()];
+#else
+ NSHTTPCookie* cookie = initialCookie;
+#endif
+
// <rdar://problem/5632883> On 10.5, NSHTTPCookieStorage would store an empty cookie,
// which would be sent as "Cookie: =". We have a workaround in setCookies() to prevent
// that, but we also need to avoid sending cookies that were previously stored, and
@@ -567,7 +575,7 @@
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), makeBlockPtr(WTFMove(work)).get());
}
-void NetworkStorageSession::deleteCookiesForHostnames(const Vector<String>& hostnames, IncludeHttpOnlyCookies includeHttpOnlyCookies, CompletionHandler<void()>&& completionHandler)
+void NetworkStorageSession::deleteCookiesForHostnames(const Vector<String>& hostnames, IncludeHttpOnlyCookies includeHttpOnlyCookies, ScriptWrittenCookiesOnly scriptWrittenCookiesOnly, CompletionHandler<void()>&& completionHandler)
{
ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies) || m_isInMemoryCookieStore);
@@ -588,6 +596,14 @@
for (NSHTTPCookie *cookie in cookies.get()) {
if (!cookie.domain || (includeHttpOnlyCookies == IncludeHttpOnlyCookies::No && cookie.isHTTPOnly))
continue;
+
+#if ENABLE(JS_COOKIE_CHECKING)
+ bool setInJS = [[cookie properties] valueForKey:@"SetInJavaScript"];
+ if (scriptWrittenCookiesOnly == ScriptWrittenCookiesOnly::Yes && !setInJS)
+ continue;
+#else
+ UNUSED_PARAM(scriptWrittenCookiesOnly);
+#endif
cookiesByDomain.ensure(cookie.domain, [] {
return Vector<RetainPtr<NSHTTPCookie>>();
}).iterator->value.append(cookie);
Modified: trunk/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp (295390 => 295391)
--- trunk/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp 2022-06-08 18:37:33 UTC (rev 295390)
+++ trunk/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp 2022-06-08 19:06:03 UTC (rev 295391)
@@ -177,7 +177,7 @@
completionHandler();
}
-void NetworkStorageSession::deleteCookiesForHostnames(const Vector<String>& cookieHostNames, IncludeHttpOnlyCookies includeHttpOnlyCookies, CompletionHandler<void()>&& completionHandler)
+void NetworkStorageSession::deleteCookiesForHostnames(const Vector<String>& cookieHostNames, IncludeHttpOnlyCookies includeHttpOnlyCookies, ScriptWrittenCookiesOnly, CompletionHandler<void()>&& completionHandler)
{
for (auto hostname : cookieHostNames)
cookieDatabase().deleteCookiesForHostname(hostname, includeHttpOnlyCookies);
Modified: trunk/Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp (295390 => 295391)
--- trunk/Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp 2022-06-08 18:37:33 UTC (rev 295390)
+++ trunk/Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp 2022-06-08 19:06:03 UTC (rev 295391)
@@ -464,7 +464,7 @@
}
}
-void NetworkStorageSession::deleteCookiesForHostnames(const Vector<String>& hostnames, IncludeHttpOnlyCookies includeHttpOnlyCookies, CompletionHandler<void()>&& completionHandler)
+void NetworkStorageSession::deleteCookiesForHostnames(const Vector<String>& hostnames, IncludeHttpOnlyCookies includeHttpOnlyCookies, ScriptWrittenCookiesOnly, CompletionHandler<void()>&& completionHandler)
{
SoupCookieJar* cookieJar = cookieStorage();
for (const auto& hostname : hostnames) {
Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp (295390 => 295391)
--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp 2022-06-08 18:37:33 UTC (rev 295390)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp 2022-06-08 19:06:03 UTC (rev 295391)
@@ -863,7 +863,7 @@
if (other.dataRecordsRemoved > currentDataRecordsRemoved)
updateDataRecordsRemoved(other.registrableDomain, other.dataRecordsRemoved);
if (other.gotLinkDecorationFromPrevalentResource && !currentIsScheduledForAllButCookieDataRemoval)
- setIsScheduledForAllButCookieDataRemoval(other.registrableDomain, true);
+ setIsScheduledForAllScriptWrittenStorageRemoval(other.registrableDomain, true);
}
void ResourceLoadStatisticsDatabaseStore::mergeStatistic(const ResourceLoadStatistics& statistic)
@@ -1488,7 +1488,7 @@
insertDomainRelationshipList(topFrameLinkDecorationsFromQuery, HashSet<RegistrableDomain>({ fromDomain }), *toDomainResult.second);
if (isPrevalentResource(fromDomain))
- setIsScheduledForAllButCookieDataRemoval(toDomain, true);
+ setIsScheduledForAllScriptWrittenStorageRemoval(toDomain, true);
}
void ResourceLoadStatisticsDatabaseStore::clearTopFrameUniqueRedirectsToSinceSameSiteStrictEnforcement(const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
@@ -1801,7 +1801,7 @@
}
}
-void ResourceLoadStatisticsDatabaseStore::setIsScheduledForAllButCookieDataRemoval(const RegistrableDomain& domain, bool value)
+void ResourceLoadStatisticsDatabaseStore::setIsScheduledForAllScriptWrittenStorageRemoval(const RegistrableDomain& domain, bool value)
{
ASSERT(!RunLoop::isMain());
@@ -1809,16 +1809,16 @@
auto result = ensureResourceStatisticsForRegistrableDomain(domain);
if (!result.second) {
- ITP_RELEASE_LOG_ERROR(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::setIsScheduledForAllButCookieDataRemoval was not completed due to failed insert attempt", this);
+ ITP_RELEASE_LOG_ERROR(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::setIsScheduledForAllScriptWrittenStorageRemoval was not completed due to failed insert attempt", this);
return;
}
- auto scopedStatement = this->scopedStatement(m_updateIsScheduledForAllButCookieDataRemovalStatement, updateIsScheduledForAllButCookieDataRemovalQuery, "setIsScheduledForAllButCookieDataRemoval"_s);
+ auto scopedStatement = this->scopedStatement(m_updateIsScheduledForAllButCookieDataRemovalStatement, updateIsScheduledForAllButCookieDataRemovalQuery, "setIsScheduledForAllScriptWrittenStorageRemoval"_s);
if (!scopedStatement
|| scopedStatement->bindInt(1, value) != SQLITE_OK
|| scopedStatement->bindText(2, domain.string()) != SQLITE_OK
|| scopedStatement->step() != SQLITE_DONE) {
- ITP_RELEASE_LOG_ERROR(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::setIsScheduledForAllButCookieDataRemoval failed to bind, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
+ ITP_RELEASE_LOG_ERROR(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::setIsScheduledForAllScriptWrittenStorageRemoval failed to bind, error message: %" PRIVATE_LOG_STRING, this, m_database.lastErrorMsg());
ASSERT_NOT_REACHED();
}
}
@@ -2322,11 +2322,11 @@
oldestUserInteraction = std::min(oldestUserInteraction, *mostRecentUserInteractionTime);
if (shouldRemoveAllWebsiteDataFor(statistic, shouldCheckForGrandfathering)) {
toDeleteOrRestrictFor.domainsToDeleteAllCookiesFor.append(statistic.registrableDomain);
- toDeleteOrRestrictFor.domainsToDeleteAllNonCookieWebsiteDataFor.append(statistic.registrableDomain);
+ toDeleteOrRestrictFor.domainsToDeleteAllScriptWrittenStorageFor.append(statistic.registrableDomain);
} else {
if (shouldRemoveAllButCookiesFor(statistic, shouldCheckForGrandfathering)) {
- toDeleteOrRestrictFor.domainsToDeleteAllNonCookieWebsiteDataFor.append(statistic.registrableDomain);
- setIsScheduledForAllButCookieDataRemoval(statistic.registrableDomain, false);
+ toDeleteOrRestrictFor.domainsToDeleteAllScriptWrittenStorageFor.append(statistic.registrableDomain);
+ setIsScheduledForAllScriptWrittenStorageRemoval(statistic.registrableDomain, false);
}
if (shouldEnforceSameSiteStrictFor(statistic, shouldCheckForGrandfathering)) {
toDeleteOrRestrictFor.domainsToEnforceSameSiteStrictFor.append(statistic.registrableDomain);
@@ -2343,7 +2343,7 @@
// Give the user enough time to interact with websites until we remove non-cookie website data.
if (!parameters().isRunningTest && now - oldestUserInteraction < parameters().minimumTimeBetweenDataRecordsRemoval)
- toDeleteOrRestrictFor.domainsToDeleteAllNonCookieWebsiteDataFor.clear();
+ toDeleteOrRestrictFor.domainsToDeleteAllScriptWrittenStorageFor.clear();
clearGrandfathering(WTFMove(domainIDsToClearGrandfathering));
Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h (295390 => 295391)
--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h 2022-06-08 18:37:33 UTC (rev 295390)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h 2022-06-08 19:06:03 UTC (rev 295391)
@@ -82,7 +82,7 @@
void setGrandfathered(const RegistrableDomain&, bool value) override;
bool isGrandfathered(const RegistrableDomain&) const override;
- void setIsScheduledForAllButCookieDataRemoval(const RegistrableDomain&, bool value);
+ void setIsScheduledForAllScriptWrittenStorageRemoval(const RegistrableDomain&, bool value);
void setSubframeUnderTopFrameDomain(const SubFrameDomain&, const TopFrameDomain&) override;
void setSubresourceUnderTopFrameDomain(const SubResourceDomain&, const TopFrameDomain&) override;
void setSubresourceUniqueRedirectTo(const SubResourceDomain&, const RedirectDomain&) override;
Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsStore.cpp (295390 => 295391)
--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsStore.cpp 2022-06-08 18:37:33 UTC (rev 295390)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsStore.cpp 2022-06-08 19:06:03 UTC (rev 295391)
@@ -65,7 +65,7 @@
builder.append(builder.isEmpty() ? "" : ", ", domain.string(), "(all data)");
for (auto& domain : domainsToRemoveOrRestrictWebsiteDataFor.domainsToDeleteAllButHttpOnlyCookiesFor)
builder.append(builder.isEmpty() ? "" : ", ", domain.string(), "(all but HttpOnly cookies)");
- for (auto& domain : domainsToRemoveOrRestrictWebsiteDataFor.domainsToDeleteAllNonCookieWebsiteDataFor)
+ for (auto& domain : domainsToRemoveOrRestrictWebsiteDataFor.domainsToDeleteAllScriptWrittenStorageFor)
builder.append(builder.isEmpty() ? "" : ", ", domain.string(), "(all but cookies)");
return builder.toString();
}
@@ -354,21 +354,20 @@
});
}
-void ResourceLoadStatisticsStore::setAgeCapForClientSideCookies(Seconds seconds)
-{
- ASSERT(!RunLoop::isMain());
- ASSERT(seconds >= 0_s);
-
- m_parameters.clientSideCookiesAgeCapTime = seconds;
- updateClientSideCookiesAgeCap();
-}
-
void ResourceLoadStatisticsStore::updateClientSideCookiesAgeCap()
{
ASSERT(!RunLoop::isMain());
#if ENABLE(INTELLIGENT_TRACKING_PREVENTION)
- RunLoop::main().dispatch([store = Ref { m_store }, seconds = m_parameters.clientSideCookiesAgeCapTime] () {
+
+ Seconds capTime;
+#if ENABLE(JS_COOKIE_CHECKING)
+ capTime = m_parameters.clientSideCookiesForLinkDecorationTargetPageAgeCapTime;
+#else
+ capTime = m_parameters.clientSideCookiesAgeCapTime;
+#endif
+
+ RunLoop::main().dispatch([store = Ref { m_store }, seconds = capTime] () {
if (auto* networkSession = store->networkSession()) {
if (auto* storageSession = networkSession->networkStorageSession())
storageSession->setAgeCapForClientSideCookies(seconds);
Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsStore.h (295390 => 295391)
--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsStore.h 2022-06-08 18:37:33 UTC (rev 295390)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsStore.h 2022-06-08 19:06:03 UTC (rev 295391)
@@ -232,6 +232,7 @@
Seconds grandfatheringTime { 24_h * 7 };
Seconds cacheMaxAgeCapTime { 24_h * 7 };
Seconds clientSideCookiesAgeCapTime { 24_h * 7 };
+ Seconds clientSideCookiesForLinkDecorationTargetPageAgeCapTime { 24_h };
Seconds minDelayAfterMainFrameDocumentLoadToNotBeARedirect { 5_s };
bool shouldNotifyPagesWhenDataRecordsWereScanned { false };
bool shouldClassifyResourcesBeforeDataRecordsRemoval { true };
@@ -263,7 +264,6 @@
void removeDataRecords(CompletionHandler<void()>&&);
void setCacheMaxAgeCap(Seconds);
void updateCacheMaxAgeCap();
- void setAgeCapForClientSideCookies(Seconds);
void updateClientSideCookiesAgeCap();
WebResourceLoadStatisticsStore& m_store;
Modified: trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h (295390 => 295391)
--- trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h 2022-06-08 18:37:33 UTC (rev 295390)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h 2022-06-08 19:06:03 UTC (rev 295391)
@@ -83,11 +83,11 @@
struct RegistrableDomainsToDeleteOrRestrictWebsiteDataFor {
Vector<WebCore::RegistrableDomain> domainsToDeleteAllCookiesFor;
Vector<WebCore::RegistrableDomain> domainsToDeleteAllButHttpOnlyCookiesFor;
- Vector<WebCore::RegistrableDomain> domainsToDeleteAllNonCookieWebsiteDataFor;
+ Vector<WebCore::RegistrableDomain> domainsToDeleteAllScriptWrittenStorageFor;
Vector<WebCore::RegistrableDomain> domainsToEnforceSameSiteStrictFor;
- RegistrableDomainsToDeleteOrRestrictWebsiteDataFor isolatedCopy() const & { return { crossThreadCopy(domainsToDeleteAllCookiesFor), crossThreadCopy(domainsToDeleteAllButHttpOnlyCookiesFor), crossThreadCopy(domainsToDeleteAllNonCookieWebsiteDataFor), crossThreadCopy(domainsToEnforceSameSiteStrictFor) }; }
- RegistrableDomainsToDeleteOrRestrictWebsiteDataFor isolatedCopy() && { return { crossThreadCopy(WTFMove(domainsToDeleteAllCookiesFor)), crossThreadCopy(WTFMove(domainsToDeleteAllButHttpOnlyCookiesFor)), crossThreadCopy(WTFMove(domainsToDeleteAllNonCookieWebsiteDataFor)), crossThreadCopy(WTFMove(domainsToEnforceSameSiteStrictFor)) }; }
- bool isEmpty() const { return domainsToDeleteAllCookiesFor.isEmpty() && domainsToDeleteAllButHttpOnlyCookiesFor.isEmpty() && domainsToDeleteAllNonCookieWebsiteDataFor.isEmpty() && domainsToEnforceSameSiteStrictFor.isEmpty(); }
+ RegistrableDomainsToDeleteOrRestrictWebsiteDataFor isolatedCopy() const & { return { crossThreadCopy(domainsToDeleteAllCookiesFor), crossThreadCopy(domainsToDeleteAllButHttpOnlyCookiesFor), crossThreadCopy(domainsToDeleteAllScriptWrittenStorageFor), crossThreadCopy(domainsToEnforceSameSiteStrictFor) }; }
+ RegistrableDomainsToDeleteOrRestrictWebsiteDataFor isolatedCopy() && { return { crossThreadCopy(WTFMove(domainsToDeleteAllCookiesFor)), crossThreadCopy(WTFMove(domainsToDeleteAllButHttpOnlyCookiesFor)), crossThreadCopy(WTFMove(domainsToDeleteAllScriptWrittenStorageFor)), crossThreadCopy(WTFMove(domainsToEnforceSameSiteStrictFor)) }; }
+ bool isEmpty() const { return domainsToDeleteAllCookiesFor.isEmpty() && domainsToDeleteAllButHttpOnlyCookiesFor.isEmpty() && domainsToDeleteAllScriptWrittenStorageFor.isEmpty() && domainsToEnforceSameSiteStrictFor.isEmpty(); }
};
class WebResourceLoadStatisticsStore final : public ThreadSafeRefCounted<WebResourceLoadStatisticsStore, WTF::DestructionThread::Main> {
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (295390 => 295391)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2022-06-08 18:37:33 UTC (rev 295390)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2022-06-08 19:06:03 UTC (rev 295391)
@@ -590,13 +590,6 @@
}
}
-void NetworkProcess::setAgeCapForClientSideCookies(PAL::SessionID sessionID, std::optional<Seconds> seconds, CompletionHandler<void()>&& completionHandler)
-{
- if (auto* networkStorageSession = storageSession(sessionID))
- networkStorageSession->setAgeCapForClientSideCookies(seconds);
- completionHandler();
-}
-
void NetworkProcess::setGrandfathered(PAL::SessionID sessionID, RegistrableDomain&& domain, bool isGrandfathered, CompletionHandler<void()>&& completionHandler)
{
if (auto* session = networkSession(sessionID)) {
@@ -1762,19 +1755,24 @@
HashSet<String> hostNamesWithCookies;
HashSet<String> hostNamesWithHSTSCache;
Vector<String> hostnamesWithCookiesToDelete;
- auto domainsToDeleteAllNonCookieWebsiteDataFor = domains.domainsToDeleteAllNonCookieWebsiteDataFor;
+ Vector<String> hostnamesWithScriptWrittenCookiesToDelete;
+ auto domainsToDeleteAllScriptWrittenStorageFor = domains.domainsToDeleteAllScriptWrittenStorageFor;
if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
if (auto* networkStorageSession = storageSession(sessionID)) {
networkStorageSession->getHostnamesWithCookies(hostNamesWithCookies);
hostnamesWithCookiesToDelete = filterForRegistrableDomains(domains.domainsToDeleteAllCookiesFor, hostNamesWithCookies);
- networkStorageSession->deleteCookiesForHostnames(hostnamesWithCookiesToDelete, WebCore::IncludeHttpOnlyCookies::Yes, [callbackAggregator] { });
+ networkStorageSession->deleteCookiesForHostnames(hostnamesWithCookiesToDelete, WebCore::IncludeHttpOnlyCookies::Yes, ScriptWrittenCookiesOnly::No, [callbackAggregator] { });
+#if ENABLE(JS_COOKIE_CHECKING)
+ hostnamesWithScriptWrittenCookiesToDelete = filterForRegistrableDomains(domains.domainsToDeleteAllScriptWrittenStorageFor, hostNamesWithCookies);
+ networkStorageSession->deleteCookiesForHostnames(hostnamesWithScriptWrittenCookiesToDelete, WebCore::IncludeHttpOnlyCookies::No, ScriptWrittenCookiesOnly::Yes, [callbackAggregator] { });
+#endif
for (const auto& host : hostnamesWithCookiesToDelete)
callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(host));
hostnamesWithCookiesToDelete = filterForRegistrableDomains(domains.domainsToDeleteAllButHttpOnlyCookiesFor, hostNamesWithCookies);
- networkStorageSession->deleteCookiesForHostnames(hostnamesWithCookiesToDelete, WebCore::IncludeHttpOnlyCookies::No, [callbackAggregator] { });
+ networkStorageSession->deleteCookiesForHostnames(hostnamesWithCookiesToDelete, WebCore::IncludeHttpOnlyCookies::No, ScriptWrittenCookiesOnly::No, [callbackAggregator] { });
for (const auto& host : hostnamesWithCookiesToDelete)
callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(host));
@@ -1785,7 +1783,7 @@
#if PLATFORM(COCOA) || USE(SOUP)
if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
hostNamesWithHSTSCache = this->hostNamesWithHSTSCache(sessionID);
- hostnamesWithHSTSToDelete = filterForRegistrableDomains(domainsToDeleteAllNonCookieWebsiteDataFor, hostNamesWithHSTSCache);
+ hostnamesWithHSTSToDelete = filterForRegistrableDomains(domainsToDeleteAllScriptWrittenStorageFor, hostNamesWithHSTSCache);
for (const auto& host : hostnamesWithHSTSToDelete)
callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(host));
@@ -1796,7 +1794,9 @@
#if HAVE(CFNETWORK_ALTERNATIVE_SERVICE)
if (websiteDataTypes.contains(WebsiteDataType::AlternativeServices) && session) {
- auto registrableDomainsToDelete = domainsToDeleteAllNonCookieWebsiteDataFor.map([](auto& domain) { return domain.string(); });
+ auto registrableDomainsToDelete = domainsToDeleteAllScriptWrittenStorageFor.map([](auto& domain) {
+ return domain.string();
+ });
session->deleteAlternativeServicesForHostNames(registrableDomainsToDelete);
}
#endif
@@ -1804,20 +1804,20 @@
if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
if (auto* session = storageSession(sessionID)) {
auto origins = session->credentialStorage().originsWithCredentials();
- auto originsToDelete = filterForRegistrableDomains(origins, domainsToDeleteAllNonCookieWebsiteDataFor, callbackAggregator->m_domains);
+ auto originsToDelete = filterForRegistrableDomains(origins, domainsToDeleteAllScriptWrittenStorageFor, callbackAggregator->m_domains);
for (auto& origin : originsToDelete)
session->credentialStorage().removeCredentialsWithOrigin(origin);
}
auto origins = WebCore::CredentialStorage::originsWithSessionCredentials();
- auto originsToDelete = filterForRegistrableDomains(origins, domainsToDeleteAllNonCookieWebsiteDataFor, callbackAggregator->m_domains);
+ auto originsToDelete = filterForRegistrableDomains(origins, domainsToDeleteAllScriptWrittenStorageFor, callbackAggregator->m_domains);
WebCore::CredentialStorage::removeSessionCredentialsWithOrigins(originsToDelete);
}
if (websiteDataTypes.contains(WebsiteDataType::DOMCache) && session) {
- CacheStorage::Engine::fetchEntries(*session, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [domainsToDeleteAllNonCookieWebsiteDataFor, session = WeakPtr { session }, callbackAggregator](auto entries) mutable {
+ CacheStorage::Engine::fetchEntries(*session, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [domainsToDeleteAllScriptWrittenStorageFor, session = WeakPtr { session }, callbackAggregator](auto entries) mutable {
- auto entriesToDelete = filterForRegistrableDomains(domainsToDeleteAllNonCookieWebsiteDataFor, entries);
+ auto entriesToDelete = filterForRegistrableDomains(domainsToDeleteAllScriptWrittenStorageFor, entries);
for (const auto& entry : entriesToDelete)
callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host));
@@ -1832,9 +1832,9 @@
#if ENABLE(SERVICE_WORKER)
bool clearServiceWorkers = websiteDataTypes.contains(WebsiteDataType::DOMCache) || websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations);
if (clearServiceWorkers && session && session->hasServiceWorkerDatabasePath()) {
- session->ensureSWServer().getOriginsWithRegistrations([domainsToDeleteAllNonCookieWebsiteDataFor, callbackAggregator, session = WeakPtr { *session }](const HashSet<SecurityOriginData>& securityOrigins) mutable {
+ session->ensureSWServer().getOriginsWithRegistrations([domainsToDeleteAllScriptWrittenStorageFor, callbackAggregator, session = WeakPtr { *session }](const HashSet<SecurityOriginData>& securityOrigins) mutable {
for (auto& securityOrigin : securityOrigins) {
- if (!domainsToDeleteAllNonCookieWebsiteDataFor.contains(RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host)))
+ if (!domainsToDeleteAllScriptWrittenStorageFor.contains(RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host)))
continue;
callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host));
if (session) {
@@ -1850,16 +1850,16 @@
#endif
if (websiteDataTypes.contains(WebsiteDataType::DiskCache)) {
- forEachNetworkSession([sessionID, fetchOptions, &domainsToDeleteAllNonCookieWebsiteDataFor, &callbackAggregator](auto& session) {
+ forEachNetworkSession([sessionID, fetchOptions, &domainsToDeleteAllScriptWrittenStorageFor, &callbackAggregator](auto& session) {
/* hack: gcc 8.4 will segfault if the WeakPtr is instantiated within the lambda captures */
auto ws = WeakPtr { session };
- fetchDiskCacheEntries(session.cache(), sessionID, fetchOptions, [domainsToDeleteAllNonCookieWebsiteDataFor, callbackAggregator, session = WTFMove(ws)](auto entries) mutable {
+ fetchDiskCacheEntries(session.cache(), sessionID, fetchOptions, [domainsToDeleteAllScriptWrittenStorageFor, callbackAggregator, session = WTFMove(ws)](auto entries) mutable {
if (!session)
return;
Vector<SecurityOriginData> entriesToDelete;
for (auto& entry : entries) {
- if (!domainsToDeleteAllNonCookieWebsiteDataFor.contains(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host)))
+ if (!domainsToDeleteAllScriptWrittenStorageFor.contains(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host)))
continue;
entriesToDelete.append(entry.origin);
callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host));
@@ -1870,7 +1870,7 @@
}
if (NetworkStorageManager::canHandleTypes(websiteDataTypes) && session) {
- session->storageManager().deleteDataForRegistrableDomains(websiteDataTypes, domainsToDeleteAllNonCookieWebsiteDataFor, [callbackAggregator](auto&& deletedDomains) mutable {
+ session->storageManager().deleteDataForRegistrableDomains(websiteDataTypes, domainsToDeleteAllScriptWrittenStorageFor, [callbackAggregator](auto&& deletedDomains) mutable {
for (auto domain : deletedDomains)
callbackAggregator->m_domains.add(WTFMove(domain));
});
@@ -1877,12 +1877,12 @@
}
auto dataTypesForUIProcess = WebsiteData::filter(websiteDataTypes, WebsiteDataProcessType::UI);
- if (!dataTypesForUIProcess.isEmpty() && !domainsToDeleteAllNonCookieWebsiteDataFor.isEmpty()) {
+ if (!dataTypesForUIProcess.isEmpty() && !domainsToDeleteAllScriptWrittenStorageFor.isEmpty()) {
CompletionHandler<void(const HashSet<RegistrableDomain>&)> completionHandler = [callbackAggregator] (const HashSet<RegistrableDomain>& domains) {
for (auto& domain : domains)
callbackAggregator->m_domains.add(domain);
};
- parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::DeleteWebsiteDataInUIProcessForRegistrableDomains(sessionID, dataTypesForUIProcess, fetchOptions, domainsToDeleteAllNonCookieWebsiteDataFor), WTFMove(completionHandler));
+ parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::DeleteWebsiteDataInUIProcessForRegistrableDomains(sessionID, dataTypesForUIProcess, fetchOptions, domainsToDeleteAllScriptWrittenStorageFor), WTFMove(completionHandler));
}
}
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.h (295390 => 295391)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.h 2022-06-08 18:37:33 UTC (rev 295390)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.h 2022-06-08 19:06:03 UTC (rev 295391)
@@ -211,7 +211,6 @@
void isGrandfathered(PAL::SessionID, RegistrableDomain&&, CompletionHandler<void(bool)>&&);
void isPrevalentResource(PAL::SessionID, RegistrableDomain&&, CompletionHandler<void(bool)>&&);
void isVeryPrevalentResource(PAL::SessionID, RegistrableDomain&&, CompletionHandler<void(bool)>&&);
- void setAgeCapForClientSideCookies(PAL::SessionID, std::optional<Seconds>, CompletionHandler<void()>&&);
void isRegisteredAsRedirectingTo(PAL::SessionID, RedirectedFromDomain&&, RedirectedToDomain&&, CompletionHandler<void(bool)>&&);
void isRegisteredAsSubFrameUnder(PAL::SessionID, SubFrameDomain&&, TopFrameDomain&&, CompletionHandler<void(bool)>&&);
void isRegisteredAsSubresourceUnder(PAL::SessionID, SubResourceDomain&&, TopFrameDomain&&, CompletionHandler<void(bool)>&&);
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in (295390 => 295391)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in 2022-06-08 18:37:33 UTC (rev 295390)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in 2022-06-08 19:06:03 UTC (rev 295391)
@@ -87,7 +87,6 @@
IsGrandfathered(PAL::SessionID sessionID, WebCore::RegistrableDomain targetDomain) -> (bool isGrandfathered)
IsPrevalentResource(PAL::SessionID sessionID, WebCore::RegistrableDomain targetDomain) -> (bool isPrevalent)
IsVeryPrevalentResource(PAL::SessionID sessionID, WebCore::RegistrableDomain targetDomain) -> (bool isVeryPrevalent)
- SetAgeCapForClientSideCookies(PAL::SessionID sessionID, std::optional<Seconds> seconds) -> ()
SetLastSeen(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain, Seconds seconds) -> ()
MergeStatisticForTesting(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain, WebCore::RegistrableDomain topFrameDomain1, WebCore::RegistrableDomain topFrameDomain2, Seconds lastSeen, bool hadUserInteraction, Seconds mostRecentUserInteraction, bool isGrandfathered, bool isPrevalent, bool isVeryPrevalent, uint64_t dataRecordsRemoved) -> ()
InsertExpiredStatisticForTesting(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain, uint64_t numberOfOperatingDaysPassed, bool hadUserInteraction, bool isScheduledForAllButCookieDataRemoval, bool isPrevalent) -> ()
Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp (295390 => 295391)
--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp 2022-06-08 18:37:33 UTC (rev 295390)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp 2022-06-08 19:06:03 UTC (rev 295391)
@@ -857,16 +857,6 @@
sendWithAsyncReply(Messages::NetworkProcess::HasLocalStorage(sessionID, resourceDomain), WTFMove(completionHandler));
}
-void NetworkProcessProxy::setAgeCapForClientSideCookies(PAL::SessionID sessionID, std::optional<Seconds> seconds, CompletionHandler<void()>&& completionHandler)
-{
- if (!canSendMessage()) {
- completionHandler();
- return;
- }
-
- sendWithAsyncReply(Messages::NetworkProcess::SetAgeCapForClientSideCookies(sessionID, seconds), WTFMove(completionHandler));
-}
-
void NetworkProcessProxy::setTimeToLiveUserInteraction(PAL::SessionID sessionID, Seconds seconds, CompletionHandler<void()>&& completionHandler)
{
if (!canSendMessage()) {
Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h (295390 => 295391)
--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h 2022-06-08 18:37:33 UTC (rev 295390)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h 2022-06-08 19:06:03 UTC (rev 295391)
@@ -160,7 +160,6 @@
void statisticsDatabaseHasAllTables(PAL::SessionID, CompletionHandler<void(bool)>&&);
void mergeStatisticForTesting(PAL::SessionID, const RegistrableDomain&, const TopFrameDomain& topFrameDomain1, const TopFrameDomain& topFrameDomain2, Seconds lastSeen, bool hadUserInteraction, Seconds mostRecentUserInteraction, bool isGrandfathered, bool isPrevalent, bool isVeryPrevalent, unsigned dataRecordsRemoved, CompletionHandler<void()>&&);
void insertExpiredStatisticForTesting(PAL::SessionID, const RegistrableDomain&, unsigned numberOfOperatingDaysPassed, bool hadUserInteraction, bool isScheduledForAllButCookieDataRemoval, bool isPrevalent, CompletionHandler<void()>&&);
- void setAgeCapForClientSideCookies(PAL::SessionID, std::optional<Seconds>, CompletionHandler<void()>&&);
void setCacheMaxAgeCap(PAL::SessionID, Seconds, CompletionHandler<void()>&&);
void setGrandfathered(PAL::SessionID, const RegistrableDomain&, bool isGrandfathered, CompletionHandler<void()>&&);
void setNotifyPagesWhenDataRecordsWereScanned(PAL::SessionID, bool, CompletionHandler<void()>&&);