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 a manifest option for the declaration of the web application running pattern #1019

Open
songql opened this issue Oct 28, 2021 · 11 comments

Comments

@songql
Copy link

songql commented Oct 28, 2021

We found that when we are having multiple instances of a PWA simultaneously, a race condition would occur that corrupts local data and causes undefined behaviors.

We will use Sudoku Game PWA to illustrate the problem we detected. Sudoku Game PWA would automatically save unfinished games after closing and reload the unfinished game when reopening. The unfinished game would be stored on our local machines.

  • Scenario I: When we only have one Sudoku Game PWA running, the application runs perfectly without any problems including saving and reloading.

  • Scenario II: When we have two running Sudoku Game PWAs named Sudoku A and Sudoku B, we can play two games at the same time normally. However, if we close Sudoku A first, then close Sudoku B, we can only reload the game played by Sudoku B from newly created Sudoku PWAs.

After exploring our local files, we determined that Sudoku B had overwritten the data saved by Sudoku A.

On operating systems level, some applications are designed to have only one running instance. Most noteable such applications are web browsers such as Firefox and Chrome. Some PWAs should also be restricted from having multiple instances for various reasons.

Therefore, it is curial to add pattern member to the current manifest standards which helps PWA and browser developers alike to better handle multi-instance PWAs and single-instance PWA concurrently.

The proposal here is for a new optional "pattern" member to be added to the manifest. The default value of this member is "non-singleton" for PWAs that are expected to have multiple instances. This member is setted to "singleton" for single-instance-only PWAs.

(We have considered the naming of the manifest member, including "mode" and "instance", and finally decided that "pattern" is more suitable.)

Below is the recommended member and value set for the manifest:

{
  "pattern": "singleton" // enum: non-singleton(default), singleton
}

For more details about the proposal, please refer to the following discussion:

comment
comment

@tomayac
Copy link
Contributor

tomayac commented Oct 28, 2021

A similar question came up in the context of Tabbed Application Mode.

@songql
Copy link
Author

songql commented Oct 28, 2021

A similar question came up in the context of Tabbed Application Mode.

@tomayac Thank you for your response.

While, of course, the tabbed-view is a nice thing to have in #737 and the new data storage model you mentioned there, I believed as an experienced developer, is a keystone for expanding the ability of web applications.

However, we are addressing two related but not identical problems. The tabbed-view function and LocalStorage is mostly focused on the UI and data storage side of the PWA development. My proposal is advocating adding new support for single-instance-only PWAs from browser-level (i.e browsers would forbid launching new instances if there is already a running single-instance-only pwa). And I don't think adding a tabbed view option to the display member would be the solution for the problem I mentioned in this proposal. Because, a single-instance-only PWA may or may not use tabbed view and the LocalStorage but our browsers need a direct way to know what type this application is and PWA developers should also have a direct way to acknowledge the browsers that their application should and can only have one running instances.

The Sudoku game scenario is just to illustrate that this type of PWA should not have multi-instance operation mentioned in the proposal, rather than to achieve the purpose of multi-instance data separation.

@songql songql closed this as completed Oct 28, 2021
@songql songql reopened this Oct 28, 2021
@marcoscaceres
Copy link
Member

I'm not if this is a problem with "PWAs" or with the JS that is being used to store the data for the app.

The specification's working model is that PWAs can be either "installed" or run in (multiple) regular browser tabs (i.e., being "installed" is a "Progressive" part of a PWA, but not a requirement or expectation): as such, a PWA could be viewed in a web browser where multiple tabs could simultaneously run the application.

It is then up to the web application to make sure it doesn't get into race conditions by, for instance, assigning a unique identifier for each open session/tab/window.

So, although I think it be nice to say "this app is a 'singleton'", it still won't solve the race condition - because the application could still be viewed in multiple regular browser tabs.

@songql
Copy link
Author

songql commented Nov 8, 2021

@marcoscaceres Thank you so much for sharing your insights.

I totally agree with you that it is the developers' job to avoid race conditions. But the intention of our proposal is to advocate a specific design in browser to support singleton-only PWAs. The Sudoku example may be somewhat misleading here. What we want to show here is that if the developer of the Sudoku PWA doesn't want multiple games to be played at the same time, they can easily declare the PWA as singleton in the manifest and the browser will do the rest of the work.

Why do we think a singleton running pattern is crucial?Because historically, web browsers have many singleton only components/features. Chrome, for example, can have only one single main process that manage resources and assign work to child processes. Chrome's history tab and downloads tab are also supposed to be singleton (although users may work around it through some "hacky" ways). In desktop environments, some programs such as some system utilities and daemons are also restricted by the operating systems to have a singleton running pattern. And because, PWA is created as an alternative to native apps and we want the PWA to be "more app and less web". As you mentioned, PWA can be in 4 possible display modes but the majority of them only chose standalone to have a app like look. And on mobile devices, we expect each app to just have one running instance. Allowing a PWA to be singleton only can better simulate the native app user experiences. And in our daily work, we encountered multiple situations that required some PWAs to be singletons. For instance, an online exam PWA that wants students can only open one exam window. And imagine what would happen if you command your character to turn right and turn left in an online game at the same time on two PWAs.

It is up to the browser developers to determine how to support the singleton running pattern. One possible solution is to forbid singleton-only PWAs to be on browser display mode. In my opinion, allowing PWA to be singleton only is one more level of "progressive" that can greatly expand the functionality of PWAs and benefit PWA and browser developers tremendously.

Again, thank you for your thoughtful comment. If you have any further questions and discussion, please feel free to comment on my reply.

@marcoscaceres
Copy link
Member

It's certainly true that there are some applications that only have one window (e.g., on my Mac, calendar, messages, Spotify, etc.).

For instance, an online exam PWA that wants students can only open one exam window.

I'd be concerned about the reliability of this mechanism as a policy enforcement point. Because PWAs originate from the Web, it may be (or at least should be) quite trivial for a user to get the URL of the application to open it in a browser tab.

In my opinion, allowing PWA to be singleton only is one more level of "progressive" that can greatly expand the functionality of PWAs and benefit PWA and browser developers tremendously.

I agree that it's a nice feature. The thing to be mindful of is that it would indeed be an "enhancement", and that there is no guaranteed that this would be enforceable (i.e., "prefers single window").

Would be great to hear thoughts from others!

@songql
Copy link
Author

songql commented Nov 9, 2021

Any opinion and suggestion are welcomed. Even if you don't like this proposal, please share your concerns to help us make this proposal better. And a big thank you to anyone who liked this proposal.

@alancutter
Copy link
Contributor

This sounds like you're after launch_handler: { route_to: existing-client } to reduce the chance of having multiple windows open (does not garantee multiple won't be open though).

@songql
Copy link
Author

songql commented Nov 10, 2021

This sounds like you're after launch_handler: { route_to: existing-client } to reduce the chance of having multiple windows open (does not garantee multiple won't be open though).

@alancutter Thanks for your response.
You understand it right, that's what the proposal means.
Developers should have the option of determining the singleton run pattern for the PWA. This give the PWA more "progressive" capability.
And the browser can provide the strict mode for this feature, PWA has only one instance in any case, whether in a window or in a tab.

@alancutter
Copy link
Contributor

I'm reluctant for regular web browsing to be interfered with e.g. if the user navigates to the site directly in a browser tab.

I think with launch_handler: { route_to: existing-client-retain } the duplicate instance situation becomes a rare corner case situation that the user deliberately gets into, regular app launches won't trigger multiple windows to be opened. If the user does force multiple instances the issue the example Sudoku app faces could be resolved by co-ordinating instances via a SharedWorker.

As a data point the Telegram PWA deals with the situation via a user message:
Screenshot from 2022-04-26 14-22-21

@songql
Copy link
Author

songql commented May 6, 2022

@alancutter Sorry for the late reply.

Because I have re-reviewed the original intention of this proposal in this few days, and checked the relevant materials and examples of launch_handler carefully:

It's nice that we're trying to solve a similar problem, just with a different solution and different final result.

The launch_handler has been updated by several versions. Currently, the route_to attribute has four values: auto, new-client, existing-client-navigate, existing-client-retain. The difference between existing-client-navigate and existing-client-retain is navigating the existing web app instance to a new URL or not. And it needs some interfaces to developers, such as LaunchQueue, LaunchParams, LaunchConsumer.

I have tried to think how to implement similar application scenarios only with the existing Web specification that have been defined by W3C. Most application features can be done through the combination of Service Worker and LocalStorage. Except when new navigation try to focus a existing instance that has not been defined and the user agent has not been provided the capability.

We implemented the features in based on Chromium project last year and made an example, you can watch the demo video: Singleton Pattern PWA Demo (p.s, the video language is Chinese). We made some conclusions with the implementation:

  1. The control logic of "single instance/reuse of existing instance" can be easily realized, whether the PWA is in standalone or browser display mode;
  2. If there is no additional control, the user can break this feature by manually entering the URL in a new tab, but it is also could be limit;
  3. Additional "strict-mode" configuration can be give developers as a choice.
    Inspired from launch_handler, the value of pattern should update from non-singleton(default), singleton to default, non-singleton, singleton, singleton-strict.

The least important thing is naming the manifest member as pattern/launch_handler or the words used to represent the attribute value. At this moment, it is not our priority.

BTW: The Sudoku Game I used as an example wasn't good earlier, but your Music Player example to description the scene is great.

I am very happy to have exchanges thoughts on this proposal continuously, and promote this to the W3C specification and the user agent implementation together.

@alancutter
Copy link
Contributor

alancutter commented May 24, 2022

Sorry for late reply, this is a complex thing to resolve.

I think the desired singleton behaviour relates more to link capturing than launch_handler. I think you want to say "all navigations into the app scope will be treated as an app launch" after which launch_handler can kick in with existing-client-* and direct the launch into an existing window.

I don't think this behaviour is something we'd implement in Chromium as we want the user to be in full control over link capturing rather than developers however other user agents may be okay with implementing "singleton" style link capturing.
Coincidentally Microsoft is pursuing a handle_links member to specify a developer preference for capturing links: https://github.com/WICG/pwa-url-handler/blob/main/handle_links/explainer.md#proposed-solution
(@LuHuangMSFT FYI)

You could probably get "singleton" like behaviour with this in your manifest:

{
  "handle_links": "preferred",
  "launch_handler": {
    "route_to": "existing-client-retain"
  }
}

It all depends on how strongly the user agent treats "handle_links": "preferred". I think in terms of spec scope it would be entirely valid for a user agent to capture all browser tab navigations as web app launches.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
5 participants
@tomayac @marcoscaceres @alancutter @songql and others