diff options
author | rockot <rockot@chromium.org> | 2015-01-27 10:35:01 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-01-27 18:37:01 +0000 |
commit | 775ce0d866ddd61b0474b83d6ed7fb12601b6320 (patch) | |
tree | e71b40cf1ba0fe910b216e5bd414292cab8365ee | |
parent | da4f04df85adfca79a30c283bcc29af4d9a39156 (diff) | |
download | chromium_src-775ce0d866ddd61b0474b83d6ed7fb12601b6320.zip chromium_src-775ce0d866ddd61b0474b83d6ed7fb12601b6320.tar.gz chromium_src-775ce0d866ddd61b0474b83d6ed7fb12601b6320.tar.bz2 |
Update mojo sdk to rev a85a2cea82d816de115e15253742b0f88a9924eb
BUG=None
TBR=aa@chromium.org for html_viewer
TBR=darin@chromium.org
Review URL: https://codereview.chromium.org/866263004
Cr-Commit-Position: refs/heads/master@{#313314}
67 files changed, 784 insertions, 398 deletions
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index faaca99..d417c3c 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc @@ -1545,11 +1545,14 @@ void RenderFrameHostImpl::SetUpMojoIfNeeded() { RegisterMojoServices(); RenderFrameSetupPtr setup; GetProcess()->GetServiceRegistry()->ConnectToRemoteService(&setup); - mojo::ServiceProviderPtr service_provider; - setup->GetServiceProviderForFrame(routing_id_, - mojo::GetProxy(&service_provider)); - service_registry_->BindRemoteServiceProvider( - service_provider.PassMessagePipe()); + + mojo::ServiceProviderPtr exposed_services; + service_registry_->Bind(GetProxy(&exposed_services)); + + mojo::ServiceProviderPtr services; + setup->ExchangeServiceProviders(routing_id_, GetProxy(&services), + exposed_services.Pass()); + service_registry_->BindRemoteServiceProvider(services.Pass()); #if defined(OS_ANDROID) service_registry_android_.reset( diff --git a/content/browser/mojo/mojo_application_host.cc b/content/browser/mojo/mojo_application_host.cc index e5a9b0b..883945f 100644 --- a/content/browser/mojo/mojo_application_host.cc +++ b/content/browser/mojo/mojo_application_host.cc @@ -21,9 +21,34 @@ base::PlatformFile PlatformFileFromScopedPlatformHandle( #endif } +class ApplicationSetupImpl : public ApplicationSetup { + public: + ApplicationSetupImpl(ServiceRegistryImpl* service_registry, + mojo::InterfaceRequest<ApplicationSetup> request) + : binding_(this, request.Pass()), + service_registry_(service_registry) { + } + + ~ApplicationSetupImpl() override { + } + + private: + // ApplicationSetup implementation. + void ExchangeServiceProviders( + mojo::InterfaceRequest<mojo::ServiceProvider> services, + mojo::ServiceProviderPtr exposed_services) override { + service_registry_->Bind(services.Pass()); + service_registry_->BindRemoteServiceProvider(exposed_services.Pass()); + } + + mojo::Binding<ApplicationSetup> binding_; + ServiceRegistryImpl* service_registry_; +}; + } // namespace -MojoApplicationHost::MojoApplicationHost() : did_activate_(false) { +MojoApplicationHost::MojoApplicationHost() + : did_activate_(false) { #if defined(OS_ANDROID) service_registry_android_.reset( new ServiceRegistryAndroid(&service_registry_)); @@ -47,7 +72,9 @@ bool MojoApplicationHost::Init() { // Forward this to the client once we know its process handle. client_handle_ = channel_pair.PassClientHandle(); - service_registry_.BindRemoteServiceProvider(message_pipe.Pass()); + application_setup_.reset(new ApplicationSetupImpl( + &service_registry_, + mojo::MakeRequest<ApplicationSetup>(message_pipe.Pass()))); return true; } diff --git a/content/browser/mojo/mojo_application_host.h b/content/browser/mojo/mojo_application_host.h index 53e150a..fc0693a 100644 --- a/content/browser/mojo/mojo_application_host.h +++ b/content/browser/mojo/mojo_application_host.h @@ -7,6 +7,7 @@ #include "base/memory/scoped_ptr.h" #include "base/process/process_handle.h" +#include "content/common/application_setup.mojom.h" #include "content/common/mojo/service_registry_impl.h" #include "third_party/mojo/src/mojo/edk/embedder/channel_init.h" #include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" @@ -29,7 +30,7 @@ namespace content { class CONTENT_EXPORT MojoApplicationHost { public: MojoApplicationHost(); - virtual ~MojoApplicationHost(); + ~MojoApplicationHost(); // Two-phase initialization: // 1- Init makes service_registry() available synchronously. @@ -53,6 +54,7 @@ class CONTENT_EXPORT MojoApplicationHost { bool did_activate_; + scoped_ptr<ApplicationSetup> application_setup_; ServiceRegistryImpl service_registry_; #if defined(OS_ANDROID) diff --git a/content/child/BUILD.gn b/content/child/BUILD.gn index c8478a9..9a1f71f 100644 --- a/content/child/BUILD.gn +++ b/content/child/BUILD.gn @@ -23,6 +23,7 @@ source_set("child") { deps = [ "//base", "//components/tracing", + "//content/common:mojo_bindings", "//mojo/common", "//mojo/environment:chromium", "//skia", diff --git a/content/child/mojo/mojo_application.cc b/content/child/mojo/mojo_application.cc index bc1426f..34fc314 100644 --- a/content/child/mojo/mojo_application.cc +++ b/content/child/mojo/mojo_application.cc @@ -5,8 +5,10 @@ #include "content/child/mojo/mojo_application.h" #include "content/child/child_process.h" +#include "content/common/application_setup.mojom.h" #include "content/common/mojo/mojo_messages.h" #include "ipc/ipc_message.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_ptr.h" namespace content { @@ -36,7 +38,16 @@ void MojoApplication::OnActivate( channel_init_.Init(handle, ChildProcess::current()->io_message_loop_proxy()); DCHECK(message_pipe.is_valid()); - service_registry_.BindRemoteServiceProvider(message_pipe.Pass()); + + ApplicationSetupPtr application_setup; + application_setup.Bind(message_pipe.Pass()); + + mojo::ServiceProviderPtr services; + mojo::ServiceProviderPtr exposed_services; + service_registry_.Bind(GetProxy(&exposed_services)); + application_setup->ExchangeServiceProviders(GetProxy(&services), + exposed_services.Pass()); + service_registry_.BindRemoteServiceProvider(services.Pass()); } } // namespace content diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index c80a5d5..27aa6d3 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn @@ -406,6 +406,7 @@ source_set("common") { mojom("mojo_bindings") { sources = [ + "application_setup.mojom", "geolocation_service.mojom", "permission_service.mojom", "render_frame_setup.mojom", diff --git a/content/common/application_setup.mojom b/content/common/application_setup.mojom new file mode 100644 index 0000000..4e094a0 --- /dev/null +++ b/content/common/application_setup.mojom @@ -0,0 +1,12 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module content; + +import "third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom"; + +interface ApplicationSetup { + ExchangeServiceProviders(mojo.ServiceProvider& services, + mojo.ServiceProvider exposed_services); +}; diff --git a/content/common/mojo/service_registry_impl.cc b/content/common/mojo/service_registry_impl.cc index 348d1d45..eec7640 100644 --- a/content/common/mojo/service_registry_impl.cc +++ b/content/common/mojo/service_registry_impl.cc @@ -9,12 +9,7 @@ namespace content { ServiceRegistryImpl::ServiceRegistryImpl() - : bound_(false), weak_factory_(this) { -} - -ServiceRegistryImpl::ServiceRegistryImpl(mojo::ScopedMessagePipeHandle handle) - : bound_(false), weak_factory_(this) { - BindRemoteServiceProvider(handle.Pass()); + : binding_(this), weak_factory_(this) { } ServiceRegistryImpl::~ServiceRegistryImpl() { @@ -24,23 +19,23 @@ ServiceRegistryImpl::~ServiceRegistryImpl() { } } +void ServiceRegistryImpl::Bind( + mojo::InterfaceRequest<mojo::ServiceProvider> request) { + binding_.Bind(request.Pass()); +} + void ServiceRegistryImpl::BindRemoteServiceProvider( - mojo::ScopedMessagePipeHandle handle) { - CHECK(!bound_); - bound_ = true; - mojo::WeakBindToPipe(this, handle.Pass()); + mojo::ServiceProviderPtr service_provider) { + CHECK(!remote_provider_); + remote_provider_ = service_provider.Pass(); while (!pending_connects_.empty()) { - client()->ConnectToService( + remote_provider_->ConnectToService( mojo::String::From(pending_connects_.front().first), mojo::ScopedMessagePipeHandle(pending_connects_.front().second)); pending_connects_.pop(); } } -void ServiceRegistryImpl::OnConnectionError() { - // TODO(sammc): Support reporting this to our owner. -} - void ServiceRegistryImpl::AddService( const std::string& service_name, const base::Callback<void(mojo::ScopedMessagePipeHandle)> service_factory) { @@ -54,12 +49,13 @@ void ServiceRegistryImpl::RemoveService(const std::string& service_name) { void ServiceRegistryImpl::ConnectToRemoteService( const base::StringPiece& service_name, mojo::ScopedMessagePipeHandle handle) { - if (!bound_) { + if (!remote_provider_) { pending_connects_.push( std::make_pair(service_name.as_string(), handle.release())); return; } - client()->ConnectToService(mojo::String::From(service_name), handle.Pass()); + remote_provider_->ConnectToService(mojo::String::From(service_name), + handle.Pass()); } base::WeakPtr<ServiceRegistry> ServiceRegistryImpl::GetWeakPtr() { diff --git a/content/common/mojo/service_registry_impl.h b/content/common/mojo/service_registry_impl.h index 16426c7..13aba81 100644 --- a/content/common/mojo/service_registry_impl.h +++ b/content/common/mojo/service_registry_impl.h @@ -14,7 +14,7 @@ #include "base/compiler_specific.h" #include "base/memory/weak_ptr.h" #include "content/public/common/service_registry.h" -#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h" #include "third_party/mojo/src/mojo/public/cpp/system/core.h" #include "third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom.h" @@ -22,17 +22,19 @@ namespace content { class CONTENT_EXPORT ServiceRegistryImpl : public ServiceRegistry, - public NON_EXPORTED_BASE(mojo::InterfaceImpl<mojo::ServiceProvider>) { + public NON_EXPORTED_BASE(mojo::ServiceProvider) { public: ServiceRegistryImpl(); - explicit ServiceRegistryImpl(mojo::ScopedMessagePipeHandle handle); ~ServiceRegistryImpl() override; + // Binds this ServiceProvider implementation to a message pipe endpoint. + void Bind(mojo::InterfaceRequest<mojo::ServiceProvider> request); + // Binds to a remote ServiceProvider. This will expose added services to the // remote ServiceProvider with the corresponding handle and enable // ConnectToRemoteService to provide access to services exposed by the remote // ServiceProvider. - void BindRemoteServiceProvider(mojo::ScopedMessagePipeHandle handle); + void BindRemoteServiceProvider(mojo::ServiceProviderPtr service_provider); // ServiceRegistry overrides. void AddService(const std::string& service_name, @@ -45,16 +47,17 @@ class CONTENT_EXPORT ServiceRegistryImpl base::WeakPtr<ServiceRegistry> GetWeakPtr(); private: - // mojo::InterfaceImpl<mojo::ServiceProvider> overrides. + // mojo::ServiceProvider overrides. void ConnectToService(const mojo::String& name, mojo::ScopedMessagePipeHandle client_handle) override; - void OnConnectionError() override; + + mojo::Binding<mojo::ServiceProvider> binding_; + mojo::ServiceProviderPtr remote_provider_; std::map<std::string, base::Callback<void(mojo::ScopedMessagePipeHandle)> > service_factories_; std::queue<std::pair<std::string, mojo::MessagePipeHandle> > pending_connects_; - bool bound_; base::WeakPtrFactory<ServiceRegistry> weak_factory_; }; diff --git a/content/common/render_frame_setup.mojom b/content/common/render_frame_setup.mojom index 22f01ea..fcf8936 100644 --- a/content/common/render_frame_setup.mojom +++ b/content/common/render_frame_setup.mojom @@ -7,6 +7,7 @@ module content; import "third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom"; interface RenderFrameSetup { - GetServiceProviderForFrame(int32 frame_routing_id, - mojo.ServiceProvider& service_provider); + ExchangeServiceProviders(int32 frame_routing_id, + mojo.ServiceProvider& services, + mojo.ServiceProvider exposed_services); }; diff --git a/content/content_common_mojo_bindings.gyp b/content/content_common_mojo_bindings.gyp index f166301..40895d0 100644 --- a/content/content_common_mojo_bindings.gyp +++ b/content/content_common_mojo_bindings.gyp @@ -11,6 +11,7 @@ 'variables': { 'mojom_files': [ # NOTE: Sources duplicated in //content/common/BUILD.gn:mojo_bindings. + 'common/application_setup.mojom', 'common/geolocation_service.mojom', 'common/permission_service.mojom', 'common/render_frame_setup.mojom', diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index ac991b4..6334f57 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc @@ -1177,8 +1177,10 @@ void RenderFrameImpl::NavigateToSwappedOutURL() { } void RenderFrameImpl::BindServiceRegistry( - mojo::ScopedMessagePipeHandle service_provider_handle) { - service_registry_.BindRemoteServiceProvider(service_provider_handle.Pass()); + mojo::InterfaceRequest<mojo::ServiceProvider> services, + mojo::ServiceProviderPtr exposed_services) { + service_registry_.Bind(services.Pass()); + service_registry_.BindRemoteServiceProvider(exposed_services.Pass()); } ManifestManager* RenderFrameImpl::manifest_manager() { diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 6fd6820..ffe14f5 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h @@ -534,10 +534,10 @@ class CONTENT_EXPORT RenderFrameImpl // TODO(nasko): Remove this method once swapped out state is no longer used. void NavigateToSwappedOutURL(); - // Binds this render frame's service registry to a handle to the remote - // service registry. + // Binds this render frame's service registry. void BindServiceRegistry( - mojo::ScopedMessagePipeHandle service_provider_handle); + mojo::InterfaceRequest<mojo::ServiceProvider> services, + mojo::ServiceProviderPtr exposed_services); ManifestManager* manifest_manager(); diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index ef6dae7..07598f1 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -313,9 +313,11 @@ class RenderFrameSetupImpl : public mojo::InterfaceImpl<RenderFrameSetup> { : routing_id_highmark_(-1) { } - void GetServiceProviderForFrame( + void ExchangeServiceProviders( int32_t frame_routing_id, - mojo::InterfaceRequest<mojo::ServiceProvider> request) override { + mojo::InterfaceRequest<mojo::ServiceProvider> services, + mojo::ServiceProviderPtr exposed_services) + override { // TODO(morrita): This is for investigating http://crbug.com/415059 and // should be removed once it is fixed. CHECK_LT(routing_id_highmark_, frame_routing_id); @@ -327,11 +329,11 @@ class RenderFrameSetupImpl : public mojo::InterfaceImpl<RenderFrameSetup> { // triggers creation of the RenderFrame we want. if (!frame) { RenderThreadImpl::current()->RegisterPendingRenderFrameConnect( - frame_routing_id, request.PassMessagePipe()); + frame_routing_id, services.Pass(), exposed_services.Pass()); return; } - frame->BindServiceRegistry(request.PassMessagePipe()); + frame->BindServiceRegistry(services.Pass(), exposed_services.Pass()); } private: @@ -656,12 +658,6 @@ void RenderThreadImpl::Init() { } RenderThreadImpl::~RenderThreadImpl() { - for (std::map<int, mojo::MessagePipeHandle>::iterator it = - pending_render_frame_connects_.begin(); - it != pending_render_frame_connects_.end(); - ++it) { - mojo::CloseRaw(it->second); - } } void RenderThreadImpl::Shutdown() { @@ -859,7 +855,7 @@ scoped_refptr<base::MessageLoopProxy> void RenderThreadImpl::AddRoute(int32 routing_id, IPC::Listener* listener) { ChildThread::GetRouter()->AddRoute(routing_id, listener); - std::map<int, mojo::MessagePipeHandle>::iterator it = + PendingRenderFrameConnectMap::iterator it = pending_render_frame_connects_.find(routing_id); if (it == pending_render_frame_connects_.end()) return; @@ -868,9 +864,14 @@ void RenderThreadImpl::AddRoute(int32 routing_id, IPC::Listener* listener) { if (!frame) return; - mojo::ScopedMessagePipeHandle handle(it->second); + scoped_refptr<PendingRenderFrameConnect> connection(it->second); + mojo::InterfaceRequest<mojo::ServiceProvider> services( + connection->services.Pass()); + mojo::ServiceProviderPtr exposed_services( + connection->exposed_services.Pass()); pending_render_frame_connects_.erase(it); - frame->BindServiceRegistry(handle.Pass()); + + frame->BindServiceRegistry(services.Pass(), exposed_services.Pass()); } void RenderThreadImpl::RemoveRoute(int32 routing_id) { @@ -896,10 +897,14 @@ void RenderThreadImpl::RemoveEmbeddedWorkerRoute(int32 routing_id) { void RenderThreadImpl::RegisterPendingRenderFrameConnect( int routing_id, - mojo::ScopedMessagePipeHandle handle) { - std::pair<std::map<int, mojo::MessagePipeHandle>::iterator, bool> result = - pending_render_frame_connects_.insert( - std::make_pair(routing_id, handle.release())); + mojo::InterfaceRequest<mojo::ServiceProvider> services, + mojo::ServiceProviderPtr exposed_services) { + std::pair<PendingRenderFrameConnectMap::iterator, bool> result = + pending_render_frame_connects_.insert(std::make_pair( + routing_id, + make_scoped_refptr(new PendingRenderFrameConnect( + services.Pass(), + exposed_services.Pass())))); CHECK(result.second) << "Inserting a duplicate item."; } @@ -1781,4 +1786,14 @@ void RenderThreadImpl::WidgetRestored() { ScheduleIdleHandler(kLongIdleHandlerDelayMs); } +RenderThreadImpl::PendingRenderFrameConnect::PendingRenderFrameConnect( + mojo::InterfaceRequest<mojo::ServiceProvider> services, + mojo::ServiceProviderPtr exposed_services) + : services(services.Pass()), + exposed_services(exposed_services.Pass()) { +} + +RenderThreadImpl::PendingRenderFrameConnect::~PendingRenderFrameConnect() { +} + } // namespace content diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index e6f4b88..483d5a3 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h @@ -11,6 +11,7 @@ #include "base/cancelable_callback.h" #include "base/memory/memory_pressure_listener.h" +#include "base/memory/ref_counted.h" #include "base/metrics/user_metrics_action.h" #include "base/observer_list.h" #include "base/strings/string16.h" @@ -404,8 +405,10 @@ class CONTENT_EXPORT RenderThreadImpl void AddEmbeddedWorkerRoute(int32 routing_id, IPC::Listener* listener); void RemoveEmbeddedWorkerRoute(int32 routing_id); - void RegisterPendingRenderFrameConnect(int routing_id, - mojo::ScopedMessagePipeHandle handle); + void RegisterPendingRenderFrameConnect( + int routing_id, + mojo::InterfaceRequest<mojo::ServiceProvider> services, + mojo::ServiceProviderPtr exposed_services); protected: virtual void SetResourceDispatchTaskQueue( @@ -597,7 +600,24 @@ class CONTENT_EXPORT RenderThreadImpl bool is_elastic_overscroll_enabled_; unsigned use_image_texture_target_; - std::map<int, mojo::MessagePipeHandle> pending_render_frame_connects_; + struct PendingRenderFrameConnect + : public base::RefCounted<PendingRenderFrameConnect> { + PendingRenderFrameConnect( + mojo::InterfaceRequest<mojo::ServiceProvider> services, + mojo::ServiceProviderPtr exposed_services); + + mojo::InterfaceRequest<mojo::ServiceProvider> services; + mojo::ServiceProviderPtr exposed_services; + + private: + friend class base::RefCounted<PendingRenderFrameConnect>; + + ~PendingRenderFrameConnect(); + }; + + typedef std::map<int, scoped_refptr<PendingRenderFrameConnect>> + PendingRenderFrameConnectMap; + PendingRenderFrameConnectMap pending_render_frame_connects_; DISALLOW_COPY_AND_ASSIGN(RenderThreadImpl); }; diff --git a/content/shell/browser/shell_mojo_test_utils_android.cc b/content/shell/browser/shell_mojo_test_utils_android.cc index eeae444..966aa5b 100644 --- a/content/shell/browser/shell_mojo_test_utils_android.cc +++ b/content/shell/browser/shell_mojo_test_utils_android.cc @@ -44,11 +44,13 @@ static jobject CreateServiceRegistryPair(JNIEnv* env, content::ServiceRegistryImpl* registry_b = new ServiceRegistryImpl(); test_environment->registries.push_back(registry_b); - mojo::ScopedMessagePipeHandle handle_a; - mojo::ScopedMessagePipeHandle handle_b; - mojo::CreateMessagePipe(NULL, &handle_a, &handle_b); - registry_a->BindRemoteServiceProvider(handle_a.Pass()); - registry_b->BindRemoteServiceProvider(handle_b.Pass()); + mojo::ServiceProviderPtr exposed_services_a; + registry_a->Bind(GetProxy(&exposed_services_a)); + registry_b->BindRemoteServiceProvider(exposed_services_a.Pass()); + + mojo::ServiceProviderPtr exposed_services_b; + registry_b->Bind(GetProxy(&exposed_services_b)); + registry_a->BindRemoteServiceProvider(exposed_services_b.Pass()); content::ServiceRegistryAndroid* wrapper_a = new ServiceRegistryAndroid(registry_a); diff --git a/mojo/services/html_viewer/html_document.cc b/mojo/services/html_viewer/html_document.cc index eca0d00..3b13a45 100644 --- a/mojo/services/html_viewer/html_document.cc +++ b/mojo/services/html_viewer/html_document.cc @@ -111,7 +111,7 @@ HTMLDocument::HTMLDocument( web_media_player_factory_(web_media_player_factory) { exported_services_.AddService(this); exported_services_.AddService(&view_manager_client_factory_); - WeakBindToPipe(&exported_services_, services.PassMessagePipe()); + exported_services_.Bind(services.Pass()); Load(response_.Pass()); } @@ -126,10 +126,10 @@ HTMLDocument::~HTMLDocument() { void HTMLDocument::OnEmbed( View* root, - mojo::ServiceProviderImpl* embedee_service_provider_impl, - scoped_ptr<mojo::ServiceProvider> embedder_service_provider) { + mojo::InterfaceRequest<mojo::ServiceProvider> services, + mojo::ServiceProviderPtr exposed_services) { root_ = root; - embedder_service_provider_ = embedder_service_provider.Pass(); + embedder_service_provider_ = exposed_services.Pass(); navigator_host_.set_service_provider(embedder_service_provider_.get()); blink::WebSize root_size(root_->bounds().width, root_->bounds().height); diff --git a/mojo/services/html_viewer/html_document.h b/mojo/services/html_viewer/html_document.h index 40515b6..3d1be63 100644 --- a/mojo/services/html_viewer/html_document.h +++ b/mojo/services/html_viewer/html_document.h @@ -110,10 +110,9 @@ class HTMLDocument : public blink::WebViewClient, virtual blink::WebEncryptedMediaClient* encryptedMediaClient(); // ViewManagerDelegate methods: - void OnEmbed( - mojo::View* root, - mojo::ServiceProviderImpl* embedee_service_provider_impl, - scoped_ptr<mojo::ServiceProvider> embedder_service_provider) override; + void OnEmbed(mojo::View* root, + mojo::InterfaceRequest<mojo::ServiceProvider> services, + mojo::ServiceProviderPtr exposed_services) override; void OnViewManagerDisconnected(mojo::ViewManager* view_manager) override; // ViewObserver methods: @@ -131,7 +130,7 @@ class HTMLDocument : public blink::WebViewClient, mojo::URLResponsePtr response_; mojo::ServiceProviderImpl exported_services_; - scoped_ptr<mojo::ServiceProvider> embedder_service_provider_; + mojo::ServiceProviderPtr embedder_service_provider_; mojo::Shell* shell_; mojo::LazyInterfacePtr<mojo::NavigatorHost> navigator_host_; blink::WebView* web_view_; diff --git a/mojo/services/html_viewer/html_viewer.cc b/mojo/services/html_viewer/html_viewer.cc index 55d4c39..06df351 100644 --- a/mojo/services/html_viewer/html_viewer.cc +++ b/mojo/services/html_viewer/html_viewer.cc @@ -102,6 +102,8 @@ class HTMLViewerApplication : public mojo::Application { } } + void RequestQuit() override {} + private: void OnResponseReceived(URLLoaderPtr loader, InterfaceRequest<ServiceProvider> services, diff --git a/mojo/services/public/js/application.js b/mojo/services/public/js/application.js index a50f84c..ed41628 100644 --- a/mojo/services/public/js/application.js +++ b/mojo/services/public/js/application.js @@ -3,11 +3,13 @@ // found in the LICENSE file. define("mojo/services/public/js/application", [ + "mojo/public/js/bindings", + "mojo/public/js/threading", "mojo/services/public/js/service_provider", "mojo/services/public/js/shell", - "mojo/public/js/threading", -], function(serviceProvider, shell, threading) { +], function(bindings, threading, serviceProvider, shell) { + const ProxyBindings = bindings.ProxyBindings; const ServiceProvider = serviceProvider.ServiceProvider; const Shell = shell.Shell; @@ -26,18 +28,27 @@ define("mojo/services/public/js/application", [ initialize(args) { } - doAcceptConnection(url, serviceProviderProxy, exposedServiceProviderProxy) { - var serviceProvider = new ServiceProvider(serviceProviderProxy); + // The mojom signature of this function is: + // AcceptConnection(string requestor_url, + // ServiceProvider&? services, + // ServiceProvider? exposed_services); + // + // We want to bind |services| to our js implementation of ServiceProvider + // and store |exposed_services| so we can request services of the connecting + // application. + doAcceptConnection(requestorUrl, servicesRequest, exposedServicesProxy) { + // Construct a new js ServiceProvider that can make outgoing calls on + // exposedServicesProxy. + var serviceProvider = new ServiceProvider(exposedServicesProxy); this.serviceProviders.push(serviceProvider); - var exposedServiceProvider = - new ServiceProvider(exposedServiceProviderProxy); - this.exposedServiceProviders.push(exposedServiceProvider); + // Then associate incoming calls with the serviceProvider. + ProxyBindings(servicesRequest).setLocalDelegate(serviceProvider); - this.acceptConnection(url, serviceProvider, exposedServiceProvider); + this.acceptConnection(requestorUrl, serviceProvider); } - acceptConnection(url, serviceProvider, exposedServiceProvider) { + acceptConnection(requestorUrl, serviceProvider) { } quit() { diff --git a/mojo/services/public/js/service_provider.js b/mojo/services/public/js/service_provider.js index 1f8fab2c..9566583 100644 --- a/mojo/services/public/js/service_provider.js +++ b/mojo/services/public/js/service_provider.js @@ -19,10 +19,7 @@ define("mojo/services/public/js/service_provider", [ class ServiceProvider { constructor(service) { - if (!(service instanceof ServiceProviderInterface.proxyClass)) - throw new Error("service must be a ServiceProvider proxy"); this.proxy = service; - ProxyBindings(this.proxy).setLocalDelegate(this); this.providers_ = new Map(); // serviceName => see provideService() below this.pendingRequests_ = new Map(); // serviceName => serviceHandle } diff --git a/mojo/services/public/js/shell.js b/mojo/services/public/js/shell.js index 8d90dcb..9fc8552 100644 --- a/mojo/services/public/js/shell.js +++ b/mojo/services/public/js/shell.js @@ -33,8 +33,10 @@ define("mojo/services/public/js/shell", [ if (application) return application; - this.proxy.connectToApplication(url, function(sp) { - application = new ServiceProvider(sp); + this.proxy.connectToApplication(url, function(services) { + application = new ServiceProvider(services); + }, function() { + return application; }); this.applications_.set(url, application); return application; diff --git a/mojo/services/view_manager/public/cpp/lib/view.cc b/mojo/services/view_manager/public/cpp/lib/view.cc index 5f7d22a..929eec4 100644 --- a/mojo/services/view_manager/public/cpp/lib/view.cc +++ b/mojo/services/view_manager/public/cpp/lib/view.cc @@ -359,19 +359,11 @@ void View::Embed(const String& url) { static_cast<ViewManagerClientImpl*>(manager_)->Embed(url, id_); } -scoped_ptr<ServiceProvider> - View::Embed(const String& url, - scoped_ptr<ServiceProviderImpl> exported_services) { - scoped_ptr<ServiceProvider> imported_services; - // BindToProxy() takes ownership of |exported_services|. - ServiceProviderImpl* registry = exported_services.release(); - ServiceProviderPtr sp; - if (registry) { - BindToProxy(registry, &sp); - imported_services.reset(registry->CreateRemoteServiceProvider()); - } - static_cast<ViewManagerClientImpl*>(manager_)->Embed(url, id_, sp.Pass()); - return imported_services.Pass(); +void View::Embed(const String& url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services) { + static_cast<ViewManagerClientImpl*>(manager_) + ->Embed(url, id_, services.Pass(), exposed_services.Pass()); } //////////////////////////////////////////////////////////////////////////////// diff --git a/mojo/services/view_manager/public/cpp/lib/view_manager_client_impl.cc b/mojo/services/view_manager/public/cpp/lib/view_manager_client_impl.cc index ef043e0..78daeb3 100644 --- a/mojo/services/view_manager/public/cpp/lib/view_manager_client_impl.cc +++ b/mojo/services/view_manager/public/cpp/lib/view_manager_client_impl.cc @@ -195,19 +195,16 @@ void ViewManagerClientImpl::SetProperty( } void ViewManagerClientImpl::Embed(const String& url, Id view_id) { - ServiceProviderPtr sp; - BindToProxy(new ServiceProviderImpl, &sp); - Embed(url, view_id, sp.Pass()); + Embed(url, view_id, nullptr, nullptr); } -void ViewManagerClientImpl::Embed( - const String& url, - Id view_id, - ServiceProviderPtr service_provider) { +void ViewManagerClientImpl::Embed(const String& url, + Id view_id, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services) { DCHECK(connected_); - service_->Embed(url, view_id, - MakeRequest<ServiceProvider>(service_provider.PassMessagePipe()), - ActionCompletedCallback()); + service_->Embed(url, view_id, services.Pass(), exposed_services.Pass(), + ActionCompletedCallback()); } void ViewManagerClientImpl::AddView(View* view) { @@ -261,7 +258,8 @@ void ViewManagerClientImpl::OnEmbed( ConnectionSpecificId connection_id, const String& creator_url, ViewDataPtr root_data, - InterfaceRequest<ServiceProvider> parent_services, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services, ScopedMessagePipeHandle window_manager_pipe) { DCHECK(!connected_); connected_ = true; @@ -272,14 +270,6 @@ void ViewManagerClientImpl::OnEmbed( root_ = AddViewToViewManager(this, nullptr, root_data); root_->AddObserver(new RootObserver(root_)); - ServiceProviderImpl* exported_services = nullptr; - scoped_ptr<ServiceProvider> remote; - - // BindToRequest() binds the lifetime of |exported_services| to the pipe. - exported_services = new ServiceProviderImpl; - BindToRequest(exported_services, &parent_services); - remote.reset(exported_services->CreateRemoteServiceProvider()); - window_manager_.Bind(window_manager_pipe.Pass()); window_manager_.set_client(this); // base::Unretained() is safe here as |window_manager_| is bound to our @@ -287,7 +277,8 @@ void ViewManagerClientImpl::OnEmbed( window_manager_->GetFocusedAndActiveViews( base::Bind(&ViewManagerClientImpl::OnGotFocusedAndActiveViews, base::Unretained(this))); - delegate_->OnEmbed(root_, exported_services, remote.Pass()); + + delegate_->OnEmbed(root_, services.Pass(), exposed_services.Pass()); } void ViewManagerClientImpl::OnEmbeddedAppDisconnected(Id view_id) { diff --git a/mojo/services/view_manager/public/cpp/lib/view_manager_client_impl.h b/mojo/services/view_manager/public/cpp/lib/view_manager_client_impl.h index cbc0086..c8ae5c4 100644 --- a/mojo/services/view_manager/public/cpp/lib/view_manager_client_impl.h +++ b/mojo/services/view_manager/public/cpp/lib/view_manager_client_impl.h @@ -63,7 +63,8 @@ class ViewManagerClientImpl : public ViewManager, void Embed(const String& url, Id view_id); void Embed(const String& url, Id view_id, - ServiceProviderPtr service_provider); + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services); void set_change_acked_callback(const base::Callback<void(void)>& callback) { change_acked_callback_ = callback; @@ -95,7 +96,8 @@ class ViewManagerClientImpl : public ViewManager, void OnEmbed(ConnectionSpecificId connection_id, const String& creator_url, ViewDataPtr root, - InterfaceRequest<ServiceProvider> parent_services, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services, ScopedMessagePipeHandle window_manager_pipe) override; void OnEmbeddedAppDisconnected(Id view_id) override; void OnViewBoundsChanged(Id view_id, diff --git a/mojo/services/view_manager/public/cpp/lib/view_manager_context.cc b/mojo/services/view_manager/public/cpp/lib/view_manager_context.cc index 45752f5..a47f59a 100644 --- a/mojo/services/view_manager/public/cpp/lib/view_manager_context.cc +++ b/mojo/services/view_manager/public/cpp/lib/view_manager_context.cc @@ -31,23 +31,13 @@ ViewManagerContext::ViewManagerContext(ApplicationImpl* application_impl) ViewManagerContext::~ViewManagerContext() {} void ViewManagerContext::Embed(const String& url) { - scoped_ptr<ServiceProviderImpl> spi(new ServiceProviderImpl); - Embed(url, spi.Pass()); + Embed(url, nullptr, nullptr); } -scoped_ptr<ServiceProvider> ViewManagerContext::Embed( - const String& url, - scoped_ptr<ServiceProviderImpl> exported_services) { - scoped_ptr<ServiceProvider> imported_services; - // BindToProxy() takes ownership of |exported_services|. - ServiceProviderImpl* registry = exported_services.release(); - ServiceProviderPtr sp; - if (registry) { - BindToProxy(registry, &sp); - imported_services.reset(registry->CreateRemoteServiceProvider()); - } - state_->wm()->Embed(url, MakeRequest<ServiceProvider>(sp.PassMessagePipe())); - return imported_services.Pass(); +void ViewManagerContext::Embed(const String& url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services) { + state_->wm()->Embed(url, services.Pass(), exposed_services.Pass()); } } // namespace mojo diff --git a/mojo/services/view_manager/public/cpp/tests/view_manager_unittest.cc b/mojo/services/view_manager/public/cpp/tests/view_manager_unittest.cc index bbfc742..d9e4db8 100644 --- a/mojo/services/view_manager/public/cpp/tests/view_manager_unittest.cc +++ b/mojo/services/view_manager/public/cpp/tests/view_manager_unittest.cc @@ -81,8 +81,8 @@ class ConnectApplicationLoader : public ApplicationLoader, // Overridden from ViewManagerDelegate: void OnEmbed(View* root, - ServiceProviderImpl* exported_services, - scoped_ptr<ServiceProvider> imported_services) override { + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services) override { callback_.Run(root); } void OnViewManagerDisconnected(ViewManager* view_manager) override {} diff --git a/mojo/services/view_manager/public/cpp/view.h b/mojo/services/view_manager/public/cpp/view.h index 9917fca..1215a3b 100644 --- a/mojo/services/view_manager/public/cpp/view.h +++ b/mojo/services/view_manager/public/cpp/view.h @@ -124,9 +124,9 @@ class View { // Embedding. void Embed(const String& url); - scoped_ptr<ServiceProvider> Embed( - const String& url, - scoped_ptr<ServiceProviderImpl> exported_services); + void Embed(const String& url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services); protected: // This class is subclassed only by test classes that provide a public ctor. diff --git a/mojo/services/view_manager/public/cpp/view_manager_context.h b/mojo/services/view_manager/public/cpp/view_manager_context.h index ed8f23e..1976598 100644 --- a/mojo/services/view_manager/public/cpp/view_manager_context.h +++ b/mojo/services/view_manager/public/cpp/view_manager_context.h @@ -26,14 +26,14 @@ class ViewManagerContext { // Subsequent times, the implementation of this method is delegated to the // application embedded at the service root View. This application will have a // specific definition of where within its View hierarchy to embed an - // un-parented URL. |exported_services| encapsulates services offered by the - // application calling Embed() to the application being embedded. Returns - // an object implementing ServiceProvider encapsulating services offered by - // the embedded application to the embedder. + // un-parented URL. + // |services| encapsulates services offered by the embedder to the embedded + // app alongside this Embed() call. |exposed_services| provides a means for + // the embedder to connect to services exposed by the embedded app. void Embed(const String& url); - scoped_ptr<ServiceProvider> Embed( - const String& url, - scoped_ptr<ServiceProviderImpl> exported_services); + void Embed(const String& url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_Services); private: class InternalState; diff --git a/mojo/services/view_manager/public/cpp/view_manager_delegate.h b/mojo/services/view_manager/public/cpp/view_manager_delegate.h index 1160861..e78e925 100644 --- a/mojo/services/view_manager/public/cpp/view_manager_delegate.h +++ b/mojo/services/view_manager/public/cpp/view_manager_delegate.h @@ -5,12 +5,10 @@ #ifndef MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_DELEGATE_H_ #define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_DELEGATE_H_ -#include "base/memory/scoped_ptr.h" #include "mojo/public/interfaces/application/service_provider.mojom.h" namespace mojo { -class ServiceProviderImpl; class View; class ViewManager; @@ -22,15 +20,18 @@ class ViewManagerDelegate { // created. |root| and it's corresponding ViewManager are valid until // OnViewManagerDisconnected() is called with the same object. // - // |exported_services| is an object that the delegate can add services to - // expose to the embedder. |imported_services| exposes the services offered by - // the embedder to the delegate. Note that if a different application is - // subsequently embedded at |root|, the pipe(s) connecting |imported_services| - // to the embedder and any services obtained from it are not broken and will - // continue to be valid. + // |services| exposes the services offered by the embedder to the delegate. + // + // |exposed_services| is an object that the delegate can add services to + // expose to the embedder. + // + // Note that if a different application is subsequently embedded at |root|, + // the pipes connecting |services| and |exposed_services| to the embedder and + // any services obtained from them are not broken and will continue to be + // valid. virtual void OnEmbed(View* root, - ServiceProviderImpl* exported_services, - scoped_ptr<ServiceProvider> imported_services) = 0; + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services) = 0; // Called when a connection to the view manager service is closed. // |view_manager| is not valid after this function returns. diff --git a/mojo/services/view_manager/public/interfaces/view_manager.mojom b/mojo/services/view_manager/public/interfaces/view_manager.mojom index 0f5c51d..55552f8 100644 --- a/mojo/services/view_manager/public/interfaces/view_manager.mojom +++ b/mojo/services/view_manager/public/interfaces/view_manager.mojom @@ -124,15 +124,16 @@ interface ViewManagerService { // children the children are removed. The one exception is the root // connection. // - // |service_provider| encapsulates services offered by the embedder to the - // embedded app alongside this Embed() call. It also provides a means for - // the embedder to connect to services symmetrically exposed by the embedded - // app. Note that if a different app is subsequently embedded at |view_id| - // the |service_provider|'s connection to its client in the embedded app and - // any services it provided are not broken and continue to be valid. + // |services| encapsulates services offered by the embedder to the embedded + // app alongside this Embed() call. |exposed_services| provides a means for + // the embedder to connect to services exposed by the embedded app. Note that + // if a different app is subsequently embedded at |view_id| the + // ServiceProvider connections to its client in the embedded app and any + // services it provided are not broken and continue to be valid. Embed(string url, uint32 view_id, - ServiceProvider& service_provider) => (bool success); + ServiceProvider&? services, + ServiceProvider? exposed_services) => (bool success); }; // Changes to views are not sent to the connection that originated the @@ -146,7 +147,8 @@ interface ViewManagerClient { OnEmbed(uint16 connection_id, string embedder_url, ViewData root, - ServiceProvider& parent_service_provider, + ServiceProvider&? services, + ServiceProvider? exposed_services, handle<message_pipe> window_manager_pipe); // Invoked when the application embedded at |view| is disconnected. diff --git a/mojo/services/window_manager/public/interfaces/window_manager.mojom b/mojo/services/window_manager/public/interfaces/window_manager.mojom index a2ef594..e365fb6 100644 --- a/mojo/services/window_manager/public/interfaces/window_manager.mojom +++ b/mojo/services/window_manager/public/interfaces/window_manager.mojom @@ -10,8 +10,9 @@ import "mojo/public/interfaces/application/service_provider.mojom"; [Client=WindowManagerClient] interface WindowManager { // Requests the WindowManager to embed the app for |url| at an appropriate - // View. See ViewMangerService::Embed() for details on |service_provider|. - Embed(string url, ServiceProvider& service_provider); + // View. See ViewMangerService::Embed() for details on |services| and + // |exposed_services|. + Embed(string url, ServiceProvider&? services, ServiceProvider? exposed_services); SetCapture(uint32 view_id) => (bool success); FocusWindow(uint32 view_id) => (bool success); diff --git a/third_party/mojo/mojo_public.gyp b/third_party/mojo/mojo_public.gyp index 3114ac9..0ab9e87 100644 --- a/third_party/mojo/mojo_public.gyp +++ b/third_party/mojo/mojo_public.gyp @@ -237,8 +237,6 @@ 'src/mojo/public/cpp/application/lib/service_connector.h', 'src/mojo/public/cpp/application/lib/service_registry.cc', 'src/mojo/public/cpp/application/lib/service_registry.h', - 'src/mojo/public/cpp/application/lib/weak_service_provider.cc', - 'src/mojo/public/cpp/application/lib/weak_service_provider.h', 'src/mojo/public/cpp/application/service_provider_impl.h', ], 'dependencies': [ diff --git a/third_party/mojo/src/mojo/edk/system/BUILD.gn b/third_party/mojo/src/mojo/edk/system/BUILD.gn index eab85a2..67310c8 100644 --- a/third_party/mojo/src/mojo/edk/system/BUILD.gn +++ b/third_party/mojo/src/mojo/edk/system/BUILD.gn @@ -2,8 +2,13 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//testing/test.gni") import("../mojo_edk.gni") +import("//testing/test.gni") + +if (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") +} config("system_config") { defines = [ diff --git a/third_party/mojo/src/mojo/edk/system/raw_channel.cc b/third_party/mojo/src/mojo/edk/system/raw_channel.cc index aff1110..383a743 100644 --- a/third_party/mojo/src/mojo/edk/system/raw_channel.cc +++ b/third_party/mojo/src/mojo/edk/system/raw_channel.cc @@ -156,7 +156,7 @@ void RawChannel::WriteBuffer::GetBuffers(std::vector<Buffer>* buffers) const { RawChannel::RawChannel() : message_loop_for_io_(nullptr), delegate_(nullptr), - read_stopped_(false), + set_on_shutdown_(nullptr), write_stopped_(false), weak_ptr_factory_(this) { } @@ -212,7 +212,10 @@ void RawChannel::Shutdown() { // Reset the delegate so that it won't receive further calls. delegate_ = nullptr; - read_stopped_ = true; + if (set_on_shutdown_) { + *set_on_shutdown_ = true; + set_on_shutdown_ = nullptr; + } write_stopped_ = true; weak_ptr_factory_.InvalidateWeakPtrs(); @@ -264,11 +267,6 @@ bool RawChannel::IsWriteBufferEmpty() { void RawChannel::OnReadCompleted(IOResult io_result, size_t bytes_read) { DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io_); - if (read_stopped_) { - NOTREACHED(); - return; - } - // Keep reading data in a loop, and dispatch messages if enough data is // received. Exit the loop if any of the following happens: // - one or more messages were dispatched; @@ -281,9 +279,8 @@ void RawChannel::OnReadCompleted(IOResult io_result, size_t bytes_read) { case IO_FAILED_SHUTDOWN: case IO_FAILED_BROKEN: case IO_FAILED_UNKNOWN: - read_stopped_ = true; CallOnError(ReadIOResultToError(io_result)); - return; + return; // |this| may have been destroyed in |CallOnError()|. case IO_PENDING: NOTREACHED(); return; @@ -318,16 +315,14 @@ void RawChannel::OnReadCompleted(IOResult io_result, size_t bytes_read) { &error_message)) { DCHECK(error_message); LOG(ERROR) << "Received invalid message: " << error_message; - read_stopped_ = true; CallOnError(Delegate::ERROR_READ_BAD_MESSAGE); - return; + return; // |this| may have been destroyed in |CallOnError()|. } if (message_view.type() == MessageInTransit::kTypeRawChannel) { if (!OnReadMessageForRawChannel(message_view)) { - read_stopped_ = true; CallOnError(Delegate::ERROR_READ_BAD_MESSAGE); - return; + return; // |this| may have been destroyed in |CallOnError()|. } } else { embedder::ScopedPlatformHandleVectorPtr platform_handles; @@ -344,9 +339,8 @@ void RawChannel::OnReadCompleted(IOResult io_result, size_t bytes_read) { platform_handle_table).Pass(); if (!platform_handles) { LOG(ERROR) << "Invalid number of platform handles received"; - read_stopped_ = true; CallOnError(Delegate::ERROR_READ_BAD_MESSAGE); - return; + return; // |this| may have been destroyed in |CallOnError()|. } } } @@ -355,13 +349,16 @@ void RawChannel::OnReadCompleted(IOResult io_result, size_t bytes_read) { // for the POSIX implementation, we should confirm that none are stored. // Dispatch the message. + // Detect the case when |Shutdown()| is called; subsequent destruction + // is also permitted then. + bool shutdown_called = false; + DCHECK(!set_on_shutdown_); + set_on_shutdown_ = &shutdown_called; DCHECK(delegate_); delegate_->OnReadMessage(message_view, platform_handles.Pass()); - if (read_stopped_) { - // |Shutdown()| was called in |OnReadMessage()|. - // TODO(vtl): Add test for this case. + if (shutdown_called) return; - } + set_on_shutdown_ = nullptr; } did_dispatch_message = true; @@ -429,8 +426,10 @@ void RawChannel::OnWriteCompleted(IOResult io_result, bytes_written); } - if (did_fail) + if (did_fail) { CallOnError(Delegate::ERROR_WRITE); + return; // |this| may have been destroyed in |CallOnError()|. + } } void RawChannel::EnqueueMessageNoLock(scoped_ptr<MessageInTransit> message) { @@ -467,8 +466,10 @@ RawChannel::Delegate::Error RawChannel::ReadIOResultToError( void RawChannel::CallOnError(Delegate::Error error) { DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io_); // TODO(vtl): Add a "write_lock_.AssertNotAcquired()"? - if (delegate_) + if (delegate_) { delegate_->OnError(error); + return; // |this| may have been destroyed in |OnError()|. + } } bool RawChannel::OnWriteCompletedNoLock(IOResult io_result, diff --git a/third_party/mojo/src/mojo/edk/system/raw_channel.h b/third_party/mojo/src/mojo/edk/system/raw_channel.h index f567767..91feaab 100644 --- a/third_party/mojo/src/mojo/edk/system/raw_channel.h +++ b/third_party/mojo/src/mojo/edk/system/raw_channel.h @@ -41,6 +41,8 @@ namespace system { // on which |Init()| is called). class MOJO_SYSTEM_IMPL_EXPORT RawChannel { public: + // This object may be destroyed on any thread (if |Init()| was called, after + // |Shutdown()| was called). virtual ~RawChannel(); // The |Delegate| is only accessed on the same thread as the message loop @@ -61,14 +63,14 @@ class MOJO_SYSTEM_IMPL_EXPORT RawChannel { ERROR_WRITE }; - // Called when a message is read. This may call |Shutdown()| (on the - // |RawChannel|), but must not destroy it. + // Called when a message is read. This may call the |RawChannel|'s + // |Shutdown()| and then (if desired) destroy it. virtual void OnReadMessage( const MessageInTransit::View& message_view, embedder::ScopedPlatformHandleVectorPtr platform_handles) = 0; - // Called when there's a (fatal) error. This may call the raw channel's - // |Shutdown()|, but must not destroy it. + // Called when there's a (fatal) error. This may call the |RawChannel|'s + // |Shutdown()| and then (if desired) destroy it. // // For each raw channel, there'll be at most one |ERROR_READ_...| and at // most one |ERROR_WRITE| notification. After |OnError(ERROR_READ_...)|, @@ -197,10 +199,10 @@ class MOJO_SYSTEM_IMPL_EXPORT RawChannel { RawChannel(); // |result| must not be |IO_PENDING|. Must be called on the I/O thread WITHOUT - // |write_lock_| held. + // |write_lock_| held. This object may be destroyed by this call. void OnReadCompleted(IOResult io_result, size_t bytes_read); // |result| must not be |IO_PENDING|. Must be called on the I/O thread WITHOUT - // |write_lock_| held. + // |write_lock_| held. This object may be destroyed by this call. void OnWriteCompleted(IOResult io_result, size_t platform_handles_written, size_t bytes_written); @@ -280,8 +282,9 @@ class MOJO_SYSTEM_IMPL_EXPORT RawChannel { // Must be called on the I/O thread WITHOUT |write_lock_| held. virtual void OnInit() = 0; // On shutdown, passes the ownership of the buffers to subclasses, which may - // want to preserve them if there are pending read/write. Must be called on - // the I/O thread under |write_lock_|. + // want to preserve them if there are pending read/writes. After this is + // called, |OnReadCompleted()| must no longer be called. Must be called on the + // I/O thread under |write_lock_|. virtual void OnShutdownNoLock(scoped_ptr<ReadBuffer> read_buffer, scoped_ptr<WriteBuffer> write_buffer) = 0; @@ -290,7 +293,7 @@ class MOJO_SYSTEM_IMPL_EXPORT RawChannel { static Delegate::Error ReadIOResultToError(IOResult io_result); // Calls |delegate_->OnError(error)|. Must be called on the I/O thread WITHOUT - // |write_lock_| held. + // |write_lock_| held. This object may be destroyed by this call. void CallOnError(Delegate::Error error); // If |io_result| is |IO_SUCCESS|, updates the write buffer and schedules a @@ -308,7 +311,7 @@ class MOJO_SYSTEM_IMPL_EXPORT RawChannel { // Only used on the I/O thread: Delegate* delegate_; - bool read_stopped_; + bool* set_on_shutdown_; scoped_ptr<ReadBuffer> read_buffer_; base::Lock write_lock_; // Protects the following members. diff --git a/third_party/mojo/src/mojo/edk/system/raw_channel_posix.cc b/third_party/mojo/src/mojo/edk/system/raw_channel_posix.cc index 078f8cb..d8c55d56 100644 --- a/third_party/mojo/src/mojo/edk/system/raw_channel_posix.cc +++ b/third_party/mojo/src/mojo/edk/system/raw_channel_posix.cc @@ -356,18 +356,23 @@ void RawChannelPosix::OnFileCanReadWithoutBlocking(int fd) { pending_read_ = false; size_t bytes_read = 0; IOResult io_result = Read(&bytes_read); - if (io_result != IO_PENDING) + if (io_result != IO_PENDING) { OnReadCompleted(io_result, bytes_read); + // TODO(vtl): If we weren't destroyed, we'd like to do + // + // DCHECK(!read_watcher_ || pending_read_); + // + // On failure, |read_watcher_| must have been reset; on success, we assume + // that |OnReadCompleted()| always schedules another read. Otherwise, we + // could end up spinning -- getting |OnFileCanReadWithoutBlocking()| again + // and again but not doing any actual read. + // TODO(yzshen): An alternative is to stop watching if RawChannel doesn't + // schedule a new read. But that code won't be reached under the current + // RawChannel implementation. + return; // |this| may have been destroyed in |OnReadCompleted()|. + } - // On failure, |read_watcher_| must have been reset; on success, - // we assume that |OnReadCompleted()| always schedules another read. - // Otherwise, we could end up spinning -- getting - // |OnFileCanReadWithoutBlocking()| again and again but not doing any actual - // read. - // TODO(yzshen): An alternative is to stop watching if RawChannel doesn't - // schedule a new read. But that code won't be reached under the current - // RawChannel implementation. - DCHECK(!read_watcher_ || pending_read_); + DCHECK(pending_read_); } void RawChannelPosix::OnFileCanWriteWithoutBlocking(int fd) { @@ -386,8 +391,10 @@ void RawChannelPosix::OnFileCanWriteWithoutBlocking(int fd) { io_result = WriteNoLock(&platform_handles_written, &bytes_written); } - if (io_result != IO_PENDING) + if (io_result != IO_PENDING) { OnWriteCompleted(io_result, platform_handles_written, bytes_written); + return; // |this| may have been destroyed in |OnWriteCompleted()|. + } } RawChannel::IOResult RawChannelPosix::ReadImpl(size_t* bytes_read) { @@ -451,6 +458,7 @@ void RawChannelPosix::WaitToWrite() { pending_write_ = false; } OnWriteCompleted(IO_FAILED_UNKNOWN, 0, 0); + return; // |this| may have been destroyed in |OnWriteCompleted()|. } } diff --git a/third_party/mojo/src/mojo/edk/system/raw_channel_unittest.cc b/third_party/mojo/src/mojo/edk/system/raw_channel_unittest.cc index a8cbcba..a95ce30 100644 --- a/third_party/mojo/src/mojo/edk/system/raw_channel_unittest.cc +++ b/third_party/mojo/src/mojo/edk/system/raw_channel_unittest.cc @@ -555,12 +555,14 @@ TEST_F(RawChannelTest, WriteMessageAfterShutdown) { EXPECT_FALSE(rc->WriteMessage(MakeTestMessage(1))); } -// RawChannelTest.ShutdownOnReadMessage ---------------------------------------- +// RawChannelTest.{Shutdown, ShutdownAndDestroy}OnReadMessage ------------------ class ShutdownOnReadMessageRawChannelDelegate : public RawChannel::Delegate { public: - explicit ShutdownOnReadMessageRawChannelDelegate(RawChannel* raw_channel) + explicit ShutdownOnReadMessageRawChannelDelegate(RawChannel* raw_channel, + bool should_destroy) : raw_channel_(raw_channel), + should_destroy_(should_destroy), done_event_(false, false), did_shutdown_(false) {} ~ShutdownOnReadMessageRawChannelDelegate() override {} @@ -574,6 +576,8 @@ class ShutdownOnReadMessageRawChannelDelegate : public RawChannel::Delegate { EXPECT_TRUE( CheckMessageData(message_view.bytes(), message_view.num_bytes())); raw_channel_->Shutdown(); + if (should_destroy_) + delete raw_channel_; did_shutdown_ = true; done_event_.Signal(); } @@ -589,6 +593,7 @@ class ShutdownOnReadMessageRawChannelDelegate : public RawChannel::Delegate { private: RawChannel* const raw_channel_; + const bool should_destroy_; base::WaitableEvent done_event_; bool did_shutdown_; @@ -601,7 +606,7 @@ TEST_F(RawChannelTest, ShutdownOnReadMessage) { EXPECT_TRUE(WriteTestMessageToHandle(handles[1].get(), 10)); scoped_ptr<RawChannel> rc(RawChannel::Create(handles[0].Pass())); - ShutdownOnReadMessageRawChannelDelegate delegate(rc.get()); + ShutdownOnReadMessageRawChannelDelegate delegate(rc.get(), false); io_thread()->PostTaskAndWait( FROM_HERE, base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate))); @@ -610,13 +615,29 @@ TEST_F(RawChannelTest, ShutdownOnReadMessage) { delegate.Wait(); } -// RawChannelTest.ShutdownOnError{Read, Write} --------------------------------- +TEST_F(RawChannelTest, ShutdownAndDestroyOnReadMessage) { + // Write a message into the other end. + EXPECT_TRUE(WriteTestMessageToHandle(handles[1].get(), 10)); + + // The delegate will destroy |rc|. + RawChannel* rc = RawChannel::Create(handles[0].Pass()).release(); + ShutdownOnReadMessageRawChannelDelegate delegate(rc, true); + io_thread()->PostTaskAndWait( + FROM_HERE, base::Bind(&InitOnIOThread, rc, base::Unretained(&delegate))); + + // Wait for the delegate, which will shut the |RawChannel| down. + delegate.Wait(); +} + +// RawChannelTest.{Shutdown, ShutdownAndDestroy}OnError{Read, Write} ----------- class ShutdownOnErrorRawChannelDelegate : public RawChannel::Delegate { public: ShutdownOnErrorRawChannelDelegate(RawChannel* raw_channel, + bool should_destroy, Error shutdown_on_error_type) : raw_channel_(raw_channel), + should_destroy_(should_destroy), shutdown_on_error_type_(shutdown_on_error_type), done_event_(false, false), did_shutdown_(false) {} @@ -633,6 +654,8 @@ class ShutdownOnErrorRawChannelDelegate : public RawChannel::Delegate { if (error != shutdown_on_error_type_) return; raw_channel_->Shutdown(); + if (should_destroy_) + delete raw_channel_; did_shutdown_ = true; done_event_.Signal(); } @@ -645,6 +668,7 @@ class ShutdownOnErrorRawChannelDelegate : public RawChannel::Delegate { private: RawChannel* const raw_channel_; + const bool should_destroy_; const Error shutdown_on_error_type_; base::WaitableEvent done_event_; bool did_shutdown_; @@ -655,7 +679,7 @@ class ShutdownOnErrorRawChannelDelegate : public RawChannel::Delegate { TEST_F(RawChannelTest, ShutdownOnErrorRead) { scoped_ptr<RawChannel> rc(RawChannel::Create(handles[0].Pass())); ShutdownOnErrorRawChannelDelegate delegate( - rc.get(), RawChannel::Delegate::ERROR_READ_SHUTDOWN); + rc.get(), false, RawChannel::Delegate::ERROR_READ_SHUTDOWN); io_thread()->PostTaskAndWait( FROM_HERE, base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate))); @@ -667,9 +691,23 @@ TEST_F(RawChannelTest, ShutdownOnErrorRead) { delegate.Wait(); } +TEST_F(RawChannelTest, ShutdownAndDestroyOnErrorRead) { + RawChannel* rc = RawChannel::Create(handles[0].Pass()).release(); + ShutdownOnErrorRawChannelDelegate delegate( + rc, true, RawChannel::Delegate::ERROR_READ_SHUTDOWN); + io_thread()->PostTaskAndWait( + FROM_HERE, base::Bind(&InitOnIOThread, rc, base::Unretained(&delegate))); + + // Close the handle of the other end, which should stuff fail. + handles[1].reset(); + + // Wait for the delegate, which will shut the |RawChannel| down. + delegate.Wait(); +} + TEST_F(RawChannelTest, ShutdownOnErrorWrite) { scoped_ptr<RawChannel> rc(RawChannel::Create(handles[0].Pass())); - ShutdownOnErrorRawChannelDelegate delegate(rc.get(), + ShutdownOnErrorRawChannelDelegate delegate(rc.get(), false, RawChannel::Delegate::ERROR_WRITE); io_thread()->PostTaskAndWait( FROM_HERE, @@ -684,6 +722,22 @@ TEST_F(RawChannelTest, ShutdownOnErrorWrite) { delegate.Wait(); } +TEST_F(RawChannelTest, ShutdownAndDestroyOnErrorWrite) { + RawChannel* rc = RawChannel::Create(handles[0].Pass()).release(); + ShutdownOnErrorRawChannelDelegate delegate(rc, true, + RawChannel::Delegate::ERROR_WRITE); + io_thread()->PostTaskAndWait( + FROM_HERE, base::Bind(&InitOnIOThread, rc, base::Unretained(&delegate))); + + // Close the handle of the other end, which should stuff fail. + handles[1].reset(); + + EXPECT_FALSE(rc->WriteMessage(MakeTestMessage(1))); + + // Wait for the delegate, which will shut the |RawChannel| down. + delegate.Wait(); +} + // RawChannelTest.ReadWritePlatformHandles ------------------------------------- class ReadPlatformHandlesCheckerRawChannelDelegate diff --git a/third_party/mojo/src/mojo/edk/system/raw_channel_win.cc b/third_party/mojo/src/mojo/edk/system/raw_channel_win.cc index 7ec7ad7..4417937 100644 --- a/third_party/mojo/src/mojo/edk/system/raw_channel_win.cc +++ b/third_party/mojo/src/mojo/edk/system/raw_channel_win.cc @@ -303,6 +303,7 @@ void RawChannelWin::RawChannelIOHandler::OnReadCompleted(DWORD bytes_read, if (!owner_) return; + // Note: |OnReadCompleted()| may detach us from |owner_|. if (error == ERROR_SUCCESS) { DCHECK_GT(bytes_read, 0u); owner_->OnReadCompleted(IO_SUCCEEDED, bytes_read); @@ -335,6 +336,7 @@ void RawChannelWin::RawChannelIOHandler::OnWriteCompleted(DWORD bytes_written, pending_write_ = false; } + // Note: |OnWriteCompleted()| may detach us from |owner_|. if (error == ERROR_SUCCESS) { owner_->OnWriteCompleted(IO_SUCCEEDED, 0, bytes_written); } else if (error == ERROR_BROKEN_PIPE) { diff --git a/third_party/mojo/src/mojo/edk/test/BUILD.gn b/third_party/mojo/src/mojo/edk/test/BUILD.gn index ea323c6..b130440 100644 --- a/third_party/mojo/src/mojo/edk/test/BUILD.gn +++ b/third_party/mojo/src/mojo/edk/test/BUILD.gn @@ -2,8 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//testing/test.gni") import("../mojo_edk.gni") +import("//testing/test.gni") mojo_edk_source_set("test_support") { testonly = true diff --git a/third_party/mojo/src/mojo/public/VERSION b/third_party/mojo/src/mojo/public/VERSION index c4ab015..928bc42 100644 --- a/third_party/mojo/src/mojo/public/VERSION +++ b/third_party/mojo/src/mojo/public/VERSION @@ -1 +1 @@ -53d4413e27ba6767cb6da33ab4342c419c725086
\ No newline at end of file +a85a2cea82d816de115e15253742b0f88a9924eb
\ No newline at end of file diff --git a/third_party/mojo/src/mojo/public/cpp/application/BUILD.gn b/third_party/mojo/src/mojo/public/cpp/application/BUILD.gn index 1c8842d..8741c694 100644 --- a/third_party/mojo/src/mojo/public/cpp/application/BUILD.gn +++ b/third_party/mojo/src/mojo/public/cpp/application/BUILD.gn @@ -22,8 +22,6 @@ mojo_sdk_source_set("application") { "lib/service_connector.h", "lib/service_registry.cc", "lib/service_registry.h", - "lib/weak_service_provider.cc", - "lib/weak_service_provider.h", ] mojo_sdk_deps = [ diff --git a/third_party/mojo/src/mojo/public/cpp/application/application_connection.h b/third_party/mojo/src/mojo/public/cpp/application/application_connection.h index d5d6dde..ca6ea07 100644 --- a/third_party/mojo/src/mojo/public/cpp/application/application_connection.h +++ b/third_party/mojo/src/mojo/public/cpp/application/application_connection.h @@ -47,10 +47,11 @@ class ApplicationConnection { // Connect to the service implementing |Interface|. template <typename Interface> void ConnectToService(InterfacePtr<Interface>* ptr) { - MessagePipe pipe; - ptr->Bind(pipe.handle0.Pass()); - GetServiceProvider()->ConnectToService(Interface::Name_, - pipe.handle1.Pass()); + if (ServiceProvider* sp = GetServiceProvider()) { + MessagePipe pipe; + ptr->Bind(pipe.handle0.Pass()); + sp->ConnectToService(Interface::Name_, pipe.handle1.Pass()); + } } // The url identifying the application on the other end of this connection. diff --git a/third_party/mojo/src/mojo/public/cpp/application/application_impl.h b/third_party/mojo/src/mojo/public/cpp/application/application_impl.h index 0ea22c9..430a124 100644 --- a/third_party/mojo/src/mojo/public/cpp/application/application_impl.h +++ b/third_party/mojo/src/mojo/public/cpp/application/application_impl.h @@ -100,6 +100,7 @@ class ApplicationImpl : public InterfaceImpl<Application> { void AcceptConnection(const String& requestor_url, InterfaceRequest<ServiceProvider> services, ServiceProviderPtr exposed_services) override; + void RequestQuit() override; typedef std::vector<internal::ServiceRegistry*> ServiceRegistryList; diff --git a/third_party/mojo/src/mojo/public/cpp/application/lib/application_impl.cc b/third_party/mojo/src/mojo/public/cpp/application/lib/application_impl.cc index 6677003..894060d 100644 --- a/third_party/mojo/src/mojo/public/cpp/application/lib/application_impl.cc +++ b/third_party/mojo/src/mojo/public/cpp/application/lib/application_impl.cc @@ -114,4 +114,8 @@ void ApplicationImpl::AcceptConnection( incoming_service_registries_.push_back(registry); } +void ApplicationImpl::RequestQuit() { + Terminate(); +} + } // namespace mojo diff --git a/third_party/mojo/src/mojo/public/cpp/application/lib/service_provider_impl.cc b/third_party/mojo/src/mojo/public/cpp/application/lib/service_provider_impl.cc index 08a0648..db55710 100644 --- a/third_party/mojo/src/mojo/public/cpp/application/lib/service_provider_impl.cc +++ b/third_party/mojo/src/mojo/public/cpp/application/lib/service_provider_impl.cc @@ -5,22 +5,23 @@ #include "mojo/public/cpp/application/service_provider_impl.h" #include "mojo/public/cpp/application/lib/service_connector.h" -#include "mojo/public/cpp/application/lib/weak_service_provider.h" #include "mojo/public/cpp/environment/logging.h" namespace mojo { -ServiceProviderImpl::ServiceProviderImpl() : remote_(nullptr) { +ServiceProviderImpl::ServiceProviderImpl() : binding_(this) { +} + +ServiceProviderImpl::ServiceProviderImpl( + InterfaceRequest<ServiceProvider> request) + : binding_(this, request.Pass()) { } ServiceProviderImpl::~ServiceProviderImpl() { } -ServiceProvider* ServiceProviderImpl::CreateRemoteServiceProvider() { - // TODO(beng): it sure would be nice if this method could return a scoped_ptr. - MOJO_DCHECK(!remote_); - remote_ = new internal::WeakServiceProvider(this, client()); - return remote_; +void ServiceProviderImpl::Bind(InterfaceRequest<ServiceProvider> request) { + binding_.Bind(request.Pass()); } void ServiceProviderImpl::ConnectToService( @@ -37,10 +38,6 @@ void ServiceProviderImpl::ConnectToService( client_handle.Pass()); } -void ServiceProviderImpl::OnConnectionError() { - ClearRemote(); -} - void ServiceProviderImpl::AddServiceConnector( internal::ServiceConnectorBase* service_connector) { RemoveServiceConnector(service_connector); @@ -59,11 +56,4 @@ void ServiceProviderImpl::RemoveServiceConnector( service_connectors_.erase(it); } -void ServiceProviderImpl::ClearRemote() { - if (remote_) { - remote_->Clear(); - remote_ = nullptr; - } -} - } // namespace mojo diff --git a/third_party/mojo/src/mojo/public/cpp/application/lib/weak_service_provider.cc b/third_party/mojo/src/mojo/public/cpp/application/lib/weak_service_provider.cc deleted file mode 100644 index de0cb6c..0000000 --- a/third_party/mojo/src/mojo/public/cpp/application/lib/weak_service_provider.cc +++ /dev/null @@ -1,36 +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. - -#include "mojo/public/cpp/application/lib/weak_service_provider.h" - -#include "mojo/public/cpp/application/service_provider_impl.h" -#include "mojo/public/interfaces/application/service_provider.mojom.h" - -namespace mojo { -namespace internal { - -WeakServiceProvider::WeakServiceProvider(ServiceProviderImpl* creator, - ServiceProvider* service_provider) - : creator_(creator), service_provider_(service_provider) { -} - -WeakServiceProvider::~WeakServiceProvider() { - if (creator_) - creator_->ClearRemote(); -} - -void WeakServiceProvider::Clear() { - creator_ = nullptr; - service_provider_ = nullptr; -} - -void WeakServiceProvider::ConnectToService( - const String& service_name, - ScopedMessagePipeHandle client_handle) { - if (service_provider_) - service_provider_->ConnectToService(service_name, client_handle.Pass()); -} - -} // namespace internal -} // namespace mojo diff --git a/third_party/mojo/src/mojo/public/cpp/application/lib/weak_service_provider.h b/third_party/mojo/src/mojo/public/cpp/application/lib/weak_service_provider.h deleted file mode 100644 index 3d959d1..0000000 --- a/third_party/mojo/src/mojo/public/cpp/application/lib/weak_service_provider.h +++ /dev/null @@ -1,41 +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_APPLICATION_LIB_WEAK_SERVICE_PROVIDER_H_ -#define MOJO_PUBLIC_APPLICATION_LIB_WEAK_SERVICE_PROVIDER_H_ - -#include "mojo/public/interfaces/application/service_provider.mojom.h" - -namespace mojo { -class ServiceProviderImpl; -namespace internal { -class ServiceConnectorBase; - -// Implements a weak pointer to a ServiceProvider. Necessary as the lifetime of -// the ServiceProviderImpl is bound to that of its pipe, but code may continue -// to reference a remote service provider beyond the lifetime of said pipe. -// Calls to ConnectToService() are silently dropped when the pipe is closed. -class WeakServiceProvider : public ServiceProvider { - public: - WeakServiceProvider(ServiceProviderImpl* creator, - ServiceProvider* service_provider); - ~WeakServiceProvider() override; - - void Clear(); - - private: - // Overridden from ServiceProvider: - void ConnectToService(const String& service_name, - ScopedMessagePipeHandle client_handle) override; - - ServiceProviderImpl* creator_; - ServiceProvider* service_provider_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(WeakServiceProvider); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_APPLICATION_LIB_WEAK_SERVICE_PROVIDER_H_ diff --git a/third_party/mojo/src/mojo/public/cpp/application/service_provider_impl.h b/third_party/mojo/src/mojo/public/cpp/application/service_provider_impl.h index 45ad7b8..a449124 100644 --- a/third_party/mojo/src/mojo/public/cpp/application/service_provider_impl.h +++ b/third_party/mojo/src/mojo/public/cpp/application/service_provider_impl.h @@ -6,57 +6,44 @@ #define MOJO_PUBLIC_APPLICATION_SERVICE_PROVIDER_IMPL_H_ #include "mojo/public/cpp/application/lib/service_connector.h" +#include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/interfaces/application/service_provider.mojom.h" namespace mojo { namespace internal { -class WeakServiceProvider; class ServiceConnectorBase; } // Implements a registry that can be used to expose services to another app. -class ServiceProviderImpl : public InterfaceImpl<ServiceProvider> { +class ServiceProviderImpl : public ServiceProvider { public: ServiceProviderImpl(); + explicit ServiceProviderImpl(InterfaceRequest<ServiceProvider> request); ~ServiceProviderImpl() override; + void Bind(InterfaceRequest<ServiceProvider> request); + template <typename Interface> void AddService(InterfaceFactory<Interface>* factory) { AddServiceConnector( new internal::InterfaceFactoryConnector<Interface>(factory)); } - // Returns an instance of a ServiceProvider that weakly wraps this impl's - // connection to some other app. Whereas the lifetime of an instance of - // ServiceProviderImpl is bound to the lifetime of the pipe it - // encapsulates, the lifetime of the ServiceProvider instance returned by this - // method is assumed by the caller. After the pipe is closed - // ConnectToService() calls on this object will be silently dropped. - // This method must only be called once per ServiceProviderImpl. - ServiceProvider* CreateRemoteServiceProvider(); - private: typedef std::map<std::string, internal::ServiceConnectorBase*> NameToServiceConnectorMap; - friend class internal::WeakServiceProvider; - // Overridden from ServiceProvider: void ConnectToService(const String& service_name, ScopedMessagePipeHandle client_handle) override; - // Overridden from InterfaceImpl: - void OnConnectionError() override; - void AddServiceConnector(internal::ServiceConnectorBase* service_connector); void RemoveServiceConnector( internal::ServiceConnectorBase* service_connector); - void ClearRemote(); - NameToServiceConnectorMap service_connectors_; - internal::WeakServiceProvider* remote_; + Binding<ServiceProvider> binding_; MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceProviderImpl); }; diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/array.h b/third_party/mojo/src/mojo/public/cpp/bindings/array.h index ca4e9cc..5194663 100644 --- a/third_party/mojo/src/mojo/public/cpp/bindings/array.h +++ b/third_party/mojo/src/mojo/public/cpp/bindings/array.h @@ -18,6 +18,8 @@ namespace mojo { +// Represents a moveable array with contents of type |T|. The array can be null, +// meaning that no value has been assigned to it. Null is distinct from empty. template <typename T> class Array { MOJO_MOVE_ONLY_TYPE(Array) @@ -31,30 +33,42 @@ class Array { typedef internal::Array_Data<typename internal::WrapperTraits<T>::DataType> Data_; + // Constructs a new array that is null. Array() : is_null_(true) {} + + // Constructs a new non-null array of the specified size. The elements will + // be value-initialized (meaning that they will be initialized by their + // default constructor, if any, or else zero-initialized). explicit Array(size_t size) : vec_(size), is_null_(false) { Traits::Initialize(&vec_); } ~Array() { Traits::Finalize(&vec_); } + // Moves the contents of |other| into this array. Array(Array&& other) : is_null_(true) { Take(&other); } Array& operator=(Array&& other) { Take(&other); return *this; } + // Creates a non-null array of the specified size. The elements will be + // value-initialized (meaning that they will be initialized by their default + // constructor, if any, or else zero-initialized). static Array New(size_t size) { return Array(size).Pass(); } + // Creates a new array with a copy of the contents of |other|. template <typename U> static Array From(const U& other) { return TypeConverter<Array, U>::Convert(other); } + // Copies the contents of this array to a new object of type |U|. template <typename U> U To() const { return TypeConverter<U, Array>::Convert(*this); } + // Resets the contents of this array back to null. void reset() { if (!vec_.empty()) { Traits::Finalize(&vec_); @@ -63,41 +77,65 @@ class Array { is_null_ = true; } + // Indicates whether the array is null (which is distinct from empty). bool is_null() const { return is_null_; } + // Returns a reference to the first element of the array. Calling this on a + // null or empty array causes undefined behavior. ConstRefType front() const { return vec_.front(); } RefType front() { return vec_.front(); } + // Returns the size of the array, which will be zero if the array is null. size_t size() const { return vec_.size(); } + // Returns a reference to the element at zero-based |offset|. Calling this on + // an array with size less than |offset|+1 causes undefined behavior. ConstRefType at(size_t offset) const { return Traits::at(&vec_, offset); } ConstRefType operator[](size_t offset) const { return at(offset); } - RefType at(size_t offset) { return Traits::at(&vec_, offset); } RefType operator[](size_t offset) { return at(offset); } + // Pushes |value| onto the back of the array. If this array was null, it will + // become non-null with a size of 1. void push_back(ForwardType value) { is_null_ = false; Traits::PushBack(&vec_, value); } + // Resizes the array to |size| and makes it non-null. Otherwise, works just + // like the resize method of |std::vector|. void resize(size_t size) { is_null_ = false; Traits::Resize(&vec_, size); } + // Returns a const reference to the |std::vector| managed by this class. If + // the array is null, this will be an empty vector. const std::vector<StorageType>& storage() const { return vec_; } operator const std::vector<StorageType>&() const { return vec_; } + // Swaps the contents of this array with the |other| array, including + // nullness. void Swap(Array* other) { std::swap(is_null_, other->is_null_); vec_.swap(other->vec_); } + + // Swaps the contents of this array with the specified vector, making this + // array non-null. Since the vector cannot represent null, it will just be + // made empty if this array is null. void Swap(std::vector<StorageType>* other) { is_null_ = false; vec_.swap(*other); } + // Returns a copy of the array where each value of the new array has been + // "cloned" from the corresponding value of this array. If this array contains + // primitive data types, this is equivalent to simply copying the contents. + // However, if the array contains objects, then each new element is created by + // calling the |Clone| method of the source element, which should make a copy + // of the element. + // // Please note that calling this method will fail compilation if the element // type cannot be cloned (which usually means that it is a Mojo handle type or // a type contains Mojo handles). @@ -108,6 +146,10 @@ class Array { return result.Pass(); } + // Indicates whether the contents of this array are equal to |other|. A null + // array is only equal to another null array. Elements are compared using the + // |ValueTraits::Equals| method, which in most cases calls the |Equals| method + // of the element. bool Equals(const Array& other) const { if (is_null() != other.is_null()) return false; @@ -136,6 +178,9 @@ class Array { bool is_null_; }; +// A |TypeConverter| that will create an |Array<T>| containing a copy of the +// contents of an |std::vector<E>|, using |TypeConverter<T, E>| to copy each +// element. The returned array will always be non-null. template <typename T, typename E> struct TypeConverter<Array<T>, std::vector<E>> { static Array<T> Convert(const std::vector<E>& input) { @@ -146,6 +191,9 @@ struct TypeConverter<Array<T>, std::vector<E>> { } }; +// A |TypeConverter| that will create an |std::vector<E>| containing a copy of +// the contents of an |Array<T>|, using |TypeConverter<E, T>| to copy each +// element. If the input array is null, the output vector will be empty. template <typename E, typename T> struct TypeConverter<std::vector<E>, Array<T>> { static std::vector<E> Convert(const Array<T>& input) { diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/binding.h b/third_party/mojo/src/mojo/public/cpp/bindings/binding.h index 4ecc6a8..658b6a0 100644 --- a/third_party/mojo/src/mojo/public/cpp/bindings/binding.h +++ b/third_party/mojo/src/mojo/public/cpp/bindings/binding.h @@ -17,8 +17,10 @@ namespace mojo { -// This binds an interface implementation a pipe. Deleting the binding closes -// the pipe. +// Represents the binding of an interface implementation to a message pipe. +// When the |Binding| object is destroyed, the binding between the message pipe +// and the interface is torn down and the message pipe is closed, leaving the +// interface implementation in an unbound state. // // Example: // @@ -43,13 +45,29 @@ namespace mojo { // // delete FooImpl on connection errors. // } // }; +// +// The caller may specify a |MojoAsyncWaiter| to be used by the connection when +// waiting for calls to arrive. Normally it is fine to use the default waiter. +// However, the caller may provide their own implementation if needed. The +// |Binding| will not take ownership of the waiter, and the waiter must outlive +// the |Binding|. +// +// TODO(ggowan): Find out under what circumstances the caller may need to +// provide their own implementation of MojoAsyncWaiter, and then describe those +// circumstances. template <typename Interface> class Binding : public ErrorHandler { public: using Client = typename Interface::Client; + // Constructs an incomplete binding that will use the implementation |impl|. + // The binding may be completed with a subsequent call to the |Bind| method. + // Does not take ownership of |impl|, which must outlive the binding. explicit Binding(Interface* impl) : impl_(impl) { stub_.set_sink(impl_); } + // Constructs a completed binding of message pipe |handle| to implementation + // |impl|. Does not take ownership of |impl|, which must outlive the binding. + // See class comment for definition of |waiter|. Binding(Interface* impl, ScopedMessagePipeHandle handle, const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) @@ -57,6 +75,12 @@ class Binding : public ErrorHandler { Bind(handle.Pass(), waiter); } + // Constructs a completed binding of |impl| to a new message pipe, passing the + // client end to |ptr|, which takes ownership of it. The caller is expected to + // pass |ptr| on to the client of the service. Does not take ownership of any + // of the parameters. |impl| must outlive the binding. |ptr| only needs to + // last until the constructor returns. See class comment for definition of + // |waiter|. Binding(Interface* impl, InterfacePtr<Interface>* ptr, const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) @@ -64,6 +88,10 @@ class Binding : public ErrorHandler { Bind(ptr, waiter); } + // Constructs a completed binding of |impl| to the message pipe endpoint in + // |request|, taking ownership of the endpoint. Does not take ownership of + // |impl|, which must outlive the binding. See class comment for definition of + // |waiter|. Binding(Interface* impl, InterfaceRequest<Interface> request, const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) @@ -71,6 +99,8 @@ class Binding : public ErrorHandler { Bind(request.PassMessagePipe(), waiter); } + // Tears down the binding, closing the message pipe and leaving the interface + // implementation unbound. ~Binding() override { delete proxy_; if (internal_router_) { @@ -79,6 +109,9 @@ class Binding : public ErrorHandler { } } + // Completes a binding that was constructed with only an interface + // implementation. Takes ownership of |handle| and binds it to the previously + // specified implementation. See class comment for definition of |waiter|. void Bind( ScopedMessagePipeHandle handle, const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) { @@ -95,6 +128,12 @@ class Binding : public ErrorHandler { proxy_ = new typename Client::Proxy_(internal_router_); } + // Completes a binding that was constructed with only an interface + // implementation by creating a new message pipe, binding one end of it to the + // previously specified implementation, and passing the other to |ptr|, which + // takes ownership of it. The caller is expected to pass |ptr| on to the + // eventual client of the service. Does not take ownership of |ptr|. See + // class comment for definition of |waiter|. void Bind( InterfacePtr<Interface>* ptr, const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) { @@ -103,35 +142,50 @@ class Binding : public ErrorHandler { Bind(pipe.handle1.Pass(), waiter); } + // Completes a binding that was constructed with only an interface + // implementation by removing the message pipe endpoint from |request| and + // binding it to the previously specified implementation. See class comment + // for definition of |waiter|. void Bind( InterfaceRequest<Interface> request, const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) { Bind(request.PassMessagePipe(), waiter); } + // Blocks the calling thread until either a call arrives on the previously + // bound message pipe, or an error occurs. bool WaitForIncomingMethodCall() { MOJO_DCHECK(internal_router_); return internal_router_->WaitForIncomingMessage(); } + // Closes the message pipe that was previously bound. void Close() { MOJO_DCHECK(internal_router_); internal_router_->CloseMessagePipe(); } + // Sets an error handler that will be called if a connection error occurs on + // the bound message pipe. void set_error_handler(ErrorHandler* error_handler) { error_handler_ = error_handler; } - // ErrorHandler implementation + // Implements the |Binding|'s response to a connection error. void OnConnectionError() override { if (error_handler_) error_handler_->OnConnectionError(); } + // Returns the interface implementation that was previously specified. Caller + // does not take ownership. Interface* impl() { return impl_; } + + // Returns the client's interface. Client* client() { return proxy_; } + // Indicates whether the binding has been completed (i.e., whether a message + // pipe has been bound to the implementation). bool is_bound() const { return !!internal_router_; } // Exposed for testing, should not generally be used. diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h b/third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h index 1723330..0b89103 100644 --- a/third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h +++ b/third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h @@ -16,7 +16,12 @@ class InterfaceRequest { public: InterfaceRequest() {} + InterfaceRequest(decltype(nullptr)) {} InterfaceRequest(InterfaceRequest&& other) { handle_ = other.handle_.Pass(); } + InterfaceRequest& operator=(decltype(nullptr)) { + handle_.reset(); + return *this; + } InterfaceRequest& operator=(InterfaceRequest&& other) { handle_ = other.handle_.Pass(); return *this; diff --git a/third_party/mojo/src/mojo/public/dart/README b/third_party/mojo/src/mojo/public/dart/README index f9cd6e6..fd75b8f 100644 --- a/third_party/mojo/src/mojo/public/dart/README +++ b/third_party/mojo/src/mojo/public/dart/README @@ -2,26 +2,16 @@ These are interim instructions for building and testing Dart's Mojo bindings. These instructions currently only work for Linux, and assume you already have a Mojo checkout. -1.) Add a Dart VM source checkout to your client: - - Edit your .gclient file. Replace "DEPS" with "DEPS.dart". - Then, run: - - $ gclient sync - - You should now have a directory //dart - - -2.) Configure Mojo with Dart. +1.) Configure Mojo with Dart. $ ./mojo/tools/mojob.py gn --release --with-dart -3.) Build Mojo with Dart. +2.) Build Mojo with Dart. $ ./mojo/tools/mojob.py build --release -4.) Run Dart tests. +3.) Run Dart tests. $ ./mojo/tools/mojob.py darttest --release diff --git a/third_party/mojo/src/mojo/public/dart/bindings.dart b/third_party/mojo/src/mojo/public/dart/bindings.dart index 5d6298e..0637737 100644 --- a/third_party/mojo/src/mojo/public/dart/bindings.dart +++ b/third_party/mojo/src/mojo/public/dart/bindings.dart @@ -6,7 +6,6 @@ library bindings; import 'dart:async'; import 'dart:convert'; -import 'dart:mirrors'; import 'dart:mojo_core' as core; import 'dart:typed_data'; diff --git a/third_party/mojo/src/mojo/public/dart/core.dart b/third_party/mojo/src/mojo/public/dart/core.dart index e9fb716..ecd671d 100644 --- a/third_party/mojo/src/mojo/public/dart/core.dart +++ b/third_party/mojo/src/mojo/public/dart/core.dart @@ -11,6 +11,7 @@ import 'dart:typed_data'; part 'src/buffer.dart'; part 'src/data_pipe.dart'; +part 'src/drain_data.dart'; part 'src/event_stream.dart'; part 'src/handle.dart'; part 'src/handle_watcher.dart'; diff --git a/third_party/mojo/src/mojo/public/dart/src/drain_data.dart b/third_party/mojo/src/mojo/public/dart/src/drain_data.dart new file mode 100644 index 0000000..ffc56e5 --- /dev/null +++ b/third_party/mojo/src/mojo/public/dart/src/drain_data.dart @@ -0,0 +1,68 @@ +// 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. + +part of core; + +class DataPipeDrainer { + MojoDataPipeConsumer _consumer; + MojoEventStream _eventStream; + List<ByteData> _dataList; + int _dataSize; + + DataPipeDrainer(this._consumer) { + _eventStream = new MojoEventStream(_consumer.handle); + _dataList = new List(); + _dataSize = 0; + } + + MojoResult _doRead() { + ByteData thisRead = _consumer.beginRead(); + if (thisRead == null) { + throw 'Data pipe beginRead failed: ${_consumer.status}'; + } + _dataList.add(thisRead); + _dataSize += thisRead.lengthInBytes; + return _consumer.endRead(thisRead.lengthInBytes); + } + + ByteData _concatData() { + var data = new ByteData(_dataSize); + int end = 0; + for (var chunk in _dataList) { + data.buffer.asUint8List().setRange( + end, end + chunk.lengthInBytes, chunk.buffer.asUint8List()); + end += chunk.lengthInBytes; + } + return data; + } + + Future<ByteData> drain() { + var completer = new Completer(); + _eventStream.listen((List<int> event) { + var mojoSignals = new MojoHandleSignals(event[1]); + if (mojoSignals.isReadable) { + var result = _doRead(); + if (!result.isOk) { + _eventStream.close(); + _eventStream = null; + completer.complete(_concatData()); + } else { + _eventStream.enableReadEvents(); + } + } else if (mojoSignals.isPeerClosed) { + _eventStream.close(); + _eventStream = null; + completer.complete(_concatData()); + } else { + throw 'Unexpected handle event: $mojoSignals'; + } + }); + return completer.future; + } + + static Future<ByteData> drainHandle(MojoDataPipeConsumer consumer) { + var drainer = new DataPipeDrainer(consumer); + return drainer.drain(); + } +} diff --git a/third_party/mojo/src/mojo/public/dart/src/event_stream.dart b/third_party/mojo/src/mojo/public/dart/src/event_stream.dart index 797f0e6..7016b31 100644 --- a/third_party/mojo/src/mojo/public/dart/src/event_stream.dart +++ b/third_party/mojo/src/mojo/public/dart/src/event_stream.dart @@ -176,8 +176,10 @@ class MojoEventStreamListener { assert(_eventStream.readyWrite); handleWrite(); } - _eventStream.enableSignals(enableSignals( - signalsWatched, signalsReceived)); + if (_isOpen) { + _eventStream.enableSignals(enableSignals( + signalsWatched, signalsReceived)); + } _isInHandler = false; }); } diff --git a/third_party/mojo/src/mojo/public/dart/src/types.dart b/third_party/mojo/src/mojo/public/dart/src/types.dart index 54c5319..49f0398 100644 --- a/third_party/mojo/src/mojo/public/dart/src/types.dart +++ b/third_party/mojo/src/mojo/public/dart/src/types.dart @@ -127,11 +127,12 @@ class MojoHandleSignals { static const int kReadWrite = kReadable | kWritable; static const int kAll = kReadable | kWritable | kPeerClosed; - // TODO(zra): Does PEER_CLOSED | anything else make sense? static const NONE = const MojoHandleSignals._(kNone); static const READABLE = const MojoHandleSignals._(kReadable); static const WRITABLE = const MojoHandleSignals._(kWritable); static const PEER_CLOSED = const MojoHandleSignals._(kPeerClosed); + static const PEER_CLOSED_READABLE = + const MojoHandleSignals._(kPeerClosed | kReadable); static const READWRITE = const MojoHandleSignals._(kReadWrite); static const ALL = const MojoHandleSignals._(kAll); @@ -146,9 +147,10 @@ class MojoHandleSignals { case kWritable: return WRITABLE; case kPeerClosed: return PEER_CLOSED; case kReadWrite: return READWRITE; + case kPeerClosed | kReadable: return PEER_CLOSED_READABLE; case kAll: return ALL; default: - throw 'Invalid handle signal'; + throw 'Invalid handle signal: $value'; } } @@ -174,8 +176,9 @@ class MojoHandleSignals { case kWritable: return "WRITABLE"; case kPeerClosed: return "PEER_CLOSED"; case kReadWrite: return "READWRITE"; + case kPeerClosed | kReadable: return "PEER_CLOSED_READABLE"; case kAll: return "ALL"; - default: return "<invalid signal>"; + default: return "<invalid signals>"; } } } diff --git a/third_party/mojo/src/mojo/public/go/system/c_allocators.c b/third_party/mojo/src/mojo/public/go/system/c_allocators.c index 7af7bb2..2f93908 100644 --- a/third_party/mojo/src/mojo/public/go/system/c_allocators.c +++ b/third_party/mojo/src/mojo/public/go/system/c_allocators.c @@ -157,3 +157,15 @@ void FreeWriteDataParams(struct WriteDataParams p) { free(p.num_bytes); free(p.elements); } + +struct TwoPhaseActionParams MallocTwoPhaseActionParams() { + struct TwoPhaseActionParams p; + p.buffer = (void**)malloc(sizeof(void*)); + p.num_bytes = (uint32_t*)malloc(sizeof(uint32_t)); + return p; +} + +void FreeTwoPhaseActionParams(struct TwoPhaseActionParams p) { + free(p.buffer); + free(p.num_bytes); +} diff --git a/third_party/mojo/src/mojo/public/go/system/c_allocators.h b/third_party/mojo/src/mojo/public/go/system/c_allocators.h index f915e6b..6050507 100644 --- a/third_party/mojo/src/mojo/public/go/system/c_allocators.h +++ b/third_party/mojo/src/mojo/public/go/system/c_allocators.h @@ -126,4 +126,11 @@ struct WriteDataParams { struct WriteDataParams MallocWriteDataParams(uint32_t length); void FreeWriteDataParams(struct WriteDataParams p); +struct TwoPhaseActionParams { + void** buffer; + uint32_t* num_bytes; +}; +struct TwoPhaseActionParams MallocTwoPhaseActionParams(); +void FreeTwoPhaseActionParams(struct TwoPhaseActionParams p); + #endif // MOJO_PUBLIC_GO_SYSTEM_C_ALLOCATORS_H_ diff --git a/third_party/mojo/src/mojo/public/go/system/data_pipe.go b/third_party/mojo/src/mojo/public/go/system/data_pipe.go index 7de27d1..b79a1e0 100644 --- a/third_party/mojo/src/mojo/public/go/system/data_pipe.go +++ b/third_party/mojo/src/mojo/public/go/system/data_pipe.go @@ -16,6 +16,31 @@ type ConsumerHandle interface { // ReadData reads data from the data pipe consumer handle with the // given flags. On success, returns the data that was read. ReadData(flags MojoReadDataFlags) (MojoResult, []byte) + + // BeginReadData begins a two-phase read from the data pipe consumer. + // On success, returns a slice from which the caller can read up to its + // length bytes of data. If flags has |MOJO_READ_DATA_FLAG_ALL_OR_NONE| + // set, then the slice length will be at least as large as |numBytes|, + // which must also be a multiple of the element size (otherwise the + // caller must check the length of the slice). + // + // During a two-phase read, this handle is *not* readable. E.g., read + // from this handle will return |MOJO_RESULT_BUSY|. + // + // Once the caller has finished reading data from the slice, it should + // call |EndReadData()| to specify the amount read and to complete the + // two-phase read. + BeginReadData(numBytes int, flags MojoReadDataFlags) (MojoResult, []byte) + + // EndReadData ends a two-phase read from the data pipe consumer that + // was begun by a call to |BeginReadData()| on the same handle. + // |numBytesRead| should indicate the amount of data actually read; it + // must be less than or equal to the length of the slice returned by + // |BeginReadData()| and must be a multiple of the element size. + // + // On failure, the two-phase read (if any) is ended (so the handle may + // become readable again) but no data is "removed" from the data pipe. + EndReadData(numBytesRead int) MojoResult } // ProducerHandle is a handle for the producer part of a data pipe. @@ -26,6 +51,34 @@ type ProducerHandle interface { // given flags. On success, returns the number of bytes that were // actually written. WriteData(data []byte, flags MojoWriteDataFlags) (MojoResult, int) + + // BeginWriteData begins a two-phase write to the data pipe producer. + // On success, returns a slice to which the caller can write. If flags + // has |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set, then the slice length will + // be at least as large as |numBytes|, which must also be a multiple of + // the element size (otherwise the caller must check the length of the + // slice). + // + // During a two-phase write, this handle is *not* writable. E.g., write + // to this handle will return |MOJO_RESULT_BUSY|. + // + // Once the caller has finished writing data to the buffer, it should + // call |EndWriteData()| to specify the amount written and to complete + // the two-phase write. + BeginWriteData(numBytes int, flags MojoWriteDataFlags) (MojoResult, []byte) + + // EndWriteData ends a two-phase write to the data pipe producer that + // was begun by a call to |BeginWriteData()| on the same handle. + // |numBytesWritten| should indicate the amount of data actually + // written; it must be less than or equal to the length of the slice + // returned by |BeginWriteData()| and must be a multiple of the element + // size. The slice returned from |BeginWriteData()| must have been + // filled with exactly |numBytesWritten| bytes of data. + // + // On failure, the two-phase write (if any) is ended (so the handle may + // become writable again, if there's space available) but no data + // written to the slice is "put into" the data pipe. + EndWriteData(numBytesWritten int) MojoResult } type dataPipeConsumer struct { @@ -49,6 +102,19 @@ func (h *dataPipeConsumer) ReadData(flags MojoReadDataFlags) (MojoResult, []byte return MojoResult(result), data } +func (h *dataPipeConsumer) BeginReadData(numBytes int, flags MojoReadDataFlags) (MojoResult, []byte) { + cParams := C.MallocTwoPhaseActionParams() + defer C.FreeTwoPhaseActionParams(cParams) + *cParams.num_bytes = C.uint32_t(numBytes) + result := C.MojoBeginReadData(h.mojoHandle.cValue(), cParams.buffer, cParams.num_bytes, flags.cValue()) + buffer := unsafeByteSlice(unsafe.Pointer(*cParams.buffer), int(*cParams.num_bytes)) + return MojoResult(result), buffer +} + +func (h *dataPipeConsumer) EndReadData(numBytesRead int) MojoResult { + return MojoResult(C.MojoEndReadData(h.mojoHandle.cValue(), C.uint32_t(numBytesRead))) +} + type dataPipeProducer struct { baseHandle } @@ -62,3 +128,16 @@ func (h *dataPipeProducer) WriteData(data []byte, flags MojoWriteDataFlags) (Moj result := C.MojoWriteData(h.mojoHandle.cValue(), cParams.elements, cParams.num_bytes, flags.cValue()) return MojoResult(result), int(*cParams.num_bytes) } + +func (h *dataPipeProducer) BeginWriteData(numBytes int, flags MojoWriteDataFlags) (MojoResult, []byte) { + cParams := C.MallocTwoPhaseActionParams() + defer C.FreeTwoPhaseActionParams(cParams) + *cParams.num_bytes = C.uint32_t(numBytes) + result := C.MojoBeginWriteData(h.mojoHandle.cValue(), cParams.buffer, cParams.num_bytes, flags.cValue()) + buffer := unsafeByteSlice(unsafe.Pointer(*cParams.buffer), int(*cParams.num_bytes)) + return MojoResult(result), buffer +} + +func (h *dataPipeProducer) EndWriteData(numBytesWritten int) MojoResult { + return MojoResult(C.MojoEndWriteData(h.mojoHandle.cValue(), C.uint32_t(numBytesWritten))) +} diff --git a/third_party/mojo/src/mojo/public/interfaces/application/application.mojom b/third_party/mojo/src/mojo/public/interfaces/application/application.mojom index d389ae2..b1508a8e 100644 --- a/third_party/mojo/src/mojo/public/interfaces/application/application.mojom +++ b/third_party/mojo/src/mojo/public/interfaces/application/application.mojom @@ -6,19 +6,39 @@ module mojo; import "mojo/public/interfaces/application/service_provider.mojom"; -// Applications vend Services through the ServiceProvider interface. Services -// implement Interfaces. +// This is the primary interface implemented by every Mojo application. It +// allows the application to receive its startup arguments from the shell, and +// to be notified of events that occur during its execution. interface Application { - // Initialize is guaranteed to be called before any AcceptConnection calls. + // Initializes the application with the specified arguments. This method is + // guaranteed to be called before any other method is called, and will only be + // called once. Initialize(array<string>? args); - // Called in response to a call to mojo.Shell.ConnectToApplication(). - // The |services| and |exposed_services| parameters are the same as those on - // mojo.Shell.ConnectToApplication(). - // |services| will be used to look up services provided by this application. - // |exposed_services| can be used to look up services exposed by the - // application at |requestor_url|. + // Called when another application (identified by |requestor_url|) attempts to + // open a connection to this application. + // + // If the other application wants to request services from this application, + // it will have passed a valid interface request through the |services| + // parameter (i.e. one containing a valid message pipe endpoint). This + // application may then bind an implementation of |ServiceProvider| to that + // request in order to make services available to the other application. + // + // If the other application wants to offer services to this application, it + // will have passed a bound interface through the |exposed_services| + // parameter. This application may then request services through that + // interface. + // + // It is possible that both parameters will be valid/bound if the other + // application wants to both request services from and offer services to this + // application. + // + // This application is free to ignore the |services| or |exposed_services| + // parameters if it does not wish to offer or request services. AcceptConnection(string requestor_url, ServiceProvider&? services, ServiceProvider? exposed_services); + + // Called to request the application shut itself down gracefully. + RequestQuit(); }; diff --git a/third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom b/third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom index b862d35..8c81879 100644 --- a/third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom +++ b/third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom @@ -4,11 +4,14 @@ module mojo; -// ServiceProvider is used to establish connections to services in a bi- -// directional fashion between two applications. -[Client=ServiceProvider] +// An interface through which a client may request services from a host. +// Instances of this interface are created within the context of an +// already-identified client and host pair, so there is no need to explicitly +// identify the client or host in the methods below. interface ServiceProvider { - // Connect the given message pipe handle to the named service. If the named - // service does not exist, then the handle will be closed. + // Asks the host to provide the service identified by |interface_name| through + // the message |pipe| endpoint supplied by the caller. If the host is not + // willing or able to provide the requested service, it should close the + // |pipe|. ConnectToService(string interface_name, handle<message_pipe> pipe); }; diff --git a/third_party/mojo/src/mojo/public/interfaces/application/shell.mojom b/third_party/mojo/src/mojo/public/interfaces/application/shell.mojom index 1adf1e6..7804b9f 100644 --- a/third_party/mojo/src/mojo/public/interfaces/application/shell.mojom +++ b/third_party/mojo/src/mojo/public/interfaces/application/shell.mojom @@ -7,14 +7,33 @@ module mojo; import "mojo/public/interfaces/application/application.mojom"; import "mojo/public/interfaces/application/service_provider.mojom"; -// The Shell is the finder and launcher of Applications. An Application uses -// it's Shell interface to connect to other Applications. +// An interface through which a Mojo application may communicate with the Mojo +// system and request connections to other applications. [Client=Application] interface Shell { - // Loads |application_url|. mojo:{service} will result in the user of the value of the - // --origin flag to the shell being used. - // |services| can be used to look up services provided by the application at |application_url|. - // |exposed_services| can be used to expose services to the application at |application_url|. + // Establishes a connection with another application (identified by + // |application_url|) through which the calling application and the other + // application may request services from one another. + // + // If the calling application would like to request services from the other + // application, it should pass a valid interface request in the |services| + // parameter (i.e. one containing a valid message pipe endpoint). If the other + // application does not wish to offer services, it may either not bind an + // implementation to the interface request, or else bind an implementation + // that will reject some or all service requests. + // + // If the calling application would like to offer services to the other + // application, it should pass a bound interface through the + // |exposed_services| parameter. The other application may then request + // services through that interface. + // + // At least one of |services| or |exposed_services| should be valid/bound in + // the call. + // + // If the |application_url| does not contain a domain, but is of the form + // "mojo:{service}", it is up to the Mojo shell to select an appropriate + // application for the service. Currently, the shell does this based on the + // value of its --origin flag. ConnectToApplication(string application_url, ServiceProvider&? services, ServiceProvider? exposed_services); diff --git a/third_party/mojo/src/mojo/public/mojo.gni b/third_party/mojo/src/mojo/public/mojo.gni index b310260..b87c463 100644 --- a/third_party/mojo/src/mojo/public/mojo.gni +++ b/third_party/mojo/src/mojo/public/mojo.gni @@ -6,9 +6,6 @@ declare_args() { # Whether to use a prebuilt mojo_shell binary instead of one built from # source. use_prebuilt_mojo_shell = false - - # Whether to build the dart bindings. - mojo_use_dart = false } # The absolute path to the directory containing the mojo public SDK (i.e., the diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl index d9fee1c..0289345 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl @@ -79,7 +79,10 @@ class {{interface|name}}Client extends bindings.Client with {{interface|name}}Ca } } - +{#--- TODO(zra): Remove Interface suffix from the name of this class. + This is tricky because some mojom files have interfaces named both + X and XClient. This leads to an XClient for the Client of X, and an + XClient for the Interface of XClient, which conflict with eachother. #} class {{interface|name}}Interface extends bindings.Interface {% if interface.client != None -%} with {{imported_from[interface.client]}}{{interface.client|upper_camel_case}}Calls @@ -114,16 +117,29 @@ with {{imported_from[interface.client]}}{{interface.client|upper_camel_case}}Cal } {%- else %} {%- set response_struct = method|response_struct_from_method %} + {{response_struct|name}} _{{response_struct|name}}Factory( + {%- for param in method.response_parameters -%} + {{param.kind|dart_type}} {{param|name}}{% if not loop.last %}, {% endif %} + {%- endfor -%} + ) { + var result = new {{response_struct|name}}(); + {%- for param in method.response_parameters %} + result.{{param|name}} = {{param|name}}; + {%- endfor %} + return result; + } + Future<{{response_struct|name}}> {{method|name}}( {%- for parameter in method.parameters -%} - {{parameter.kind|dart_type}} {{parameter|name}}{% if not loop.last %}, {% endif %} + {{parameter.kind|dart_type}} {{parameter|name}}, {%- endfor -%} - ) { + Function responseFactory) { assert(_delegate != null); return _delegate.{{method|name}}( {%- for parameter in method.parameters -%} - {{parameter|name}}{% if not loop.last %}, {% endif %} - {%- endfor %}); + {{parameter|name}}, + {%- endfor %} + responseFactory); } {%- endif %} {%- endfor %} @@ -142,11 +158,12 @@ with {{imported_from[interface.client]}}{{interface.client|upper_camel_case}}Cal {%- endfor -%} ); {%- else %} +{%- set response_struct = method|response_struct_from_method %} return {{method|name}}( {%- for parameter in method.parameters -%} - params.{{parameter|name}}{% if not loop.last %}, {% endif %} + params.{{parameter|name}}, {%- endfor -%} - ).then((response) { + _{{response_struct|name}}Factory).then((response) { if (response != null) { return buildResponseWithId( response, diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_dart_generator.py b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_dart_generator.py index 893e665..9862943 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_dart_generator.py +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_dart_generator.py @@ -121,8 +121,8 @@ _spec_to_encode_method = { def GetDartType(kind): if kind.imported_from: - return kind.imported_from["unique_name"] + "." + kind.name - return kind.name + return kind.imported_from["unique_name"] + "." + GetNameForElement(kind) + return GetNameForElement(kind) def DartDefaultValue(field): if field.default: |