1. Introduction
As the capabilities of the web grow, the functionality of web apps begins to match that of corresponding native apps. The situation of users having a web app and the corresponding native app both installed on the same device will become more common, and the feature sets of these apps will converge.
It is important to allow websites to detect if an app is installed, whether a native app or a web app, to allow them to disable functionality that should be provided by the other app.
1.1. Example
const installedApps= await navigator. getInstalledRelatedApps(); const nativeApp= installedApps. find( app=> app. id=== 'com.example.myapp' ); if ( nativeApp&& doesVersionSendPushMessages( nativeApp. version)) { // There’s an installed native app that handles sending push messages. // No need to do anything. return ; } // Create a push subscription.
In the above example, doesVersionSendPushMessages is a developer-defined function.
2. Privacy Considerations
This API is only enabled in secure top-level contexts. This ensures that the website cannot be spoofed, and that the association between the site and application is valid.
The association between the web app and its counterpart is bidirectional, meaning that the web app has to declare its association with the related app, and the related app has to declare its association with the web app. This prevents malicious websites from fingerprinting users and getting a list of their installed applications.
The user agent MAY limit the number of related applications to be matched, to limit fingerprinting.
The user agent MUST NOT return installed applications when running in a privacy preserving mode, for example Incognito in Chrome or Private Browsing in Firefox.
3. Infrastructure
3.1. Platform
A platform is an OS-specific concept, which groups applications of the same class together. It is represented by a USVString
.
An OS has installed apps, a map where the keys are platforms, and the values are lists of installed apps.
3.2. Installed App
An installed app represents an application that is installed on the user’s device.
An installed app consists of:
-
An id (a
DOMString
). This a unique identifier for an application within the platform it belongs to. -
A version (a
USVString
). This is the version of the application, as defined by the platform. -
Fingerprints (a list of
Fingerprint
s). These are cryptographic values for identifying the application defined within the application metadata. -
relatedURLs (a set of
URL
s). These areorigin
s of related web applications declared within the application.
An installed app also has an associated platform.
4. Algorithms
4.1. Match an installed app
ExternalApplicationResource
) and manifestURL (a URL
), run these steps:
-
Let platform be relatedApp’s
platform
. -
If installed apps[platform] does not exist, return null.
-
Let installedApps be installed apps[platform].
-
For each installedApp in installedApps:
-
If relatedApp’s
id
is not equal to installedApp’s id, and relatedApp’surl
is not equal to installedApp’s id, continue. -
Let minVersion be relatedApp’s
min_version
if present, otherwise the empty string. -
If minVersion is not the empty string and minVersion is greater than installedApp’s version, return null.
Note: `greater` is a platform-specific concept for ordering application versions. It does not have to be lexicographic order.
-
Let fingerprints be relatedApp’s
fingerprints
if present, otherwise an empty list. -
For each fingerprint of fingerprints:
-
If installedApp’s fingerprints does not contain fingerprint, return null.
-
-
If installedApp’s relatedURLs does not contain manifestURL, return null.
-
Return installedApp.
-
-
Return null.
5. API
5.1. RelatedApplication
dictionary {
RelatedApplication required USVString ;
platform USVString ;
url DOMString ;
id USVString ; };
version
Each RelatedApplication
represents an installed app that was matched with the provided ExternalApplicationResource
s from the WebAppManifest
.
5.2. Extensions to Navigator
[Exposed =Window ]partial interface Navigator { [SecureContext ]Promise <sequence <RelatedApplication >>getInstalledRelatedApps (); };
5.2.1. getInstalledRelatedApps()
getInstalledRelatedApps()
method, when invoked, runs these steps:
-
Let relevantBrowsingContext be the context object's relevant settings object's responsible browsing context.
-
If relevantBrowsingContext is not a top-level browsing context, then return a promise rejected with an
InvalidStateError
DOMException
.Should this restriction be removed? (#11)
-
Let promise be a new promise.
-
Run the following steps in parallel:
-
Let manifest and manifestURL be the results of obtaining the manifest. If this fails, resolve promise with an empty list and abort these steps.
-
Let relatedApplications be manifest’s
related_applications
. -
Optionally:
-
Let maxRelatedApps be a user agent determined number.
-
If relatedApplications’ size is greater than maxRelatedApps, truncate relatedApplications to a size of maxRelatedApps.
Note: This limits how many native applications a website can know are installed. The extra items need to be truncated so the same
ExternalApplicationResource
s are returned every time. -
-
Let installedApps be an empty list.
-
For each relatedApplication in relatedApplications:
-
Let matchedApp be the result of running match an installed app with relatedApplication and manifestURL.
-
If matchedApp is null, continue.
-
Let installedApp be a new
RelatedApplication
with: -
Append installedApp to installedApps.
-
-
Resolve promise with installedApps.
-
-
Return promise.