Feature Permissions Playground


Related discussion on Capabilities container at mozilla-labs.

Doug Turner is also pondering how to do Device API permission management. Added a Capability-based Security inspired proposal.

Initial version of the demo.

This demo implements the Permissions interface with some changes. The demo should work with any modern browser. Click Run buttons in Examples to experiment. Contacts, Calendar and System Information are used as placeholders only, and may not be applicable for this model.

This document is merely a W3C-internal document. It has no official standing of any kind and does not represent consensus of the W3C Membership. Feel free to join the discussion on public-device-apis.

log() Output






Changes to Feature Permissions Interface

Option A: Each Device API implements Permissions (this demo)

E.g. FoobarSensor implements Permissions, where FoobarSensor is any applicable Device API:

interface FoobarSensor : Permissions {
// ...

Each interface that implements Permissions has a unique feature id.

console.log(navigator.foobar.feature); // returns "foobar"

requestPermission() can drop its first feature argument. If requestPermission() is invoked with undefined arguments the user interaction (such as displaying an infobar) is deferred until requestPermission() is invoked with a non-null callback (similar to the proxy design pattern):

navigator.foobar.requestPermission(); // returns nothing

If the callback is non-null in requestPermission(callback), a user interface is shown to the user from where the user is able to change feature permission settings or dismiss the UI. The UI includes all feature requests, including those deferred (callback is undefined) in the browsing context. The callback is invoked only after user's explicit consent is received. If the user chooses to dismiss the UI the callback is not invoked. For example, to ask for foobar and baz feature permissions:

navigator.baz.requestPermission(function(response) { console.log(response); });

The callback response returned is an object. The property names of the response object map to feature identifiers, the property values to feature's properties such as permission_level. System default permission levels are used, if the user does not explicitly set the permission permission level. For example, if the user allows access to foobar feature but leaves the baz feature permission level to default the following response is returned:

  'foobar': {'permission_level': 2}, // USER_ALLOWED
  'baz': {'permission_level': -1}    // DEFAULT_DENIED

If feature parameter passed to permissionLevel(feature) getter is undefined (i.e. not defined), the permission level of the interface that implements Permissions is returned:

navigator.foobar.permissionLevel(); // returns foobar's permission_level, e.g. 2 for USER_ALLOWED

Option B: Capability-based Security-ish Way

The API objects are exposed only if the user has given permission. The objects are passed by reference to the success callback:

function success(response) {
    // case 1: the API is exposed only if the user has given permission
    if (response.foobar !== 'undefined') {
        response.foobar.doSomething(); // do something with the API

    // case 2: the entry point is known e.g. navigator.baz, an equality comparison works
    if (navigator.baz === response.baz) {

function error(response) {
    // example response:
    // {
    //    'foobar': {'permission_level': -2}, // USER_DENIED
    //    'baz': {'permission_level': -1}    // DEFAULT_DENIED
    // }
    console.log(response.foobar.permission_level); // logs '-2'

// the feature factory
navigator.requestPermissions(['foobar', 'baz'], success, error);

Misc Notes

Misc UI Ideas