Skip to content

Refactor background.js: Automate Push Subscription & Improve Notification Handling #1422

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 59 additions & 45 deletions functional-samples/cookbook.push/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,65 +14,79 @@

/*eslint no-unused-vars: ["error", { "varsIgnorePattern": "subscribeUserVisibleOnlyFalse" }]*/

const APPLICATION_SERVER_PUBLIC_KEY = '<key>';

async function subscribeUserVisibleOnlyFalse() {
const applicationServerKey = urlB64ToUint8Array(
APPLICATION_SERVER_PUBLIC_KEY
);
console.log("Background service worker is running!");

// Run push subscription logic when the extension is installed or updated
chrome.runtime.onInstalled.addListener(() => {
console.log("Extension Installed/Updated.");
subscribeUserToPush();
});

// Function to subscribe to push notifications
async function subscribeUserToPush() {
try {
let subscriptionData = await self.registration.pushManager.subscribe({
// With our new change[1], this can be set to false. Before it must
// always be set to true otherwise an error will be thrown about
// permissions denied.
userVisibleOnly: false,
applicationServerKey: applicationServerKey
console.log("Checking existing subscription...");
const existingSubscription = await self.registration.pushManager.getSubscription();

if (existingSubscription) {
console.log("Already subscribed:", existingSubscription);
return;
}

console.log("Subscribing to push notifications...");
const applicationServerKey = urlB64ToUint8Array("BCLyuEzuxaJ9bCt5yWcniKUHaiOWASyZlB-w8uFpGHYCKzfxGRodfrmMUHBaLAqFk6UtfhGqPmPkNWWbwAsC1ko");

const subscription = await self.registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey
});
console.log('[Service Worker] Extension is subscribed to push server.');
logSubscriptionDataToConsole(subscriptionData);

console.log("Subscription successful:", subscription);
} catch (error) {
console.error('[Service Worker] Failed to subscribe, error: ', error);
console.error("Subscription failed:", error);
}
}

function logSubscriptionDataToConsole(subscription) {
// The `subscription` data would normally only be know by the push server,
// but for this sample we'll print it out to the console so it can be pasted
// into a testing push notification server (at
// https://web-push-codelab.glitch.me/) to send push messages to this
// endpoint (extension).
console.log(
'[Service Worker] Subscription data to be pasted in the test push' +
'notification server: '
);
console.log(JSON.stringify(subscription));
}
// Push event listener - Handles incoming push notifications
self.addEventListener("push", (event) => {
console.log("Push Event Received!");

// Push message event listener.
self.addEventListener('push', function (event) {
console.log('[Service Worker] Push Received.');
console.log(
`[Service Worker] Push had this data/text: "${event.data.text()}"`
if (!event.data) {
console.warn("No push data received.");
return;
}

const pushData = event.data.json();
console.log("Push Data:", pushData);

event.waitUntil(
self.registration.showNotification(pushData.title, {
body: pushData.message,
icon: "icon.png",
data: { url: pushData.url || "" },
requireInteraction: true
})
);
});

// Before `userVisibleOnly` could be passed as false we would have to show a
// notification at this point (or if we didn't the browser would show a
// generic notification), but now we no longer have to.
// Handle notification clicks
self.addEventListener("notificationclick", (event) => {
console.log("Notification Clicked:", event.notification.data.url);
event.notification.close();

event.waitUntil(
clients.openWindow(event.notification.data.url)
);
});

// Helper method for converting the server key to an array that is passed
// when subscribing to a push server.
function urlB64ToUint8Array(base64String) {
const padding = '='.repeat((4 - (base64String.length % 4)) % 4);
const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');

function urlB64ToUint8Array(base64String) {
const padding = "=".repeat((4 - (base64String.length % 4)) % 4);
const base64 = (base64String + padding).replace(/-/g, "+").replace(/_/g, "/");
const rawData = atob(base64);
const outputArray = new Uint8Array(rawData.length);

for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
return new Uint8Array([...rawData].map((char) => char.charCodeAt(0)));
}


// [1]: https://chromiumdash.appspot.com/commit/f6a8800208dc4bc20a0250a7964983ce5aa746f0