chrome/browser/web_applications/docs/projects/multi-step-install/install-and-launch-decoupling-design.md
Last Modified: 2026-04-20 Editor: [email protected]
This document describes the design for splitting the 'reparenting' or 'launching' portion of the web app install process from the 'install' portion on desktop, by passing a closure to the dialog/caller.
Currently, the web app install process (e.g., in
FetchManifestAndInstallCommand) often automatically reparents the web contents
used for installation into the newly installed app's window. This is handled via
direct calls to WebAppUiManager. Similarly, WebInstallFromUrlCommand
launches the app directly using WebAppUiManager after installation.
For multi-step install flows, we need to decouple these operations. The install commands should complete their primary task (installation) and then provide a closure to the dialog/caller to handle the launch/reparenting step using the command system.
Modify the install process to allow separating the installation from the reparenting/launching step, by passing a closure to the dialog/caller.
We change how the install dialog communicates with the install command.
Instead of the dialog calling a callback that completes everything, the dialog receives a callback that, when invoked to accept the install:
base::OnceClosure.base::OnceClosure, when called, will schedule a new command to handle
the reparenting or launching.The install command will complete and call its own callback immediately after installation is complete, independent of whether the launch closure is ever called. This avoids the "dead end" where the command's completion callback was tied to the launch command.
Callers who do not want to trigger the launch (e.g., DevTools protocol handler) can simply ignore the closure provided in the callback.
In chrome/browser/web_applications/web_app_install_params.h:
using WebAppInstallationAcceptanceResultCallback =
base::OnceCallback<void(bool install_success, base::OnceClosure reparent_closure)>;
using WebAppInstallationAcceptanceCallback = base::OnceCallback<void(
bool user_accepted,
std::unique_ptr<WebAppInstallInfo>,
WebAppInstallationAcceptanceResultCallback result_callback)>;
LaunchOrReparentWebContentsIntoAppCommandA new command is created to handle the post-install action for
FetchManifestAndInstallCommand.
Name: LaunchOrReparentWebContentsIntoAppCommand
Behavior:
AppId and the WebContents that was used for installation.WebContentsManager to check if the current web contents is in-scope
of the app.start_url.WebInstallFromUrlCommandLaunchWebAppCommand (via
WebAppCommandScheduler::LaunchApp) with
apps::LaunchSource::kFromWebInstallApi.Existing install dialogs that want to maintain the current behavior can use the
AdaptToLaunchOnInstallSuccess helper to wrap their callback, which
automatically runs the reparent_closure immediately on success.
Test helpers like AutoAcceptDialogCallback have been updated to automatically
run the closure on success to ensure tests that expect auto-launch still work.
LaunchOrReparentWebContentsIntoAppCommand.FetchManifestAndInstallCommand and
WebInstallFromUrlCommand to handle the new callback signature.