Re: Adding Web Intents to the Webapps WG deliverables

On Tue, 20 Sep 2011, Rich Tibbett wrote:
> Ian Hickson wrote:
> > Why not just improve both navigator.registerContentHandler and
> > navigator.registerProtocolHandler?
> 
> http://groups.google.com/group/web-intents/browse_thread/thread/3dff7c2cdf5815b8
> 
> I tend to agree with rolling this in to RCH and RPH and seeing if we 
> could refine the processing algorithms therein to satisfy the security 
> issues highlighted in that thread (i.e. ensuring the cross document 
> messaging channel setup from a window.open with a registered protocol 
> handler is origin bound).

I'm not sure it necessarily makes sense to use registerProtocolHandler() 
itself, but something based on it seems like it would work, rather than 
reinventing the wheel entirely.


On Tue, 20 Sep 2011, Paul Kinlan wrote:
> 
> Q: Why are the verbs URLs?
> 
> Verbs don't have to be URL's but a URL will allow us a point of 
> reference to documentation, versioning and namespacing allowing verbs 
> with similar names but by a different provider to not conflict with each 
> other (thus allowing developers to come up with their own schemes and 
> APIs outside of standardisation).

If they're just arbitrary strings, this should be made clearer.


> Q: Why are some verbs hard-coded into the API?
> 
> Convenience and ensuring there is a consistent use of the first set of 
> intents that cover the most common initial use cases.

If the strings are inconvenient enough that you feel the need to provide a 
constant for them, maybe that's a sign that the strings should be changed!

Rather than 'http://webintents.org/share', why not just 'share' for the 
share intent, for example?


> Q: How are types matched?
> 
> I don't know the best phrase, mime-typedness.  A direct string 
> comparison unless there is a * after the / (image/*) which then means 
> every image.

This needs to be defined much more precisely. e.g. what happens to MIME 
parameters? Does */* match foo/*? What syntax checking is done on the 
inputs here?


> Q: Why not just improve both navigator.registerContentHandler and
> navigator.registerProtocolHandler?
> 
> WI encompasses aspects of both of these API's - but more importantly 
> there are some paradigms we wish to bring that will not fit in to either 
> directly.

I'm not saying to actually use navigator.registerContentHandler and 
navigator.registerProtocolHandler, but why not base something on that API 
rather than reinventing the wheel?


> We want one consistent way of delivering data to applications

Soemthing based on navigator.register*Handler() would give you that. 
Inventing something new wouldn't, since then you'd have two mechanisms 
(the register*Handler() methods, and Web Intents).


> we want it to be a client-side delivery mechanism

If it's going to be entirely client-side, I would recommend using 
MessagePorts, so that the communication isn't just one-post, one-response. 
For example, consider an intent where the provider needs to take the 
submitted data, encrypt it, then hand it back to the original site for a 
signature, then needs to take the result and send it somewhere. With a 
mechanism that just consists of post/response, there's no good way to get 
the data back (you'd have to do it on the server end). If we provide ports 
to communicate back and forth, you wouldn't have a problem.


> and we want applications to be able to tell the action it supports and 
> the data types it can handle.

That doesn't seem hard to do if we just work on an extension to 
register*Handler(). No need for a completely different API.


> Q: How does an already-open page get to handle an action? e.g. say GMail 
> wants to handle the "share" intent, and the user already has GMail open, 
> and the user clicks a "share" button on Flickr. How does the existing 
> GMail instance get the notification?
> 
> If it was a share, we would envisage the UI to open the "compose" email 
> function rather than the full interface. 

Sure, but what if the full interface is already open? Maybe Google+ is a 
better example: you could envisage the "Share" dialog appearing on the 
open Google+ page rather than opening an entirely new page just to share a 
post.

I think this is an important case to support.


> Q: In particular, why are intents registered via a new HTML element 
> rather than an API? How do you unregister? How do you determine if the 
> intent was registered or not? How do you conditionally register (e.g. 
> once the user has paid for the service)?
> 
> External discoverability, indexing and scraping is a very important part 
> of the intent tag understanding the API points of an application is very 
> powerful to external systems - via an API we lose this ability, or at 
> least make it fiendishly hard to discover.

Could you elaborate on this need? What use case does it address?

Adding new elements (especially to <head>) is a high-cost affair and 
should be avoided unless there are really good reasons for it.


> Flexibility for the UA; the UA gets a much richer understanding of the 
> capabilities of an application, allowing it to have more control of how 
> it presents and manages the intents and registration to the user.

Could you elaborate on this? As far as I can tell it doesn't make any 
difference to the UA whether the registrations are declared via markup or 
via an API.


> If it is available as a tag it allows screen-readers or other 
> accessibility tools to be able to indicate that A) and intent might need 
> to be installed, or that B) the application is a handler for something 
> at load time rather than at some point in the applications lifecycle.

So does an API.


> Developer experience is another important reason for the tag: We didn't 
> want the developers to have to think too hard about enabling their apps 
> to receive data; questions developers ask often of an API is "when 
> should I call the code", should it be in onload, before, after? Given 
> our experience working with developers, the more steps or potential 
> questions that are raised in a developers head about implementing 
> functionality, the more likely they are to de-prioritise the work in 
> favor of other work.

I think this dramatically overstates the complexity here. Authors could 
call the API whenever they want; simple guidelines can be trivially given 
in the same amount of room as it takes to tell authors to use a new 
element.


> We considered the cases of the Notifications API, where there is a 
> semi-complex dance of checking for permissions, requesting for 
> permission and then executing the notification - the burden falls on the 
> developer to keep track of whether they think the user has notifications 
> enabled in their app as well as by the UA and the developer just doesn't 
> bother to implement it.

Yes, the notification API is a terrible design IMHO. There is no need for 
permission checks here.


> Unregistering would be handled by the UA's management interface directly 
> by the user.

So how does a site that has stopped providing a feature unregister its 
handler for that feature?


> Conditional registration can be handled on the client or server, it is 
> about the presence of the intent tag - when the tag is in the DOM the UA 
> will pick this up and offer the install prompt (when it determines that 
> it should). This allows you to manage it in a paywall (maybe you have a 
> template that will render the tag in the paywall), or as the result of 
> some client-side action (the developer will add <intent> dynamically to 
> the DOM).

If you are supporting dynamic additions, surely all the points about 
declarative markup that you mentioned earlier are moot.


> Determining if the intent was registered - is that in the context of the 
> app knowing the user clicked "install" to a prompt or for external apps 
> to know that there is a handler? In the case of the former, we haven't 
> got that speced - it could be an event on the elements however my 
> question is: why do you need to know? in the case of the latter we 
> didn't want to offer it as part of the API for the same concerns that 
> vendors have expressed for registerProtocolHandler.

On the contrary, vendors have actively asked for it to be provided for 
registerProtocolHandler(). There was a whole thread about this on the 
WHATWG list recently that may be illuminating.


Here's a possibly simpler proposal:

 - to register:

   navigator.registerIntentHandler(intent, filter, url, kind);
     intent = string like "share", "play"
     filter = MIME type (foo/bar) or MIME wildcard (foo/* or */*)
     url = page to load to handle intent
     kind = a flag indicating if the page should be:
       - always opened in a new tab
       - opened in the intent handler dialog (inline/pop-up)
       - opened in an existing tab if possible, else a new tab

 - to check if registered, to unregister:

   navigator.isIntentHandlerRegistered(intent, filter, url);
   navigator.unregisterIntentandler(intent, filter, url);

 - to invoke intent:

   var port = navigator.handleIntent(intent, filter);
   port.postMessage(data);
   port.onmessage = function (event) { handle(event.data) };

 - to handle an intent:

   body.onintent = function (event) {
     // Check event.origin if you want to be origin-limited.
     // We could add event.intent and event.filter, for processors that
     // support many intents.
     var port = event.ports[0];
     var response = process(event.data);
     port.postMessage(response);
   };

In simple cases, the above can be even further simplified. For example, if 
you don't care about the response (e.g. for a share intent), and you don't 
have a filter type (so it'll only match */* filters):

   navigator.handleIntent('share').postMessage(data);

Similarly, handling an intent can be even easier than the above for simple 
cases. For example, in the share case again, where you don't send anything 
back but just share whatever is passed in:

   <body onintent="share(event.data)">

-- 
Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'

Received on Tuesday, 20 September 2011 22:37:06 UTC