Runtime and Security Model for Web Applications

W3C Editor's Draft

This version:
http://www.w3.org/2012/sysapps/runtime/
Latest published version:
https://www.w3.org/TR/runtime/
Latest editor's draft:
http://www.w3.org/2012/sysapps/runtime/
Editors:
Mounir Lamouri (Mozilla)
金明 (Ming Jin) (Samsung Electronics, Co., Ltd)

Abstract

This document specifies two classes of Web application: hosted Web applications and packaged applications. These applications differ from traditional Web applications in their life cycle, security model, and access to APIs that are not normally available to Web applications. Conceptually, the application manifest indicates that an application can be "installed" on an end-user's device. What distinguishes a traditional Web application from a hosted web application is an application manifest: this is a JSON resource that contains application specific metadata (e.g., the name of the application), and optionally various security related permission requests to resources on the Web and/or services and capabilities on the device.

Figure 1 The figure shows the overlap between traditional web applications, hosted web applications, and packaged applications. Web applications make use of standard Web technologies but don't make use of an application manifest. On the other hand, hosted applications make use of an application manifest, while packaged applications have both an application manifest and are packaged using [ZIP].

Installation of hosted or packaged applications onto a device can be initiated through either linking to an application manifest or through the use of the ApplicationRegistry API. This API gives a developer a degree of control over the installation process.

This specification also specifies aspects related to the application's lifecycle that are outside the control of the developer. These events sometimes result in system messages being generated. Developers can register event listeners to listen for these special events during the life cycle of their application.

Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

The key words MAY, MUST, MUST NOT, RECOMMENDED, SHOULD, and SHOULD NOT in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

There is only one class of product that can claim conformance to this specification: a user agent.

The IDL fragments in this specification must be interpreted as required for conforming IDL fragments, as described in the Web IDL specification. [WEBIDL].

Terminology

The EventHandler interface represents a callback used for event handlers as defined in [HTML5].

The concept of fire a simple event is defined in [HTML5].

The terms event handlers and event handler event types are defined in [HTML5].

The DOMError interface represents an error handling object as defined in [DOM4].

Application Manifest and its members

Note
The "application manifest and its members" section has become its own specification. You can now find it at http://www.w3.org/2012/sysapps/manifest/.

Application Management

Note
The ApplicationManagement interface is defined in the Privileged Applications Extensions specification.

Application interface

Web Applications are represented by the Application interface.

readonly attribute DOMString origin
The attribute MUST return the application's origin.
readonly attribute Object manifest
The attribute MUST return an object representing the parsed application manifest.
readonly attribute DOMString installOrigin
The attribute MUST return the origin of the page from which the application was installed. [ORIGIN]
readonly attribute unsigned long installTime
The attribute MUST return the time in milliseconds since epoch at which the application was installed.
readonly attribute Object parameters
The attribute MUST return the parameters that were provided at install time. See install() in ApplicationRegistry.
DOMRequest launch()
This method MUST return a DOMRequest instance and then run the following steps asynchronously:
  1. If the caller is not allowed by the UA to launch the application, the UA MUST fire an error event to the DOMRequest object with the "NotAllowedError" error code and exit those steps.
  2. If the caller is allowed to launch the application, the UA SHOULD launch the application.
  3. If the application has been successfully launched, the UA MUST fire a success event to the DOMRequest object and set result to null.
    Otherwise, the UA MUST fire an error event to the DOMRequest object with an error code that describes the error.
DOMRequest uninstall()
This method MUST return a DOMRequest instance and then run the following steps asynchronously:
  1. If the application is not currently installed, the UA MUST fire an error event to the DOMRequest object with the "NotInstalledError" error code and exit those steps.
  2. If the caller is not allowed by the UA to uninstall the application, the UA MUST fire an error event to the DOMRequest object with the "NotAllowedError" error code and exit those steps.
  3. If the caller is allowed to uninstall the application, the UA SHOULD uninstall the application.
  4. If the application has been successfully uninstalled, the UA MUST fire a success event to the DOMRequest object and set result to null.
    Otherwise, the UA MUST fire an error event to the DOMRequest object with an error code that describes the error.
readonly attribute DOMString updateState
The attribute MUST return the empty string, available, downloading, downloaded or installing, depending on the state of the application.
If the application is being updated, the attribute MUST return installing.
If the application is ready to be updated, with the update fully downloaded or if there is no download to proceed to the update, the attribute MUST return downloaded.
If the application's update is being downloaded, the attribute MUST return downloading.
If there is an application update available, it is not being installed, nor downloaded, nor downloading, the attribute MUST return available. Otherwise, the attribute MUST return the empty string.
readonly attribute unsigned long downloadSize
The attribute SHOULD return the size of the download that would be required to update the application in kilobytes, if any. If the application does not have an available update, if the download has already been done or if the UA can't find out the size of the download required for the update, the attribute MUST return 0.
If the download is happening, the attribute MUST return 0.
If the download has been made but interrupted and the UA is able to continue it, the attribute SHOULD return the remaining size to download.
DownloadRequest downloadUpdate()
The method MUST return a DownloadRequest object and asynchronously run the following steps:
  1. If the application does not have an available update, the UA MUST send an error message to the request object with the value InvalidState and abort these steps.
  2. If the application does not require a download to process the update, the UA MUST send a success message to the request object with no value and abort these steps.
  3. If the application's update is currently being downloaded, the request MUST reflect the current state of the download. Otherwise, the request must start the download.
readonly attribute DOMString state;
The attribute MUST return running if the current application state is running. Otherwise, if the current application state is paused, it MUST return paused. Otherwise, it MUST return terminated.
void hide()
When this method is called, the UA SHOULD hide the application from the user. Hiding the application SHOULD fire visibility events as described in [PAGE-VISIBILITY].
If the application was already not visible, this method MUST be a no-op.
void exit()
When this method is called, the UA MUST put the application state to terminated and fire the appropriate events.
If the application was already in the terminated state, this method MUST be a no-op.
attribute EventHandler onlaunch
TBD
attribute EventHandler onpause
TBD
attribute EventHandler onresume
TBD
attribute EventHandler onterminate
TBD

The following are the event handlers (and their corresponding event handler event types) that MUST be supported as attributes by the Application objects:

event handler event handler event type
onlaunch launch
onpause pause
onresume resume
onterminate terminate

DownloadRequest interface

void cancel()
This method MUST stops the download and asynchronously send an error message to itself with the value UserCancel.
attribute double progress
If the current state is error the attribute MUST return 0.0. Otherwise, if the current state is success, the attribute MUST return 1.0. Otherwise, the attribute SHOULD return the current progress of the download expressed between 0.0 and 1.0.
attribute EventHandler onprogress
TBD

When the caller start the download, the DownloadRequest SHOULD start downloading the resource.

If the resource fails to download, the UA MUST send an error message to the request.

If the resource succeed to download, the UA MUST send a success message to the request.

While the resource is downloading, which means as long as readyState is pending, the UA SHOULD regularly fire a simple event named progress on the object. The UA should note that sending too much events might have an impact on performance but sending too few of them might impact the user experience.

The following are the event handlers (and their corresponding event handler event types) that MUST be supported as attributes by the DOMRequest objects:

event handler event handler event type
onprogress progress

Extension to the Navigator interface

An ApplicationRegistry instance is exposed on the Navigator object trough the an app attribute.

readonly attribute ApplicationRegistry app
The attribute MUST return an ApplicationRegistry instance.

ApplicationRegistry interface

The ApplicationRegistry interface allows handling applications and query there status.

DOMRequest install(in DOMString manifestUrl, [Optional] in Object parameters)
This method MUST return a DOMRequest instance and then run the following steps asynchronously:
  1. If the caller is not allowed by the UA to install the application, the UA MUST fire an error event to the DOMRequest object with the "NotAllowedError" error code and exit those steps.
  2. If the caller is allowed to install the application, the UA SHOULD install the application as described in the manifest at manifestUrl.
  3. If the application has been successfully installed, the UA MUST fire a success event to the DOMRequest object and set result to null.
    Otherwise, the UA MUST fire an error event to the DOMRequest object with an error code that describes the error.

The UA SHOULD verify at any moment before installing that manifestUrl points to a valid manifest. If this is not the case, the UA MUST fire an error event to the DOMRequest object with the "InvalidArgumentError" and exit the steps.

The UA SHOULD save the parameters if some are passed so they can later be retrieved by the parameters attribute on the Application interface.

DOMRequest getSelf()
The UA SHOULD return a DOMRequest object and asynchronously check if the current context is an application context.
When the check is done, the UA SHOULD send a success event to the DOMRequest object and sets its result attribute to the Application object representing the current context or null if the current context is not an application context.
DOMRequest getInstalled()
The UA SHOULD return a DOMRequest object and asynchronously get all applications that have been installed by the caller's origin. [ORIGIN]
When those applications are collected, the UA SHOULD send a success event to the DOMRequest object and populate its result attribute with an array of Application objects representing the applications.
DOMRequest checkInstalled(DOMString manifestURL)
The UA SHOULD return a DOMRequest object and asynchronously check if there is an installed application in the system with a manifest URL matching manifestURL.
After the asynchronous operation is done, the IA SHOULD send a success event to the DOMRequest object and populate its result attribute with the boolean value true if there is an installed application fulfilling the condition, otherwise result should be set to false.
  • checkInstalled() could be synchronous. Seems way more convenient.

Packaged applications

A packaged application is an application that is self-contained in a container. All resources that are commonly used by the application SHOULD be available in the container.

A hosted application is an application that is not a packaged application.

Use cases

A packaged application would be useful in a few situations, amongst them:

Package format

An application manifest for the application MUST be present at the root of the container.

The container of a packaged application MUST be a ZIP file.

Origin and dereferring URLs

The origin of each instance of a packaged application MUST be universally unique for the life of that application (i.e., until it is uninstalled) [ORIGIN]. As such, it is RECOMMENDED that a user agent synthesize an origin for a packaged application using the app: URI scheme [APP-URI]. Relative URLs to resources within the packaged application can then be dereferenced using the dereferencing rules specified in the [APP-URI] specification.

Manifest

Inside a packaged application, the valid application manifest filename is manifest.webapp.

A packaged application MUST have a copy of its application manifest outside of the package so it can be used for installation and updates purposes. As a consequence, that copy of the application manifest can be reduced to only a few properties: name, version and relNotes. In addition, a new property can be used only in the content a packaged application manifest: package that SHOULD contain an object with the following properties:

{
  "name": "My Packaged App",
  "description": "This is my first packaged app!",
  "launch_path": "/",
  "version": "1.0",
  "developer": {
    "name": "Mozilla",
    "url": "https://mozilla.org/en-US"
  },
  "package": {
    "url": "http://example.org/mypackagedapp.zip",
    "size": "1024",
    "sha256": "6df134b0cfd88d6d4f27a99e29b9923d50eb8b2c0d5289c60012de424c7a9d97"
  }
}
* Add relNotes to the properties of the manifest, like: 'relNotes': { '1.0': "This is what has been done...", '0.1': "That was so long ago..." }

Updates

An application SHOULD advertise an update by updating its application manifest.

The UA SHOULD regularly check if the application manifest of installed applications has not been updated. To know if the file has been updated, HTTP semantics apply.

For package applications, both application manifests (outside and inside the package) SHOULD be updated. However, the application manifest inside the package SHOULD always be checked to make sure the update (or the install) is genuine.

Data isolation

In the context of a running application, all usual rules for data isolation MUST apply: same-origin policy, same-domain policy, or whatever is used. However, between two applications, those rules no longer apply. Two applications MUST be fully isolated from each other in the sense that they SHOULD NOT be able to access data from each other. For example, if App1 accesses http://example.org and gets a cookie from it, App2 should not be able to see that cookie when accessing http://example.org even if the usual cookie sharing policy should allow this to happen.

This isolation SHOULD apply for all data storage like cookies, localStorage, IndexedDB, app cache and any other Web Platform mechanism that allows to store data and does not explicitly opt out from the application data isolation.
The isolation SHOULD also apply to UA specifics data storage. For example, any permission granted or denied to a host/origin/domain should be isolated per-application or auto-fill and auto-completion features for forms.

Navigation

Depending on the user interface around the application context, navigating outside the application's origin might lock the user out of the application. To prevent that, the UA SHOULD NOT allow navigation out of the application's origin, unless the origin is specified in the following application manifest property:

If the application tries to navigate to an unauthorized origin, the UA SHOULD open the link in a regular but distinct browsing context.

System Messages

TODO: We might want to have something describing how an application goes inactive, get killed and everything to have a better description of system messages. TODO: there is no notion of multi-page applications in this description of system messages. We do not handle system messages that are registered on another page.

System Messages are events sent by the system to an application which has registered for it before. Those events are different from DOM events in the sense that they are always originated by the system and that if the targeted application is not currently running, it will be started.
In addition, unhandled messages will stay in a queue.

Use cases

Some applications might be interested in getting some events even if they are not running and want to be woken up if such event is sent while they are asleep.
In addition, when the application is being woken, it needs to know as soon as possible why it has been disturbed to be able to show the appropriate interface.
Finally, the capability of being woken should be transparent to the application.

Extension to the Navigator interface

optional Object message
The parameter message SHOULD contain an object that would be used by the handler and giving information about the system message. For example, a system message about a delivered pizza should give information about the pizzas that have been delivered. If the system message is already self-explanatory, message SHOULD be null.
void setMessageHandler(DOMString type, systemMessageCallback? callback)
The method MUST set callback as the new message handler for the type of system message type.
If callback is null, the current callback, if any, for the type of message type must be reset and no callback should no longer be set for this type.
If callback is not null and there was no message handler for the given type and there are messages in the pool of messages for the type, then the UA MUST start an asynchronous task that executes all the messages in the pool by the new handler in a FIFO basis and then remove all those messages from the pool of messages.
If the callback is not null and there is a message handler for the given type, that message handler should be replaced by callback.
boolean hasPendingMessages(DOMString type)
The method MUST returns true if there is at least one message in the pool of messages for the given type. Otherwise, it MUST return false.

Definitions

The type of system message identifies a category of system messages.
Application are able to register and handle system messages based on their types. There is no exhaustive list of system messages type. Any specification can create a new type of system message.

Each application has a pool of messages for each type of system message. Every time a system message is sent to an application, if there is no handler for that message's type, the UA MUST add the message to the pool of messages used for that type.
The UA MAY, for memory optimization, discard old messages if the pool becomes too big or if the messages are too old.

When a UA is required to fire a system message of a given type, it has to do one of these actions:

Permissions

Note
Trust mechanisms for privileged applications and the concept privileged application are defined in the Privileged Applications Extensions specification.

Use cases

Some API might allow the application to access sensitive parts of the hardware or sensitive information. To prevent applications to access them, some APIs might require one or more permissions. For example, for an application to be allowed to access your geolocation information, it has to be granted the geolocation permission.

Permission declaration

An application SHOULD define all permissions it is going to use in the application manifest. The UA MAY automatically grant some permissions at install-time or ask the user to grant some applications. However, MAY, in addition or alternatively, ask the user to grant permissions at run-time.

The user MUST be able to revoke a granted permission or grant a denied permission at any time.

Basic Permissions

Specifications are expected to declare the permissions they will require for their feature to work. Altough, some basic permissions can't really go into a specific specification or a related to specifications that might be harder to change.

Thus, this specification defines the following permissions:

Permission Name Permission Description Access Type
notification Allow the application to use the Web Notifications API. N/A
geolocation Allow the application to access the Geolocation API. N/A
storage Allow localStorage and IndexedDB without size limitations. N/A
webapps-manage Allow access to the navigator.apps.management API to manage installed webapps. N/A

Application life-cycle

Application states

At any time, an application MUST be in one of the following states: running, paused, terminated.

An application is running when it has been launched by the UA and has not been put in paused. A running application can transition to paused or terminated states.

If a running application transitions to a paused state, the UA MUST fire a simple event named pause on the Application object before switching its state.

If a running application transitions to a terminated state, the UA MUST fire a simple event named terminate on the Application object before shutting down the application.

An application is paused when the UA stops the execution of an application without terminating it. A paused application SHOULD have all its scripts no longer running, such as rendering, parsing, processing media files and any action that requires CPU and memory or would distract the user. A paused application can transition to running or terminated states.

If a paused application transitions to a running state, the UA MUST fire a simple event named resume on the Application object after changing its state.

An application is terminated when the application has been stopped and is no longer loaded in the system. The state of a terminated application can only be changed to running if the application is launched again.

If a terminated application transitions to a running state, the UA MUST fire a simple event named launch on the Application object after the main browsing context is created but before the load and DOMContentLoaded events are fired.

Issue 1

The specification currently assumes that one will save important when paused so there is no terminate event when transitioning from pause to terminate.

Issue 2

Do we have real use cases for launch?
Is firing before load a hard thing to do?

Consequences of visibility

While an application is running, it can be part or fully hidden. The visibility events described in [PAGE-VISIBILITY] MUST be sent when the visibility status of the application changes.

In addition, when the application becomes fully hidden, the UA MAY put the application in a paused state.

DOMRequest interface

Note

The DOMRequest interface is temporarily hosted by this specification. The Runtime and Security Model for Web Applications specificaton does not plan to keep that guest for ever, this is why it is currently staying in an appendix.

Use cases

Some methods want to return a value or do an action but can't do it synchronously, most of the time for performance reasons. In that case, most of those methods will use a callback mechanism to inform the caller of the success or the failure of the action.
However, this callback mechanism makes the code barely readable and there is no common pattern used by all API in the Web Platform.
DOMRequest intend to be used instead of those callbacks to make those APIs more developer-friendly and help code readability.

Definition

The DOMRequest interface is intended to be used by asynchronous methods that want to return something after performing an action or simply want to inform the caller that the action is done. It returned request can also be used to inform that an error happened during the operation.

A DOMRequest has three state. It is whether pending, success or error.
The initial state of a DOMRequest MUST be pending.

If a DOMRequest receives a success message while in the pending state, its state MUST change to success and SHOULD NOT change afterward.

If a DOMRequest receives an error message while in the pending state, its state MUST change to error and SHOULD NOT change afterward.

If a DOMRequest receives a success message or an error message while not in the pending state, the message MUST be ignored.

A success message SHOULD be sent to the DOMRequest when the operation is successfully terminated. The message MAY contain a value which MUST be used by the result attribute. If the message does not contain a value, null MUST be used instead.

As soon as a success message is received, readyState MUST return done, result MUST return the received value or null as explained above and the object MUST NOT change its state and MUST, therefore, ignore all following success message and error message.
Finally, the UA MUST fire a simple event named success on the object

An error message SHOULD be sent to the DOMRequest when the operation has failed. The message MAY contain a value which MUST be a DOMError object and MUST be used by the error attribute. If the message does not contain a value, the UA SHOULD find the most appropriate DOMError that represents the failure.

As soon as an error message is received, readyState MUST return done, error MUST return the received value the most appropriate error value as explained above and the object MUST NOT change its state and MUST, therefore, ignore all following success message and error message.
Finally, the UA MUST fire a simple event named error on the object.

readonly attribute DOMString readyState
The attribute MUST return pending if the current state is pending. Otherwise, it MUST return done.
readonly attribute any result
The attribute MUST return undefined if the current state is not success. Otherwise, it MUST return the value provided by the success message or null if no value was sent with the message.
readonly attribute DOMError? error
The attribute MUST return null if the current state is not error. Otherwise, it MUST return the value provided by by the error message. If there was no provided value, it SHOULD return the most appropriate DOMError that represents the failure.
[TreatNonCallableAsNull] attribute EventHandler onsuccess
TBD
[TreatNonCallableAsNull] attribute EventHandler onerror
TBD

Events

The following are the event handlers (and their corresponding event handler event types) that MUST be supported as attributes by the DOMRequest objects:

event handler event handler event type
onerror error
onsuccess success

Acknowledgments

Special thanks to the Mozilla team working on Open Web Apps, especially Anant Narayanan for his Web Application Manifest Format and Management APIs specification that this document reuse shamelessly and Fabrice Desré for his help in understanding why some decisions were made.

Special thanks to the Samsung team, especially 金明(Ming Jin), Janusz Majnert and 송정기(Jungkee Song) for their work on the System Application Runtime: Execution and Security Model specification.

Special thanks to Jonas Sicking and Marcos Caceres for their invaluable help.

Thanks to John Lyle, Christophe Dumez and Jonathan Jeon for their useful comments and change proposals.