Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Unified Diff: chrome/browser/chromeos/dbus/cros_disks_client.cc

Issue 8499007: Add CrosDisksClient (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix to please clang Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/dbus/cros_disks_client.cc
diff --git a/chrome/browser/chromeos/dbus/cros_disks_client.cc b/chrome/browser/chromeos/dbus/cros_disks_client.cc
new file mode 100644
index 0000000000000000000000000000000000000000..5a27883f540ac26112df0b53c13717c0539482e2
--- /dev/null
+++ b/chrome/browser/chromeos/dbus/cros_disks_client.cc
@@ -0,0 +1,531 @@
+// Copyright (c) 2011 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 "chrome/browser/chromeos/dbus/cros_disks_client.h"
+
+#include "base/bind.h"
+#include "base/memory/scoped_vector.h"
+#include "chrome/browser/chromeos/system/runtime_environment.h"
+#include "dbus/bus.h"
+#include "dbus/message.h"
+#include "dbus/object_proxy.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace chromeos {
+
+namespace {
+
+const char* kDefaultMountOptions[] = {
+ "rw",
+ "nodev",
+ "noexec",
+ "nosuid",
+ "sync"
satorux1 2011/11/11 19:01:48 you might want to add ,
hashimoto 2011/11/14 13:52:45 Done.
+};
+
+const char* kDefaultUnmountOptions[] = {
+ "force"
satorux1 2011/11/11 19:01:48 ditto.
hashimoto 2011/11/14 13:52:45 Done.
+};
+
+// Returns the device type from the given arguments.
+DeviceType GetDeviceType(bool is_optical, bool is_rotational) {
+ if (is_optical)
+ return OPTICAL;
+ if (is_rotational)
+ return HDD;
+ return FLASH;
+}
+
+// Pops a bool value when |reader| is not NULL.
+// Returns true when a value is popped, false otherwise.
+bool MaybePopBool(dbus::MessageReader* reader, bool* value) {
+ if (!reader)
+ return false;
+ return reader->PopBool(value);
+}
+
+// Pops a string value when |reader| is not NULL.
+// Returns true when a value is popped, false otherwise.
+bool MaybePopString(dbus::MessageReader* reader, std::string* value) {
+ if (!reader)
+ return false;
+ return reader->PopString(value);
+}
+
+// Pops a uint64 value when |reader| is not NULL.
+// Returns true when a value is popped, false otherwise.
+bool MaybePopUint64(dbus::MessageReader* reader, uint64* value) {
+ if (!reader)
+ return false;
+ return reader->PopUint64(value);
+}
+
+// Pops an array of strings when |reader| is not NULL.
+// Returns true when an array is popped, false otherwise.
+bool MaybePopArrayOfStrings(dbus::MessageReader* reader,
+ std::vector<std::string>* value) {
+ if (!reader)
+ return false;
+ return reader->PopArrayOfStrings(value);
+}
+
+// The CrosDisksClient implementation
+class CrosDisksClientImpl : public CrosDisksClient {
+ public:
+ explicit CrosDisksClientImpl(dbus::Bus* bus)
+ : proxy_(bus->GetObjectProxy(cros_disks::kCrosDisksServiceName,
+ cros_disks::kCrosDisksServicePath)),
+ weak_ptr_factory_(this) {
+ }
+
+ virtual void Mount(const std::string& source_path,
satorux1 2011/11/11 19:01:48 // CrosDisksClient override.
hashimoto 2011/11/14 13:52:45 Done.
+ MountType type,
+ MountCallback callback,
+ ErrorCallback error_callback) OVERRIDE {
+ dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
+ cros_disks::kMount);
+ dbus::MessageWriter writer(&method_call);
+ writer.AppendString(source_path);
+ writer.AppendString(""); // auto detect filesystem.
+ std::vector<std::string> mount_options(kDefaultMountOptions,
+ kDefaultMountOptions +
+ arraysize(kDefaultMountOptions));
+ writer.AppendArrayOfStrings(mount_options);
+ proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+ base::Bind(&CrosDisksClientImpl::OnMount,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback,
+ error_callback));
+ }
+
+ virtual void Unmount(const std::string& device_path,
+ UnmountCallback callback,
+ ErrorCallback error_callback) OVERRIDE {
+ dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
+ cros_disks::kUnmount);
+ dbus::MessageWriter writer(&method_call);
+ writer.AppendString(device_path);
+ std::vector<std::string> unmount_options(kDefaultUnmountOptions,
+ kDefaultUnmountOptions +
+ arraysize(kDefaultUnmountOptions));
+ writer.AppendArrayOfStrings(unmount_options);
+ proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+ base::Bind(&CrosDisksClientImpl::OnUnmount,
+ weak_ptr_factory_.GetWeakPtr(),
+ device_path,
+ callback,
+ error_callback));
+ }
+
+ virtual void EnumerateAutoMountableDevices(
+ EnumerateAutoMountableDevicesCallback callback,
+ ErrorCallback error_callback) OVERRIDE {
+ dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
+ cros_disks::kEnumerateAutoMountableDevices);
+ proxy_->CallMethod(
+ &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+ base::Bind(&CrosDisksClientImpl::OnEnumerateAutoMountableDevices,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback,
+ error_callback));
+ }
+
+ virtual void FormatDevice(const std::string& device_path,
+ const std::string& filesystem,
+ FormatDeviceCallback callback,
+ ErrorCallback error_callback) OVERRIDE {
+ dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
+ cros_disks::kFormatDevice);
+ dbus::MessageWriter writer(&method_call);
+ writer.AppendString(device_path);
+ writer.AppendString(filesystem);
+ proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+ base::Bind(&CrosDisksClientImpl::OnFormatDevice,
+ weak_ptr_factory_.GetWeakPtr(),
+ device_path,
+ callback,
+ error_callback));
+ }
+
+ virtual void GetDeviceProperties(const std::string& device_path,
+ GetDevicePropertiesCallback callback,
+ ErrorCallback error_callback) OVERRIDE {
+ dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
+ cros_disks::kGetDeviceProperties);
+ dbus::MessageWriter writer(&method_call);
+ writer.AppendString(device_path);
+ proxy_->CallMethod(&method_call,
+ dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+ base::Bind(&CrosDisksClientImpl::OnGetDeviceProperties,
+ weak_ptr_factory_.GetWeakPtr(),
+ device_path,
+ callback,
+ error_callback));
+ }
+
+ virtual void SetUpConnections(
+ MountEventHandler mount_event_handler,
+ MountCompletedHandler mount_completed_handler) OVERRIDE {
+ static const SignalEventTuple kSignalEventTuples[] = {
+ { "DeviceAdded", DEVICE_ADDED },
+ { "DeviceScanned", DEVICE_SCANNED },
+ { "DeviceRemoved", DEVICE_REMOVED },
+ { "DiskAdded", DISK_ADDED },
+ { "DiskChanged", DISK_CHANGED },
+ { "DiskRemoved", DISK_REMOVED },
+ { "FormattingFinished", FORMATTING_FINISHED },
satorux1 2011/11/11 19:01:48 ah, signal names are hard-coded. I'll add constant
hashimoto 2011/11/14 13:52:45 OK, Thanks!
+ };
+ const size_t kNumSignalEventTuples = arraysize(kSignalEventTuples);
+
+ for (size_t i = 0; i < kNumSignalEventTuples; ++i) {
+ proxy_->ConnectToSignal(
+ cros_disks::kCrosDisksInterface,
+ kSignalEventTuples[i].signal_name,
+ base::Bind(&CrosDisksClientImpl::OnMountEvent,
+ weak_ptr_factory_.GetWeakPtr(),
+ kSignalEventTuples[i].event_type,
+ mount_event_handler),
+ base::Bind(&CrosDisksClientImpl::OnSignalConnected,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+ proxy_->ConnectToSignal(
+ cros_disks::kCrosDisksInterface,
+ "MountCompleted",
satorux1 2011/11/11 19:01:48 ditto.
+ base::Bind(&CrosDisksClientImpl::OnMountCompleted,
+ weak_ptr_factory_.GetWeakPtr(),
+ mount_completed_handler ),
+ base::Bind(&CrosDisksClientImpl::OnSignalConnected,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
+ private:
+ // A struct to contain a pair of signal name and mount event type.
+ // Used by SetUpConnections.
+ struct SignalEventTuple {
+ const char *signal_name;
+ MountEventType event_type;
+ };
+
+ // Handles the result of Mount and calls |callback| or |error_callback|
+ void OnMount(MountCallback callback,
+ ErrorCallback error_callback,
+ dbus::Response* response) {
+ if (!response) {
+ error_callback.Run();
+ return;
+ }
+ callback.Run();
+ }
+
+ // Handles the result of Unount and calls |callback| or |error_callback|
+ void OnUnmount(const std::string& device_path,
+ UnmountCallback callback,
+ ErrorCallback error_callback,
+ dbus::Response* response) {
+ if (!response) {
+ error_callback.Run();
+ return;
+ }
+ callback.Run(device_path);
+ }
+
+ // Handles the result of EnumerateAutoMountableDevices and calls |callback| or
+ // |error_callback|
+ void OnEnumerateAutoMountableDevices(
+ EnumerateAutoMountableDevicesCallback callback,
+ ErrorCallback error_callback,
+ dbus::Response* response) {
+ if (!response) {
+ error_callback.Run();
+ return;
+ }
+ dbus::MessageReader reader(response);
+ std::vector<std::string> device_paths;
+ if (!reader.PopArrayOfStrings(&device_paths)) {
+ LOG(ERROR) << "Invalid response: " << response->ToString();
+ error_callback.Run();
+ return;
+ }
+ callback.Run(device_paths);
+ }
+
+ // Handles the result of FormatDevice and calls |callback| or |error_callback|
+ void OnFormatDevice(const std::string& device_path,
+ FormatDeviceCallback callback,
+ ErrorCallback error_callback,
+ dbus::Response* response) {
+ if (!response) {
+ error_callback.Run();
+ return;
+ }
+ dbus::MessageReader reader(response);
+ bool success = false;
+ if (!reader.PopBool(&success)) {
+ LOG(ERROR) << "Invalid response: " << response->ToString();
+ error_callback.Run();
+ return;
+ }
+ callback.Run(device_path, success);
+ }
+
+ // Handles the result of GetDeviceProperties and calls |callback| or
+ // |error_callback|
+ void OnGetDeviceProperties(const std::string& device_path,
+ GetDevicePropertiesCallback callback,
+ ErrorCallback error_callback,
+ dbus::Response* response) {
+ if (!response) {
+ error_callback.Run();
+ return;
+ }
+ DiskInfo disk(device_path, response);
+ callback.Run(disk);
+ }
+
+ // Handles mount event signals and calls |handler|
+ void OnMountEvent(MountEventType event_type,
+ MountEventHandler handler,
+ dbus::Signal* signal) {
+ dbus::MessageReader reader(signal);
+ std::string device;
+ if (!reader.PopString(&device)) {
+ LOG(ERROR) << "Invalid signal: " << signal->ToString();
+ return;
+ }
+ handler.Run(event_type, device);
+ }
+
+ // Handles MountCompleted signal and calls |handler|
+ void OnMountCompleted(MountCompletedHandler handler, dbus::Signal* signal) {
+ dbus::MessageReader reader(signal);
+ unsigned int error_code = 0;
+ std::string source_path;
+ unsigned int mount_type = 0;
+ std::string mount_path;
+ if (!reader.PopUint32(&error_code) ||
+ !reader.PopString(&source_path) ||
+ !reader.PopUint32(&mount_type) ||
+ !reader.PopString(&mount_path)) {
+ LOG(ERROR) << "Invalid signal: " << signal->ToString();
+ return;
+ }
+ handler.Run(static_cast<MountError>(error_code), source_path,
+ static_cast<MountType>(mount_type), mount_path);
+ }
+
+ // Handles the result of signal connection setup.
+ void OnSignalConnected(const std::string& interface,
+ const std::string& signal,
+ bool successed) {
+ LOG_IF(ERROR, !successed) << "Connect to " << interface << " " <<
+ signal << " failed.";
+ }
+
+ dbus::ObjectProxy* proxy_;
+ base::WeakPtrFactory<CrosDisksClientImpl> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(CrosDisksClientImpl);
+};
+
+// A stub implementaion of CrosDisksClient
+class CrosDisksClientStubImpl : public CrosDisksClient {
+ public:
+ CrosDisksClientStubImpl() {}
+ virtual ~CrosDisksClientStubImpl() {}
+
+ virtual void Mount(const std::string& source_path,
+ MountType type,
+ MountCallback callback,
+ ErrorCallback error_callback) OVERRIDE {}
+ virtual void Unmount(const std::string& device_path,
+ UnmountCallback callback,
+ ErrorCallback error_callback) OVERRIDE {}
+ virtual void EnumerateAutoMountableDevices(
+ EnumerateAutoMountableDevicesCallback callback,
+ ErrorCallback error_callback) OVERRIDE {}
+ virtual void FormatDevice(const std::string& device_path,
+ const std::string& filesystem,
+ FormatDeviceCallback callback,
+ ErrorCallback error_callback) OVERRIDE {}
+ virtual void GetDeviceProperties(const std::string& device_path,
+ GetDevicePropertiesCallback callback,
+ ErrorCallback error_callback) OVERRIDE {}
+ virtual void SetUpConnections(
+ MountEventHandler mount_event_handler,
+ MountCompletedHandler mount_completed_handler) OVERRIDE {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CrosDisksClientStubImpl);
+};
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// DiskInfo
+
+DiskInfo::DiskInfo(const std::string& device_path, dbus::Response* response)
+ : device_path_(device_path),
+ is_drive_(false),
+ has_media_(false),
+ on_boot_device_(false),
+ device_type_(UNDEFINED),
+ total_size_in_bytes_(0),
+ is_read_only_(false),
+ is_hidden_(true) {
+ InitializeFromResponse(response);
+}
+
+DiskInfo::~DiskInfo() {
+}
+
+// Initialize |this| from |response| given by the cros-disks service.
+// Below is an example of |response|'s raw message (long string is ellipsized)
+//
+//
+// message_type: MESSAGE_METHOD_RETURN
+// destination: :1.8
+// sender: :1.16
+// signature: a{sv}
+// serial: 96
+// reply_serial: 267
+//
+// array [
+// dict entry {
+// string "DeviceFile"
+// variant string "/dev/sdb"
+// }
+// dict entry {
+// string "DeviceIsDrive"
+// variant bool true
+// }
+// dict entry {
+// string "DeviceIsMediaAvailable"
+// variant bool true
+// }
+// dict entry {
+// string "DeviceIsMounted"
+// variant bool false
+// }
+// dict entry {
+// string "DeviceIsOnBootDevice"
+// variant bool false
+// }
+// dict entry {
+// string "DeviceIsOpticalDisc"
+// variant bool false
+// }
+// dict entry {
+// string "DeviceIsReadOnly"
+// variant bool false
+// }
+// dict entry {
+// string "DeviceIsVirtual"
+// variant bool false
+// }
+// dict entry {
+// string "DeviceMediaType"
+// variant uint32 1
+// }
+// dict entry {
+// string "DeviceMountPaths"
+// variant array [
+// ]
+// }
+// dict entry {
+// string "DevicePresentationHide"
+// variant bool true
+// }
+// dict entry {
+// string "DeviceSize"
+// variant uint64 7998537728
+// }
+// dict entry {
+// string "DriveIsRotational"
+// variant bool false
+// }
+// dict entry {
+// string "DriveModel"
+// variant string "TransMemory"
+// }
+// dict entry {
+// string "IdLabel"
+// variant string ""
+// }
+// dict entry {
+// string "IdUuid"
+// variant string ""
+// }
+// dict entry {
+// string "NativePath"
+// variant string "/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-4/...
+// }
+// ]
+void DiskInfo::InitializeFromResponse(dbus::Response* response) {
+ dbus::MessageReader response_reader(response);
+ dbus::MessageReader array_reader(response);
+ if (!response_reader.PopArray(&array_reader)) {
+ LOG(ERROR) << "Invalid response: " << response->ToString();
+ return;
+ }
+ // TODO(satorux): Rework this code using Protocol Buffers. crosbug.com/22626
+ ScopedVector<dbus::MessageReader> value_readers_owner;
+ std::map<std::string, dbus::MessageReader*> properties;
+ while (array_reader.HasMoreData()) {
+ // |value_readers_owner| is responsible to delete |value_reader|
+ dbus::MessageReader* value_reader = new dbus::MessageReader(response);
+ value_readers_owner.push_back(value_reader);
+ dbus::MessageReader dict_entry_reader(response);
+ std::string key;
+ if (!array_reader.PopDictEntry(&dict_entry_reader) ||
+ !dict_entry_reader.PopString(&key) ||
+ !dict_entry_reader.PopVariant(value_reader)) {
+ LOG(ERROR) << "Invalid response: " << response->ToString();
+ return;
+ }
+ properties[key] = value_reader;
+ }
+ MaybePopBool(properties[cros_disks::kDeviceIsDrive], &is_drive_);
+ MaybePopBool(properties[cros_disks::kDeviceIsReadOnly], &is_read_only_);
+ MaybePopBool(properties[cros_disks::kDevicePresentationHide], &is_hidden_);
+ MaybePopBool(properties[cros_disks::kDeviceIsMediaAvailable], &has_media_);
+ MaybePopBool(properties[cros_disks::kDeviceIsOnBootDevice],
+ &on_boot_device_);
+ MaybePopString(properties[cros_disks::kNativePath], &system_path_);
+ MaybePopString(properties[cros_disks::kDeviceFile], &file_path_);
+ MaybePopString(properties[cros_disks::kDriveModel], &drive_model_);
+ MaybePopString(properties[cros_disks::kIdLabel], &label_);
+ MaybePopUint64(properties[cros_disks::kDeviceSize], &total_size_in_bytes_);
+
+ std::vector<std::string> mount_paths;
+ if (MaybePopArrayOfStrings(properties[cros_disks::kDeviceMountPaths],
+ &mount_paths) && !mount_paths.empty())
+ mount_path_ = mount_paths[0];
+
+ bool is_rotational = false;
+ bool is_optical = false;
+ if (MaybePopBool(properties[cros_disks::kDriveIsRotational],
+ &is_rotational) &&
+ MaybePopBool(properties[cros_disks::kDeviceIsOpticalDisc],
+ &is_optical))
+ device_type_ = GetDeviceType(is_optical, is_rotational);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// CrosDisksClient
+
+CrosDisksClient::CrosDisksClient() {}
+
+CrosDisksClient::~CrosDisksClient() {}
+
+// static
+CrosDisksClient* CrosDisksClient::Create(dbus::Bus* bus) {
+ CrosDisksClient* impl;
satorux1 2011/11/11 19:01:48 = NULL; just in case.
+ if (system::runtime_environment::IsRunningOnChromeOS())
+ impl = new CrosDisksClientImpl(bus);
satorux1 2011/11/11 19:01:48 return new CrosDisksClientImpl(bus); may be simpl
hashimoto 2011/11/14 13:52:45 Done.
+ else
+ impl = new CrosDisksClientStubImpl();
+ return impl;
+}
+
+} // namespace chromeos

Powered by Google App Engine
This is Rietveld 408576698