lacros_service.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef CHROMEOS_LACROS_LACROS_SERVICE_H_
  5. #define CHROMEOS_LACROS_LACROS_SERVICE_H_
  6. #include <stdint.h>
  7. #include <map>
  8. #include <memory>
  9. #include <string>
  10. #include <vector>
  11. #include "base/check.h"
  12. #include "base/component_export.h"
  13. #include "base/containers/contains.h"
  14. #include "base/memory/scoped_refptr.h"
  15. #include "base/memory/weak_ptr.h"
  16. #include "base/observer_list_threadsafe.h"
  17. #include "base/sequence_checker.h"
  18. #include "base/task/sequenced_task_runner.h"
  19. #include "base/token.h"
  20. #include "chromeos/components/sensors/mojom/cros_sensor_service.mojom.h"
  21. #include "chromeos/crosapi/mojom/account_manager.mojom.h"
  22. #include "chromeos/crosapi/mojom/crosapi.mojom.h"
  23. #include "chromeos/crosapi/mojom/device_attributes.mojom.h"
  24. #include "chromeos/crosapi/mojom/structured_metrics_service.mojom.h"
  25. #include "chromeos/crosapi/mojom/video_capture.mojom.h"
  26. #include "chromeos/lacros/lacros_service_never_blocking_state.h"
  27. #include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h"
  28. #include "mojo/public/cpp/bindings/generic_pending_receiver.h"
  29. #include "mojo/public/cpp/bindings/pending_receiver.h"
  30. #include "mojo/public/cpp/bindings/receiver.h"
  31. #include "mojo/public/cpp/bindings/remote.h"
  32. #include "third_party/abseil-cpp/absl/types/optional.h"
  33. namespace media {
  34. namespace stable::mojom {
  35. class StableVideoDecoderFactory;
  36. } // namespace stable::mojom
  37. } // namespace media
  38. namespace chromeos {
  39. class NativeThemeCache;
  40. class SystemIdleCache;
  41. // Forward declaration for class defined in .cc file that holds most of the
  42. // business logic of this class.
  43. class LacrosServiceNeverBlockingState;
  44. // This class is responsible for receiving and routing mojo messages from
  45. // ash-chrome via the mojo::Receiver |sequenced_state_.receiver_|. This class is
  46. // responsible for sending and routing messages to ash-chrome via the
  47. // mojo::Remote |sequenced_state_.crosapi_|. Messages are sent and
  48. // received on a dedicated, never-blocking sequence to avoid deadlocks.
  49. //
  50. // This object is constructed, destroyed, and mostly used on an "affine
  51. // sequence". For most intents and purposes, this is the main/UI thread.
  52. //
  53. // This class is a singleton but is not thread safe. Each method is individually
  54. // documented with threading requirements.
  55. class COMPONENT_EXPORT(CHROMEOS_LACROS) LacrosService {
  56. public:
  57. using ComponentPolicyMap =
  58. base::flat_map<policy::PolicyNamespace, base::Value>;
  59. class Observer {
  60. public:
  61. // Called when the new policy data is received from Ash.
  62. virtual void OnPolicyUpdated(
  63. const std::vector<uint8_t>& policy_fetch_response) {}
  64. // Called when policy fetch attempt is made in Ash.
  65. virtual void OnPolicyFetchAttempt() {}
  66. // Called when the new component policy is received from Ash.
  67. virtual void OnComponentPolicyUpdated(const ComponentPolicyMap& policy) {}
  68. protected:
  69. virtual ~Observer() = default;
  70. };
  71. // The getter is safe to call from all threads.
  72. //
  73. // This method returns nullptr very early or late in the application
  74. // lifecycle. We've chosen to have precise constructor/destructor timings
  75. // rather than rely on a lazy initializer and no destructor to allow for
  76. // more precise testing.
  77. //
  78. // If this is accessed on a thread other than the affine sequence, the caller
  79. // must invalidate or destroy the pointer before shutdown. Attempting to use
  80. // this pointer during shutdown can result in UaF.
  81. static LacrosService* Get();
  82. // This class is expected to be constructed and destroyed on the same
  83. // sequence.
  84. LacrosService();
  85. LacrosService(const LacrosService&) = delete;
  86. LacrosService& operator=(const LacrosService&) = delete;
  87. ~LacrosService();
  88. // This can be called on any thread. This call allows LacrosService
  89. // to start receiving messages from ash-chrome.
  90. // |browser_version| is the version of lacros-chrome displayed to user in
  91. // feedback report, etc.
  92. // It includes both browser version and channel in the format of:
  93. // {browser version} {channel}
  94. // For example, "87.0.0.1 dev", "86.0.4240.38 beta".
  95. void BindReceiver(const std::string& browser_version);
  96. // Each of these functions guards usage of access to the corresponding remote.
  97. // Keep these in alphabetical order.
  98. // Most use-cases of these methods can be replaced by IsAvailable(). See
  99. // crosapi::mojom::Clipboard for an example.
  100. bool IsAccountManagerAvailable() const;
  101. bool IsBrowserCdmFactoryAvailable() const;
  102. bool IsMediaSessionAudioFocusAvailable() const;
  103. bool IsMediaSessionAudioFocusDebugAvailable() const;
  104. bool IsMediaSessionControllerAvailable() const;
  105. bool IsMetricsReportingAvailable() const;
  106. bool IsSensorHalClientAvailable() const;
  107. bool IsStableVideoDecoderFactoryAvailable() const;
  108. // Methods to add/remove observer. Safe to call from any thread.
  109. void AddObserver(Observer* obs);
  110. void RemoveObserver(Observer* obs);
  111. // Notifies that the device account policy is updated with the input data
  112. // to observers. The data comes as serialized blob of PolicyFetchResponse
  113. // object.
  114. // This must be called on the affined sequence.
  115. void NotifyPolicyUpdated(const std::vector<uint8_t>& policy);
  116. // Notifies that an attempt to update the device account policy has been made.
  117. void NotifyPolicyFetchAttempt();
  118. // Notifies that the device account component policy is updated with the
  119. // input data. Must be called on the affined sequence.
  120. void NotifyComponentPolicyUpdated(ComponentPolicyMap policy);
  121. // Returns whether this interface uses the automatic registration system to be
  122. // available for immediate use at startup. Any crosapi interface can be
  123. // registered by using ConstructRemote.
  124. template <typename CrosapiInterface>
  125. bool IsRegistered() const {
  126. return base::Contains(interfaces_, CrosapiInterface::Uuid_);
  127. }
  128. // Guards usage to the corresponding crosapi interface. Can only be used with
  129. // automatically registered interfaces. See IsRegistered().
  130. template <typename CrosapiInterface>
  131. bool IsAvailable() const {
  132. DCHECK(IsRegistered<CrosapiInterface>());
  133. return interfaces_.find(CrosapiInterface::Uuid_)->second->IsAvailable();
  134. }
  135. // Returns the automatically registered remote for a given crosapi interface.
  136. // Can only be used with automatically registered features that are also
  137. // available. This method can only be called from the affine sequence (main
  138. // thread). The returned remote can only be used on the affine sequence (main
  139. // thread).
  140. template <typename CrosapiInterface>
  141. mojo::Remote<CrosapiInterface>& GetRemote() {
  142. DCHECK_CALLED_ON_VALID_SEQUENCE(affine_sequence_checker_);
  143. DCHECK(IsAvailable<CrosapiInterface>());
  144. return interfaces_.find(CrosapiInterface::Uuid_)
  145. ->second->template Get<CrosapiInterface>();
  146. }
  147. // --------------------------------------------------------------------------
  148. // Some clients will want to use mojo::Remotes on arbitrary sequences (e.g.
  149. // background threads). The following methods allow the client to construct a
  150. // mojo::Remote bound to an arbitrary sequence, and pass the other endpoint of
  151. // the Remote (mojo::PendingReceiver) to ash to set up the interface. For
  152. // other interfaces, such as media::stable::mojom::StableVideoDecoderFactory,
  153. // the main reason to use a Bind*() method instead of GetRemote() is not the
  154. // threading model, but the fact that the browser may want to maintain
  155. // multiple independent mojo::Remotes, and ash-chrome can use this behavior as
  156. // useful information (for example, to start one ash-chrome utility video
  157. // decoder process per lacros-chrome renderer process in order to host the
  158. // implementation of a media::stable::mojom::StableVideoDecoderFactory).
  159. // --------------------------------------------------------------------------
  160. // This may be called on any thread.
  161. void BindAccountManagerReceiver(
  162. mojo::PendingReceiver<crosapi::mojom::AccountManager> pending_receiver);
  163. // This may be called on any thread.
  164. void BindAudioFocusManager(
  165. mojo::PendingReceiver<media_session::mojom::AudioFocusManager> remote);
  166. // This may be called on any thread.
  167. void BindAudioFocusManagerDebug(
  168. mojo::PendingReceiver<media_session::mojom::AudioFocusManagerDebug>
  169. remote);
  170. // This may be called on any thread.
  171. void BindBrowserCdmFactory(mojo::GenericPendingReceiver receiver);
  172. // This may be called on any thread.
  173. void BindGeolocationService(
  174. mojo::PendingReceiver<crosapi::mojom::GeolocationService>
  175. pending_receiver);
  176. // This may be called on any thread.
  177. void BindMachineLearningService(
  178. mojo::PendingReceiver<
  179. chromeos::machine_learning::mojom::MachineLearningService> receiver);
  180. // This may be called on any thread.
  181. void BindMediaControllerManager(
  182. mojo::PendingReceiver<media_session::mojom::MediaControllerManager>
  183. remote);
  184. // This may be called on any thread.
  185. void BindMetricsReporting(
  186. mojo::PendingReceiver<crosapi::mojom::MetricsReporting> receiver);
  187. // This may be called on any thread.
  188. void BindRemoteAppsLacrosBridge(
  189. mojo::PendingReceiver<
  190. chromeos::remote_apps::mojom::RemoteAppsLacrosBridge> receiver);
  191. // This may be called on any thread.
  192. void BindSensorHalClient(
  193. mojo::PendingRemote<chromeos::sensors::mojom::SensorHalClient> remote);
  194. // OnLacrosStartup method of Crosapi can only be called if this method
  195. // returns true.
  196. bool IsOnBrowserStartupAvailable() const;
  197. // Binds video capture host.
  198. void BindVideoCaptureDeviceFactory(
  199. mojo::PendingReceiver<crosapi::mojom::VideoCaptureDeviceFactory>
  200. pending_receiver);
  201. // This may be called on any thread.
  202. void BindStableVideoDecoderFactory(
  203. mojo::PendingReceiver<media::stable::mojom::StableVideoDecoderFactory>
  204. receiver);
  205. // BindVideoCaptureDeviceFactory() can only be used if this method returns
  206. // true.
  207. bool IsVideoCaptureDeviceFactoryAvailable() const;
  208. // Returns SystemIdleCache, which uses IdleInfoObserver to observe idle info
  209. // changes and caches the results. Requires IsIdleServiceAvailable() for full
  210. // function, and is robust against unavailability.
  211. SystemIdleCache* system_idle_cache() { return system_idle_cache_.get(); }
  212. // Returns the version for an ash interface with a given UUID. Returns -1 if
  213. // the interface is not found. This is a synchronous version of
  214. // mojo::Remote::QueryVersion. It relies on Ash M88. Features that need to
  215. // work on M87 or older should not use this.
  216. int GetInterfaceVersion(base::Token interface_uuid) const;
  217. using Crosapi = crosapi::mojom::Crosapi;
  218. // This function binds a pending receiver or remote by posting the
  219. // corresponding bind task to the |never_blocking_sequence_|.
  220. // This method is public because not all clients can use the syntax sugar of
  221. // ConstructRemote(), which relies on the assumption that each crosapi
  222. // interface only has a single associated Bind* method.
  223. template <typename PendingReceiverOrRemote,
  224. void (Crosapi::*bind_func)(PendingReceiverOrRemote)>
  225. void BindPendingReceiverOrRemote(
  226. PendingReceiverOrRemote pending_receiver_or_remote) {
  227. never_blocking_sequence_->PostTask(
  228. FROM_HERE,
  229. base::BindOnce(
  230. &LacrosServiceNeverBlockingState::BindCrosapiFeatureReceiver<
  231. PendingReceiverOrRemote, bind_func>,
  232. weak_sequenced_state_, std::move(pending_receiver_or_remote)));
  233. }
  234. private:
  235. // This class is a wrapper around a crosapi remote, e.g.
  236. // mojo::Remote<crosapi::mojom::Automation>. This base class uses type erasure
  237. // to allow us to store all instances in a single container.
  238. class InterfaceEntryBase {
  239. public:
  240. virtual ~InterfaceEntryBase();
  241. // Returns the remote that is being wrapped.
  242. template <typename CrosapiInterface>
  243. mojo::Remote<CrosapiInterface>& Get() {
  244. return *reinterpret_cast<mojo::Remote<CrosapiInterface>*>(GetInternal());
  245. }
  246. // Returns whether Ash is sufficiently recent to support the crosapi
  247. // protocol that the remote is based on.
  248. bool IsAvailable() const { return available_; }
  249. // Initialization for the remote and |available_|.
  250. virtual void MaybeBind(uint32_t crosapi_version, LacrosService* impl) = 0;
  251. protected:
  252. InterfaceEntryBase();
  253. InterfaceEntryBase(const InterfaceEntryBase&) = delete;
  254. InterfaceEntryBase& operator=(const InterfaceEntryBase&) = delete;
  255. // Returns a raw pointer to a mojo::Remote<CrosapiInterface>.
  256. virtual void* GetInternal() = 0;
  257. // See |IsAvailable|.
  258. bool available_ = false;
  259. };
  260. // LacrosServiceNeverBlockingState is an implementation detail of
  261. // this class.
  262. friend class LacrosServiceNeverBlockingState;
  263. // Forward declare inner class to give it access to private members.
  264. template <typename CrosapiInterface,
  265. void (Crosapi::*bind_func)(mojo::PendingReceiver<CrosapiInterface>),
  266. uint32_t MethodMinVersion>
  267. class InterfaceEntry;
  268. // Returns ash's version of the Crosapi mojo interface version. This
  269. // determines which interface methods are available. This is safe to call from
  270. // any sequence. This can only be called after BindReceiver().
  271. absl::optional<uint32_t> CrosapiVersion() const;
  272. // Requests ash-chrome to send idle info updates.
  273. void StartSystemIdleCache();
  274. // Requests ash-chrome to send native theme info updates.
  275. void StartNativeThemeCache();
  276. // This function initializes a remote for a given CrosapiInterface.
  277. // It performs the following operations:
  278. // 1) Calls BindNewPipeAndPassReceiver() on the remote.
  279. // 2) Calls BindPendingReceiverOrRemote() on the PendingReceiver.
  280. template <typename CrosapiInterface,
  281. void (Crosapi::*bind_func)(mojo::PendingReceiver<CrosapiInterface>)>
  282. void InitializeAndBindRemote(mojo::Remote<CrosapiInterface>* remote);
  283. // This function constructs a new remote for a crosapi interface and stashes
  284. // it in |interfaces_|. This remote will later be bound during BindReceiver().
  285. template <typename CrosapiInterface,
  286. void (Crosapi::*bind_func)(mojo::PendingReceiver<CrosapiInterface>),
  287. uint32_t MethodMinVersion>
  288. void ConstructRemote();
  289. // BrowserService implementation injected by chrome/. Must only be used on the
  290. // affine sequence.
  291. // TODO(hidehiko): Remove this.
  292. std::unique_ptr<crosapi::mojom::BrowserService> browser_service_;
  293. // Receiver and cache of system idle info updates.
  294. std::unique_ptr<SystemIdleCache> system_idle_cache_;
  295. // Receiver and cache of native theme info updates.
  296. std::unique_ptr<NativeThemeCache> native_theme_cache_;
  297. // A sequence that is guaranteed to never block.
  298. scoped_refptr<base::SequencedTaskRunner> never_blocking_sequence_;
  299. // This member is instantiated on the affine sequence alongside the
  300. // constructor. All subsequent invocations of this member, including
  301. // destruction, happen on the |never_blocking_sequence_|.
  302. std::unique_ptr<LacrosServiceNeverBlockingState, base::OnTaskRunnerDeleter>
  303. sequenced_state_;
  304. // This member is instantiated on the affine sequence, but only ever
  305. // dereferenced on the |never_blocking_sequence_|.
  306. base::WeakPtr<LacrosServiceNeverBlockingState> weak_sequenced_state_;
  307. // Set to true after BindReceiver() is called.
  308. bool did_bind_receiver_ = false;
  309. // The list of observers.
  310. scoped_refptr<base::ObserverListThreadSafe<Observer>> observer_list_;
  311. // Each element of |interfaces_| corresponds to a crosapi interface remote
  312. // (e.g. mojo::Remote<crosapi::mojom::Automation>). The key of the element is
  313. // the UUID of the crosapi interface. The value is a wrapper around the
  314. // mojo::Remote. Each element can only be used on the affine sequence. Each
  315. // element is automatically bound to the corresponding receiver in ash.
  316. std::map<base::Token, std::unique_ptr<InterfaceEntryBase>> interfaces_;
  317. // Checks that the method is called on the affine sequence.
  318. SEQUENCE_CHECKER(affine_sequence_checker_);
  319. base::WeakPtrFactory<LacrosService> weak_factory_{this};
  320. };
  321. } // namespace chromeos
  322. #endif // CHROMEOS_LACROS_LACROS_SERVICE_H_