Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Require id in manifest and support 0 param installation #894

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 15 additions & 13 deletions WebInstall/explainer_same_domain.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,16 @@ Modern browsers have UX that enable users to *install* web content on their devi
### **Installing a web app from the current origin**
The site can trigger its own installation.

The current way of supporting installation is vai the `onbeforeinstallprompt` event, which only works in browsers that have a prompting UI affordace.
The current way of supporting installation is via the `onbeforeinstallprompt` event, which only works in browsers that have a prompting UI affordance.

The `navigator.install` method allows a imperative way to install web content, and works for UAs that prompt and don't prompt:

```javascript
/* tries to install the current domain */
amandabaker marked this conversation as resolved.
Show resolved Hide resolved
/* tries to install the current document */
const installApp = async () => {
if (!navigator.install) return; // api not supported
try {
await navigator.install('content_id_123');
await navigator.install();
} catch(err) {
switch(err.name){
case 'AbortError':
Expand All @@ -61,18 +61,16 @@ const installApp = async () => {

The **`navigator.install` method can overlap with some functionality of `beforeinstallprompt` for same-origin installation**. When the method is called it will trigger the UA to prompt for the installation of an application. This is analogous to when the end user clicks on an affordance that the UA might have to inform the user of installing. On Edge, Chrome (desktop) and Samsung Internet (mobile), this would be when the user clicks on the 'app available' banner or related UX that appears on the omnibox of the browser. For browsers that do not implement prompting, the expected behaviour is analogous to their installation paradigm. For example, in Safari (desktop) the behaviour might be that it shows a dialog to add the content to the dock as an app.

On UAs that support prompting, the threshold for `navigator.install` to resolve on same-origin installations uses the same checks that `onbeforeinstallprompt` currently has for prompting (if required by the UA). The promise doesn't resolve unless the *installability criteria* is met. *Note that the criteria defined by UAs varies and can be that there is NO criteria*.
On UAs that support prompting, the threshold for `navigator.install` to resolve on same-origin installations uses the same checks that `onbeforeinstallprompt` currently has for prompting (if required by the UA). The promise doesn't resolve unless the *installability criteria* is met. *Note that the criteria defined by UAs varies and can be that there is NO criteria aside from requiring an id in the site's manifest*.

When called on the same domain, the **`install` method will trigger/open the prompt for installation the same way that using `onbeforeinstallprompt` does right now for browser that prompts.** If there is an error with the installation, then the promise returns a `DOMException` of type 'AbortError'.

amandabaker marked this conversation as resolved.
Show resolved Hide resolved
*Any same-origin content can be installed even if it is **NOT** an application.*


## Proposed Solution

### The `navigator.install` method

To install a web site/app, the site/app would use the promise-based method`navigator.install(<id>[[, install_url], <params>])`. This method will:
To install a web site/app, the site/app would use the promise-based method `navigator.install(id, install_url, [<params>])`. This method will:

* Resolve when an installation was completed.
* The success value will be an object that contains:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the id "computed" at this point? Based on this design, web install no longer permits the usage of computed ids, only explicitly defined id's declared in the manifest.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to update 2. below ~100 to say "computed or id in manifest"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't add a comment lower, so putting it here. I encourage you to open an Issue tracking that there's a single error that is just AbortError. I think it would be helpful to devs if there was at least one other error that helped identify that the problem was that a id was either not found, or the one specified in the call didn't match the one in the target manifest.

Expand All @@ -85,7 +83,7 @@ To install a web site/app, the site/app would use the promise-based method`navig

const installApp = async () => {
try{
const value = await navigator.install('content_id_123');
const value = await navigator.install();
}
catch(err){console.error(err.message)}
};
Expand All @@ -96,8 +94,10 @@ const installApp = async () => {
#### **Signatures of the `install` method (same-origin)**
The same-origin part of the Web Install API consists of the extension to the navigator interface with the install method. The install method can be used in several different ways. There is no difference in behaviour when this is called from a standalone window or a tab.

1. `navigator.install(id[[, install_url], <params>])`: The method takes an id (and optional install url) and tries to install the current origin. If the content being installed has a manifest file, this `id` must match the value in the manifest file. If there is no manifest file present, this `id` will act as the app id for the installed content. This is relevant since if the installed content were to be given a manifest file and made into an application, there is a way to automatically update the app going forward.
The call can also receive an object with parameters that it can use to customize a same domain installation. These parameters alter how the app is installed and are defined in an object. More information about the parameters is found in the [Parameters](#parameters) subsection of this specification.
1. `navigator.install(<params>)`: The method takes no parameters and tries to install the current document. If the content to be installed does not link to a manifest with an explicitly defined `id` value, then installation will fail.
2. `navigator.install(id, install_url, [<params>])`: The method takes an id and install url and tries to install the web content at `install_url`. If the content to be installed does not link to a manifest OR if the manifest does not include a valid id OR if the id parameter does not match either the declared or resolved manifest id, then installation will fail.

Both calls can also receive an object with parameters that they can use to customize a same domain installation. These parameters alter how the app is installed and are defined in an object. More information about the parameters is found in the [Parameters](#parameters) subsection of this specification.
amandabaker marked this conversation as resolved.
Show resolved Hide resolved

#### **Parameters**

Expand All @@ -115,7 +115,7 @@ To install a same domain web site/app, the process is as follows:

## Relation with other web APIs

* **`navigator.install` and manifest file's `prefer_related_applications`:** When the `related_applications` and `prefer_related_applications` key/values are present in the manifest, the UA should try to handoff the install to the prefered catalog. If this is not possible then it fallback to a default UA install.
* **`navigator.install` and manifest file's `prefer_related_applications`:** When the `related_applications` and `prefer_related_applications` key/values are present in the manifest, the UA should try to handoff the install to the preferred catalog. If this is not possible then it fallback to a default UA install.

* **`navigator.install` and getInstalledRelatedApps():** If a web app tries to install itself (same domain install) it can first use the `getInstalledRelatedApps()` to check if it is already installed and hide the installation UI.

Expand Down Expand Up @@ -158,8 +158,10 @@ A user agent might decide to have only the requirement of HTTPS to allow install
* Should we allow an [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) to enable cancelling the installation if the process takes too long?

## Glossary
* **installation origin**: the origin that initiates the call to the `install` method.
* **installed origin**: the origin that is installed with the `install` method.
* **Installation origin**: The origin that initiates the call to the `install` method.
* **Installed origin**: The origin that is installed with the `install` method.
* **Declared manifest id**: The id as it is declared in the manifest. See [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/Manifest/id) for more info.
* **Resolved manifest id**: The processed id after it is resolved against the `start_url`'s origin. Since the declared id is resolved against an origin, this will take the form of a url (e.g. "https://example.com/my_app"), although it may not point to a valid resource. See [W3 manifest spec](https://www.w3.org/TR/appmanifest/#id-member) for detailed parsing info.

## Acknowledgements

Expand Down