Taking a second look at registerProtocolHandler

204 views
Skip to first unread message

Tyler Close

unread,
Sep 12, 2011, 2:11:06 PM9/12/11
to web-i...@googlegroups.com
At our meeting last week, we spent a good deal of time discussing
registerProtocolHandler and whether it made sense to consolidate our
efforts behind this API instead of continuing with parallel efforts. I
took an action to redo the examples at webintents.org using
registerProtocolHandler.

The front page of webintents.org uses the link sharing example to
showcase the syntax for registering for an intent and for invoking an
intent. For registration, the WI syntax is:

<intent
action="http://webintents.org/share"
type="image/*"
href="share.html"
title="Share Link"
/>

The equivalent RPH syntax is:

navigator.registerProtocolHandler(
'web+share',
'share.html#%s',
'Share Link'
);

For invoking an intent, the WI syntax is:

var intent = new Intent("http://webintents.org/share",
"text/uri-list",
"http://news.bbc.co.uk");
window.navigator.startActivity(intent);

The equivalent RPH syntax is:

window.open('web+share:http://news.bbc.co.uk');

The WI pick intent shows the syntax for the client to receive a
response from the intent handler:

var intent = new Intent();
intent.action = "http://webintents.org/pick";
intent.type = "image/*";
window.navigator.startActivity(intent, intentResponse);
var intentResponse = function (intentData) {
var output = document.getElementById("output");
output.src = intentData.data[0];
};

The equivalent RPH syntax is:

var service = window.open('web+share:http://news.bbc.co.uk');
window.addEventListener('message', function (msg) {
if (msg.source !== service) {
return; // Not the response message we're looking for.
}
var output = document.getElementById("output");
output.src = msg.data[0];
}, false);

In RPH, the client page might learn the origin of the selected
service; whereas in WI, there's no channel for communicating this
information. In RPH, a service could conceal its origin by serving the
handler page with "Content-Type: text/html-sandboxed".

For handling an intent, the WI syntax is not yet defined, but View
Source on the Link Share example is currently:

attachEventListener(window, "load", function(e) {
var output = document.getElementById("output");
if(intent.data instanceof Array)
setText(output, intent.data[0]);
else
setText(output, intent.data);

intent.postResult(intent.data);
}, false);

The equivalent RPH syntax is:

if (isIntentFromChooser()) {
window.opener.postMessage(window.location.hash,
OriginOf(document.referrer));
}

The OriginOf() method extracts the origin of the document.referrer or
returns '*' if there is none.

An intent handler might or might not have an isIntentFromChooser()
method, depending on the security properties it wants. If the intent
handler wants to ensure that the intent was invoked via the browser's
Chooser, then it will want to guard against a client directly invoking
the intent handler. This could be implemented by embedding a secret in
the handler URL and checking for that secret before handling the
intent. Since the secret is only known to the browser's RPH
implementation, the secret will only be in window.location if the
intent was fired by the browser's Chooser.

AFAICT, we have equivalent functionality for all of the use cases that
have been documented on webintents.org using the existing RPH API. In
some cases, such as invoking an intent, the RPH syntax is much more
concise; in other cases, the syntax is not as good. For example, it
would probably be a good thing in general to augment the window.opener
API with the opener's origin. This would help in RPH as well as other
uses of postMessage. It might also make sense to continue with
defining a window.intent API, but one that is defined to hold a second
copy of the "%s" string for the RPH invocation. That would eliminate
the need for the client to implement an isIntentFromChooser() check.
With these improvements, the previously shown RPH syntax for handling
an intent becomes:

window.opener.postMessage(window.intent, window.openerOrigin);

The current webintents.org use-cases are probably not exhaustive of
what WI wants to achieve; so these other use-cases should be
documented so we can continue to compare them to the RPH based
implementation.

--Tyler

Rachel Blum

unread,
Sep 12, 2011, 2:22:43 PM9/12/11
to web-i...@googlegroups.com
I'm probably missing something, but doesn't using RPH mean we give up client-side differentiation by mime type?

Rachel

Tyler Close

unread,
Sep 12, 2011, 2:35:28 PM9/12/11
to web-i...@googlegroups.com
With RPH as is, an intent is only dispatched on the URI scheme;
whereas in WI as is, there are two strings to dispatch on: the verb
and a MIME type. The conversation around RPH already has people who
want to dispatch on more than just the URI scheme, such as to handle
URNs where there's both a NID and NSS to dispatch on. If we come
across a use case that can't be solved without two dispatch
identifiers, then we could weigh in on the current conversation around
this topic on RPH.

So I don't think "give up" is the right way to think about it. There
are two fluid but currently separate conversations going on, so there
should be room for accommodation.

--Tyler

Paul Kinlan

unread,
Sep 12, 2011, 4:22:43 PM9/12/11
to web-i...@googlegroups.com
Hi,

CIL on a couple of the points.

On Mon, Sep 12, 2011 at 11:11 AM, Tyler Close <tjc...@google.com> wrote:
At our meeting last week, we spent a good deal of time discussing
registerProtocolHandler and whether it made sense to consolidate our
efforts behind this API instead of continuing with parallel efforts. I
took an action to redo the examples at webintents.org using
registerProtocolHandler.

The front page of webintents.org uses the link sharing example to
showcase the syntax for registering for an intent and for invoking an
intent. For registration, the WI syntax is:

 <intent
   action="http://webintents.org/share"
   type="image/*"
   href="share.html"
   title="Share Link"
  />

The equivalent RPH syntax is:

 navigator.registerProtocolHandler(
   'web+share',
   'share.html#%s',
   'Share Link'
 );

Probably a typo - WI is registering as a handler for sharing an image, and RPH is just sharing a link.


For invoking an intent, the WI syntax is:

 var intent = new Intent("http://webintents.org/share",
   "text/uri-list",
   "http://news.bbc.co.uk");
 window.navigator.startActivity(intent);

The equivalent RPH syntax is:

 window.open('web+share:http://news.bbc.co.uk');

This is a really big thing for me, whilst I quite like the conciseness of window.open, we have lost the ability to filter on the data type.  The example prior of the registration is very explicit in that it will only handle images.

I am presuming this is where you would imagine the NSS coming in.
 

The WI pick intent shows the syntax for the client to receive a
response from the intent handler:

 var intent = new Intent();
 intent.action = "http://webintents.org/pick";
 intent.type = "image/*";
 window.navigator.startActivity(intent, intentResponse);
 var intentResponse = function (intentData) {
   var output = document.getElementById("output");
   output.src = intentData.data[0];
 };

The equivalent RPH syntax is:

 var service = window.open('web+share:http://news.bbc.co.uk');
 window.addEventListener('message', function (msg) {
   if (msg.source !== service) {
     return;  // Not the response message we're looking for.
   }
   var output = document.getElementById("output");
   output.src = msg.data[0];
 }, false);
 
The RPH demo is only sharing a link.  I am curious, how would RPH look for sharing a full DataURI given that we might be constrained for the url length?  We are starting to work more with the activity stream folks, they have a rich photo activity stream object (essentially JSON or XML http://activitystrea.ms/specs/json/1.0/), how would RPH look in that case?   The WI would just pass the object straight through.

intent.action = "http://webintents.org/share";
intent.type = "activitystream/photo";
intent.data = {
  "object" : {
       "url": "http://example.org/album/my_fluffy_cat.jpg",
       "objectType": "photo",
       "id": "tag:example.org,2011:my_fluffy_cat",
       "image": {
          "url": "http://example.org/album/my_fluffy_cat_thumb.jpg",
          "width": 250,
         "height": 250
      }
   }
}
window.navigator.startActivity(intent);

I also worry about the origin checking boiler plate that the developer would have to include as well as issues with repeated messages.
 
In RPH, the client page might learn the origin of the selected
service; whereas in WI, there's no channel for communicating this
information. In RPH, a service could conceal its origin by serving the
handler page with "Content-Type: text/html-sandboxed".

The current solution is the returned data could be used if the service wanted to expose the data, so a share of a link could return twitter.com/status/123456 if it was a public DM, twitter.com/ if it is a DM, or nothing at all.  It is up to the service.

Content types are a pain for developers to set up and is not application specific, if flickr chose to handle "share" and they didn't want to expose their url back they have to set their server from now on forwards to return text/html-sandboxed?  That is a pretty comprehensive change (even though it might seem innocuous) - my experience with AppCache suggests that this is not the best solution.
 
For handling an intent, the WI syntax is not yet defined, but View
Source on the Link Share example is currently:

   attachEventListener(window, "load", function(e) {
     var output = document.getElementById("output");
     if(intent.data instanceof Array)
       setText(output, intent.data[0]);
     else
       setText(output, intent.data);

     intent.postResult(intent.data);
   }, false);

The equivalent RPH syntax is:

 if (isIntentFromChooser()) {
   window.opener.postMessage(window.location.hash,
                                             OriginOf(document.referrer));
 }

Window.intent is where the data will be and is defined in the spec. Can you include the code that parses the data and uses it, the idea behind that WI demo is that we are doing something with the data - the example looks a little biased.  

In the RPH example we have two new API methods.  Are they intended to be implemented by the UA or the developer.

This is the problem that developers have at the moment with postMessage is that they have to manage where it is calling back to.
 
 
The OriginOf() method extracts the origin of the document.referrer or
returns '*' if there is none.

So if the client changes it's own document.location (i.e, a normal navigation) we could end up broadcasting secret data to the wrong window?  Given we have a lot of filtering proxies and https sites, this seems pretty insecure.
 
An intent handler might or might not have an isIntentFromChooser()
method, depending on the security properties it wants. If the intent
handler wants to ensure that the intent was invoked via the browser's
Chooser, then it will want to guard against a client directly invoking
the intent handler. This could be implemented by embedding a secret in
the handler URL and checking for that secret before handling the
intent. Since the secret is only known to the browser's RPH
implementation, the secret will only be in window.location if the
intent was fired by the browser's Chooser.

AFAICT, we have equivalent functionality for all of the use cases that
have been documented on webintents.org using the existing RPH API. In
some cases, such as invoking an intent, the RPH syntax is much more
concise; in other cases, the syntax is not as good. For example, it
would probably be a good thing in general to augment the window.opener
API with the opener's origin.

I initially explored document.referrer, which can give you the origin on none https connections.  So the current RPH might have to be mindful of that any window opened would potentially leak the client information.  If I was a client site and I didn't want to share knowledge of my service what would I do to not leak that information - use https?

In the native UA implementation window.intent will be populated and modifiable only by the UA.  We also shouldn't have a window.opener or window.parent.  In this situation other than onmessage and using a window.name hack (as per the shim) is there any other way to populate window.intent.

In RPH how do we stop pages on the same domain manipulating each other once launched?

This would help in RPH as well as other
uses of postMessage. It might also make sense to continue with
defining a window.intent API, but one that is defined to hold a second
copy of the "%s" string for the RPH invocation. That would eliminate
the need for the client to implement an isIntentFromChooser() check.
With these improvements, the previously shown RPH syntax for handling
an intent becomes:

 window.opener.postMessage(window.intent, window.openerOrigin);

The current webintents.org use-cases are probably not exhaustive of
what WI wants to achieve; so these other use-cases should be
documented so we can continue to compare them to the RPH based
implementation.

There is a range on http://usecases.webintents.org/ but I agree, there is a lot more to document.  PICK, EDIT and VIEW are big usecases.
 

--Tyler

I know we talked alot about using an iframe at the meeting. Are we discounting that now?

--
Paul Kinlan
Developer Advocate @ Google for Chrome and HTML5

Tyler Close

unread,
Sep 12, 2011, 6:08:02 PM9/12/11
to web-i...@googlegroups.com
A suspect a videoconference would work better for this depth of
conversation, but I'll try responses inline for now...

It's an inherited typo. :) I copy pasted the example code from the
webintents.org home page. You should probably fix it there too so that
the registration and invocation examples correspond to each other.

>> For invoking an intent, the WI syntax is:
>>
>>  var intent = new Intent("http://webintents.org/share",
>>    "text/uri-list",
>>    "http://news.bbc.co.uk");
>>  window.navigator.startActivity(intent);
>>
>> The equivalent RPH syntax is:
>>
>>  window.open('web+share:http://news.bbc.co.uk');
>
> This is a really big thing for me, whilst I quite like the conciseness of
> window.open, we have lost the ability to filter on the data type.  The
> example prior of the registration is very explicit in that it will only
> handle images.
> I am presuming this is where you would imagine the NSS coming in.

There are a couple ways to narrow the filter:
1. We could dive into the RPH discussion on finer grained matching of the URL.
2. We could collapse the two identifier space into a single
identifier. So 'web+share-image' is the intent to use when image
handlers are most relevant. A generic share handler would register for
both of the intents: web+share-image and web+share. An image share
handler would only register for the one.

I doubt this question should be a blocker for using RPH for intents.

>> The WI pick intent shows the syntax for the client to receive a
>> response from the intent handler:
>>
>>  var intent = new Intent();
>>  intent.action = "http://webintents.org/pick";
>>  intent.type = "image/*";
>>  window.navigator.startActivity(intent, intentResponse);
>>  var intentResponse = function (intentData) {
>>    var output = document.getElementById("output");
>>    output.src = intentData.data[0];
>>  };
>>
>> The equivalent RPH syntax is:
>>
>>  var service = window.open('web+share:http://news.bbc.co.uk');
>>  window.addEventListener('message', function (msg) {
>>    if (msg.source !== service) {
>>      return;  // Not the response message we're looking for.
>>    }
>>    var output = document.getElementById("output");
>>    output.src = msg.data[0];
>>  }, false);
>
>
> The RPH demo is only sharing a link.  I am curious, how would RPH look for
> sharing a full DataURI given that we might be constrained for the url
> length?

Are we constrained on the length? AFAIK, URL length limitation only
applies to dispatches that go through the local operating system,
especially on Windows. Do dispatches that happen entirely within the
browser have a URL length limitation?

For big data, it's probably best to pass the data through the
postMessage API, but doing something with the BLOB URLs in the browser
might also be interesting.

>  We are starting to work more with the activity stream folks, they
> have a rich photo activity stream object (essentially JSON or XML
> http://activitystrea.ms/specs/json/1.0/), how would RPH look in that case?
> The WI would just pass the object straight through.
> intent.action = "http://webintents.org/share";
> intent.type = "activitystream/photo";
> intent.data = {
>   "object" : {
>        "url": "http://example.org/album/my_fluffy_cat.jpg",
>        "objectType": "photo",
>        "id": "tag:example.org,2011:my_fluffy_cat",
>        "image": {
>           "url": "http://example.org/album/my_fluffy_cat_thumb.jpg",
>           "width": 250,
>          "height": 250
>       }
>    }
> }
> window.navigator.startActivity(intent);

If you want to pass it all upfront, you could do:

window.open('web+share:' + encodeURI(JSON.stringify(activityObject)));

If you're willing to do it in two passes, you could just pass the
object.url initially and then postMessage all the extra meta data.

> I also worry about the origin checking boiler plate that the developer would
> have to include as well as issues with repeated messages.

I think I included all the necessary checking in the example code I've
provided. Could you point out the lines that trouble you?

>> In RPH, the client page might learn the origin of the selected
>> service; whereas in WI, there's no channel for communicating this
>> information. In RPH, a service could conceal its origin by serving the
>> handler page with "Content-Type: text/html-sandboxed".
>
> The current solution is the returned data could be used if the service
> wanted to expose the data, so a share of a link could return
> twitter.com/status/123456 if it was a public DM, twitter.com/ if it is a DM,
> or nothing at all.  It is up to the service.
> Content types are a pain for developers to set up and is not application
> specific, if flickr chose to handle "share" and they didn't want to expose
> their url back they have to set their server from now on forwards to return
> text/html-sandboxed?

The handler's URL is never exposed to the client. Only the handler's
origin might be exposed to the client as a result of a postMessage
invocation. Are you saying Flickr might need to hide its origin from
client pages, but is unable to deploy a Content-Type header? A site
that is truly trying to be anonymous is going to have a lot more to do
than just deploying a Content-Type header, independent of Web Intents
or RPH.

>  That is a pretty comprehensive change (even though it
> might seem innocuous) - my experience with AppCache suggests that this is
> not the best solution.
>
>>
>> For handling an intent, the WI syntax is not yet defined, but View
>> Source on the Link Share example is currently:
>>
>>    attachEventListener(window, "load", function(e) {
>>      var output = document.getElementById("output");
>>      if(intent.data instanceof Array)
>>        setText(output, intent.data[0]);
>>      else
>>        setText(output, intent.data);
>>
>>      intent.postResult(intent.data);
>>    }, false);
>>
>> The equivalent RPH syntax is:
>>
>>  if (isIntentFromChooser()) {
>>    window.opener.postMessage(window.location.hash,
>>                                              OriginOf(document.referrer));
>>  }
>
> Window.intent is where the data will be and is defined in the spec.

Huh, I don't see it on the webintents.org home page yet. Clicking
specification just links to the home page. Is there another document I
should be looking at? The last meeting with Mozilla also left me with
the impression that window.intent is not agreed to yet.

> Can you
> include the code that parses the data and uses it, the idea behind that WI
> demo is that we are doing something with the data - the example looks a
> little biased.

For the link sharing example that I was doing, there is no parsing to
be done. "window.location.hash" just works. If you want to put complex
data types in the intent, you'll need a call to JSON.parse().
Alternatively, use postMessage for exchange of complex meta data.

> In the RPH example we have two new API methods.  Are they intended to be
> implemented by the UA or the developer.

Those methods are to be implemented by the developer. Later, I show
how we could avoid those methods by enhancing the RPH API with a
"window.intent" and "window.openerOrigin" API. By showing both
techniques, I show we have backwards compatibility.

> This is the problem that developers have at the moment with postMessage is
> that they have to manage where it is calling back to.

You mean intent.postResult() versus opener.postMessage()?

>> The OriginOf() method extracts the origin of the document.referrer or
>> returns '*' if there is none.
>
> So if the client changes it's own document.location (i.e, a normal
> navigation) we could end up broadcasting secret data to the wrong window?

How would that happen?

>  Given we have a lot of filtering proxies and https sites, this seems pretty
> insecure.

You'll have to elaborate.

>> An intent handler might or might not have an isIntentFromChooser()
>> method, depending on the security properties it wants. If the intent
>> handler wants to ensure that the intent was invoked via the browser's
>> Chooser, then it will want to guard against a client directly invoking
>> the intent handler. This could be implemented by embedding a secret in
>> the handler URL and checking for that secret before handling the
>> intent. Since the secret is only known to the browser's RPH
>> implementation, the secret will only be in window.location if the
>> intent was fired by the browser's Chooser.
>>
>> AFAICT, we have equivalent functionality for all of the use cases that
>> have been documented on webintents.org using the existing RPH API. In
>> some cases, such as invoking an intent, the RPH syntax is much more
>> concise; in other cases, the syntax is not as good. For example, it
>> would probably be a good thing in general to augment the window.opener
>> API with the opener's origin.
>
> I initially explored document.referrer, which can give you the origin on
> none https connections.  So the current RPH might have to be mindful of that
> any window opened would potentially leak the client information.

Passing the intent data in the URL fragment prevents the data from
leaking via referrer.

>  If I was a
> client site and I didn't want to share knowledge of my service what would I
> do to not leak that information - use https?

To hide your origin from client pages, you'd need to use
"Content-Type: text/html-sandboxed". It's not ideal, but it would work
and this is not the main use case.

> In the native UA implementation window.intent will be populated and
> modifiable only by the UA.  We also shouldn't have a window.opener or
> window.parent.  In this situation other than onmessage and using a
> window.name hack (as per the shim) is there any other way to populate
> window.intent.

Pull the string out of window.location.hash after performing the
optional isIntentFromChooser() check I described.

> In RPH how do we stop pages on the same domain manipulating each other once
> launched?

Uh, you must mean something else. There's no protection in the browser
between pages in the same origin.

>> This would help in RPH as well as other
>> uses of postMessage. It might also make sense to continue with
>> defining a window.intent API, but one that is defined to hold a second
>> copy of the "%s" string for the RPH invocation. That would eliminate
>> the need for the client to implement an isIntentFromChooser() check.
>> With these improvements, the previously shown RPH syntax for handling
>> an intent becomes:
>>
>>  window.opener.postMessage(window.intent, window.openerOrigin);
>>
>> The current webintents.org use-cases are probably not exhaustive of
>> what WI wants to achieve; so these other use-cases should be
>> documented so we can continue to compare them to the RPH based
>> implementation.
>
> There is a range on http://usecases.webintents.org/ but I agree, there is a
> lot more to document.  PICK, EDIT and VIEW are big usecases.

Let's find one that can't be done using RPH, or else use RPH. Which
one should we look at next?

>
>>
>> --Tyler
>
> I know we talked alot about using an iframe at the meeting. Are we
> discounting that now?

No, I think iframes are also useful. I'm just sticking to the WI
use-cases for now, since WI doesn't use iframes.

--Tyler

Greg Billock

unread,
Sep 12, 2011, 6:32:52 PM9/12/11
to web-i...@googlegroups.com
Would it make more sense to mock these calls up using an "intent:" scheme? It seems likely that there'd end up being lots of different scheme types using web+, and they'd all need roughly parallel definitions.

This might also provide a good insight into the difference in the standardization approaches, which was a key reason to consider this. I think an "intent:" scheme RFC, and the change to add it to the RPH whitelist, is a good indicator of the standardization work involved.

Tyler Close

unread,
Sep 12, 2011, 8:00:43 PM9/12/11
to web-i...@googlegroups.com
On Mon, Sep 12, 2011 at 3:32 PM, Greg Billock <gbil...@google.com> wrote:
> Would it make more sense to mock these calls up using an "intent:" scheme?

AFAICT, HTML5 explicitly set aside the web+ URI scheme space for
exactly this sort of coordination between Web sites. Seems easier to
use it than to go asking for something different.

> It seems likely that there'd end up being lots of different scheme types
> using web+, and they'd all need roughly parallel definitions.

Why do you think the definitions would be roughly parallel? Wouldn't
each web+ scheme specify different intent data to be passed in the
scheme specific part of the URL? I can see where we might get families
of web+ schemes if we often need to embed MIME type information in the
scheme. Is that what you're thinking of?

> This might also provide a good insight into the difference in the
> standardization approaches, which was a key reason to consider this. I think
> an "intent:" scheme RFC, and the change to add it to the RPH whitelist, is a
> good indicator of the standardization work involved.

But we could also just use the web+ scheme that was provided to us and
do almost no standardization work. There's a lot of consensus work
that's already been done that we could leverage to handle the
use-cases we are interested in.

--Tyler

Greg Billock

unread,
Sep 13, 2011, 1:57:11 PM9/13/11
to web-i...@googlegroups.com
I think it'll be easier to specify a single url scheme, and it's a poor developer experience to have to deal with a different parser for many different scheme encodings. I'd guess the difference in standardization complexity for "intent:" or "web+intent:" is pretty comparable, but I may be wrong about that.

Here's a proposed mechanical flattening from intent data to a url scheme:

Intent {
   string action
   string type
   any data
}

maps to

web+intent:action;urlencode(type)/urlencode(JSON.stringify(data))

The charset for action is any urlsafe characters not including ';'. The suggestion is a url-style identifier like "www.webintents.org/share".

We've discussed such transformations before in the context of having forms initiate intents and so forth. There may be interesting classes of data which are hard to transmit this way, such as large image payloads and exotic serializable types.

The issues we talked about last week were more along the lines of how you manage the iframe communication to provide the proper isolation and communication coordination. Specifically, it seems almost certain to me that apps will want to know that the intent data is coming to them through a user action rather than as part of a clickjacking attack. How would the secret url-based token you envision work for that case? Also, the matter of how to handshake to bring down any subsequent data through postMessage ought to be spelled out as part of the API.

Ben's worry, and I tend to agree, is that these pieces will be large enough and error-prone enough that they need to be part of a new API, and once that happens, there's very little leverage in using the RPH substrate. Perhaps there's an ingenious and compelling solution, though, that we haven't thought of yet. I like the request-response RPC style metaphor that a URL signals. I think that's a better match to the problem domain than a channel-based model. If RPH ends up steering us into a mixture of both, though, that's a loss in terms of complexity in the spec and hence accessibility to developers.

Tyler Close

unread,
Sep 13, 2011, 2:51:01 PM9/13/11
to web-i...@googlegroups.com
On Tue, Sep 13, 2011 at 10:57 AM, Greg Billock <gbil...@google.com> wrote:
> I think it'll be easier to specify a single url scheme, and it's a poor
> developer experience to have to deal with a different parser for many
> different scheme encodings. I'd guess the difference in standardization
> complexity for "intent:" or "web+intent:" is pretty comparable, but I may be
> wrong about that.
> Here's a proposed mechanical flattening from intent data to a url scheme:
> Intent {
>    string action
>    string type
>    any data
> }
> maps to
> web+intent:action;urlencode(type)/urlencode(JSON.stringify(data))
>
> The charset for action is any urlsafe characters not including ';'. The
> suggestion is a url-style identifier like "www.webintents.org/share".
> We've discussed such transformations before in the context of having forms
> initiate intents and so forth. There may be interesting classes of data
> which are hard to transmit this way, such as large image payloads and exotic
> serializable types.

I think there are a number of feasible RPH-based solutions in this
area, so I'm going to step back from this part of the discussion to
focus on your other questions. I expect the RPH implementers will have
opinions here too.

> The issues we talked about last week were more along the lines of how you
> manage the iframe communication to provide the proper isolation and
> communication coordination. Specifically, it seems almost certain to me that
> apps will want to know that the intent data is coming to them through a user
> action rather than as part of a clickjacking attack. How would the secret
> url-based token you envision work for that case?

The secret token implementation need only be used by the JavaScript
shim, until we get native support for window.intent, which stores a
copy of the %s string for the current RPH request.

The JavaScript shim generates a per-user secret before calling
registerProtocolHandler() . It stores a copy of this secret in
localStorage, or in a cookie, or server-side. It also puts a copy of
this secret in the RPH handler URL. On each RPH invocation, the shim
checks that the window.location URL contains the expected secret. If
the secret is present, the shim will populate window.intent with the
%s data. This check ensures that the load of the handler URL must have
been done via the browser's RPH UX.

> Also, the matter of how to
> handshake to bring down any subsequent data through postMessage ought to be
> spelled out as part of the API.

I think the sequence is always:
1) client initiates RPH with an intent URL
2) handler responds via opener.postMessage
3) (optional) client and handler exchange additional postMessage data

I expect part 3 will be dependent upon the type of intent. For social
bookmarking and many others, there may be no step 3.

Think of this RPH API as providing even better support for the
one-shot data exchange use-cases that Web Intents focuses on, while
also enabling extended conversations as Web Introducer does and as
Mozilla has said is important. We also get the bonus of an existing
specification home, an implementation deployed since Firefox 3.0, and
we can ride under the "mailto" use-case to wide deployment across
browsers. This really is a pretty sweet setup to hit the Web Intents
use-cases.

> Ben's worry, and I tend to agree, is that these pieces will be large enough
> and error-prone enough that they need to be part of a new API, and once that
> happens, there's very little leverage in using the RPH substrate.

The window.intent and window.openerOrigin (or even just window.origin)
API changes I proposed seem very lightweight to me. Do you disagree or
do you think they are insufficient? What else is needed? As we
discussed during the meeting, the purpose of this email thread is to
get specific about these worries so we can either prove them or
invalidate them.

> Perhaps
> there's an ingenious and compelling solution, though, that we haven't
> thought of yet. I like the request-response RPC style metaphor that a URL
> signals. I think that's a better match to the problem domain than a
> channel-based model. If RPH ends up steering us into a mixture of both,
> though, that's a loss in terms of complexity in the spec and hence
> accessibility to developers.

The RPH has a strong bias to simple RPC style, via the intent URL,
similar to Web Intents. RPH does enable extended postMessage
conversations, but does so without adding any new API surface to the
browser (postMessage already exists, we don't have to specify it).
More power with less API is always a good thing. Ben made it clear
during our last meeting that he suspects extended conversations will
be important, so enabling them at no API cost seems like a great win.
If you really don't like extended postMessage conversations, I think
the thing to do is work through the Web Intents use cases to ensure
they can be implemented in a style that you like. AFAICT, the only
potential stumbling block is the need to encode the initial intent
data in URL form, instead of as a JSON object. Can you see any other
specific issues?

Greg Billock

unread,
Sep 13, 2011, 3:08:09 PM9/13/11
to web-i...@googlegroups.com
I didn't realize you envisioned still proposing a 'window.intent' for use with an RPH delivery method. My impression was that using a combination of window.location and postMessage might accomplish that. If there's serious usability problems or security concerns with that approach, there's definitely intermediate steps, but they get a lot less appealing to consider as more changes end up being involved.

Tyler Close

unread,
Sep 13, 2011, 3:40:01 PM9/13/11
to web-i...@googlegroups.com
On Tue, Sep 13, 2011 at 12:08 PM, Greg Billock <gbil...@google.com> wrote:
> I didn't realize you envisioned still proposing a 'window.intent' for use
> with an RPH delivery method. My impression was that using a combination of
> window.location and postMessage might accomplish that.

The JavaScript shim implementation I described works.

> If there's serious
> usability problems or security concerns with that approach, there's
> definitely intermediate steps, but they get a lot less appealing to consider
> as more changes end up being involved.

Wow, really? I've proposed adding two string constants to DOMWindow to
make RPH easier to use safely. That's it. Compare getting those in to
starting a new WG.

--Tyler

Greg Billock

unread,
Sep 13, 2011, 4:44:38 PM9/13/11
to web-i...@googlegroups.com
On Tue, Sep 13, 2011 at 12:40 PM, Tyler Close <tjc...@google.com> wrote:
On Tue, Sep 13, 2011 at 12:08 PM, Greg Billock <gbil...@google.com> wrote:
> I didn't realize you envisioned still proposing a 'window.intent' for use
> with an RPH delivery method. My impression was that using a combination of
> window.location and postMessage might accomplish that.

The JavaScript shim implementation I described works.

> If there's serious
> usability problems or security concerns with that approach, there's
> definitely intermediate steps, but they get a lot less appealing to consider
> as more changes end up being involved.

Wow, really? I've proposed adding two string constants to DOMWindow to
make RPH easier to use safely. That's it. Compare getting those in to
starting a new WG.


I'm confused, then. I was thinking you wanted to use window.intent for delivery.
Is that what you mean by a string constant? Or is it simply that having a new DOMWindow
element isn't something that needs any standardization work? My perception at present
is that most of the delay and work with the W3C is the fixed cost of getting on the agenda
of the right WG.

The proposed Web Intents IDL is also quite small: a method on navigator and window.intent.
If using RPH will end up being of comparable weight, then it looks to me like the original reason
for considering this approach is quite weak. There may be other reasons to like it -- encoding
an intent as a URL is pretty slick, and getting the RPH folks thinking about the problems involved
would be great, for instance.

James Hawkins

unread,
Sep 13, 2011, 4:51:40 PM9/13/11
to web-i...@googlegroups.com
On Tue, Sep 13, 2011 at 1:44 PM, Greg Billock <gbil...@google.com> wrote:

On Tue, Sep 13, 2011 at 12:40 PM, Tyler Close <tjc...@google.com> wrote:
On Tue, Sep 13, 2011 at 12:08 PM, Greg Billock <gbil...@google.com> wrote:
> I didn't realize you envisioned still proposing a 'window.intent' for use
> with an RPH delivery method. My impression was that using a combination of
> window.location and postMessage might accomplish that.

The JavaScript shim implementation I described works.

> If there's serious
> usability problems or security concerns with that approach, there's
> definitely intermediate steps, but they get a lot less appealing to consider
> as more changes end up being involved.

Wow, really? I've proposed adding two string constants to DOMWindow to
make RPH easier to use safely. That's it. Compare getting those in to
starting a new WG.


I'm confused, then. I was thinking you wanted to use window.intent for delivery.
Is that what you mean by a string constant? Or is it simply that having a new DOMWindow
element isn't something that needs any standardization work? My perception at present
is that most of the delay and work with the W3C is the fixed cost of getting on the agenda
of the right WG.

The proposed Web Intents IDL is also quite small: a method on navigator and window.intent.
If using RPH will end up being of comparable weight, then it looks to me like the original reason
for considering this approach is quite weak. There may be other reasons to like it -- encoding
an intent as a URL is pretty slick, and getting the RPH folks thinking about the problems involved
would be great, for instance.
 
Encoding intents as URL is also useful for the WI proposal, e.g., easily embedding invocation directly into HTML elements or forms.

Tyler Close

unread,
Sep 13, 2011, 5:33:40 PM9/13/11
to web-i...@googlegroups.com
On Tue, Sep 13, 2011 at 1:44 PM, Greg Billock <gbil...@google.com> wrote:
>
> On Tue, Sep 13, 2011 at 12:40 PM, Tyler Close <tjc...@google.com> wrote:
>>
>> On Tue, Sep 13, 2011 at 12:08 PM, Greg Billock <gbil...@google.com>
>> wrote:
>> > I didn't realize you envisioned still proposing a 'window.intent' for
>> > use
>> > with an RPH delivery method. My impression was that using a combination
>> > of
>> > window.location and postMessage might accomplish that.
>>
>> The JavaScript shim implementation I described works.
>>
>> > If there's serious
>> > usability problems or security concerns with that approach, there's
>> > definitely intermediate steps, but they get a lot less appealing to
>> > consider
>> > as more changes end up being involved.
>>
>> Wow, really? I've proposed adding two string constants to DOMWindow to
>> make RPH easier to use safely. That's it. Compare getting those in to
>> starting a new WG.
>
>
> I'm confused, then. I was thinking you wanted to use window.intent for
> delivery.

window.intent is a readonly DOMString that contains the %s data for
the RPH invocation.
document.origin is a readonly DOMString that contains the opener's Origin.

Two string constants. The first is a small tweak to the existing RPH
API. The second could be seen as an obvious extension of the Origin
work to document.referrrer.

> Is that what you mean by a string constant? Or is it simply that having a
> new DOMWindow
> element isn't something that needs any standardization work? My perception
> at present
> is that most of the delay and work with the W3C is the fixed cost of getting
> on the agenda
> of the right WG.

RPH is already a deliverable of the HTML5 WG. We could ask for small
tweaks to it, such as two string constants.

> The proposed Web Intents IDL is also quite small: a method on navigator and
> window.intent.

Web Intents is a new deliverable.

> If using RPH will end up being of comparable weight, then it looks to me
> like the original reason
> for considering this approach is quite weak. There may be other reasons to
> like it -- encoding
> an intent as a URL is pretty slick, and getting the RPH folks thinking about
> the problems involved
> would be great, for instance.

I think there are a number of reasons to prefer RPH over WI beyond
just ease of standardization. I'm proposing this because I think it's
a better way forward in all respects.

--Tyler

Ben Adida

unread,
Sep 14, 2011, 10:33:49 PM9/14/11
to web-i...@googlegroups.com

Hi Tyler,

Thanks for taking up this action.

Overall, seeing these examples, I am increasingly uncomfortable with
window.open() as the approach for starting an activity. It greatly
limits flexibility as to how activities are fulfilled in the future, in
particular wrt mediation and trusted UA interfaces (doorhangers and the
like.) window.open is window.open. But that's not necessarily what
starting an activity should do.

Using RPH a cool idea, but I don't think it takes us far enough.

Digging further into some detail:

> var service = window.open('web+share:http://news.bbc.co.uk');
> window.addEventListener('message', function (msg) {
> if (msg.source !== service) {
> return; // Not the response message we're looking for.
> }

Does the above protect against that window being navigated to some other
location? I don't think so, but maybe I'm missing something.

> handler page with "Content-Type: text/html-sandboxed".

Is this final in the HTML spec? I can't quite tell.

> The equivalent RPH syntax is:
>
> if (isIntentFromChooser()) {
> window.opener.postMessage(window.location.hash,
> OriginOf(document.referrer));
> }

Again, I'm not sure this protects against window.opener having change
location. I can imagine some gnarly situations where an attacker opens
up a window to the good initiator, which initiates the activity, then
the attacker navigates the window it opened before the provider
responds, and the attacker receives the response.

It looks like this approach inherently cannot use the security
properties of postMessage(), and thus must rely on these extra secrets
in the fragment identifier, and hoping that windows are not re-navigated
in the interim. It feels very brittle.

So I'm back to the feeling I originally had: this seems like an
interesting stop-gap implementation strategy, but not like a great
*contract* on which to build the next generation of web IPC.

-Ben

Tyler Close

unread,
Sep 15, 2011, 12:53:59 PM9/15/11
to web-i...@googlegroups.com
Hi Ben,

It looks like you have two concerns with RPH:

1) You're worried window.open() prevents the browser from using a
special browsing context instead of a popup window.
2) You have some misunderstandings about how postMessage authentication works.

AFAICT, 2) really is just a misunderstanding about postMesage, but
please correct me if I've missed something. In postMessage, the
invoker specifies the expected origin of the target window. If the
expected origin doesn't match the actual origin, the message is not
delivered. In RPH, the intent handler responds to an intent with code
like:

window.opener.postMessage(someData, document.origin)

The shim will setup document.origin using document.referrer.
document.origin is fixed at the time the intent is launched and
doesn't change even if the opener window is navigated to some other
URL. So if a legitimate window launches an intent and then an attacker
navigates the legitimate window to his own origin, the browser will
drop the intent response on the floor. So the attacker cannot
intercept the response.

For 1), I think browsers have a lot of discretion in terms of how they
process window.open(). The popup blockers already introduce custom UX
(the infobar and other widgets) before processing the open(). I
believe browsers also have a lot of discretion in term of what kind of
browsing context is finally created for the window.open(). What
inviolable constraints do you think window.open() places on the
browser?

--Tyler

Ben Adida

unread,
Sep 15, 2011, 5:43:43 PM9/15/11
to web-i...@googlegroups.com
On 9/15/11 9:53 AM, Tyler Close wrote:
> 1) You're worried window.open() prevents the browser from using a
> special browsing context instead of a popup window.

Yes.

> 2) You have some misunderstandings about how postMessage authentication works.

I don't think so :)

> In postMessage, the invoker specifies the expected origin of the target window.

Right, and in the case where the service provider doesn't know the
origin of the invoker, it is forced to specify "*" (as I believe you
pointed out in your example.)

Also, from the invocation point of view, are you envisioning that the
URL of the opened window stays "web+share:..." ? Are we sure that works?

> For 1), I think browsers have a lot of discretion in terms of how they
> process window.open(). The popup blockers already introduce custom UX
> (the infobar and other widgets) before processing the open().

That's just about whether to open the window or not. The window opening
action itself, if it goes through, is always the same in current browsers.

> believe browsers also have a lot of discretion in term of what kind of
> browsing context is finally created for the window.open().

I'm not convinced. The mediation examples we've suggested require
completely hijacking the process and then possibly framing the target
URL, rather than having it in its own window. That is a significant
change of behavior for window.open that feels like a big stretch.

-Ben

Tyler Close

unread,
Sep 15, 2011, 7:14:19 PM9/15/11
to web-i...@googlegroups.com
On Thu, Sep 15, 2011 at 2:43 PM, Ben Adida <bena...@mozilla.com> wrote:
> On 9/15/11 9:53 AM, Tyler Close wrote:
>>
>> 1) You're worried window.open() prevents the browser from using a
>> special browsing context instead of a popup window.
>
> Yes.
>
>> 2) You have some misunderstandings about how postMessage authentication
>> works.
>
> I don't think so :)
>
>> In postMessage, the invoker specifies the expected origin of the target
>> window.
>
> Right, and in the case where the service provider doesn't know the origin of
> the invoker, it is forced to specify "*" (as I believe you pointed out in
> your example.)

No. The intent handler will always specify document.origin in the
postMessage() invocation. In an updated browser, that will always
contain the origin of the page that launched the intent. I'm
suggesting we ask for two updates to HTML5: document.origin and
window.intent. So as a "going forward" API, we have strong security.

For the shim implementation, document.origin might end up as '*' if
document.referrer is not populated, though there might be some hackery
to fix that as well. For example, we could pass the opener origin
through the window.location.

> Also, from the invocation point of view, are you envisioning that the URL of
> the opened window stays "web+share:..." ?

No, window.location will have the value specified by RPH.

>> For 1), I think browsers have a lot of discretion in terms of how they
>> process window.open(). The popup blockers already introduce custom UX
>> (the infobar and other widgets) before processing the open().
>
> That's just about whether to open the window or not. The window opening
> action itself, if it goes through, is always the same in current browsers.

Is it? For a mailto: URL or any other scheme not handled by the
browser, literally anything could happen, depending on how the host OS
is configured. Depending on how Firefox is configured, I think a
window.open() request can also be forced into a tab, instead of using
a popup. If that's OK, why isn't it OK to put it in a newly defined
kind of browsing context?

>> believe browsers also have a lot of discretion in term of what kind of
>> browsing context is finally created for the window.open().
>
> I'm not convinced. The mediation examples we've suggested require completely
> hijacking the process and then possibly framing the target URL, rather than
> having it in its own window. That is a significant change of behavior for
> window.open that feels like a big stretch.

Firefox already hijacks the process with its existing RPH
implementation. Depending on how Firefox is configured, it also can
frame a popup as a new tab. Firefox already engages in exactly this
sort of massaging of window.open() calls. So you may already be
stretched more than you realize. Also keep in mind that this new
behavior is only triggered for web+ schemes, and so the invoking page
has effectively opted in. AFAIK, a web page currently doesn't have any
guarantees about what UX will be presented if it does a window.open on
a URL with an unknown scheme. Depending on the OS, anything could
happen.

Whatever way you lean on this, also remember that the RPH train has
left the station. So it's going to be there regardless of whether or
not there is an additional intents API. So the question to ponder is
what's the best API and UX for RPH, because you have to deal with that
question no matter what. If you do a good job of it, you can avoid the
question of what new intent UX should we also create.

--Tyler

Paul Kinlan

unread,
Sep 15, 2011, 8:30:43 PM9/15/11
to web-i...@googlegroups.com
Hi,

Sorry for the delay in replying I have been in-flight for a while and just got back from an event in Stockholm.  I take the point that the RPH train has left the station, but jumping on to a moving train is pretty hard ;)

So, here are my thoughts thus far about why RPH is not quite what we are looking for:
  • Changing the window.opener to give the origin to me seems like a bigger change than it sounds and also risky, UA's are restricting access to any opener information and opening it up again seems odd - if we use https, surely we MUST NOT populate origin since UA's no longer populate the referrer, and if we don't populate it then aren't we still at square one?
  • RPH and postMessage will have the origin on all messages, this seems pretty crazy for a system that is trying to not disclose client and service destinations, there was mention of removing the origin when using text/html-sandboxed, if this feature exists there is no way to constrain a response back to the service and ensuring that only the correct origin recieves the message.
    • Also, text/html-sandboxed seems like security by exception, given that developers have nightmare enough setting correct mime-types on servers I could see the becoming a big issue if a developer forgot to set a server up correctly and wanted their origin to remain hidden.
    • I don't know the answer to this, but if I visit an app in a legacy browser that returns text/html-sandboxed will it assume text/html?
  • RPH has no success/failure response - We have postResult and possibly postException to indicate failure and potential re-selection of a service.  There is no way for the RPH framework to know that a call to a service was met with success or failure as the communication channel is between client and service app.  Knowing the success of an intent invocation is core to providing a solid user-experience.
  • RPH uses onmessage to handle all responses. This is a big one for me. If I fire three intents, intent:share and intent:save and intent:pick how do we know which launched intent is sending the data back to the me?  "onmessage" tells us the window that sent it but not what the action was, the RPH "string" is not part what is discoverable - and if it was it still doesn't solve the problem, if I start two "shares" and they could take arbitrarily long to complete (or fail) we don't have a way of directly knowing which response response is for a given invocation.  If I don't know this I am not in a great position - we would have to have an API/protocol layer on top of RPH that defines message formats and how you should interop with the service.
    • What if a newly created context closes?  Do we ever know it didn't complete?
    • You could say we can use a message port, but requiring a message port to be able to process the correct response enters developers in to a nightmare of boilerplate code and detecting when to pass the message port to or from the newly opened window.
  • Boiler plate, every "onmessage" you have to check if it is from a known source, if it is not then it is possibly from some RPH request (partly tied to the code above) or possibly some other frame that could be sending it messages.  Seems like a nightmare code maintenance issue.
  • Parsing window.location.hash or what-ever:  Developers hate parsing query string data inside their apps.
When you look at the UX of the RPH selection and the Web Intents service selection, will there be a big difference?  It is hard to tell at this stage, a user will have a task they need to perform on some data and will ask for an app that can handle it and they will be given a list. WI will be able to detect success or failure of an action so we could provide a re-selection prompt to the user. 

We believe we can make the UX for picking the services clear and intuitive to users so that they clearly understand what is happening and so that it feels natural.  At the same time Developer Experience of the physical API will play a huge part in the developer adoption of this API:
  • If developers have to think about 3 different ways to encode and transport data we will lose them;
  • if they have to think of the different ways they might receive the newly sent data (window.location or postMessage) then we will lose more;
  • if they have to think about how many messages they can send on a channel we will lose more again;
  • if they can't detect success or failure without a specific wire data format protocol then I think we will lose more developers;
  • if they have to think hard about how their client app should handle return messages (for instance they might have to create a state machine) we will lose more developers; 
  • if they have to attach a new mime-type to their apps to secure their origin we will lose more; 
  • if the developer has to have the same bolier plate cruft to filter out message not intended for the handler, then we will lose more;
  • if the developer can't just copy and paste code to get started in 2 minutes then we will lose more developers. 
The more developers we lose, then the less apps that will integrate with each other and then it doesn't matter how great we make the service picker.

The WI is a simple API intuitive API that can handle the three core scenarios: fire and forget messages; request and response; long lived MessageChannel (ok the shim can't yet but that is a side effect of supporting browsers that don't support MessageChannel/MessagePort).  The aim is to keep the API simple, accessible and open so that developers find it easy to build services that can receive data and build services that can ask for data.  If we can do that then we will have lots of happy users.

We have demos of apps showing how apps can be integrated, each with only a couple of lines of code.  They should be released shortly, I just have to pull the latest code and write some documentation.

P

Tyler Close

unread,
Sep 16, 2011, 1:38:27 PM9/16/11
to web-i...@googlegroups.com
Hi Paul,

Responses inline below...

On Thu, Sep 15, 2011 at 5:30 PM, Paul Kinlan <paulk...@google.com> wrote:
> Hi,

> Sorry for the delay in replying I have been in-flight for a while and just
> got back from an event in Stockholm.  I take the point that the RPH train
> has left the station, but jumping on to a moving train is pretty hard ;)
> So, here are my thoughts thus far about why RPH is not quite what we are
> looking for:

So "not quite" isn't a good enough reason to start standardization of
a parallel API. The friction that WI is encountering right now exists
to encourage would-be API designers to instead pitch in and make the
"not quite" solution a good fit for the use-case. It looks to me like
we can easily do that in this case. The issues you raise below can be
talked up in prose, but once you look at some example code, they just
melt away.

> Changing the window.opener to give the origin to me seems like a bigger
> change than it sounds and also risky,

The intent handler page already has access to the opener's origin via
the Origin HTTP header. It's just requires a round trip to the server
to fetch it. By defining document.origin, we just make it easier to
get at information that the page is already allowed to have.

> UA's are restricting access to any
> opener information and opening it up again seems odd - if we use https,
> surely we MUST NOT populate origin since UA's no longer populate the
> referrer, and if we don't populate it then aren't we still at square one?

You need to read up on the Origin HTTP header. It's been made
pervasive and is unaffected by https<->http transitions.

> RPH and postMessage will have the origin on all messages, this seems pretty
> crazy for a system that is trying to not disclose client and service
> destinations, there was mention of removing the origin when using
> text/html-sandboxed, if this feature exists there is no way to constrain a
> response back to the service and ensuring that only the correct origin
> recieves the message.

Messages from the client to the service are at much lower risk of
being hijacked than messages in the other direction due to the rules
governing window and frame navigation in the browser. If a client
launches an intent with the code:

var service = window.open('web+share:http://example.com/');

then only the client itself and the service itself can cause the
service window to be navigated. Another tab in the browser or even an
iframe inside the client cannot navigate the service window. On caveat
is that if the service itself opens another window, the service window
could be navigated by the opened window. So, in the unusual case where
the service is trying to conceal its identity from the client, we are
still pretty safe from message hijacking.

> Also, text/html-sandboxed seems like security by exception, given that

I agree, but that is the norm in the HTML world. For this particular
case, the risks are small. I expect in the vast majority of cases,
services are going to want to publicize their identity, not conceal
it. For the minority case where concealment is needed, we have a
workable solution.

> developers have nightmare enough setting correct mime-types on servers I
> could see the becoming a big issue if a developer forgot to set a server up
> correctly and wanted their origin to remain hidden.
> I don't know the answer to this, but if I visit an app in a legacy browser
> that returns text/html-sandboxed will it assume text/html?

I suspect the browser would content sniff it to HTML, but I haven't
tested. Since HTML is already taking on the task of how a page can
drop its origin, I suggest we just leave them to it.

> RPH has no success/failure response - We have postResult and possibly
> postException to indicate failure and potential re-selection of a service.
>  There is no way for the RPH framework to know that a call to a service was
> met with success or failure as the communication channel is between client
> and service app.

The RPH framework does of course see the results of the page load and
so knows if the page failed to load. So there's an empirical question
of "How will intent handler failures manifest?". Will the page fail to
load, or will it load but not call postResult, or will it load and
call postResult with the wrong data? Hard to know in advance. With RPH
the browser has the signals:

1) did the page load
2) was window.opener.postMessage() invoked?

with WI, the signals are almost the same. So either way, browser
detection of application-level failures seems about the same.

> Knowing the success of an intent invocation is core to
> providing a solid user-experience.

Does Android require this kind of oversight? AFAICT, Android as the
same level of information about intent dispatch that RPH does.

> RPH uses onmessage to handle all responses. This is a big one for me. If I
> fire three intents, intent:share and intent:save and intent:pick how do we
> know which launched intent is sending the data back to the me?

There's one line of code that you need to use at the top of your
handler whenever you're using the postMesage API in the browser,
independent of intents.

var service = window.open('web+share:http://example.com/');


window.addEventListener('message', function (msg) {

if (service !=== msg.source) { return; } // This is the magic line.
}, false);

>  "onmessage"
> tells us the window that sent it but not what the action was,

Ah, but the intent was opened in a unique window.

> the RPH
> "string" is not part what is discoverable - and if it was it still doesn't
> solve the problem, if I start two "shares" and they could
> take arbitrarily long to complete (or fail) we don't have a way of directly
> knowing which response response is for a given invocation.  If I don't know
> this I am not in a great position - we would have to have an API/protocol
> layer on top of RPH that defines message formats and how you should interop
> with the service.

Everything you wrote above is taken care of by that one line of
example code. That line of code is also one that anyone using
postMessage already needs to be familiar with.

If you want to make the window.postMessage API more like the
MessagePort.postMessage API (where this check isn't needed), I applaud
you and point you in the direction of the HTML5 WG. Inventing a new
messaging API just for the Web Intents use-cases isn't the way to
build a robust web platform.

> What if a newly created context closes?  Do we ever know it didn't complete?
> You could say we can use a message port, but requiring a message port to be
> able to process the correct response enters developers in to a nightmare of
> boilerplate code and detecting when to pass the message port to or from the
> newly opened window.

I'm not sure that closing versus staying open and doing nothing is a
useful way to distinguish error cases, but we could look into it.
Personally, I expect the best way for an application to handle these
errors is to enable the user to re-launch an intent if they don't like
what's happening. The client application then abandons any work is was
planning to do in response to the previous intent and starts up the
new intent. I think that fits the likely user behavior and also covers
a wider swath of possible error behavior by the service.

> Boiler plate, every "onmessage" you have to check if it is from a known
> source, if it is not then it is possibly from some RPH request (partly tied
> to the code above) or possibly some other frame that could be sending it
> messages.  Seems like a nightmare code maintenance issue.

Let's try to stay dispassionate about this.

> Parsing window.location.hash or what-ever:  Developers hate parsing query
> string data inside their apps.

The intent data is sitting inside window.intent.

> When you look at the UX of the RPH selection and the Web Intents service
> selection, will there be a big difference?  It is hard to tell at this
> stage, a user will have a task they need to perform on some data and will
> ask for an app that can handle it and they will be given a list.

If it's hard to tell at this stage, we should push on the existing API
until it breaks.

> WI will be
> able to detect success or failure of an action so we could provide a
> re-selection prompt to the user.

How long does it wait before deciding that the service will never
invoke postResult?

> We believe we can make the UX for picking the services clear and intuitive
> to users so that they clearly understand what is happening and so that it
> feels natural.  At the same time Developer Experience of the physical API
> will play a huge part in the developer adoption of this API:

AFAICT, RPH enables the same UX possibilities as WI.

So, your following comments get a little ranty. Please forgive a
little humor in my responses.

> If developers have to think about 3 different ways to encode and transport
> data we will lose them;

Huh, so URLs and JSON is too hard? Ah well, the Web was nice while it lasted.

> if they have to think of the different ways they might receive the newly
> sent data (window.location or postMessage) then we will lose more;

The intent data is always in window.intent. Some specific intents
might send additional data via postMessage.

I guess XHR also failed because developers need to know both what URL
to post to and what data to put in the post body.

> if they have to think about how many messages they can send on a channel we
> will lose more again;

Most often zero. Sometimes one.

Some requests are a GET and others are POST. We're all gonna die!

> if they can't detect success or failure without a specific wire data format
> protocol then I think we will lose more developers;

Again, I think the best signal is the user got bored or annoyed by
what was happening and so clicked on something else in my app. We can
enable a well-behaved service to provide good error info, but we can't
get reliable error info from a misbehaving service.

> if they have to think hard about how their client app should handle return
> messages (for instance they might have to create a state machine) we will
> lose more developers;

That one line again.

> if they have to attach a new mime-type to their apps to secure their origin
> we will lose more;

No, not to "secure their origin". I think you're really overplaying
the use-case where the service wants to conceal its identity from the
client. We enable that use case. It requires a MIME type on the server
side. Done.

> if the developer has to have the same bolier plate cruft to filter out
> message not intended for the handler, then we will lose more;

Oh, that same line again.

> if the developer can't just copy and paste code to get started in 2 minutes
> then we will lose more developers.

Wow, I've discovered a form of JavaScript that can't be copy pasted.
Quick, to the patent office!

> The more developers we lose, then the less apps that will integrate with
> each other and then it doesn't matter how great we make the service picker.

I'm glad you're concerned about ease for developers. You should be
excited by RPH. On the client-side, we don't need a shim. We don't
even need any code. The web page just includes a link to a web+share:
URL. Done. With Web Intents, you have to host a library and write
JavaScript code. It's an outrageous advantage for RPH. It will spread
like wild fire.

> The WI is a simple API intuitive API that can handle the three core
> scenarios: fire and forget messages; request and response; long lived
> MessageChannel (ok the shim can't yet but that is a side effect of
> supporting browsers that don't support MessageChannel/MessagePort).  The aim
> is to keep the API simple, accessible and open so that developers find it
> easy to build services that can receive data and build services that can ask
> for data.  If we can do that then we will have lots of happy users.
> We have demos of apps showing how apps can be integrated, each with only a
> couple of lines of code.  They should be released shortly, I just have to
> pull the latest code and write some documentation.

I understand you've put some work into WI. Trust me, I feel your pain.
But given where we are, polishing RPH is the best thing to do for the
web platform.

--Tyler

Greg Billock

unread,
Sep 16, 2011, 4:03:44 PM9/16/11
to web-i...@googlegroups.com
Something we haven't talked about in this discussion is whether using window.open predisposes us as much less likely to be handle device interaction types of intent servicing. These aren't a big part of the initial scope, but it makes sense to not wall them off as exceptionally awkward. An RPC-style syntax is pretty clearly compatible with such extra-browser services. window.open is substantially harder to see in that role.

Something that's URL-based but a better model for what's going on would be an XHR-style syntax. But actually re-using the actual XMLHttpRequest object (new XMLHttpRequest().open("GET", "web+share:url")) is pretty unappealing. Sure you could cobble something together with this exact syntax, it's just software. But as with window.open, there's already a particular thing this means, and layering on a new set of semantics doesn't really dodge the specification problem of what those new semantics are, and just complicates the issue of what the underlying syntax is for. I'm not convinced yet that it's easier to do that than to create a more purpose-built platform API, as witness many other examples.


Tyler Close

unread,
Sep 16, 2011, 7:07:25 PM9/16/11
to web-i...@googlegroups.com
Whether a service operates on a local device or one in the cloud, it's
still going to need a user interface, so postMessage between windows
seems like a fine way to exchange data with the client Web page. Using
window.open to open that window therefore seems natural. For example,
perhaps one of the RPH handlers for a web+ scheme is a chrome: URL
that opens a Web page backed by native code that operates on a local
device.

--Tyler

Paul Kinlan

unread,
Sep 20, 2011, 9:25:09 AM9/20/11
to web-i...@googlegroups.com
Hi Tyler,

On the point of the Origin header, I know of no browser that sends it other than for XMLHttpRequests CORS with the exception of WebKit which does it on cross domain POST request. I know the spec says a UA can attach Origin when ever it wants, but according to https://wiki.mozilla.org/Security/Origin Origin is intended to be null for window.open (if it were even implemented), and should be null on actions that could be generated  in an untrusted way. Is the proposal to change the process defined there and get that implemented on all requests initiated by window.open on all browsers - if not it seems that origin would still be * in the majority of cases.  On another point, would we expect origin in the DOM to map on to the spec? If so do you need to change that spec to make it have a *?

It looks like RPH based urls will be able to be set via window.location, iframe src, form or anchor href.  I have concerns that the initiating app will no longer be around, or the channel back to the client will be through a route other than opener causing the developer to have to manage that as well.

RPH can't register support for data-types.  You mentioned earlier that launching RPH could handle dispatch on "URNs where there's both a NID and NSS".  That is on dispatch right?  Where does the service register what it can handle?  If you have any pointers to the group mailing you mentioned, I am interested to read more. My concern is that this is on dispatch and not registration. Additionally, my understanding of the spec is that we can only match exactly against the scheme so we can't have wildcard matches for things like data-types. Another issue, RPH scheme can only contain "LATIN SMALL LETTER A to U+007A LATIN SMALL LETTER Z", so we cant have +'s ;'s etc after web+ nor can we have anything that might describe the data being sent- the naming is only a minor issue web+share+image becomes web+shareimage - but I worry about not being able to even include data filters, and it being a larger than anticipated spec change on RPH.

You mention invoking via RPH can see the result of page load - how? As far as all my tests in recent memory go, we can't see any property directly on the newly opened window object if it is on a different origin.  There is no readyStatus and onload events don't fire.  Is there another way to check?  You can't tell if the service 404ed or 501ed etc, how does the app tell the UA there was an error?  If you know, I want to also include this in the shim.  Or are you saying that the UA should handle this?

To my point about not knowing which window ultimately sent the event - I didn't word it clearly enough or provide examples.  Let me write some examples maybe that will help express the complexity I believe will be added using RPH.  The examples are just the client-side for now.

Multiple Share clicks (RPH):

We can do it with a closure - however we need to expand the logic to remove the handler.  We can't move the  listener out of the loop because we loose the window reference, and if we move that out we can only handle one action at a time unless we try and manage the state.

shareButton.addEventListener("click", function() {
   var service = window.open('web+share:http://example.com/');
   window.addEventListener('message', function (msg) {
     if (service !=== msg.source) { return; }  // This is the magic line. 
     doSomethingAwesome(msg.data); // do we need to deserialize the data, we don't know?
  
     // we only expect one message in return so we need to remove this.
     window.removeEventListener("message", this, false);
   }, false);
});

The same code in Web Intents:
shareButton.addEventListener("click", function() {
   var intent = new Intent("http://webintents.org/share", "text/uri-list", "http://example.com/");
   window.navigator.startActivity(intent), function(data) {
      doSomethingAwesome(data);
   });
});

Sharing some more exotic data (RPH) - an image DataURI using postMessage because it is too big in the URL and window.location.hash:
shareButton.addEventListener("click", function() {
   var service = window.open('web+share'); // not even sure this works - we normally need to add data

   window.addEventListener('message', function (msg) {
     if (service !=== msg.source) { return; }  // This is the magic line.
     if(msg.data == "ready") // let the remote page tell us we are ok to send it data
     {
       msg.source.postMessage(getData(), msg.origin);
     }
     else {
       doSomethingAwesome(msg.data);  
     }
     // we only expect one message in return.
     window.removeEventListener("message", this, false);
   }, false);
});

Sharing some more exotic data (WI):
shareButton.addEventListener("click", function() {
   var intent = new Intent("http://webintents.org/share", "image/png", getData());
   window.navigator.startActivity(intent), function(data) {
       doSomethingAwesome(data);
   });
});

I like the web intent code because it is exactly the same (just changing the type filter) as the url sharing.  We have to have getData - but that is in common in both RPH and WI.

The requirement to track the service and all incoming message is the point of what I am saying is the extra burden on the developer.  The need to understand when and how we can post a complex message to the opened app is key in the RPH - attaching a 1MB data uri to the URL as would be the case in RPH will not work, it can't be sent to the server and it doesn't work offline.  At least in Chrome/WebKit we seem to be able to attach more via location.hash (2MB I am told), but everything needs to string/url encoded.  It is also on the burden of the client app developer to correctly URL Encode all the data for use in the URL and for the service developer to decode it.

WI is all client-side, two offline enabled apps can talk to each other when the user is completely offline.  If a user has registered a service that sends data via RPH through the query parameters on the URL to the services server and they are offline - what happens, it fails.  Therefore to ensure users have a consistent experience we at the very least need to make sure all data for offline enabled apps is passed via the #, but that again is size limited and causes issues when the developers are already using onhashchange to manage their applications.  If it is available on window.intent (as per your suggestion, not the same as the intent object on WI), that helps, there is still all the string parsing that is required, removing the protocol (data-type if specified) and then decoding all the data that was passed, this is a lot of the same work developers will have to do every time they build an app.

To get rid of the removeEventListener in every message handler we would need to remove the closure code but we need to track windows and intents and it becomes significantly more complex to manage. In fact, I haven't successfully done it yet, we don't have the ability to map the RPH string to a valid URL (because we can't see the URL - only the origin on postMessage).

var services = [];

shareButton.addEventListener("click", function() {
   var intent = 'web+share:http://example.com/'; // Imagine this changes - didn't want to hook up the getElementById
   var service = window.open(intent);
   services.push({ source: service, intent: intent }); // keep track of the window and the intent
});

window.addEventListener('message', function (msg) {
  // determine which.
  for(var service in services) {
    if (service.source !=== msg.source) { return; }
  }

  for(var service in services) {
    if (service.source == msg.source) { 
       // we could look at the origin, but this has the problem with mapping clicks on the same action and values.
       if(service.intent  == ### TODO, work out which intent ###)
         doSomethingCool(msg.data);
       }
       services.splice(service, 1);
       break;
    }
  }
}, false);

Without playing on it longer, my initial thoughts are that most of the client apps will have to use the closure way of registering for callbacks and will therefore have to provide the filter and the handler removal.  If you have a solution it should be documented.  I don't think we will ever see the window.intent you mentioned on msg.source.

I also played around with the idea of a chatty interface, my concerns are: 1) we have two ways of communicating, one over the existing channel (the window and opener) and one over MessagePorts, how is an app or service supposed to tell which it needs to use? and 2) we have to wait to hear from the remote app that it is ready to be able to be sent a MessagePort.

Example of Simple Chatty app using window.postMessage with RPH:
chattyButton.addEventListener("click", function() {
   var service = window.open('web+chatty');

   window.addEventListener('message', function (msg) {
     if (service !=== msg.source) { return; }  // This is the magic line.
     if(msg.data == "ready") // let the remote page tell us we are ok to send it data
     {
       msg.source.postMessage(getData(), msg.origin);
     }
     else if(msg.data == "command1"){
       try {
         doSomethingAwesome(msg.data);
         msg.source.postMessage(getData(), msg.origin);
       }
       catch(e) {}
     }
     else if(msg.data == "command2") {
        ...
     }
     else if(msg.data == "close") {
       // we are finished
       window.removeEventListener("message", this);
     }
   }, false);
});

Example of Simple Chatty app using MessageChannel with RPH:
chattyButton.addEventListener("click", function() {
   var service = window.open('web+chatty');
   var channel = new MessageChannel();
   // We need to deliver the message port so wait for the app to tell us it is ready.
   window.addEventListener('message', function (msg) {
     if (service !=== msg.source) { return; }
     msg.source.postMessage(getData(), [channel.port2], msg.origin);
     window.removeEventListener("message", this);
   }, false);
   
   // handle rest of the chatty api.
  channel.port1.onmessage =  function (event) {
    if(event.data == "command1"){
       try {
         doSomethingAwesome(event.data);
         event.source.postMessage(getData());
       }
       catch(e) {}
     }
     else if(msg.data == "command2") {
        ...
     }
  }
});

The Web Intents code:
chattyButton.addEventListener("click", function() {
   var channel = new MessageChannel();
   window.navigator.startActivity(new Intent("http://chattyintent.com/", "*", channel.port2));
   
   // handle rest of the chatty api.
   channel.port1.onmessage =  function (event) {
    if(event.data == "command1"){
       try {
         doSomethingAwesome(event.data);
         event.source.postMessage(getData());
       }
       catch(e) {}
     }
     else if(msg.data == "command2") {
        ...
     }
   }
});

Once you get on to the channel, the code is the same, but in WI there is a lot less work needed to establish that channel.  WI is constraining the communication over one type of channel so there is no confusion about the channels a chatty interface should operate across.

P

Tyler Close

unread,
Sep 20, 2011, 3:00:19 PM9/20/11
to web-i...@googlegroups.com
On Tue, Sep 20, 2011 at 6:25 AM, Paul Kinlan <paulk...@google.com> wrote:
> Hi Tyler,
> On the point of the Origin header, I know of no browser that sends it other
> than for XMLHttpRequests CORS with the exception of WebKit which does it on
> cross domain POST request.

The Mozilla wiki page you link to in the next sentence claims that
Firefox also sends Origin in several non-XHR cases.

> I know the spec says a UA can attach Origin when
> ever it wants, but according
> to https://wiki.mozilla.org/Security/Origin Origin is intended to be null
> for window.open (if it were even implemented), and should be null on actions
> that could be generated  in an untrusted way. Is the proposal to change the
> process defined there and get that implemented on all requests initiated by
> window.open on all browsers - if not it seems that origin would still be *
> in the majority of cases.

For window.opener.postMessage() to be secure, the caller needs to know
the opener's origin. If there is resistance to always including the
origin for window.open() calls, then we could simply move the origin
to window.intent.origin, putting the intent URL at window.intent.url.
All we need are the two string constants: origin and intent. We can
put them wherever the consensus dictates.

>  On another point, would we expect origin in the
> DOM to map on to the spec? If so do you need to change that spec to make it
> have a *?

Are you referring to the distinction between null and '*'? I think
leaving that as is, is best. We probably want things to break if
somehow we don't have an origin value to secure the response data. A
correct UA should be providing an intent origin value.

> It looks like RPH based urls will be able to be set via window.location,
> iframe src, form or anchor href.  I have concerns that the initiating app
> will no longer be around, or the channel back to the client will be through
> a route other than opener causing the developer to have to manage that as
> well.

If the client is no longer around, it is because it fired the intent
in a way that ensured it would not still be around and so is not
interested in the response. That seems like a fine choice for some
scenarios.

An intent handler would have to switch between window.opener and
window.parent if it wanted to be usable as both a top-level window and
as an inline widget. The intent handler would likely want to also
present a different UI in each of these dispositions, so likely needs
the switch regardless.

> RPH can't register support for data-types.

RCH (registerContentHandler) can. Perhaps some of the use cases you
are thinking of are better done using RCH instead of RPH.

>  You mentioned earlier that
> launching RPH could handle dispatch on "URNs where there's both a NID and
> NSS".  That is on dispatch right?  Where does the service register what it
> can handle? If you have any pointers to the group mailing you mentioned, I
> am interested to read more.   My concern is that this is on dispatch and not
> registration.

RPH as is, only dispatches on the URL scheme. I read some blog
comments where people were asking for the ability to dispatch on more
parts of the URL, such as:

http://deletethis.net/dave/?q=registerprotocolhandler

So if we come across a use case that cannot be implemented using only
the scheme, we could try to raise that issue again.

> Additionally, my understanding of the spec is that we can only
> match exactly against the scheme so we can't have wildcard matches for
> things like data-types. Another issue, RPH scheme can only contain "LATIN
> SMALL LETTER A to U+007A LATIN SMALL LETTER Z", so we cant have +'s ;'s etc
> after web+ nor can we have anything that might describe the data being sent-
> the naming is only a minor issue web+share+image becomes web+shareimage -
> but I worry about not being able to even include data filters, and it being
> a larger than anticipated spec change on RPH.

I suspect we can handle the WI use-cases while staying within the RPH
spec and so limit our ask to the HTML WG to only the two string
constants.

> You mention invoking via RPH can see the result of page load - how? As far
> as all my tests in recent memory go, we can't see any property directly on
> the newly opened window object if it is on a different origin.  There is no
> readyStatus and onload events don't fire.  Is there another way to check?
>  You can't tell if the service 404ed or 501ed etc, how does the app tell the
> UA there was an error?  If you know, I want to also include this in the
> shim.  Or are you saying that the UA should handle this?

I was referring to the browser implementation in that passage. When
using window.open, I don't think a shim could detect page load
failure.

I still think the most reliable detection of a misbehaving intent
handler will be a user click in the client application. But the RPH
API gives us the opportunity to try to do more in the native
implementation.

> To my point about not knowing which window ultimately sent the event - I
> didn't word it clearly enough or provide examples.  Let me write some
> examples maybe that will help express the complexity I believe will be added
> using RPH.  The examples are just the client-side for now.
> Multiple Share clicks (RPH):
> We can do it with a closure - however we need to expand the logic to remove
> the handler.

It's not deadly if the handler is never removed.

>  We can't move the  listener out of the loop because we loose
> the window reference, and if we move that out we can only handle one action
> at a time unless we try and manage the state.
> shareButton.addEventListener("click", function() {
>    var service = window.open('web+share:http://example.com/');
>    window.addEventListener('message', function (msg) {
>      if (service !=== msg.source) { return; }  // This is the magic line.
>      doSomethingAwesome(msg.data); // do we need to deserialize the data, we
> don't know?

According to the HTML5 spec, the structured clone algorithm is
supposed to be used here. I believe that's not widely implemented yet
though. It's still probably on a faster deployment timeline than
postResult is.

>      // we only expect one message in return so we need to remove this.
>      window.removeEventListener("message", this, false);
>    }, false);
> });
> The same code in Web Intents:
> shareButton.addEventListener("click", function() {
>    var intent = new Intent("http://webintents.org/share", "text/uri-list",
> "http://example.com/");
>    window.navigator.startActivity(intent), function(data) {
>       doSomethingAwesome(data);
>    });
> });

So, as is, we've got 8 lines for RPH and 6 lines for WI. The
removeEventListener() call is optional, so that's 7 to 6. So the
advantage of standardizing a new API is a savings of one line. That
doesn't seem good enough to me to justify the fragmentation of the
API.

You've also not taken into account one of the more likely scenarios.
Today, sites that embed the AddThis widget don't do their own
accounting of share clicks. They offload that task to the share
handler. So the client page doesn't actually need to get a response.
So for the typical site, the RPH code is:

<a href="web+share:http://example.com/" target="_blank">share me</a>

That's one line of standards compliant HTML markup versus 6 lines of
JavaScript code that requires a shim library and a new standard. Note
that we can also crawl for intent invocation call sites with this
syntax, whereas the WI code obscures intent invocation call sites from
a crawler.

> Sharing some more exotic data (RPH) - an image DataURI using postMessage
> because it is too big in the URL and window.location.hash:
> shareButton.addEventListener("click", function() {
>    var service = window.open('web+share'); // not even sure this works - we
> normally need to add data
>    window.addEventListener('message', function (msg) {
>      if (service !=== msg.source) { return; }  // This is the magic line.
>      if(msg.data == "ready") // let the remote page tell us we are ok to
> send it data
>      {
>        msg.source.postMessage(getData(), msg.origin);
>      }
>      else {
>        doSomethingAwesome(msg.data);
>      }
>      // we only expect one message in return.
>      window.removeEventListener("message", this, false);
>    }, false);
> });
> Sharing some more exotic data (WI):
> shareButton.addEventListener("click", function() {
>    var intent = new Intent("http://webintents.org/share",
> "image/png", getData());
>    window.navigator.startActivity(intent), function(data) {
>        doSomethingAwesome(data);
>    });
> });

I wonder if RCH might be the way to do this:

var service = window.open('data:image/png;base64,asdfasdfasdgf...');


window.addEventListener('message', function (msg) {

if (service !== msg.source) { return; }
doSomethingAwesome(msg.data);
}, false);

> I like the web intent code because it is exactly the same (just changing the
> type filter) as the url sharing.  We have to have getData - but that is in
> common in both RPH and WI.

What are your thoughts on the RCH code?

> The requirement to track the service and all incoming message is the point
> of what I am saying is the extra burden on the developer.

It is still just one line of code (or two if you really want to call
removeEventListener).

>  The need to
> understand when and how we can post a complex message to the opened app is
> key in the RPH - attaching a 1MB data uri to the URL as would be the case in
> RPH will not work, it can't be sent to the server and it doesn't work
> offline.  At least in Chrome/WebKit we seem to be able to attach more via
> location.hash (2MB I am told),

So attaching 1MB would work in Chrome.

Regardless, using RCH or RPH + postMessage would work.

> but everything needs to string/url encoded.
>  It is also on the burden of the client app developer to correctly URL
> Encode all the data for use in the URL and for the service developer to
> decode it.

With RCH you might be able to use the browser cache to pass the data.
With postMessage, you've got structured clone, probably on a better
timeline than postResult.

> WI is all client-side, two offline enabled apps can talk to each other when
> the user is completely offline.

Both RCH and RPH work offline.

>  If a user has registered a service that
> sends data via RPH through the query parameters on the URL to the services
> server and they are offline - what happens, it fails.  Therefore to ensure
> users have a consistent experience we at the very least need to make sure
> all data for offline enabled apps is passed via the #, but that again is
> size limited

RCH or postMessage again.

> and causes issues when the developers are already using
> onhashchange to manage their applications.  If it is available on
> window.intent (as per your suggestion, not the same as the intent object on
> WI), that helps, there is still all the string parsing that is required,
> removing the protocol (data-type if specified) and then decoding all the
> data that was passed, this is a lot of the same work developers will have to
> do every time they build an app.

Consequently, developers will prefer to pass complex metadata using
postMessage. The intent URI will only be used to transmit data that it
makes sense to put in an <a> tag.

> To get rid of the removeEventListener in every message handler we would need
> to remove the closure code but we need to track windows and intents and it
> becomes significantly more complex to manage.

I think you're tying a knot here. I doubt there's a significant
performance penalty to not calling removeEventListener, so it's not
worth these contortions. If you have a page that fires lots of
intents, then making a little helper function to call
removeEventListener makes more sense. For example,

function onReturn(service, callback) {
window.addEventListener('message', function listener(msg) {
if (service !== msg.source) { return; }
callback(msg.data);
window.removeEventListener('message', listener, false);
}, false);
}

shareButton.addEventListener('click, function () {
onReturn(window.open('web+share:http://example.com/'), doSomethingCool);
});

This is the sort of thing we can safely leave to app and library
developers. This isn't a good enough justification for forking the
existing RPH API.

> I also played around with the idea of a chatty interface, my concerns are:
> 1) we have two ways of communicating, one over the existing channel (the
> window and opener) and one over MessagePorts, how is an app or service
> supposed to tell which it needs to use?

Use the window and opener.

Does WI really work that way? A MessagePort is not compatible with
structured clone.

>
>    // handle rest of the chatty api.
>    channel.port1.onmessage =  function (event) {
>     if(event.data == "command1"){
>        try {
>          doSomethingAwesome(event.data);
>          event.source.postMessage(getData());
>        }
>        catch(e) {}
>      }
>      else if(msg.data == "command2") {
>         ...
>      }
>    }
> });
> Once you get on to the channel, the code is the same, but in WI there is a
> lot less work needed to establish that channel.  WI is constraining the
> communication over one type of channel so there is no confusion about the
> channels a chatty interface should operate across.

So you left out the call to MessagePort.close() which is similar in
purpose to window.removeEventListener. Once you put that back in, the
code looks really similar. In RPH + postMessage, you need the
msg.origin argument on all the postMessage calls and you need the one
magic line at the top of the listener. Other than that, the code is
identical. The line count actually ends up exactly the same, since in
RPH + postMessage, the client doesn't have to construct a
MessageChannel.

--Tyler

Reply all
Reply to author
Forward
0 new messages