1010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// found in the LICENSE file.
4010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
5010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "mojo/dbus/dbus_external_service.h"
6010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
7010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/bind.h"
8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/callback.h"
9010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/logging.h"
10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "dbus/bus.h"
13010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "dbus/exported_object.h"
14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "dbus/file_descriptor.h"
15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "dbus/message.h"
16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "dbus/object_path.h"
176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "mojo/embedder/channel_init.h"
18010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "mojo/public/cpp/bindings/error_handler.h"
19010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "mojo/shell/external_service.mojom.h"
20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
21010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace mojo {
22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)DBusExternalServiceBase::DBusExternalServiceBase(
24010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::string& service_name)
25010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    : service_name_(service_name),
26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      exported_object_(NULL) {
27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)DBusExternalServiceBase::~DBusExternalServiceBase() {}
29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DBusExternalServiceBase::Start() {
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  InitializeDBus();
32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ExportMethods();
33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  TakeDBusServiceOwnership();
34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DVLOG(1) << "External service started";
35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DBusExternalServiceBase::ConnectChannel(
38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    dbus::MethodCall* method_call,
39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    dbus::ExportedObject::ResponseSender sender) {
40010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  dbus::MessageReader reader(method_call);
41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  dbus::FileDescriptor wrapped_fd;
42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!reader.PopFileDescriptor(&wrapped_fd)) {
43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    sender.Run(
44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        dbus::ErrorResponse::FromMethodCall(
45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            method_call,
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            "org.chromium.Mojo.BadHandle",
47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            "Invalid FD.").PassAs<dbus::Response>());
48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  wrapped_fd.CheckValidity();
516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  channel_init_.reset(new mojo::embedder::ChannelInit);
52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  mojo::ScopedMessagePipeHandle message_pipe =
53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      channel_init_->Init(wrapped_fd.TakeValue(),
54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                          base::MessageLoopProxy::current());
55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CHECK(message_pipe.is_valid());
56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
570de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  Connect(message_pipe.Pass());
58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  sender.Run(dbus::Response::FromMethodCall(method_call));
59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DBusExternalServiceBase::ExportMethods() {
62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CHECK(exported_object_);
63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CHECK(exported_object_->ExportMethodAndBlock(
64010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      kMojoDBusInterface, kMojoDBusConnectMethod,
65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&DBusExternalServiceBase::ConnectChannel,
66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 base::Unretained(this))));
67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DBusExternalServiceBase::InitializeDBus() {
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(!bus_.get());
71010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  dbus::Bus::Options options;
72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  options.bus_type = dbus::Bus::SESSION;
73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  bus_ = new dbus::Bus(options);
74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CHECK(bus_->Connect());
75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CHECK(bus_->SetUpAsyncOperations());
76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  exported_object_ =
78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      bus_->GetExportedObject(dbus::ObjectPath(kMojoDBusImplPath));
79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DBusExternalServiceBase::TakeDBusServiceOwnership() {
82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CHECK(bus_->RequestOwnershipAndBlock(
83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      service_name_,
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      dbus::Bus::REQUIRE_PRIMARY_ALLOW_REPLACEMENT))
85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      << "Unable to take ownership of " << service_name_;
86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
88010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}  // namespace mojo
89