Skip to content

Commit 5e109d2

Browse files
authored
Clearly explain update_token behavior differences in explainer for predictable app updating. (#115)
* Rename questionnaire * Explainer images * Cache-control
1 parent 83c2925 commit 5e109d2

File tree

2 files changed

+72
-31
lines changed

2 files changed

+72
-31
lines changed
202 KB
Loading

predictable-app-updating.md

Lines changed: 72 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,40 @@ Author: Dibyajyoti Pal (dibyapal@chromium.org)
44

55
# **Introduction**
66

7-
This explainer proposes a way to have PWAs fully update their identities in a safe and resourceful manner, to further bridge the gap between PWAs and native apps. This is done by updating the [manifest spec](https://www.w3.org/TR/appmanifest/#web-application-manifest) to have a specific field for making updates more deterministic by the developer, and for providing a consistent experience. The proposal attempts to do so in a way that:
7+
This explainer proposes a consistent way for developers to identify when to fully update their PWA in a safe and resourceful manner that is backwards compatible. This is done by updating the [manifest spec](https://www.w3.org/TR/appmanifest/#web-application-manifest) to have a specific field for making updates more deterministic and consistent. The proposal attempts to do so in a way that:
88

9-
1. Uses less resources, making network usage more efficient.
9+
1. Specifies the update check algorithm to ensure the user agent can use minimal network resources.
1010
2. Prevent user confusion by showing the update UX less often.
1111

12+
Doing so helps to further bridge the gap between PWAs and native apps.
13+
1214
# **Background**
1315

14-
[PWAs](https://web.dev/explore/progressive-web-apps) are app experiences built on the web, and like native apps, they support updating themselves. Developers have the option of changing any field in the manifest (including the [security sensitive fields](https://www.w3.org/TR/appmanifest/#dfn-security-sensitive-members)), and the user agent can then apply the changes in a way as defined in the [manifest updating spec](https://www.w3.org/TR/appmanifest/#updating). One of the ways Chromium does it is by showing the update dialog, as seen below under the `Chromium PWA update detection` section. This is done to prevent known [phishing risks](#phishing).
16+
[PWAs](https://web.dev/explore/progressive-web-apps) are app experiences built on the web, and like native apps, they support updating themselves. Developers have the option of changing any field in the manifest (including the [security sensitive fields](https://www.w3.org/TR/appmanifest/#dfn-security-sensitive-members)), and the user agent can then apply the changes in a way as defined in the [manifest updating spec](https://www.w3.org/TR/appmanifest/#updating). For example, changes to the security sensitive manifest properties **require** the user agent to explicitly get user permission, which is why Chromium shows an update dialog to the user. This helps prevent [phishing risks](#phishing).
1517

1618
Updates on PWAs are important because they allow:
1719
- Rebranding via icon and name changes.
1820
- Icon changes via changing icon urls in the manifest.
1921
- Minor visual changes in the icon even if the url has stayed the same (due to dynamic re-encoding by CDNs).
2022

21-
For all these use-cases, the detection of when an update should happen is not clearly defined in the spec, leading to [problems](#chromium-problems). This proposal attempts to fix that.
23+
gFor all these use-cases however, the **detection** of when an update should happen is not clearly defined in the spec, leading to [problems](#chromium-problems). The next session attempts to dive into these problems, and [propose](#proposal) a solution that all user agents can implement without running into the same problems.
2224

2325
# [**Chromium PWA update detection, and its problems**](#chromium-problems)
2426

2527
Currently, detecting that a PWA needs an update goes like this:
2628

27-
- On page load of an url within the [scope of an installed PWA](https://www.w3.org/TR/appmanifest/#scope-member), a manifest update is triggered.
29+
- On page load of an url within the [scope of an installed PWA](https://www.w3.org/TR/appmanifest/#scope-member), a manifest update is triggered.
2830
- The manifest, and the resources defined in it, are downloaded and compared with the installed PWA and its resources.
2931
- If there is a difference, an update happens.
3032
- If the difference is in security sensitive fields, like the name, icon or short name, the user agent shows a UX notifying the user that an update is supposed to happen.
3133
- The UX shows the differences between the old and the new sensitive fields, and asks the user to either accept the changes or uninstall the app.
3234

3335
![Update dialogs](./images/current-chromium-dialogs.png)
3436

37+
## Problem: Developers have no control over when the update dialog may show up
38+
39+
The dialog shows up whenever Chromium sees the new manifest & detects changes. Developers have to accept that every change to security sensitive members could trigger this. They cannot, for example, make a number of incremental changes, and then trigger one update dialog at the end once they are all done.
40+
3541
## Problem: Update check wastes bandwidth, requiring a throttle
3642

3743
Network resources are wasted by performing icon downloads over and over again just to see if an update is needed. Chromium's current implementation is forced to mitigate this problem by introducing a [throttle](https://web.dev/articles/manifest-updates) to reduce wasted downloads for non-updates.
@@ -49,27 +55,26 @@ Both these would trigger manifest updates, with the end user seeing no “visibl
4955

5056
Chrome on Android solved it with a stop gap where PWA updates were automatic if the visual difference between the downloaded icon and the local icon was less than 10%.
5157

52-
## Problem: Developers have no control over when the update dialog may show up
53-
54-
The dialog shows up whenever Chrome sees the new manifest & detects changes. Developers have to accept that every change to security sensitive members could trigger this. They cannot, for example, make a number of incremental changes, and then trigger one update dialog at the end once they are all done.
55-
5658
# **Goals**
5759

58-
The current manifest update process gets the job done, but it could be better in a way so that the problems above can be fixed:
60+
The current manifest update process gets the job done, but if it could be [specified properly](https://github.com/w3c/manifest/issues/384) to know when that should happen and be backwards compatible, it would certainly help developers. As such, the goals to solve are:
5961

60-
* [**Consistency**](#consistency): Provide a consistent way to detect when a manifest update should happen.
62+
* [**Developer control**](#devc): Support developers to allow them to update their installed experiences:
63+
- Do not negatively affect developers who do not change their icon urls.
64+
- Empower developers to choose when to update their installed experiences.
6165
* [**Preventing unnecessary user interruption**](#useint): Users should not see an update dialog more than necessary to confirm security-sensitive changes.
62-
* [**User agent flexibility**](#uaf): It should be possible for users agents to use their judgement to block updates for known bad sites, allow known trusted apps to update without UX, or allow tiny visual changes to icons without requiring UX.
63-
* [**Developer control**](#devc): Developers should have more control over when the update dialog may show to users.
66+
* [**Consistency**](#consistency): Provide a consistent way to detect when a manifest update should happen, which can be implemented across all user agents.
67+
* [**User agent flexibility**](#uaf): It should be possible for user agents to use their judgement to block updates for known bad sites, allow known trusted apps to update without UX, or allow tiny visual changes to icons without requiring UX.
6468
* [**Reduce network traffic**](#traffic): Unnecessary network traffic should be minimized.
6569
* [**Prevent manifest id foot-gun**](#footgun): Encourage developers to set the manifest 'id' field, preventing a known [foot-gun](https://github.com/w3c/manifest/issues/1148).
6670

67-
# **Proposal: Introduce 'update\_token', ignore icon changes by default**
71+
# [**Proposal: Introduce 'update\_token', ignore icon changes by default**](#proposal)
6872

69-
The existence and non-existence of the `update_token` field will be used to trigger manifest updating logic, based on the following guidelines:
73+
The proposal is to introduce a new field in the manifest called `update_token`, whose existence (and non-existence) will be used to trigger manifest updating logic, based on the following guidelines:
7074

7175
* `update_token` is parsed if-and-only-if an 'id' field is set. This helps solve the goal of preventing the [`manifest id foot-gun`](#footgun).
7276

77+
This has already been discussed extensively in [TPAC 2022](https://www.w3.org/2022/09/13-webapps-minutes.html#t02) and [TPAC 2023](https://docs.google.com/document/d/1QDqllh8inOcIkTrblERm4HRKYh8Ce9Lu5S7WhOygs_0/edit?tab=t.0#heading=h.sg3uxnf61udd), with consensus received from developers and WebKit.
7378

7479
```
7580
@@ -84,6 +89,10 @@ The existence and non-existence of the `update_token` field will be used to trig
8489
8590
```
8691

92+
## Pre-requisites:
93+
94+
- An app corresponding to the manifest has already been installed.
95+
8796
## Token based update detection
8897

8998
* If `seen_manifest.update_token` and is changed from the `saved_manifest.update_token,`then a manifest update is triggered.
@@ -92,28 +101,55 @@ The existence and non-existence of the `update_token` field will be used to trig
92101

93102
## Default (non-token-based) update detection
94103

95-
Without the presence of an `update_token` in the manifest, **ONLY** icon updates will be allowed if there are changes in the icon url specified in the manifest.
104+
Without the presence of an `update_token` in the manifest, **ONLY** icon updates will be allowed if there are changes in the icon url specified in the manifest. This is similar to the behavior shown by [Cache-Control:Immutable](https://caniuse.com/mdn-http_headers_cache-control_immutable). The reason why the `Cache-Control` is not being used is the absense of backwards compatibility with existing PWAs on Android, where updates can only be triggered by changing the icon bitmap and not the url.
96105

97106
## Behavior
98107

99-
The below table introduces all possible combinations of behavior that can happen based on the status of the `update_token` field in `seen_manifest` or in `saved_manifest.`
108+
The below table introduces all possible combinations of behavior that can happen based on the status of an `existing update token` that is in the saved manifest vs a `new update token` that is newly seen in the manifest.
100109

101-
| saved ↓ seen → | “foo2” | “foo” | unspecified |
102-
| :---: | :---: | :---: | :---: |
103-
| **“foo”** | Token based | No update | Token-based |
104-
| **unspecified** | Token based | Token based | Non token based |
110+
![Update behavior](./images/proposed-update-behavior.png)
105111

106-
### Pre-requisites:
112+
## Future Considerations
107113

108-
- An app corresponding to the manifest has already been installed.
114+
### Javascript API for developers
115+
116+
Introducing a javascript API similar to [`beforeinstallprompt`](https://wicg.github.io/manifest-incubations/#beforeinstallpromptevent-interface) would provide developers with more fine grained control over when to trigger an update for their API (or even put UX) on their site to trigger the update process. For our proposal, let's call it `appupdateprompt`.
117+
118+
```
119+
let deferredUpdatePrompt;
120+
window.addEventListener('appupdateprompt', (e) => {
121+
e.preventDefault();
122+
// Save the event to trigger it later.
123+
deferredUpdatePrompt = e;
124+
// Show customized update prompt for PWA.
125+
showAppUpdateDialog();
126+
});
127+
```
128+
129+
The developer can then choose to tie it to an update button on their UX:
130+
131+
```
132+
// Gather the data from custom update UI
133+
updateButton.addEventListener('click', async () => {
134+
deferredPrompt.prompt();
135+
// Find out whether the user confirmed the installation or not
136+
const { outcome } = await deferredPrompt.outcome;
137+
// Act on the user choice, as if the outcome is either `accepted` or `dismissed`
138+
if (outcome === 'accepted') {
139+
console.log('Update UX accepted');
140+
} else if (outcome === 'dismissed') {
141+
console.log('Update UX dismissed');
142+
}
143+
});
144+
```
109145

110146
# **How does this solve the problem?**
111147

112148
Let’s review the goals again to see how this proposal meets them:
113149

114-
> Goal: [`Consistency`](#consistency)
150+
> Goal: [`Consistency`](#consistency), [`User Agent Flexibility`](#uaf)
115151
116-
The presence of a different value of `update_token` compared to the one saved, and icon urls changing are the only 2 use-cases that can trigger a manifest update.
152+
The presence of a different value of `update_token` compared to the one saved, and icon urls changing are the only 2 use-cases that can trigger a manifest update. Since this will be specified in the manifest, user agents can choose to implement their own behavior around this.
117153

118154
> Goal: [`Developer Control`](#devc), [`Preventing unnecessary user interruption.`](#useint)
119155
@@ -125,6 +161,17 @@ The most network heavy traffic is downloading icons, which will only happen when
125161

126162
# **Alternatives considered**
127163

164+
## Use a `version` field to trigger manifest updates
165+
166+
Add the concept of versioning to the web app manifest, so that the developer can change "versions" of their installed experiences to trigger updates. This has been proposed earlier in the manifest spec multiple times (like [manifest#1036](https://github.com/w3c/manifest/issues/1036) and [manifest#1157](https://github.com/w3c/manifest/issues/1157)).
167+
168+
Pros:
169+
- This would also help support this [FR about changelogs](https://github.com/w3c/manifest-app-info/issues/1).
170+
171+
Cons:
172+
- The term is highly overloaded, and it is [hard to get consensus on the data type](https://github.com/w3c/manifest/issues/446#issuecomment-904359501) and what its purpose is. Compared to that, `update_token` is highly confined to a specific use-case, and is simpler to reason about.
173+
- Leads to complications around supporting a lot of things like [version downgrades](https://github.com/w3c/manifest/issues/446#issuecomment-905725612), upgrades as well as [ overall interpretation of the field](https://github.com/w3c/manifest/issues/1036).
174+
128175
## Allow end users to ignore updates
129176

130177
End users can turn off “updates” for their installed app from the settings page of their app.
@@ -140,12 +187,6 @@ Cons:
140187

141188
While this solution is simple to implement, it breaks existing update behavior, and is also cumbersome for developers, who would have to update where they serve their manifest from every time a change is made.
142189

143-
## **Future Considerations**
144-
145-
### Allow developers to use javascript to trigger a pending update
146-
147-
This proposal allows developers to control when an update happens in general for users of an old version, but not at a specific time in the user experience of their site. In the future a javascript API could be used similar to the `beforeinstallprompt` API, allowing the developer to put UX on their site to trigger the update dialog.
148-
149190
# **Notes**
150191

151192
- Since [any website is an installable application](https://www.w3.org/TR/appmanifest/#installable-web-applications), if a user agent allows installation of a site that never specified an explicit manifest, update can still occur if the manifest ids matches.

0 commit comments

Comments
 (0)