1

I'd like to create a browser extension that at its core proxies the registration.showNotification function to filter then based on rules set within the addon. Proxying window.Notification is trivial, but I'm having trouble even approaching the problem. I know I can get service worker registrations, but reassigning showNotification doesn't seem to be permanent and doesn't actually seem to work except when I'm the one calling the function through the console.

My 'last resort' idea (which seems difficult) is intercept and modify incoming requests to modify the showNotification function via window.postMessage or something similar - but I want that to be the last resort.

Is there any conceivable way to do what I'm trying to do here? Or maybe a API I'm missing? Based on my research so far my guess is no. I'm not the most experienced when in comes to JS, so I thought I'd give this question a shot. I'm using Firefox if that makes a difference.

Mattwmaster58
  • 2,266
  • 3
  • 23
  • 36

1 Answers1

-1

On the Firefox Addons Store there is a similar extension, Service Worker Control, and you can find its source here, under the MPL license.

Now, more specifically, I understand you want to intercept or change the showNotification function, which can be achieved by something similar to the code below (a snippet adapted from the above cited source):

const showNotification_backup = ServiceWorkerRegistration.prototype.showNotification

function showNotification(title, options) {
    const obj = { type: 'notification', isInjected }
    try {
        const sw = this.installing || this.waiting || this.active
        obj.url = typeof sw === 'object' && sw ? '' + sw.scriptURL : undefined
    } catch { }
    try { obj.scope = '' + this.scope } catch { }
    try { obj.title = '' + title } catch { }
    try { obj.body = '' + options.body } catch { }
    send(obj)
    return showNotification_backup.apply(this, arguments)
}

if (setupCondition) {
    ServiceWorkerRegistration.prototype.showNotification = showNotification
} else {
    exportFunction(showNotification, ServiceWorkerRegistration.prototype,
            { defineAs: 'showNotification' })
}

where exportFunction is part of XPCOM API, thus changing the prototype of the ServiceWorker.

EDIT

As mentioned in the comments, XPCOM is outdated and almost completely deprecated, leaving you with only modifying the prototype of the service worker registrations, as below:

let registrations = await navigator.serviceWorker.getRegistrations()

if (registrations.length > 0) {
    Object.getPrototypeOf(registrations[0]).showNotification = showNotification
}

This indeed directly modifies the prototype chain method, which is not a good JS practice, however considering the given showNotification function applies the arguments to the original one, it somewhat extends it.

vanntile
  • 2,727
  • 4
  • 26
  • 48