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

Way to detect if a web app is installed #1092

Open
marcoscaceres opened this issue Jun 9, 2023 · 13 comments
Open

Way to detect if a web app is installed #1092

marcoscaceres opened this issue Jun 9, 2023 · 13 comments

Comments

@marcoscaceres
Copy link
Member

marcoscaceres commented Jun 9, 2023

The navigator.standalone attribute has been in iOS since forever and has the nice semantics in that, as a boolean value, it distinguishes between installed web applications and those running in the regular browser tab.

It's slightly unfortunate that "standalone" will mean "installed" (as per the spec's definition), and there is also "display-mode: standalone", but I think that's ok.

What do folks here think? @dmurph, @aarongustafson, would love to hear your thoughts!

See also this webkit bug.

@marcoscaceres marcoscaceres changed the title should we standardize navigator.standalone should we standardize navigator.standalone ? Jun 9, 2023
@karlcow
Copy link
Member

karlcow commented Jun 9, 2023

Previously #273

@mgiuca
Copy link
Collaborator

mgiuca commented Jun 9, 2023

This is the first I'm hearing of navigator.standalone.

Q: Is there a difference between navigator.standalone and matchMedia('(display-mode: standalone)').matches? Does navigator.standalone return true for other non-browser display modes like minimal-ui, fullscreen, and future ones like window-controls-overlay?

I would prefer to have some way to express that as a CSS MQ. I seem to be able to express it using matchMedia('not (display-mode: browser)').matches, which is a bit of a mouthful, but makes sense using existing APIs. It was difficult to come up with that, but we can document it on MDN and elsewhere.

It's slightly unfortunate that "standalone" will mean "installed" (as per the spec's definition)

I don't follow this (also, which spec?). If you use navigator.standalone on a browser tab inside an app scope, while that app is installed, it will still be false, right? So it doesn't mean "installed". Do you mean that it's unfortunate that it means "running in a separate window outside the browser" as opposed to "having display-mode standalone"? If so, yes, that's why I think it's OK to tell developers to use matchMedia('not (display-mode: browser)').matches to say exactly what they mean.

@mgiuca
Copy link
Collaborator

mgiuca commented Jun 9, 2023

Note from chatting with Marcos: Yes it basically is matchMedia('not (display-mode: browser)').matches but a small exception for fullscreen (because display-mode: fullscreen is weird).

dm: fullscreen is true when you're in the browser but fullscreen mode. But navigator.standalone is false in that case.

Further discussion:
It sounds like there is a good reason to have a definitive Boolean "yes or no: is this in an installed context?" (Which we currently almost-but-don't-quite have with the MQ).

Ideally such a thing would be itself a new MQ, not a JavaScript Boolean with somewhat the wrong name. So we can design a new MQ for it. But that aside, should we just standardize navigator.standalone because it's been around for so long, and have other browsers implement it, to avoid compat issues.

Matt will ask around internally to see if we have seen compat issues due to a lack of navigator.standalone.

@marcoscaceres
Copy link
Member Author

Having a corresponding media feature/query would be great, particularly given the use case is generally to control the web page's UI (generally to take away install buttons and instructions). It could be as simple as (standalone: yes)... which would be clear when used with @media (standalone: yes and display-mode: fullscreen) {...}. If we go forward with a CSS media feature, we should probably ping some of our CSS WG friends.

@tomayac
Copy link
Contributor

tomayac commented Jun 9, 2023

FWIW, it's been something iOS-focused web developers have depended upon and expected to be in Chrome DevTools' iOS device simulation mode, so I filed crbug/1197498 some time ago. I'm not opposed to standardizing it as a legacy feature.

The future is definitely non-ambiguous media queries where you can exactly express what you want to test for, which is why I created the WebKit bug.

If WebKit decides to report it, there should probably a differentiation between navigation controls on (corresponds to minimal-ui) and navigation controls off (corresponds to standalone).

@karlcow
Copy link
Member

karlcow commented Jul 2, 2023

Update here. Standardizing navigator.standalone creates a potential webcompat issue for people who want to detect iPad (or being iPad) and send links to the appropriate download/banner.

See mozilla/bedrock#13328

What happened?

Mozilla to detect the iPad Pro was using (pf.indexOf('MacIntel') !== -1 && 'standalone' in navigator)

So Safari 17 Desktop with navigator.standalone was identified as an iPad and instead to have a download link to a DMG file it was redirecting to the iOS Appstore.

Mozilla fixed it.
but a quick search online shows potential for more breakages.

So this is to keep in mind in the solutions that needs to be evaluated.

@dmurph
Copy link
Collaborator

dmurph commented Jul 6, 2023

One potential difference here, if you want an "is this installed" bit, is that display mode css media query is spec'd to be the current display mode, which includes 'fullscreen'. So if you have an installed app that you go fullscreen, then it'll be "standalone" -> "fullscreen" -> "standalone" (when you exit fullscreen).

This seems to really confuse developers, so I propose we have a signal that is something like "is this URL within scope of an installed app" signal (this allows it to work with Safari & Chrome's different implementations of isolation).

@marcoscaceres
Copy link
Member Author

@dmurph, that's an interesting re-interpretation and might work.

However, when you say "This seems to really confuse developers", what is "this" exactly? Can you clarify a bit?

@aarongustafson
Copy link
Collaborator

One potential difference here, if you want an "is this installed" bit, is that display mode css media query is spec'd to be the current display mode, which includes 'fullscreen'. So if you have an installed app that you go fullscreen, then it'll be "standalone" -> "fullscreen" -> "standalone" (when you exit fullscreen).

This seems to really confuse developers, so I propose we have a signal that is something like "is this URL within scope of an installed app" signal (this allows it to work with Safari & Chrome's different implementations of isolation).

Reminder: there's a lengthy discussion of an “installed” signal on the App Info spec: w3c/manifest-app-info#42

There is also the Client Hint for display modes proposal too (though that's more server side). Of course I'm also still super skeptical about the wisdom in relying on display modes as an indication of installation. I'd much prefer an explicit signal that you are, in fact, viewing the site in it's installed state (hence the discussion above).

I'm not entirely sure what's to be gained from having this. I'm not deadset against it, I guess I'm just not convinced of the value yet.

@marcoscaceres
Copy link
Member Author

Discussing with @dmurph, as an alternative:

@media (installed: yes and display-mode: fullscreen) {...}

And we keep the legacy:

navigator.standalone; 

As WebKit/Safari Web Apps are fully isolated (they are an entirely different user agent), there is no way of sharing "is this web app installed". For a site in a browser to know if a web app is (or was) installed would break the privacy model of Safari.

@aarongustafson
Copy link
Collaborator

For a site in a browser to know if a web app is (or was) installed would break the privacy model of Safari.

I can understand how, when compared to the web overall, this would be an issue, but this is not something shared by apps developed in Swift, even those that make use of the web view, right?

I'm also curious to know what Apple's specific privacy concerns are, especially if the check only applied specifically within the context of the installed app and not in a casual browsing (e.g., browser tab) scenario.

@marcoscaceres
Copy link
Member Author

marcoscaceres commented Sep 12, 2023

Action here is to float this with the CSS Working Group.

You say "installed" in cases where you wouldn't want to show an install button... has the user "installed" this web application.

Only applies to top-level navigable. This can't apply cross origin. Cross-origin must return false (or "no").

@marcoscaceres marcoscaceres changed the title should we standardize navigator.standalone ? Way to detect if a web app is installed Apr 10, 2024
@dmurph
Copy link
Collaborator

dmurph commented Apr 10, 2024

Feedback here: https://issues.chromium.org/issues/331692948#comment15

For us, with the PWA, we offer more UI options primarily to match the PC native app and provide additional control options, such as a refresh button, because we know users don't have access to browser tools.

As a small example, we always hide the website's navbar when a user is logged in on the PWA. This provides more screen real estate for the app since we understand that's the main focus. We prefer users not to see the logout and settings options, which are rarely used; instead, they have to click to show the side menu.

This is supportive evidence for an 'installed' attribute that can be media-queried.

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

No branches or pull requests

6 participants