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 #include "base/memory/raw_ptr.h" 24 25 namespace base { 26 27 template <typename Interface> 28 class BASE_EXPORT ScopedServicePublisher { 29 public: 30 // Publishes a public service in the specified |outgoing_directory|. 31 // |outgoing_directory| and |handler| must outlive the binding. 32 ScopedServicePublisher(sys::OutgoingDirectory* outgoing_directory, 33 fidl::InterfaceRequestHandler<Interface> handler, 34 std::string_view name = Interface::Name_) 35 : ScopedServicePublisher(outgoing_directory->GetOrCreateDirectory("svc"), 36 std::move(handler), 37 name) {} 38 39 // Publishes a service in the specified |pseudo_dir|. |pseudo_dir| and 40 // |handler| must outlive the binding. 41 ScopedServicePublisher(vfs::PseudoDir* pseudo_dir, 42 fidl::InterfaceRequestHandler<Interface> handler, 43 std::string_view name = Interface::Name_) pseudo_dir_(pseudo_dir)44 : pseudo_dir_(pseudo_dir), name_(name) { 45 zx_status_t status = pseudo_dir_->AddEntry( 46 name_, std::make_unique<vfs::Service>(std::move(handler))); 47 ZX_DCHECK(status == ZX_OK, status) << "vfs::PseudoDir::AddEntry"; 48 } 49 50 ScopedServicePublisher(const ScopedServicePublisher&) = delete; 51 ScopedServicePublisher& operator=(const ScopedServicePublisher&) = delete; 52 ~ScopedServicePublisher()53 ~ScopedServicePublisher() { pseudo_dir_->RemoveEntry(name_); } 54 55 private: 56 const raw_ptr<vfs::PseudoDir> pseudo_dir_ = nullptr; 57 std::string name_; 58 }; 59 60 template <typename Protocol> 61 class BASE_EXPORT ScopedNaturalServicePublisher { 62 public: 63 // Publishes a public service in the specified |outgoing_directory|. 64 // |outgoing_directory| and |handler| must outlive the binding. The service is 65 // unpublished on destruction. 66 ScopedNaturalServicePublisher( 67 sys::OutgoingDirectory* outgoing_directory, 68 fidl::ProtocolHandler<Protocol> handler, 69 std::string_view name = fidl::DiscoverableProtocolName<Protocol>) 70 : ScopedNaturalServicePublisher( 71 outgoing_directory->GetOrCreateDirectory("svc"), 72 std::move(handler), 73 name) {} 74 75 // Publishes a service in the specified |pseudo_dir|. |pseudo_dir| and 76 // |handler| must outlive the binding. The service is unpublished on 77 // destruction. 78 ScopedNaturalServicePublisher( 79 vfs::PseudoDir* pseudo_dir, 80 fidl::ProtocolHandler<Protocol> handler, 81 std::string_view name = fidl::DiscoverableProtocolName<Protocol>) pseudo_dir_(pseudo_dir)82 : pseudo_dir_(pseudo_dir), name_(name) { 83 zx_status_t status = pseudo_dir_->AddEntry( 84 name_, std::make_unique<vfs::Service>( 85 [handler = std::move(handler)]( 86 zx::channel channel, async_dispatcher_t* dispatcher) { 87 handler(fidl::ServerEnd<Protocol>(std::move(channel))); 88 })); 89 ZX_DCHECK(status == ZX_OK, status) << "vfs::PseudoDir::AddEntry"; 90 } 91 92 ScopedNaturalServicePublisher(const ScopedNaturalServicePublisher&) = delete; 93 ScopedNaturalServicePublisher& operator=( 94 const ScopedNaturalServicePublisher&) = delete; 95 ~ScopedNaturalServicePublisher()96 ~ScopedNaturalServicePublisher() { pseudo_dir_->RemoveEntry(name_); } 97 98 private: 99 const raw_ptr<vfs::PseudoDir> pseudo_dir_ = nullptr; 100 std::string name_; 101 }; 102 103 } // namespace base 104 105 #endif // BASE_FUCHSIA_SCOPED_SERVICE_PUBLISHER_H_ 106