blob: 753d1c54ff0f7fa169ccdb73f232c8f9b13743e6 [file] [log] [blame]
// Copyright 2024 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/internal/command_internal.h"
#include <string_view>
#include <type_traits>
#include <utility>
#include "base/atomic_sequence_num.h"
#include "base/check.h"
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/values.h"
#include "chrome/browser/web_applications/locks/all_apps_lock.h"
#include "chrome/browser/web_applications/locks/app_lock.h"
#include "chrome/browser/web_applications/locks/noop_lock.h"
#include "chrome/browser/web_applications/locks/shared_web_contents_lock.h"
#include "chrome/browser/web_applications/locks/shared_web_contents_with_app_lock.h"
#include "chrome/browser/web_applications/locks/web_app_lock_manager.h"
#include "chrome/browser/web_applications/web_app_command_manager.h"
namespace web_app::internal {
namespace {
int GetNextCommandId() {
static base::AtomicSequenceNumber g_incrementing_id_;
return g_incrementing_id_.GetNext();
}
} // namespace
CommandBase::CommandBase(std::string name)
: id_(GetNextCommandId()), name_(std::move(name)) {
DETACH_FROM_SEQUENCE(command_sequence_checker_);
// We don't have an easy way to enforce construction of class on the
// WebAppProvider sequence without requiring a UI thread in unittests, so just
// allow this construction to happen from any thread.
base::Value::Dict* metadata = GetMutableDebugValue().EnsureDict("!metadata");
metadata->Set("name", name_);
metadata->Set("id", id_);
metadata->Set("started", false);
}
CommandBase::~CommandBase() = default;
content::WebContents* CommandBase::GetInstallingWebContents(
base::PassKey<WebAppCommandManager>) {
DCHECK_CALLED_ON_VALID_SEQUENCE(command_sequence_checker_);
return nullptr;
}
void CommandBase::OnShutdown(base::PassKey<WebAppCommandManager>) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(command_sequence_checker_);
}
bool CommandBase::IsStarted() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(command_sequence_checker_);
return started_;
}
base::WeakPtr<CommandBase> CommandBase::GetBaseCommandWeakPtr() {
DCHECK_CALLED_ON_VALID_SEQUENCE(command_sequence_checker_);
return weak_factory_.GetWeakPtr();
}
void CommandBase::SetScheduledLocation(base::PassKey<WebAppCommandManager>,
const base::Location& location) {
DCHECK_CALLED_ON_VALID_SEQUENCE(command_sequence_checker_);
GetMutableDebugValue()
.EnsureDict("!metadata")
->Set("scheduled_location", location.ToString());
}
void CommandBase::SetCommandManager(base::PassKey<WebAppCommandManager>,
WebAppCommandManager* command_manager) {
DCHECK_CALLED_ON_VALID_SEQUENCE(command_sequence_checker_);
command_manager_ = command_manager;
}
const base::Value::Dict& CommandBase::GetDebugValue() const {
return debug_value_;
}
WebAppCommandManager* CommandBase::command_manager() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(command_sequence_checker_);
return command_manager_;
}
base::Value::Dict& CommandBase::GetMutableDebugValue() {
return debug_value_;
}
void CommandBase::SetStarted() {
DCHECK_CALLED_ON_VALID_SEQUENCE(command_sequence_checker_);
started_ = true;
GetMutableDebugValue().EnsureDict("!metadata")->Set("started", true);
}
void CommandBase::CompleteAndSelfDestructInternal(
CommandResult result,
base::OnceClosure after_destruction) {
command_manager()->OnCommandComplete(base::PassKey<CommandBase>(), this,
result, std::move(after_destruction));
}
template <typename LockType>
CommandWithLock<LockType>::CommandWithLock(const std::string& name,
LockDescription initial_lock_request)
: CommandBase(name),
initial_lock_request_(std::move(initial_lock_request)),
initial_lock_(std::make_unique<LockType>()) {
GetMutableDebugValue()
.EnsureDict("!metadata")
->Set("initial_lock_request", initial_lock_request_.AsDebugValue());
}
template <typename LockType>
CommandWithLock<LockType>::~CommandWithLock() = default;
template <typename LockType>
void CommandWithLock<LockType>::RequestLock(
base::PassKey<WebAppCommandManager>,
WebAppLockManager* lock_manager,
LockAcquiredCallback on_lock_acquired,
const base::Location& location) {
DCHECK_CALLED_ON_VALID_SEQUENCE(command_sequence_checker_);
lock_manager->AcquireLock(
initial_lock_request_, *initial_lock_,
base::BindOnce(&CommandWithLock::PrepareForStart,
weak_factory_.GetWeakPtr(), std::move(on_lock_acquired)),
location);
}
template <typename LockType>
void CommandWithLock<LockType>::PrepareForStart(
LockAcquiredCallback on_lock_acquired) {
DCHECK_CALLED_ON_VALID_SEQUENCE(command_sequence_checker_);
CHECK(command_manager());
CHECK(!IsStarted());
SetStarted();
std::move(on_lock_acquired)
.Run(base::BindOnce(&CommandWithLock::StartWithLock,
weak_factory_.GetWeakPtr(),
std::move(initial_lock_)));
}
template <typename LockType>
bool CommandWithLock<LockType>::ShouldPrepareWebContentsBeforeStart(
base::PassKey<WebAppCommandManager>) const {
return initial_lock_request_.IncludesSharedWebContents();
}
template class CommandWithLock<NoopLock>;
template class CommandWithLock<SharedWebContentsLock>;
template class CommandWithLock<AppLock>;
template class CommandWithLock<SharedWebContentsWithAppLock>;
template class CommandWithLock<AllAppsLock>;
} // namespace web_app::internal