chromium/chromecast/external_mojo/external_service_support/external_service.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 CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_EXTERNAL_SERVICE_H_
#define CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_EXTERNAL_SERVICE_H_

#include <map>
#include <memory>
#include <string>
#include <utility>

#include "base/functional/callback.h"
#include "base/sequence_checker.h"
#include "chromecast/external_mojo/public/mojom/connector.mojom.h"
#include "chromecast/mojo/interface_bundle.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/system/message_pipe.h"

namespace chromecast {
namespace external_service_support {

// API for external (non-Chromium process) Mojo services.
class ExternalService : public external_mojo::mojom::ExternalService {
 public:
  ExternalService();

  ExternalService(const ExternalService&) = delete;
  ExternalService& operator=(const ExternalService&) = delete;

  ~ExternalService() override;

  // Returns the Mojo receiver for this service.
  mojo::PendingRemote<external_mojo::mojom::ExternalService> GetReceiver();

  // Adds an interface that users of this service may bind to. To avoid races
  // where the service is registered but interfaces cannot be bound by other
  // processes/services, add all interfaces before registering this service.
  // The |bind_callback| will be called once for each bind attempt. The callback
  // will not be called after this ExternalService instance is destroyed.
  template <typename Interface>
  void AddInterface(
      base::RepeatingCallback<void(mojo::PendingReceiver<Interface>)>
          bind_callback) {
    RemoveInterface<Interface>();
    bundle_.AddBinder(std::move(bind_callback));
  }

  // Convenience method for exposing an interface. The implementation must
  // outlive the service or be explicitly removed before the implementation is
  // destroyed.
  template <typename Interface>
  void AddInterface(Interface* interface) {
    RemoveInterface<Interface>();
    bundle_.AddInterface<Interface>(interface);
  }

  // Removes an interface, preventing new bindings from being created. Does not
  // affect existing bindings.
  template <typename Interface>
  void RemoveInterface() {
    bundle_.RemoveInterface<Interface>();
  }

  InterfaceBundle* bundle() { return &bundle_; }

 private:
  // external_mojo::mojom::ExternalService implementation:
  void OnBindInterface(const std::string& interface_name,
                       mojo::ScopedMessagePipeHandle interface_pipe) override;

  InterfaceBundle bundle_;
  mojo::Receiver<external_mojo::mojom::ExternalService> service_receiver_{this};

  SEQUENCE_CHECKER(sequence_checker_);
};

}  // namespace external_service_support
}  // namespace chromecast

#endif  // CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_EXTERNAL_SERVICE_H_