xref: /aosp_15_r20/external/cronet/base/fuchsia/scoped_service_publisher.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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