Hi All,
We're currently struggling a bit with a couple of things for system
messages. For background on system messages, see the thread here
https://groups.google.com/forum/#!topic/mozilla.dev.webapi/o8bkwx0EtmM/discussion
However the current implementation of system messages only works well
for apps where either
* The app consists of only a single webpage.
* The app wants to always navigate the user to a specific page
whenever there's an incoming message of the given type.
In other cases the app risks navigating the user as soon as there's an
incoming message, whether handling that message needs UI or not.
Also, any time there's an incoming message, even if the app starts in
the background, the app shows up in the application switcher. This can
be confusing to users since they never started the app.
We also have the problem that since system messages rely on manifests,
they only work for apps currently, not for normal web pages. While
we're planning on making it possible for websites to create a manifest
for their web pages, forcing people to create a manifest just because
they want to handle a system message.
The two APIs where we currently could use system messages for web pages are:
* Push notifications. An incoming message from a server needs to be
handled by a webpage. In some cases by showing UI, in other cases in
the background.
* Web Notifications. This spec is what allows a webpage to put a
message in the "message center". This works fine as long as the page
is being displayed as long as the message sits around in the message
center. However the spec doesn't work well if the user leaves the page
before seeing the message in the message center. If the user clicks
the message at that point we currently can't notify the page.
To solve these problems I propose we start by changing the syntax in
the manifest to something like:
"messages": [
{ "alarm": { page: "/index.html" } }
]
We can then add support for
"messages": [
{ "alarm": { eventPage: "/event-page.html" } }
]
This borrows an idea from how Chrome OS is handling similar issues. In
Chrome OS all incoming messages are sent to a special "events page".
This is a normal DOM window, but one that isn't ever rendered. The
window has access to all the normal APIs, including window.open for
opening new, visible, windows. It would also need access to new API
for enumerating all currently opened windows.
When a system message is sent to the event page for an application we
first start the event page if it's not already running. The page can
then process the incoming message and decide to either display no UI,
navigate an already opened window, or open a new window. All depending
on application specific logic using information in the incoming
message and from elsewhere.
We could also eventually add support for something like:
"messages": [
{ "alarm": { worker: "/messageHandler.js" } }
]
Which would work essentially the same way except that instead of using
a window to handle the message, it'd use a worker. This mainly has the
advantage that certain APIs are only available to workers since they
rely on synchronous IO. This is likely not something that we're going
to implement very soon since we need additional plumbing support in
workers in order to be able to do this. Also, since we have fewer APIs
supported in workers it's not as attractive for developers yet.
In order to support system messages for web pages we can then borrow
from this syntax. So for example registering for a push notification
from a web page could look like:
navigator.push.register({ page: "/foo.html"});
or
navigator.push.register({ eventPage: "/foo.html"});
I.e. the syntax is the same as what's put as the value part in the
manifest. The first syntax would mean that when there's an incoming
event, we'd open a new tab with "/foo.html" and render to the user.
We'd then send that page a system message using the same syntax as we
currently use for system messages.
The second syntax would mean that a background page would be opened
and a system message would be sent to that page. If the page decides
to, it could then use window.open in order to open a new tab which is
displayed to the user.
Thoughts?
/ Jonas