summaryrefslogtreecommitdiffstats
path: root/mojo/dbus
diff options
context:
space:
mode:
authorcmasone@chromium.org <cmasone@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-01 23:30:06 +0000
committercmasone@chromium.org <cmasone@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-01 23:30:06 +0000
commit8110218d6bbce9092fe3afc2d683af735d8909ba (patch)
treeffddd7a74d4f16e6cb9b0cddb7f7cc973783b573 /mojo/dbus
parenta0a380053dd2697c893bc9b42e04ac07193f588f (diff)
downloadchromium_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/DEPS4
-rw-r--r--mojo/dbus/dbus_external_service.cc95
-rw-r--r--mojo/dbus/dbus_external_service.h85
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