| // Copyright 2020 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROMECAST_MOJO_REMOTE_INTERFACES_H_ |
| #define CHROMECAST_MOJO_REMOTE_INTERFACES_H_ |
| |
| #include "base/sequence_checker.h" |
| #include "chromecast/mojo/mojom/remote_interfaces.mojom.h" |
| #include "mojo/public/cpp/bindings/generic_pending_receiver.h" |
| #include "mojo/public/cpp/bindings/pending_receiver.h" |
| #include "mojo/public/cpp/bindings/remote.h" |
| |
| namespace chromecast { |
| |
| // Client helper object which wraps a mojo::Remote<mojom::RemoteInterfaces> and |
| // provides convenience methods for binding local Remote stubs. |
| // |
| // ============================================================================= |
| // Example Usage |
| // ============================================================================= |
| // |
| // From a service, create a pending RemoteInterfaces, such as from |
| // InterfaceBundle: |
| // |
| // InterfaceBundle bundle; |
| // bundle.AddInterface<mojom::Foo>(GetFooImpl()); |
| // bundle.AddInterface<mojom::Bar>(GetBarImpl()); |
| // mojo::PendingRemote<mojom::RemoteInterfaces> pending_provider = |
| // bundle.CreateRemote(); |
| // |
| // In a different service, we can use RemoteInterfaces to wrap |
| // |pending_provider| and access the interfaces that were added: |
| // |
| // RemoteService::InjectInterfaces( |
| // mojo::PendingRemote<mojom::RemoteInterfaces> pending_provider) { |
| // RemoteInterfaces provider(std::move(pending_provider)); |
| // mojo::Remote<mojom::Bar> bar = bundle.GetRemote<mojom::Bar>(); |
| // bar->DoBarStuff(); |
| // } |
| class RemoteInterfaces { |
| public: |
| RemoteInterfaces(); |
| explicit RemoteInterfaces( |
| mojo::PendingRemote<mojom::RemoteInterfaces> provider); |
| ~RemoteInterfaces(); |
| |
| RemoteInterfaces(const RemoteInterfaces&) = delete; |
| RemoteInterfaces& operator=(const RemoteInterfaces&) = delete; |
| |
| // Late-binds a provider if one was not injected on creation. |
| void SetProvider(mojo::PendingRemote<mojom::RemoteInterfaces> provider); |
| |
| // Exposes interfaces to a remote provider. |
| mojo::PendingRemote<mojom::RemoteInterfaces> Forward(); |
| |
| // Gets the currently unbound receiver to pass to a remote provider. There |
| // must not already be a receiver bound to this class. |
| mojo::PendingReceiver<mojom::RemoteInterfaces> GetReceiver(); |
| |
| // =========================================================================== |
| // Interface binding methods: After binding, the Remotes/PendingRemotes which |
| // are bound are guaranteed to be bound and connected (i.e. remote.is_bound() |
| // and remote.is_connected() will return true immediately). Clients can safely |
| // start issuing method calls at this point. However, if the remote provider |
| // does not fulfill the request, then the Remote/PendingRemote will become |
| // disconnected (remote.is_connected() == false), but still be bound. |
| // =========================================================================== |
| |
| // Binds a generic receiver to an implementation in the remote provider. |
| void Bind(mojo::GenericPendingReceiver receiver); |
| |
| // Binds an <Interface> implementation in the remote provider. |
| template <typename Interface> |
| void Bind(mojo::PendingReceiver<Interface> receiver) { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| remote_provider_->BindInterface(Interface::Name_, receiver.PassPipe()); |
| } |
| |
| // Binds a new message pipe to |remote|, and passes the request to the remote |
| // provider. |
| template <typename Interface> |
| void BindNewPipe(mojo::Remote<Interface>* remote) { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| auto pending_receiver = remote->BindNewPipeAndPassReceiver(); |
| Bind(std::move(pending_receiver)); |
| } |
| |
| // Dispenses a mojo::Remote<Interface> which is bound by the remote provider. |
| template <typename Interface> |
| mojo::Remote<Interface> CreateRemote() { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| mojo::Remote<Interface> remote; |
| BindNewPipe(&remote); |
| return remote; |
| } |
| |
| private: |
| void Init(); |
| |
| mojo::Remote<mojom::RemoteInterfaces> remote_provider_; |
| |
| // Temporary pending receiver which allows the client to immediately |
| // start acquiring remote interfaces while we wait for an implementation |
| // to be provided. |
| mojo::PendingReceiver<mojom::RemoteInterfaces> waiting_receiver_; |
| |
| SEQUENCE_CHECKER(sequence_checker_); |
| }; |
| |
| } // namespace chromecast |
| |
| #endif // CHROMECAST_MOJO_REMOTE_INTERFACES_H_ |