How are events passed between chrome and content?

From what I can tell, if I click inside a webpage, the event starts out
in chrome and then propagates down into content. I assume there's some
sort of magic happening in the message manager that pushes the event
across process boundaries. However, I can't figure out how to create my
own event in chrome and have it propagate down into content. Is there
any code/documentation I should be looking at to figure out how to do this?

If you're wondering why I want to know about this, read on; otherwise,
you can stop here.

I'm working on a Firefox add-on for mouse gestures and as part of this I
need to delay the opening of the context menu on Linux to occur on
mouseup rather than mousedown. I do this by swallowing the original
contextmenu event with .preventDefault()/.stopPropagation(). Then on
mouseup, I synthesize my own contextmenu event. This works fine when
clicking on something in chrome, but no context menu pops up if I click
on something in content.

- Jim
0
Jim
6/15/2017 8:16:03 PM
mozilla.dev.platform 5867 articles. 0 followers. Post Follow

4 Replies
25 Views

Similar Articles

[PageSpeed] 29

On Thu, Jun 15, 2017 at 4:16 PM, Jim Porter <jporter@mozilla.com> wrote:
> From what I can tell, if I click inside a webpage, the event starts out
> in chrome and then propagates down into content. I assume there's some
> sort of magic happening in the message manager that pushes the event
> across process boundaries.

Not quite. For e10s, mouse events are sent across the process boundary
using the PBrowser ipdl protocol. On the parent side they go into
EventStateManager::DispatchCrossProcessEvent [1] which picks up the
TabParent and sends it over IPC to the TabChild. The TabChild then
dispatches it to the PuppetWidget in the content process.

> I'm working on a Firefox add-on for mouse gestures and as part of this I
> need to delay the opening of the context menu on Linux to occur on
> mouseup rather than mousedown. I do this by swallowing the original
> contextmenu event with .preventDefault()/.stopPropagation(). Then on
> mouseup, I synthesize my own contextmenu event. This works fine when
> clicking on something in chrome, but no context menu pops up if I click
> on something in content.

If you set the right flags on the event it should get through.
Presumably you're creating this event from JS - you want to make sure
that it creates a WidgetMouseEvent with eContextMenu message type. I
don't know if that can be done without using the DOMWindowUtils APIs.
Posting your code snippet for event creation might help.

[1] http://searchfox.org/mozilla-central/rev/20d16dadd336e0c6b97e3e19dc4ff907744b5734/dom/events/EventStateManager.cpp#1228
0
Kartikaya
6/15/2017 9:12:04 PM
On 6/15/17 4:12 PM, Kartikaya Gupta wrote:
> Not quite. For e10s, mouse events are sent across the process boundary
> using the PBrowser ipdl protocol. On the parent side they go into
> EventStateManager::DispatchCrossProcessEvent [1] which picks up the
> TabParent and sends it over IPC to the TabChild. The TabChild then
> dispatches it to the PuppetWidget in the content process.

Thanks for the code reference! That at least gives me a rough idea of
where all this is happening so I can maybe debug it.

> If you set the right flags on the event it should get through.
> Presumably you're creating this event from JS - you want to make sure
> that it creates a WidgetMouseEvent with eContextMenu message type. I
> don't know if that can be done without using the DOMWindowUtils APIs.
> Posting your code snippet for event creation might help.

Here's the code I'm currently using to generate a contextmenu event:
<https://github.com/jimporter/gesticulate/blob/e10s/src/chrome/modules/mouseGestures.jsm#L214-L216>.
As mentioned, it works fine for creating a context menu in chrome, but
not content. (It also works fine in non-e10s content, but that shouldn't
be surprising.) I might be missing something, but when I looked in the
inspector, I didn't see any obvious differences between this event and
the original contextmenu event that I suppressed.

Maybe there's some issue with the event target? When the original
contextmenu event is fired, it says the target is the XUL tabbrowser
(#content) and the originalTarget is the XUL browser element. I've tried
dispatching my synthetic event to both, but neither does anything.

I've also tried keeping the original contextmenu event around that I
suppressed and re-dispatching that, but it doesn't work either. However,
since I called .preventDefault()/.stopPropagation() on that object, I'm
not sure I'd expect it to work anyway.

- Jim
0
Jim
6/15/2017 11:32:04 PM
On 06/16/2017 02:32 AM, Jim Porter wrote:
> On 6/15/17 4:12 PM, Kartikaya Gupta wrote:
>> Not quite. For e10s, mouse events are sent across the process boundary
>> using the PBrowser ipdl protocol. On the parent side they go into
>> EventStateManager::DispatchCrossProcessEvent [1] which picks up the
>> TabParent and sends it over IPC to the TabChild. The TabChild then
>> dispatches it to the PuppetWidget in the content process.
>
> Thanks for the code reference! That at least gives me a rough idea of
> where all this is happening so I can maybe debug it.
>
>> If you set the right flags on the event it should get through.
>> Presumably you're creating this event from JS - you want to make sure
>> that it creates a WidgetMouseEvent with eContextMenu message type. I
>> don't know if that can be done without using the DOMWindowUtils APIs.
>> Posting your code snippet for event creation might help.
>
> Here's the code I'm currently using to generate a contextmenu event:
> <https://github.com/jimporter/gesticulate/blob/e10s/src/chrome/modules/mouseGestures.jsm#L214-L216>.
That just dispatches the event to dom. No forwarding to child process will happen.
You need to use methods in nsIDOMWindowUtils to dispatch events in a way which simulates real events better
and causes forwarding to happen.


> As mentioned, it works fine for creating a context menu in chrome, but
> not content. (It also works fine in non-e10s content, but that shouldn't
> be surprising.) I might be missing something, but when I looked in the
> inspector, I didn't see any obvious differences between this event and
> the original contextmenu event that I suppressed.
>
> Maybe there's some issue with the event target? When the original
> contextmenu event is fired, it says the target is the XUL tabbrowser
> (#content) and the originalTarget is the XUL browser element. I've tried
> dispatching my synthetic event to both, but neither does anything.
>
> I've also tried keeping the original contextmenu event around that I
> suppressed and re-dispatching that, but it doesn't work either. However,
> since I called .preventDefault()/.stopPropagation() on that object, I'm
> not sure I'd expect it to work anyway.
>
> - Jim
>

0
smaug
6/16/2017 11:18:12 AM
On 6/16/17 6:18 AM, smaug wrote:
> On 06/16/2017 02:32 AM, Jim Porter wrote:
>> Here's the code I'm currently using to generate a contextmenu event:
>> <https://github.com/jimporter/gesticulate/blob/e10s/src/chrome/modules/mouseGestures.jsm#L214-L216>.
>>
> That just dispatches the event to dom. No forwarding to child process
> will happen.
> You need to use methods in nsIDOMWindowUtils to dispatch events in a way
> which simulates real events better
> and causes forwarding to happen.

Awesome, it works! Thanks for the pointer.

Now I just need to work on making this into a WebExtension... :)

- Jim
0
Jim
6/16/2017 7:39:14 PM
Reply: