File: web_app_lock_manager.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (149 lines) | stat: -rw-r--r-- 5,759 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// 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_