Get Installed Related Apps API

Draft Community Group Report,

This version:
https://wicg.github.io/get-installed-related-apps/spec/
Issue Tracking:
GitHub
Inline In Spec
Editor:
(Google)

Abstract

The GetInstalledRelatedApps API allows web apps to detect if related native apps are installed on the current device.

Status of this document

This specification was published by the Web Platform Incubator Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.

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 apps to detect this situation 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.filter(app => app.id === 'com.example.myapp')[0];

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 feature only works in secure 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 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 installed app also has an associated platform.

4. Algorithms

4.1. Match an installed app

To match an installed app for relatedApp (an ExternalApplicationResource) and manifestURL (a URL), run these steps:
  1. Let platform be relatedApp’s platform.

  2. If installed apps[platform] does not exist, return null.

  3. Let installedApps be installed apps[platform].

  4. For each installedApp in installedApps:

    1. If relatedApp’s id is not equal to installedApp’s id, and relatedApp’s url is not equal to installedApp’s id, continue.

    2. Let minVersion be relatedApp’s min_version if present, otherwise the empty string.

    3. If 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.

    4. Let fingerprints be relatedApp’s fingerprints if present, otherwise an empty list.

    5. For each fingerprint of fingerprints:

      1. If installedApp’s fingerprints does not contain fingerprint, return null.

    6. If installedApp’s relatedURLs does not contain manifestURL, return null.

    7. Return installedApp.

  5. Return null.

5. API

dictionary RelatedApplication {
    required USVString platform;
    USVString url;
    DOMString id;
    USVString version;
};

Each RelatedApplication represents an installed app that was matched with the provided ExternalApplicationResources from the WebAppManifest.

5.2. Extensions to Navigator

[Exposed=Window]
partial interface Navigator {
  [SecureContext] Promise<sequence<RelatedApplication>> getInstalledRelatedApps();
};
The getInstalledRelatedApps() method, when invoked, runs these steps:
  1. Let relevantBrowsingContext be the context object's relevant settings object's responsible browsing context.

  2. If relevantBrowsingContext is not a top-level browsing context, then return a promise rejected with an InvalidStateError DOMException.

    Should this restriction be removed? (#11)

  3. Let promise be a new promise.

  4. Run the following steps in parallel:

    1. Let manifest and manifestURL be the results of obtaining the manifest. If this fails, resolve promise with an empty list and abort these steps.

    2. Let relatedApplications be manifest’s related_applications.

    3. Let installedApps be an empty list.

    4. For each relatedApplication in relatedApplications:

      1. Let matchedApp be the result of running match an installed app with relatedApplication and manifestURL.

      2. If matchedApp is null, continue.

      3. Let installedApp be a new RelatedApplication with:

        platform

        relatedApplication’s platform

        url

        relatedApplication’s url

        id

        relatedApplication’s id

        version

        matchedApp’s version

      4. Append installedApp to installedApps.

    5. Resolve promise with installedApps.

  5. Return promise.

Conformance

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[APPMANIFEST]
Marcos Caceres; et al. Web App Manifest. 31 May 2019. WD. URL: https://www.w3.org/TR/appmanifest/
[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[PROMISES-GUIDE]
Domenic Denicola. Writing Promise-Using Specifications. 9 November 2018. TAG Finding. URL: https://www.w3.org/2001/tag/doc/promises-guide
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[URL]
Anne van Kesteren. URL Standard. Living Standard. URL: https://url.spec.whatwg.org/
[WebIDL]
Boris Zbarsky. Web IDL. 15 December 2016. ED. URL: https://heycam.github.io/webidl/

IDL Index

dictionary RelatedApplication {
    required USVString platform;
    USVString url;
    DOMString id;
    USVString version;
};

[Exposed=Window]
partial interface Navigator {
  [SecureContext] Promise<sequence<RelatedApplication>> getInstalledRelatedApps();
};

Issues Index

Should this restriction be removed? (#11)