From 3b2c487e21ffc9b522f2d8bf145117e222792750 Mon Sep 17 00:00:00 2001 From: Christian Liebel Date: Fri, 6 Jun 2025 21:42:43 +0200 Subject: [PATCH 1/2] Add API for installing the current document --- index.html | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/index.html b/index.html index 092c9b6e..10d1322a 100644 --- a/index.html +++ b/index.html @@ -2433,6 +2433,15 @@

a new [=top-level browsing context=] with the manifest's members [=applied=].

+

+ At the discretion of the operating system or user agent, web + applications may be [=installed=] once or multiple times. +

+

Once a web application is [=installed=] it is known as a installed web application: That is, the manifest's @@ -2599,6 +2608,124 @@

+
+

+ API Definition +

+
+

+ Extensions to the `Navigator` interface +

+ + +
+          partial interface Navigator {
+              [SecureContext, NewObject] Promise<undefined> install();
+          };
+        
+

+ Internal Slots +

+

+ This API adds the following internal slot to the {{Navigator}} + interface. +

+
+
+ {{Promise}}? [[\installPromise]] +
+
+ The [=this=].{{Navigator/[[installPromise]]}} is a promise that + represents a user's current intent to install an application. It is + initialized to `null`. +
+
+

+ install() method +

+

+ When the {{Navigator/install()}} method is called, run the following + steps to [=install=] the website. +

+
    +
  1. Let |global:Window| be [=this=]'s [=relevant global object=]. +
  2. +
  3. Let |document:Document| be |global|'s [=associated Document=]. +
  4. +
  5. If |document| is not [=Document/fully active=], return [=a + promise rejected with=] an {{"InvalidStateError"}} {{DOMException}}. +
  6. +
  7. If [=this=].{{Navigator/[[installPromise]]}} is not `null`, + return [=a promise rejected with=] an {{"InvalidStateError"}} + {{DOMException}}. +
  8. +
  9. If |global| does not have [=transient activation=], return [=a + promise rejected with=] a {{"NotAllowedError"}} {{DOMException}}. +
  10. +
  11. [=Consume user activation=] of |global|. +
  12. +
  13. Set [=this=].{{Navigator/[[installPromise]]}} to be a new + promise. +
  14. +
  15. Return [=this=].{{Navigator/[[installPromise]]}} and in + parallel: +
      +
    1. [=Processing|Process=] the |document|'s [=manifest=]. +
    2. +
    3. If the |document|'s [=Document/processed manifest=] is null, + [=queue a global task=] on the [=user interaction task source=] + using |global| to: +
        +
      1. [=Reject=] [=this=].{{Navigator/[[installPromise]]}} with + an {{"DataError"}} {{DOMException}}. +
      2. +
      3. Set [=this=].{{Navigator/[[installPromise]]}} to `null`. +
      4. +
      5. Terminate this algorithm. +
      6. +
      +
    4. +
    5. Present an installation UI for the |document|'s + [=Document/processed manifest=]. + +
    6. +
    7. Wait for the user's choice. +
    8. +
    9. If the user chose to abort the install operation, or if + installing the application has failed, [=queue a global task=] on + the [=user interaction task source=] using |global| to: +
        +
      1. [=Reject=] [=this=].{{Navigator/[[installPromise]]}} with + an {{"AbortError"}} {{DOMException}}. +
      2. +
      3. Set [=this=].{{Navigator/[[installPromise]]}} to `null`. +
      4. +
      5. Terminate this algorithm. +
      6. +
      +
    10. +
    11. Otherwise, [=queue a global task=] on the [=user interaction + task source=] using |global| to: +
        +
      1. [=Resolve=] [=this=].{{Navigator/[[installPromise]]}} + with `undefined`. +
      2. +
      3. Set [=this=].{{Navigator/[[installPromise]]}} to `null`. +
      4. +
      +
    12. +
    +
  16. +
+
+
+
From ba5b5f9a3f56e1dc7c75ef6d6e6f75fcdac74a24 Mon Sep 17 00:00:00 2001 From: Christian Liebel Date: Thu, 26 Jun 2025 14:13:53 +0200 Subject: [PATCH 2/2] Apply suggestions from review --- index.html | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/index.html b/index.html index 10d1322a..1ca46629 100644 --- a/index.html +++ b/index.html @@ -2645,7 +2645,7 @@

When the {{Navigator/install()}} method is called, run the following - steps to [=install=] the website. + steps:

  1. Let |global:Window| be [=this=]'s [=relevant global object=]. @@ -2654,7 +2654,11 @@

  2. If |document| is not [=Document/fully active=], return [=a promise rejected with=] an {{"InvalidStateError"}} {{DOMException}}. -
  3. + +
  4. If the |document| is not the [=top-level traversable=], return + [=a promise rejected with=] an {{"NotAllowedError"}} + {{DOMException}}. +
  5. If [=this=].{{Navigator/[[installPromise]]}} is not `null`, return [=a promise rejected with=] an {{"InvalidStateError"}} {{DOMException}}. @@ -2670,31 +2674,7 @@

  6. Return [=this=].{{Navigator/[[installPromise]]}} and in parallel:
      -
    1. [=Processing|Process=] the |document|'s [=manifest=]. -
    2. -
    3. If the |document|'s [=Document/processed manifest=] is null, - [=queue a global task=] on the [=user interaction task source=] - using |global| to: -
        -
      1. [=Reject=] [=this=].{{Navigator/[[installPromise]]}} with - an {{"DataError"}} {{DOMException}}. -
      2. -
      3. Set [=this=].{{Navigator/[[installPromise]]}} to `null`. -
      4. -
      5. Terminate this algorithm. -
      6. -
      -
    4. -
    5. Present an installation UI for the |document|'s - [=Document/processed manifest=]. - +
    6. Present an installation UI for the |document|'s [=manifest=].
    7. Wait for the user's choice.