blob: 29d883615e6a8638fa7f89f814d1fa5b5164a67a [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <string>
#include <utility>
#include "base/macros.h"
#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "mojo/public/cpp/bindings/disconnect_reason.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
#include "mojo/public/cpp/bindings/pipe_control_message_proxy.h"
#include "mojo/public/cpp/system/message_pipe.h"
namespace mojo {
// Represents a request from a remote client for an implementation of Interface
// over a specified message pipe. The implementor of the interface should
// remove the message pipe by calling PassMessagePipe() and bind it to the
// implementation. If this is not done, the InterfaceRequest will automatically
// close the pipe on destruction. Can also represent the absence of a request
// if the client did not provide a message pipe.
template <typename Interface>
class InterfaceRequest {
// Constructs an empty InterfaceRequest, representing that the client is not
// requesting an implementation of Interface.
InterfaceRequest() {}
InterfaceRequest(decltype(nullptr)) {}
// Creates a new message pipe over which Interface is to be served, binding
// the specified InterfacePtr to one end of the message pipe and this
// InterfaceRequest to the other. For example usage, see comments on
// MakeRequest(InterfacePtr*) below.
explicit InterfaceRequest(InterfacePtr<Interface>* ptr,
scoped_refptr<base::SingleThreadTaskRunner> runner =
base::ThreadTaskRunnerHandle::Get()) {
MessagePipe pipe;
ptr->Bind(InterfacePtrInfo<Interface>(std::move(pipe.handle0), 0u),
// Takes the message pipe from another InterfaceRequest.
InterfaceRequest(InterfaceRequest&& other) {
handle_ = std::move(other.handle_);
InterfaceRequest& operator=(InterfaceRequest&& other) {
handle_ = std::move(other.handle_);
return *this;
// Assigning to nullptr resets the InterfaceRequest to an empty state,
// closing the message pipe currently bound to it (if any).
InterfaceRequest& operator=(decltype(nullptr)) {
return *this;
// Binds the request to a message pipe over which Interface is to be
// requested. If the request is already bound to a message pipe, the current
// message pipe will be closed.
void Bind(ScopedMessagePipeHandle handle) { handle_ = std::move(handle); }
// Indicates whether the request currently contains a valid message pipe.
bool is_pending() const { return handle_.is_valid(); }
// Removes the message pipe from the request and returns it.
ScopedMessagePipeHandle PassMessagePipe() { return std::move(handle_); }
bool Equals(const InterfaceRequest& other) const {
if (this == &other)
return true;
// Now that the two refer to different objects, they are equivalent if
// and only if they are both invalid.
return !is_pending() && !other.is_pending();
void ResetWithReason(uint32_t custom_reason, const std::string& description) {
if (!handle_.is_valid())
Message message =
kMasterInterfaceId, DisconnectReason(custom_reason, description));
MojoResult result = WriteMessageNew(
handle_.get(), message.TakeMojoMessage(), MOJO_WRITE_MESSAGE_FLAG_NONE);
ScopedMessagePipeHandle handle_;
// Makes an InterfaceRequest bound to the specified message pipe. If |handle|
// is empty or invalid, the resulting InterfaceRequest will represent the
// absence of a request.
template <typename Interface>
InterfaceRequest<Interface> MakeRequest(ScopedMessagePipeHandle handle) {
InterfaceRequest<Interface> request;
return std::move(request);
// Creates a new message pipe over which Interface is to be served. Binds the
// specified InterfacePtr to one end of the message pipe, and returns an
// InterfaceRequest bound to the other. The InterfacePtr should be passed to
// the client, and the InterfaceRequest should be passed to whatever will
// provide the implementation. The implementation should typically be bound to
// the InterfaceRequest using the Binding or StrongBinding classes. The client
// may begin to issue calls even before an implementation has been bound, since
// messages sent over the pipe will just queue up until they are consumed by
// the implementation.
// Example #1: Requesting a remote implementation of an interface.
// ===============================================================
// Given the following interface:
// interface Database {
// OpenTable(Table& table);
// }
// The client would have code similar to the following:
// DatabasePtr database = ...; // Connect to database.
// TablePtr table;
// database->OpenTable(MakeRequest(&table));
// Upon return from MakeRequest, |table| is ready to have methods called on it.
// Example #2: Registering a local implementation with a remote service.
// =====================================================================
// Given the following interface
// interface Collector {
// RegisterSource(Source source);
// }
// The client would have code similar to the following:
// CollectorPtr collector = ...; // Connect to Collector.
// SourcePtr source;
// InterfaceRequest<Source> source_request(&source);
// collector->RegisterSource(std::move(source));
// CreateSource(std::move(source_request)); // Create implementation locally.
template <typename Interface>
InterfaceRequest<Interface> MakeRequest(
InterfacePtr<Interface>* ptr,
scoped_refptr<base::SingleThreadTaskRunner> runner =
base::ThreadTaskRunnerHandle::Get()) {
return InterfaceRequest<Interface>(ptr, runner);
// Fuses an InterfaceRequest<T> endpoint with an InterfacePtrInfo<T> endpoint.
// Returns |true| on success or |false| on failure.
template <typename Interface>
bool FuseInterface(InterfaceRequest<Interface> request,
InterfacePtrInfo<Interface> proxy_info) {
MojoResult result = FuseMessagePipes(request.PassMessagePipe(),
return result == MOJO_RESULT_OK;
} // namespace mojo