Feature specifications for Web Application Manifest extensions & incubations which Chromium has shipped but do not have committments / implementations from other user agents. Instead of keeping these features as explainers, they are documented more officially here.
This is an unofficial proposal.
display_override
member
For advanced usages, the [=manifest/display_override=] member can be used to specify a custom fallback order of display mode list values for developers to choose their preferred display mode for the web application. Its value is a [=display mode=].
The [=manifest/display_override=] member of the [=application manifest=] is a sequence of display mode list values including extensions like [=display mode/window-controls-overlay=] and [=display mode/borderless=]. This member represents the developer's preferred fallback chain for [=display mode=]s. This field overrides the [=manifest/display=] member. If the user agent does not support any of the [=display mode=]s specified here, then it falls back to considering the [=manifest/display=] member. See processing the display members for the algorithm steps.
The following steps are added to the [=application manifest/processing extension-point=] in determining the web app's chosen display mode:
This member is intended to be only used for advanced cases, where the developer wants explicit control over the fallback order of their display modes. Otherwise, the [=manifest/display=] member is sufficient for most use cases.
Additionally to the normal display modes, [=manifest/display_override=] also supports certain extensions to it.
The following shows a [=manifest=] that prefers the
minimal-ui
display mode over
standalone
, but if minimal-ui
isn't
supported, falls back to standalone
as opposed to
browser
.
{ "name": "Recipe Zone", "description": "All of the recipes!", "icons": [{ "src": "icon/hd_hi", "sizes": "128x128" }], "start_url": "/index.html", "display_override": ["minimal-ui"], "display": "standalone", "theme_color": "yellow", "background_color": "red" }
[=app-region=] CSS property has not been implemented in any user agent, so it is at risk. Note that some user agents use the non-standard CSS property `-webkit-app-region` for the same purpose.
The `app-region` property can be used to define with CSS which regions or elements in for example a title bar are draggable.
The `share_target` member registers a web application as "target" for share actions (e.g., for sharing a text, a URL, or a file). The `share_target` member is part of the [[[web-share-target]]] specification.
note_taking
member
The `note_taking` member of the Web Application Manifest is an object that contains information related to note-taking. It has the following members:
A user agent MAY use these members to treat the web application differently as an application with note-taking capabilities (e.g., integrate with operating system note-taking surfaces).
new_note_url
member
The [=note_taking=] `new_note_url` member is a [=string=] that represents the URL the developer would prefer the user agent load when the user wants to take a new note using the web application (e.g., from an operating system shortcut icon or keyboard shortcut).
The `new_note_url` member is purely advisory, and a user agent MAY ignore it or provide the end-user the choice of whether to use it. The user agent MAY provide the end-user the choice to modify it.
The following shows a [=manifest=] for a note-taking application.
{ "name": "My Note Taking App", "description": "You can take notes!", "icons": [{ "src": "icon/hd_hi", "sizes": "128x128" }], "start_url": "/index.html", "display": "standalone", "note_taking": { "new_note_url": "/new_note.html" } }
To process the `note_taking` member, given [=ordered map=] |json:ordered map|, [=ordered map=] |manifest:ordered map|, [=URL=] |manifest_URL:URL|, run the following during the extension point in [=processing a manifest=]:
To process the `new_note_url` member, given [=ordered map=] |json_note_taking:ordered map|, [=ordered map=] |manifest_note_taking:ordered map|, [=URL=] |manifest_URL:URL|, run the following:
To launch the `new_note_url`, given processed manifest |manifest:processed manifest|, run the following steps:
The [=manifest's=] protocol_handlers
member is an array of
protocol handler descriptions that allows a web application to
handle URL protocols.
On installation, a user agent SHOULD register protocol handlers with the Operating System via interactions that are consistent with:
To process the `protocol_handlers` member, given [=object=] |json:JSON|, |manifest:ordered map|:
A user agent SHOULD ask users for permission before registering a [=protocol handler description=] protocol_handlers as the default handler for a protocol with the host operating system. A user agent MAY truncate the list of [=protocol handler description=] protocol_handlers presented in order to remain consistent with the conventions or limitations of the host operating system.
Each protocol handler description is an [=object=] that represents a protocol that the web application wants to handle. It has the following members:
A user agent SHOULD use these values to register the web application as a handler with the operating system. When the user activates a protocol handler URL, the user agent SHOULD run handling a protocol launch.
[[HTML]]'s {{NavigatorContentUtils/registerProtocolHandler()}} allows
web sites to register themselves as possible handlers for particular
protocols. What constitutes valid protocol
and
url
values for protocol handler descriptions is
defined in that API. Also note that the [[HTML]] API uses
[=url/scheme=] where we use protocol
but the same
restrictions apply.
The protocol member of a protocol handler description is a string that represents the protocol to be handled, such as `mailto` or `web+auth`.
The protocol member of a protocol handler description is equivalent to {{NavigatorContentUtils/registerProtocolHandler()}}'s |scheme| argument defined in [[HTML]].
The url member of a protocol handler description is the URL [=manifest/within scope=] of the application that opens when the associated protocol is activated.
The url member of a protocol handler description is
equivalent to {{NavigatorContentUtils/registerProtocolHandler()}}'s
url
argument defined in [[HTML]].
When a protocol handler description protocol_handler having [=manifest=] manifest is invoked, it goes through the same steps used to [=invoke a protocol handler=] where the user agent, instead of [=navigating=] to resultURL, SHOULD [=launch a web application=] passing manifest and resultURL.
This should not invoke and alter [=invoke a protocol handler=] in this way. The computation of resultURL should be extracted out into a separate algorithm for general use.
Depending on the operating system capabilities, the protocol handler could become a 'default' handler (e.g. handling launches of a given protocol automatically) of a given protocol without the explicit knowledge of the user. To protect against possible misuse, user agents MAY employ protections such as:
If a user agent removes the the registration of the protocol handler entity it SHOULD provide UX for the user to re-register the web app and protocol with the operating system.
The [=manifest's=] file_handlers
member is a [=list=] that
provides instructions for how the app handles file-opening actions that
originate outside of the app itself.
The management, presentation, and selection of registered file-handling applications is at the discretion of the operating system.
To process the `file_handlers` member, given [=ordered map=] |json:ordered map|, [=ordered map=] |manifest:ordered map|, [=URL=] |manifest_url:URL|:
On [=installation=], a user agent SHOULD run the process to [=register file handlers=].
Each file handler represents a URL in the scope of the application that can handle launches with [=file types=] it accepts. It has the following members:
A user agent can use these members to associate the web application with [=file type=] on the operating system.
A file type can be defined by a [=MIME type=] and/or [=file extension=]. A file belongs to a file type if the OS determines it to have a [=MIME type=] and/or its name ends with a certain [=file extension=]. A file extension is a string that start with a "." and only contains valid suffix code points. Additionally, [=file extensions=] are limited to a length of 16 code points.
The [=file handler=]'s action
member is a string that
represents a URL relative to the manifest URL that is
[=manifest/within scope=] of a processed manifest . This
URL will be navigated to in the steps to [=execute a file handler
launch=].
The [=file handler=]'s name
member is a string that
identifies the file type to the user. [=User agents=] MAY pass this
information to the operating system during file handler
registration.
The file handler's icons
member lists icons that serve as
graphical representations of a [=file type=] on a platform. User
agents MAY pass this information to the operating system during
file handler registration.
The [=file handler=]'s accept
member is a dictionary
mapping [=MIME types=] to a list of [=file extensions=].
[=User agents=] MUST enforce that the [=file handler/accept=] entry only applies to files that have a matching extension.
In order to [=register file handlers=], some operating systems require [=MIME types=] and some require [=file extensions=]. Thus the manifest MUST always provide both for each [=file handler/accept=] entry.
In addition to complete [=MIME types=], "*"
can be
used as the subtype of a [=MIME type=] to match, for example, all
image formats with "image/*"
(that also apply to the
provided list of [=file extensions=]).
The [=file handler=]'s launch_type
member is a string
that determines how the app is launched for files routed to this
handler. The possible values are `"single-client"` and
`"multiple-clients"`. If not provided, it defaults to
`"single-client"`.
When a [=file handler=] is determined to match a set of files, the [=user agent=] SHOULD use [=file handler/launch_type=] to control whether the app is launched once for each file (`"multiple-clients"`), or one time for all files (`"single-client"`). See {{LaunchParams/files}}. The user agent MUST NOT coalesce files from different [=file handlers=] into a single launch event.
To process a file handler item, given [=ordered map=] |item:ordered map|, [=URL=] |start_url:URL|, [=URL=] |scope:URL|, and [=URL=] |manifest URL:URL|:
The steps to execute a file handler launch are given by the following algorithm. The algorithm takes [=list=] |files:list| and a [=ordered map=] |manifest:ordered_map| which holds results from [=processing a manifest=].
A user agent SHOULD register file handlers with the host operating system, consistent with:
A user agent MAY truncate the total set of [=file extensions=] to preserve functionality and prevent abuse. A user agent MAY prevent associations with certain filetypes.
Depending on the operating system capabilities, the [=file handler=] could become a default handler of a given [=file type=] without the explicit knowledge of the user, handling launches of a given file type automatically. To protect against possible mis-use, [=user agents=] MAY require explicit user consent to begin with the process to [=execute a file handler launch=]. If consent is sought, the user agent SHOULD allow the user to specify that the decision is permanent and if so specified SHOULD remove the web application's OS registration as a file handling entity.
The name and icon of each file handler can be sensitive to privacy and security, as there isn't a specified way for the user to see and confirm these. Due to this, [=user agents=] MAY choose to ignore these in favor of alternative strings and icons or fall back on OS defaults.
In the following example, the web application has 3 different file handlers.
There are multiple ways that the installation process can be triggered:
In any case, the user agent MUST NOT present an install prompt if the document is not installable.
The user agent MAY, at any time (only if the document is installable), run the steps to notify that an install prompt is available at any time, giving the site the opportunity to show a site-triggered install prompt without the user needing to interact with the user agent UI.
To present an install prompt:
The steps to notify that an install prompt is available are given by the following algorithm:
The steps to install the web application are given by the following algorithm:
By design, this specification does not provide developers with an explicit API to "install" a web application. Instead, a manifest can serve as an installability signal to a user agent that a web application can be installed. These signals will vary per user agent, as each user agent will have its own heuristics to determine whether a web site is elegible of an install prompt. Implementers generally will provide documentation that describe their particular installabilty signals or other relevant criteria a web application needs to meet to be deemed installable.
Examples of possible installability signals for a web application that a user agent might implement:
This list is not exhaustive and some installability signals might not apply to all user agents. How a user agent makes use of these installability signals to determine if a web application can be installed is left to implementers.
[=event|Events=] of this specification rely on the application life-cycle task source.
[Exposed=Window] interface BeforeInstallPromptEvent : Event { constructor(DOMString type, optional EventInit eventInitDict = {}); Promise<PromptResponseObject> prompt(); }; dictionary PromptResponseObject { AppBannerPromptOutcome userChoice; }; enum AppBannerPromptOutcome { "accepted", "dismissed" };
The {{BeforeInstallPromptEvent}} is dispatched when the site is allowed to present a site-triggered install prompt, or prior to the user agent presenting an automated install prompt. It allows the site to cancel the automated install prompt, as well as manually present the site-triggered install prompt.
The PromptResponseObject contains the result of calling {{BeforeInstallPromptEvent/prompt()}}. It contains one member, userChoice, which states the user's chosen outcome.
An instance of a {{BeforeInstallPromptEvent}} has the following internal slots:
prompt()
method
The prompt method, when called, runs the following steps:
To request to present an install prompt with {{BeforeInstallPromptEvent}} event:
This example shows how one might prevent an automated install prompt from showing until the user clicks a button to show a site-triggered install prompt. In this way, the site can leave installation at the user's discretion (rather than prompting at an arbitrary time), whilst still providing a prominent UI to do so.
window.addEventListener("beforeinstallprompt", event => { // Suppress automatic prompting. event.preventDefault(); // Show the (disabled-by-default) install button. This button // resolves the installButtonClicked promise when clicked. installButton.disabled = false; // Wait for the user to click the button. installButton.addEventListener("click", async e => { // The prompt() method can only be used once. installButton.disabled = true; // Show the prompt. const { userChoice } = await event.prompt(); console.info(`user choice was: ${userChoice}`); }); });
AppBannerPromptOutcome
enum
The AppBannerPromptOutcome enum's values represent the outcomes from presenting an install prompt.
partial interface Window { attribute EventHandler onappinstalled; attribute EventHandler onbeforeinstallprompt; };
onappinstalled
attribute
The onappinstalled event handler IDL attribute handles "appinstalled" events.
onbeforeinstallprompt
attribute
The onbeforeinstallprompt event handler IDL attribute handles "beforeinstallprompt" events.