blob: 5e008390acdcf6d2530b835e27aa314c5779f9ee [file] [log] [blame]
// Copyright 2017 The Chromium OS 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 "midis/daemon.h"
#include <fcntl.h>
#include <memory>
#include <utility>
#include <base/bind.h>
#include <base/files/file_util.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/bus.h>
#include <dbus/message.h>
#include "midis/client_tracker.h"
#include "midis/device_tracker.h"
namespace midis {
Daemon::Daemon()
: device_tracker_(std::make_unique<DeviceTracker>()),
client_tracker_(std::make_unique<ClientTracker>()),
weak_factory_(this) {}
Daemon::~Daemon() {}
int Daemon::OnInit() {
if (!device_tracker_->InitDeviceTracker()) {
return -1;
}
// It's OK to set |device_tracker_| here because the D-Bus connection
// has not yet been initialized, so it is impossible for clients to be
// registered.
client_tracker_->SetDeviceTracker(device_tracker_.get());
client_tracker_->InitClientTracker();
InitDBus();
return 0;
}
void Daemon::InitDBus() {
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SYSTEM;
scoped_refptr<dbus::Bus> bus(new dbus::Bus(options));
CHECK(bus->Connect());
dbus::ExportedObject* exported_object =
bus->GetExportedObject(dbus::ObjectPath(kMidisServicePath));
CHECK(exported_object);
CHECK(exported_object->ExportMethodAndBlock(
kMidisInterfaceName, kBootstrapMojoConnectionMethod,
base::Bind(&Daemon::BootstrapMojoConnection,
weak_factory_.GetWeakPtr())));
CHECK(bus->RequestOwnershipAndBlock(kMidisServiceName,
dbus::Bus::REQUIRE_PRIMARY));
VLOG(1) << "D-Bus Registration succeeded";
}
void Daemon::BootstrapMojoConnection(
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender) {
LOG(INFO) << "Successfully received call from D-Bus client.";
if (client_tracker_->IsProxyConnected()) {
LOG(WARNING) << "Midis can only instantiate one Mojo Proxy instance.";
return;
}
base::ScopedFD file_handle;
dbus::MessageReader reader(method_call);
if (!reader.PopFileDescriptor(&file_handle)) {
LOG(ERROR) << "Couldn't extract Mojo IPC handle.";
return;
}
if (!file_handle.is_valid()) {
LOG(ERROR) << "Couldn't get file handle sent over D-Bus.";
return;
}
if (!base::SetCloseOnExec(file_handle.get())) {
PLOG(ERROR) << "Failed setting FD_CLOEXEC on fd.";
return;
}
client_tracker_->AcceptProxyConnection(std::move(file_handle));
LOG(INFO) << "MojoBridger connection established.";
std::unique_ptr<dbus::Response> response =
dbus::Response::FromMethodCall(method_call);
std::move(response_sender).Run(std::move(response));
}
} // namespace midis