diff options
Diffstat (limited to 'chromium/base/fuchsia/scoped_service_binding.h')
-rw-r--r-- | chromium/base/fuchsia/scoped_service_binding.h | 102 |
1 files changed, 36 insertions, 66 deletions
diff --git a/chromium/base/fuchsia/scoped_service_binding.h b/chromium/base/fuchsia/scoped_service_binding.h index 568a1ffe56b..9da1218510b 100644 --- a/chromium/base/fuchsia/scoped_service_binding.h +++ b/chromium/base/fuchsia/scoped_service_binding.h @@ -7,10 +7,13 @@ #include <lib/fidl/cpp/binding.h> #include <lib/fidl/cpp/binding_set.h> +#include <lib/fidl/cpp/interface_request.h> #include <lib/zx/channel.h> #include "base/base_export.h" #include "base/callback.h" +#include "base/fuchsia/scoped_service_publisher.h" +#include "base/optional.h" namespace sys { class OutgoingDirectory; @@ -23,128 +26,95 @@ class PseudoDir; namespace base { namespace fuchsia { -namespace internal { - -class BASE_EXPORT ScopedServiceBindingBase { - public: - explicit ScopedServiceBindingBase(sys::OutgoingDirectory* outgoing_directory); - explicit ScopedServiceBindingBase(vfs::PseudoDir* pseudo_dir); - - ~ScopedServiceBindingBase(); - - protected: - // Same type as vfs::Service::Connector, so the value can be passed directly - // to vfs::Service. - using Connector = - fit::function<void(zx::channel channel, async_dispatcher_t* dispatcher)>; - - void RegisterService(const char* service_name, Connector connector); - void UnregisterService(const char* service_name); - - private: - vfs::PseudoDir* const pseudo_dir_ = nullptr; -}; - -} // namespace internal - template <typename Interface> -class ScopedServiceBinding : public internal::ScopedServiceBindingBase { +class BASE_EXPORT ScopedServiceBinding { public: // Published a public service in the specified |outgoing_directory|. // |outgoing_directory| and |impl| must outlive the binding. ScopedServiceBinding(sys::OutgoingDirectory* outgoing_directory, Interface* impl) - : ScopedServiceBindingBase(outgoing_directory), impl_(impl) { - RegisterService(Interface::Name_, - fit::bind_member(this, &ScopedServiceBinding::BindClient)); - } + : publisher_(outgoing_directory, bindings_.GetHandler(impl)) {} // Publishes a service in the specified |pseudo_dir|. |pseudo_dir| and |impl| // must outlive the binding. ScopedServiceBinding(vfs::PseudoDir* pseudo_dir, Interface* impl) - : ScopedServiceBindingBase(pseudo_dir), impl_(impl) { - RegisterService(Interface::Name_, - fit::bind_member(this, &ScopedServiceBinding::BindClient)); - } + : publisher_(pseudo_dir, bindings_.GetHandler(impl)) {} - ~ScopedServiceBinding() { UnregisterService(Interface::Name_); } + ~ScopedServiceBinding() = default; - void SetOnLastClientCallback(base::OnceClosure on_last_client_callback) { - on_last_client_callback_ = std::move(on_last_client_callback); + // |on_last_client_callback| will be called every time the number of connected + // clients drops to 0. + void SetOnLastClientCallback(base::RepeatingClosure on_last_client_callback) { bindings_.set_empty_set_handler( - fit::bind_member(this, &ScopedServiceBinding::OnBindingSetEmpty)); + [callback = std::move(on_last_client_callback)] { callback.Run(); }); } bool has_clients() const { return bindings_.size() != 0; } private: - void BindClient(zx::channel channel, async_dispatcher_t* dispatcher) { - bindings_.AddBinding(impl_, - fidl::InterfaceRequest<Interface>(std::move(channel)), - dispatcher); - } - - void OnBindingSetEmpty() { - bindings_.set_empty_set_handler(nullptr); - std::move(on_last_client_callback_).Run(); - } - - sys::OutgoingDirectory* const directory_ = nullptr; - vfs::PseudoDir* const pseudo_dir_ = nullptr; - Interface* const impl_; fidl::BindingSet<Interface> bindings_; - base::OnceClosure on_last_client_callback_; + ScopedServicePublisher<Interface> publisher_; DISALLOW_COPY_AND_ASSIGN(ScopedServiceBinding); }; // Scoped service binding which allows only a single client to be connected // at any time. By default a new connection will disconnect an existing client. -enum class ScopedServiceBindingPolicy { kPreferNew, kPreferExisting }; +enum class ScopedServiceBindingPolicy { + kPreferNew, + kPreferExisting, + kConnectOnce +}; template <typename Interface, ScopedServiceBindingPolicy Policy = ScopedServiceBindingPolicy::kPreferNew> -class ScopedSingleClientServiceBinding - : public internal::ScopedServiceBindingBase { +class BASE_EXPORT ScopedSingleClientServiceBinding { public: // |outgoing_directory| and |impl| must outlive the binding. ScopedSingleClientServiceBinding(sys::OutgoingDirectory* outgoing_directory, Interface* impl) - : ScopedServiceBindingBase(outgoing_directory), binding_(impl) { - RegisterService( - Interface::Name_, + : binding_(impl) { + publisher_.emplace( + outgoing_directory, fit::bind_member(this, &ScopedSingleClientServiceBinding::BindClient)); + binding_.set_error_handler(fit::bind_member( + this, &ScopedSingleClientServiceBinding::OnBindingEmpty)); } - ~ScopedSingleClientServiceBinding() { UnregisterService(Interface::Name_); } + ~ScopedSingleClientServiceBinding() = default; typename Interface::EventSender_& events() { return binding_.events(); } + // |on_last_client_callback| will be called the first time a client + // disconnects. It is still possible for a client to connect after that point + // if Policy is kPreferNew of kPreferExisting. void SetOnLastClientCallback(base::OnceClosure on_last_client_callback) { on_last_client_callback_ = std::move(on_last_client_callback); - binding_.set_error_handler(fit::bind_member( - this, &ScopedSingleClientServiceBinding::OnBindingEmpty)); } bool has_clients() const { return binding_.is_bound(); } private: - void BindClient(zx::channel channel, async_dispatcher_t* dispatcher) { + void BindClient(fidl::InterfaceRequest<Interface> request) { if (Policy == ScopedServiceBindingPolicy::kPreferExisting && binding_.is_bound()) { return; } - binding_.Bind(fidl::InterfaceRequest<Interface>(std::move(channel)), - dispatcher); + binding_.Bind(std::move(request)); + if (Policy == ScopedServiceBindingPolicy::kConnectOnce) { + publisher_.reset(); + } } void OnBindingEmpty(zx_status_t status) { - binding_.set_error_handler(nullptr); - std::move(on_last_client_callback_).Run(); + if (on_last_client_callback_) { + std::move(on_last_client_callback_).Run(); + } } fidl::Binding<Interface> binding_; + base::Optional<ScopedServicePublisher<Interface>> publisher_; base::OnceClosure on_last_client_callback_; DISALLOW_COPY_AND_ASSIGN(ScopedSingleClientServiceBinding); |