blob: 0dcf034ac2dbff7fbcae58f03ca8c5912ece8f53 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/web_applications/commands/launch_web_app_command.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/functional/concurrent_closures.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/apps/app_service/app_launch_params.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/web_applications/commands/web_app_command.h"
#include "chrome/browser/web_applications/locks/app_lock.h"
#include "chrome/browser/web_applications/mojom/user_display_mode.mojom-shared.h"
#include "chrome/browser/web_applications/os_integration/os_integration_test_override.h"
#include "chrome/browser/web_applications/proto/web_app_install_state.pb.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/browser/web_applications/web_app_registry_update.h"
#include "chrome/browser/web_applications/web_app_sync_bridge.h"
#include "chrome/browser/web_applications/web_app_ui_manager.h"
#include "components/services/app_service/public/cpp/app_launch_util.h"
namespace web_app {
LaunchWebAppCommand::LaunchWebAppCommand(
Profile* profile,
WebAppProvider* provider,
apps::AppLaunchParams params,
LaunchWebAppWindowSetting launch_setting,
LaunchWebAppCallback callback)
: WebAppCommand<AppLock,
base::WeakPtr<Browser>,
base::WeakPtr<content::WebContents>,
apps::LaunchContainer>(
"LaunchWebAppCommand",
AppLockDescription(params.app_id),
std::move(callback),
/*args_for_shutdown=*/
std::make_tuple(nullptr,
nullptr,
apps::LaunchContainer::kLaunchContainerNone)),
params_(std::move(params)),
launch_setting_(launch_setting),
profile_(*profile),
provider_(*provider) {
CHECK(provider);
}
LaunchWebAppCommand::~LaunchWebAppCommand() = default;
void LaunchWebAppCommand::StartWithLock(std::unique_ptr<AppLock> lock) {
lock_ = std::move(lock);
if (!lock_->registrar().IsInRegistrar(params_.app_id)) {
GetMutableDebugValue().Set("error", "not_installed");
CompleteAndSelfDestruct(CommandResult::kFailure, nullptr, nullptr,
apps::LaunchContainer::kLaunchContainerNone);
return;
}
const WebApp* current_app = lock_->registrar().GetAppById(params_.app_id);
CHECK(current_app);
bool is_standalone_launch =
params_.container == apps::LaunchContainer::kLaunchContainerWindow ||
(launch_setting_ ==
LaunchWebAppWindowSetting::kOverrideWithWebAppConfig &&
current_app->user_display_mode() != mojom::UserDisplayMode::kBrowser);
GetMutableDebugValue().Set("is_standalone_launch", is_standalone_launch);
if (is_standalone_launch) {
// Launching an app in a standalone windows requires OS integration, and the
// only way this is supported in tests is to use the
// OsIntegrationTestOverride functionality.
CHECK_OS_INTEGRATION_ALLOWED();
}
bool needs_os_integration_sync = false;
// Upgrade to fully installed if needed.
if (is_standalone_launch &&
lock_->registrar().GetInstallState(params_.app_id) !=
proto::INSTALLED_WITH_OS_INTEGRATION) {
ScopedRegistryUpdate update = lock_->sync_bridge().BeginUpdate();
update->UpdateApp(params_.app_id)
->SetInstallState(proto::INSTALLED_WITH_OS_INTEGRATION);
needs_os_integration_sync = true;
}
std::optional<proto::os_state::WebAppOsIntegration> os_integration =
lock_->registrar().GetAppCurrentOsIntegrationState(params_.app_id);
CHECK(os_integration);
GetMutableDebugValue().Set("needs_os_integration_sync",
needs_os_integration_sync);
base::ConcurrentClosures completion;
if (needs_os_integration_sync) {
// TODO(crbug.com/339451551): Remove adding to desktop on linux after the
// OsIntegrationTestOverride can use the xdg install command to detect
// install.
SynchronizeOsOptions options;
#if BUILDFLAG(IS_LINUX)
options.add_shortcut_to_desktop = true;
#endif
lock_->os_integration_manager().Synchronize(
params_.app_id,
base::BindOnce(&LaunchWebAppCommand::OnOsIntegrationSynchronized,
weak_factory_.GetWeakPtr())
.Then(completion.CreateClosure()),
options);
}
std::move(completion)
.Done(base::BindOnce(&LaunchWebAppCommand::DoLaunch,
weak_factory_.GetWeakPtr()));
}
void LaunchWebAppCommand::OnOsIntegrationSynchronized() {
GetMutableDebugValue().Set("os_integration_synchronized", true);
}
void LaunchWebAppCommand::DoLaunch() {
provider_->ui_manager().LaunchWebApp(
std::move(params_), launch_setting_, *profile_,
base::BindOnce(&LaunchWebAppCommand::OnAppLaunched,
weak_factory_.GetWeakPtr()),
*lock_);
}
void LaunchWebAppCommand::OnAppLaunched(
base::WeakPtr<Browser> browser,
base::WeakPtr<content::WebContents> web_contents,
apps::LaunchContainer container,
base::Value debug_value) {
GetMutableDebugValue().Set("launch_web_app_debug_value",
std::move(debug_value));
CompleteAndSelfDestruct(CommandResult::kSuccess, std::move(browser),
std::move(web_contents), container);
}
} // namespace web_app