// 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_LOCKS_WEB_APP_LOCK_MANAGER_H_ #define CHROME_BROWSER_WEB_APPLICATIONS_LOCKS_WEB_APP_LOCK_MANAGER_H_ #include <memory> #include "base/containers/flat_set.h" #include "base/functional/callback_forward.h" #include "base/location.h" #include "base/memory/raw_ref.h" #include "base/memory/weak_ptr.h" #include "base/types/pass_key.h" #include "chrome/browser/web_applications/locks/partitioned_lock_manager.h" #include "components/webapps/common/web_app_id.h" namespace base { class Value; } namespace web_app { class AppLock; class AppLockDescription; class LockDescription; class WebAppCommandManager; class NoopLock; class SharedWebContentsLock; class SharedWebContentsWithAppLock; class SharedWebContentsWithAppLockDescription; class WebAppProvider; // Locks allow types of exclusive access to resources in the WebAppProvider // system, depending on the lock. These are not for multi-sequence access, but // instead required due to the async nature of operations in the system. Locks // do NOT protect against common problems like handling profile shutdown. In // fact, locks will CHECK-fail if they are called accessed during profile // shutdown. Thus using a WebAppCommand is a better option, as commands are // destroyed automatically during shutdown. // // Locks can be a great way to make synchronous operations composable. For // example, the following method call guarantees that it is done in an isolated // context: // // void UpdateWidget(WithAppResources& lock_with_app_exclusivity, webapps::AppId // id) { // widget_.SetTitle(lock_with_app_exclusivity.registrar().GetShortName(id)); // ... // } // // To access data across an async call chain, then // 1) The brokering of the lock needs to be done through a command to make sure // shutdown is handled. // 2) a WeakPtr of the lock can be used so the async logic can correctly handle // this shutdown. // // Example of using a lock across an async boundary: // // void UpdateWidget(base::WeakPtr<WithAppResources> lock_with_app_exclusivity, // webapps::AppId id) { // widget_.SetTitle(lock_with_app_exclusivity.registrar().GetShortName(id)); // TalkToAsyncSystem(..., base::BindOnce(&OnAsyncSystemUpdated, // lock_with_app_exclusivity)); // } // // void OnAsyncSystemUpdated(base::WeakPtr<WithAppResources> // lock_with_app_exclusivity) { // if (!lock_with_app_exclusivity) { // // Do cleanup? // return; // } // ... do things with the lock. // } class WebAppLockManager { … }; } // namespace web_app #endif // CHROME_BROWSER_WEB_APPLICATIONS_LOCKS_WEB_APP_LOCK_MANAGER_H_