diff options
author | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-30 05:22:26 +0000 |
---|---|---|
committer | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-30 05:22:26 +0000 |
commit | 846543597405c95ecfcc3318e1c071f5f9a2b1f1 (patch) | |
tree | 3bf717a0044950e509579c65d4b4c542dc26cebd /mojo | |
parent | 422b0bc37562eea81a48268bc74de7ad9f413824 (diff) | |
download | chromium_src-846543597405c95ecfcc3318e1c071f5f9a2b1f1.zip chromium_src-846543597405c95ecfcc3318e1c071f5f9a2b1f1.tar.gz chromium_src-846543597405c95ecfcc3318e1c071f5f9a2b1f1.tar.bz2 |
Mojo: Implement support for |Foo&| mojom syntax
BUG=374439
Review URL: https://codereview.chromium.org/272323003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@273717 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'mojo')
41 files changed, 306 insertions, 74 deletions
diff --git a/mojo/aura/context_factory_mojo.cc b/mojo/aura/context_factory_mojo.cc index 3edee0b..a95cc25 100644 --- a/mojo/aura/context_factory_mojo.cc +++ b/mojo/aura/context_factory_mojo.cc @@ -16,8 +16,9 @@ namespace mojo { -ContextFactoryMojo::ContextFactoryMojo(ScopedMessagePipeHandle gles2_handle) - : gles2_handle_(gles2_handle.Pass()) { +ContextFactoryMojo::ContextFactoryMojo( + ScopedMessagePipeHandle command_buffer_handle) + : command_buffer_handle_(command_buffer_handle.Pass()) { } ContextFactoryMojo::~ContextFactoryMojo() { @@ -25,8 +26,9 @@ ContextFactoryMojo::~ContextFactoryMojo() { scoped_ptr<cc::OutputSurface> ContextFactoryMojo::CreateOutputSurface( ui::Compositor* compositor, bool software_fallback) { - return make_scoped_ptr(new cc::OutputSurface( - new ContextProviderMojo(gles2_handle_.Pass()))); + return make_scoped_ptr( + new cc::OutputSurface( + new ContextProviderMojo(command_buffer_handle_.Pass()))); } scoped_refptr<ui::Reflector> ContextFactoryMojo::CreateReflector( diff --git a/mojo/aura/context_factory_mojo.h b/mojo/aura/context_factory_mojo.h index 485dc9f..3eca794 100644 --- a/mojo/aura/context_factory_mojo.h +++ b/mojo/aura/context_factory_mojo.h @@ -19,7 +19,7 @@ namespace mojo { // The default factory that creates in-process contexts. class ContextFactoryMojo : public ui::ContextFactory { public: - explicit ContextFactoryMojo(ScopedMessagePipeHandle gles2_handle); + explicit ContextFactoryMojo(ScopedMessagePipeHandle command_buffer_handle); virtual ~ContextFactoryMojo(); // ContextFactory implementation @@ -42,7 +42,7 @@ class ContextFactoryMojo : public ui::ContextFactory { scoped_refptr<webkit::gpu::ContextProviderInProcess> shared_main_thread_contexts_; - ScopedMessagePipeHandle gles2_handle_; + ScopedMessagePipeHandle command_buffer_handle_; DISALLOW_COPY_AND_ASSIGN(ContextFactoryMojo); }; diff --git a/mojo/aura/window_tree_host_mojo.cc b/mojo/aura/window_tree_host_mojo.cc index bcebbdfb..f3e42d1 100644 --- a/mojo/aura/window_tree_host_mojo.cc +++ b/mojo/aura/window_tree_host_mojo.cc @@ -34,8 +34,9 @@ WindowTreeHostMojo::WindowTreeHostMojo( native_viewport_.set_client(this); native_viewport_->Create(Rect::From(bounds)); - ScopedMessagePipeHandle gles2_handle, gles2_client_handle; - CreateMessagePipe(&gles2_handle, &gles2_client_handle); + MessagePipe pipe; + native_viewport_->CreateGLES2Context( + MakeRequest<CommandBuffer>(pipe.handle0.Pass())); // The ContextFactory must exist before any Compositors are created. if (context_factory_) { @@ -43,12 +44,10 @@ WindowTreeHostMojo::WindowTreeHostMojo( delete context_factory_; context_factory_ = NULL; } - context_factory_ = new ContextFactoryMojo(gles2_handle.Pass()); + context_factory_ = new ContextFactoryMojo(pipe.handle1.Pass()); ui::ContextFactory::SetInstance(context_factory_); aura::Env::GetInstance()->set_context_factory(context_factory_); CHECK(context_factory_) << "No GL bindings."; - - native_viewport_->CreateGLES2Context(gles2_client_handle.Pass()); } WindowTreeHostMojo::~WindowTreeHostMojo() { diff --git a/mojo/cc/context_provider_mojo.cc b/mojo/cc/context_provider_mojo.cc index 8a759fd..7356b58 100644 --- a/mojo/cc/context_provider_mojo.cc +++ b/mojo/cc/context_provider_mojo.cc @@ -8,13 +8,17 @@ namespace mojo { -ContextProviderMojo::ContextProviderMojo(ScopedMessagePipeHandle gl_pipe) - : gl_pipe_(gl_pipe.Pass()) {} +ContextProviderMojo::ContextProviderMojo( + ScopedMessagePipeHandle command_buffer_handle) + : command_buffer_handle_(command_buffer_handle.Pass()) {} bool ContextProviderMojo::BindToCurrentThread() { - DCHECK(gl_pipe_.is_valid()); + DCHECK(command_buffer_handle_.is_valid()); context_ = MojoGLES2CreateContext( - gl_pipe_.release().value(), &ContextLostThunk, NULL, this); + command_buffer_handle_.release().value(), + &ContextLostThunk, + NULL, + this); return !!context_; } diff --git a/mojo/cc/context_provider_mojo.h b/mojo/cc/context_provider_mojo.h index 5ddc7c1..eda6e43 100644 --- a/mojo/cc/context_provider_mojo.h +++ b/mojo/cc/context_provider_mojo.h @@ -13,7 +13,7 @@ namespace mojo { class ContextProviderMojo : public cc::ContextProvider { public: - explicit ContextProviderMojo(ScopedMessagePipeHandle gl_pipe); + explicit ContextProviderMojo(ScopedMessagePipeHandle command_buffer_handle); // cc::ContextProvider implementation. virtual bool BindToCurrentThread() OVERRIDE; @@ -42,7 +42,7 @@ class ContextProviderMojo : public cc::ContextProvider { void ContextLost(); cc::ContextProvider::Capabilities capabilities_; - ScopedMessagePipeHandle gl_pipe_; + ScopedMessagePipeHandle command_buffer_handle_; MojoGLES2Context context_; }; diff --git a/mojo/examples/compositor_app/compositor_app.cc b/mojo/examples/compositor_app/compositor_app.cc index 0b4baaa..e4b72da 100644 --- a/mojo/examples/compositor_app/compositor_app.cc +++ b/mojo/examples/compositor_app/compositor_app.cc @@ -30,9 +30,10 @@ class SampleApp : public Application, public NativeViewportClient { viewport_->Create(Rect::From(gfx::Rect(10, 10, 800, 600))); viewport_->Show(); - MessagePipe gles2_pipe; - viewport_->CreateGLES2Context(gles2_pipe.handle0.Pass()); - host_.reset(new CompositorHost(gles2_pipe.handle1.Pass())); + MessagePipe pipe; + viewport_->CreateGLES2Context( + MakeRequest<CommandBuffer>(pipe.handle0.Pass())); + host_.reset(new CompositorHost(pipe.handle1.Pass())); } virtual void OnCreated() OVERRIDE { diff --git a/mojo/examples/compositor_app/compositor_host.cc b/mojo/examples/compositor_app/compositor_host.cc index e985364..3160145 100644 --- a/mojo/examples/compositor_app/compositor_host.cc +++ b/mojo/examples/compositor_app/compositor_host.cc @@ -14,9 +14,10 @@ namespace mojo { namespace examples { -CompositorHost::CompositorHost(ScopedMessagePipeHandle gl_pipe) - : gl_pipe_(gl_pipe.Pass()), compositor_thread_("compositor") { - DCHECK(gl_pipe_.is_valid()); +CompositorHost::CompositorHost(ScopedMessagePipeHandle command_buffer_handle) + : command_buffer_handle_(command_buffer_handle.Pass()), + compositor_thread_("compositor") { + DCHECK(command_buffer_handle_.is_valid()); bool started = compositor_thread_.Start(); DCHECK(started); @@ -72,7 +73,8 @@ void CompositorHost::ApplyScrollAndScale(const gfx::Vector2d& scroll_delta, scoped_ptr<cc::OutputSurface> CompositorHost::CreateOutputSurface( bool fallback) { return make_scoped_ptr( - new cc::OutputSurface(new ContextProviderMojo(gl_pipe_.Pass()))); + new cc::OutputSurface( + new ContextProviderMojo(command_buffer_handle_.Pass()))); } void CompositorHost::DidInitializeOutputSurface() { diff --git a/mojo/examples/compositor_app/compositor_host.h b/mojo/examples/compositor_app/compositor_host.h index 35c78c5..ea49e28 100644 --- a/mojo/examples/compositor_app/compositor_host.h +++ b/mojo/examples/compositor_app/compositor_host.h @@ -23,7 +23,7 @@ class GLES2ClientImpl; class CompositorHost : public cc::LayerTreeHostClient { public: - explicit CompositorHost(ScopedMessagePipeHandle gl_pipe); + explicit CompositorHost(ScopedMessagePipeHandle command_buffer_handle); virtual ~CompositorHost(); void SetSize(const gfx::Size& viewport_size); @@ -46,7 +46,7 @@ class CompositorHost : public cc::LayerTreeHostClient { private: void SetupScene(); - ScopedMessagePipeHandle gl_pipe_; + ScopedMessagePipeHandle command_buffer_handle_; scoped_ptr<cc::LayerTreeHost> tree_; scoped_refptr<cc::Layer> child_layer_; base::Thread compositor_thread_; diff --git a/mojo/examples/pepper_container_app/pepper_container_app.cc b/mojo/examples/pepper_container_app/pepper_container_app.cc index 8d8b4e9..6e92a68 100644 --- a/mojo/examples/pepper_container_app/pepper_container_app.cc +++ b/mojo/examples/pepper_container_app/pepper_container_app.cc @@ -85,9 +85,9 @@ class PepperContainerApp: public Application, // MojoPpapiGlobals::Delegate implementation. virtual ScopedMessagePipeHandle CreateGLES2Context() OVERRIDE { - MessagePipe gles2_pipe; - viewport_->CreateGLES2Context(gles2_pipe.handle1.Pass()); - return gles2_pipe.handle0.Pass(); + CommandBufferPtr command_buffer; + viewport_->CreateGLES2Context(Get(&command_buffer)); + return command_buffer.PassMessagePipe(); } private: diff --git a/mojo/examples/sample_app/gles2_client_impl.cc b/mojo/examples/sample_app/gles2_client_impl.cc index 981caaa..82ab114 100644 --- a/mojo/examples/sample_app/gles2_client_impl.cc +++ b/mojo/examples/sample_app/gles2_client_impl.cc @@ -26,10 +26,10 @@ float GetRandomColor() { } -GLES2ClientImpl::GLES2ClientImpl(ScopedMessagePipeHandle pipe) +GLES2ClientImpl::GLES2ClientImpl(CommandBufferPtr command_buffer) : getting_animation_frames_(false) { context_ = MojoGLES2CreateContext( - pipe.release().value(), + command_buffer.PassMessagePipe().release().value(), &ContextLostThunk, &DrawAnimationFrameThunk, this); diff --git a/mojo/examples/sample_app/gles2_client_impl.h b/mojo/examples/sample_app/gles2_client_impl.h index 08b2a3e..a75a284 100644 --- a/mojo/examples/sample_app/gles2_client_impl.h +++ b/mojo/examples/sample_app/gles2_client_impl.h @@ -16,7 +16,7 @@ namespace examples { class GLES2ClientImpl { public: - explicit GLES2ClientImpl(ScopedMessagePipeHandle pipe); + explicit GLES2ClientImpl(CommandBufferPtr command_buffer); virtual ~GLES2ClientImpl(); void SetSize(const Size& size); diff --git a/mojo/examples/sample_app/sample_app.cc b/mojo/examples/sample_app/sample_app.cc index 2e126b0..ec1ba51 100644 --- a/mojo/examples/sample_app/sample_app.cc +++ b/mojo/examples/sample_app/sample_app.cc @@ -38,9 +38,9 @@ class SampleApp : public Application, public NativeViewportClient { viewport_->Create(rect.Pass()); viewport_->Show(); - MessagePipe gles2_pipe; - viewport_->CreateGLES2Context(gles2_pipe.handle0.Pass()); - gles2_client_.reset(new GLES2ClientImpl(gles2_pipe.handle1.Pass())); + CommandBufferPtr command_buffer; + viewport_->CreateGLES2Context(Get(&command_buffer)); + gles2_client_.reset(new GLES2ClientImpl(command_buffer.Pass())); } virtual void OnCreated() MOJO_OVERRIDE { diff --git a/mojo/gles2/command_buffer_client_impl.cc b/mojo/gles2/command_buffer_client_impl.cc index c40f82b..c051ac2 100644 --- a/mojo/gles2/command_buffer_client_impl.cc +++ b/mojo/gles2/command_buffer_client_impl.cc @@ -51,13 +51,12 @@ CommandBufferClientImpl::CommandBufferClientImpl( MojoAsyncWaiter* async_waiter, ScopedMessagePipeHandle command_buffer_handle) : delegate_(delegate), - command_buffer_(MakeProxy<mojo::CommandBuffer>( - command_buffer_handle.Pass(), async_waiter)), shared_state_(NULL), last_put_offset_(-1), next_transfer_buffer_id_(0), initialize_result_(false), async_waiter_(async_waiter) { + command_buffer_.Bind(command_buffer_handle.Pass(), async_waiter); command_buffer_.set_error_handler(this); command_buffer_.set_client(this); } diff --git a/mojo/mojo_public.gypi b/mojo/mojo_public.gypi index 0e53ae9..27dcf02 100644 --- a/mojo/mojo_public.gypi +++ b/mojo/mojo_public.gypi @@ -230,6 +230,7 @@ 'public/cpp/bindings/error_handler.h', 'public/cpp/bindings/interface_impl.h', 'public/cpp/bindings/interface_ptr.h', + 'public/cpp/bindings/interface_request.h', 'public/cpp/bindings/message.h', 'public/cpp/bindings/message_filter.h', 'public/cpp/bindings/no_interface.h', diff --git a/mojo/mojo_services.gypi b/mojo/mojo_services.gypi index 112893f..5f372d9 100644 --- a/mojo/mojo_services.gypi +++ b/mojo/mojo_services.gypi @@ -110,6 +110,7 @@ ], 'dependencies': [ 'mojo_geometry_bindings', + 'mojo_gles2_bindings', 'mojo_input_events_bindings', 'mojo_cpp_bindings', ], diff --git a/mojo/public/cpp/bindings/interface_impl.h b/mojo/public/cpp/bindings/interface_impl.h index fc1e524..a7272b6 100644 --- a/mojo/public/cpp/bindings/interface_impl.h +++ b/mojo/public/cpp/bindings/interface_impl.h @@ -5,6 +5,7 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_IMPL_H_ #define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_IMPL_H_ +#include "mojo/public/cpp/bindings/interface_request.h" #include "mojo/public/cpp/bindings/lib/interface_impl_internal.h" #include "mojo/public/cpp/system/macros.h" @@ -81,6 +82,24 @@ Impl* BindToProxy(Impl* instance, return instance; } +// Takes an instance of an InterfaceImpl<..> subclass and binds it to the given +// InterfaceRequest<..>. 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* BindToRequest(Impl* instance, + InterfaceRequest<Interface>* request, + MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter()) { + return BindToPipe(instance, request->PassMessagePipe(), waiter); +} + } // 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 index 6d47a86..266cda0 100644 --- a/mojo/public/cpp/bindings/interface_ptr.h +++ b/mojo/public/cpp/bindings/interface_ptr.h @@ -24,10 +24,11 @@ class InterfacePtr { InterfacePtr() {} InterfacePtr(RValue other) { - other.object->internal_state_.Swap(&internal_state_); + internal_state_.Swap(&other.object->internal_state_); } InterfacePtr& operator=(RValue other) { - other.object->internal_state_.Swap(&internal_state_); + reset(); + internal_state_.Swap(&other.object->internal_state_); return *this; } @@ -37,7 +38,7 @@ class InterfacePtr { return internal_state_.instance(); } Interface* operator->() const { return get(); } - Interface* operator*() const { return get(); } + Interface& operator*() const { return *get(); } void reset() { State doomed; @@ -84,11 +85,11 @@ class InterfacePtr { // 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() { + ScopedMessagePipeHandle PassMessagePipe() { State state; internal_state_.Swap(&state); return state.router() ? - state.router()->ReleaseMessagePipe() : ScopedMessagePipeHandle(); + state.router()->PassMessagePipe() : ScopedMessagePipeHandle(); } // DO NOT USE. Exposed only for internal use and for testing. diff --git a/mojo/public/cpp/bindings/interface_request.h b/mojo/public/cpp/bindings/interface_request.h new file mode 100644 index 0000000..6b7d303 --- /dev/null +++ b/mojo/public/cpp/bindings/interface_request.h @@ -0,0 +1,76 @@ +// 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_REQUEST_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_REQUEST_H_ + +#include "mojo/public/cpp/bindings/interface_ptr.h" + +namespace mojo { + +// Used in methods that return instances of remote objects. +template <typename Interface> +class InterfaceRequest { + MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(InterfaceRequest, RValue) + public: + InterfaceRequest() {} + + InterfaceRequest(RValue other) { + handle_ = other.object->handle_.Pass(); + } + InterfaceRequest& operator=(RValue other) { + handle_ = other.object->handle_.Pass(); + return *this; + } + + // Returns true if the request has yet to be completed. + bool is_pending() const { return handle_.is_valid(); } + + void Bind(ScopedMessagePipeHandle handle) { + handle_ = handle.Pass(); + } + + ScopedMessagePipeHandle PassMessagePipe() { + return handle_.Pass(); + } + + private: + ScopedMessagePipeHandle handle_; +}; + +template <typename Interface> +InterfaceRequest<Interface> MakeRequest(ScopedMessagePipeHandle handle) { + InterfaceRequest<Interface> request; + request.Bind(handle.Pass()); + return request.Pass(); +} + +// Used to construct a request that synchronously binds an InterfacePtr<..>, +// making it immediately usable upon return. The resulting request object may +// then be later bound to an InterfaceImpl<..> via BindToRequest. +// +// Given the following interface: +// +// interface Foo { +// CreateBar(Bar& bar); +// } +// +// The caller of CreateBar would have code similar to the following: +// +// InterfacePtr<Foo> foo = ...; +// InterfacePtr<Bar> bar; +// foo->CreateBar(Get(&bar)); +// +// Upon return from CreateBar, |bar| is ready to have methods called on it. +// +template <typename Interface> +InterfaceRequest<Interface> Get(InterfacePtr<Interface>* ptr) { + MessagePipe pipe; + ptr->Bind(pipe.handle0.Pass()); + return MakeRequest<Interface>(pipe.handle1.Pass()); +} + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_REQUEST_H_ diff --git a/mojo/public/cpp/bindings/lib/connector.cc b/mojo/public/cpp/bindings/lib/connector.cc index 536cf20..a373e9b 100644 --- a/mojo/public/cpp/bindings/lib/connector.cc +++ b/mojo/public/cpp/bindings/lib/connector.cc @@ -38,7 +38,7 @@ void Connector::CloseMessagePipe() { Close(message_pipe_.Pass()); } -ScopedMessagePipeHandle Connector::ReleaseMessagePipe() { +ScopedMessagePipeHandle Connector::PassMessagePipe() { if (async_wait_id_) { waiter_->CancelWait(waiter_, async_wait_id_); async_wait_id_ = 0; diff --git a/mojo/public/cpp/bindings/lib/connector.h b/mojo/public/cpp/bindings/lib/connector.h index 03d1f9e..c7077b6 100644 --- a/mojo/public/cpp/bindings/lib/connector.h +++ b/mojo/public/cpp/bindings/lib/connector.h @@ -59,7 +59,7 @@ class Connector : public MessageReceiver { // Releases the pipe, not triggering the error state. Connector is put into // a quiescent state. - ScopedMessagePipeHandle ReleaseMessagePipe(); + ScopedMessagePipeHandle PassMessagePipe(); // MessageReceiver implementation: virtual bool Accept(Message* message) MOJO_OVERRIDE; diff --git a/mojo/public/cpp/bindings/lib/router.h b/mojo/public/cpp/bindings/lib/router.h index caab1a6..4a487d7 100644 --- a/mojo/public/cpp/bindings/lib/router.h +++ b/mojo/public/cpp/bindings/lib/router.h @@ -48,8 +48,8 @@ class Router : public MessageReceiverWithResponder { connector_.CloseMessagePipe(); } - ScopedMessagePipeHandle ReleaseMessagePipe() { - return connector_.ReleaseMessagePipe(); + ScopedMessagePipeHandle PassMessagePipe() { + return connector_.PassMessagePipe(); } // MessageReceiver implementation: diff --git a/mojo/public/cpp/bindings/no_interface.h b/mojo/public/cpp/bindings/no_interface.h index 9152300..caeb0fd 100644 --- a/mojo/public/cpp/bindings/no_interface.h +++ b/mojo/public/cpp/bindings/no_interface.h @@ -38,6 +38,7 @@ class NoInterfaceStub : public MessageReceiverWithResponder { public: NoInterfaceStub() {} void set_sink(NoInterface* sink) {} + NoInterface* sink() { return NULL; } virtual bool Accept(Message* message) MOJO_OVERRIDE; virtual bool AcceptWithResponder(Message* message, MessageReceiver* responder) MOJO_OVERRIDE; diff --git a/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc b/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc index 485937d..7f886b6 100644 --- a/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc +++ b/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc @@ -15,6 +15,36 @@ namespace { const char kText1[] = "hello"; const char kText2[] = "world"; +class StringRecorder { + public: + explicit StringRecorder(std::string* buf) : buf_(buf) { + } + void Run(const String& a) const { + *buf_ = a.To<std::string>(); + } + private: + std::string* buf_; +}; + +class SampleObjectImpl : public InterfaceImpl<sample::Object> { + public: + virtual void OnConnectionError() MOJO_OVERRIDE { + delete this; + } + + virtual void SetName(const mojo::String& name) MOJO_OVERRIDE { + name_ = name; + } + + virtual void GetName(const mojo::Callback<void(mojo::String)>& callback) + MOJO_OVERRIDE { + callback.Run(name_); + } + + private: + std::string name_; +}; + class SampleFactoryImpl : public InterfaceImpl<sample::Factory> { public: virtual void OnConnectionError() MOJO_OVERRIDE { @@ -65,6 +95,12 @@ class SampleFactoryImpl : public InterfaceImpl<sample::Factory> { client()->DidStuff2(data); } + virtual void CreateObject(InterfaceRequest<sample::Object> object_request) + MOJO_OVERRIDE { + EXPECT_TRUE(object_request.is_pending()); + BindToRequest(new SampleObjectImpl(), &object_request); + } + private: ScopedMessagePipeHandle pipe1_; }; @@ -259,6 +295,37 @@ TEST_F(HandlePassingTest, IsHandle) { EXPECT_FALSE(internal::IsHandle<String>::value); } +TEST_F(HandlePassingTest, CreateObject) { + sample::FactoryPtr factory; + BindToProxy(new SampleFactoryImpl(), &factory); + + sample::ObjectPtr object1; + EXPECT_FALSE(object1.get()); + + InterfaceRequest<sample::Object> object1_request = Get(&object1); + EXPECT_TRUE(object1_request.is_pending()); + factory->CreateObject(object1_request.Pass()); + EXPECT_FALSE(object1_request.is_pending()); // We've passed the request. + + ASSERT_TRUE(object1.get()); + object1->SetName("object1"); + + sample::ObjectPtr object2; + factory->CreateObject(Get(&object2)); + object2->SetName("object2"); + + std::string name1; + object1->GetName(StringRecorder(&name1)); + + std::string name2; + object2->GetName(StringRecorder(&name2)); + + PumpMessages(); // Yield for results. + + EXPECT_EQ(std::string("object1"), name1); + EXPECT_EQ(std::string("object2"), name2); +} + } // namespace } // namespace test } // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/request_response_unittest.cc b/mojo/public/cpp/bindings/tests/request_response_unittest.cc index c6cf11b..338d968 100644 --- a/mojo/public/cpp/bindings/tests/request_response_unittest.cc +++ b/mojo/public/cpp/bindings/tests/request_response_unittest.cc @@ -50,7 +50,7 @@ class ProviderImpl : public InterfaceImpl<sample::Provider> { class StringRecorder { public: - StringRecorder(std::string* buf) : buf_(buf) { + explicit StringRecorder(std::string* buf) : buf_(buf) { } void Run(const String& a) const { *buf_ = a; @@ -64,7 +64,7 @@ class StringRecorder { class EnumRecorder { public: - EnumRecorder(sample::Enum* value) : value_(value) { + explicit EnumRecorder(sample::Enum* value) : value_(value) { } void Run(sample::Enum a) const { *value_ = a; diff --git a/mojo/public/cpp/bindings/tests/sample_service_unittest.cc b/mojo/public/cpp/bindings/tests/sample_service_unittest.cc index 3d0112d..b2998a5 100644 --- a/mojo/public/cpp/bindings/tests/sample_service_unittest.cc +++ b/mojo/public/cpp/bindings/tests/sample_service_unittest.cc @@ -275,6 +275,10 @@ class ServiceImpl : public Service { Print(depth, "port", port.get()); } } + + virtual void GetPort(mojo::InterfaceRequest<Port> port_request) + MOJO_OVERRIDE { + } }; class ServiceProxyImpl : public ServiceProxy { diff --git a/mojo/public/interfaces/bindings/tests/sample_factory.mojom b/mojo/public/interfaces/bindings/tests/sample_factory.mojom index 42408bd..daaed1e 100644 --- a/mojo/public/interfaces/bindings/tests/sample_factory.mojom +++ b/mojo/public/interfaces/bindings/tests/sample_factory.mojom @@ -19,10 +19,16 @@ struct Response { handle<message_pipe> pipe; }; +interface Object { + SetName(string name); + GetName() => (string name); +}; + [Client=FactoryClient] interface Factory { DoStuff(Request request, handle<message_pipe> pipe); DoStuff2(handle<data_pipe_consumer> pipe); + CreateObject(Object& obj); }; interface FactoryClient { diff --git a/mojo/public/interfaces/bindings/tests/sample_service.mojom b/mojo/public/interfaces/bindings/tests/sample_service.mojom index fabf2b3..f663183 100644 --- a/mojo/public/interfaces/bindings/tests/sample_service.mojom +++ b/mojo/public/interfaces/bindings/tests/sample_service.mojom @@ -94,6 +94,7 @@ interface Service { }; const uint8 kFavoriteBaz = 1; Frobinate@0(Foo foo@0, BazOptions baz@1, Port port@2); + GetPort@1(Port& port @0); }; interface ServiceClient { 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 e0b74f9..762d161 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl @@ -19,6 +19,8 @@ p{{loop.index}} p{{loop.index}}.Pass() {%- elif param.kind|is_interface_kind -%} mojo::MakeProxy<{{param.kind.name}}>(mojo::MakeScopedHandle(mojo::internal::FetchAndReset(¶ms->{{param.name}}))) +{%- elif param.kind|is_interface_request_kind -%} +mojo::MakeRequest<{{param.kind.kind.name}}>(mojo::MakeScopedHandle(mojo::internal::FetchAndReset(¶ms->{{param.name}}))) {%- elif param.kind|is_handle_kind -%} mojo::MakeScopedHandle(mojo::internal::FetchAndReset(¶ms->{{param.name}})) {%- elif param.kind|is_enum_kind -%} @@ -53,9 +55,11 @@ params->{{param.name}} params->{{param.name}} = mojo::MessagePipeHandle(); } else { // Delegate handle. - params->{{param.name}} = - in_{{param.name}}.ResetAndReturnMessagePipe().release(); + params->{{param.name}} = in_{{param.name}}.PassMessagePipe().release(); } +{%- elif param.kind|is_interface_request_kind %} + // Delegate handle. + params->{{param.name}} = in_{{param.name}}.PassMessagePipe().release(); {%- elif param.kind|is_handle_kind %} params->{{param.name}} = in_{{param.name}}.release(); {%- else %} 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 70e1b84..4e21d47 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl @@ -12,6 +12,7 @@ #include "mojo/public/cpp/bindings/callback.h" #include "mojo/public/cpp/bindings/interface_impl.h" #include "mojo/public/cpp/bindings/interface_ptr.h" +#include "mojo/public/cpp/bindings/interface_request.h" #include "mojo/public/cpp/bindings/message_filter.h" #include "mojo/public/cpp/bindings/no_interface.h" #include "mojo/public/cpp/bindings/string.h" diff --git a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py index 6b7492d..ceb14b3 100644 --- a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py +++ b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py @@ -49,7 +49,8 @@ def GetCppType(kind): return "%s_Data*" % GetNameForKind(kind, internal=True) if isinstance(kind, mojom.Array): return "mojo::internal::Array_Data<%s>*" % GetCppType(kind.kind) - if isinstance(kind, mojom.Interface): + if isinstance(kind, mojom.Interface) or \ + isinstance(kind, mojom.InterfaceRequest): return "mojo::MessagePipeHandle" if isinstance(kind, mojom.Enum): return "int32_t" @@ -71,6 +72,8 @@ def GetCppArrayArgWrapperType(kind): return "mojo::Array<%s> " % GetCppArrayArgWrapperType(kind.kind) if isinstance(kind, mojom.Interface): raise Exception("Arrays of interfaces not yet supported!") + if isinstance(kind, mojom.InterfaceRequest): + raise Exception("Arrays of interface requests not yet supported!") if kind.spec == 's': return "mojo::String" if kind.spec == 'h': @@ -94,6 +97,8 @@ def GetCppResultWrapperType(kind): return "mojo::Array<%s>" % GetCppArrayArgWrapperType(kind.kind) if isinstance(kind, mojom.Interface): return "%sPtr" % kind.name + if isinstance(kind, mojom.InterfaceRequest): + return "mojo::InterfaceRequest<%s>" % kind.kind.name if kind.spec == 's': return "mojo::String" if kind.spec == 'h': @@ -117,6 +122,8 @@ def GetCppWrapperType(kind): return "mojo::Array<%s>" % GetCppArrayArgWrapperType(kind.kind) if isinstance(kind, mojom.Interface): return "mojo::ScopedMessagePipeHandle" + if isinstance(kind, mojom.InterfaceRequest): + raise Exception("InterfaceRequest fields not supported!") if kind.spec == 's': return "mojo::String" if kind.spec == 'h': @@ -138,6 +145,8 @@ def GetCppConstWrapperType(kind): return "mojo::Array<%s>" % GetCppArrayArgWrapperType(kind.kind) if isinstance(kind, mojom.Interface): return "%sPtr" % kind.name + if isinstance(kind, mojom.InterfaceRequest): + return "mojo::InterfaceRequest<%s>" % kind.kind.name if isinstance(kind, mojom.Enum): return GetNameForKind(kind) if kind.spec == 's': @@ -162,7 +171,8 @@ def GetCppFieldType(kind): GetNameForKind(kind, internal=True)) if isinstance(kind, mojom.Array): return "mojo::internal::ArrayPointer<%s>" % GetCppType(kind.kind) - if isinstance(kind, mojom.Interface): + if isinstance(kind, mojom.Interface) or \ + isinstance(kind, mojom.InterfaceRequest): return "mojo::MessagePipeHandle" if isinstance(kind, mojom.Enum): return GetNameForKind(kind) @@ -229,6 +239,7 @@ class Generator(generator.Generator): "is_move_only_kind": generator.IsMoveOnlyKind, "is_handle_kind": generator.IsHandleKind, "is_interface_kind": generator.IsInterfaceKind, + "is_interface_request_kind": generator.IsInterfaceRequestKind, "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/generators/mojom_js_generator.py b/mojo/public/tools/bindings/generators/mojom_js_generator.py index 7bb600e..c89218c 100644 --- a/mojo/public/tools/bindings/generators/mojom_js_generator.py +++ b/mojo/public/tools/bindings/generators/mojom_js_generator.py @@ -39,7 +39,8 @@ def JavaScriptDefaultValue(field): return "null" if isinstance(field.kind, mojom.Array): return "[]" - if isinstance(field.kind, mojom.Interface): + if isinstance(field.kind, mojom.Interface) or \ + isinstance(field.kind, mojom.InterfaceRequest): return _kind_to_javascript_default_value[mojom.MSGPIPE] if isinstance(field.kind, mojom.Enum): return "0" @@ -83,7 +84,8 @@ def CodecType(kind): return "new codec.PointerTo(%s)" % CodecType(kind.name) if isinstance(kind, mojom.Array): return "new codec.ArrayOf(%s)" % CodecType(kind.kind) - if isinstance(kind, mojom.Interface): + if isinstance(kind, mojom.Interface) or \ + isinstance(kind, mojom.InterfaceRequest): return CodecType(mojom.MSGPIPE) if isinstance(kind, mojom.Enum): return _kind_to_codec_type[mojom.INT32] @@ -97,7 +99,8 @@ def JavaScriptDecodeSnippet(kind): return "decodeStructPointer(%s)" % CodecType(kind.name) if isinstance(kind, mojom.Array): return "decodeArrayPointer(%s)" % CodecType(kind.kind) - if isinstance(kind, mojom.Interface): + if isinstance(kind, mojom.Interface) or \ + isinstance(kind, mojom.InterfaceRequest): return JavaScriptDecodeSnippet(mojom.MSGPIPE) if isinstance(kind, mojom.Enum): return JavaScriptDecodeSnippet(mojom.INT32) @@ -110,7 +113,8 @@ def JavaScriptEncodeSnippet(kind): return "encodeStructPointer(%s, " % CodecType(kind.name) if isinstance(kind, mojom.Array): return "encodeArrayPointer(%s, " % CodecType(kind.kind) - if isinstance(kind, mojom.Interface): + if isinstance(kind, mojom.Interface) or \ + isinstance(kind, mojom.InterfaceRequest): return JavaScriptEncodeSnippet(mojom.MSGPIPE) if isinstance(kind, mojom.Enum): return JavaScriptEncodeSnippet(mojom.INT32) diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/data.py b/mojo/public/tools/bindings/pylib/mojom/generate/data.py index 862371a..000379f 100644 --- a/mojo/public/tools/bindings/pylib/mojom/generate/data.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/data.py @@ -87,6 +87,9 @@ def KindFromData(kinds, data, scope): if data.startswith('a:'): kind = mojom.Array() kind.kind = KindFromData(kinds, data[2:], scope) + elif data.startswith('r:'): + kind = mojom.InterfaceRequest() + kind.kind = KindFromData(kinds, data[2:], scope) else: kind = mojom.Kind() kind.spec = data @@ -94,8 +97,8 @@ def KindFromData(kinds, data, scope): return kind def KindFromImport(original_kind, imported_from): - """Used with 'import module' - clones the kind imported from the - given module's namespace. Only used with Structs and Enums.""" + """Used with 'import module' - clones the kind imported from the given + module's namespace. Only used with Structs, Interfaces and Enums.""" kind = copy.deepcopy(original_kind) kind.imported_from = imported_from return kind @@ -110,7 +113,7 @@ def ImportFromData(module, data): # Copy the struct kinds from our imports into the current module. for kind in import_module.kinds.itervalues(): - if (isinstance(kind, (mojom.Struct, mojom.Enum)) and + if (isinstance(kind, (mojom.Struct, mojom.Enum, mojom.Interface)) and kind.imported_from is None): kind = KindFromImport(kind, import_item) module.kinds[kind.spec] = kind diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/generator.py b/mojo/public/tools/bindings/pylib/mojom/generate/generator.py index bea69b8..2b70a5e 100644 --- a/mojo/public/tools/bindings/pylib/mojom/generate/generator.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/generator.py @@ -44,11 +44,16 @@ def IsObjectKind(kind): return isinstance(kind, (mojom.Struct, mojom.Array)) or IsStringKind(kind) def IsHandleKind(kind): - return kind.spec.startswith('h') or isinstance(kind, mojom.Interface) + return kind.spec.startswith('h') or \ + isinstance(kind, mojom.Interface) or \ + isinstance(kind, mojom.InterfaceRequest) def IsInterfaceKind(kind): return isinstance(kind, mojom.Interface) +def IsInterfaceRequestKind(kind): + return isinstance(kind, mojom.InterfaceRequest) + def IsMoveOnlyKind(kind): return IsObjectKind(kind) or IsHandleKind(kind) diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/module.py b/mojo/public/tools/bindings/pylib/mojom/generate/module.py index b60986a..345f432 100644 --- a/mojo/public/tools/bindings/pylib/mojom/generate/module.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/module.py @@ -122,6 +122,15 @@ class Array(Kind): Kind.__init__(self) +class InterfaceRequest(Kind): + def __init__(self, kind=None): + self.kind = kind + if kind != None: + Kind.__init__(self, 'r:' + kind.spec) + else: + Kind.__init__(self) + + class Parameter(object): def __init__(self, name=None, kind=None, ordinal=None, default=None): self.name = name @@ -155,6 +164,7 @@ class Interface(Kind): def __init__(self, name=None, client=None, module=None): self.module = module self.name = name + self.imported_from = None if name != None: spec = 'x:' + name else: diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/pack.py b/mojo/public/tools/bindings/pylib/mojom/generate/pack.py index 019fe48..21d2c18 100644 --- a/mojo/public/tools/bindings/pylib/mojom/generate/pack.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/pack.py @@ -36,7 +36,8 @@ class PackedField(object): def GetSizeForKind(cls, kind): if isinstance(kind, mojom.Array) or isinstance(kind, mojom.Struct): return 8 - if isinstance(kind, mojom.Interface): + if isinstance(kind, mojom.Interface) or \ + isinstance(kind, mojom.InterfaceRequest): kind = mojom.MSGPIPE if isinstance(kind, mojom.Enum): # TODO(mpcomplete): what about big enums? diff --git a/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py b/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py index ad13311..3175d12 100644 --- a/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py +++ b/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py @@ -89,6 +89,7 @@ class Lexer(object): # Operators 'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'MOD', 'OR', 'AND', 'NOT', 'XOR', 'LSHIFT', 'RSHIFT', + 'AMP', # Assignment 'EQUALS', @@ -183,6 +184,7 @@ class Lexer(object): t_XOR = r'\^' t_LSHIFT = r'<<' t_RSHIFT = r'>>' + t_AMP = r'&' # = t_EQUALS = r'=' diff --git a/mojo/public/tools/bindings/pylib/mojom/parse/parser.py b/mojo/public/tools/bindings/pylib/mojom/parse/parser.py index 694594a..3898e93 100644 --- a/mojo/public/tools/bindings/pylib/mojom/parse/parser.py +++ b/mojo/public/tools/bindings/pylib/mojom/parse/parser.py @@ -187,7 +187,8 @@ class Parser(object): def p_typename(self, p): """typename : basictypename - | array""" + | array + | interfacerequest""" p[0] = p[1] def p_basictypename(self, p): @@ -216,6 +217,10 @@ class Parser(object): """array : typename LBRACKET RBRACKET""" p[0] = p[1] + "[]" + def p_interfacerequest(self, p): + """interfacerequest : identifier AMP""" + p[0] = p[1] + "&" + def p_ordinal(self, p): """ordinal : ORDINAL | """ diff --git a/mojo/public/tools/bindings/pylib/mojom/parse/translate.py b/mojo/public/tools/bindings/pylib/mojom/parse/translate.py index 8ad952c..8407a088 100644 --- a/mojo/public/tools/bindings/pylib/mojom/parse/translate.py +++ b/mojo/public/tools/bindings/pylib/mojom/parse/translate.py @@ -33,6 +33,8 @@ def _MapKind(kind): 'handle<shared_buffer>': 'h:s'} if kind.endswith('[]'): return 'a:' + _MapKind(kind[0:len(kind)-2]) + if kind.endswith('&'): + return 'r:' + _MapKind(kind[0:len(kind)-1]) if kind in map_to_kind: return map_to_kind[kind] return 'x:' + kind diff --git a/mojo/public/tools/bindings/pylib/mojom_tests/parse/lexer_unittest.py b/mojo/public/tools/bindings/pylib/mojom_tests/parse/lexer_unittest.py index a5fb37c..5aea9f6 100644 --- a/mojo/public/tools/bindings/pylib/mojom_tests/parse/lexer_unittest.py +++ b/mojo/public/tools/bindings/pylib/mojom_tests/parse/lexer_unittest.py @@ -143,6 +143,8 @@ class LexerTest(unittest.TestCase): _MakeLexToken("LSHIFT", "<<")) self.assertEquals(self._SingleTokenForInput(">>"), _MakeLexToken("RSHIFT", ">>")) + self.assertEquals(self._SingleTokenForInput("&"), + _MakeLexToken("AMP", "&")) self.assertEquals(self._SingleTokenForInput("="), _MakeLexToken("EQUALS", "=")) self.assertEquals(self._SingleTokenForInput("=>"), diff --git a/mojo/services/native_viewport/native_viewport.mojom b/mojo/services/native_viewport/native_viewport.mojom index 5535da1..42f1cbd 100644 --- a/mojo/services/native_viewport/native_viewport.mojom +++ b/mojo/services/native_viewport/native_viewport.mojom @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import "../gles2/command_buffer.mojom" import "../public/interfaces/geometry/geometry.mojom" import "../public/interfaces/input_events/input_events.mojom" @@ -14,7 +15,7 @@ interface NativeViewport { Hide(); Close(); SetBounds(Rect bounds); - CreateGLES2Context(handle<message_pipe> gles2_client); + CreateGLES2Context(CommandBuffer& gles2_client); }; interface NativeViewportClient { diff --git a/mojo/services/native_viewport/native_viewport_service.cc b/mojo/services/native_viewport/native_viewport_service.cc index 96d9ec50..336f497 100644 --- a/mojo/services/native_viewport/native_viewport_service.cc +++ b/mojo/services/native_viewport/native_viewport_service.cc @@ -66,16 +66,13 @@ class NativeViewportImpl native_viewport_->SetBounds(bounds.To<gfx::Rect>()); } - virtual void CreateGLES2Context(ScopedMessagePipeHandle client_handle) - OVERRIDE { - if (command_buffer_.get() || command_buffer_handle_.is_valid()) { + virtual void CreateGLES2Context( + InterfaceRequest<CommandBuffer> command_buffer_request) OVERRIDE { + if (command_buffer_.get() || command_buffer_request_.is_pending()) { LOG(ERROR) << "Can't create multiple contexts on a NativeViewport"; return; } - - // TODO(darin): CreateGLES2Context should accept a |CommandBufferPtr*|. - command_buffer_handle_ = client_handle.Pass(); - + command_buffer_request_ = command_buffer_request.Pass(); CreateCommandBufferIfNeeded(); } @@ -84,7 +81,7 @@ class NativeViewportImpl } void CreateCommandBufferIfNeeded() { - if (!command_buffer_handle_.is_valid()) + if (!command_buffer_request_.is_pending()) return; DCHECK(!command_buffer_.get()); if (widget_ == gfx::kNullAcceleratedWidget) @@ -93,8 +90,8 @@ class NativeViewportImpl if (size.IsEmpty()) return; command_buffer_.reset( - BindToPipe(new CommandBufferImpl(widget_, native_viewport_->GetSize()), - command_buffer_handle_.Pass())); + new CommandBufferImpl(widget_, native_viewport_->GetSize())); + BindToRequest(command_buffer_.get(), &command_buffer_request_); } virtual bool OnEvent(ui::Event* ui_event) OVERRIDE { @@ -167,7 +164,7 @@ class NativeViewportImpl shell::Context* context_; gfx::AcceleratedWidget widget_; scoped_ptr<services::NativeViewport> native_viewport_; - ScopedMessagePipeHandle command_buffer_handle_; + InterfaceRequest<CommandBuffer> command_buffer_request_; scoped_ptr<CommandBufferImpl> command_buffer_; bool waiting_for_event_ack_; }; |