blob: 65c1f7090076927a1e3a48e776b78d68c5b1e4c2 [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.
#ifndef CHROME_BROWSER_WEB_APPLICATIONS_COMMANDS_INTERNAL_COMMAND_INTERNAL_H_
#define CHROME_BROWSER_WEB_APPLICATIONS_COMMANDS_INTERNAL_COMMAND_INTERNAL_H_
#include <memory>
#include <string>
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/types/pass_key.h"
#include "base/values.h"
enum class CommandResult;
namespace base {
class Location;
}
namespace content {
class WebContents;
}
namespace web_app {
class WebAppCommandManager;
class WebAppLockManager;
namespace internal {
// Base class of the command, allowing non-templated storage by the
// CommandManager.
class CommandBase {
public:
using Id = int;
explicit CommandBase(std::string name);
virtual ~CommandBase();
// Optionally override this to returns the pre-existing web contents the
// installation was initiated with. Only implement this when the command is
// used for installation and uses a pre-existing web contents.
virtual content::WebContents* GetInstallingWebContents(
base::PassKey<WebAppCommandManager>);
// Optionally override this to be notified when shutdown happens. Do not
// change any state in this function, it should only be used for stateless
// operations like recording metrics.
// TODO(b/304553492): Remove this after per-command success/failure/shutdown
// metrics are implemented.
virtual void OnShutdown(base::PassKey<WebAppCommandManager>) const;
// Returns if the command has been started yet.
bool IsStarted() const;
// Unique id generated for this command.
Id id() const { return id_; }
// Debug value used for chrome://web-app-internals. This should not be read
// from or relied upon for any business logic under any circumstances.
const base::Value::Dict& GetDebugValue() const;
base::WeakPtr<CommandBase> GetBaseCommandWeakPtr();
void SetScheduledLocation(base::PassKey<WebAppCommandManager>,
const base::Location& location);
// Sets the command manager, allowing `CompleteAndSelfDestruct` to
// work correctly.
void SetCommandManager(base::PassKey<WebAppCommandManager>,
WebAppCommandManager* command_manager);
// Triggered by the WebAppCommandManager. Request lock and start the command
// after the lock is acquired.
using LockAcquiredCallback =
base::OnceCallback<void(base::OnceClosure start_command)>;
virtual void RequestLock(base::PassKey<WebAppCommandManager>,
WebAppLockManager* lock_manager,
LockAcquiredCallback on_lock_acquired,
const base::Location& location) = 0;
// Returns if the command manager should prepare the shared web contents by
// loading about:blank.
virtual bool ShouldPrepareWebContentsBeforeStart(
base::PassKey<WebAppCommandManager>) const = 0;
// Called by the WebAppCommandManager when this command needs to be destroyed
// before `StartWithLock` is called.
virtual base::OnceClosure TakeCallbackWithShutdownArgs(
base::PassKey<WebAppCommandManager>) = 0;
protected:
WebAppCommandManager* command_manager() const;
// Debug value used for chrome://web-app-internals. Commands can add
// information here to help document the configuration, operation, and results
// of a command's run. This should not be read from or relied upon for any
// business logic under any circumstances.
// Note that
base::Value::Dict& GetMutableDebugValue();
void SetStarted();
void CompleteAndSelfDestructInternal(CommandResult result,
base::OnceClosure after_destruction);
SEQUENCE_CHECKER(command_sequence_checker_);
private:
const Id id_;
const std::string name_;
base::Value::Dict debug_value_;
bool started_ = false;
raw_ptr<WebAppCommandManager> command_manager_ = nullptr;
base::WeakPtrFactory<CommandBase> weak_factory_{this};
};
// This base class implements all of the lock-specific logic, with per-lock
// specializations in the .cc file.
template <typename LockType>
class CommandWithLock : public CommandBase {
public:
using LockDescription = LockType::LockDescription;
explicit CommandWithLock(const std::string& name,
LockDescription initial_lock_request);
~CommandWithLock() override;
void RequestLock(base::PassKey<WebAppCommandManager>,
WebAppLockManager* lock_manager,
LockAcquiredCallback on_lock_acquired,
const base::Location& location) final;
bool ShouldPrepareWebContentsBeforeStart(
base::PassKey<WebAppCommandManager>) const final;
const LockDescription& InitialLockRequestForTesting() const {
return initial_lock_request_;
}
protected:
// Triggered after lock is acquired. Signals that this command can
// start its operations. When this command is complete, it should call-
// `CompleteAndSelfDestruct` to signal it's completion and destruct
// itself. Note: It is not guaranteed that the web app this command was
// created for is still installed. All state must be re-checked when this
// method is called.
virtual void StartWithLock(std::unique_ptr<LockType> lock) = 0;
private:
void PrepareForStart(LockAcquiredCallback on_lock_acquired);
const LockDescription initial_lock_request_;
std::unique_ptr<LockType> initial_lock_;
base::WeakPtrFactory<CommandWithLock<LockType>> weak_factory_{this};
};
} // namespace internal
} // namespace web_app
#endif // CHROME_BROWSER_WEB_APPLICATIONS_COMMANDS_INTERNAL_COMMAND_INTERNAL_H_