1 // Copyright 2020 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_FUCHSIA_SCOPED_SERVICE_PUBLISHER_H_ 6 #define BASE_FUCHSIA_SCOPED_SERVICE_PUBLISHER_H_ 7 8 #include <lib/async/dispatcher.h> 9 #include <lib/fidl/cpp/interface_request.h> 10 #include <lib/fidl/cpp/wire/connect_service.h> 11 #include <lib/sys/cpp/outgoing_directory.h> 12 #include <lib/vfs/cpp/pseudo_dir.h> 13 #include <lib/vfs/cpp/service.h> 14 #include <lib/zx/channel.h> 15 16 #include <memory> 17 #include <string> 18 #include <string_view> 19 #include <utility> 20 21 #include "base/base_export.h" 22 #include "base/fuchsia/fuchsia_logging.h" 23 24 namespace base { 25 26 template <typename Interface> 27 class BASE_EXPORT ScopedServicePublisher { 28 public: 29 // Publishes a public service in the specified |outgoing_directory|. 30 // |outgoing_directory| and |handler| must outlive the binding. 31 ScopedServicePublisher(sys::OutgoingDirectory* outgoing_directory, 32 fidl::InterfaceRequestHandler<Interface> handler, 33 std::string_view name = Interface::Name_) 34 : ScopedServicePublisher(outgoing_directory->GetOrCreateDirectory("svc"), 35 std::move(handler), 36 name) {} 37 38 // Publishes a service in the specified |pseudo_dir|. |pseudo_dir| and 39 // |handler| must outlive the binding. 40 ScopedServicePublisher(vfs::PseudoDir* pseudo_dir, 41 fidl::InterfaceRequestHandler<Interface> handler, 42 std::string_view name = Interface::Name_) pseudo_dir_(pseudo_dir)43 : pseudo_dir_(pseudo_dir), name_(name) { 44 zx_status_t status = pseudo_dir_->AddEntry( 45 name_, std::make_unique<vfs::Service>(std::move(handler))); 46 ZX_DCHECK(status == ZX_OK, status) << "vfs::PseudoDir::AddEntry"; 47 } 48 49 ScopedServicePublisher(const ScopedServicePublisher&) = delete; 50 ScopedServicePublisher& operator=(const ScopedServicePublisher&) = delete; 51 ~ScopedServicePublisher()52 ~ScopedServicePublisher() { pseudo_dir_->RemoveEntry(name_); } 53 54 private: 55 vfs::PseudoDir* const pseudo_dir_ = nullptr; 56 std::string name_; 57 }; 58 59 template <typename Protocol> 60 class BASE_EXPORT ScopedNaturalServicePublisher { 61 public: 62 // Publishes a public service in the specified |outgoing_directory|. 63 // |outgoing_directory| and |handler| must outlive the binding. The service is 64 // unpublished on destruction. 65 ScopedNaturalServicePublisher( 66 sys::OutgoingDirectory* outgoing_directory, 67 fidl::ProtocolHandler<Protocol> handler, 68 std::string_view name = fidl::DiscoverableProtocolName<Protocol>) 69 : ScopedNaturalServicePublisher( 70 outgoing_directory->GetOrCreateDirectory("svc"), 71 std::move(handler), 72 name) {} 73 74 // Publishes a service in the specified |pseudo_dir|. |pseudo_dir| and 75 // |handler| must outlive the binding. The service is unpublished on 76 // destruction. 77 ScopedNaturalServicePublisher( 78 vfs::PseudoDir* pseudo_dir, 79 fidl::ProtocolHandler<Protocol> handler, 80 std::string_view name = fidl::DiscoverableProtocolName<Protocol>) pseudo_dir_(pseudo_dir)81 : pseudo_dir_(pseudo_dir), name_(name) { 82 zx_status_t status = pseudo_dir_->AddEntry( 83 name_, std::make_unique<vfs::Service>( 84 [handler = std::move(handler)]( 85 zx::channel channel, async_dispatcher_t* dispatcher) { 86 handler(fidl::ServerEnd<Protocol>(std::move(channel))); 87 })); 88 ZX_DCHECK(status == ZX_OK, status) << "vfs::PseudoDir::AddEntry"; 89 } 90 91 ScopedNaturalServicePublisher(const ScopedNaturalServicePublisher&) = delete; 92 ScopedNaturalServicePublisher& operator=( 93 const ScopedNaturalServicePublisher&) = delete; 94 ~ScopedNaturalServicePublisher()95 ~ScopedNaturalServicePublisher() { pseudo_dir_->RemoveEntry(name_); } 96 97 private: 98 vfs::PseudoDir* const pseudo_dir_ = nullptr; 99 std::string name_; 100 }; 101 102 } // namespace base 103 104 #endif // BASE_FUCHSIA_SCOPED_SERVICE_PUBLISHER_H_ 105