summaryrefslogtreecommitdiffstats
path: root/mojo/public
diff options
context:
space:
mode:
authordarin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-09 22:35:51 +0000
committerdarin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-09 22:35:51 +0000
commit5e1a832c8186ef29546b6b60f90d7974ca72d3c9 (patch)
tree41b3fd3eaf316e7353a566c2b8923566788dd446 /mojo/public
parent92028f1406eeb252247b55b8db63b1b8cdf69945 (diff)
downloadchromium_src-5e1a832c8186ef29546b6b60f90d7974ca72d3c9.zip
chromium_src-5e1a832c8186ef29546b6b60f90d7974ca72d3c9.tar.gz
chromium_src-5e1a832c8186ef29546b6b60f90d7974ca72d3c9.tar.bz2
Mojo: Replace RemotePtr with InterfacePtr and InterfaceImpl
Interfaces no longer have explicit Peer attributes. An interface may now optionally have a Client interface, in which case a SetClient method will be auto-generated. InterfacePtr is a proxy to a remote instance of an interface. InterfaceImpl is a base class used when implementing an interface. Both have facilities for binding to a pipe, etc. An InterfacePtr is movable but not copyable and looks a lot like RemotePtr save for how it gets initialized (via the Bind method now). I've added some new top-level functions: MakeProxy - makes it easy to initialize an InterfacePtr in say a member initializer list. BindToPipe - this is how you bind an InterfaceImpl to a pipe. once bound, they cannot be unbound until the object is destroyed or the pipe is closed. BindToProxy - builds on top of BindToPipe, however, it hides the details of the pipe. What you get back is an InterfacePtr. Generated C++ code now passes InterfacePtr instead of InterfaceHandle. As a result, we have far less need for typed subclasses of MessagePipeHandle, so I eliminated them. The code that needs to deal with raw handles generally has to deal with {Scoped}MessagePipeHandle, and adding strong typing to these handles doesn't seem helpful anymore. R=davemoore@chromium.org Review URL: https://codereview.chromium.org/265793015 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@269443 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'mojo/public')
-rw-r--r--mojo/public/cpp/bindings/BUILD.gn6
-rw-r--r--mojo/public/cpp/bindings/error_handler.h12
-rw-r--r--mojo/public/cpp/bindings/interface.h92
-rw-r--r--mojo/public/cpp/bindings/interface_impl.h79
-rw-r--r--mojo/public/cpp/bindings/interface_ptr.h116
-rw-r--r--mojo/public/cpp/bindings/lib/array_internal.h1
-rw-r--r--mojo/public/cpp/bindings/lib/connector.cc12
-rw-r--r--mojo/public/cpp/bindings/lib/connector.h7
-rw-r--r--mojo/public/cpp/bindings/lib/interface_impl_internal.h72
-rw-r--r--mojo/public/cpp/bindings/lib/interface_ptr_internal.h108
-rw-r--r--mojo/public/cpp/bindings/lib/no_interface.cc (renamed from mojo/public/cpp/bindings/lib/interface.cc)2
-rw-r--r--mojo/public/cpp/bindings/lib/router.h8
-rw-r--r--mojo/public/cpp/bindings/no_interface.h52
-rw-r--r--mojo/public/cpp/bindings/remote_ptr.h161
-rw-r--r--mojo/public/cpp/bindings/sync_dispatcher.h10
-rw-r--r--mojo/public/cpp/bindings/tests/array_unittest.cc26
-rw-r--r--mojo/public/cpp/bindings/tests/handle_passing_unittest.cc155
-rw-r--r--mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc (renamed from mojo/public/cpp/bindings/tests/remote_ptr_unittest.cc)113
-rw-r--r--mojo/public/cpp/bindings/tests/request_response_unittest.cc38
-rw-r--r--mojo/public/cpp/bindings/tests/sample_service_unittest.cc32
-rw-r--r--mojo/public/cpp/shell/application.h8
-rw-r--r--mojo/public/cpp/shell/lib/application.cc4
-rw-r--r--mojo/public/cpp/shell/lib/service.cc5
-rw-r--r--mojo/public/cpp/shell/service.h125
-rw-r--r--mojo/public/interfaces/bindings/tests/math_calculator.mojom3
-rw-r--r--mojo/public/interfaces/bindings/tests/sample_factory.mojom3
-rw-r--r--mojo/public/interfaces/bindings/tests/sample_interfaces.mojom4
-rw-r--r--mojo/public/interfaces/bindings/tests/sample_service.mojom5
-rw-r--r--mojo/public/interfaces/shell/shell.mojom3
-rw-r--r--mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl21
-rw-r--r--mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl14
-rw-r--r--mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl6
-rw-r--r--mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl4
-rw-r--r--mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl9
-rw-r--r--mojo/public/tools/bindings/generators/mojom_cpp_generator.py13
-rw-r--r--mojo/public/tools/bindings/pylib/mojom/generate/data.py4
-rw-r--r--mojo/public/tools/bindings/pylib/mojom/generate/data_tests.py2
-rw-r--r--mojo/public/tools/bindings/pylib/mojom/generate/generator.py3
-rw-r--r--mojo/public/tools/bindings/pylib/mojom/generate/module.py4
-rw-r--r--mojo/public/tools/bindings/pylib/mojom/parse/translate.py2
40 files changed, 801 insertions, 543 deletions
diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn
index 66b8733..9753c73 100644
--- a/mojo/public/cpp/bindings/BUILD.gn
+++ b/mojo/public/cpp/bindings/BUILD.gn
@@ -9,10 +9,10 @@ source_set("bindings") {
"buffer.h",
"callback.h",
"error_handler.h",
- "interface.h",
+ "interface_ptr.h",
"message.h",
+ "no_interface.h",
"passable.h",
- "remote_ptr.h",
"sync_dispatcher.h",
"type_converter.h",
"lib/array.cc",
@@ -27,13 +27,13 @@ source_set("bindings") {
"lib/connector.h",
"lib/fixed_buffer.cc",
"lib/fixed_buffer.h",
- "lib/interface.cc",
"lib/message.cc",
"lib/message_builder.cc",
"lib/message_builder.h",
"lib/message_internal.h",
"lib/message_queue.cc",
"lib/message_queue.h",
+ "lib/no_interface.cc",
"lib/router.cc",
"lib/router.h",
"lib/scratch_buffer.cc",
diff --git a/mojo/public/cpp/bindings/error_handler.h b/mojo/public/cpp/bindings/error_handler.h
index 25c0d65..a6f0a4a 100644
--- a/mojo/public/cpp/bindings/error_handler.h
+++ b/mojo/public/cpp/bindings/error_handler.h
@@ -7,10 +7,20 @@
namespace mojo {
+// This interface is used to report connection errors.
class ErrorHandler {
public:
virtual ~ErrorHandler() {}
- virtual void OnError() = 0;
+ virtual void OnConnectionError() = 0;
+};
+
+// Used when you'd like to extend a base class with the same method signature
+// as ErrorHandler.
+template <typename Base>
+class WithErrorHandler : public Base {
+ public:
+ virtual ~WithErrorHandler() {}
+ virtual void OnConnectionError() = 0;
};
} // namespace mojo
diff --git a/mojo/public/cpp/bindings/interface.h b/mojo/public/cpp/bindings/interface.h
deleted file mode 100644
index bba8fef..0000000
--- a/mojo/public/cpp/bindings/interface.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// 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.
-
-#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_H_
-#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_H_
-
-#include <assert.h>
-
-#include "mojo/public/cpp/bindings/message.h"
-#include "mojo/public/cpp/system/core.h"
-
-namespace mojo {
-
-
-// NoInterface is for use in cases when a non-existent or empty interface is
-// needed (e.g., when the Mojom "Peer" attribute is not present).
-
-class NoInterface;
-
-class NoInterfaceStub : public MessageReceiver {
- public:
- NoInterfaceStub(NoInterface* unused) {}
- virtual bool Accept(Message* message) MOJO_OVERRIDE;
- virtual bool AcceptWithResponder(Message* message, MessageReceiver* responder)
- MOJO_OVERRIDE;
-};
-
-class NoInterface {
- public:
- typedef NoInterfaceStub _Stub;
- typedef NoInterface _Peer;
-};
-
-
-// AnyInterface is for use in cases where any interface would do (e.g., see the
-// Shell::Connect method).
-
-typedef NoInterface AnyInterface;
-
-
-// InterfaceHandle<S>
-
-template <typename S>
-class InterfaceHandle : public MessagePipeHandle {
- public:
- InterfaceHandle() {}
- explicit InterfaceHandle(MojoHandle value) : MessagePipeHandle(value) {}
-};
-
-
-// Interface<S>
-
-template <typename S>
-struct Interface {
- typedef InterfaceHandle<S> Handle;
- typedef ScopedHandleBase<InterfaceHandle<S> > ScopedHandle;
-};
-
-template <>
-struct Interface<mojo::NoInterface> {
- typedef MessagePipeHandle Handle;
- typedef ScopedMessagePipeHandle ScopedHandle;
-};
-
-
-// InterfacePipe<S,P> is used to construct a MessagePipe with typed interfaces
-// on either end.
-
-template <typename S, typename P = typename S::_Peer>
-class InterfacePipe {
- public:
- InterfacePipe() {
- typename Interface<S>::Handle h0;
- typename Interface<P>::Handle h1;
- MojoResult result MOJO_ALLOW_UNUSED =
- MojoCreateMessagePipe(h0.mutable_value(), h1.mutable_value());
- assert(result == MOJO_RESULT_OK);
- handle_to_self.reset(h0);
- handle_to_peer.reset(h1);
- }
-
- typename Interface<S>::ScopedHandle handle_to_self;
- typename Interface<P>::ScopedHandle handle_to_peer;
-};
-
-// TODO(darin): Once we have the ability to use C++11 features, consider
-// defining a template alias for ScopedInterfaceHandle<S>.
-
-} // namespace mojo
-
-#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_H_
diff --git a/mojo/public/cpp/bindings/interface_impl.h b/mojo/public/cpp/bindings/interface_impl.h
new file mode 100644
index 0000000..ec6bc91
--- /dev/null
+++ b/mojo/public/cpp/bindings/interface_impl.h
@@ -0,0 +1,79 @@
+// 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.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_IMPL_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_IMPL_H_
+
+#include "mojo/public/cpp/bindings/lib/interface_impl_internal.h"
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+
+// InterfaceImpl<..> is designed to be the base class of an interface
+// implementation. It may be bound to a pipe or a proxy, see BindToPipe and
+// BindToProxy.
+//
+// NOTE: A base class of WithErrorHandler<Interface> is used to avoid multiple
+// inheritance. This base class inserts the signature of ErrorHandler into the
+// inheritance chain.
+template <typename Interface>
+class InterfaceImpl : public WithErrorHandler<Interface> {
+ public:
+ InterfaceImpl() : internal_state_(this) {}
+ virtual ~InterfaceImpl() {}
+
+ // Subclasses must handle connection errors.
+ virtual void OnConnectionError() = 0;
+
+ // DO NOT USE. Exposed only for internal use and for testing.
+ internal::InterfaceImplState<Interface>* internal_state() {
+ return &internal_state_;
+ }
+
+ private:
+ internal::InterfaceImplState<Interface> internal_state_;
+ MOJO_DISALLOW_COPY_AND_ASSIGN(InterfaceImpl);
+};
+
+// Takes an instance of an InterfaceImpl<..> subclass and binds it to the given
+// MessagePipe. The instance is returned for convenience in member initializer
+// lists, etc. If the pipe is closed, the instance's OnConnectionError method
+// will be called.
+//
+// The instance is also bound to the current thread. Its methods will only be
+// called on the current thread, and if the current thread exits, then it will
+// also be deleted, and along with it, its end point of the pipe will be closed.
+//
+// Before returning, the instance will receive a SetClient call, providing it
+// with a proxy to the client on the other end of the pipe.
+template <typename Impl>
+Impl* BindToPipe(Impl* instance,
+ ScopedMessagePipeHandle handle,
+ MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter()) {
+ instance->internal_state()->Bind(handle.Pass(), waiter);
+ return instance;
+}
+
+// Takes an instance of an InterfaceImpl<..> subclass and binds it to the given
+// InterfacePtr<..>. The instance is returned for convenience in member
+// initializer lists, etc. If the pipe is closed, the instance's
+// OnConnectionError method will be called.
+//
+// The instance is also bound to the current thread. Its methods will only be
+// called on the current thread, and if the current thread exits, then it will
+// also be deleted, and along with it, its end point of the pipe will be closed.
+//
+// Before returning, the instance will receive a SetClient call, providing it
+// with a proxy to the client on the other end of the pipe.
+template <typename Impl, typename Interface>
+Impl* BindToProxy(Impl* instance,
+ InterfacePtr<Interface>* ptr,
+ MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter()) {
+ instance->internal_state()->BindProxy(ptr, waiter);
+ return instance;
+}
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_IMPL_H_
diff --git a/mojo/public/cpp/bindings/interface_ptr.h b/mojo/public/cpp/bindings/interface_ptr.h
new file mode 100644
index 0000000..91bd6ba
--- /dev/null
+++ b/mojo/public/cpp/bindings/interface_ptr.h
@@ -0,0 +1,116 @@
+// 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.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_
+
+#include <assert.h>
+
+#include <algorithm>
+
+#include "mojo/public/cpp/bindings/error_handler.h"
+#include "mojo/public/cpp/bindings/lib/interface_ptr_internal.h"
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+class ErrorHandler;
+
+// InterfacePtr represents a proxy to a remote instance of an interface.
+template <typename Interface>
+class InterfacePtr {
+ MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(InterfacePtr, RValue)
+ public:
+ InterfacePtr() {}
+
+ InterfacePtr(RValue other) {
+ other.object->internal_state_.Swap(&internal_state_);
+ }
+ InterfacePtr& operator=(RValue other) {
+ other.object->internal_state_.Swap(&internal_state_);
+ return *this;
+ }
+
+ ~InterfacePtr() {}
+
+ Interface* get() const {
+ return internal_state_.instance();
+ }
+ Interface* operator->() const { return get(); }
+ Interface* operator*() const { return get(); }
+
+ void reset() {
+ State doomed;
+ internal_state_.Swap(&doomed);
+ }
+
+ // This method configures the InterfacePtr<..> to be a proxy to a remote
+ // object on the other end of the given pipe.
+ //
+ // The proxy is bound to the current thread, which means its methods may
+ // only be called on the current thread.
+ //
+ // To move a bound InterfacePtr<..> to another thread, call
+ // ResetAndReturnMessagePipe. Then create a new InterfacePtr<..> on another
+ // thread, and bind the new InterfacePtr<..> to the message pipe on that
+ // thread.
+ void Bind(ScopedMessagePipeHandle handle,
+ MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter()) {
+ reset();
+ internal_state_.ConfigureProxy(handle.Pass(), waiter);
+ }
+
+ // This method may be called to query if the underlying pipe has encountered
+ // an error. If true, this means method calls made on this interface will be
+ // dropped (and may have already been dropped) on the floor.
+ bool encountered_error() const {
+ assert(internal_state_.router());
+ return internal_state_.router()->encountered_error();
+ }
+
+ // This method may be called to register an ErrorHandler to observe a
+ // connection error on the underlying pipe. The callback runs asynchronously
+ // from the current message loop.
+ void set_error_handler(ErrorHandler* error_handler) {
+ assert(internal_state_.router());
+ internal_state_.router()->set_error_handler(error_handler);
+ }
+
+ // Returns the underlying message pipe handle (if any) and resets the
+ // InterfacePtr<..> to its uninitialized state. This method is helpful if you
+ // need to move a proxy to another thread. See related notes for Bind.
+ ScopedMessagePipeHandle ResetAndReturnMessagePipe() {
+ State state;
+ internal_state_.Swap(&state);
+ return state.router() ?
+ state.router()->ReleaseMessagePipe() : ScopedMessagePipeHandle();
+ }
+
+ // DO NOT USE. Exposed only for internal use and for testing.
+ internal::InterfacePtrState<Interface>* internal_state() {
+ return &internal_state_;
+ }
+
+ private:
+ typedef internal::InterfacePtrState<Interface> State;
+ State internal_state_;
+};
+
+// Takes a handle to the proxy end-point of a pipe. On the other end is
+// presumed to be an interface implementation of type |Interface|. Returns a
+// generated proxy to that interface, which may be used on the current thread.
+// It is valid to call SetClient on the returned Interface to set an instance
+// of Interface::Client.
+template <typename Interface>
+InterfacePtr<Interface> MakeProxy(
+ ScopedMessagePipeHandle handle,
+ MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter()) {
+ InterfacePtr<Interface> ptr;
+ if (handle.is_valid())
+ ptr.Bind(handle.Pass(), waiter);
+ return ptr.Pass();
+}
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_
diff --git a/mojo/public/cpp/bindings/lib/array_internal.h b/mojo/public/cpp/bindings/lib/array_internal.h
index 4ecad35..865bf1c 100644
--- a/mojo/public/cpp/bindings/lib/array_internal.h
+++ b/mojo/public/cpp/bindings/lib/array_internal.h
@@ -8,7 +8,6 @@
#include <new>
#include "mojo/public/cpp/bindings/buffer.h"
-#include "mojo/public/cpp/bindings/interface.h"
#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
#include "mojo/public/cpp/bindings/lib/bindings_serialization.h"
#include "mojo/public/cpp/bindings/passable.h"
diff --git a/mojo/public/cpp/bindings/lib/connector.cc b/mojo/public/cpp/bindings/lib/connector.cc
index aa6c45e..d9ce9d1 100644
--- a/mojo/public/cpp/bindings/lib/connector.cc
+++ b/mojo/public/cpp/bindings/lib/connector.cc
@@ -38,7 +38,17 @@ void Connector::CloseMessagePipe() {
Close(message_pipe_.Pass());
}
+ScopedMessagePipeHandle Connector::ReleaseMessagePipe() {
+ if (async_wait_id_) {
+ waiter_->CancelWait(waiter_, async_wait_id_);
+ async_wait_id_ = 0;
+ }
+ return message_pipe_.Pass();
+}
+
bool Connector::Accept(Message* message) {
+ assert(message_pipe_.is_valid());
+
if (error_)
return false;
@@ -99,7 +109,7 @@ void Connector::OnHandleReady(MojoResult result) {
}
if (error_ && error_handler_)
- error_handler_->OnError();
+ error_handler_->OnConnectionError();
}
void Connector::WaitToReadMore() {
diff --git a/mojo/public/cpp/bindings/lib/connector.h b/mojo/public/cpp/bindings/lib/connector.h
index f32a170..6e9c1b9 100644
--- a/mojo/public/cpp/bindings/lib/connector.h
+++ b/mojo/public/cpp/bindings/lib/connector.h
@@ -53,9 +53,14 @@ class Connector : public MessageReceiver {
// waiting to read from the pipe.
bool encountered_error() const { return error_; }
- // Closes the pipe, triggering the error state.
+ // Closes the pipe, triggering the error state. Connector is put into a
+ // quiescent state.
void CloseMessagePipe();
+ // Releases the pipe, not triggering the error state. Connector is put into
+ // a quiescent state.
+ ScopedMessagePipeHandle ReleaseMessagePipe();
+
// MessageReceiver implementation:
virtual bool Accept(Message* message) MOJO_OVERRIDE;
virtual bool AcceptWithResponder(Message* message, MessageReceiver* responder)
diff --git a/mojo/public/cpp/bindings/lib/interface_impl_internal.h b/mojo/public/cpp/bindings/lib/interface_impl_internal.h
new file mode 100644
index 0000000..50fe566
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/interface_impl_internal.h
@@ -0,0 +1,72 @@
+// 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.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_IMPL_INTERNAL_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_IMPL_INTERNAL_H_
+
+#include "mojo/public/cpp/bindings/error_handler.h"
+#include "mojo/public/cpp/bindings/interface_ptr.h"
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+namespace internal {
+
+template <typename Interface>
+class InterfaceImplState : public ErrorHandler {
+ public:
+ explicit InterfaceImplState(WithErrorHandler<Interface>* instance)
+ : router_(NULL),
+ proxy_(NULL) {
+ assert(instance);
+ stub_.set_sink(instance);
+ }
+
+ virtual ~InterfaceImplState() {
+ delete proxy_;
+ if (router_) {
+ router_->set_error_handler(NULL);
+ delete router_;
+ }
+ }
+
+ void BindProxy(
+ InterfacePtr<Interface>* ptr,
+ MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter()) {
+ MessagePipe pipe;
+ ptr->Bind(pipe.handle0.Pass(), waiter);
+ Bind(pipe.handle1.Pass(), waiter);
+ }
+
+ void Bind(ScopedMessagePipeHandle handle,
+ MojoAsyncWaiter* waiter) {
+ assert(!router_);
+
+ router_ = new Router(handle.Pass(), waiter);
+ router_->set_incoming_receiver(&stub_);
+ router_->set_error_handler(this);
+
+ proxy_ = new typename Interface::Client_::Proxy_(router_);
+
+ stub_.sink()->SetClient(proxy_);
+ }
+
+ Router* router() { return router_; }
+
+ private:
+ virtual void OnConnectionError() MOJO_OVERRIDE {
+ static_cast<WithErrorHandler<Interface>*>(stub_.sink())->
+ OnConnectionError();
+ }
+
+ internal::Router* router_;
+ typename Interface::Client_::Proxy_* proxy_;
+ typename Interface::Stub_ stub_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(InterfaceImplState);
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_IMPL_INTERNAL_H_
diff --git a/mojo/public/cpp/bindings/lib/interface_ptr_internal.h b/mojo/public/cpp/bindings/lib/interface_ptr_internal.h
new file mode 100644
index 0000000..041a31c
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/interface_ptr_internal.h
@@ -0,0 +1,108 @@
+// 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.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_INTERNAL_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_INTERNAL_H_
+
+#include <stdio.h>
+
+#include "mojo/public/cpp/bindings/lib/router.h"
+
+namespace mojo {
+namespace internal {
+
+template <typename Interface>
+class InterfacePtrState {
+ public:
+ InterfacePtrState() : instance_(NULL), client_(NULL), router_(NULL) {}
+
+ ~InterfacePtrState() {
+ // Destruction order matters here. We delete |instance_| first, even though
+ // |router_| may have a reference to it, so that |~Interface| may have a
+ // shot at generating new outbound messages (ie, invoking client methods).
+ delete instance_;
+ delete router_;
+ delete client_;
+ }
+
+ Interface* instance() const { return instance_; }
+ void set_instance(Interface* instance) { instance_ = instance; }
+
+ Router* router() const { return router_; }
+
+ bool is_configured_as_proxy() const {
+ // This question only makes sense if we have a bound pipe.
+ return router_ && !client_;
+ }
+
+ void Swap(InterfacePtrState* other) {
+ std::swap(other->instance_, instance_);
+ std::swap(other->client_, client_);
+ std::swap(other->router_, router_);
+ }
+
+ void ConfigureProxy(ScopedMessagePipeHandle handle,
+ MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter()) {
+ assert(!instance_);
+ assert(!router_);
+
+ router_ = new Router(handle.Pass(), waiter);
+ ProxyWithStub* proxy = new ProxyWithStub(router_);
+ router_->set_incoming_receiver(&proxy->stub);
+
+ instance_ = proxy;
+ }
+
+ void ConfigureStub(ScopedMessagePipeHandle handle,
+ MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter()) {
+ assert(instance_); // Should have already been set!
+ assert(!router_);
+
+ // Stub for binding to state_.instance
+ // Proxy for communicating to the client on the other end of the pipe.
+
+ router_ = new Router(handle.Pass(), waiter);
+ ClientProxyWithStub* proxy = new ClientProxyWithStub(router_);
+ proxy->stub.set_sink(instance_);
+ router_->set_incoming_receiver(&proxy->stub);
+
+ instance_->SetClient(proxy);
+ client_ = proxy;
+ }
+
+ private:
+ class ProxyWithStub : public Interface::Proxy_ {
+ public:
+ explicit ProxyWithStub(MessageReceiver* receiver)
+ : Interface::Proxy_(receiver) {
+ }
+ virtual void SetClient(typename Interface::Client_* client) MOJO_OVERRIDE {
+ stub.set_sink(client);
+ }
+ typename Interface::Client_::Stub_ stub;
+ private:
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ProxyWithStub);
+ };
+
+ class ClientProxyWithStub : public Interface::Client_::Proxy_ {
+ public:
+ explicit ClientProxyWithStub(MessageReceiver* receiver)
+ : Interface::Client_::Proxy_(receiver) {
+ }
+ typename Interface::Stub_ stub;
+ private:
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ClientProxyWithStub);
+ };
+
+ Interface* instance_;
+ typename Interface::Client_* client_;
+ Router* router_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(InterfacePtrState);
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_INTERNAL_H_
diff --git a/mojo/public/cpp/bindings/lib/interface.cc b/mojo/public/cpp/bindings/lib/no_interface.cc
index 3b552be..7ce223a 100644
--- a/mojo/public/cpp/bindings/lib/interface.cc
+++ b/mojo/public/cpp/bindings/lib/no_interface.cc
@@ -2,7 +2,7 @@
// 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/interface.h"
+#include "mojo/public/cpp/bindings/no_interface.h"
namespace mojo {
diff --git a/mojo/public/cpp/bindings/lib/router.h b/mojo/public/cpp/bindings/lib/router.h
index 08c184e..220af7d 100644
--- a/mojo/public/cpp/bindings/lib/router.h
+++ b/mojo/public/cpp/bindings/lib/router.h
@@ -43,6 +43,14 @@ class Router : public MessageReceiver {
// waiting to read from the pipe.
bool encountered_error() const { return connector_.encountered_error(); }
+ void CloseMessagePipe() {
+ connector_.CloseMessagePipe();
+ }
+
+ ScopedMessagePipeHandle ReleaseMessagePipe() {
+ return connector_.ReleaseMessagePipe();
+ }
+
// MessageReceiver implementation:
virtual bool Accept(Message* message) MOJO_OVERRIDE;
virtual bool AcceptWithResponder(Message* message, MessageReceiver* responder)
diff --git a/mojo/public/cpp/bindings/no_interface.h b/mojo/public/cpp/bindings/no_interface.h
new file mode 100644
index 0000000..02682d4
--- /dev/null
+++ b/mojo/public/cpp/bindings/no_interface.h
@@ -0,0 +1,52 @@
+// 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.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_NO_INTERFACE_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_NO_INTERFACE_H_
+
+#include <assert.h>
+
+#include "mojo/public/cpp/bindings/message.h"
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+
+// NoInterface is for use in cases when a non-existent or empty interface is
+// needed (e.g., when the Mojom "Peer" attribute is not present).
+
+class NoInterfaceProxy;
+class NoInterfaceStub;
+
+class NoInterface {
+ public:
+ typedef NoInterfaceProxy Proxy_;
+ typedef NoInterfaceStub Stub_;
+ typedef NoInterface Client_;
+ virtual ~NoInterface() {}
+ virtual void SetClient(NoInterface* client) {}
+};
+
+class NoInterfaceProxy : public NoInterface {
+ public:
+ explicit NoInterfaceProxy(MessageReceiver* receiver) {}
+};
+
+class NoInterfaceStub : public MessageReceiver {
+ public:
+ NoInterfaceStub() {}
+ void set_sink(NoInterface* sink) {}
+ virtual bool Accept(Message* message) MOJO_OVERRIDE;
+ virtual bool AcceptWithResponder(Message* message, MessageReceiver* responder)
+ MOJO_OVERRIDE;
+};
+
+
+// AnyInterface is for use in cases where any interface would do (e.g., see the
+// Shell::Connect method).
+
+typedef NoInterface AnyInterface;
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_NO_INTERFACE_H_
diff --git a/mojo/public/cpp/bindings/remote_ptr.h b/mojo/public/cpp/bindings/remote_ptr.h
deleted file mode 100644
index e1b9a5b..0000000
--- a/mojo/public/cpp/bindings/remote_ptr.h
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2013 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_REMOTE_PTR_H_
-#define MOJO_PUBLIC_CPP_BINDINGS_REMOTE_PTR_H_
-
-#include <assert.h>
-
-#include "mojo/public/cpp/bindings/interface.h"
-#include "mojo/public/cpp/bindings/lib/router.h"
-#include "mojo/public/cpp/system/macros.h"
-
-namespace mojo {
-
-// A RemotePtr is a smart-pointer for managing the connection of a message pipe
-// to an interface proxy.
-//
-// EXAMPLE:
-//
-// Given foo.mojom containing the following interfaces:
-//
-// [Peer=FooClient]
-// interface Foo {
-// void Ping();
-// };
-//
-// [Peer=Foo]
-// interface FooClient {
-// void Pong();
-// };
-//
-// On the client side of a service, RemotePtr might be used like so:
-//
-// class FooClientImpl : public FooClient {
-// public:
-// explicit FooClientImpl(ScopedFooHandle handle)
-// : foo_(handle.Pass(), this) {
-// foo_.Ping();
-// }
-// virtual void Pong() {
-// ...
-// }
-// private:
-// mojo::RemotePtr<Foo> foo_;
-// };
-//
-// On the implementation side of a service, RemotePtr might be used like so:
-//
-// class FooImpl : public Foo {
-// public:
-// explicit FooImpl(ScopedFooClientHandle handle)
-// : client_(handle.Pass(), this) {
-// }
-// virtual void Ping() {
-// client_->Pong();
-// }
-// private:
-// mojo::RemotePtr<FooClient> client_;
-// };
-//
-// NOTE:
-//
-// 1- It is valid to pass NULL for the peer if you are not interested in
-// receiving incoming messages. Those messages will still be consumed.
-//
-// 2- You may optionally register an ErrorHandler on the RemotePtr to be
-// notified if the peer has gone away. Alternatively, you may poll the
-// |encountered_error()| method to check if the peer has gone away.
-//
-template <typename S>
-class RemotePtr {
- struct State;
- MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(RemotePtr, RValue)
-
- public:
- RemotePtr() : state_(NULL) {}
- explicit RemotePtr(typename Interface<S>::ScopedHandle interface_handle,
- typename S::_Peer* peer,
- ErrorHandler* error_handler = NULL,
- MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter())
- : state_(new State(ScopedMessagePipeHandle(interface_handle.Pass()), peer,
- error_handler, waiter)) {
- }
-
- // Move-only constructor and operator=.
- RemotePtr(RValue other) : state_(other.object->release()) {}
- RemotePtr& operator=(RValue other) {
- delete state_;
- state_ = other.object->release();
- return *this;
- }
-
- ~RemotePtr() {
- delete state_;
- }
-
- bool is_null() const {
- return !state_;
- }
-
- S* get() {
- assert(state_);
- return &state_->proxy;
- }
-
- S* operator->() {
- return get();
- }
-
- void reset() {
- delete state_;
- state_ = NULL;
- }
-
- void reset(typename Interface<S>::ScopedHandle interface_handle,
- typename S::_Peer* peer,
- ErrorHandler* error_handler = NULL,
- MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter()) {
- delete state_;
- state_ = new State(ScopedMessagePipeHandle(interface_handle.Pass()), peer,
- error_handler, waiter);
- }
-
- bool encountered_error() const {
- assert(state_);
- return state_->router.encountered_error();
- }
-
- internal::Router* router_for_testing() {
- return &state_->router;
- }
-
- private:
- struct State {
- State(ScopedMessagePipeHandle message_pipe, typename S::_Peer* peer,
- ErrorHandler* error_handler, MojoAsyncWaiter* waiter)
- : router(message_pipe.Pass(), waiter),
- proxy(&router),
- stub(peer) {
- router.set_error_handler(error_handler);
- if (peer)
- router.set_incoming_receiver(&stub);
- }
- internal::Router router;
- typename S::_Proxy proxy;
- typename S::_Peer::_Stub stub;
- };
-
- State* release() {
- State* state = state_;
- state_ = NULL;
- return state;
- }
-
- State* state_;
-};
-
-} // namespace mojo
-
-#endif // MOJO_PUBLIC_CPP_BINDINGS_REMOTE_PTR_H_
diff --git a/mojo/public/cpp/bindings/sync_dispatcher.h b/mojo/public/cpp/bindings/sync_dispatcher.h
index e267a17..7521180 100644
--- a/mojo/public/cpp/bindings/sync_dispatcher.h
+++ b/mojo/public/cpp/bindings/sync_dispatcher.h
@@ -16,11 +16,11 @@ class MessageReceiver;
bool WaitForMessageAndDispatch(MessagePipeHandle handle,
mojo::MessageReceiver* receiver);
-template<typename S> class SyncDispatcher {
+template<typename Interface> class SyncDispatcher {
public:
- SyncDispatcher(ScopedMessagePipeHandle message_pipe, S* sink)
- : message_pipe_(message_pipe.Pass()),
- stub_(sink) {
+ SyncDispatcher(ScopedMessagePipeHandle message_pipe, Interface* sink)
+ : message_pipe_(message_pipe.Pass()) {
+ stub_.set_sink(sink);
}
bool WaitAndDispatchOneMessage() {
@@ -29,7 +29,7 @@ template<typename S> class SyncDispatcher {
private:
ScopedMessagePipeHandle message_pipe_;
- typename S::_Stub stub_;
+ typename Interface::Stub_ stub_;
};
} // namespace mojo
diff --git a/mojo/public/cpp/bindings/tests/array_unittest.cc b/mojo/public/cpp/bindings/tests/array_unittest.cc
index dccd716..4bef4cd 100644
--- a/mojo/public/cpp/bindings/tests/array_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/array_unittest.cc
@@ -4,7 +4,6 @@
#include "mojo/public/cpp/bindings/allocation_scope.h"
#include "mojo/public/cpp/bindings/array.h"
-#include "mojo/public/cpp/bindings/interface.h"
#include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
#include "mojo/public/cpp/bindings/lib/scratch_buffer.h"
#include "mojo/public/cpp/environment/environment.h"
@@ -141,31 +140,6 @@ TEST(ArrayTest, MessagePipeHandlesAreClosed) {
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe1_value));
}
-// Tests that Array<InterfaceHandle<S>> supports closing handles.
-TEST(ArrayTest, InterfaceHandlesAreClosed) {
- Environment env;
-
- InterfacePipe<sample::Port, sample::Port> pipe;
-
- MojoHandle pipe0_value = pipe.handle_to_self.get().value();
- MojoHandle pipe1_value = pipe.handle_to_peer.get().value();
-
- {
- AllocationScope scope;
-
- Array<sample::PortHandle>::Builder handles_builder(2);
- handles_builder[0] = pipe.handle_to_self.Pass();
- handles_builder[1].reset(pipe.handle_to_peer.release());
-
- MOJO_ALLOW_UNUSED Array<sample::PortHandle> handles =
- handles_builder.Finish();
- }
-
- // We expect the pipes to have been closed.
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe0_value));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe1_value));
-}
-
} // namespace
} // namespace test
} // namespace mojo
diff --git a/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc b/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc
index 7df6db6..2cbd789 100644
--- a/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc
@@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "mojo/public/cpp/bindings/allocation_scope.h"
-#include "mojo/public/cpp/bindings/remote_ptr.h"
#include "mojo/public/cpp/environment/environment.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "mojo/public/cpp/utility/run_loop.h"
@@ -17,10 +16,14 @@ namespace {
const char kText1[] = "hello";
const char kText2[] = "world";
-class SampleFactoryImpl : public sample::Factory {
+class SampleFactoryImpl : public InterfaceImpl<sample::Factory> {
public:
- explicit SampleFactoryImpl(sample::ScopedFactoryClientHandle handle)
- : client_(handle.Pass(), this) {
+ virtual void OnConnectionError() MOJO_OVERRIDE {
+ delete this;
+ }
+
+ virtual void SetClient(sample::FactoryClient* client) MOJO_OVERRIDE {
+ client_ = client;
}
virtual void DoStuff(const sample::Request& request,
@@ -70,69 +73,17 @@ class SampleFactoryImpl : public sample::Factory {
}
private:
- RemotePtr<sample::FactoryClient> client_;
+ sample::FactoryClient* client_;
ScopedMessagePipeHandle pipe1_;
};
class SampleFactoryClientImpl : public sample::FactoryClient {
public:
- explicit SampleFactoryClientImpl(sample::ScopedFactoryHandle handle)
- : factory_(handle.Pass(), this),
- got_response_(false) {
- }
-
- void Start() {
- expected_text_reply_ = kText1;
-
- ScopedMessagePipeHandle pipe0;
- CreateMessagePipe(&pipe0, &pipe1_);
-
- EXPECT_TRUE(WriteTextMessage(pipe1_.get(), kText1));
-
- ScopedMessagePipeHandle pipe2;
- CreateMessagePipe(&pipe2, &pipe3_);
-
- EXPECT_TRUE(WriteTextMessage(pipe3_.get(), kText2));
-
- AllocationScope scope;
- sample::Request::Builder request;
- request.set_x(1);
- request.set_pipe(pipe2.Pass());
- factory_->DoStuff(request.Finish(), pipe0.Pass());
- }
-
- void StartNoPipes() {
- expected_text_reply_.clear();
-
- AllocationScope scope;
- sample::Request::Builder request;
- request.set_x(1);
- factory_->DoStuff(request.Finish(), ScopedMessagePipeHandle().Pass());
+ SampleFactoryClientImpl() : got_response_(false) {
}
- // Writes a string to a data pipe and passes the data pipe (consumer) to the
- // factory.
- void StartDataPipe() {
- expected_text_reply_.clear();
-
- ScopedDataPipeProducerHandle producer_handle;
- ScopedDataPipeConsumerHandle consumer_handle;
- MojoCreateDataPipeOptions options = {
- sizeof(MojoCreateDataPipeOptions),
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,
- 1,
- 1024};
- ASSERT_EQ(MOJO_RESULT_OK,
- CreateDataPipe(&options, &producer_handle, &consumer_handle));
- expected_text_reply_ = "got it";
- // +1 for \0.
- uint32_t data_size = static_cast<uint32_t>(expected_text_reply_.size() + 1);
- ASSERT_EQ(MOJO_RESULT_OK,
- WriteDataRaw(producer_handle.get(), expected_text_reply_.c_str(),
- &data_size, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
-
- AllocationScope scope;
- factory_->DoStuff2(consumer_handle.Pass());
+ void set_expected_text_reply(const std::string& expected_text_reply) {
+ expected_text_reply_ = expected_text_reply;
}
bool got_response() const {
@@ -167,7 +118,6 @@ class SampleFactoryClientImpl : public sample::FactoryClient {
}
private:
- RemotePtr<sample::Factory> factory_;
ScopedMessagePipeHandle pipe1_;
ScopedMessagePipeHandle pipe3_;
std::string expected_text_reply_;
@@ -176,6 +126,10 @@ class SampleFactoryClientImpl : public sample::FactoryClient {
class HandlePassingTest : public testing::Test {
public:
+ virtual void TearDown() {
+ PumpMessages();
+ }
+
void PumpMessages() {
loop_.RunUntilIdle();
}
@@ -186,12 +140,31 @@ class HandlePassingTest : public testing::Test {
};
TEST_F(HandlePassingTest, Basic) {
- InterfacePipe<sample::Factory> pipe;
+ sample::FactoryPtr factory;
+ BindToProxy(new SampleFactoryImpl(), &factory);
+
+ SampleFactoryClientImpl factory_client;
+ factory_client.set_expected_text_reply(kText1);
+
+ factory->SetClient(&factory_client);
+
+ ScopedMessagePipeHandle pipe0, pipe1;
+ CreateMessagePipe(&pipe0, &pipe1);
+
+ EXPECT_TRUE(WriteTextMessage(pipe1.get(), kText1));
+
+ ScopedMessagePipeHandle pipe2, pipe3;
+ CreateMessagePipe(&pipe2, &pipe3);
- SampleFactoryImpl factory(pipe.handle_to_peer.Pass());
- SampleFactoryClientImpl factory_client(pipe.handle_to_self.Pass());
+ EXPECT_TRUE(WriteTextMessage(pipe3.get(), kText2));
- factory_client.Start();
+ {
+ AllocationScope scope;
+ sample::Request::Builder request;
+ request.set_x(1);
+ request.set_pipe(pipe2.Pass());
+ factory->DoStuff(request.Finish(), pipe0.Pass());
+ }
EXPECT_FALSE(factory_client.got_response());
@@ -201,12 +174,18 @@ TEST_F(HandlePassingTest, Basic) {
}
TEST_F(HandlePassingTest, PassInvalid) {
- InterfacePipe<sample::Factory> pipe;
+ sample::FactoryPtr factory;
+ BindToProxy(new SampleFactoryImpl(), &factory);
- SampleFactoryImpl factory(pipe.handle_to_peer.Pass());
- SampleFactoryClientImpl factory_client(pipe.handle_to_self.Pass());
+ SampleFactoryClientImpl factory_client;
+ factory->SetClient(&factory_client);
- factory_client.StartNoPipes();
+ {
+ AllocationScope scope;
+ sample::Request::Builder request;
+ request.set_x(1);
+ factory->DoStuff(request.Finish(), ScopedMessagePipeHandle().Pass());
+ }
EXPECT_FALSE(factory_client.got_response());
@@ -217,12 +196,35 @@ TEST_F(HandlePassingTest, PassInvalid) {
// Verifies DataPipeConsumer can be passed and read from.
TEST_F(HandlePassingTest, DataPipe) {
- InterfacePipe<sample::Factory> pipe;
+ sample::FactoryPtr factory;
+ BindToProxy(new SampleFactoryImpl(), &factory);
+
+ SampleFactoryClientImpl factory_client;
+ factory->SetClient(&factory_client);
- SampleFactoryImpl factory(pipe.handle_to_peer.Pass());
- SampleFactoryClientImpl factory_client(pipe.handle_to_self.Pass());
+ // Writes a string to a data pipe and passes the data pipe (consumer) to the
+ // factory.
+ ScopedDataPipeProducerHandle producer_handle;
+ ScopedDataPipeConsumerHandle consumer_handle;
+ MojoCreateDataPipeOptions options = {
+ sizeof(MojoCreateDataPipeOptions),
+ MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,
+ 1,
+ 1024};
+ ASSERT_EQ(MOJO_RESULT_OK,
+ CreateDataPipe(&options, &producer_handle, &consumer_handle));
+ std::string expected_text_reply = "got it";
+ factory_client.set_expected_text_reply(expected_text_reply);
+ // +1 for \0.
+ uint32_t data_size = static_cast<uint32_t>(expected_text_reply.size() + 1);
+ ASSERT_EQ(MOJO_RESULT_OK,
+ WriteDataRaw(producer_handle.get(), expected_text_reply.c_str(),
+ &data_size, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
- ASSERT_NO_FATAL_FAILURE(factory_client.StartDataPipe());
+ {
+ AllocationScope scope;
+ factory->DoStuff2(consumer_handle.Pass());
+ }
EXPECT_FALSE(factory_client.got_response());
@@ -232,8 +234,11 @@ TEST_F(HandlePassingTest, DataPipe) {
}
TEST_F(HandlePassingTest, PipesAreClosed) {
- InterfacePipe<sample::Factory> pipe;
- RemotePtr<sample::Factory> factory(pipe.handle_to_self.Pass(), NULL);
+ sample::FactoryPtr factory;
+ BindToProxy(new SampleFactoryImpl(), &factory);
+
+ SampleFactoryClientImpl factory_client;
+ factory->SetClient(&factory_client);
MessagePipe extra_pipe;
diff --git a/mojo/public/cpp/bindings/tests/remote_ptr_unittest.cc b/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc
index 13311d4..3f9a80d 100644
--- a/mojo/public/cpp/bindings/tests/remote_ptr_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc
@@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "mojo/public/cpp/bindings/error_handler.h"
-#include "mojo/public/cpp/bindings/remote_ptr.h"
#include "mojo/public/cpp/environment/environment.h"
#include "mojo/public/cpp/utility/run_loop.h"
#include "mojo/public/interfaces/bindings/tests/math_calculator.mojom.h"
@@ -21,7 +20,7 @@ class ErrorObserver : public ErrorHandler {
bool encountered_error() const { return encountered_error_; }
- virtual void OnError() MOJO_OVERRIDE {
+ virtual void OnConnectionError() MOJO_OVERRIDE {
encountered_error_ = true;
}
@@ -29,13 +28,19 @@ class ErrorObserver : public ErrorHandler {
bool encountered_error_;
};
-class MathCalculatorImpl : public math::Calculator {
+class MathCalculatorImpl : public InterfaceImpl<math::Calculator> {
public:
virtual ~MathCalculatorImpl() {}
- explicit MathCalculatorImpl(math::ScopedCalculatorUIHandle ui_handle)
- : ui_(ui_handle.Pass(), this),
- total_(0.0) {
+ MathCalculatorImpl() : total_(0.0) {
+ }
+
+ virtual void OnConnectionError() MOJO_OVERRIDE {
+ delete this;
+ }
+
+ virtual void SetClient(math::CalculatorUI* ui) MOJO_OVERRIDE {
+ ui_ = ui;
}
virtual void Clear() MOJO_OVERRIDE {
@@ -53,16 +58,16 @@ class MathCalculatorImpl : public math::Calculator {
}
private:
- RemotePtr<math::CalculatorUI> ui_;
+ math::CalculatorUI* ui_;
double total_;
};
class MathCalculatorUIImpl : public math::CalculatorUI {
public:
- explicit MathCalculatorUIImpl(math::ScopedCalculatorHandle calculator_handle,
- ErrorHandler* error_handler = NULL)
- : calculator_(calculator_handle.Pass(), this, error_handler),
+ explicit MathCalculatorUIImpl(math::CalculatorPtr calculator)
+ : calculator_(calculator.Pass()),
output_(0.0) {
+ calculator_->SetClient(this);
}
bool encountered_error() const {
@@ -95,30 +100,31 @@ class MathCalculatorUIImpl : public math::CalculatorUI {
output_ = value;
}
- RemotePtr<math::Calculator> calculator_;
+ math::CalculatorPtr calculator_;
double output_;
};
-class RemotePtrTest : public testing::Test {
+class InterfacePtrTest : public testing::Test {
public:
- void PumpMessages() {
+ virtual ~InterfacePtrTest() {
loop_.RunUntilIdle();
}
- protected:
- InterfacePipe<math::CalculatorUI> pipe_;
+ void PumpMessages() {
+ loop_.RunUntilIdle();
+ }
private:
Environment env_;
RunLoop loop_;
};
-TEST_F(RemotePtrTest, EndToEnd) {
- // Suppose this is instantiated in a process that has pipe0_.
- MathCalculatorImpl calculator(pipe_.handle_to_self.Pass());
+TEST_F(InterfacePtrTest, EndToEnd) {
+ math::CalculatorPtr calc;
+ BindToProxy(new MathCalculatorImpl(), &calc);
// Suppose this is instantiated in a process that has pipe1_.
- MathCalculatorUIImpl calculator_ui(pipe_.handle_to_peer.Pass());
+ MathCalculatorUIImpl calculator_ui(calc.Pass());
calculator_ui.Add(2.0);
calculator_ui.Multiply(5.0);
@@ -128,43 +134,48 @@ TEST_F(RemotePtrTest, EndToEnd) {
EXPECT_EQ(10.0, calculator_ui.GetOutput());
}
-TEST_F(RemotePtrTest, Movable) {
- RemotePtr<math::Calculator> a;
- RemotePtr<math::Calculator> b(pipe_.handle_to_peer.Pass(), NULL);
+TEST_F(InterfacePtrTest, Movable) {
+ math::CalculatorPtr a;
+ math::CalculatorPtr b;
+ BindToProxy(new MathCalculatorImpl(), &b);
- EXPECT_TRUE(a.is_null());
- EXPECT_FALSE(b.is_null());
+ EXPECT_TRUE(!a.get());
+ EXPECT_FALSE(!b.get());
a = b.Pass();
- EXPECT_FALSE(a.is_null());
- EXPECT_TRUE(b.is_null());
+ EXPECT_FALSE(!a.get());
+ EXPECT_TRUE(!b.get());
}
-TEST_F(RemotePtrTest, Resettable) {
- RemotePtr<math::Calculator> a;
+TEST_F(InterfacePtrTest, Resettable) {
+ math::CalculatorPtr a;
- EXPECT_TRUE(a.is_null());
+ EXPECT_TRUE(!a.get());
- math::CalculatorHandle handle = pipe_.handle_to_peer.get();
+ MessagePipe pipe;
- a.reset(pipe_.handle_to_peer.Pass(), NULL);
+ // Save this so we can test it later.
+ Handle handle = pipe.handle0.get();
- EXPECT_FALSE(a.is_null());
+ a = MakeProxy<math::Calculator>(pipe.handle0.Pass());
+
+ EXPECT_FALSE(!a.get());
a.reset();
- EXPECT_TRUE(a.is_null());
+ EXPECT_TRUE(!a.get());
+ EXPECT_FALSE(a.internal_state()->router());
// Test that handle was closed.
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, CloseRaw(handle));
}
-TEST_F(RemotePtrTest, EncounteredError) {
- MathCalculatorImpl* calculator =
- new MathCalculatorImpl(pipe_.handle_to_self.Pass());
+TEST_F(InterfacePtrTest, EncounteredError) {
+ math::CalculatorPtr proxy;
+ MathCalculatorImpl* server = BindToProxy(new MathCalculatorImpl(), &proxy);
- MathCalculatorUIImpl calculator_ui(pipe_.handle_to_peer.Pass());
+ MathCalculatorUIImpl calculator_ui(proxy.Pass());
calculator_ui.Add(2.0);
PumpMessages();
@@ -174,8 +185,8 @@ TEST_F(RemotePtrTest, EncounteredError) {
calculator_ui.Multiply(5.0);
EXPECT_FALSE(calculator_ui.encountered_error());
- // Close the other side of the pipe.
- delete calculator;
+ // Close the server.
+ server->internal_state()->router()->CloseMessagePipe();
// The state change isn't picked up locally yet.
EXPECT_FALSE(calculator_ui.encountered_error());
@@ -186,13 +197,14 @@ TEST_F(RemotePtrTest, EncounteredError) {
EXPECT_TRUE(calculator_ui.encountered_error());
}
-TEST_F(RemotePtrTest, EncounteredErrorCallback) {
- MathCalculatorImpl* calculator =
- new MathCalculatorImpl(pipe_.handle_to_self.Pass());
+TEST_F(InterfacePtrTest, EncounteredErrorCallback) {
+ math::CalculatorPtr proxy;
+ MathCalculatorImpl* server = BindToProxy(new MathCalculatorImpl(), &proxy);
ErrorObserver error_observer;
- MathCalculatorUIImpl calculator_ui(pipe_.handle_to_peer.Pass(),
- &error_observer);
+ proxy.set_error_handler(&error_observer);
+
+ MathCalculatorUIImpl calculator_ui(proxy.Pass());
calculator_ui.Add(2.0);
PumpMessages();
@@ -202,8 +214,8 @@ TEST_F(RemotePtrTest, EncounteredErrorCallback) {
calculator_ui.Multiply(5.0);
EXPECT_FALSE(calculator_ui.encountered_error());
- // Close the other side of the pipe.
- delete calculator;
+ // Close the server.
+ server->internal_state()->router()->CloseMessagePipe();
// The state change isn't picked up locally yet.
EXPECT_FALSE(calculator_ui.encountered_error());
@@ -218,11 +230,12 @@ TEST_F(RemotePtrTest, EncounteredErrorCallback) {
EXPECT_TRUE(error_observer.encountered_error());
}
-TEST_F(RemotePtrTest, NoPeerAttribute) {
+TEST_F(InterfacePtrTest, NoClientAttribute) {
// This is a test to ensure the following compiles. The sample::Port interface
- // does not have an explicit Peer attribute.
- InterfacePipe<sample::Port, NoInterface> pipe;
- RemotePtr<sample::Port> port(pipe.handle_to_self.Pass(), NULL);
+ // does not have an explicit Client attribute.
+ sample::PortPtr port;
+ MessagePipe pipe;
+ port.Bind(pipe.handle0.Pass());
}
} // namespace
diff --git a/mojo/public/cpp/bindings/tests/request_response_unittest.cc b/mojo/public/cpp/bindings/tests/request_response_unittest.cc
index 94ed91f..d163f7d 100644
--- a/mojo/public/cpp/bindings/tests/request_response_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/request_response_unittest.cc
@@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "mojo/public/cpp/bindings/allocation_scope.h"
-#include "mojo/public/cpp/bindings/remote_ptr.h"
#include "mojo/public/cpp/environment/environment.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "mojo/public/cpp/utility/run_loop.h"
@@ -15,10 +14,14 @@ namespace mojo {
namespace test {
namespace {
-class ProviderImpl : public sample::Provider {
+class ProviderImpl : public InterfaceImpl<sample::Provider> {
public:
- explicit ProviderImpl(sample::ScopedProviderClientHandle handle)
- : client_(handle.Pass(), this) {
+ virtual void OnConnectionError() MOJO_OVERRIDE {
+ delete this;
+ }
+
+ virtual void SetClient(sample::ProviderClient* client) MOJO_OVERRIDE {
+ // Ignored. TODO(darin): Eliminate ProviderClient.
}
virtual void EchoString(
@@ -51,9 +54,6 @@ class ProviderImpl : public sample::Provider {
MOJO_OVERRIDE {
callback.Run(a);
}
-
- private:
- RemotePtr<sample::ProviderClient> client_;
};
class StringRecorder {
@@ -94,6 +94,10 @@ class MessagePipeWriter {
class RequestResponseTest : public testing::Test {
public:
+ virtual ~RequestResponseTest() {
+ loop_.RunUntilIdle();
+ }
+
void PumpMessages() {
loop_.RunUntilIdle();
}
@@ -104,9 +108,8 @@ class RequestResponseTest : public testing::Test {
};
TEST_F(RequestResponseTest, EchoString) {
- InterfacePipe<sample::Provider> pipe;
- ProviderImpl provider_impl(pipe.handle_to_peer.Pass());
- RemotePtr<sample::Provider> provider(pipe.handle_to_self.Pass(), NULL);
+ sample::ProviderPtr provider;
+ BindToProxy(new ProviderImpl(), &provider);
std::string buf;
{
@@ -120,9 +123,8 @@ TEST_F(RequestResponseTest, EchoString) {
}
TEST_F(RequestResponseTest, EchoStrings) {
- InterfacePipe<sample::Provider> pipe;
- ProviderImpl provider_impl(pipe.handle_to_peer.Pass());
- RemotePtr<sample::Provider> provider(pipe.handle_to_self.Pass(), NULL);
+ sample::ProviderPtr provider;
+ BindToProxy(new ProviderImpl(), &provider);
std::string buf;
{
@@ -136,9 +138,8 @@ TEST_F(RequestResponseTest, EchoStrings) {
}
TEST_F(RequestResponseTest, EchoMessagePipeHandle) {
- InterfacePipe<sample::Provider> pipe;
- ProviderImpl provider_impl(pipe.handle_to_peer.Pass());
- RemotePtr<sample::Provider> provider(pipe.handle_to_self.Pass(), NULL);
+ sample::ProviderPtr provider;
+ BindToProxy(new ProviderImpl(), &provider);
MessagePipe pipe2;
{
@@ -156,9 +157,8 @@ TEST_F(RequestResponseTest, EchoMessagePipeHandle) {
}
TEST_F(RequestResponseTest, EchoEnum) {
- InterfacePipe<sample::Provider> pipe;
- ProviderImpl provider_impl(pipe.handle_to_peer.Pass());
- RemotePtr<sample::Provider> provider(pipe.handle_to_self.Pass(), NULL);
+ sample::ProviderPtr provider;
+ BindToProxy(new ProviderImpl(), &provider);
sample::Enum value;
{
diff --git a/mojo/public/cpp/bindings/tests/sample_service_unittest.cc b/mojo/public/cpp/bindings/tests/sample_service_unittest.cc
index 9a4cf36..c13517d 100644
--- a/mojo/public/cpp/bindings/tests/sample_service_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/sample_service_unittest.cc
@@ -266,7 +266,14 @@ void DumpHex(const uint8_t* bytes, uint32_t num_bytes) {
class ServiceImpl : public Service {
public:
- virtual void Frobinate(const Foo& foo, BazOptions baz, ScopedPortHandle port)
+ ServiceImpl() : client_(NULL) {
+ }
+
+ virtual void SetClient(ServiceClient* client) MOJO_OVERRIDE {
+ client_ = client;
+ }
+
+ virtual void Frobinate(const Foo& foo, BazOptions baz, PortPtr port)
MOJO_OVERRIDE {
// Users code goes here to handle the incoming Frobinate message.
@@ -283,6 +290,20 @@ class ServiceImpl : public Service {
Print(depth, "port", port.get());
}
}
+
+ private:
+ ServiceClient* client_;
+};
+
+class ServiceProxyImpl : public ServiceProxy {
+ public:
+ explicit ServiceProxyImpl(mojo::MessageReceiver* receiver)
+ : ServiceProxy(receiver) {
+ }
+
+ virtual void SetClient(ServiceClient* client) MOJO_OVERRIDE {
+ assert(false);
+ }
};
class SimpleMessageReceiver : public mojo::MessageReceiver {
@@ -299,7 +320,8 @@ class SimpleMessageReceiver : public mojo::MessageReceiver {
// the system. It receives the incoming message.
ServiceImpl impl;
- ServiceStub stub(&impl);
+ ServiceStub stub;
+ stub.set_sink(&impl);
return stub.Accept(message);
}
@@ -315,7 +337,7 @@ TEST(BindingsSampleTest, Basic) {
SimpleMessageReceiver receiver;
// User has a proxy to a Service somehow.
- Service* service = new ServiceProxy(&receiver);
+ Service* service = new ServiceProxyImpl(&receiver);
// User constructs a message to send.
@@ -328,8 +350,8 @@ TEST(BindingsSampleTest, Basic) {
Foo foo = MakeFoo();
CheckFoo(foo);
- mojo::InterfacePipe<Port, mojo::AnyInterface> pipe;
- service->Frobinate(foo, Service::BAZ_EXTRA, pipe.handle_to_self.Pass());
+ PortPtr port;
+ service->Frobinate(foo, Service::BAZ_EXTRA, port.Pass());
}
TEST(BindingsSampleTest, DefaultValues) {
diff --git a/mojo/public/cpp/shell/application.h b/mojo/public/cpp/shell/application.h
index ffca7fe..933077b 100644
--- a/mojo/public/cpp/shell/application.h
+++ b/mojo/public/cpp/shell/application.h
@@ -7,7 +7,6 @@
#include <vector>
-#include "mojo/public/cpp/bindings/remote_ptr.h"
#include "mojo/public/cpp/shell/service.h"
#include "mojo/public/cpp/system/core.h"
#include "mojo/public/interfaces/shell/shell.mojom.h"
@@ -16,7 +15,7 @@ namespace mojo {
class Application : public internal::ServiceConnectorBase::Owner {
public:
- explicit Application(ScopedShellHandle shell_handle);
+ explicit Application(ScopedMessagePipeHandle shell_handle);
explicit Application(MojoHandle shell_handle);
virtual ~Application();
@@ -27,6 +26,11 @@ class Application : public internal::ServiceConnectorBase::Owner {
virtual void RemoveServiceConnector(
internal::ServiceConnectorBase* service_connector) MOJO_OVERRIDE;
+ template <typename Interface>
+ void ConnectTo(const std::string& url, InterfacePtr<Interface>* ptr) {
+ mojo::ConnectTo(shell(), url, ptr);
+ }
+
protected:
// ShellClient methods.
virtual void AcceptConnection(const mojo::String& url,
diff --git a/mojo/public/cpp/shell/lib/application.cc b/mojo/public/cpp/shell/lib/application.cc
index 3224202..161e4e0 100644
--- a/mojo/public/cpp/shell/lib/application.cc
+++ b/mojo/public/cpp/shell/lib/application.cc
@@ -6,13 +6,13 @@
namespace mojo {
-Application::Application(ScopedShellHandle shell_handle)
+Application::Application(ScopedMessagePipeHandle shell_handle)
: internal::ServiceConnectorBase::Owner(shell_handle.Pass()) {
}
Application::Application(MojoHandle shell_handle)
: internal::ServiceConnectorBase::Owner(
- mojo::MakeScopedHandle(ShellHandle(shell_handle)).Pass()) {}
+ mojo::MakeScopedHandle(MessagePipeHandle(shell_handle)).Pass()) {}
Application::~Application() {
for (ServiceConnectorList::iterator it = service_connectors_.begin();
diff --git a/mojo/public/cpp/shell/lib/service.cc b/mojo/public/cpp/shell/lib/service.cc
index e408481..2f2e542 100644
--- a/mojo/public/cpp/shell/lib/service.cc
+++ b/mojo/public/cpp/shell/lib/service.cc
@@ -7,8 +7,9 @@
namespace mojo {
namespace internal {
-ServiceConnectorBase::Owner::Owner(ScopedShellHandle shell_handle)
- : shell_(shell_handle.Pass(), this) {
+ServiceConnectorBase::Owner::Owner(ScopedMessagePipeHandle shell_handle)
+ : shell_(MakeProxy<Shell>(shell_handle.Pass())) {
+ shell_->SetClient(this);
}
ServiceConnectorBase::Owner::~Owner() {}
diff --git a/mojo/public/cpp/shell/service.h b/mojo/public/cpp/shell/service.h
index 7dd08ff..c546289 100644
--- a/mojo/public/cpp/shell/service.h
+++ b/mojo/public/cpp/shell/service.h
@@ -5,11 +5,11 @@
#ifndef MOJO_PUBLIC_SHELL_SERVICE_H_
#define MOJO_PUBLIC_SHELL_SERVICE_H_
+#include <assert.h>
+
#include <vector>
-#include "mojo/public/cpp/bindings/error_handler.h"
-#include "mojo/public/cpp/bindings/remote_ptr.h"
-#include "mojo/public/cpp/system/core.h"
+#include "mojo/public/cpp/bindings/allocation_scope.h"
#include "mojo/public/interfaces/shell/shell.mojom.h"
// Utility classes for creating ShellClients that vend service instances.
@@ -19,11 +19,9 @@
// class FooImpl : public Foo {
// public:
// FooImpl();
-// void Initialize(ServiceConnector<FooImpl>* service_connector,
-// ScopedMessagePipeHandle client_handle
+// void Initialize();
// private:
// ServiceConnector<FooImpl>* service_connector_;
-// RemotePtr<FooPeer> client_;
// };
//
//
@@ -66,8 +64,8 @@ class ServiceConnectorBase {
public:
class Owner : public ShellClient {
public:
- Owner(ScopedShellHandle shell_handle);
- ~Owner();
+ Owner(ScopedMessagePipeHandle shell_handle);
+ virtual ~Owner();
Shell* shell() { return shell_.get(); }
virtual void AddServiceConnector(
internal::ServiceConnectorBase* service_connector) = 0;
@@ -79,7 +77,7 @@ class ServiceConnectorBase {
Owner* owner) {
service_connector->owner_ = owner;
}
- RemotePtr<Shell> shell_;
+ ShellPtr shell_;
};
ServiceConnectorBase() : owner_(NULL) {}
virtual ~ServiceConnectorBase();
@@ -98,27 +96,33 @@ class ServiceConnector : public internal::ServiceConnectorBase {
ServiceConnector(Context* context = NULL) : context_(context) {}
virtual ~ServiceConnector() {
- for (typename ServiceList::iterator it = services_.begin();
- it != services_.end(); ++it) {
+ ConnectionList doomed;
+ doomed.swap(connections_);
+ for (typename ConnectionList::iterator it = doomed.begin();
+ it != doomed.end(); ++it) {
delete *it;
}
+ assert(connections_.empty()); // No one should have added more!
}
virtual void AcceptConnection(const std::string& url,
- ScopedMessagePipeHandle client_handle)
- MOJO_OVERRIDE {
- ServiceImpl* service = new ServiceImpl();
- service->Initialize(this, client_handle.Pass());
- services_.push_back(service);
+ ScopedMessagePipeHandle handle) MOJO_OVERRIDE {
+ ServiceImpl* impl = BindToPipe(new ServiceImpl(), handle.Pass());
+ impl->set_connector(this);
+
+ connections_.push_back(impl);
+
+ impl->Initialize();
}
- void RemoveService(ServiceImpl* service) {
- for (typename ServiceList::iterator it = services_.begin();
- it != services_.end(); ++it) {
- if (*it == service) {
- services_.erase(it);
- delete service;
- if (services_.empty())
+ void RemoveConnection(ServiceImpl* impl) {
+ // Called from ~ServiceImpl, in response to a connection error.
+ for (typename ConnectionList::iterator it = connections_.begin();
+ it != connections_.end(); ++it) {
+ if (*it == impl) {
+ delete impl;
+ connections_.erase(it);
+ if (connections_.empty())
owner_->RemoveServiceConnector(this);
return;
}
@@ -128,58 +132,63 @@ class ServiceConnector : public internal::ServiceConnectorBase {
Context* context() const { return context_; }
private:
- typedef std::vector<ServiceImpl*> ServiceList;
- ServiceList services_;
+ typedef std::vector<ServiceImpl*> ConnectionList;
+ ConnectionList connections_;
Context* context_;
};
// Specialization of ServiceConnection.
// ServiceInterface: Service interface.
-// ServiceImpl: Implementation of Service interface.
+// ServiceImpl: Subclass of ServiceConnection<...>.
// Context: Optional type of shared context.
template <class ServiceInterface, class ServiceImpl, typename Context=void>
-class ServiceConnection : public ServiceInterface {
- public:
+class ServiceConnection : public InterfaceImpl<ServiceInterface> {
+ protected:
+ // NOTE: shell() and context() are not available at construction time.
+ // Initialize() will be called once those are available.
+ ServiceConnection() : service_connector_(NULL) {}
+
virtual ~ServiceConnection() {}
- protected:
- ServiceConnection() : reaper_(this), service_connector_(NULL) {}
-
- void Initialize(ServiceConnector<ServiceImpl, Context>* service_connector,
- ScopedMessagePipeHandle client_handle) {
- service_connector_ = service_connector;
- client_.reset(
- MakeScopedHandle(
- InterfaceHandle<typename ServiceInterface::_Peer>(
- client_handle.release().value())).Pass(),
- this,
- &reaper_);
+ virtual void OnConnectionError() MOJO_OVERRIDE {
+ service_connector_->RemoveConnection(static_cast<ServiceImpl*>(this));
+ }
+
+ // Shadow this method in ServiceImpl to perform one-time initialization.
+ // At the time this is called, shell() and context() will be available.
+ // NOTE: No need to call the base class Initialize from your subclass. It
+ // will always be a no-op.
+ void Initialize() {}
+
+ Shell* shell() {
+ return service_connector_->shell();
}
- Shell* shell() { return service_connector_->shell(); }
- Context* context() const { return service_connector_->context(); }
- typename ServiceInterface::_Peer* client() { return client_.get(); }
+ Context* context() const {
+ return service_connector_->context();
+ }
private:
- // The Reaper class allows us to handle errors on the client proxy without
- // polluting the name space of the ServiceConnection<> class.
- class Reaper : public ErrorHandler {
- public:
- Reaper(ServiceConnection<ServiceInterface, ServiceImpl, Context>* service)
- : service_(service) {}
- virtual void OnError() {
- service_->service_connector_->RemoveService(
- static_cast<ServiceImpl*>(service_));
- }
- private:
- ServiceConnection<ServiceInterface, ServiceImpl, Context>* service_;
- };
friend class ServiceConnector<ServiceImpl, Context>;
- Reaper reaper_;
+
+ // Called shortly after this class is instantiated.
+ void set_connector(ServiceConnector<ServiceImpl, Context>* connector) {
+ service_connector_ = connector;
+ }
+
ServiceConnector<ServiceImpl, Context>* service_connector_;
- RemotePtr<typename ServiceInterface::_Peer> client_;
};
+template <typename Interface>
+inline void ConnectTo(Shell* shell, const std::string& url,
+ InterfacePtr<Interface>* ptr) {
+ MessagePipe pipe;
+ ptr->Bind(pipe.handle0.Pass());
+
+ AllocationScope scope;
+ shell->Connect(url, pipe.handle1.Pass());
+}
+
} // namespace mojo
#endif // MOJO_PUBLIC_SHELL_SERVICE_H_
diff --git a/mojo/public/interfaces/bindings/tests/math_calculator.mojom b/mojo/public/interfaces/bindings/tests/math_calculator.mojom
index e4a1c94..63b7a69 100644
--- a/mojo/public/interfaces/bindings/tests/math_calculator.mojom
+++ b/mojo/public/interfaces/bindings/tests/math_calculator.mojom
@@ -5,14 +5,13 @@
[JavaPackage="org.chromium.mojo.bindings.test"]
module math {
-[Peer=CalculatorUI]
+[Client=CalculatorUI]
interface Calculator {
Clear@0();
Add@1(double value @0);
Multiply@2(double value @0);
};
-[Peer=Calculator]
interface CalculatorUI {
Output@0(double value @0);
};
diff --git a/mojo/public/interfaces/bindings/tests/sample_factory.mojom b/mojo/public/interfaces/bindings/tests/sample_factory.mojom
index bad466f..33de19f 100644
--- a/mojo/public/interfaces/bindings/tests/sample_factory.mojom
+++ b/mojo/public/interfaces/bindings/tests/sample_factory.mojom
@@ -19,13 +19,12 @@ struct Response {
handle<message_pipe> pipe;
};
-[Peer=FactoryClient]
+[Client=FactoryClient]
interface Factory {
DoStuff(Request request, handle<message_pipe> pipe);
DoStuff2(handle<data_pipe_consumer> pipe);
};
-[Peer=Factory]
interface FactoryClient {
DidStuff(Response response, string text);
DidStuff2(string text);
diff --git a/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom b/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom
index 462e3cd..597fd0d 100644
--- a/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom
+++ b/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom
@@ -10,7 +10,7 @@ enum Enum {
ENUM_VALUE
};
-[Peer=ProviderClient]
+[Client=ProviderClient]
interface Provider {
EchoString(string a) => (string a);
EchoStrings(string a, string b) => (string a, string b);
@@ -18,7 +18,7 @@ interface Provider {
EchoEnum(Enum a) => (Enum a);
};
-[Peer=Provider]
+// TODO(darin): We shouldn't need this, but JS bindings don't work without it.
interface ProviderClient {
};
diff --git a/mojo/public/interfaces/bindings/tests/sample_service.mojom b/mojo/public/interfaces/bindings/tests/sample_service.mojom
index 0336998..c840709 100644
--- a/mojo/public/interfaces/bindings/tests/sample_service.mojom
+++ b/mojo/public/interfaces/bindings/tests/sample_service.mojom
@@ -53,7 +53,7 @@ struct DefaultsTest {
Bar.Type bar_type = Bar.TYPE_BOTH;
};
-[Peer=ServiceClient]
+[Client=ServiceClient]
interface Service {
enum BazOptions {
BAZ_REGULAR = 0,
@@ -62,7 +62,6 @@ interface Service {
Frobinate@0(Foo foo @0, BazOptions baz @1, Port port @2);
};
-[Peer=Service]
interface ServiceClient {
DidFrobinate@0(int32 result @0);
};
@@ -70,7 +69,7 @@ interface ServiceClient {
// This interface is referenced above where it is defined. It also refers to
// itself from a method.
interface Port {
- PostMessage@0(string message_text @0, Port[] extra_ports@1);
+ PostMessage@0(string message_text @0, Port port@1);
};
}
diff --git a/mojo/public/interfaces/shell/shell.mojom b/mojo/public/interfaces/shell/shell.mojom
index 39eae78..e5f6c39 100644
--- a/mojo/public/interfaces/shell/shell.mojom
+++ b/mojo/public/interfaces/shell/shell.mojom
@@ -4,14 +4,13 @@
module mojo {
-[Peer=ShellClient]
+[Client=ShellClient]
interface Shell {
// Loads url. mojo:{service} will result in the user of the value of the
// --origin flag to the shell being used.
Connect(string url, handle<message_pipe> client_handle);
};
-[Peer=Shell]
interface ShellClient {
AcceptConnection(string url, handle<message_pipe> client_handle);
};
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl
index 60fbfc5..d1c7e53 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl
@@ -1,18 +1,18 @@
{%- import "interface_macros.tmpl" as interface_macros %}
class {{interface.name}}Proxy;
class {{interface.name}}Stub;
-{% if interface.peer %}
-class {{interface.peer}};
+{% if interface.client %}
+class {{interface.client}};
{% endif %}
class {{interface.name}} {
public:
- typedef {{interface.name}}Proxy _Proxy;
- typedef {{interface.name}}Stub _Stub;
-{% if interface.peer %}
- typedef {{interface.peer}} _Peer;
+ typedef {{interface.name}}Proxy Proxy_;
+ typedef {{interface.name}}Stub Stub_;
+{% if interface.client %}
+ typedef {{interface.client}} Client_;
{% else %}
- typedef mojo::NoInterface _Peer;
+ typedef mojo::NoInterface Client_;
{% endif %}
{#--- Enums #}
@@ -22,6 +22,13 @@ class {{interface.name}} {
{%- endfor %}
{#--- Methods #}
+ virtual ~{{interface.name}}() {}
+{%- if interface.client %}
+ // Called once before any other method.
+ virtual void SetClient({{interface.client}}* client) = 0;
+{%- else %}
+ virtual void SetClient(mojo::NoInterface* client) {}
+{%- endif %}
{%- for method in interface.methods %}
virtual void {{method.name}}({{interface_macros.declare_request_params("", method)}}) = 0;
{%- endfor %}
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
index 7a03023..ccd4b42 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
@@ -6,6 +6,8 @@
{%- for param in parameters %}
{%- if param.kind|is_object_kind -%}
mojo::internal::Wrap(params->{{param.name}}())
+{%- elif param.kind|is_interface_kind -%}
+mojo::MakeProxy<{{param.kind.name}}>(mojo::MakePassable(params->{{param.name}}()).Pass())
{%- elif param.kind|is_handle_kind -%}
mojo::MakePassable(params->{{param.name}}()).Pass()
{%- elif param.kind|is_enum_kind -%}
@@ -38,6 +40,14 @@ params->{{param.name}}()
if (!in_{{param.name}}.is_null())
params->set_{{param.name}}(
mojo::internal::Unwrap(in_{{param.name}})->Clone(builder.buffer()));
+{%- elif param.kind|is_interface_kind %}
+ if (!in_{{param.name}}.get()) {
+ params->set_{{param.name}}(mojo::MessagePipeHandle());
+ } else {
+ // Delegate handle.
+ params->set_{{param.name}}(
+ in_{{param.name}}.ResetAndReturnMessagePipe().release());
+ }
{%- elif param.kind|is_handle_kind %}
params->set_{{param.name}}(in_{{param.name}}.release());
{%- else %}
@@ -165,8 +175,8 @@ void {{class_name}}_{{method.name}}_ProxyToResponder::Run(
{%- endif -%}
{%- endfor %}
-{{class_name}}Stub::{{class_name}}Stub({{class_name}}* sink)
- : sink_(sink) {
+{{class_name}}Stub::{{class_name}}Stub()
+ : sink_(NULL) {
}
{#--- Stub definition #}
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl
index c4a8bed..b9cf4bc 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl
@@ -3,6 +3,12 @@ class {{interface.name}}Proxy : public {{interface.name}} {
public:
explicit {{interface.name}}Proxy(mojo::MessageReceiver* receiver);
+{%- if interface.client %}
+ virtual void SetClient({{interface.client}}* client) = 0;
+{%- else %}
+ virtual void SetClient(mojo::NoInterface* client) {}
+{%- endif %}
+
{%- for method in interface.methods %}
virtual void {{method.name}}(
{{interface_macros.declare_request_params("", method)}}
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl
index 0e4b202..b435d5d 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl
@@ -1,6 +1,8 @@
class {{interface.name}}Stub : public mojo::MessageReceiver {
public:
- explicit {{interface.name}}Stub({{interface.name}}* sink);
+ {{interface.name}}Stub();
+ void set_sink({{interface.name}}* sink) { sink_ = sink; }
+ {{interface.name}}* sink() { return sink_; }
virtual bool Accept(mojo::Message* message) MOJO_OVERRIDE;
virtual bool AcceptWithResponder(mojo::Message* message,
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
index 4c667ae..6a0f6cf 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
@@ -10,7 +10,9 @@
#include "mojo/public/cpp/bindings/array.h"
#include "mojo/public/cpp/bindings/callback.h"
-#include "mojo/public/cpp/bindings/interface.h"
+#include "mojo/public/cpp/bindings/interface_impl.h"
+#include "mojo/public/cpp/bindings/interface_ptr.h"
+#include "mojo/public/cpp/bindings/no_interface.h"
#include "{{module.path}}-internal.h"
{%- for import in imports %}
#include "{{import.module.path}}.h"
@@ -28,10 +30,7 @@ namespace {{namespace}} {
{#--- Interface Forward Declarations -#}
{% for interface in interfaces %}
class {{interface.name}};
-// A typesafe variant of MessagePipeHandle:
-typedef mojo::Interface<{{interface.name}}>::Handle {{interface.name}}Handle;
-// A typesafe variant of ScopedMessagePipeHandle:
-typedef mojo::Interface<{{interface.name}}>::ScopedHandle Scoped{{interface.name}}Handle;
+typedef mojo::InterfacePtr<{{interface.name}}> {{interface.name}}Ptr;
{% endfor %}
{#--- Structs #}
diff --git a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
index 8f48f8e..3996d5e 100644
--- a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
@@ -50,7 +50,7 @@ def GetCppType(kind):
if isinstance(kind, mojom.Array):
return "mojo::internal::Array_Data<%s>*" % GetCppType(kind.kind)
if isinstance(kind, mojom.Interface):
- return "%sHandle" % kind.name
+ return "mojo::MessagePipeHandle"
if isinstance(kind, mojom.Enum):
return "int32_t"
if kind.spec == 's':
@@ -63,7 +63,7 @@ def GetCppArrayArgWrapperType(kind):
if isinstance(kind, mojom.Array):
return "mojo::Array<%s >" % GetCppArrayArgWrapperType(kind.kind)
if isinstance(kind, mojom.Interface):
- return "%sHandle" % kind.name
+ raise Exception("Arrays of interfaces not yet supported!")
if kind.spec == 's':
return "mojo::String"
return _kind_to_cpp_type[kind]
@@ -74,7 +74,7 @@ def GetCppResultWrapperType(kind):
if isinstance(kind, mojom.Array):
return "mojo::Array<%s >" % GetCppArrayArgWrapperType(kind.kind)
if isinstance(kind, mojom.Interface):
- return "Scoped%sHandle" % kind.name
+ return "%sPtr" % kind.name
if kind.spec == 's':
return "mojo::String"
if kind.spec == 'h':
@@ -95,7 +95,7 @@ def GetCppWrapperType(kind):
if isinstance(kind, mojom.Array):
return "mojo::Array<%s >" % GetCppArrayArgWrapperType(kind.kind)
if isinstance(kind, mojom.Interface):
- return "mojo::Passable<%sHandle>" % kind.name
+ return "mojo::Passable<mojo::MessagePipeHandle>"
if kind.spec == 's':
return "mojo::String"
if generator.IsHandleKind(kind):
@@ -108,7 +108,7 @@ def GetCppConstWrapperType(kind):
if isinstance(kind, mojom.Array):
return "const mojo::Array<%s >&" % GetCppArrayArgWrapperType(kind.kind)
if isinstance(kind, mojom.Interface):
- return "Scoped%sHandle" % kind.name
+ return "%sPtr" % kind.name
if isinstance(kind, mojom.Enum):
return GetNameForKind(kind)
if kind.spec == 's':
@@ -134,7 +134,7 @@ def GetCppFieldType(kind):
if isinstance(kind, mojom.Array):
return "mojo::internal::ArrayPointer<%s>" % GetCppType(kind.kind)
if isinstance(kind, mojom.Interface):
- return "%sHandle" % kind.name
+ return "mojo::MessagePipeHandle"
if isinstance(kind, mojom.Enum):
return GetNameForKind(kind)
if kind.spec == 's':
@@ -180,6 +180,7 @@ class Generator(generator.Generator):
"get_pad": pack.GetPad,
"is_enum_kind": generator.IsEnumKind,
"is_handle_kind": generator.IsHandleKind,
+ "is_interface_kind": generator.IsInterfaceKind,
"is_object_kind": generator.IsObjectKind,
"is_string_kind": generator.IsStringKind,
"is_array_kind": lambda kind: isinstance(kind, mojom.Array),
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/data.py b/mojo/public/tools/bindings/pylib/mojom/generate/data.py
index 1f2f808..2199782 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/data.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/data.py
@@ -221,7 +221,7 @@ def MethodFromData(module, data, interface):
def InterfaceToData(interface):
return {
istr(0, 'name'): interface.name,
- istr(1, 'peer'): interface.peer,
+ istr(1, 'client'): interface.client,
istr(2, 'methods'): map(MethodToData, interface.methods)
}
@@ -229,7 +229,7 @@ def InterfaceFromData(module, data):
interface = mojom.Interface(module=module)
interface.name = data['name']
interface.spec = 'x:' + module.namespace + '.' + interface.name
- interface.peer = data['peer'] if data.has_key('peer') else None
+ interface.client = data['client'] if data.has_key('client') else None
module.kinds[interface.spec] = interface
interface.enums = map(lambda enum:
EnumFromData(module, enum, interface), data['enums'])
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/data_tests.py b/mojo/public/tools/bindings/pylib/mojom/generate/data_tests.py
index bca7ed8..096554c 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/data_tests.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/data_tests.py
@@ -44,7 +44,7 @@ test_dict = {
{'name': 'testfield2', 'kind': 'a:i32', 'ordinal': 42}]}],
'interfaces': [{
'name': 'Server',
- 'peer': None,
+ 'client': None,
'methods': [{
'name': 'Foo',
'parameters': [
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/generator.py b/mojo/public/tools/bindings/pylib/mojom/generate/generator.py
index 709aa2a..76e5998 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/generator.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/generator.py
@@ -46,6 +46,9 @@ def IsObjectKind(kind):
def IsHandleKind(kind):
return kind.spec.startswith('h') or isinstance(kind, mojom.Interface)
+def IsInterfaceKind(kind):
+ return isinstance(kind, mojom.Interface)
+
def StudlyCapsToCamel(studly):
return studly[0].lower() + studly[1:]
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/module.py b/mojo/public/tools/bindings/pylib/mojom/generate/module.py
index 4abe690..875ede9 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/module.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/module.py
@@ -139,7 +139,7 @@ class Method(object):
class Interface(Kind):
- def __init__(self, name=None, peer=None, module=None):
+ def __init__(self, name=None, client=None, module=None):
self.module = module
self.name = name
if name != None:
@@ -147,7 +147,7 @@ class Interface(Kind):
else:
spec = None
Kind.__init__(self, spec)
- self.peer = peer
+ self.client = client
self.methods = []
def AddMethod(self, name, ordinal=None):
diff --git a/mojo/public/tools/bindings/pylib/mojom/parse/translate.py b/mojo/public/tools/bindings/pylib/mojom/parse/translate.py
index 2300cb6..b363d9c 100644
--- a/mojo/public/tools/bindings/pylib/mojom/parse/translate.py
+++ b/mojo/public/tools/bindings/pylib/mojom/parse/translate.py
@@ -88,7 +88,7 @@ def _MapStruct(tree):
def _MapInterface(tree):
interface = {}
interface['name'] = tree[1]
- interface['peer'] = _GetAttribute(tree[2], 'Peer')
+ interface['client'] = _GetAttribute(tree[2], 'Client')
interface['methods'] = _MapTree(_MapMethod, tree[3], 'METHOD')
interface['enums'] = _MapTree(_MapEnum, tree[3], 'ENUM')
return interface