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

Clarify circumstances in which BeforeInstallPromptEvent.prompt() may be called #691

Closed
mgiuca opened this issue Jun 14, 2018 · 9 comments · Fixed by #836
Closed

Clarify circumstances in which BeforeInstallPromptEvent.prompt() may be called #691

mgiuca opened this issue Jun 14, 2018 · 9 comments · Fixed by #836

Comments

@mgiuca
Copy link
Collaborator

mgiuca commented Jun 14, 2018

Currently a few issues:

  1. Chrome requires prompt() to be called on user gesture. This isn't in the spec. Is this something we can just require in the spec, or can we say that the user agent MAY require a user gesture?
  2. Neither Chrome nor the spec requires preventDefault() to be called before prompt(). Consider this code (assuming the #install_app button is disabled on load):
addEventListener('beforeinstallprompt', e => {
  document.querySelector('#install_app').disabled = false;
  stashed_bip = e;
});

document.querySelector('#install_app').addEventListener('click', async () => {
  console.log(await stashed_bip.prompt());
});

It doesn't call preventDefault, which means if you have a standards-compliant browser that shows an automated prompt, the above code works this way:

  1. The UA fires the beforeinstallprompt event.
  2. The beforeinstallprompt event handler enables the "Install" button.
  3. The UA shows an automated prompt, and the user accepts or dismisses it.
  4. The user clicks the still-active "Install" button.
  5. prompt() immediately resolves with the result of the automated install banner, without showing a second prompt.

This is a bad user experience because they are left with an enabled, but ineffective Install button.

However, the above code runs perfectly well in a browser that does not use automated install prompts, such as Chrome.

Suggested changes:

  1. Require a user gesture for prompt(). (Are there any UAs that implement BeforeInstallPromptEvent.prompt() that don't require a user gesture?)
  2. I think we need to disassociate the automated install prompt with BeforeInstallPromptEvent. UAs are still allowed to show an automated install prompt, and may fire BIP at the same time as showing the automated prompt. But calling prompt() from inside BIP would require the UA to show a second prompt, even if an automated one was already shown. prompt() wouldn't just return the result of the previously-shown automated prompt. You would still be able to use preventDefault to cancel some automated prompts (see below). There would be no need to use preventDefault before calling prompt, but sites may still wish to do this.

This gives UAs a couple of options:

  1. Don't ever show an automated prompt; dispatch the BeforeInstallPromptEvent, requiring the site to opt in to showing a prompt.
  2. Show an automated prompt, and do not implement BeforeInstallPromptEvent. The prompt is considered part of the user agent's user interface, not under the control of the developer (no different to any other affordance offered by a user agent). Firefox today
  3. Show an automated prompt, and independently, dispatch the BeforeInstallPromptEvent (perhaps at different times or under different circumstances). This is just a combination of the previous two options. The automated prompt might look quite different to the site-triggered prompt (e.g., being smaller or more subtle). In this approach, using preventDefault on the BeforeInstallPromptEvent would have no effect, since it is independent of the automated install prompt. Chrome today
  4. Dispatch the BeforeInstallPromptEvent, and if it is not cancelled, show an automated prompt. In this approach, using preventDefault would stop the automatic prompt from appearing. User agents that adopt this approach would need to show a second prompt if the event's prompt() method is called (otherwise, the site might show an "Install" button that does nothing when clicked). Chrome from 2017

Edit: Updated the descriptions above to be clearer (based on text in the spec draft).

The above suggestion, I believe, will be compatible with Chrome and Firefox today, and avoid the awkward compat issue with any future browsers (or old versions of Chrome) highlighted above.

@jungkees does Samsung Browser behave in a way compatible with the described changes?

@dominickng @marcoscaceres @kenchris

(I can rework the described changes in the form of a pull request if it's unclear.)

@jungkees
Copy link

@mgiuca, I'm not at Samsung now. @poshaughnessy and @romandev may be able to answer or route the question.

@mgiuca
Copy link
Collaborator Author

mgiuca commented Jun 14, 2018

@dominickng and I worked out three distinct proposals we could apply to the spec (I'm referencing UA Options 1, 2, 3 and 4 from the "This gives UAs a couple of options" list above).

Proposal 1

Allow automatic prompt to be cancelled by preventDefault. But prompt can show a second prompt, after the automatic prompt completes. This is what I propose above, and implemented in #692. This allows UAs to choose between Options 1, 2, 3 and 4 above.

Pros: Most flexible for user agents. preventDefault still works in UA Option 4, but not in UA Option 3. Developers who forget to call preventDefault will still have a functional Install button in all UAs that fire BeforeInstallPrompt (UA Options 1, 3 and 4).

Cons: If UA Option 4 is rare, developers may not know they have to call preventDefault to suppress the automated install prompt, which may be more intrusive in UA Option 4 because it's preventable. preventDefault may or may not work.

Proposal 2

Completely detach BIP from automated prompt. preventDefault does nothing (BIP is no longer cancellable). Automated prompt cannot be suppressed by developer (it is simply considered part of the browser UI). This allows UAs to choose between Options 1, 2 and 3 above. Developers do not need to call preventDefault.

Pros: Simple for developers and user agents. BIP is now fully misnamed, but at least it has clear semantics: it just controls manual prompting, which is unrelated to automatic prompting. This is the way we are heading with Chrome (with our minimalistic automatic prompt explorations; we are no longer tying that to BIP).

Cons: UA has no option to show an intrusive automatic prompt which can be suppressed by the developer. Must design a minimalistic automatic prompt instead. Developers may be upset that they are unable to suppress the automatic prompt (but this is already the case with UA Option 3).

Proposal 3

preventDefault is required before using prompt (even if there is no automatic prompt). UA Option 4 is now a choice of auto or manual (you can't have both).

Pros: Most flexible for user agents, without the weirdness of UA Option 4's double prompting from Proposal 1.

Cons: Use of prompt requires a superfluous call to preventDefault which may not make sense in UA Options 1 and 3 (confusing developer experience), especially since no known UAs will take Option 4. Essentially, for legacy reasons.

Conclusion

Proposal 2 is the simplest with the least rough edges. We should do this, unless there are any UAs that really want to take Option 4 (a suppressible automatic prompt).

@mgiuca
Copy link
Collaborator Author

mgiuca commented Jun 14, 2018

@jungkees ah thanks for the heads up.

@kenchris
Copy link
Collaborator

Adding @andreasbovens who is PM on the Firefox PWA support

@andreasbovens
Copy link

andreasbovens commented Jun 14, 2018

From a quick reading, it seems indeed like proposal 2 is best here. Looping in @marcoscaceres for his take.

@madmoizo
Copy link

madmoizo commented Jul 26, 2018

From proposal 2:

Developers may be upset that they are unable to suppress the automatic prompt (but this is already the case with UA Option 3).

Totally agree. As a web author, I started some tests after chrome post and I'm
already upset :)

To me, UA components should not (automatically) invade webapp land. What is the downside of the option 1 (opt-in) ?

@mgiuca
Copy link
Collaborator Author

mgiuca commented Jul 30, 2018

We must carefully distinguish User Agent Options (the Options 1–4 above) and Spec Proposals (the Proposals 1–3 above). Here, we're just debating the spec proposals, which are three different ways we could go with the spec requirements, and then UAs would have (in any proposal) a number of Options available.

@frlinw You're arguing for a particular UA option (1) but that's a debate you need to have with individual browser manufacturers (including me, on Chrome, but not here). We can't mandate a particular UI in the spec, only the requirements around the API. Note that all 3 Proposals allow both Options 1 (developer opt-in) and 2/3 (automated prompt not linked to BeforeInstallPrompt event).

We can't specify that browsers are not allowed to show an automated prompt not linked to the BeforeInstallPrompt event, because that's browser UI and they can do anything they want.

Now putting on my browser manufacturer hat (Chrome):

To me, UA components should not (automatically) invade webapp land. What is the downside of the option 1 (opt-in) ?

It's mainly that most sites aren't currently using BeforeInstallPrompt, and we (browser manufactures) still want to let users know that it's installable. I agree the current infobar that appears along the bottom of the screen in Chrome for Android is a bit heavy-handed, and we are currently exploring ways to make it a more subtle icon in the address bar (as Firefox has today). That "add to home screen" icon in the address bar, as well as the "add to home screen" menu item, are essentially the same thing as an "automated prompt", in that they are install UI shown by the browser without the developer's explicit request, just a lot more subtle.

@madmoizo
Copy link

madmoizo commented Jul 30, 2018

Must design a minimalistic automatic prompt instead

I had the mini-infobar in mind but if it's a component in the UA land (Indeed, I saw it here), obviously it wont be an issue and the opt-in does not make sense.
I consider that the rendered content is not a part of the UA interface so if a UA component invade the content space, the spec should give the possibility to control it. That's why I was for the option 1, but as you said, it's all about UA responsibility.

Just a last thing, I still don't understand how option 1 (opt-in) can be compatible with option 2 & 3 (auto) in Proposal 2. Is that mean the opt-in feature wont be described as a part of the spec but UA can implement it if they want ?
Option 1

Don't ever show an automated prompt

Proposal 2

Automated prompt cannot be suppressed by developer

@mgiuca
Copy link
Collaborator Author

mgiuca commented Jul 31, 2018

I had the mini-infobar in mind but if it's a component in the UA land ... obviously it wont be an issue and the opt-in does not make sense.

It could be either. From a spec standpoint, certainly the infobar versus an icon in the address bar are the same (they're both non-page content so they're outside the realm where the spec can dictate UA behaviour).

I consider that the rendered content is not a part of the UA interface so if a UA component invade the content space, the spec should give the possibility to control it. That's why I was for the option 1, but as you said, it's all about UA responsibility.

The thing is that Chrome, at least, shows infobars "invading the content space" all the time, for many things which are not specced, and don't give developer control. For a few examples:

  • Offering to translate a page if the browser detects a different language.
  • Offering to turn on data saver if the page is using too much bandwidth.
  • Offering to render the page better for mobile, if the page seems to not be designed for mobile.

The infobar to install the app is fairly in-line with other parts of the Chrome UI and I believe all browsers have similar features. Having said that, we recognise that it's a bit heavy-handed to show this all the time so we're looking at more subtle UI.

Just a last thing, I still don't understand how option 1 (opt-in) can be compatible with option 2 & 3 (auto) in Proposal 2. Is that mean the opt-in feature wont be described as a part of the spec but UA can implement it if they want ?

Yeah, Proposal 2 just means that BeforeInstallPrompt is only used to control manual prompting, and isn't tied to automatic prompt at all. Thus:

  • Cancelling the event does not suppress any automatic prompt that the browser may or may not show.
  • The browser is not required to fire BeforeInstallPrompt before showing the prompt.

Automatic prompts are purely a UA-specific feature which the spec says nothing about, normatively (contrary to the spec today which explicitly talks about automatic prompts). A UA could choose to never show an automatic prompt (Option 1) or to show one, but not tied to the BeforeInstallPrompt event (Option 2 or 3).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants