// 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()); 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