blob: 6aa036158b1122ad06e28e39de7a3f26d8223255 [file] [log] [blame]
// Copyright 2022 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/install_from_info_command.h"
#include <memory>
#include <utility>
#include "base/functional/bind.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/web_applications/jobs/install_from_info_job.h"
#include "chrome/browser/web_applications/jobs/uninstall/web_app_uninstall_and_replace_job.h"
#include "chrome/browser/web_applications/locks/app_lock.h"
#include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/browser/web_applications/web_app_helpers.h"
#include "chrome/browser/web_applications/web_app_id.h"
#include "chrome/browser/web_applications/web_app_install_finalizer.h"
#include "chrome/browser/web_applications/web_app_install_utils.h"
#include "components/webapps/browser/install_result_code.h"
#include "components/webapps/browser/installable/installable_metrics.h"
namespace web_app {
InstallFromInfoCommand::InstallFromInfoCommand(
Profile* profile,
std::unique_ptr<WebAppInstallInfo> install_info,
bool overwrite_existing_manifest_fields,
webapps::WebappInstallSource install_surface,
OnceInstallCallback install_callback)
: WebAppCommandTemplate<AppLock>("InstallFromInfoCommand"),
profile_(*profile),
manifest_id_(
install_info->manifest_id.is_empty()
? GenerateManifestIdFromStartUrlOnly(install_info->start_url)
: install_info->manifest_id),
app_id_(GenerateAppIdFromManifestId(manifest_id_)),
install_callback_(base::BindOnce(
[](OnceInstallCallback install_callback,
const AppId& app_id,
webapps::InstallResultCode code,
bool _) { std::move(install_callback).Run(app_id, code); },
std::move(install_callback))),
lock_description_(std::make_unique<AppLockDescription>(app_id_)) {
install_from_info_job_ = std::make_unique<InstallFromInfoJob>(
profile, std::move(install_info), overwrite_existing_manifest_fields,
install_surface, /*install_params=*/absl::nullopt,
base::BindOnce(&InstallFromInfoCommand::OnInstallFromInfoJobCompleted,
weak_factory_.GetWeakPtr()));
}
InstallFromInfoCommand::InstallFromInfoCommand(
Profile* profile,
std::unique_ptr<WebAppInstallInfo> install_info,
bool overwrite_existing_manifest_fields,
webapps::WebappInstallSource install_surface,
OnceInstallCallback install_callback,
const WebAppInstallParams& install_params)
: WebAppCommandTemplate<AppLock>("InstallFromInfoCommand"),
profile_(*profile),
manifest_id_(
install_info->manifest_id.is_empty()
? GenerateManifestIdFromStartUrlOnly(install_info->start_url)
: install_info->manifest_id),
app_id_(GenerateAppIdFromManifestId(manifest_id_)),
install_callback_(base::BindOnce(
[](OnceInstallCallback install_callback,
const AppId& app_id,
webapps::InstallResultCode code,
bool _) { std::move(install_callback).Run(app_id, code); },
std::move(install_callback))),
lock_description_(std::make_unique<AppLockDescription>(app_id_)) {
install_from_info_job_ = std::make_unique<InstallFromInfoJob>(
profile, std::move(install_info), overwrite_existing_manifest_fields,
install_surface, install_params,
base::BindOnce(&InstallFromInfoCommand::OnInstallFromInfoJobCompleted,
weak_factory_.GetWeakPtr()));
}
InstallFromInfoCommand::InstallFromInfoCommand(
Profile* profile,
std::unique_ptr<WebAppInstallInfo> install_info,
bool overwrite_existing_manifest_fields,
webapps::WebappInstallSource install_surface,
InstallAndReplaceCallback install_callback,
const WebAppInstallParams& install_params,
const std::vector<AppId>& apps_or_extensions_to_uninstall)
: WebAppCommandTemplate<AppLock>("InstallFromInfoCommand"),
profile_(*profile),
manifest_id_(
install_info->manifest_id.is_empty()
? GenerateManifestIdFromStartUrlOnly(install_info->start_url)
: install_info->manifest_id),
app_id_(GenerateAppIdFromManifestId(manifest_id_)),
install_callback_(std::move(install_callback)),
apps_or_extensions_to_uninstall_(apps_or_extensions_to_uninstall),
lock_description_(std::make_unique<AppLockDescription>(app_id_)) {
install_from_info_job_ = std::make_unique<InstallFromInfoJob>(
profile, std::move(install_info), overwrite_existing_manifest_fields,
install_surface, install_params,
base::BindOnce(&InstallFromInfoCommand::OnInstallFromInfoJobCompleted,
weak_factory_.GetWeakPtr()));
}
InstallFromInfoCommand::~InstallFromInfoCommand() = default;
const LockDescription& InstallFromInfoCommand::lock_description() const {
return *lock_description_;
}
void InstallFromInfoCommand::StartWithLock(std::unique_ptr<AppLock> lock) {
lock_ = std::move(lock);
install_from_info_job_->Start(lock_.get());
}
void InstallFromInfoCommand::OnShutdown() {
Abort(webapps::InstallResultCode::kCancelledOnWebAppProviderShuttingDown);
return;
}
base::Value InstallFromInfoCommand::ToDebugValue() const {
base::Value::Dict dict;
dict.Set("install_from_info_job", install_from_info_job_
? install_from_info_job_->ToDebugValue()
: base::Value());
dict.Set("uninstall_and_replace_job",
uninstall_and_replace_job_
? uninstall_and_replace_job_->ToDebugValue()
: base::Value());
return base::Value(std::move(dict));
}
void InstallFromInfoCommand::OnInstallFromInfoJobCompleted(
const AppId& app_id,
webapps::InstallResultCode code,
OsHooksErrors os_hook_errors) {
webapps::InstallableMetrics::TrackInstallResult(webapps::IsSuccess(code));
if (!webapps::IsSuccess(code)) {
Abort(code);
return;
}
uninstall_and_replace_job_.emplace(
&profile_.get(), *lock_, std::move(apps_or_extensions_to_uninstall_),
app_id,
base::BindOnce(&InstallFromInfoCommand::OnUninstallAndReplaced,
weak_factory_.GetWeakPtr(), std::move(code)));
uninstall_and_replace_job_->Start();
}
void InstallFromInfoCommand::OnUninstallAndReplaced(
webapps::InstallResultCode code,
bool did_uninstall_and_replace) {
if (!install_callback_) {
return;
}
SignalCompletionAndSelfDestruct(
webapps::IsSuccess(code) ? CommandResult::kSuccess
: CommandResult::kFailure,
base::BindOnce(std::move(install_callback_), std::move(app_id_), code,
did_uninstall_and_replace));
}
void InstallFromInfoCommand::Abort(webapps::InstallResultCode code) {
webapps::InstallableMetrics::TrackInstallResult(false);
if (!install_callback_) {
return;
}
SignalCompletionAndSelfDestruct(
(code ==
webapps::InstallResultCode::kCancelledOnWebAppProviderShuttingDown)
? CommandResult::kShutdown
: CommandResult::kFailure,
base::BindOnce(std::move(install_callback_), std::move(app_id_), code,
/*did_uninstall_and_replace=*/false));
}
} // namespace web_app