The only thing missing hidden from Rob W's excellent answer is how to communicate between the injected page script and the content script.
On the receiving side (either your content script or the injected page script) add an event listener:
document.addEventListener('yourCustomEvent', function (e) {
var data = e.detail;
console.log('received', data);
});
On the initiator side (content script or injected page script) send the event:
var data = {
allowedTypes: 'those supported by structured cloning, see the list below',
inShort: 'no DOM elements or classes/functions',
};
document.dispatchEvent(new CustomEvent('yourCustomEvent', { detail: data }));
Notes:
In Firefox, to send an object (i.e. not a primitive value) from the content script to the page context you have to explicitly clone it into the target using cloneInto
(a built-in function), otherwise it'll fail with a security violation error.
document.dispatchEvent(new CustomEvent('yourCustomEvent', {
detail: cloneInto(data, document.defaultView),
}));