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