Closed Bug 852240 Opened 11 years ago Closed 7 years ago

allow `window.postMessage` to an add-on origin

Categories

(Add-on SDK Graveyard :: General, defect)

x86
macOS
defect
Not set
normal

Tracking

(Not tracked)

RESOLVED INCOMPLETE

People

(Reporter: irakli, Unassigned)

References

Details

In a lot of cases add-on SDK APIs replicates standard HTML APIs like window.postMessage: https://developer.mozilla.org/en-US/docs/DOM/window.postMessage

Instead we should leverage standard and allow add-on authors to use just window.postMessage for communication with add-on code. We need to support special
`origin` per add-on though in order to allow private communications between host and client without interference from other domains.

In a future we should just desugar `self` APIs to the same thing and maybe even deprecate it after a while.

SDK should implement simple API that will let add-on register listener for all the message events addressed to it. Those message events will have to have `target` property that can be used to send messages back to source and establish two way communication between host and client.
I think target will need to have some more properties to be useful:

`location:[Object Location]` - window.location for the target
`frame:[Boolean]` - weather target is an iframe
I like the overall idea. If we do this, we should use postMessage and addEventListener in both sides. Currently postMessage accept a string target, I'm wondering if you can make it so that it accepts an object. It would have the benefit to be easily unforgable. Then we would do something like this:
window.onmessage = function (event) {
  if (event.target == addon) {
    window.postMessage("pong", addon);
  }
}
(We would still have to inject this addon object in global page/content script scope)

So, regarding bug 850449, did you meant doing this instead of injecting self/addon into page's scope?
(In reply to Alexandre Poirot (:ochameau) from comment #2)
> I like the overall idea. If we do this, we should use postMessage and
> addEventListener in both sides. 

I don't mind that. Although I think `addEventListener` can just be an alias to `on`.

Maybe these messages could be even dispatched on the addon-window itself.

> Currently postMessage accept a string
> target, I'm wondering if you can make it so that it accepts an object. It
> would have the benefit to be easily unforgable. Then we would do something
> like this:
> window.onmessage = function (event) {
>   if (event.target == addon) {
>     window.postMessage("pong", addon);
>   }
> }
> (We would still have to inject this addon object in global page/content
> script scope)

As a matter of fact `event.target` is an object according to specs. Did you meant origin ? Although I don't think injecting `addon` is necessary. I think we
should make `event.target` be an object like:

```
{ isAddon: true, id: addonId }
```

As far as I know `event.target` can't be overridden it's a window that dispatched event.

Also note that add-on code could dispatch event to a specific (content script) origin so that actual page scripts won't be able to receive these messages.

> 
> So, regarding bug 850449, did you meant doing this instead of injecting
> self/addon into page's scope?

Yes I meant that, but of course there is another piece there, API on the addon
side for listening / dispatching events from / to add-on pages.
I also think we need a JEP for this, I don't know when I'll have time for this, @ochameau do you wanna do that ? We can iterate over it.
To be clear there are few reasons why I don't want to inject things like `addon` to the pages:

1. In some cases users basically write content scripts that serve as proxy between page scripts and addon. That implies overhead in performance and complexity for no real benefit. This way we can enable direct communication but of course not at the cost of security there for events objects on the add-on side should have info identifying source so it's clear weather it's content script or page script. Maybe even having different event target for listening events coming from page-scripts so
that add-on won't trip up by accident.

2. When I write an add-on's I usually write regular html page that later is used in panel or add-on page. Ability to develop it as page embeded in iframe makes it
a lot easier so no requirements on non-standard globals help. Not to mention cases where you can write postMessage based apps that can gain extra capabilities
if backed up by add-on host.
(In reply to Irakli Gozilalishvili [:irakli] [:gozala] [@gozala] from comment #1)
> I think target will need to have some more properties to be useful:
> 
> `location:[Object Location]` - window.location for the target
> `frame:[Boolean]` - weather target is an iframe

We should also have some property here that can be used for distinguishing content scripts from page scripts.

Maybe yet another property to know weather it's a document that is local to add-on or not. I mean weather it's from data folder or not.
`event.target` also should implement DOM EventTarget interface:
https://developer.mozilla.org/en-US/docs/DOM/EventTarget

On both client and host sides
This may require fix for Bug 790367 but not sure yet.
It looks like we need `event.source` instead of `event.target`:
http://www.w3.org/TR/2008/WD-html5-20080610/comms.html#messageevent
It looks like there is a huge amount of work here to manage api changes and old api deprecation for a huge amount of add-ons. What is the benefit for existing or new add-on developers? Is it simply that the apis are more like web apis? How would you suggest we manage deprecation of addon or self or the EventEmitter pattern we currently use?
(In reply to Jeff Griffiths (:canuckistani) from comment #10)
> It looks like there is a huge amount of work here to manage api changes and
> old api deprecation for a huge amount of add-ons. What is the benefit for
> existing or new add-on developers? 

- They already know DOM APIs.
- DOM API's are standard.
- It has potential to be more efficient.

More points were made on:
https://bugzilla.mozilla.org/show_bug.cgi?id=852240#c5

> Is it simply that the apis are more like
> web apis? How would you suggest we manage deprecation of addon or self or
> the EventEmitter pattern we currently use?

By deprecation I don't mean we actually remove old APIs just provide more efficient alternative and encourage switching to it. self & addon can be then
implemented as sugar on top. I'm counting that benefits will make users switch.
Also things like add-on page have no self or addon instead they could just use
postMessage so code sharing will also encourage the switch.
Here is an API proposal we've considered:

https://gist.github.com/ZER0/5209412
Eddy or Gabour does one of you want to look into this issue ? There is an updated overview of what we would like to do: https://gist.github.com/Gozala/5391531

I guess main place where we'll need some platform work is in making messages like window.postMessage(data, "addon:name") observable somehow from chrome side. If that's too hacky we could consider alternative of dispatching custom events on documents to expose a some MessageChannel http://dev.w3.org/html5/postmsg/#messagechannel between content and addon, such that outer frame could not mimic
or interfere with.
Flags: needinfo?(gkrizsanits)
(In reply to Irakli Gozilalishvili [:irakli] [:gozala] [@gozala] from comment #12)
> Here is an API proposal we've considered:
> 
> https://gist.github.com/ZER0/5209412

Based on the documentation and spec of the window.postMessage API this is very confusing hack. The target is always the window reference, while the targetOrigin what we are trying to abuse to redirect the message is just an additional filter (since by the time we send the message the window we have reference to may have started/completed a navigation for example, or we just want to identify the window reference we have).
The window object by the way have no idea about the addons that are attached to it, so probably first a registration should happen. All in all I'm not supporting this approach, and would be surprised if anyone r+-ed it even if I implement it.

So what can we know about that MessageChannel based version? That sounds like a better one... What do we need to open such a channel?
Flags: needinfo?(gkrizsanits)
Priority: P1 → --
https://bugzilla.mozilla.org/show_bug.cgi?id=1399562
Status: NEW → RESOLVED
Closed: 7 years ago
Resolution: --- → INCOMPLETE
You need to log in before you can comment on or make changes to this bug.