[whatwg] register*Handler and Web Intents

Rick Waldron waldron.rick at gmail.com
Thu Aug 2 12:39:58 PDT 2012


On Wed, Jul 25, 2012 at 10:20 PM, Ian Hickson <ian at hixie.ch> wrote:

>
> Having carefully studied the Mozilla Web Activities proposal, the Web
> Intents draft, the register*Handler APIs, and to a lesser extent the
> dispatch mechanisms in existing operating systems (desktop and mobile) and
> the piles of advocacy on teh subject on the Web, I've tried to come up
> with a concrete proposal for merging all of them into a coherent whole
> that addresses the limited use cases that are of most interest.
>
> Overall, this proposal mainly draws from the following sources:
>
>  - For the handling mechanimsm, it's basically directly based on the
>    Mozilla "System Message Handler" mechanism.
>
>  - For the dispatch mechanism, it is based mainly on the Web Intents
>    draft.
>
>  - For the registration mechanism, it's based on extending the
>    register*Handler APIs consistently.
>
> However, I have attempted to simplify the proposal from its sources of
> inspiration, where that seemed possibly without sacrificing key use cases.
>
> The overall design is that there are URLs that can handle particular
> messages, herein called intents (mostly because that's what Web developers
> seem to have adopted as the term already).
>
> These "intents" are indications that the user, or the system on behalf of
> the user, wants the application to do something or other.
>
>    For example: "please open this PDF", "please share these four images",
>    "please be aware that it is now the time you asked to be awoken at",
>    "please allow the user to compose an e-mail to this address".
>
> We want pages to be able to handle intents promptly upon being opened.
> This puts certain constraints on the design that are explained in detail
> in the Mozilla "System Intents" thread:
>
>
> https://groups.google.com/forum/?fromgroups#!topic/mozilla.dev.webapi/o8bkwx0EtmM
>
> This leads therefore to the first part of the concrete proposal:
>
>   partial interface Window {
>     void setIntentHandler(DOMString action, IntentCallback callback);
>

"set" generally implies only one value for a given key - is this the case?
Or is this more like "add"—where I can add an arbitrary number of handlers
to for any given "action".



>     boolean hasPendingIntent(DOMString action);
>   }
>
>   callback IntentCallback = void (Intent intent);
>

Is there any way this can be re-thought that avoids adding more API to the
global object? What about using "Intent" as the global namespace object and
hanging the Intent API there. The Intent object below would need to be
renamed—why not "Intention", it works nicely in discussion/explanation as
well: "Intent handlers receive an Intention object as the sole argument
when the UA asynchronously calls the handler..."


>
> When a page is loaded, it registers its intent handler callback using
> setIntentHandler(), and as soon as that happens, the UA asynchronously
> calls the handler.
>
> The Intent object itself "just" needs to describe what the page is being
> asked to do. For this, I borrowed freely from all the proposals mentioned
> above, and ended up with:
>
>   interface Intent {
>

See "Intention" above...


    readonly attribute DOMString action,
>

Inclusion of an "action" property supports the "arbitrary number of
handlers" case (as well as the "single delegation handler" case.


>     readonly attribute DOMString type,
>

What piece of information is this?


>     readonly attribute any data,
>     void success(any data, optional sequence<Transferable> transfer);
>     void failure(DOMString message);
>

Where do I define success and failure?


>   }
>
> This is basically the data that needs to be sent from the application that
> wants to initiate an intent, too:
>
>   dictionary IntentSettings {
>     DOMString action,
>     DOMString type,
>

What piece of information is this?


>     any data, // structured-cloned
>     sequence<Transferable> transfer,
>   };
>
> So how do we start an intent? Well, for intent handlers that are just
> registered to handle URLs being loaded using certain schemes or that have
> certain MIME types, you just use a link:
>
>   <a href="web+customscheme:foo">...</a>
>   <a href="file.customtype">...</a>
>
> But more interestingly, to start one programmatically you would use a
> startIntent() method:
>
>   partial interface Window {
>     void startIntent(IntentSettings intent,
>

Again, I hope you consider not making this a method of the global object.
(proposal below)

                     optional AnyCallback success,
>                      optional DOMStringCallback failure);
>

I'm guessing this where the previously questioned success and failure are
defined?

What is a "DOMStringCallback"



>   }
>
>   callback AnyCallback = void (any data);
>   callback DOMStringCallback = void (DOMString message);
>
> The callbacks given in the method, if provided, are invoked asynchronously
> in reaction to the handler calling success() or failure() on the Intent
> object. We would just allow one success or failure message per Intent,
> for sanity's sake.
>


All of my notes above summarized would look like this...


Intent is a property of the global object (ie. window)


interface Intent {

  void addHandler(DOMString type, IntentionCallback callback);

  boolean hasPending(DOMString type);

  void request(IntentionSettings intention,
                   optional AnyCallback success,
                   optional DOMStringCallback failure);
}

("request" is just a suggestion, as "start" indicates something that should
also have a means to "stop")

callback IntentionCallback = void (Intention intention);


interface Intention {
  readonly attribute DOMString type,
  readonly attribute any data,
  void success(any data, optional sequence<Transferable> transfer);
  void failure(DOMString message);
}


dictionary IntentionSettings {
  DOMString type,
  any data, // structured-cloned
  sequence<Transferable> transfer,
};

callback AnyCallback = void (any data);
callback DOMStringCallback = void (DOMString message);


Forgive me, I don't speak "Web IDL", so this is at best an approximation of
my thoughts in expressed in something similar to what was originally
proposed.

Somethings remain exactly the same, eg. the callback definitions.



>
> There is another way of starting an intent that I alluded to earlier: the
> system can decide to dispatch one to a specific application. For example,
> say an application has told the system (using some other API) that it
> wants to be woken up at 07:00 to start playing a song (the user's alarm).
> The system could dispatch an intent to the application using the mechanism
> described above -- a system intent. To distinguish these from intents sent
> by applications like "airplay media", "share picture", or "open mailto:",
> one would use intent names prefixed by the string "system-", for example,
> "system-alarm" or "system-nfc". The startIntent() method described above
> therefore would, in this proposal, fail if the intent name started with
> the substring "system-".
>
> All of this leads to the final piece of the puzzle, namely how to offer to
> the user the ability to use a page as an intent handler. This is where the
> existing register*Handler() methods come in. Taking a cue from Mozilla's
> Web Activities proposal, I propose that we just use introduce methods for
> the more generic "intents" system:
>
>   partial interface Navigator {
>     void registerProtocolHandler(DOMString scheme,
>       DOMString url, DOMString title, optional HandlerDisposition
> disposition);
>     void registerContentHandler(DOMString mimeType,
>       DOMString url, DOMString title, optional HandlerDisposition
> disposition);
>     void registerIntentHandler(DOMString action, DOMString? mimeType,
>       DOMString url, DOMString title, optional HandlerDisposition
> disposition);
>     DOMString isProtocolHandlerRegistered(DOMString scheme, DOMString url);
>     DOMString isContentHandlerRegistered(DOMString mimeType, DOMString
> url);
>     DOMString isIntentHandlerRegistered(DOMString action, DOMString?
> mimeType, DOMString url);
>     void unregisterProtocolHandler(DOMString scheme, DOMString url);
>     void unregisterContentHandler(DOMString mimeType, DOMString url);
>     void unregisterIntentHandler(DOMString action, DOMString? mimeType,
> DOMString url);
>   }
>
>
Similar to my concerns above, perhaps this would be better organized within
a property of the Navigator object instead of hanging all new API directly
on the object.

navigator.handlers {
  intent { registerHandler, isHandler, unregisterHandler }
  content { registerHandler, isHandler, unregisterHandler }
  protocol { registerHandler, isHandler, unregisterHandler }
}


Even this seems too repetitive—I'm sure there is an even better way to lay
out the API.



>   enum HandlerDisposition {
>      "replace", // means that you use the browsing context of the page
>      // that invoked the intent, just like clicking a link normally
>      "new", // means you must open a new top-level browsing context
>      // (window, tab) to handle the intent
>      "overlay", // means you must open an auxiliary browsing context
>      // (popup dialog, sidebar) to handle the intent;
>      "reuse", // means the same as "new" unless the page is already open,
>      // in which case it just switches focus to that one and sends a new
> message
>   };
>
> A strong argument has been made, however, that we should offer a
> declarative way of registering these: it would dramatically help with
> discovery (e.g. by allowing Web applications to be indexed by search
> engines). Thus, I propose a parallel mechanism in the form of an empty
> element that goes in the <head>:
>
>   <intent
>     action="edit"     intent action, e.g. open or edit, default "share"
>     type="image/png"  MIME type filter, default omitted, required if
> scheme omitted
>     scheme="mailto"   Scheme filter, default omitted, required if type
> omitted
>     href=""           Handler URL, default "" (current page)
>     title="Foo"       Handler user-visible name, required attribute
>     disposition=""    HandlerDisposition values, default "overlay"
>   >
>

Some folks seem to oppose you on this, I actually completely agree. There
is no reason to continue to overload "link" and "meta" with more _stuff_
(in the same way I argue against dumping new _stuff_ on window and
navigator)



>
> I welcome feedback on this concrete, though only briefly described,
> proposal.
>



Rick



More information about the whatwg mailing list