From 19fe553001c1d2066b6cbee8b34041859dc514da Mon Sep 17 00:00:00 2001
From: Kagami Sascha Rosylight <saschanaz@outlook.com>
Date: Thu, 14 Dec 2023 18:31:58 +0000
Subject: [PATCH] Bug 1869558 - Port applicationServerKey validation tests to
 WPT r=asuth

Porting only the main thread checks but not the checks inside service workers, because it's not clear what to do with permissions there as testdriver.js is window specific. Maybe it can be tweaked for service worker compatibility, but not in this patch.

Differential Revision: https://phabricator.services.mozilla.com/D196181
---
 dom/push/test/test_register_key.html          | 28 ---------
 .../web-platform/meta/push-api/__dir__.ini    |  1 +
 .../web-platform/tests/push-api/noop-sw.js    |  0
 .../tests/push-api/resources/helpers.js       | 12 ++++
 ...aulty-applicationServerKey.https.window.js | 62 +++++++++++++++++++
 5 files changed, 75 insertions(+), 28 deletions(-)
 create mode 100644 testing/web-platform/tests/push-api/noop-sw.js
 create mode 100644 testing/web-platform/tests/push-api/resources/helpers.js
 create mode 100644 testing/web-platform/tests/push-api/subscribe-with-faulty-applicationServerKey.https.window.js

diff --git a/dom/push/test/test_register_key.html b/dom/push/test/test_register_key.html
index ff80b1afda722..b3e75707705ca 100644
--- a/dom/push/test/test_register_key.html
+++ b/dom/push/test/test_register_key.html
@@ -78,34 +78,6 @@ http://creativecommons.org/licenses/publicdomain/
     controlledFrame = await injectControlledFrame();
   });
 
-  add_task(async function emptyKey() {
-    try {
-      await registration.pushManager.subscribe({
-        applicationServerKey: new ArrayBuffer(0),
-      });
-      ok(false, "Should reject for empty app server keys");
-    } catch (error) {
-      ok(error instanceof DOMException,
-        "Wrong exception type for empty key");
-      is(error.name, "InvalidAccessError",
-        "Wrong exception name for empty key");
-    }
-  });
-
-  add_task(async function invalidKey() {
-    try {
-      await registration.pushManager.subscribe({
-        applicationServerKey: new Uint8Array([0]),
-      });
-      ok(false, "Should reject for invalid app server keys");
-    } catch (error) {
-      ok(error instanceof DOMException,
-        "Wrong exception type for invalid key");
-      is(error.name, "InvalidAccessError",
-        "Wrong exception name for invalid key");
-    }
-  });
-
   add_task(async function validKey() {
     var pushSubscription = await registration.pushManager.subscribe({
       applicationServerKey: await generateKey(),
diff --git a/testing/web-platform/meta/push-api/__dir__.ini b/testing/web-platform/meta/push-api/__dir__.ini
index 7a2b4cc48ef3d..77d79360bae1e 100644
--- a/testing/web-platform/meta/push-api/__dir__.ini
+++ b/testing/web-platform/meta/push-api/__dir__.ini
@@ -1 +1,2 @@
 lsan-allowed: [Alloc, Create, Malloc, Realloc, Then, mozilla::BasePrincipal::CreateContentPrincipal, mozilla::dom::DocGroup::Create, mozilla::dom::ServiceWorkerManager::Unregister, mozilla::dom::ServiceWorkerRegistrationMainThread::Unregister, mozilla::dom::UnregisterCallback::UnregisterCallback, mozilla::net::nsStandardURL::TemplatedMutator, operator]
+prefs: [notification.prompt.testing:true, dom.push.testing.ignorePermission:true, marionette.setpermission.enabled:true]
diff --git a/testing/web-platform/tests/push-api/noop-sw.js b/testing/web-platform/tests/push-api/noop-sw.js
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/testing/web-platform/tests/push-api/resources/helpers.js b/testing/web-platform/tests/push-api/resources/helpers.js
new file mode 100644
index 0000000000000..8395c638f3ee0
--- /dev/null
+++ b/testing/web-platform/tests/push-api/resources/helpers.js
@@ -0,0 +1,12 @@
+function resetSw() {
+  return navigator.serviceWorker.getRegistrations().then(registrations => {
+    return Promise.all(registrations.map(r => r.unregister()));
+  });
+}
+
+async function registerSw(path) {
+  await resetSw();
+  add_completion_callback(resetSw);
+  const reg = await navigator.serviceWorker.register(path);
+  return reg;
+}
diff --git a/testing/web-platform/tests/push-api/subscribe-with-faulty-applicationServerKey.https.window.js b/testing/web-platform/tests/push-api/subscribe-with-faulty-applicationServerKey.https.window.js
new file mode 100644
index 0000000000000..7d600803e4329
--- /dev/null
+++ b/testing/web-platform/tests/push-api/subscribe-with-faulty-applicationServerKey.https.window.js
@@ -0,0 +1,62 @@
+// META: script=/resources/testdriver.js
+// META: script=/resources/testdriver-vendor.js
+// META: script=resources/helpers.js
+
+// NOTE:
+// We are not testing success cases here as doing so will try creating external network
+// connection, which is not allowed by all browser test environments.
+// (e.g. Gecko explicitly disables push service for testing environment.)
+// Ideally we should have WPT-specific mock server in this case. See also
+// https://github.com/w3c/push-api/issues/365.
+
+promise_setup(async () => {
+  // The spec does not enforce validation order and implementations
+  // indeed check other things before checking applicationServerKey.
+
+  // Get the permission because Firefox checks it before key validation.
+  // (The permission test is done in permission.https.html.)
+  await test_driver.set_permission({ name: "notifications" }, "granted");
+  // Get the active service worker because Chrome checks it before key validation
+  registration = await registerSw("noop-sw.js");
+  await navigator.serviceWorker.ready;
+});
+
+promise_test(async (t) => {
+  await promise_rejects_dom(
+    t,
+    "InvalidAccessError",
+    registration.pushManager.subscribe({ applicationServerKey: "" }),
+  );
+}, "Reject empty string applicationServerKey");
+
+promise_test(async (t) => {
+  await promise_rejects_dom(
+    t,
+    "InvalidAccessError",
+    registration.pushManager.subscribe({ applicationServerKey: new ArrayBuffer(0) }),
+  );
+}, "Reject empty ArrayBuffer applicationServerKey");
+
+promise_test(async (t) => {
+  await promise_rejects_dom(
+    t,
+    "InvalidAccessError",
+    registration.pushManager.subscribe({ applicationServerKey: new Uint8Array(0) }),
+  );
+}, "Reject empty Uint8Array applicationServerKey");
+
+promise_test(async (t) => {
+  await promise_rejects_dom(
+    t,
+    "InvalidAccessError",
+    registration.pushManager.subscribe({ applicationServerKey: new Uint8Array([1, 2, 3]) }),
+  );
+}, "Reject a key that is not a valid point on P-256 curve");
+
+promise_test(async (t) => {
+  await promise_rejects_dom(
+    t,
+    "InvalidCharacterError",
+    registration.pushManager.subscribe({ applicationServerKey: "!@#$^&*" }),
+  );
+}, "Reject a string key that can't be decoded by base64url");
-- 
GitLab