Skip to content

Commit

Permalink
Implement support for the Clear-Site-Data HTTP header
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=203215

Reviewed by Darin Adler.

Implement support for the Clear-Site-Data HTTP header:
- https://w3c.github.io/webappsec-clear-site-data

All header values are implemented expect for "executionContexts".

Firefox and Chrome already ship this.

* LayoutTests/TestExpectations:
* LayoutTests/imported/w3c/resources/import-expectations.json:
* LayoutTests/imported/w3c/resources/resource-files.json:
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/META.yml: Added.
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/executionContexts.sub-expected.txt: Added.
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/executionContexts.sub.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/navigation-insecure-expected.txt: Added.
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/navigation-insecure.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/navigation.https-expected.txt: Added.
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/navigation.https.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/resource-expected.txt: Added.
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/resource.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/storage.https-expected.txt: Added.
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/storage.https.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/support/controlled-endpoint.py: Added.
(main):
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/support/echo-clear-site-data.py: Added.
(main):
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/support/iframe_executionContexts.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/support/page_using_service_worker.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/support/page_with_resource.sub.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/support/send_report.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/support/service_worker.js: Added.
(e.url.pathname.match):
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/support/test_utils.sub.js: Added.
(TestUtils.STORAGE.string_appeared_here):
(string_appeared_here):
(TestUtils.DATATYPES.string_appeared_here):
(TestUtils.COMBINATIONS):
(TestUtils.getClearSiteDataUrl):
(TestUtils.getPageWithResourceUrl):
(TestUtils):
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/support/w3c-import.log: Added.
* LayoutTests/imported/w3c/web-platform-tests/clear-site-data/w3c-import.log: Added.
* LayoutTests/platform/ios-wk2/TestExpectations:
* LayoutTests/platform/mac-wk1/TestExpectations:
* LayoutTests/platform/mac-wk2/TestExpectations:
* LayoutTests/platform/win/TestExpectations:
* Source/WebCore/page/SecurityOrigin.h:
* Source/WebCore/platform/network/HTTPHeaderNames.in:
* Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp:
(WebKit::NetworkConnectionToWebProcess::deleteWebsiteDataForOrigins):
* Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h:
* Source/WebKit/NetworkProcess/NetworkProcess.h:
* Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp:
(WebKit::NetworkResourceLoader::processClearSiteDataHeader):
(WebKit::NetworkResourceLoader::didReceiveResponse):
* Source/WebKit/NetworkProcess/NetworkResourceLoader.h:
* Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp:
(WebKit::computeNetworkProcessAccessTypeForDataFetch):
(WebKit::computeWebProcessAccessTypeForDataFetch):
(WebKit::computeNetworkProcessAccessTypeForDataRemoval):
(WebKit::WebsiteDataStore::computeWebProcessAccessTypeForDataRemoval):
(WebKit::computeWebProcessAccessTypeForDataRemoval): Deleted.
* Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h:
* Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp:
(WebKit::NetworkProcessConnection::deleteWebsiteDataForOrigins):
* Source/WebKit/WebProcess/Network/NetworkProcessConnection.h:
* Source/WebKit/WebProcess/Network/NetworkProcessConnection.messages.in:
* Source/WebKit/WebProcess/WebProcess.h:

Canonical link: https://commits.webkit.org/254745@main
  • Loading branch information
cdumez committed Sep 22, 2022
1 parent 4671450 commit c65efd2
Show file tree
Hide file tree
Showing 45 changed files with 990 additions and 57 deletions.
3 changes: 3 additions & 0 deletions LayoutTests/TestExpectations
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,9 @@ imported/w3c/web-platform-tests/server-timing/test_server_timing.https.html [ Sk
imported/w3c/web-platform-tests/server-timing/navigation_timing_idl.html [ Skip ]
imported/w3c/web-platform-tests/server-timing/navigation_timing_idl.https.html [ Skip ]

# No support for Clear-Site-Data: "executionContexts".
imported/w3c/web-platform-tests/clear-site-data/executionContexts.sub.html [ Skip ]

# Console log lines may appear in a different order so we silence them.
http/tests/security/cookie-module-import-propagate.html [ DumpJSConsoleLogInStdErr ]
http/tests/security/window-opened-from-sandboxed-iframe-should-inherit-sandbox.html [ DumpJSConsoleLogInStdErr ]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
"web-platform-tests/beacon": "import",
"web-platform-tests/bluetooth": "skip",
"web-platform-tests/browser-payment-api": "skip",
"web-platform-tests/clear-site-data": "skip",
"web-platform-tests/clear-site-data": "import",
"web-platform-tests/clipboard": "skip",
"web-platform-tests/clipboard-apis": "import",
"web-platform-tests/common": "import",
Expand Down
4 changes: 4 additions & 0 deletions LayoutTests/imported/w3c/resources/resource-files.json
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,10 @@
"web-platform-tests/acid/acid3/svg.xml",
"web-platform-tests/beacon/fetch-keepalive-navigate.iFrame.html",
"web-platform-tests/beacon/navigate.iFrame.sub.html",
"web-platform-tests/clear-site-data/support/iframe_executionContexts.html",
"web-platform-tests/clear-site-data/support/page_using_service_worker.html",
"web-platform-tests/clear-site-data/support/page_with_resource.sub.html",
"web-platform-tests/clear-site-data/support/send_report.html",
"web-platform-tests/compat/webkit-box-fixed-position-child.html",
"web-platform-tests/content-security-policy/README.html",
"web-platform-tests/content-security-policy/embedded-enforcement/support/embed-img-and-message-top.html",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
spec: https://w3c.github.io/webappsec-clear-site-data/
suggested_reviewers:
- mikewest
- msramek
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Blocked access to external URL https://www2.localhost:9443/clear-site-data/support/iframe_executionContexts.html


Harness Error (TIMEOUT), message = null

TIMEOUT executionContexts triggers the reload of contexts Test timed out
NOTRUN * triggers the reload of contexts

Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>

<body>
<script>
function createAndLoadIframe() {
return new Promise(resolve => {
addEventListener("message", function() {
assert_true(true, "Iframe loaded");
resolve();
}, { once: true });

let ifr = document.createElement('iframe');
document.body.appendChild(ifr);
ifr.src = "https://{{domains[www2]}}:{{ports[https][0]}}/clear-site-data/support/iframe_executionContexts.html";
});
}

function loadClearSiteDataResource(what) {
return new Promise(resolve => {
addEventListener("message", function() {
assert_true(true, "Iframe re-loaded");
resolve();
}, { once: true });

let image = new Image();
image.src = "https://{{domains[www2]}}:{{ports[https][0]}}/clear-site-data/support/echo-clear-site-data.py?" + what;
});
}

promise_test(function(test) {
return createAndLoadIframe()
.then(() => loadClearSiteDataResource("executionContexts"))
}, "executionContexts triggers the reload of contexts");

promise_test(function(test) {
return createAndLoadIframe()
.then(() => loadClearSiteDataResource("*"));
}, "* triggers the reload of contexts");
</script>
</body>
</html>

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CONSOLE MESSAGE: Unhandled Promise Rejection: Error: assert_false: cookies should NOT have been cleared. expected false got true


Harness Error (FAIL), message = Unhandled rejection: assert_false: cookies should NOT have been cleared. expected false got true

PASS Do not clear datatypes on insecure navigation (header: )
TIMEOUT Do not clear datatypes on insecure navigation (header: cookies) Test timed out
NOTRUN Do not clear datatypes on insecure navigation (header: storage)
NOTRUN Do not clear datatypes on insecure navigation (header: cookies, storage)

Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<!DOCTYPE html>
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support/test_utils.sub.js"></script>
</head>

<body>
<script>
/**
* @param Array.<Array.<Datatype>> combination A combination of datatypes.
* @param Dict.<string, boolean> report A map between a datatype name and
* whether it is empty.
* @return boolean Whether all datatypes are still nonempty.
*/
function verifyDatatypes(report) {
TestUtils.DATATYPES.forEach(function(datatype) {
assert_false(
report[datatype.name],
datatype.name + " should NOT have been cleared.");
});
}

TestUtils.COMBINATIONS.forEach(function(combination) {
var test_name =
"Do not clear datatypes on insecure navigation (header: " +
combination.map(function(e) { return e.name; }).join(", ") +
")";

promise_test(function(test) {
return new Promise(function(resolve_test, reject_test) {
TestUtils.populateDatatypes()
.then(function() {
// Navigate to a resource with a Clear-Site-Data header in
// an iframe, then verify that no data have been deleted.
return new Promise(function(resolve, reject) {
window.addEventListener("message", resolve);
var iframe = document.createElement("iframe");
iframe.src = TestUtils.getClearSiteDataUrl(combination);
document.body.appendChild(iframe);
}).then(function(messageEvent) {
verifyDatatypes(messageEvent.data);
resolve_test();
});
});
});
}, test_name);
});
</script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@


PASS Clear datatypes on navigation:
PASS Clear datatypes on navigation: cookies
PASS Clear datatypes on navigation: storage
PASS Clear datatypes on navigation: cookies, storage

Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support/test_utils.sub.js"></script>
</head>

<body>
<script>
/**
* @param Array.<Array.<Datatype>> combination A combination of datatypes.
* @param Dict.<string, boolean> report A map between a datatype name and
* whether it is empty.
* @return boolean Whether all datatypes are empty if and only if they are
* included in the |combination|.
*/
function verifyDatatypes(combination, report) {
TestUtils.DATATYPES.forEach(function(datatype) {
if (combination.indexOf(datatype) != -1) {
assert_true(
report[datatype.name],
datatype.name + " should have been cleared.");
} else {
assert_false(
report[datatype.name],
datatype.name + " should NOT have been cleared.");
}
});
}

TestUtils.COMBINATIONS.forEach(function(combination) {
var test_name =
"Clear datatypes on navigation: " +
combination.map(function(e) { return e.name; }).join(", ");

promise_test(function(test) {
return new Promise(function(resolve_test, reject_test) {
TestUtils.populateDatatypes()
.then(function() {
// Navigate to a resource with a Clear-Site-Data header in
// an iframe, then verify that the correct types have been
// deleted.
return new Promise(function(resolve, reject) {
window.addEventListener("message", resolve);
var iframe = document.createElement("iframe");
iframe.src = TestUtils.getClearSiteDataUrl(combination);
document.body.appendChild(iframe);
}).then(function(messageEvent) {
verifyDatatypes(combination, messageEvent.data);
resolve_test();
});
});
});
}, test_name);
});
</script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CONSOLE MESSAGE: Unhandled Promise Rejection: Error: assert_false: Storage should NOT have been cleared. expected false got true


Harness Error (FAIL), message = Unhandled rejection: assert_false: Storage should NOT have been cleared. expected false got true

PASS https resource on a https page
PASS https resource on a http page
TIMEOUT http resource on a https page Test timed out
NOTRUN http resource on a http page

Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<!DOCTYPE html>
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support/test_utils.sub.js"></script>
</head>

<body>
<script>
/**
* @typedef{TestCase}
* @type{object}
* @property{string} frame The scheme of the url of the iframe.
* @property{string} resource The scheme of the resource in the iframe.
* @property{boolean} deleted Whether it is expected that Clear-Site-Data
* will be respected when loading |resource| in |frame|.
*/
var TestCase;

/** Array<TestCase> Test cases. */
var test_cases = [
{ "frame": "https", "resource": "https", "deleted": true },
{ "frame": "http", "resource": "https", "deleted": true },
{ "frame": "https", "resource": "http", "deleted": false },
{ "frame": "http", "resource": "http", "deleted": false },
];

/**
* @param TestCase test_case The test case that is tested.
* @param Dict.<string, boolean> report A map between a datatype name and
* whether it is empty.
*/
function verifyDatatypes(test_case, report) {
if (test_case.deleted) {
assert_true(
report["storage"],
"Storage should have been cleared.");
} else {
assert_false(
report["storage"],
"Storage should NOT have been cleared.");
}
}

test_cases.forEach(function(test_case) {
var test_name =
test_case.resource + " resource on a " + test_case.frame + " page";

promise_test(function(test) {
return new Promise(function(resolve_test, reject_test) {
TestUtils.populateDatatypes()
.then(function() {
// Navigate to a page with a resource that is loaded with
// the Clear-Site-Data header, then verify that storage
// has been deleted if and only if the resource was loaded
// via HTTPS.
return new Promise(function(resolve, reject) {
window.addEventListener("message", resolve);
var iframe = document.createElement("iframe");
iframe.src = TestUtils.getPageWithResourceUrl(
test_case.frame, test_case.resource);
document.body.appendChild(iframe);
}).then(function(messageEvent) {
verifyDatatypes(test_case, messageEvent.data);
resolve_test();
});
});
});
}, test_name);
});
</script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@


Harness Error (TIMEOUT), message = null

PASS Populate backends.
PASS storage
PASS Baseline: Service worker responds to request
PASS Clear backend when 'storage' is deleted: local storage
PASS Clear backend when 'storage' is deleted: Indexed DB
PASS Clear backend when 'storage' is deleted: service workers
PASS Service worker no longer responds to requests
TIMEOUT controllerchange event fires and client no longer has controller Test timed out

Loading

0 comments on commit c65efd2

Please sign in to comment.