Implement PWA scope attribute for GeckoView-based standalone mode

RESOLVED FIXED

Status

()

Firefox for Android
General
RESOLVED FIXED
a year ago
3 months ago

People

(Reporter: esawin, Unassigned)

Tracking

(Blocks: 1 bug)

51 Branch
All
Android
Points:
---
Dependency tree / graph

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

a year ago
Implement scope attribute [1] for GeckoView-based standalone mode PWAs.

A possible solution involves adding a navigation delegate to allow for loadUri handling.

[1] https://w3c.github.io/manifest/#dfn-navigation-scope
Bug 1364052 should be considered here as well
Blocks: 1285858
Hi Anthony, I'm just wondering whether there is a UX spec for this yet?

In the current implementation (behind a pref) in Firefox Nightly all navigations stay inside the standalone browsing context of an installed web app with no URL bar visible. This is a security problem because the user is unaware when they have left a trusted origin.

Dale proposed a UI design in https://bug1285858.bmoattachments.org/attachment.cgi?id=8815744 in which the URL bar appears and disappears as you leave and enter the scope of an installed web app and there's a global gesture to show the URL bar at any time. This is a great design but unfortunately is probably difficult to implement in practice within the constrains of the Android OS.

Having previously implemented web app manifest scope in Firefox OS, and contributed to the W3C spec, I've come across some tricky areas and questions which aren't really answered by the spec and in which existing implementations in Chrome, Opera and Samsung's browser currently interpret differently.

Some quirks:
* The spec says that if no scope is provided by the manifest, the default scope is "unbounded". That means navigations to any URL, including at other origins, are considered part of the app. Chrome implements a "soft boundary" when leaving the origin of the app and displays a mini URL bar to make the user aware they have navigated to a different origin but stays in the standalone display mode. I believe Opera opens out-of-scope URLs in a new browser tab so the user has full access to browser features.
* Technically an installed web app could "capture" navigations within its scope when following hyperlinks in the browser so that the URL opens in standalone display mode rather than browser display mode. No browser currently implements this but seamless deep linking between installed web apps could be a really powerful feature.
* In standalone display mode I think all current implementations hide the URL bar and browser menu, but this makes it impossible to access, bookmark or share the current URL of the page. This is why Dale suggested a gesture to access a URL bar from standalone mode, which as far as I know no other browser currently implements
* Many web apps (e.g. Google properties) redirect to a different origin for user authentication (e.g. mail.google.com -> accounts.google.com). Depending on the implementation of standalone display mode this can end up being quite a disjointed user experience.
* Hyperlinks in an installed web app can specify target=_blank to open the link in a new tab/window. The implementation needs to know how to handle this. It should ideally open URLs which are within the scope of an installed web app in the web app's standalone window and URLs which aren't within the scope of an installed app in a new browser tab (see bug 1394766).

We managed to solve most of these issues in Firefox OS because we had control over the whole OS user experience so we had a universal URL bar which collapsed down into the status bar in standalone display mode but could always be expanded with a tap. This made navigating into and out of the URL scope of web apps quite seamless. This is much trickier to achieve within the constraints of the Android OS so different solutions are likely to be needed.

Other notes:
* On Firefox "Add to homescreen" is currently buried under the "Page" section, on other browsers it's a top level menu item. This is a bit confusing on Firefox because add to homescreen with a manifest really applies to the whole web app, not just the current page. It also makes the feature less discoverable (especially as we don't have app install banners or "ambient badging" yet).
* Android 8 may break the current "Add to Homescreen" feature altogether as Chrome is moving to WebAPK which isn't currently available to other browsers! https://medium.com/@firt/android-oreo-takes-a-bite-out-of-progressive-web-apps-30b7e854648f
Flags: needinfo?(alam)
If you're interested, see the "Pinning Sites" section of the Pin the Web specification to see how we solved some of these issues in Firefox OS https://docs.google.com/presentation/d/1t39xMPHQYzQ17KcIfDwcsMR4S21DCM_3YcIUnHbFwzU/pub#slide=id.gc510677ad_0_18

Comment 4

7 months ago
Hey Ben!

Sorry for the delay, but I'm going to NI' Harly here because members of his pod have been handling this for Fennec more recently than I have.
Flags: needinfo?(alam) → needinfo?(hhsu)

Comment 5

7 months ago
Also cc'ing Jack and Tori from Taipei

Comment 6

7 months ago
Hi there, 
Mark from my team (which I Ni here)is working on the PWA UX, I also added Joe & Wesley to put this under their radar~
Flags: needinfo?(hhsu) → needinfo?(mliang)
Hi Ben!

Thanks for the information, currently the design spec only covers the "add to home screen" action and not yet considering the experience within the added web apps. Will need Joe to take a look and see if we want to include this into our scope.
Flags: needinfo?(mliang) → needinfo?(jcheng)
Ben, have you seen https://bugzilla.mozilla.org/show_bug.cgi?id=1389236? External links will be opened in a custom tab. This is an elegant solution, finding a middle ground between Chrome's mini URL bar, and Opera's full browser UI.
Flags: needinfo?(bfrancis)
This is working.
Status: NEW → RESOLVED
Last Resolved: 7 months ago
Resolution: --- → FIXED
Hi Andreas,

This is definitely better than doing nothing, it means that the user knows when they've left the scope of the app and can see the origin of out-of-scope web pages which is important for security.

However, this does mean that you will get a different user experience for the same web page depending on where you navigated to it from. No hyperlink from a web app will ever open in the full Firefox browser so you'll be limited to the subset of browser features available in a custom tab. Also, a deep link (https://w3c.github.io/manifest/#deep-links) into an installed app won't open in the app (i.e. in its own standalone or fullscreen display mode), it will either open in a custom tab on top of the source app or stay in the browser depending on where you are navigating from. My personal preference would be to support seamless deep linking in both directions - that is URLs within the scope of an installed web app always load in the app (i.e. in a standalone or fullscreen display mode where specified) and URLs outside the scope of any installed app always open in the browser (in an ordinary browser tab).

What is being used as the default scope if one isn't provided? The W3C specification says that the default scope should be "unbounded" (https://w3c.github.io/manifest/#navigation-scope). That would mean that if no scope is provided in the manifest then no URLs would load in a custom tab.

With my inexperienced scanning of the Fennec source code it appears that the default scope is being set to the start_url minus one path segment (https://github.com/mozilla/gecko-dev/blob/master/mobile/android/base/java/org/mozilla/gecko/webapps/WebAppManifest.java#L190). That's pretty arbitrary and not compliant with the W3C spec. It does mean that that navigations to another host will always open in a custom tab (which is arguably better for security) but it also means that some URLs will be considered out of scope which aren't supposed to be (e.g. http://foo.com/bar with a start URL of http://foo.com/bar/baz/start.html). It will also provide a worse user experience for web apps which intentionally span multiple origins (quite a common practice in Asia), but this isn't something that the current W3C specification caters for very well anyway.

Also note that isInScope() (https://github.com/mozilla/gecko-dev/blob/master/mobile/android/base/java/org/mozilla/gecko/webapps/WebAppManifest.java#L208) appears to be comparing host rather than origin (scheme + host) which also technically isn't compliant with the spec as an http:// URL should be out of scope for an https:// scope.

I haven't been able to test this on my Pixel running Android 8, is it still disabled on Android 8? I see the Add to Home Screen in the Page menu which opens the page in Firefox, but not yet the new add app to homescreen implementation with the icon in the URL bar I've seen mockups for.
Flags: needinfo?(bfrancis)
> No hyperlink from a web app will ever open in the full Firefox browser

This depends on user preference. If the user turns off Custom Tabs, links will open in full Firefox instead.

>  deep link (https://w3c.github.io/manifest/#deep-links) into an installed app 

Deep linking is indeed not supported yet. WebAPKs are one way to make this happen, but we don't support those yet. We're also investigating if there are other ways to implement deep links.

> That would mean that if no scope is provided in the manifest then no URLs would load in a custom tab.

Note https://w3c.github.io/manifest/#navigation-scope-security-considerations
where the spec says: "When the navigation scope is unbounded and a display mode other than browser is being applied, it is RECOMMENDED that user agents signal to the end-user when security and/or privacy sensitive navigations occur." This "signaling" can be interpreted as loading the content in question in a custom tab.

> some URLs will be considered out of scope which aren't supposed to be

@snorp?

> is it still disabled on Android 8

Yup, for now it is. We're working on it. The new UI also hasn't landed yet.
Flags: needinfo?(jcheng) → needinfo?(snorp)
(In reply to Andreas Bovens from comment #11)
> > some URLs will be considered out of scope which aren't supposed to be
> 
> @snorp?
> 

In the example Ben gave, that's true. We could change the default scope to be the origin in order to avoid this. It's probably what most developers would expect, and more in the spirit of the clause Andreas references above. I'll file a bug.
Flags: needinfo?(snorp)
I filed bug 1405021 to change the default scope.
> We could change the default scope to be the origin

That was what I argued the W3C spec should say, although not a perfect solution. This isn't spec compliant and it's a bit of a fudge to combine it with the "signaling" of security sensitive navigations, but I do think it's an obvious default to choose.

Just a heads up, make sure that web apps which redirect to another origin to do authentication (e.g. accounts.google.com) still work with this implementation. They may not expect a new browsing context (i.e. the custom tab) to be created.
You need to log in before you can comment on or make changes to this bug.