// 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. #ifndef CHROME_BROWSER_WEB_APPLICATIONS_COMMANDS_WEB_APP_COMMAND_H_ #define CHROME_BROWSER_WEB_APPLICATIONS_COMMANDS_WEB_APP_COMMAND_H_ #include <iterator> #include <memory> #include <optional> #include <tuple> #include <type_traits> #include "base/functional/bind.h" #include "base/functional/bind_internal.h" #include "base/functional/callback.h" #include "base/location.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "base/strings/to_string.h" #include "base/types/pass_key.h" #include "base/values.h" #include "chrome/browser/web_applications/commands/command_result.h" #include "chrome/browser/web_applications/commands/internal/command_internal.h" #include "components/webapps/common/web_app_id.h" namespace content { class WebContents; } namespace web_app { class LockDescription; class WebAppCommandManager; class WebAppLockManager; // Encapsulates code that reads or modifies the WebAppProvider system. All // reading or writing to the system should occur in a WebAppCommand to ensure // that it is isolated. Reading can also happen in any WebAppRegistrar observer. // // Commands allow an operation to: // - Ensure that resources are not being used by another operation (e.g. no // other operation is operating on the given app id). // - Automatically handles edge cases like profile shutdown. // - Prevent any possible re-entry bugs by allowing any final callback to be // called after the command is destructed. // - Record detailed logs that are exposed in chrome://web-app-internals. // // For simple operations that require holding on to lock only for single // synchronous function calls, WebAppCommandScheduler::ScheduleCallback* // can be used instead of creating a sub-class. // // To create a command sub-class, extend the below type `WebAppCommand, // which allows specification of the type of lock to retrieve. For example: // // class GetAppInformationForMySystem // : public WebAppCommand<AppLock, CallbackArgType> { // GetAppInformationForMySystem(ReportBackInformationCallback callback) // : WebAppCommand(std::move(callback), // /*args_for_shutdown*/=CallbackArgType::kShutdownValue) {} // ... // void StartWithLock(std::unique_ptr<AppLock> lock) { // ... // // ... // CompleteAndSelfDestruct( // CommandResult::kSuccess, // lock.<information>()); // } // ... // // // Implement this if installing from an external web contents. // WebContents* GetInstallingWebContents(...) override; // }; // // See the `WebAppLockManager` for information about the available locks & how // they work. // // Commands can only be started by enqueueing the command in the // WebAppCommandManager, which is done by the WebAppCommandScheduler. When a // command is complete, it can call `CompleteAndSelfDestruct` to signal // completion and self-destruct. // // Call pattern of commands: // - StartWithLock(), // - <subclass stuff> // - <subclass calls CompleteAndSelfDestruct()>. // // The command can use the following optional features: // - Populate the `GetMutableDebugValue()` with information that is useful for // debugging - this shown in chrome://web-app-internals and printed in failed // tests. // - To prevent multiple installs occurring at the same time for a given // `WebContents`, installations that install from an external `WebContents` // should override `GetInstallingWebContents()` and return that WebContents. // - `OnShutdown()` can be overridden to do stateless tasks like recording // metrics. // // Invariants: // * Destruction can occur without `StartWithLock()` being called. If the system // shuts down and the command was never started, then it will simply be // destructed and the `callback` will be called with the // `args_for_shutdown`, if they exist. // // TODO(dmurph): Add an example of a CL that creates a command. template <typename LockType, typename... CallbackArgs> class WebAppCommand : public internal::CommandWithLock<LockType> { … }; } // namespace web_app #endif // CHROME_BROWSER_WEB_APPLICATIONS_COMMANDS_WEB_APP_COMMAND_H_