Commit f2af33fc authored by yzshen's avatar yzshen Committed by Commit bot

Mojo C++ bindings: introduce public associated-interface-related types.

This includes:
- AssociatedBinding
- AssociatedGroup
- AssociatedInterfacePtr
- AssociatedInterfacePtrInfo
- AssociatedInterfaceRequest

BUG=546067

Review URL: https://codereview.chromium.org/1465293002

Cr-Commit-Position: refs/heads/master@{#361365}
parent c2a9f618
......@@ -5,6 +5,9 @@
source_set("bindings") {
sources = [
"array.h",
"associated_binding.h",
"associated_group.h",
"associated_interface_ptr.h",
"associated_interface_ptr_info.h",
"associated_interface_request.h",
"binding.h",
......@@ -14,6 +17,8 @@ source_set("bindings") {
"lib/array_internal.cc",
"lib/array_internal.h",
"lib/array_serialization.h",
"lib/associated_group.cc",
"lib/associated_interface_ptr_internal.h",
"lib/bindings_internal.h",
"lib/bindings_serialization.cc",
"lib/bindings_serialization.h",
......
// Copyright 2015 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.
#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_H_
#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_H_
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "mojo/public/cpp/bindings/associated_group.h"
#include "mojo/public/cpp/bindings/associated_interface_request.h"
#include "mojo/public/cpp/bindings/callback.h"
#include "mojo/public/cpp/bindings/lib/interface_endpoint_client.h"
#include "mojo/public/cpp/bindings/lib/multiplex_router.h"
#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h"
namespace mojo {
// Represents the implementation side of an associated interface. It is similar
// to Binding, except that it doesn't own a message pipe handle.
template <typename Interface>
class AssociatedBinding {
public:
// Constructs an incomplete associated binding that will use the
// implementation |impl|. It may be completed with a subsequent call to the
// |Bind| method. Does not take ownership of |impl|, which must outlive this
// object.
explicit AssociatedBinding(Interface* impl) : impl_(impl) {
stub_.set_sink(impl_);
}
// Constructs a completed associated binding of |impl|. The output |ptr_info|
// should be passed through the message pipe endpoint referred to by
// |associated_group| to setup the corresponding asssociated interface
// pointer. |impl| must outlive this object.
AssociatedBinding(Interface* impl,
AssociatedInterfacePtrInfo<Interface>* ptr_info,
AssociatedGroup* associated_group)
: AssociatedBinding(impl) {
Bind(ptr_info, associated_group);
}
// Constructs a completed associated binding of |impl|. |impl| must outlive
// the binding.
AssociatedBinding(Interface* impl,
AssociatedInterfaceRequest<Interface> request)
: AssociatedBinding(impl) {
Bind(request.Pass());
}
~AssociatedBinding() {}
// Creates an associated inteface and sets up this object as the
// implementation side. The output |ptr_info| should be passed through the
// message pipe endpoint referred to by |associated_group| to setup the
// corresponding asssociated interface pointer.
void Bind(AssociatedInterfacePtrInfo<Interface>* ptr_info,
AssociatedGroup* associated_group) {
AssociatedInterfaceRequest<Interface> request;
associated_group->CreateAssociatedInterface(AssociatedGroup::WILL_PASS_PTR,
ptr_info, &request);
Bind(request.Pass());
}
// Sets up this object as the implementation side of an associated interface.
void Bind(AssociatedInterfaceRequest<Interface> request) {
internal::ScopedInterfaceEndpointHandle handle =
internal::AssociatedInterfaceRequestHelper::PassHandle(&request);
DCHECK(handle.is_local())
<< "The AssociatedInterfaceRequest is supposed to be used at the "
<< "other side of the message pipe.";
if (!handle.is_valid() || !handle.is_local()) {
endpoint_client_.reset();
return;
}
endpoint_client_.reset(new internal::InterfaceEndpointClient(
handle.Pass(), &stub_,
make_scoped_ptr(new typename Interface::RequestValidator_())));
endpoint_client_->set_connection_error_handler(
[this]() { connection_error_handler_.Run(); });
}
// Closes the associated interface. Puts this object into a state where it can
// be rebound.
void Close() {
DCHECK(endpoint_client_);
endpoint_client_.reset();
}
// Unbinds and returns the associated interface request so it can be
// used in another context, such as on another thread or with a different
// implementation. Puts this object into a state where it can be rebound.
AssociatedInterfaceRequest<Interface> Unbind() {
DCHECK(endpoint_client_);
AssociatedInterfaceRequest<Interface> request;
internal::AssociatedInterfaceRequestHelper::SetHandle(
&request, endpoint_client_->PassHandle());
endpoint_client_.reset();
return request.Pass();
}
// Sets an error handler that will be called if a connection error occurs.
void set_connection_error_handler(const Closure& error_handler) {
connection_error_handler_ = error_handler;
}
// Returns the interface implementation that was previously specified.
Interface* impl() { return impl_; }
// Indicates whether the associated binding has been completed.
bool is_bound() const { return !!endpoint_client_; }
// Returns the associated group that this object belongs to. Returns null if
// the object is not bound.
AssociatedGroup* associated_group() {
return endpoint_client_ ? endpoint_client_->associated_group() : nullptr;
}
private:
scoped_ptr<internal::InterfaceEndpointClient> endpoint_client_;
typename Interface::Stub_ stub_;
Interface* impl_;
Closure connection_error_handler_;
DISALLOW_COPY_AND_ASSIGN(AssociatedBinding);
};
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_H_
// Copyright 2015 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.
#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_H_
#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_H_
#include "base/memory/ref_counted.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
#include "mojo/public/cpp/bindings/associated_interface_request.h"
#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h"
namespace mojo {
namespace internal {
class MultiplexRouter;
}
// AssociatedGroup refers to all the interface endpoints running at one end of a
// message pipe. It is used to create associated interfaces for that message
// pipe.
// It is thread safe and cheap to make copies.
class AssociatedGroup {
public:
// Configuration used by CreateAssociatedInterface(). Please see the comments
// of that method for more details.
enum AssociatedInterfaceConfig { WILL_PASS_PTR, WILL_PASS_REQUEST };
AssociatedGroup();
AssociatedGroup(const AssociatedGroup& other);
~AssociatedGroup();
AssociatedGroup& operator=(const AssociatedGroup& other);
// |config| indicates whether |ptr_info| or |request| will be sent to the
// remote side of the message pipe.
//
// NOTE: If |config| is |WILL_PASS_REQUEST|, you will want to bind |ptr_info|
// to a local AssociatedInterfacePtr to make calls. However, there is one
// restriction: the pointer should NOT be used to make calls before |request|
// is sent. Violating that will cause the message pipe to be closed. On the
// other hand, as soon as |request| is sent, the pointer is usable. There is
// no need to wait until |request| is bound to an implementation at the remote
// side.
template <typename T>
void CreateAssociatedInterface(AssociatedInterfaceConfig config,
AssociatedInterfacePtrInfo<T>* ptr_info,
AssociatedInterfaceRequest<T>* request) {
internal::ScopedInterfaceEndpointHandle local;
internal::ScopedInterfaceEndpointHandle remote;
CreateEndpointHandlePair(&local, &remote);
if (!local.is_valid() || !remote.is_valid()) {
*ptr_info = AssociatedInterfacePtrInfo<T>();
*request = AssociatedInterfaceRequest<T>();
return;
}
if (config == WILL_PASS_PTR) {
internal::AssociatedInterfacePtrInfoHelper::SetHandle(ptr_info,
remote.Pass());
// The implementation is local, therefore set the version according to
// the interface definition that this code is built against.
ptr_info->set_version(T::Version_);
internal::AssociatedInterfaceRequestHelper::SetHandle(request,
local.Pass());
} else {
internal::AssociatedInterfacePtrInfoHelper::SetHandle(ptr_info,
local.Pass());
// The implementation is remote, we don't know about its actual version
// yet.
ptr_info->set_version(0u);
internal::AssociatedInterfaceRequestHelper::SetHandle(request,
remote.Pass());
}
}
private:
friend class internal::MultiplexRouter;
void CreateEndpointHandlePair(
internal::ScopedInterfaceEndpointHandle* local_endpoint,
internal::ScopedInterfaceEndpointHandle* remote_endpoint);
scoped_refptr<internal::MultiplexRouter> router_;
};
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_H_
// Copyright 2015 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.
#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_H_
#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_H_
#include <algorithm>
#include "base/macros.h"
#include "mojo/public/cpp/bindings/associated_group.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
#include "mojo/public/cpp/bindings/associated_interface_request.h"
#include "mojo/public/cpp/bindings/callback.h"
#include "mojo/public/cpp/bindings/lib/associated_interface_ptr_internal.h"
namespace mojo {
// Represents the client side of an associated interface. It is similar to
// InterfacePtr, except that it doesn't own a message pipe handle.
template <typename Interface>
class AssociatedInterfacePtr {
MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(AssociatedInterfacePtr)
public:
// Constructs an unbound AssociatedInterfacePtr.
AssociatedInterfacePtr() {}
AssociatedInterfacePtr(decltype(nullptr)) {}
AssociatedInterfacePtr(AssociatedInterfacePtr&& other) {
internal_state_.Swap(&other.internal_state_);
}
AssociatedInterfacePtr& operator=(AssociatedInterfacePtr&& other) {
reset();
internal_state_.Swap(&other.internal_state_);
return *this;
}
// Assigning nullptr to this class causes it to closes the associated
// interface (if any) and returns the pointer to the unbound state.
AssociatedInterfacePtr& operator=(decltype(nullptr)) {
reset();
return *this;
}
~AssociatedInterfacePtr() {}
// Sets up this object as the client side of an associated interface.
// Calling with an invalid |info| has the same effect as reset(). In this
// case, the AssociatedInterfacePtr is not considered as bound.
//
// NOTE: Please see the comments of
// AssociatedGroup.CreateAssociatedInterface() about when you can use this
// object to make calls.
void Bind(AssociatedInterfacePtrInfo<Interface> info) {
reset();
bool is_local =
internal::AssociatedInterfacePtrInfoHelper::GetHandle(&info).is_local();
DCHECK(is_local) << "The AssociatedInterfacePtrInfo is supposed to be used "
"at the other side of the message pipe.";
if (info.is_valid() && is_local)
internal_state_.Bind(info.Pass());
}
bool is_bound() const { return internal_state_.is_bound(); }
Interface* get() const { return internal_state_.instance(); }
// Functions like a pointer to Interface. Must already be bound.
Interface* operator->() const { return get(); }
Interface& operator*() const { return *get(); }
// Returns the version number of the interface that the remote side supports.
uint32_t version() const { return internal_state_.version(); }
// Queries the max version that the remote side supports. On completion, the
// result will be returned as the input of |callback|. The version number of
// this object will also be updated.
void QueryVersion(const Callback<void(uint32_t)>& callback) {
internal_state_.QueryVersion(callback);
}
// If the remote side doesn't support the specified version, it will close the
// associated interface asynchronously. This does nothing if it's already
// known that the remote side supports the specified version, i.e., if
// |version <= this->version()|.
//
// After calling RequireVersion() with a version not supported by the remote
// side, all subsequent calls to interface methods will be ignored.
void RequireVersion(uint32_t version) {
internal_state_.RequireVersion(version);
}
// Closes the associated interface (if any) and returns the pointer to the
// unbound state.
void reset() {
State doomed;
internal_state_.Swap(&doomed);
}
// Indicates whether an error has been encountered. If true, method calls made
// on this interface will be dropped (and may already have been dropped).
bool encountered_error() const { return internal_state_.encountered_error(); }
// Registers a handler to receive error notifications.
//
// This method may only be called after the AssociatedInterfacePtr has been
// bound.
void set_connection_error_handler(const Closure& error_handler) {
internal_state_.set_connection_error_handler(error_handler);
}
// Unbinds and returns the associated interface pointer information which
// could be used to setup an AssociatedInterfacePtr again. This method may be
// used to move the proxy to a different thread.
//
// It is an error to call PassInterface() while there are pending responses.
// TODO: fix this restriction, it's not always obvious when there is a
// pending response.
AssociatedInterfacePtrInfo<Interface> PassInterface() {
DCHECK(!internal_state_.has_pending_callbacks());
State state;
internal_state_.Swap(&state);
return state.PassInterface();
}
// Returns the associated group that this object belongs to. Returns null if
// the object is not bound.
AssociatedGroup* associated_group() {
return internal_state_->associated_group();
}
// DO NOT USE. Exposed only for internal use and for testing.
internal::AssociatedInterfacePtrState<Interface>* internal_state() {
return &internal_state_;
}
// Allow AssociatedInterfacePtr<> to be used in boolean expressions, but not
// implicitly convertible to a real bool (which is dangerous).
private:
typedef internal::AssociatedInterfacePtrState<Interface>
AssociatedInterfacePtr::*Testable;
public:
operator Testable() const {
return internal_state_.is_bound() ? &AssociatedInterfacePtr::internal_state_
: nullptr;
}
private:
// Forbid the == and != operators explicitly, otherwise AssociatedInterfacePtr
// will be converted to Testable to do == or != comparison.
template <typename T>
bool operator==(const AssociatedInterfacePtr<T>& other) const = delete;
template <typename T>
bool operator!=(const AssociatedInterfacePtr<T>& other) const = delete;
typedef internal::AssociatedInterfacePtrState<Interface> State;
mutable State internal_state_;
};
// Creates an associated interface. The output |ptr| should be used locally
// while the returned request should be passed through the message pipe endpoint
// referred to by |associated_group| to setup the corresponding asssociated
// interface implementation at the remote side.
//
// NOTE: |ptr| should NOT be used to make calls before the request is sent.
// Violating that will cause the message pipe to be closed. On the other hand,
// as soon as the request is sent, |ptr| is usable. There is no need to wait
// until the request is bound to an implementation at the remote side.
template <typename Interface>
AssociatedInterfaceRequest<Interface> GetProxy(
AssociatedInterfacePtr<Interface>* ptr,
AssociatedGroup* group) {
AssociatedInterfaceRequest<Interface> request;
AssociatedInterfacePtrInfo<Interface> ptr_info;
group->CreateAssociatedInterface(AssociatedGroup::WILL_PASS_REQUEST,
&ptr_info, &request);
ptr->Bind(ptr_info.Pass());
return request.Pass();
}
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_H_
......@@ -5,28 +5,81 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_INFO_H_
#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_INFO_H_
#include "mojo/public/cpp/system/macros.h"
#include "base/macros.h"
#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h"
namespace mojo {
namespace internal {
class AssociatedInterfacePtrInfoHelper;
}
// AssociatedInterfacePtrInfo stores necessary information to construct an
// associated interface pointer.
// TODO(yzshen): implement it.
// associated interface pointer. It is similar to InterfacePtrInfo except that
// it doesn't own a message pipe handle.
template <typename Interface>
class AssociatedInterfacePtrInfo {
MOJO_MOVE_ONLY_TYPE(AssociatedInterfacePtrInfo);
MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(AssociatedInterfacePtrInfo);
public:
AssociatedInterfacePtrInfo() {}
AssociatedInterfacePtrInfo(AssociatedInterfacePtrInfo&& other) {}
AssociatedInterfacePtrInfo() : version_(0u) {}
AssociatedInterfacePtrInfo(AssociatedInterfacePtrInfo&& other)
: handle_(other.handle_.Pass()), version_(other.version_) {
other.version_ = 0u;
}
~AssociatedInterfacePtrInfo() {}
AssociatedInterfacePtrInfo& operator=(AssociatedInterfacePtrInfo&& other) {
if (this != &other) {
handle_ = other.handle_.Pass();
version_ = other.version_;
other.version_ = 0u;
}
return *this;
}
bool is_valid() const { return false; }
bool is_valid() const { return handle_.is_valid(); }
uint32_t version() const { return version_; }
void set_version(uint32_t version) { version_ = version; }
private:
friend class internal::AssociatedInterfacePtrInfoHelper;
internal::ScopedInterfaceEndpointHandle handle_;
uint32_t version_;
};
namespace internal {
// With this helper, AssociatedInterfacePtrInfo doesn't have to expose any
// operations related to ScopedInterfaceEndpointHandle, which is an internal
// class.
class AssociatedInterfacePtrInfoHelper {
public:
template <typename Interface>
static ScopedInterfaceEndpointHandle PassHandle(
AssociatedInterfacePtrInfo<Interface>* info) {
return info->handle_.Pass();
}
template <typename Interface>
static const ScopedInterfaceEndpointHandle& GetHandle(
AssociatedInterfacePtrInfo<Interface>* info) {
return info->handle_;
}
template <typename Interface>
static void SetHandle(AssociatedInterfacePtrInfo<Interface>* info,
ScopedInterfaceEndpointHandle handle) {
info->handle_ = handle.Pass();
}
};
} // namespace internal
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_INFO_H_
......@@ -5,27 +5,83 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_REQUEST_H_
#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_REQUEST_H_
#include "mojo/public/cpp/system/macros.h"
#include "base/macros.h"
#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h"
namespace mojo {
// Represents an associated interface request.
// TODO(yzshen): implement it.
namespace internal {
class AssociatedInterfaceRequestHelper;
}
// AssociatedInterfaceRequest represents an associated interface request. It is
// similar to InterfaceRequest except that it doesn't own a message pipe handle.
template <typename Interface>
class AssociatedInterfaceRequest {
MOJO_MOVE_ONLY_TYPE(AssociatedInterfaceRequest)
MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(AssociatedInterfaceRequest);
public:
// Constructs an empty AssociatedInterfaceRequest, representing that the
// client is not requesting an implementation of Interface.
AssociatedInterfaceRequest() {}
AssociatedInterfaceRequest(AssociatedInterfaceRequest&& other) {}
AssociatedInterfaceRequest(decltype(nullptr)) {}
// Takes the interface endpoint handle from another
// AssociatedInterfaceRequest.
AssociatedInterfaceRequest(AssociatedInterfaceRequest&& other) {
handle_ = other.handle_.Pass();
}
AssociatedInterfaceRequest& operator=(AssociatedInterfaceRequest&& other) {
if (this != &other)
handle_ = other.handle_.Pass();
return *this;
}
// Assigning to nullptr resets the AssociatedInterfaceRequest to an empty
// state, closing the interface endpoint handle currently bound to it (if
// any).
AssociatedInterfaceRequest& operator=(decltype(nullptr)) {
handle_.reset();
return *this;
}
bool is_pending() const { return false; }
// Indicates whether the request currently contains a valid interface endpoint
// handle.
bool is_pending() const { return handle_.is_valid(); }
private:
friend class internal::AssociatedInterfaceRequestHelper;
internal::ScopedInterfaceEndpointHandle handle_;
};
namespace internal {
// With this helper, AssociatedInterfaceRequest doesn't have to expose any
// operations related to ScopedInterfaceEndpointHandle, which is an internal
// class.
class AssociatedInterfaceRequestHelper {
public:
template <typename Interface>
static ScopedInterfaceEndpointHandle PassHandle(
AssociatedInterfaceRequest<Interface>* request) {
return request->handle_.Pass();
}
template <typename Interface>
static const ScopedInterfaceEndpointHandle& GetHandle(
AssociatedInterfaceRequest<Interface>* request) {
return request->handle_;
}
template <typename Interface>
static void SetHandle(AssociatedInterfaceRequest<Interface>* request,
ScopedInterfaceEndpointHandle handle) {
request->handle_ = handle.Pass();
}
};
} // namespace internal
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_REQUEST_H_
// Copyright 2015 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 "mojo/public/cpp/bindings/associated_group.h"
#include "mojo/public/cpp/bindings/lib/multiplex_router.h"
namespace mojo {
AssociatedGroup::AssociatedGroup() {}
AssociatedGroup::AssociatedGroup(const AssociatedGroup& other)
: router_(other.router_) {}
AssociatedGroup::~AssociatedGroup() {}
AssociatedGroup& AssociatedGroup::operator=(const AssociatedGroup& other) {
if (this == &other)
return *this;
router_ = other.router_;
return *this;
}
void AssociatedGroup::CreateEndpointHandlePair(
internal::ScopedInterfaceEndpointHandle* local_endpoint,
internal::ScopedInterfaceEndpointHandle* remote_endpoint) {
if (!router_)
return;
router_->CreateEndpointHandlePair(local_endpoint, remote_endpoint);
}
} // namespace mojo
// Copyright 2015 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.
#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ASSOCIATED_INTERFACE_PTR_INTERNAL_H_
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ASSOCIATED_INTERFACE_PTR_INTERNAL_H_
#include <algorithm> // For |std::swap()|.
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "mojo/public/cpp/bindings/associated_group.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
#include "mojo/public/cpp/bindings/callback.h"
#include "mojo/public/cpp/bindings/lib/control_message_proxy.h"
#include "mojo/public/cpp/bindings/lib/interface_endpoint_client.h"
#include "mojo/public/cpp/bindings/lib/interface_id.h"
#include "mojo/public/cpp/bindings/lib/multiplex_router.h"
#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h"
namespace mojo {
namespace internal {
template <typename Interface>
class AssociatedInterfacePtrState {
public:
AssociatedInterfacePtrState() : version_(0u) {}
~AssociatedInterfacePtrState() {
endpoint_client_.reset();
proxy_.reset();
}
Interface* instance() {
// This will be null if the object is not bound.
return proxy_.get();
}
uint32_t version() const { return version_; }
void QueryVersion(const Callback<void(uint32_t)>& callback) {
// It is safe to capture |this| because the callback won't be run after this
// object goes away.
auto callback_wrapper = [this, callback](uint32_t version) {
this->version_ = version;
callback.Run(version);
};
// Do a static cast in case the interface contains methods with the same
// name.
static_cast<ControlMessageProxy*>(proxy_.get())
->QueryVersion(callback_wrapper);
}
void RequireVersion(uint32_t version) {
if (version <= version_)
return;
version_ = version;
// Do a static cast in case the interface contains methods with the same
// name.
static_cast<ControlMessageProxy*>(proxy_.get())->RequireVersion(version);
}
void Swap(AssociatedInterfacePtrState* other) {
using std::swap;
swap(other->endpoint_client_, endpoint_client_);
swap(other->proxy_, proxy_);
swap(other->version_, version_);
}
void Bind(AssociatedInterfacePtrInfo<Interface> info) {
DCHECK(!endpoint_client_);
DCHECK(!proxy_);
DCHECK_EQ(0u, version_);
DCHECK(info.is_valid());
version_ = info.version();
endpoint_client_.reset(new InterfaceEndpointClient(
AssociatedInterfacePtrInfoHelper::PassHandle(&info), nullptr,
make_scoped_ptr(new typename Interface::ResponseValidator_())));
proxy_.reset(new Proxy(endpoint_client_.get()));
}
// After this method is called, the object is in an invalid state and
// shouldn't be reused.
AssociatedInterfacePtrInfo<Interface> PassInterface() {
ScopedInterfaceEndpointHandle handle = endpoint_client_->PassHandle();
endpoint_client_.reset();
proxy_.reset();
AssociatedInterfacePtrInfo<Interface> result;
result.set_version(version_);
AssociatedInterfacePtrInfoHelper::SetHandle(&result, handle.Pass());
return result.Pass();
}
bool is_bound() const { return !!endpoint_client_; }
bool encountered_error() const {
return endpoint_client_ ? endpoint_client_->encountered_error() : false;
}
void set_connection_error_handler(const Closure& error_handler) {
DCHECK(endpoint_client_);
endpoint_client_->set_connection_error_handler(error_handler);
}
// Returns true if bound and awaiting a response to a message.
bool has_pending_callbacks() const {
return endpoint_client_ && endpoint_client_->has_pending_responders();
}
AssociatedGroup* associated_group() {
return endpoint_client_ ? endpoint_client_->associated_group() : nullptr;
}
private:
using Proxy = typename Interface::Proxy_;
scoped_ptr<InterfaceEndpointClient> endpoint_client_;
scoped_ptr<Proxy> proxy_;
uint32_t version_;
DISALLOW_COPY_AND_ASSIGN(AssociatedInterfacePtrState);
};
} // namespace internal
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ASSOCIATED_INTERFACE_PTR_INTERNAL_H_
......@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
#include "mojo/public/cpp/bindings/associated_group.h"
#include "mojo/public/cpp/bindings/lib/multiplex_router.h"
namespace mojo {
......@@ -117,6 +118,12 @@ InterfaceEndpointClient::~InterfaceEndpointClient() {
handle_.router()->DetachEndpointClient(handle_);
}
AssociatedGroup* InterfaceEndpointClient::associated_group() {
if (!associated_group_)
associated_group_ = handle_.router()->CreateAssociatedGroup();
return associated_group_.get();
}
ScopedInterfaceEndpointHandle InterfaceEndpointClient::PassHandle() {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!has_pending_responders());
......
......@@ -18,8 +18,13 @@
#include "mojo/public/cpp/bindings/message_filter.h"
namespace mojo {
class AssociatedGroup;
namespace internal {
class MultiplexRouter;
// InterfaceEndpointClient handles message sending and receiving of an interface
// endpoint, either the implementation side or the client side.
// It should only be accessed and destructed on the creating thread.
......@@ -52,6 +57,7 @@ class InterfaceEndpointClient : public MessageReceiverWithResponder {
}
MultiplexRouter* router() const { return handle_.router(); }
AssociatedGroup* associated_group();
// After this call the object is in an invalid state and shouldn't be reused.
ScopedInterfaceEndpointHandle PassHandle();
......@@ -94,6 +100,7 @@ class InterfaceEndpointClient : public MessageReceiverWithResponder {
bool HandleValidatedMessage(Message* message);
ScopedInterfaceEndpointHandle handle_;
scoped_ptr<AssociatedGroup> associated_group_;
MessageReceiverWithResponderStatus* const incoming_receiver_;
scoped_ptr<MessageFilter> payload_validator_;
......
......@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
#include "mojo/public/cpp/bindings/associated_group.h"
#include "mojo/public/cpp/bindings/lib/interface_endpoint_client.h"
namespace mojo {
......@@ -284,6 +285,17 @@ void MultiplexRouter::RaiseError() {
}
}
scoped_ptr<AssociatedGroup> MultiplexRouter::CreateAssociatedGroup() {
scoped_ptr<AssociatedGroup> group(new AssociatedGroup);
group->router_ = this;
return group.Pass();
}
// static
MultiplexRouter* MultiplexRouter::GetRouter(AssociatedGroup* associated_group) {
return associated_group->router_.get();
}
ScopedMessagePipeHandle MultiplexRouter::PassMessagePipe() {
DCHECK(thread_checker_.CalledOnValidThread());
{
......
......@@ -27,6 +27,9 @@
#include "mojo/public/cpp/environment/environment.h"
namespace mojo {
class AssociatedGroup;
namespace internal {
class InterfaceEndpointClient;
......@@ -85,6 +88,10 @@ class MultiplexRouter
// and notifies all interfaces running on this pipe.
void RaiseError();
scoped_ptr<AssociatedGroup> CreateAssociatedGroup();
static MultiplexRouter* GetRouter(AssociatedGroup* associated_group);
// ---------------------------------------------------------------------------
// The following public methods are called on the creating thread.
......
......@@ -35,12 +35,7 @@ ScopedInterfaceEndpointHandle::~ScopedInterfaceEndpointHandle() {
ScopedInterfaceEndpointHandle& ScopedInterfaceEndpointHandle::operator=(
ScopedInterfaceEndpointHandle&& other) {
reset();
id_ = other.id_;
is_local_ = other.is_local_;
router_.swap(other.router_);
other.id_ = kInvalidInterfaceId;
swap(other);
return *this;
}
......@@ -52,6 +47,7 @@ void ScopedInterfaceEndpointHandle::reset() {
router_->CloseEndpointHandle(id_, is_local_);
id_ = kInvalidInterfaceId;
is_local_ = true;
router_ = nullptr;
}
......@@ -66,6 +62,7 @@ InterfaceId ScopedInterfaceEndpointHandle::release() {
InterfaceId result = id_;
id_ = kInvalidInterfaceId;
is_local_ = true;
router_ = nullptr;
return result;
......
......@@ -9,6 +9,7 @@ source_set("tests") {
sources = [
"array_unittest.cc",
"associated_interface_unittest.cc",
"binding_callback_unittest.cc",
"binding_unittest.cc",
"bounds_checker_unittest.cc",
......
......@@ -28,3 +28,13 @@ interface InterfacePassesAssociated {
PassUnion(UnionContainsAssociated foo_union) =>
(UnionContainsAssociated foo_union);
};
interface IntegerSender {
Echo(int32 value) => (int32 value);
Send(int32 value);
};
interface IntegerSenderConnection {
GetSender(associated IntegerSender& sender);
AsyncGetSender() => (associated IntegerSender sender);
};
......@@ -40,12 +40,14 @@
'mojo_edk.gyp:mojo_run_all_unittests',
'mojo_public.gyp:mojo_cpp_bindings',
'mojo_public.gyp:mojo_public_bindings_test_utils',
'mojo_public.gyp:mojo_public_test_associated_interfaces',
'mojo_public.gyp:mojo_public_test_interfaces',
'mojo_public.gyp:mojo_public_test_utils',
'mojo_public.gyp:mojo_utility',
],
'sources': [
'../../mojo/public/cpp/bindings/tests/array_unittest.cc',
'../../mojo/public/cpp/bindings/tests/associated_interface_unittest.cc',
'../../mojo/public/cpp/bindings/tests/bounds_checker_unittest.cc',
'../../mojo/public/cpp/bindings/tests/buffer_unittest.cc',
'../../mojo/public/cpp/bindings/tests/connector_unittest.cc',
......
......@@ -97,6 +97,11 @@
],
'sources': [
'../../mojo/public/cpp/bindings/array.h',
'../../mojo/public/cpp/bindings/associated_binding.h',
'../../mojo/public/cpp/bindings/associated_group.h',
'../../mojo/public/cpp/bindings/associated_interface_ptr.h',
'../../mojo/public/cpp/bindings/associated_interface_ptr_info.h',
'../../mojo/public/cpp/bindings/associated_interface_request.h',
'../../mojo/public/cpp/bindings/binding.h',
'../../mojo/public/cpp/bindings/callback.h',
'../../mojo/public/cpp/bindings/interface_ptr.h',
......@@ -104,6 +109,8 @@
'../../mojo/public/cpp/bindings/lib/array_internal.cc',
'../../mojo/public/cpp/bindings/lib/array_internal.h',
'../../mojo/public/cpp/bindings/lib/array_serialization.h',
'../../mojo/public/cpp/bindings/lib/associated_group.cc',
'../../mojo/public/cpp/bindings/lib/associated_interface_ptr_internal.h',
'../../mojo/public/cpp/bindings/lib/bindings_internal.h',
'../../mojo/public/cpp/bindings/lib/bindings_serialization.cc',
'../../mojo/public/cpp/bindings/lib/bindings_serialization.h',
......@@ -369,6 +376,31 @@
'mojo_cpp_bindings',
],
},
{
'target_name': 'mojo_public_test_associated_interfaces_mojom',
'type': 'none',
'variables': {
# These files are not included in the mojo_public_test_interfaces_mojom
# target because associated interfaces are not supported by all bindings
# languages yet.
'mojom_files': [
'../../mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom',
],
},
'includes': [ 'mojom_bindings_generator_explicit.gypi' ],
},
{
# GN version: //mojo/public/interfaces/bindings/tests:test_associated_interfaces
'target_name': 'mojo_public_test_associated_interfaces',
'type': 'static_library',
'export_dependent_settings': [
'mojo_cpp_bindings',
],
'dependencies': [
'mojo_public_test_associated_interfaces_mojom',
'mojo_cpp_bindings',
],
},
],
'conditions': [
['OS == "android"', {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment