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

Add the beforeinstallprompt and appinstalled events #441

Open
atjn opened this issue Jan 11, 2024 · 4 comments
Open

Add the beforeinstallprompt and appinstalled events #441

atjn opened this issue Jan 11, 2024 · 4 comments
Labels
enhancement New feature or request

Comments

@atjn
Copy link

atjn commented Jan 11, 2024

Hi and thanks for making this awesome project! I am a little sad to see that you are not interested in adding Fugu API's, as I think I might be able to contribute those to this project, but I don't think I have the time to write my own plugin from scratch that can do it.

I do however think that these events are relevant to this project because they specifically deal with PWA installation :)

Problem Description

Websites have no way of knowing that the browser sees them as "installable", and also have no way of integrating install buttons into their own UI.

Proposed Solution

The beforeinstallprompt event is Chrome's way of signalling that it knows the app can be installed. This allows the website to add an install UI. The event has a prompt method that allows the website itself to activate the browser's install flow when the user clicks on a custom install button.

When PWAsForFirefox detects an installable website, it should fire this event at startup. It does not have to display an install prompt UI, although that might be a cool addition in the future.

The appinstalled event is Chrome's way of letting the website know that the app has been installed, and therefore it should remove the install UI and possibly display a post-install UI.

PWAsForFirefox should fire this event when it installs an app.

Additional Information

I don't personally like the way this API is designed, it is somewhat confusing and tries to solve too many problems that I think would be better separated into different APIs. The API also seems to be rejected by Firefox and Safari.

Despite this, I think we should implement it, as it gives the PWAs new capabilities that are otherwise impossible. Better to support a bad API than no API, and currently there is no alternative solution being proposed.

I would be interested in making a PR for this feature if you agree to it, but I cannot provide any guarantees when/if I will have time to make it.

Check out this article for a good overview: https://web.dev/articles/customize-install

@atjn atjn added the enhancement New feature or request label Jan 11, 2024
@filips123
Copy link
Owner

To be honest, I don't really see how these events are actually useful. If a website is detected as installable, PWAsForFirefox just shows the page action icon from where the user can install the web app, without the website needing to know or do anything. I don't know why the website itself should handle and trigger the install flow, and when this is useful...

However, I don't object to them being implemented. I may implement them in the future, but I also don't know when I'll have time. You can also submit PR when you have time, but when you start making it, please let me know that you are working on it, so we won't implement the same thing twice.

And now for some more implementation details. I think that extensions can send custom events to websites, but I'm not sure about receiving data back (which is needed for the prompt method). Once that prompt method call is received, the extension can probably use browser.pageAction.openPopup to show the page action with the install popup. For web apps that are already installed, I guess that beforeinstallprompt should not be called, but if the user installs another instance of that web app, the appinstalled event should still be sent after it is installed, right?

In case this is implemented, I would like it to be optional with some extension setting like "Allow websites to control/intercept/something the installation flow" (I don't know yet what the appropriate name would be). The first reason for this is that it could be annoying for users if websites can randomly show the installation popups. The second reason is for privacy, because then websites could detect that PWAsForFirefox is installed, and when the user decides to install them.


There is also another part of letting websites know they are installed as PWAs. This is the (display-mode: standalone) media query (#431), which should be implemented in the PWAsForFirefox app browser. This is something that I would like to support, but the problem is that it seems it's not possible to control media queries with UserChrome JS that PWAsForFirefox uses. Do you know any way to do this?


I am a little sad to see that you are not interested in adding Fugu API's, as I think I might be able to contribute those to this project, but I don't think I have the time to write my own plugin from scratch that can do it.

Which APIs specifically are you interested in? Some of them can maybe still be implemented.

My main reasons for not implementing them are currently mainly:

  • Most of them are not standard and Chromium-only. Some of them may also be unstable with frequent updates, so PWAsForFirefox would need to get updated to support the latest versions.

  • I don't know if it's possible to implement them easily without modifying the main Firefox source, which would probably require forking. And even if they can be implemented, it would probably still be quite a lot of work to match everything from the specifications.

  • The security of some of those APIs is in my opinion questionable. For example, for the filesystem, USB and similar APIs, the main security protection seems to be that users need to accept the access in the popup. It would be nice to have some other layer of protection (and I'm not sure what a good one would be), as some users often just accept all those popups without knowing what they do (like for push notifications).

Still, if you know a way how to implement some of those APIs easily, you can still let me know and create PR. For those APIs that may cause security or privacy issues, I'm still not sure what the proper solution would be, but a quick solution is to make them disabled by default, so users need to enable them manually in the app browser settings (possibly with explanation/link describing what they do).

@atjn
Copy link
Author

atjn commented Jan 12, 2024

To be honest, I don't really see how these events are actually useful.

I think it is very nice to have install prompts integrated in the website. Especially if I am doing something in the app that would work better when it is installed, and it can tell me to install it because of that. This article contains a few examples: https://web.dev/articles/promote-install

I think that extensions can send custom events to websites, but I'm not sure about receiving data back (which is needed for the prompt method)

It is a little clunky but not a problem:

  1. Send a message from the website to an extension content script: https://github.com/mdn/webextensions-examples/tree/main/page-to-extension-messaging
  2. Send a message from the extension content script to the core extension files: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage

For web apps that are already installed, I guess that beforeinstallprompt should not be called, but if the user installs another instance of that web app, the appinstalled event should still be sent after it is installed, right?

Yes, that is also my understanding :)

In case this is implemented, I would like it to be optional with some extension setting

I would probably call it "Allow websites to initiate the installation flow".
I agree, it should be possible to disable, but I think it should be enabled by default because:

The first reason for this is that it could be annoying for users if websites can randomly show the installation popups.

The websites can only display the prompt once in a page lifetime and only as part of a user action, so it would be very limited how annoying they can be.

The second reason is for privacy, because then websites could detect that PWAsForFirefox is installed, and when the user decides to install them.

That is true, but I am not sure how important that is. If you have tracking protection enabled, it should remove most telemetry, and if you don't have tracking protection enabled, then the website can probably already infer everything it needs to know from other tracking vectors.


Which APIs specifically are you interested in? Some of them can maybe still be implemented.

That would be awesome! The most important one for me is the File System Access API. Most of my productivity web apps are essentially useless if they can't quickly open and modify files.
I know that this is a Chrome-only API that might change in the future, but I think it is worth supporting it because of the massive capabilities it unlocks.

I have considered implementing the Idle detection API because it seems easy to implement on top of the extension API for idle detection.

I also really want to have the Window Controls Overlay API, but I think that would require a lot of Firefox patching, so that is probably off the table.

I don't know if it's possible to implement them easily without modifying the main Firefox source,

I was thinking that the file access capabilities should be implemented in the native part of the plugin. I am sure there is a rust crate that does most of the file work for us, then we just need to build a bridge between the JS API and the rust crate.

For those APIs that may cause security or privacy issues, I'm still not sure what the proper solution would be, but a quick solution is to make them disabled by default

I think we should model it the same way that Firefox has for the Web Midi API. They call it Site Permission Addons and it seems like they plan to support more Fugu APIs via this install flow.

It works like this:

  1. The user must press a button in the website to request the feature
  2. Screenshot from 2024-01-11 22-53-03
  3. Click "Continue to installation"
  4. Screenshot from 2024-01-11 22-53-28
  5. Click "Add"
  6. Screenshot from 2024-01-11 22-53-47

We should probably also mention that our implementation isn't backed by a world-class security team and thus might have serious vulnerabilities.

The feature can be managed from the addons settings:
image

@filips123
Copy link
Owner

filips123 commented Jan 12, 2024

I agree, it should be possible to disable, but I think it should be enabled by default because:

Sure, I guess this API can be enabled by default (and with an option to disable it in the extension settings).

But for other APIs that give PWAs more capabilities when they are installed, I think they should still be disabled by default with an option to enable (each of them separately) in the app browser settings. So, when an API is disabled, it should not be available to the website, the website should not detect that it exists (so should not even display the permission popup). This is similar to how many normal Firefox APIs can be disabled (like dom.webmidi.enabled, dom.webaudio.enabled, etc.). The reason for them being disabled by default is that there may be security, privacy or instability issues, especially as they won't be reviewed by a professional security team.

I have considered implementing the Idle detection API because it seems easy to implement on top of the extension API for idle detection.

This APIs need to be implemented in the app browser (the separate Firefox instance that runs apps), which is programmed with internal Firefox JS APIs (with UserChromeJS), so you can't just use WebExtensions APIs. However, it should be possible to look how those WebExtensions APIs were implemented internally in Firefox and directly call the internal APIs they use.

I also really want to have the Window Controls Overlay API, but I think that would require a lot of Firefox patching, so that is probably off the table.

I think it should be possible to implement this, but it might be annoying. The main problem is probably implementing all those CSS environment variables and JS interfaces and changing positions of all website elements where needed so they display correctly.

I was thinking that the file access capabilities should be implemented in the native part of the plugin. I am sure there is a rust crate that does most of the file work for us, then we just need to build a bridge between the JS API and the rust crate.

Actually, I think that those things (where possible) should be implemented in UserChrome with internal Firefox APIs. Some APIs are quite low-level so they may be a bit more annoying to use, but there are already built into Firefox and provide support for file streams, which would probably be even harder to implement when using a native program in Rust.

For example, it's possible to read files, like here where it reads the config file. Here, things are a bit more complicated because of streams, but they may also be other APIs to read files that I don't know. And in any case, we would probably need to use streams to support the web API.

There are also IOUtils which provide nicer async APIs.

It's also possible to send messages to the native program via native messaging, but this is meant more for one-time requests and not streaming file contents and such things.

I think we should model it the same way that Firefox has for the Web Midi API. They call it Site Permission Addons and it seems like they plan to support more Fugu APIs via this install flow.

This is probably fine, with the additional step that the user first needs to enable the whole API from settings that I mentioned above.

However, will this actually work? These site permissions addons need to be approved/signed by Mozilla, but will that work with addons that request permissions for non-existing (at least in normal Firefox) APIs?


Also, another thing...

I will rewrite most of the existing UserChrome code in the future (probably this year) as it has become quite messy and not that easy to maintain, and fix some existing problems. Specifically, I plan to switch to ESM modules, cleanup everything, reorganize it into multiple files, change how some things are loaded and other things.

So, with those changes, it would make sense if the code that implements each of those additional APIs is also separate and more modular. I don't know what exactly will those APIs need, so I'm also not sure how that organization/modularity should look.

I also haven't written any code that injects custom APIs into the website and dynamically communicates with it (apart from one function that reads meta tags for dynamic color theme, but that implementation isn't so good and I will probably also change it during rewrite), so I don't know how exactly Firefox handles IPC between processes. Firefox uses JSActors and some other things so it would make sense to organize code according to that.

@Jaifroid
Copy link

+1 for File System Access API support. Actually, Mozilla already supports part of it (the File System API parts) with the Origin Private File System, so many of the required methods are actually in Firefox, just gated behind OPFS. What is particularly missing is window.showOpenFilePicker() (and window.showDirectoryPicker()), but access can be gained by equivalent File API commands and the webkitdirectory extension. I think pretty much everything else is already in Firefox.

An alternative to this, and maybe a lot simpler, would be to increase the quota of the OPFS. It's max 10GB in Firefox, but my use case is for storing files as large as 100GB, which works fine in Chromium browsers, so long as there is the underlying disk space of course.

Regarding security, the second OPFS idea above would still respect all the (somewhat paranoid) Firefox security. The first option would need careful coding to prevent opening any executable files, batch files, script files, or at least to ensure they can't be run, as is the case with window.showOpenFilePicker. Having said that, we have never seen the dire Firefox developer predictions of users getting hacked via the File System Access API in the years since it has become generally available in Chromium browsers...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: To Do
Development

No branches or pull requests

3 participants