MicrosoftEdge / MSEdgeExplainers

Home for explainer documents originated by the Microsoft Edge team
Creative Commons Attribution 4.0 International
1.31k stars 216 forks source link

[Web Install] Declarative vs Imperative version of cross-origin Web Install #893

Open diekus opened 1 month ago

diekus commented 1 month ago

Web Install is an imperative (JS) API. Is this better than declarative? What are the reasons for this?

photopea commented 1 month ago

I think everything would be so much easier if installing was as simple as writing

<a href="//www.google.com" target="_install">Install Google</a> 

and after clicking it, a browser would offer the user to install Google.com (the icon could be taken from the "href" URL from some tag, or its manifest.json). You would be able to install a webapp from an online store of webapps, without even opening a webapp.

I think a browser shouldn't have any trouble preventing the abuse of this mechanism. Just like browsers prevent the abuse of alert() for the past 30 years. Why does everything have to be done in the most complicated way?

diekus commented 1 month ago

hola @photopea! Thanks for the feedback. We definitely want a declarative entry point for the Install API. It is not discarded, and I think it's a perfect complement to the imperative version. We've certainly discussed a declarative version of Web Install, and for the first version we want to push out we've carefully considered how to avoid having multiple versions of the same app installed. You can see these slides that summarize a bit the complexity.

Specially for cross-origin installs, which is where this issue is relevant, we want to make sure that only web apps are allowed to be installed. This implies having a mandatory manifest_id and reinforcing the concept of an install_url as well. Potentially this could all be stated in a declarative way as follows:

<a href="//www.webapp.com" target="_install" app_id="<app id>" install_url="<install url>">Install Web App</a>

Even declaratively things start getting a bit more complex if we want to navigate away from a world where end users have N versions of the same app where N-1 of them aren't being able to be updated by the developer.

Working on the declarative approach allows us to get feedback for a navigator.install(<app id>,<install url>); and gives plenty of flexibility for developers to for example, query if an origin has permission to install apps, and then proactively remove the install UX and display a link using JS.

Nonetheless, I 100% agree and want a declarative version of this API, and I don't see any reason why both, declarative and imperative versions can't coexist. Appreciate the feedback and further discussion you might have on the topic!

cc @dmurph @amandabaker

diekus commented 1 month ago

@photopea following up on this, do you have any use cases you require with the install API that the shape of the API wouldn't be able to fulfill? Please let me know.

dmurph commented 1 month ago

Good to document this idea. I think it could compliment things if it's needed. I don't want to block the existing more flexible API from shipping on this though. This is a good follow-up if there is enough demand.

Cases where this might not be as suited:

photopea commented 1 month ago

I think "installing a webapp" should not be anything more than adding a website into bookmarks, but a bookmark will be on the homescreen, with a special icon, which opens the website without a brower UI. Manifest files should be optional.

I think it is a very wrong path to treat installed apps differently than websites, and to create a "new, parallel standard", making webapps which would exist "parallel" to websites, and developers would basically have to learn a new technology. I am afraid you want to turn "good old websites" into "Android", where apps would be extremely hard to get "verified" to be installed, and a website would require tons of effort to turn into a webapp.

So basically, an installed webapp should be a URL (similar to bookmarks). A specific URL can be "installed" (added to homescreen) just once.

dmurph commented 1 month ago

I think that generally matches how we are treating them as well. Some things 'only' make sense when you have OS integration, like handling files now can work (e.g. photopea can be a file handler for someone double clicking on .png file on their OS). And then now it's an OS entity, let it do things like specify the little 'shortcuts' / 'jumplist' things that appear when you right click on the dock icon on window/mac. But otherwise - yeah it's just a website / tab in a different dressing.

photopea commented 1 month ago

I have a JSON with web games, that I have created. I want to make a simple site, which loads this JSON and lets the visitor play these games, I made this: photopea.com/games.

I want to let the user add an icon of each game to their homescreen. Each game has a different URL, e.g.

My PHP generates a custom manifest.json for each of these games (since Chromium doesn't allow it to be generated dynamically within a webpage). However, when I install one game, it considers all games to be installed. Is there a way to overcome this? This link says that it is discouraged to have multiple PWAs on the same domain.

I think that each URL should be allowed to be installed. The installation should be initiated by a website (by a visitor), and not by a web browser (and sending the "beforeinstallprompt" event). A browser should look for manifest.json only after the installation has been requested.

The current limitations do not help anyone, they only overcomplicate everything.

dmurph commented 1 month ago

@photopea said:

However, when I install one game, it considers all games to be installed. Is there a way to overcome this?

What considers all games to be installed? You may have an issue with your 'scope' variable - you should make sure that the scope of the apps do not overlap. Nested scopes are highly discouraged - in your example, if photopea is installed, then the browser will not promote your 'nested' app games as those urls are controlled by photopea. In the future, we want to allow developers to have more control over their scope (see https://github.com/w3c/manifest/issues/996 and https://github.com/WICG/manifest-incubations/issues/105) which helps here.

As that article mentions - there are multiple reasons why it can be confusing and a struggle to have apps on the same origin, but especially nested. I recommend making a new origin for your games. Then you won't have weird things like user settings affecting both Photopea and the games (user zoom levels), local storage sharing, permissions, etc. And those games won't 'open in' an installed Photopea PWA as if they were part of that app (unless you want that).

Finally - we do have a feature in Chrome that allows you to create a 'shortcut' to a site - see how "Create Shortcut" works now. This currently just launches in Chrome - it's like a bookmark but on the desktop. We have gotten feature requests to make this an API that an installed PWA can use to create shortcuts on the desktop that deep link into the PWA. Then - there won't be multiple apps installed, but there can be different entry points on the OS. Are you interested in that feature?

@amandabaker I think we should consider preventing install if there is an app already installed that controls the start_url of the app, or the current document in the same-origin case. This is mostly to prevent this kind of use, which hinders the UA's ability to promote installation / know which urls belong to which app (and other problems cited in here. Then, when we solve https://github.com/w3c/manifest/issues/996, devs can make sure the places they need to installed (if nested) fall outside of the outer app's scope.

photopea commented 1 month ago

I was talking about the current implementation of PWAs in Chromium-based browsers. E.g. these two games:

Each has a different manifest file, but if I install the first game and open the second one, the second game is not available to be installed anymore. Could you tell me what scopes should I give to these games?

dmurph commented 1 month ago

It looks like your manifest is here?

(hint: check out chrome://web-app-internals to see properties of your web app).

I would probably recommend a static file, but that works. It looks like you set the start_url to be "//www.photopea.com/games/peasmaker". When parsing this using the spec algorithm, that makes the 'scope' of your app to be "www.photopea.com/games". That is why all URLs under that are controlled by the one game.

Fix options:

I also strongly recommend setting an 'id' field to uniquely identify your app. For backwards compatibility, I recommend setting it to /games/peasmaker (as recommended by dev tools) to make sure any manifest updates will also apply to any existing app installations.

photopea commented 1 month ago

I have tried setting the scope to the start_url, but it still works as before :( Could you write me to ivan.kuckir@gmail.com ?