diff options
author | cmasone@chromium.org <cmasone@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-01 23:30:06 +0000 |
---|---|---|
committer | cmasone@chromium.org <cmasone@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-01 23:30:06 +0000 |
commit | 8110218d6bbce9092fe3afc2d683af735d8909ba (patch) | |
tree | ffddd7a74d4f16e6cb9b0cddb7f7cc973783b573 /mojo/dbus | |
parent | a0a380053dd2697c893bc9b42e04ac07193f588f (diff) | |
download | chromium_src-8110218d6bbce9092fe3afc2d683af735d8909ba.zip chromium_src-8110218d6bbce9092fe3afc2d683af735d8909ba.tar.gz chromium_src-8110218d6bbce9092fe3afc2d683af735d8909ba.tar.bz2 |
Generalize DBus-Mojo bootstrapping code
Most of the code to bootstrap a Mojo service over DBus is
moved into a templated class under mojo/dbus. Simply implement your Mojo service
and then specialize DBusExternalService with your service implementation.
TBR=darin@chromium.org
BUG=chromium:367816
TEST=run mojo_dbus_echo_service in one shell, and then ./out/Debug/mojo_shell --origin=http://127.0.0.1:4444 --disable-cache mojo:mojo_dbus_echo in the other.
Review URL: https://codereview.chromium.org/245253004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@267662 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'mojo/dbus')
-rw-r--r-- | mojo/dbus/DEPS | 4 | ||||
-rw-r--r-- | mojo/dbus/dbus_external_service.cc | 95 | ||||
-rw-r--r-- | mojo/dbus/dbus_external_service.h | 85 |
3 files changed, 184 insertions, 0 deletions
diff --git a/mojo/dbus/DEPS b/mojo/dbus/DEPS new file mode 100644 index 0000000..0abf683 --- /dev/null +++ b/mojo/dbus/DEPS @@ -0,0 +1,4 @@ +include_rules = [ + "+base", + "+dbus", +] diff --git a/mojo/dbus/dbus_external_service.cc b/mojo/dbus/dbus_external_service.cc new file mode 100644 index 0000000..3a13cf7 --- /dev/null +++ b/mojo/dbus/dbus_external_service.cc @@ -0,0 +1,95 @@ +// 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/dbus/dbus_external_service.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop_proxy.h" +#include "dbus/bus.h" +#include "dbus/exported_object.h" +#include "dbus/file_descriptor.h" +#include "dbus/message.h" +#include "dbus/object_path.h" +#include "mojo/common/channel_init.h" +#include "mojo/public/cpp/bindings/error_handler.h" +#include "mojo/public/cpp/bindings/remote_ptr.h" +#include "mojo/public/cpp/shell/application.h" +#include "mojo/public/interfaces/shell/shell.mojom.h" +#include "mojo/shell/external_service.mojom.h" + +namespace mojo { + +DBusExternalServiceBase::DBusExternalServiceBase( + const std::string& service_name) + : service_name_(service_name), + exported_object_(NULL) { +} +DBusExternalServiceBase::~DBusExternalServiceBase() {} + +void DBusExternalServiceBase::Start() { + InitializeDBus(); + ExportMethods(); + TakeDBusServiceOwnership(); + DVLOG(1) << "External service started"; +} + +void DBusExternalServiceBase::OnError() { + Disconnect(); +} + +void DBusExternalServiceBase::ConnectChannel( + dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender sender) { + dbus::MessageReader reader(method_call); + dbus::FileDescriptor wrapped_fd; + if (!reader.PopFileDescriptor(&wrapped_fd)) { + sender.Run( + dbus::ErrorResponse::FromMethodCall( + method_call, + "org.chromium.Mojo.BadHandle", + "Invalid FD.").PassAs<dbus::Response>()); + return; + } + wrapped_fd.CheckValidity(); + channel_init_.reset(new mojo::common::ChannelInit); + mojo::ScopedMessagePipeHandle message_pipe = + channel_init_->Init(wrapped_fd.TakeValue(), + base::MessageLoopProxy::current()); + CHECK(message_pipe.is_valid()); + + Connect(mojo::ScopedExternalServiceHostHandle::From(message_pipe.Pass())); + sender.Run(dbus::Response::FromMethodCall(method_call)); +} + +void DBusExternalServiceBase::ExportMethods() { + CHECK(exported_object_); + CHECK(exported_object_->ExportMethodAndBlock( + kMojoDBusInterface, kMojoDBusConnectMethod, + base::Bind(&DBusExternalServiceBase::ConnectChannel, + base::Unretained(this)))); +} + +void DBusExternalServiceBase::InitializeDBus() { + CHECK(!bus_); + dbus::Bus::Options options; + options.bus_type = dbus::Bus::SESSION; + bus_ = new dbus::Bus(options); + CHECK(bus_->Connect()); + CHECK(bus_->SetUpAsyncOperations()); + + exported_object_ = + bus_->GetExportedObject(dbus::ObjectPath(kMojoDBusImplPath)); +} + +void DBusExternalServiceBase::TakeDBusServiceOwnership() { + CHECK(bus_->RequestOwnershipAndBlock( + service_name_, + dbus::Bus::REQUIRE_PRIMARY_ALLOW_REPLACEMENT)) + << "Unable to take ownership of " << service_name_; +} + +} // namespace mojo diff --git a/mojo/dbus/dbus_external_service.h b/mojo/dbus/dbus_external_service.h new file mode 100644 index 0000000..1a33c4c7 --- /dev/null +++ b/mojo/dbus/dbus_external_service.h @@ -0,0 +1,85 @@ +// 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 "base/memory/scoped_ptr.h" +#include "dbus/bus.h" +#include "dbus/exported_object.h" +#include "dbus/message.h" +#include "dbus/object_path.h" +#include "mojo/common/channel_init.h" +#include "mojo/public/cpp/bindings/interface.h" +#include "mojo/public/cpp/bindings/remote_ptr.h" +#include "mojo/public/cpp/shell/application.h" +#include "mojo/public/interfaces/shell/shell.mojom.h" +#include "mojo/shell/external_service.mojom.h" + +namespace mojo { +const char kMojoDBusImplPath[] = "/org/chromium/MojoImpl"; +const char kMojoDBusInterface[] = "org.chromium.Mojo"; +const char kMojoDBusConnectMethod[] = "ConnectChannel"; + +class DBusExternalServiceBase : public mojo::ErrorHandler { + public: + explicit DBusExternalServiceBase(const std::string& service_name); + virtual ~DBusExternalServiceBase(); + + void Start(); + + protected: + // TODO(cmasone): Enable multiple peers to connect/disconnect + virtual void Connect(ScopedExternalServiceHostHandle client_handle) = 0; + virtual void Disconnect() = 0; + + private: + virtual void OnError() OVERRIDE; + + // Implementation of org.chromium.Mojo.ConnectChannel, exported over DBus. + // Takes a file descriptor and uses it to create a MessagePipe that is then + // hooked to a RemotePtr<mojo::ExternalServiceHost>. + void ConnectChannel(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender sender); + + void ExportMethods(); + void InitializeDBus(); + void TakeDBusServiceOwnership(); + + const std::string service_name_; + scoped_refptr<dbus::Bus> bus_; + dbus::ExportedObject* exported_object_; // Owned by bus_; + scoped_ptr<mojo::common::ChannelInit> channel_init_; + DISALLOW_COPY_AND_ASSIGN(DBusExternalServiceBase); +}; + +template <class ServiceImpl> +class DBusExternalService : public DBusExternalServiceBase, + public mojo::ExternalService { + public: + explicit DBusExternalService(const std::string& service_name) + : DBusExternalServiceBase(service_name) { + } + virtual ~DBusExternalService() {} + + protected: + virtual void Connect(ScopedExternalServiceHostHandle client_handle) OVERRIDE { + external_service_host_.reset(client_handle.Pass(), this, this); + } + + virtual void Disconnect() OVERRIDE { + app_.reset(); + external_service_host_.reset(); + } + + private: + virtual void Activate(mojo::ScopedMessagePipeHandle client_handle) OVERRIDE { + mojo::ScopedShellHandle shell_handle( + mojo::ShellHandle(client_handle.release().value())); + app_.reset(new mojo::Application(shell_handle.Pass())); + app_->AddServiceConnector(new mojo::ServiceConnector<ServiceImpl>()); + } + + mojo::RemotePtr<mojo::ExternalServiceHost> external_service_host_; + scoped_ptr<mojo::Application> app_; +}; + +} // namespace mojo |