|  | // 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 NoopLock; | 
|  | class SharedWebContentsLock; | 
|  | class SharedWebContentsWithAppLock; | 
|  | class SharedWebContentsWithAppLockDescription; | 
|  | class WebAppCommandManager; | 
|  | 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 { | 
|  | public: | 
|  | using PassKey = base::PassKey<WebAppLockManager>; | 
|  |  | 
|  | WebAppLockManager(); | 
|  | ~WebAppLockManager(); | 
|  |  | 
|  | void SetProvider(base::PassKey<WebAppCommandManager>, | 
|  | WebAppProvider& provider); | 
|  |  | 
|  | // Returns if the lock for the shared web contents is free.  This means no one | 
|  | // is using the shared web contents. | 
|  | bool IsSharedWebContentsLockFree(); | 
|  |  | 
|  | // Acquires the lock for the given `lock_description` and `lock`. The `lock` | 
|  | // must be owned by the caller, and when the lock is destroyed the request | 
|  | // and/or internal locks are released. `on_lock_acquired` is called when the | 
|  | // lock is granted. Any access of the `lock` before `on_lock_acquired` is | 
|  | // called will CHECK-fail. | 
|  | // TODO(crbug.com/371221610): Move the lock description to be owned by the | 
|  | // lock. | 
|  | template <class LockType> | 
|  | void AcquireLock(const LockType::LockDescription& lock_description, | 
|  | LockType& lock, | 
|  | base::OnceClosure on_lock_acquired, | 
|  | const base::Location& location); | 
|  |  | 
|  | // Upgrades the given lock to a new one, and will call `on_lock_acquired` on | 
|  | // when the new lock has been acquired. | 
|  | std::unique_ptr<SharedWebContentsWithAppLockDescription> | 
|  | UpgradeAndAcquireLock(std::unique_ptr<SharedWebContentsLock> old_lock, | 
|  | SharedWebContentsWithAppLock& new_lock, | 
|  | const base::flat_set<webapps::AppId>& app_ids, | 
|  | base::OnceClosure on_lock_acquired, | 
|  | const base::Location& location = FROM_HERE); | 
|  |  | 
|  | // Upgrades the given lock to a new one, and will call `on_lock_acquired` on | 
|  | // when the new lock has been acquired. | 
|  | std::unique_ptr<AppLockDescription> UpgradeAndAcquireLock( | 
|  | std::unique_ptr<NoopLock> old_lock, | 
|  | AppLock& new_lock, | 
|  | const base::flat_set<webapps::AppId>& app_ids, | 
|  | base::OnceClosure on_lock_acquired, | 
|  | const base::Location& location = FROM_HERE); | 
|  |  | 
|  | base::Value ToDebugValue() const; | 
|  |  | 
|  | WebAppProvider& provider() const { return *provider_; } | 
|  |  | 
|  | base::WeakPtr<WebAppLockManager> GetWeakPtr(); | 
|  |  | 
|  | private: | 
|  | // Method used to call `GrantLock` function on the lock, after the | 
|  | // `lock_manager_` has granted the locks. | 
|  | // Note: `lock` is guaranteed to be populated, as otherwise the 'holder' for | 
|  | // the lock will be destroyed, and then this callback is never called. | 
|  | template <class LockType> | 
|  | void GrantLock(base::WeakPtr<LockType> lock); | 
|  |  | 
|  | // Acquires the lock for the given `lock`, calling `on_lock_acquired` when | 
|  | // complete. | 
|  | void AcquireLockImpl(PartitionedLockHolder& holder, | 
|  | const LockDescription& lock, | 
|  | base::OnceClosure on_lock_acquired, | 
|  | const base::Location& location); | 
|  |  | 
|  | PartitionedLockManager lock_manager_; | 
|  | raw_ptr<WebAppProvider> provider_ = nullptr; | 
|  | base::WeakPtrFactory<WebAppLockManager> weak_factory_{this}; | 
|  | }; | 
|  |  | 
|  | }  // namespace web_app | 
|  |  | 
|  | #endif  // CHROME_BROWSER_WEB_APPLICATIONS_LOCKS_WEB_APP_LOCK_MANAGER_H_ |