w3c / manifest

Manifest for web apps
https://www.w3.org/TR/appmanifest/
Other
659 stars 162 forks source link

Scope: Allow developer to have more fine-grained control of app scope. #996

Open hanguokai opened 3 years ago

hanguokai commented 3 years ago

(I originally posted a related issue at manifest-incubations)

Although there is a scope concept in service worker and manifest file, for URLs in the scope, developers need a way to tell the browser which URLs can be regarded as the app and which URLs are not.

Why need to tell browser this information?

install launch

As shown in the screenshots above, Chrome address bar has install/launch icon for installing and launching the app. But not all URLs in the origin/scope should be regarded as the app. For example, help pages of the app should be opened as web pages in the browser, rather than load them into the app.

A core concept: whether a URL in the scope should be treated as the app.

alancutter commented 3 years ago

Do you want a way to remove URL paths from the app scope? Would it be reasonable to host those paths outside of the app scope instead?

hanguokai commented 3 years ago

Do you want a way to remove URL paths from the app scope? Would it be reasonable to host those paths outside of the app scope instead?

Simple answer: No

Chrome shows a launch icon in the address bar for all URLs in the scope after installation. I want to tell the browser which URLs can show, and which URLs can't show it.

The browser has a wrong assumption: all URLs in the scope can be opened in the installed app. The fact is:

For example:

If the browser did not have this launch icon, I would not file this issue.

alancutter commented 3 years ago

In that example it sounds like the scope should be app.html.

hanguokai commented 3 years ago

My Test

I did some tests, focusing on how to control the install icon and launch icon in the address bar.

Assuming that service worker's scope is /, thus it can control all URLs. But /manifest.json scope is /app.

URL(File) Show Install Icon(before install) Show Launch Icon(after install)
index.html include manifest.json Yes No
index.html not include manifest.json No No
app.html include manifest.json Yes Yes
app.html not include manifest.json No Yes
app.js or app.css No Yes
app.js or app.css if manifest's scope is /app.html No No

My Goal

index.html must show the install icon, but don't show the launch icon because it is a landing page(not the app itself). And app.html can show both install icon and launch icon. The launch icon should only appear for app files, don't appear for other files(like index.html and app.js).

My Conclusions

Browser use manifest file to determines whether the install icon will appear, regardless of whether current URL is in the manifest's scope or not.

Browser use string prefix matching (like url.startsWith(manifest-scope)) determines whether the launch icon will appear. So if the app is a multiple files app(not single file app), all app files should have a same and unique prefix.

@alancutter Could you confirm that the spec can guarantee these?

@tomayac I rarely see articles or documents that explicitly say these. I think developers might be interested in these knowledge.

alancutter commented 3 years ago

It should be noted that the install and launch icons mentioned here are behaviours of Chromium and aren't part of any spec.

My Goal

index.html must show the install icon, but don't show the launch icon because it is a landing page(not the app itself). And app.html can show both install icon and launch icon. The launch icon should only appear for app files, don't appear for other files(like index.html and app.js).

It sounds like you want your manifest.json to contain:

{
  "start_url": "app.html",
  "scope": "app.html"
}
hanguokai commented 3 years ago

Thank you for your reply, but my purpose is not to solve a personal problem.

It should be noted that the install and launch icons mentioned here are behaviours of Chromium and aren't part of any spec.

Currently, on desktop OS, only Chromium-based browsers support to install a PWA. From developers' perspective, we care about the process of install and launch the app, and how to control it. When I transformed a web app to an installable PWA, I was thinking about:

As you said, the spec does not define these, so I think this part needs to be considered in the specification, especially from the developer's point of view.

alancutter commented 3 years ago

That affects the structure of directories and file names.

You should put your app in a /app/ directory and make that the scope. /index.html can link the manifest and still be installable for the web app. Example: https://mulberry-phase-leopon.glitch.me/

hanguokai commented 3 years ago

The core problem is that the behavior of the launch icon and its relationship with the manifest's scope is not clearly defined in the specification. And only chromium-based browsers have this behavior. The spec only defines launching the app with start_url or shortcut urls. It is undefined whether other URLs can be used by the browser to launch the app.

hanguokai commented 3 years ago

I suggest that browser shows that launch icon in the address bar only when the current url is the start_url or shortcuts url. Because other URLs may not be appropriate to launch the app.

hanguokai commented 3 years ago

The manifest's scope member is a string that represents the navigation scope of this web application's application context. - Manifest Spec

The manifest format assist with this problem by allowing you to specify a "URL scope" for your application. This scope sets a boundary for an app. It can either be a domain or a directory within that domain. - Manifest Explainer

From the definition above, the manifest's scope is not used to define which URLs can be used to launch the app, but to delimit the boundaries of the app. It does not say that all URLs in the scope can be used to launch the app. So the launch icon in current chromium browser is a misuse, sometimes it is right, sometimes it is wrong.

alancutter commented 3 years ago

The core problem is that the behavior of the launch icon and its relationship with the manifest's scope is not clearly defined in the specification.

It sounds like you want to standardise manifest controls for Chromium's install/popout UI. The current title sounds like it's asking for the scope field.

hanguokai commented 3 years ago

It sounds like you want to standardise manifest controls for Chromium's install/popout UI. The current title sounds like it's asking for the scope field.

They are essentially the same issue. It depends on how to solve the problem.

hanguokai commented 3 years ago

I just looked at URLPattern. It might solve this problem. If browsers really wants to supply an "open" icon for users to launch the app, the manifest could add a new "entry_points" item, that defines a URLPatternList by developers for all entry points of the app. When user navigate to a matched entry point, browser show the open icon.

dmurph commented 1 week ago

See https://github.com/WICG/manifest-incubations/issues/105 as well.

dmurph commented 1 week ago

For compatability with different OS's (where we need to tell the OS which urls are part of the installed app and which aren't), we likely cannot use URLPattern.

Based on my memory - Android supports basic 'patterns' and advanced 'patterns'. iOS allows some patterns, and also 'excludes'.

@LuHuangMSFT FYI - maybe a good manifest issue to work in for making better scope control

benfrancis commented 1 week ago

I see there's renewed interest in refining how navigation scope is defined.

It's a decade old now, but a long time ago I did a study of URL scope in web applications from what were then the top web sites/web apps on the Chrome Web Store, Firefox Marketplace and Alexa Top 20.

Whilst that study is now very out of date, the proposed solutions derived from that report may still be useful.

Some factors to think about:

An example solution:

{
  "start_url”: “https://foo.com/foo",
  "scope": {
    "include": ["/foo", "/bar"],
    "exclude": ["/foo/baz", "/bar/qux"]
  },
  "stay_in_app": ["https://norf.com"]
}
mkruisselbrink commented 1 week ago

For compatability with different OS's (where we need to tell the OS which urls are part of the installed app and which aren't), we likely cannot use URLPattern.

I think this statement needs a bit more reasoning before we start inventing our own thing; one option would be to only allow some subset of the more generic URL pattern syntax (which is what the SW static routing API does as well, as that API does not want to allow arbitrary URLPatterns either). It is certainly possible that it doesn't make sense to describe the allowed scopes as a subset of URLPatterns, but I wouldn't dismiss URL pattern up front without first figuring out what functionality we actually want to support.

dmurph commented 1 week ago

@mkruisselbrink I agree - I haven't researched URLPattern closely enough to know if it is truly incompatible. Research is needed here, with an explainer, so we can see all options & what is possible per-OS, etc.

mgiuca commented 1 week ago

When URLPattern was defined, we worked with @wanderview to ensure it would be usable in Web App Manifest eventually - that was always the plan. (That's why the URLPattern spec has a section about using it in JSON.)

Acknowledged the difficulty of communicating to the OS the exact scope, but I don't believe this should restrict the way app scope is defined, since the OS interaction (OS-level link capturing) is just a small part of its utility. I think of the scope as being much more about when you're inside the browser/webapp ecosystem, deciding whether a given link should open in the browser or webapp. For most purposes, scope can be fully implemented as a URLPattern.

When it comes to registering the URLPattern with the OS, you could define a subset of the syntax that's designed to work with OS link capturing, but let the full syntax be used for internal navigation. (Though there can't possibly be a guarantee about what URLs can be supported by all possible OSes; that is outside the jurisdiction of a web spec.)

Also note the (intentional) precedence here: in the Manifest Incubations spec we defined the tab mode home scope using URLPattern, with the intention that the main manifest scope would follow. A lot of the hard spec work (and implementation, in chromium) has already been done there and can be generalized. Albeit, tab mode home scope does not need to be registered with the OS.

dmurph commented 1 week ago

@mgiuca I expect that an explainer proposing the solutions/alternatives here will explore what it would look like to have a URLPattern, and how that would work with different OS's (and expand on what, exactly, each OS supports). Then we'll be able to make a more informed decision.