W3C home > Mailing lists > Public > public-device-apis@w3.org > June 2010

Re: API patterns and requirements

From: Rich Tibbett <rich.tibbett@gmail.com>
Date: Fri, 18 Jun 2010 13:40:08 +0100
Message-ID: <AANLkTin4vtGC8ke-6btJTFqqnMjBxV8xTwuYeOveaNAm@mail.gmail.com>
To: Wojciech Masłowski <wmaslowski@opera.com>
Cc: public-device-apis@w3.org
2010/6/18 Wojciech Masłowski <wmaslowski@opera.com>

>  W dniu 2010-06-17 16:23, Rich Tibbett pisze:
> I've been thinking about the general interface patterns that we are using
> in the some of the APIs, particularly with a focus on Contacts and
> System-Info.
>  On the one hand there is a requirement that API calls be asynchronous. On
> the other hand, in order to ensure a reasonable user experience (i.e. don't
> bombard the user with more than one permission request at a time) I think we
> should include a requirement for serial access to each API (or collectively,
> all APIs) - that no more than one API call should be executable
> concurrently. I'd like to explore if this is a reasonable assumption for
> e.g. Contacts and whether any changes to the pattern used may be required
> for this.
> *
> *
> *[original code snipped]*

> **
> I don't really think that mandating that only one call is going to help
> with a problem of annoying user with security requests in any way.

Security requests may be unavoidable where we don't have any pre-defined
trust relationships. This proposal does not remove the need for security
requests but only ensures that a web app cannot bombard the user with those
security requests.

> Consider the following use case: web app wants to get power and network
> info. With your suggested solution it would look like that.
> navigator.system.request.onsuccess = function() {
>     doSomethingWithBatteries(navigator.system.request.result);
>     navigator.system.request.onsuccess = function() {
>         doSomethingWithNetworks(navigator.system.request.result);
>      };
>     navigator.system.get('Network'); // triggers 2nd permission request
>  };
> navigator.system.request.onerror = function() {
>     // even if we don't get access to Power we want to try to get Network
> info
>     navigator.system.request.onsuccess = function() {
>         doSomethingWithNetworks(navigator.system.request.result);
>      };
>     navigator.system.get('Network'); // triggers 2nd permission request
>  };
>  navigator.system.get('Power'); // triggers 1st permission request
> If we allow concurrent request the code looks like this
> navigator.system.get('Power', doSomethingWithBatteries ); // triggers 1st
> permission request
> navigator.system.get('Network' doSomethingWithNetworks); // triggers 2nd
> permission request
> In both examples the user will be asked for permission twice. The first one
> is much more complicated.

It looks a little more complex but the application is presenting a clearer
interaction flow in the first example than in the second. Developers
actually have to design their web application from a user interaction
perspective in the first snippet: each nested API call probably requires a
subsequent security request and the pattern requires the developer to plan
that appropriately (and limit the number of permission requests being
called). So I actually still prefer the first example. The second example
could also generate race conditions if we're not careful (e.g. if the web
app requires that 'Power' completes before examining 'Network' but 'Network'
returns first).

Using the second example, if a web application executes 1000 API calls up
front would the user will be presented with 1000 security dialogs? The
proposal would mitigate such malicious usage of Device APIs.

> Additionally with your solution we have to specify what happens in this
> case :
> navigator.system.request.onsuccess = fun1
> navigator.system.get('Network');
> navigator.system.request.onsuccess = fun2
> will fun1 be called or fun2?
fun2 would be called. Just like any other ECMAScript
variable, navigator.system.request.onsuccess has been overwritten with a new
value in the snippet above.

> This pattern provides two additional benefits over the current APIs:
>  1. only one async method (e.g. in the Contacts API this includes find(),
> save() and remove()) can be requested at any one time (i.e. serial access
> only).
> I don't see how mandating only one async call gives advantage over
> possibility of many concurrent calls. In both cases developer will spam user
> with permission requests if he requests data too often.

I see the following advantages of serializing access to API calls.

- it throttles the user interaction (e.g. security/permissions opt-in)
required with the app. A malicious app cannot send 10000 requests to a
Device API.
- Developers are required to plan their applications intelligently around a
clear Device API access flow.
- Race conditions are removed (e.g. performing a 'save contact process'
while performing a 'find contacts process' could result in such a race
condition and inconsistent responses).
- User interaction is less confusing - only one permission request at a time
for the user to authorize.

...FWIW, I do question the SysInfo API model: if a user is required to
authorize each SysInfo API call seperately it would probably make more sense
for a web app to be able to request a bunch of System Information in a
single API call (and hence a single permission request). The current SysInfo
API does not have the ability to provide that yet :-(

- Richard

[1] http://www.w3.org/TR/IndexedDB/
>  [2] http://dev.w3.org/html5/spec/Overview.html#file-upload-state
>  [3] http://dev.w3.org/2009/dap/contacts/contacts_picker.png
Received on Friday, 18 June 2010 12:41:02 UTC

This archive was generated by hypermail 2.3.1 : Monday, 23 October 2017 14:53:44 UTC