1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "mojo/dbus/dbus_external_service.h" 6 7#include "base/bind.h" 8#include "base/callback.h" 9#include "base/logging.h" 10#include "base/memory/scoped_ptr.h" 11#include "base/message_loop/message_loop_proxy.h" 12#include "dbus/bus.h" 13#include "dbus/exported_object.h" 14#include "dbus/file_descriptor.h" 15#include "dbus/message.h" 16#include "dbus/object_path.h" 17#include "mojo/embedder/channel_init.h" 18#include "mojo/public/cpp/bindings/error_handler.h" 19#include "mojo/shell/external_service.mojom.h" 20 21namespace mojo { 22 23DBusExternalServiceBase::DBusExternalServiceBase( 24 const std::string& service_name) 25 : service_name_(service_name), 26 exported_object_(NULL) { 27} 28DBusExternalServiceBase::~DBusExternalServiceBase() {} 29 30void DBusExternalServiceBase::Start() { 31 InitializeDBus(); 32 ExportMethods(); 33 TakeDBusServiceOwnership(); 34 DVLOG(1) << "External service started"; 35} 36 37void DBusExternalServiceBase::ConnectChannel( 38 dbus::MethodCall* method_call, 39 dbus::ExportedObject::ResponseSender sender) { 40 dbus::MessageReader reader(method_call); 41 dbus::FileDescriptor wrapped_fd; 42 if (!reader.PopFileDescriptor(&wrapped_fd)) { 43 sender.Run( 44 dbus::ErrorResponse::FromMethodCall( 45 method_call, 46 "org.chromium.Mojo.BadHandle", 47 "Invalid FD.").PassAs<dbus::Response>()); 48 return; 49 } 50 wrapped_fd.CheckValidity(); 51 channel_init_.reset(new mojo::embedder::ChannelInit); 52 mojo::ScopedMessagePipeHandle message_pipe = 53 channel_init_->Init(wrapped_fd.TakeValue(), 54 base::MessageLoopProxy::current()); 55 CHECK(message_pipe.is_valid()); 56 57 Connect(message_pipe.Pass()); 58 sender.Run(dbus::Response::FromMethodCall(method_call)); 59} 60 61void DBusExternalServiceBase::ExportMethods() { 62 CHECK(exported_object_); 63 CHECK(exported_object_->ExportMethodAndBlock( 64 kMojoDBusInterface, kMojoDBusConnectMethod, 65 base::Bind(&DBusExternalServiceBase::ConnectChannel, 66 base::Unretained(this)))); 67} 68 69void DBusExternalServiceBase::InitializeDBus() { 70 CHECK(!bus_.get()); 71 dbus::Bus::Options options; 72 options.bus_type = dbus::Bus::SESSION; 73 bus_ = new dbus::Bus(options); 74 CHECK(bus_->Connect()); 75 CHECK(bus_->SetUpAsyncOperations()); 76 77 exported_object_ = 78 bus_->GetExportedObject(dbus::ObjectPath(kMojoDBusImplPath)); 79} 80 81void DBusExternalServiceBase::TakeDBusServiceOwnership() { 82 CHECK(bus_->RequestOwnershipAndBlock( 83 service_name_, 84 dbus::Bus::REQUIRE_PRIMARY_ALLOW_REPLACEMENT)) 85 << "Unable to take ownership of " << service_name_; 86} 87 88} // namespace mojo 89