How can a page script call an event handler in a content script?

Here is code that I have discovered works

let win = window.wrappedJSObject;

exportFunction(onScroll, win, {defineAs: 'onScroll'});
win.eval("addEventListener('scroll', onScroll, true);");

function onScroll(ev)
{
    ev.stopPropagation();
}

Anything else results in permission errors.

Is this: the best way to do it; the only way to do it; or about to be prevented by future changes?

1 Like

I’m not quite sure what you try to achieve, but postMessage by the page script should fire onmesssage in the content script.

That doesn’t respond to an event. I need an event listener in the page script that does what I want, in particular, to stop the propagation of the event.

How can a page script call an event handler in a content script?

My suggestion definitely does that.

Anyway. Calling .stopImmediatePropagation() from a capturing handler on the window on an event in a content script should also stop the event from reaching page handlers.

The page script isn’t mine. It is whatever the user has loaded, from some other domain. The page script cannot call as an event handler a function in the content script, even if exported, due to a permission error. I don’t know if this is deliberate or a bug. For example I tried

let handler = exportFunction(onScroll, win, {defineAs: 'onScroll'});
win.addEventListener('scroll', handler, true);

but still there is a permission error, even though the handler is an exported function within the page’s window. Only by compiling code in the context of the page can I get something that works. I was just wondering if there was a better way.

You could cancel the scroll event you get and re-fire it from your content script. Make sure to export the event object you’re firing to the page context using cloneInto. You shouldn’t need your own listener infrastructure.

I don’t get the scroll event. In anything less than the version with win.eval() the call to the event handler fails with “permission error”.

I assume you mean the call to dispatching the error? And that looks something like this?

const e = new Event("scroll");
cloneInto(window, e);
window.dispatchEvent(e);

No, the error comes from the FF system trying to deliver the event to my handler and failing. I do not generate anything.

(Unless you meant that the above code represented what the FF system was trying to do).

Maybe you should

  • tell us what exactly you do now and what exact error you get
  • tell us what it is you want to achieve.

I have an extension that responds to 'wheel' events and calls .preventDefault() on them just fine. I can hardly imagine that you are unable to receive 'scroll' events.

I’ve tried it again and the following now works:

let handler = exportFunction(onScroll, win, {defineAs: '__onScroll'});
win.addEventListener('scroll', handler, true);

So I guess I had a script reload problem. False alarm. Sorry.

Ah, you’re attaching on win, whatever that is and not the window global. When you add a listener to the window or document etc. you shouldn’t need to export the handler.

Well dog ma’ cats. win is window.wrappedJSObject which worked in a previous version of FF, before WebExtensions.

That is the non-X-Rayed version of the object (waived shims version) and thus you do indeed have to export the listener, however it is not recommended to attach DOM listeners to that version of window, as the page may have tampered with it.