116 lines
3.9 KiB
JavaScript
116 lines
3.9 KiB
JavaScript
// META: global=window-module
|
|
// META: script=/resources/testdriver.js
|
|
// META: script=/resources/testdriver-vendor.js
|
|
// META: script=/notifications/resources/helpers.js
|
|
// META: variant=?includeAppServerKey=true
|
|
// META: variant=?includeAppServerKey=false
|
|
|
|
import { encrypt } from "./resources/helpers.js"
|
|
import { createVapid } from "./resources/vapid.js";
|
|
|
|
const includeAppServerKey = new URL(location.href).searchParams.get("includeAppServerKey") === "true";
|
|
let registration;
|
|
|
|
async function subscribe(t) {
|
|
if (includeAppServerKey) {
|
|
const vapid = await createVapid();
|
|
const subscription = await registration.pushManager.subscribe({
|
|
applicationServerKey: vapid.publicKey
|
|
});
|
|
t.add_cleanup(() => subscription.unsubscribe());
|
|
return { vapid, subscription };
|
|
}
|
|
|
|
// without key
|
|
try {
|
|
const subscription = await registration.pushManager.subscribe();
|
|
t.add_cleanup(() => subscription.unsubscribe());
|
|
return { subscription };
|
|
} catch (err) {
|
|
if (err.name === "NotSupportedError") {
|
|
// happens if and only if applicationServerKey omission is disallowed,
|
|
// which is permitted per the spec. Throwing OptionalFeatureUnsupportedError marks the
|
|
// result as PRECONDITION_FAILED.
|
|
//
|
|
// https://w3c.github.io/push-api/#subscribe-method
|
|
// If the options argument does not include a non-null value for the applicationServerKey
|
|
// member, and the push service requires one to be given, queue a global task on the
|
|
// networking task source using global to reject promise with a "NotSupportedError"
|
|
// DOMException.
|
|
throw new OptionalFeatureUnsupportedError(description);
|
|
} else {
|
|
throw err;
|
|
}
|
|
}
|
|
}
|
|
|
|
async function pushMessage(subscription, { vapid, message }) {
|
|
const result = !message
|
|
? { headers: { TTL: 15 } }
|
|
: await encrypt(
|
|
message,
|
|
subscription.getKey("p256dh"),
|
|
subscription.getKey("auth")
|
|
);
|
|
|
|
if (includeAppServerKey) {
|
|
result.headers.Authorization = await vapid.generateAuthHeader(
|
|
new URL(subscription.endpoint).origin
|
|
);
|
|
}
|
|
|
|
const promise = new Promise(r => {
|
|
navigator.serviceWorker.addEventListener("message", r, { once: true })
|
|
});
|
|
|
|
await fetch(subscription.endpoint, {
|
|
method: "post",
|
|
...result
|
|
});
|
|
|
|
return (await promise).data;
|
|
}
|
|
|
|
promise_setup(async () => {
|
|
await trySettingPermission("granted");
|
|
registration = await prepareActiveServiceWorker("push-sw.js");
|
|
});
|
|
|
|
promise_test(async (t) => {
|
|
const { vapid, subscription } = await subscribe(t);
|
|
|
|
const event = await pushMessage(subscription, { vapid });
|
|
|
|
assert_equals(event.constructor, "PushEvent");
|
|
assert_equals(event.data, null);
|
|
}, "Posting to the push endpoint should fire push event on the service worker");
|
|
|
|
const entries = [
|
|
{ isJSON: false, message: new TextEncoder().encode("Hello") },
|
|
{ isJSON: false, message: new Uint8Array([226, 130, 40, 240, 40, 140, 188]) },
|
|
{ isJSON: true, message: new TextEncoder().encode(JSON.stringify({ hello: "world" })) },
|
|
{ isJSON: false, message: new Uint8Array() },
|
|
{ isJSON: false, message: new Uint8Array([0x48, 0x69, 0x21, 0x20, 0xf0, 0x9f, 0x91, 0x80]) },
|
|
];
|
|
|
|
for (const { isJSON, message } of entries) {
|
|
promise_test(async (t) => {
|
|
const { vapid, subscription } = await subscribe(t);
|
|
|
|
const event = await pushMessage(subscription, { vapid, message });
|
|
|
|
assert_equals(event.constructor, "PushEvent");
|
|
assert_array_equals(new Uint8Array(event.data.arrayBuffer), message);
|
|
assert_array_equals(new Uint8Array(await event.data.blob.arrayBuffer()), message);
|
|
assert_equals(event.data.text, new TextDecoder().decode(message));
|
|
|
|
assert_equals(event.data.json.ok, isJSON);
|
|
if (isJSON) {
|
|
assert_array_equals(
|
|
new TextEncoder().encode(JSON.stringify(event.data.json.value)),
|
|
message
|
|
);
|
|
}
|
|
|
|
}, `Posting to the push endpoint with encrypted data ${message} should fire push event on the service worker`);
|
|
}
|