diff --git a/gpc/META.yml b/gpc/META.yml new file mode 100644 index 00000000000000..e9bbee032d854f --- /dev/null +++ b/gpc/META.yml @@ -0,0 +1,7 @@ +spec: https://www.w3.org/TR/gpc/ +suggested_reviewers: + - AramZS + - bvandersloot-mozilla + - j-br0 + - pes10k + - SebastianZimmeck diff --git a/gpc/WEB_FEATURES.yml b/gpc/WEB_FEATURES.yml new file mode 100644 index 00000000000000..02c6a0f383eaa8 --- /dev/null +++ b/gpc/WEB_FEATURES.yml @@ -0,0 +1,3 @@ +features: +- name: gpc + files: "**" diff --git a/gpc/global_privacy_control.testdriver.html b/gpc/global_privacy_control.testdriver.html new file mode 100644 index 00000000000000..138bba2eb4528f --- /dev/null +++ b/gpc/global_privacy_control.testdriver.html @@ -0,0 +1,24 @@ + + +GPC Testdriver Validation + + + + + diff --git a/gpc/idlharness.any.js b/gpc/idlharness.any.js new file mode 100644 index 00000000000000..7a7305eb623535 --- /dev/null +++ b/gpc/idlharness.any.js @@ -0,0 +1,15 @@ +// META: global=window,worker +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js + +idl_test( + ['gpc'], + ['html'], + idl_array => { + if (self.Window) { + idl_array.add_objects({ Navigator: ['navigator'] }); + } else { + idl_array.add_objects({ WorkerNavigator: ['navigator'] }); + } + } +); diff --git a/gpc/navigator-globalPrivacyControl.https.html b/gpc/navigator-globalPrivacyControl.https.html new file mode 100644 index 00000000000000..6ddc7ffca4194a --- /dev/null +++ b/gpc/navigator-globalPrivacyControl.https.html @@ -0,0 +1,33 @@ + + +Primary navigator.globalPrivacyControl test window + + + + + + + +
+ + + diff --git a/gpc/sec-gpc.https.html b/gpc/sec-gpc.https.html new file mode 100644 index 00000000000000..6acc350d241cab --- /dev/null +++ b/gpc/sec-gpc.https.html @@ -0,0 +1,33 @@ + + +Primary Sec-GPC test window + + + + + + + +
+ + + diff --git a/gpc/support/getGPC.py b/gpc/support/getGPC.py new file mode 100644 index 00000000000000..d1c46aac254f9d --- /dev/null +++ b/gpc/support/getGPC.py @@ -0,0 +1,90 @@ +import base64 + +def maybeBoolToJavascriptLiteral(value): + if value == None: + return "undefined" + if value == True: + return "true" + if value == False: + return "false" + raise ValueError("Expected bool or None") + +def main(request, response): + destination = request.headers.get("sec-fetch-dest").decode("utf-8") + gpcValue = request.headers.get("sec-gpc") == b'1' + expectedGPCValue = request.GET.get(b"gpc") == b"true" + inFrame = request.GET.get(b"framed") != None + destinationDescription = "framed " + destination if inFrame else destination + if destination == "document" or destination == "iframe": + response.headers.set('Content-Type', 'text/html'); + return f""" + + +Sec-GPC {destination} + + + + +
+ + +""" + (f""" + + """ if destination == "document" else "") + f""" + + + +""" + elif destination == "image": + if gpcValue == expectedGPCValue: + return (200, [(b"Content-Type", b"image/png")], base64.b64decode("iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEUlEQVR42mP8nzaTAQQYYQwALssD/5ca+r8AAAAASUVORK5CYII=")) + return (400, [], "") + elif destination == "script": + response.headers.set('Content-Type', 'application/javascript'); + return f""" +debugger; +test(function(t) {{ + assert_equals({maybeBoolToJavascriptLiteral(gpcValue)}, {maybeBoolToJavascriptLiteral(expectedGPCValue)}, "Expected Sec-GPC value ({maybeBoolToJavascriptLiteral(expectedGPCValue)}) is on the {destinationDescription} fetch"); +}}, `Expected Sec-GPC value ({maybeBoolToJavascriptLiteral(expectedGPCValue)}) is on the {destinationDescription} fetch`); +""" + elif destination == "worker" or destination == "sharedworker" or destination == "serviceworker": + response.headers.set('Content-Type', 'application/javascript'); + return f""" +importScripts("/resources/testharness.js"); +test(function(t) {{ + assert_equals({maybeBoolToJavascriptLiteral(gpcValue)}, {maybeBoolToJavascriptLiteral(expectedGPCValue)}, "Expected Sec-GPC value ({maybeBoolToJavascriptLiteral(expectedGPCValue)}) is on the {destinationDescription} fetch"); +}}, `Expected Sec-GPC value ({maybeBoolToJavascriptLiteral(expectedGPCValue)}) is on the {destinationDescription} fetch`); +done(); +""" + raise ValueError("Unexpected destination") diff --git a/gpc/support/navigator-globalPrivacyControl.html b/gpc/support/navigator-globalPrivacyControl.html new file mode 100644 index 00000000000000..270023ed9cf81a --- /dev/null +++ b/gpc/support/navigator-globalPrivacyControl.html @@ -0,0 +1,35 @@ + + +navigator.globalPrivacyControl Window + + + + +
+ + + diff --git a/gpc/support/navigator-globalPrivacyControl.js b/gpc/support/navigator-globalPrivacyControl.js new file mode 100644 index 00000000000000..beb9ea372cd44b --- /dev/null +++ b/gpc/support/navigator-globalPrivacyControl.js @@ -0,0 +1,11 @@ +importScripts("/resources/testharness.js"); + +const queryString = self.location.search; +const urlParams = new URLSearchParams(queryString); +const expectedValue = urlParams.has("gpc", "true"); +const workerType = urlParams.get("workerType"); +test(function(t) { + assert_equals(navigator.globalPrivacyControl, expectedValue, "Expected navigator.globalPrivacyControl value is read from the worker"); +}, `Expected navigator.globalPrivacyControl value (${expectedValue}) is read from the ${workerType} worker`); + +done();