1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_PUBLIC_CPP_BINDINGS_SERVICE_FACTORY_H_
#define MOJO_PUBLIC_CPP_BINDINGS_SERVICE_FACTORY_H_
#include <map>
#include <memory>
#include "base/component_export.h"
#include "base/containers/flat_set.h"
#include "base/containers/unique_ptr_adapters.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/generic_pending_receiver.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "mojo/public/cpp/system/simple_watcher.h"
namespace mojo {
namespace internal {
template <typename Func>
struct ServiceFactoryTraits;
}
// ServiceFactory is a helper that Mojo consumers can use to conveniently handle
// dynamic service interface requests via a GenericPendingReceiver by matching
// the receiver's interface type against a series of strongly-typed factory
// function pointers, each with the signature:
//
// std::unique_ptr<T>(mojo::PendingReceiver<Interface>)
//
// where |T| is any type (generally an implementation of |Interface|), and
// |Interface| is a mojom interface.
//
// Any time |RunService()| is called on the ServiceFactory, it will match the
// GenericPendingReceiver argument's interface type against the list of
// factories it has available and run the corresponding function, retaining
// ownership of the returned object until the corresponding receiver is
// disconnected.
//
// Typical usage might look something like:
//
// auto RunFooService(mojo::PendingReceiver<foo::mojom::Foo> receiver) {
// return std::make_unique<foo::FooImpl>(std::move(receiver));
// }
//
// auto RunBarService(mojo::PendingReceiver<bar::mojom::Bar> receiver) {
// return std::make_unique<bar::BarImpl>(std::move(receiver));
// }
//
// void RegisterServices(mojo::ServiceFactory& services) {
// services.Add(RunFooService);
// services.Add(RunBarService);
// }
//
// void HandleServiceRequest(const mojo::ServiceFactory& factory,
// mojo::GenericPendingReceiver receiver) {
// if (factory.CanRunService(receiver)) {
// factory.RunService(std::move(receiver), base::NullCallback());
// return;
// }
//
// // The receiver was for neither the Foo nor Bar service. Sad!
// LOG(ERROR) << "Unknown service: " << *receiver.interface_name();
// }
//
class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) ServiceFactory {
public:
ServiceFactory();
ServiceFactory(const ServiceFactory&) = delete;
ServiceFactory& operator=(const ServiceFactory&) = delete;
~ServiceFactory();
// Adds a new service to the factory. The argument may be any function that
// accepts a single PendingReceiver<T> and returns a unique_ptr<T>, where T is
// a service interface (that is, a generated mojom interface class
// corresponding to some service's main interface.) Safely drops registration
// if Interface is RuntimeFeature disabled. CanRunService() will return false
// for these ignored Interfaces.
template <typename Func>
void Add(Func func) {
using Interface = typename internal::ServiceFactoryTraits<Func>::Interface;
if (internal::GetRuntimeFeature_IsEnabled<Interface>()) {
constructors_[Interface::Name_] =
base::BindRepeating(&RunConstructor<Func>, func);
}
}
// If `receiver` is references an interface matching a service known to this
// factory, this returns true. Otherwise it returns false. `receiver` MUST be
// valid.
bool CanRunService(const GenericPendingReceiver& receiver) const;
// Consumes `receiver` and binds it to a new instance of the corresponding
// service, constructed using the service's registered function within this
// factory.
//
// `termination_callback`, if not null, will be invoked on the calling
// TaskRunner whenever the new service instance is eventually destroyed.
//
// If the service represented by `receiver` is not known to this factory, it
// is discarded and `termination_callback` is never run.
bool RunService(GenericPendingReceiver receiver,
base::OnceClosure termination_callback);
private:
class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) InstanceHolderBase {
public:
InstanceHolderBase();
InstanceHolderBase(const InstanceHolderBase&) = delete;
InstanceHolderBase& operator=(const InstanceHolderBase&) = delete;
virtual ~InstanceHolderBase();
void WatchPipe(MessagePipeHandle pipe,
base::OnceClosure disconnect_callback);
private:
void OnPipeSignaled(MojoResult result, const HandleSignalsState& state);
SimpleWatcher watcher_;
base::OnceClosure disconnect_callback_;
};
template <typename Impl>
class InstanceHolder : public InstanceHolderBase {
public:
explicit InstanceHolder(std::unique_ptr<Impl> instance)
: instance_(std::move(instance)) {}
InstanceHolder(const InstanceHolder&) = delete;
InstanceHolder& operator=(const InstanceHolder&) = delete;
~InstanceHolder() override = default;
private:
const std::unique_ptr<Impl> instance_;
};
template <typename Func>
static std::unique_ptr<InstanceHolderBase> RunConstructor(
Func fn,
GenericPendingReceiver receiver) {
using Interface = typename internal::ServiceFactoryTraits<Func>::Interface;
using Impl = typename internal::ServiceFactoryTraits<Func>::Impl;
auto impl = fn(receiver.As<Interface>());
if (!impl)
return nullptr;
return std::make_unique<InstanceHolder<Impl>>(std::move(impl));
}
void OnInstanceDisconnected(InstanceHolderBase* instance);
using Constructor =
base::RepeatingCallback<std::unique_ptr<InstanceHolderBase>(
GenericPendingReceiver)>;
std::map<std::string, Constructor> constructors_;
base::flat_set<std::unique_ptr<InstanceHolderBase>, base::UniquePtrComparator>
instances_;
base::WeakPtrFactory<ServiceFactory> weak_ptr_factory_{this};
};
namespace internal {
template <typename ImplType, typename InterfaceType>
struct ServiceFactoryTraits<std::unique_ptr<ImplType> (*)(
PendingReceiver<InterfaceType>)> {
using Interface = InterfaceType;
using Impl = ImplType;
};
} // namespace internal
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_SERVICE_FACTORY_H_
|