Hello,
I’m trying my hand at writing extensions, but I have troubles with the new V3 Manifest and runtime + storage API.
I have a content-script that can initiate a connection to a service-worker in order to start a download. I want to keep the port open and periodically send updates to the content-script on the download state.
Here’s the simplified idea; the worker may interact with several pages at the same time hence the Map for tracking the downloads and their corresponding port.
// content script
function onUserAction(url) {
browser.runtime.connect((port) => {
port.onMessage.addListener(m => {
console.log("Progress: ", m.progress)
})
port.sendMessage({ url: url })
})
}
// service worker
// with manifest v2, I would have done:
const initiators = new Map()
browser.runtime.onConnect.addListener((port) => {
port.onMessage.addListener(m => {
// start new download, store the mapping downloadID => port
chrome.downloads.download(m.url).then(id => {
initiators[id] = port
})
})
})
browser.downloads.onChanged.addListener((delta) => {
const port = initiators[delta.id]
port.sendMessage({ progress: ... })
})
The problem is, now using globals is deprecated (instead we should use the storage API); but I can’t store a runtime.Port
because it’s an Object, not JSON serializable.
I’ve tried to store the port’s name instead; but I’ve got no clue how to get back the Port object from it.
And the fact that listeners should be added synchronously means that I cannot add the download listener inside the onConnected callbacks, where I could have kept a list/map of Port.
So any help / suggestions would be appreciated, or please tell me if I’m going about it the wrong way - I’m relatively new to JS and add-on dev.
Cheers