chromium/mojo/public/cpp/bindings/service_factory.h

// 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 {};

namespace internal {

ServiceFactoryTraits<std::unique_ptr<ImplType> (*)(PendingReceiver<InterfaceType>)>;

}  // namespace internal

}  // namespace mojo

#endif  // MOJO_PUBLIC_CPP_BINDINGS_SERVICE_FACTORY_H_