blob: 46a8d7fbf086adf58d4625652dce777ab2d52af3 [file] [log] [blame]
// Copyright 2021 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 "rmad/system/cros_disks_client_impl.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <base/bind.h>
#include <base/callback.h>
#include <base/logging.h>
#include <base/memory/scoped_refptr.h>
#include <brillo/variant_dictionary.h>
#include <dbus/bus.h>
#include <dbus/cros-disks/dbus-constants.h>
#include <dbus/message.h>
#include <dbus/object_proxy.h>
namespace {
void OnSignalConnected(const std::string& interface,
const std::string& signal,
bool succeeded) {
if (!succeeded) {
LOG(ERROR) << "Failed to connect to " << interface << " " << signal;
} else {
VLOG(1) << "Connected to " << interface << " " << signal;
}
}
void OnMountCompleted(
base::RepeatingCallback<void(const rmad::MountEntry&)> callback,
dbus::Signal* signal) {
VLOG(1) << "Get signal MountCompleted";
dbus::MessageReader reader(signal);
uint32_t error_type;
std::string source;
uint32_t source_type;
std::string mount_path;
rmad::MountEntry entry;
if (reader.PopUint32(&error_type) && reader.PopString(&source) &&
reader.PopUint32(&source_type) && reader.PopString(&mount_path)) {
VLOG(1) << "Mount succeeds";
entry.success = (error_type == cros_disks::MOUNT_ERROR_NONE);
entry.source = source;
entry.mount_path = mount_path;
} else {
VLOG(1) << "Mount failed";
entry.success = false;
}
std::move(callback).Run(entry);
}
} // namespace
namespace rmad {
CrosDisksClientImpl::CrosDisksClientImpl(const scoped_refptr<dbus::Bus>& bus) {
proxy_ =
bus->GetObjectProxy(cros_disks::kCrosDisksServiceName,
dbus::ObjectPath(cros_disks::kCrosDisksServicePath));
}
bool CrosDisksClientImpl::EnumerateDevices(std::vector<std::string>* devices) {
CHECK(devices);
dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
cros_disks::kEnumerateDevices);
std::unique_ptr<dbus::Response> response = proxy_->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
if (!response.get()) {
LOG(ERROR) << "Failed to call cros-disks D-Bus service";
return false;
}
dbus::MessageReader reader(response.get());
if (!reader.PopArrayOfStrings(devices)) {
LOG(ERROR) << "Failed to decode cros-disks response";
return false;
}
return true;
}
bool CrosDisksClientImpl::GetDeviceProperties(
const std::string& device, DeviceProperties* device_properties) {
CHECK(device_properties);
dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
cros_disks::kGetDeviceProperties);
dbus::MessageWriter writer(&method_call);
writer.AppendString(device);
std::unique_ptr<dbus::Response> response = proxy_->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
if (!response.get()) {
LOG(ERROR) << "Failed to call cros-disks D-Bus service";
return false;
}
dbus::MessageReader reader(response.get());
brillo::VariantDictionary properties;
if (!brillo::dbus_utils::PopValueFromReader(&reader, &properties)) {
LOG(ERROR) << "Failed to decode cros-disks response";
return false;
}
device_properties->device_file =
properties[cros_disks::kDeviceFile].TryGet<std::string>();
device_properties->is_on_removable_device =
properties[cros_disks::kDeviceIsOnRemovableDevice].TryGet<bool>();
device_properties->is_auto_mountable =
properties[cros_disks::kIsAutoMountable].TryGet<bool>();
return true;
}
void CrosDisksClientImpl::AddMountCompletedHandler(
base::RepeatingCallback<void(const MountEntry&)> callback) {
proxy_->ConnectToSignal(cros_disks::kCrosDisksInterface,
cros_disks::kMountCompleted,
base::BindRepeating(&OnMountCompleted, callback),
base::BindOnce(&OnSignalConnected));
}
void CrosDisksClientImpl::Mount(const std::string& source,
const std::string& filesystem_type,
const std::vector<std::string>& options) {
dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
cros_disks::kMount);
dbus::MessageWriter writer(&method_call);
writer.AppendString(source);
writer.AppendString(filesystem_type);
writer.AppendArrayOfStrings(options);
// No response from Mount method_call. cros-disks emits a |MountCompleted|
// signal when the mount is done.
proxy_->CallMethodAndBlock(&method_call,
dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
}
bool CrosDisksClientImpl::Unmount(const std::string& path,
const std::vector<std::string>& options,
uint32_t* result) {
CHECK(result);
dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
cros_disks::kUnmount);
dbus::MessageWriter writer(&method_call);
writer.AppendString(path);
writer.AppendArrayOfStrings(options);
std::unique_ptr<dbus::Response> response = proxy_->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
if (!response.get()) {
LOG(ERROR) << "Failed to call cros-disks D-Bus service";
return false;
}
dbus::MessageReader reader(response.get());
if (!reader.PopUint32(result)) {
LOG(ERROR) << "Failed to decode cros-disks response";
return false;
}
return true;
}
} // namespace rmad