1 // Copyright (c) 2012 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 "chromeos/dbus/cros_disks_client.h"
6
7 #include <map>
8
9 #include "base/bind.h"
10 #include "base/file_util.h"
11 #include "base/files/file_path.h"
12 #include "base/location.h"
13 #include "base/message_loop/message_loop_proxy.h"
14 #include "base/stl_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/sys_info.h"
17 #include "base/task_runner_util.h"
18 #include "base/threading/worker_pool.h"
19 #include "base/values.h"
20 #include "dbus/bus.h"
21 #include "dbus/message.h"
22 #include "dbus/object_path.h"
23 #include "dbus/object_proxy.h"
24 #include "dbus/values_util.h"
25 #include "third_party/cros_system_api/dbus/service_constants.h"
26
27 namespace chromeos {
28
29 namespace {
30
31 const char* kDefaultMountOptions[] = {
32 "rw",
33 "nodev",
34 "noexec",
35 "nosuid",
36 };
37
38 const char* kDefaultUnmountOptions[] = {
39 "force",
40 };
41
42 const char kLazyUnmountOption[] = "lazy";
43
44 const char kMountLabelOption[] = "mountlabel";
45
46 // Checks if retrieved media type is in boundaries of DeviceMediaType.
IsValidMediaType(uint32 type)47 bool IsValidMediaType(uint32 type) {
48 return type < static_cast<uint32>(cros_disks::DEVICE_MEDIA_NUM_VALUES);
49 }
50
51 // Translates enum used in cros-disks to enum used in Chrome.
52 // Note that we could just do static_cast, but this is less sensitive to
53 // changes in cros-disks.
DeviceMediaTypeToDeviceType(uint32 media_type_uint32)54 DeviceType DeviceMediaTypeToDeviceType(uint32 media_type_uint32) {
55 if (!IsValidMediaType(media_type_uint32))
56 return DEVICE_TYPE_UNKNOWN;
57
58 cros_disks::DeviceMediaType media_type =
59 cros_disks::DeviceMediaType(media_type_uint32);
60
61 switch (media_type) {
62 case(cros_disks::DEVICE_MEDIA_UNKNOWN):
63 return DEVICE_TYPE_UNKNOWN;
64 case(cros_disks::DEVICE_MEDIA_USB):
65 return DEVICE_TYPE_USB;
66 case(cros_disks::DEVICE_MEDIA_SD):
67 return DEVICE_TYPE_SD;
68 case(cros_disks::DEVICE_MEDIA_OPTICAL_DISC):
69 return DEVICE_TYPE_OPTICAL_DISC;
70 case(cros_disks::DEVICE_MEDIA_MOBILE):
71 return DEVICE_TYPE_MOBILE;
72 case(cros_disks::DEVICE_MEDIA_DVD):
73 return DEVICE_TYPE_DVD;
74 default:
75 return DEVICE_TYPE_UNKNOWN;
76 }
77 }
78
79 // The CrosDisksClient implementation.
80 class CrosDisksClientImpl : public CrosDisksClient {
81 public:
CrosDisksClientImpl()82 CrosDisksClientImpl() : proxy_(NULL), weak_ptr_factory_(this) {}
83
84 // CrosDisksClient override.
Mount(const std::string & source_path,const std::string & source_format,const std::string & mount_label,const base::Closure & callback,const base::Closure & error_callback)85 virtual void Mount(const std::string& source_path,
86 const std::string& source_format,
87 const std::string& mount_label,
88 const base::Closure& callback,
89 const base::Closure& error_callback) OVERRIDE {
90 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
91 cros_disks::kMount);
92 dbus::MessageWriter writer(&method_call);
93 writer.AppendString(source_path);
94 writer.AppendString(source_format);
95 std::vector<std::string> mount_options(kDefaultMountOptions,
96 kDefaultMountOptions +
97 arraysize(kDefaultMountOptions));
98 if (!mount_label.empty()) {
99 std::string mount_label_option = base::StringPrintf("%s=%s",
100 kMountLabelOption,
101 mount_label.c_str());
102 mount_options.push_back(mount_label_option);
103 }
104 writer.AppendArrayOfStrings(mount_options);
105 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
106 base::Bind(&CrosDisksClientImpl::OnMount,
107 weak_ptr_factory_.GetWeakPtr(),
108 callback,
109 error_callback));
110 }
111
112 // CrosDisksClient override.
Unmount(const std::string & device_path,UnmountOptions options,const base::Closure & callback,const base::Closure & error_callback)113 virtual void Unmount(const std::string& device_path,
114 UnmountOptions options,
115 const base::Closure& callback,
116 const base::Closure& error_callback) OVERRIDE {
117 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
118 cros_disks::kUnmount);
119 dbus::MessageWriter writer(&method_call);
120 writer.AppendString(device_path);
121
122 std::vector<std::string> unmount_options(
123 kDefaultUnmountOptions,
124 kDefaultUnmountOptions + arraysize(kDefaultUnmountOptions));
125 if (options == UNMOUNT_OPTIONS_LAZY)
126 unmount_options.push_back(kLazyUnmountOption);
127
128 writer.AppendArrayOfStrings(unmount_options);
129 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
130 base::Bind(&CrosDisksClientImpl::OnUnmount,
131 weak_ptr_factory_.GetWeakPtr(),
132 callback,
133 error_callback));
134 }
135
136 // CrosDisksClient override.
EnumerateAutoMountableDevices(const EnumerateAutoMountableDevicesCallback & callback,const base::Closure & error_callback)137 virtual void EnumerateAutoMountableDevices(
138 const EnumerateAutoMountableDevicesCallback& callback,
139 const base::Closure& error_callback) OVERRIDE {
140 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
141 cros_disks::kEnumerateAutoMountableDevices);
142 proxy_->CallMethod(
143 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
144 base::Bind(&CrosDisksClientImpl::OnEnumerateAutoMountableDevices,
145 weak_ptr_factory_.GetWeakPtr(),
146 callback,
147 error_callback));
148 }
149
150 // CrosDisksClient override.
FormatDevice(const std::string & device_path,const std::string & filesystem,const FormatDeviceCallback & callback,const base::Closure & error_callback)151 virtual void FormatDevice(const std::string& device_path,
152 const std::string& filesystem,
153 const FormatDeviceCallback& callback,
154 const base::Closure& error_callback) OVERRIDE {
155 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
156 cros_disks::kFormatDevice);
157 dbus::MessageWriter writer(&method_call);
158 writer.AppendString(device_path);
159 writer.AppendString(filesystem);
160 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
161 base::Bind(&CrosDisksClientImpl::OnFormatDevice,
162 weak_ptr_factory_.GetWeakPtr(),
163 callback,
164 error_callback));
165 }
166
167 // CrosDisksClient override.
GetDeviceProperties(const std::string & device_path,const GetDevicePropertiesCallback & callback,const base::Closure & error_callback)168 virtual void GetDeviceProperties(
169 const std::string& device_path,
170 const GetDevicePropertiesCallback& callback,
171 const base::Closure& error_callback) OVERRIDE {
172 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
173 cros_disks::kGetDeviceProperties);
174 dbus::MessageWriter writer(&method_call);
175 writer.AppendString(device_path);
176 proxy_->CallMethod(&method_call,
177 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
178 base::Bind(&CrosDisksClientImpl::OnGetDeviceProperties,
179 weak_ptr_factory_.GetWeakPtr(),
180 device_path,
181 callback,
182 error_callback));
183 }
184
185 // CrosDisksClient override.
SetUpConnections(const MountEventHandler & mount_event_handler,const MountCompletedHandler & mount_completed_handler)186 virtual void SetUpConnections(
187 const MountEventHandler& mount_event_handler,
188 const MountCompletedHandler& mount_completed_handler) OVERRIDE {
189 static const SignalEventTuple kSignalEventTuples[] = {
190 { cros_disks::kDeviceAdded, CROS_DISKS_DEVICE_ADDED },
191 { cros_disks::kDeviceScanned, CROS_DISKS_DEVICE_SCANNED },
192 { cros_disks::kDeviceRemoved, CROS_DISKS_DEVICE_REMOVED },
193 { cros_disks::kDiskAdded, CROS_DISKS_DISK_ADDED },
194 { cros_disks::kDiskChanged, CROS_DISKS_DISK_CHANGED },
195 { cros_disks::kDiskRemoved, CROS_DISKS_DISK_REMOVED },
196 { cros_disks::kFormattingFinished, CROS_DISKS_FORMATTING_FINISHED },
197 };
198 const size_t kNumSignalEventTuples = arraysize(kSignalEventTuples);
199
200 for (size_t i = 0; i < kNumSignalEventTuples; ++i) {
201 proxy_->ConnectToSignal(
202 cros_disks::kCrosDisksInterface,
203 kSignalEventTuples[i].signal_name,
204 base::Bind(&CrosDisksClientImpl::OnMountEvent,
205 weak_ptr_factory_.GetWeakPtr(),
206 kSignalEventTuples[i].event_type,
207 mount_event_handler),
208 base::Bind(&CrosDisksClientImpl::OnSignalConnected,
209 weak_ptr_factory_.GetWeakPtr()));
210 }
211 proxy_->ConnectToSignal(
212 cros_disks::kCrosDisksInterface,
213 cros_disks::kMountCompleted,
214 base::Bind(&CrosDisksClientImpl::OnMountCompleted,
215 weak_ptr_factory_.GetWeakPtr(),
216 mount_completed_handler),
217 base::Bind(&CrosDisksClientImpl::OnSignalConnected,
218 weak_ptr_factory_.GetWeakPtr()));
219 }
220
221 protected:
Init(dbus::Bus * bus)222 virtual void Init(dbus::Bus* bus) OVERRIDE {
223 proxy_ = bus->GetObjectProxy(
224 cros_disks::kCrosDisksServiceName,
225 dbus::ObjectPath(cros_disks::kCrosDisksServicePath));
226 }
227
228 private:
229 // A struct to contain a pair of signal name and mount event type.
230 // Used by SetUpConnections.
231 struct SignalEventTuple {
232 const char *signal_name;
233 MountEventType event_type;
234 };
235
236 // Handles the result of Mount and calls |callback| or |error_callback|.
OnMount(const base::Closure & callback,const base::Closure & error_callback,dbus::Response * response)237 void OnMount(const base::Closure& callback,
238 const base::Closure& error_callback,
239 dbus::Response* response) {
240 if (!response) {
241 error_callback.Run();
242 return;
243 }
244 callback.Run();
245 }
246
247 // Handles the result of Unount and calls |callback| or |error_callback|.
OnUnmount(const base::Closure & callback,const base::Closure & error_callback,dbus::Response * response)248 void OnUnmount(const base::Closure& callback,
249 const base::Closure& error_callback,
250 dbus::Response* response) {
251 if (!response) {
252 error_callback.Run();
253 return;
254 }
255
256 // Temporarly allow Unmount method to report failure both by setting dbus
257 // error (in which case response is not set) and by returning mount error
258 // different from MOUNT_ERROR_NONE. This is done so we can change Unmount
259 // method to return mount error (http://crbug.com/288974) without breaking
260 // Chrome.
261 // TODO(tbarzic): When Unmount implementation is changed on cros disks side,
262 // make this fail if reader is not able to read the error code value from
263 // the response.
264 dbus::MessageReader reader(response);
265 unsigned int error_code;
266 if (reader.PopUint32(&error_code) &&
267 static_cast<MountError>(error_code) != MOUNT_ERROR_NONE) {
268 error_callback.Run();
269 return;
270 }
271
272 callback.Run();
273 }
274
275 // Handles the result of EnumerateAutoMountableDevices and calls |callback| or
276 // |error_callback|.
OnEnumerateAutoMountableDevices(const EnumerateAutoMountableDevicesCallback & callback,const base::Closure & error_callback,dbus::Response * response)277 void OnEnumerateAutoMountableDevices(
278 const EnumerateAutoMountableDevicesCallback& callback,
279 const base::Closure& error_callback,
280 dbus::Response* response) {
281 if (!response) {
282 error_callback.Run();
283 return;
284 }
285 dbus::MessageReader reader(response);
286 std::vector<std::string> device_paths;
287 if (!reader.PopArrayOfStrings(&device_paths)) {
288 LOG(ERROR) << "Invalid response: " << response->ToString();
289 error_callback.Run();
290 return;
291 }
292 callback.Run(device_paths);
293 }
294
295 // Handles the result of FormatDevice and calls |callback| or
296 // |error_callback|.
OnFormatDevice(const FormatDeviceCallback & callback,const base::Closure & error_callback,dbus::Response * response)297 void OnFormatDevice(const FormatDeviceCallback& callback,
298 const base::Closure& error_callback,
299 dbus::Response* response) {
300 if (!response) {
301 error_callback.Run();
302 return;
303 }
304 dbus::MessageReader reader(response);
305 bool success = false;
306 if (!reader.PopBool(&success)) {
307 LOG(ERROR) << "Invalid response: " << response->ToString();
308 error_callback.Run();
309 return;
310 }
311 callback.Run(success);
312 }
313
314 // Handles the result of GetDeviceProperties and calls |callback| or
315 // |error_callback|.
OnGetDeviceProperties(const std::string & device_path,const GetDevicePropertiesCallback & callback,const base::Closure & error_callback,dbus::Response * response)316 void OnGetDeviceProperties(const std::string& device_path,
317 const GetDevicePropertiesCallback& callback,
318 const base::Closure& error_callback,
319 dbus::Response* response) {
320 if (!response) {
321 error_callback.Run();
322 return;
323 }
324 DiskInfo disk(device_path, response);
325 callback.Run(disk);
326 }
327
328 // Handles mount event signals and calls |handler|.
OnMountEvent(MountEventType event_type,MountEventHandler handler,dbus::Signal * signal)329 void OnMountEvent(MountEventType event_type,
330 MountEventHandler handler,
331 dbus::Signal* signal) {
332 dbus::MessageReader reader(signal);
333 std::string device;
334 if (!reader.PopString(&device)) {
335 LOG(ERROR) << "Invalid signal: " << signal->ToString();
336 return;
337 }
338 handler.Run(event_type, device);
339 }
340
341 // Handles MountCompleted signal and calls |handler|.
OnMountCompleted(MountCompletedHandler handler,dbus::Signal * signal)342 void OnMountCompleted(MountCompletedHandler handler, dbus::Signal* signal) {
343 dbus::MessageReader reader(signal);
344 unsigned int error_code = 0;
345 std::string source_path;
346 unsigned int mount_type = 0;
347 std::string mount_path;
348 if (!reader.PopUint32(&error_code) ||
349 !reader.PopString(&source_path) ||
350 !reader.PopUint32(&mount_type) ||
351 !reader.PopString(&mount_path)) {
352 LOG(ERROR) << "Invalid signal: " << signal->ToString();
353 return;
354 }
355 handler.Run(static_cast<MountError>(error_code), source_path,
356 static_cast<MountType>(mount_type), mount_path);
357 }
358
359 // Handles the result of signal connection setup.
OnSignalConnected(const std::string & interface,const std::string & signal,bool succeeded)360 void OnSignalConnected(const std::string& interface,
361 const std::string& signal,
362 bool succeeded) {
363 LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " " <<
364 signal << " failed.";
365 }
366
367 dbus::ObjectProxy* proxy_;
368
369 // Note: This should remain the last member so it'll be destroyed and
370 // invalidate its weak pointers before any other members are destroyed.
371 base::WeakPtrFactory<CrosDisksClientImpl> weak_ptr_factory_;
372
373 DISALLOW_COPY_AND_ASSIGN(CrosDisksClientImpl);
374 };
375
376 // A stub implementaion of CrosDisksClient.
377 class CrosDisksClientStubImpl : public CrosDisksClient {
378 public:
CrosDisksClientStubImpl()379 CrosDisksClientStubImpl()
380 : weak_ptr_factory_(this) {}
381
~CrosDisksClientStubImpl()382 virtual ~CrosDisksClientStubImpl() {}
383
384 // CrosDisksClient overrides:
Init(dbus::Bus * bus)385 virtual void Init(dbus::Bus* bus) OVERRIDE {}
Mount(const std::string & source_path,const std::string & source_format,const std::string & mount_label,const base::Closure & callback,const base::Closure & error_callback)386 virtual void Mount(const std::string& source_path,
387 const std::string& source_format,
388 const std::string& mount_label,
389 const base::Closure& callback,
390 const base::Closure& error_callback) OVERRIDE {
391 // This stub implementation only accepts archive mount requests.
392 const MountType type = MOUNT_TYPE_ARCHIVE;
393
394 const base::FilePath mounted_path = GetArchiveMountPoint().Append(
395 base::FilePath::FromUTF8Unsafe(mount_label));
396
397 // Already mounted path.
398 if (mounted_to_source_path_map_.count(mounted_path.value()) != 0) {
399 FinishMount(MOUNT_ERROR_PATH_ALREADY_MOUNTED, source_path, type,
400 std::string(), callback);
401 return;
402 }
403
404 // Perform fake mount.
405 base::PostTaskAndReplyWithResult(
406 base::WorkerPool::GetTaskRunner(true /* task_is_slow */).get(),
407 FROM_HERE,
408 base::Bind(&PerformFakeMount, source_path, mounted_path),
409 base::Bind(&CrosDisksClientStubImpl::ContinueMount,
410 weak_ptr_factory_.GetWeakPtr(),
411 source_path,
412 type,
413 callback,
414 mounted_path));
415 }
416
Unmount(const std::string & device_path,UnmountOptions options,const base::Closure & callback,const base::Closure & error_callback)417 virtual void Unmount(const std::string& device_path,
418 UnmountOptions options,
419 const base::Closure& callback,
420 const base::Closure& error_callback) OVERRIDE {
421 // Not mounted.
422 if (mounted_to_source_path_map_.count(device_path) == 0) {
423 base::MessageLoopProxy::current()->PostTask(FROM_HERE, error_callback);
424 return;
425 }
426
427 mounted_to_source_path_map_.erase(device_path);
428
429 // Remove the directory created in Mount().
430 base::WorkerPool::PostTaskAndReply(
431 FROM_HERE,
432 base::Bind(base::IgnoreResult(&base::DeleteFile),
433 base::FilePath::FromUTF8Unsafe(device_path),
434 true /* recursive */),
435 callback,
436 true /* task_is_slow */);
437 }
438
EnumerateAutoMountableDevices(const EnumerateAutoMountableDevicesCallback & callback,const base::Closure & error_callback)439 virtual void EnumerateAutoMountableDevices(
440 const EnumerateAutoMountableDevicesCallback& callback,
441 const base::Closure& error_callback) OVERRIDE {
442 std::vector<std::string> device_paths;
443 base::MessageLoopProxy::current()->PostTask(
444 FROM_HERE, base::Bind(callback, device_paths));
445 }
446
FormatDevice(const std::string & device_path,const std::string & filesystem,const FormatDeviceCallback & callback,const base::Closure & error_callback)447 virtual void FormatDevice(const std::string& device_path,
448 const std::string& filesystem,
449 const FormatDeviceCallback& callback,
450 const base::Closure& error_callback) OVERRIDE {
451 base::MessageLoopProxy::current()->PostTask(FROM_HERE, error_callback);
452 }
453
GetDeviceProperties(const std::string & device_path,const GetDevicePropertiesCallback & callback,const base::Closure & error_callback)454 virtual void GetDeviceProperties(
455 const std::string& device_path,
456 const GetDevicePropertiesCallback& callback,
457 const base::Closure& error_callback) OVERRIDE {
458 base::MessageLoopProxy::current()->PostTask(FROM_HERE, error_callback);
459 }
460
SetUpConnections(const MountEventHandler & mount_event_handler,const MountCompletedHandler & mount_completed_handler)461 virtual void SetUpConnections(
462 const MountEventHandler& mount_event_handler,
463 const MountCompletedHandler& mount_completed_handler) OVERRIDE {
464 mount_event_handler_ = mount_event_handler;
465 mount_completed_handler_ = mount_completed_handler;
466 }
467
468 private:
469 // Performs file actions for Mount().
PerformFakeMount(const std::string & source_path,const base::FilePath & mounted_path)470 static MountError PerformFakeMount(const std::string& source_path,
471 const base::FilePath& mounted_path) {
472 // Check the source path exists.
473 if (!base::PathExists(base::FilePath::FromUTF8Unsafe(source_path))) {
474 DLOG(ERROR) << "Source does not exist at " << source_path;
475 return MOUNT_ERROR_INVALID_PATH;
476 }
477
478 // Just create an empty directory and shows it as the mounted directory.
479 if (!base::CreateDirectory(mounted_path)) {
480 DLOG(ERROR) << "Failed to create directory at " << mounted_path.value();
481 return MOUNT_ERROR_DIRECTORY_CREATION_FAILED;
482 }
483
484 // Put a dummy file.
485 const base::FilePath dummy_file_path =
486 mounted_path.Append("SUCCESSFULLY_PERFORMED_FAKE_MOUNT.txt");
487 const std::string dummy_file_content = "This is a dummy file.";
488 const int write_result = file_util::WriteFile(
489 dummy_file_path, dummy_file_content.data(), dummy_file_content.size());
490 if (write_result != static_cast<int>(dummy_file_content.size())) {
491 DLOG(ERROR) << "Failed to put a dummy file at "
492 << dummy_file_path.value();
493 return MOUNT_ERROR_MOUNT_PROGRAM_FAILED;
494 }
495
496 return MOUNT_ERROR_NONE;
497 }
498
499 // Part of Mount() implementation.
ContinueMount(const std::string & source_path,MountType type,const base::Closure & callback,const base::FilePath & mounted_path,MountError mount_error)500 void ContinueMount(const std::string& source_path,
501 MountType type,
502 const base::Closure& callback,
503 const base::FilePath& mounted_path,
504 MountError mount_error) {
505 if (mount_error != MOUNT_ERROR_NONE) {
506 FinishMount(mount_error, source_path, type, std::string(), callback);
507 return;
508 }
509 mounted_to_source_path_map_[mounted_path.value()] = source_path;
510 FinishMount(MOUNT_ERROR_NONE, source_path, type,
511 mounted_path.AsUTF8Unsafe(), callback);
512 }
513
514 // Runs |callback| and sends MountCompleted signal.
515 // Part of Mount() implementation.
FinishMount(MountError error,const std::string & source_path,MountType type,const std::string & mounted_path,const base::Closure & callback)516 void FinishMount(MountError error,
517 const std::string& source_path,
518 MountType type,
519 const std::string& mounted_path,
520 const base::Closure& callback) {
521 base::MessageLoopProxy::current()->PostTask(FROM_HERE, callback);
522 if (!mount_completed_handler_.is_null()) {
523 base::MessageLoopProxy::current()->PostTask(
524 FROM_HERE,
525 base::Bind(mount_completed_handler_,
526 error, source_path, type, mounted_path));
527 }
528 }
529
530 // Mounted path to source path map.
531 std::map<std::string, std::string> mounted_to_source_path_map_;
532
533 MountEventHandler mount_event_handler_;
534 MountCompletedHandler mount_completed_handler_;
535
536 base::WeakPtrFactory<CrosDisksClientStubImpl> weak_ptr_factory_;
537
538 DISALLOW_COPY_AND_ASSIGN(CrosDisksClientStubImpl);
539 };
540
541 } // namespace
542
543 ////////////////////////////////////////////////////////////////////////////////
544 // DiskInfo
545
DiskInfo(const std::string & device_path,dbus::Response * response)546 DiskInfo::DiskInfo(const std::string& device_path, dbus::Response* response)
547 : device_path_(device_path),
548 is_drive_(false),
549 has_media_(false),
550 on_boot_device_(false),
551 device_type_(DEVICE_TYPE_UNKNOWN),
552 total_size_in_bytes_(0),
553 is_read_only_(false),
554 is_hidden_(true) {
555 InitializeFromResponse(response);
556 }
557
~DiskInfo()558 DiskInfo::~DiskInfo() {
559 }
560
561 // Initializes |this| from |response| given by the cros-disks service.
562 // Below is an example of |response|'s raw message (long string is ellipsized).
563 //
564 //
565 // message_type: MESSAGE_METHOD_RETURN
566 // destination: :1.8
567 // sender: :1.16
568 // signature: a{sv}
569 // serial: 96
570 // reply_serial: 267
571 //
572 // array [
573 // dict entry {
574 // string "DeviceFile"
575 // variant string "/dev/sdb"
576 // }
577 // dict entry {
578 // string "DeviceIsDrive"
579 // variant bool true
580 // }
581 // dict entry {
582 // string "DeviceIsMediaAvailable"
583 // variant bool true
584 // }
585 // dict entry {
586 // string "DeviceIsMounted"
587 // variant bool false
588 // }
589 // dict entry {
590 // string "DeviceIsOnBootDevice"
591 // variant bool false
592 // }
593 // dict entry {
594 // string "DeviceIsReadOnly"
595 // variant bool false
596 // }
597 // dict entry {
598 // string "DeviceIsVirtual"
599 // variant bool false
600 // }
601 // dict entry {
602 // string "DeviceMediaType"
603 // variant uint32 1
604 // }
605 // dict entry {
606 // string "DeviceMountPaths"
607 // variant array [
608 // ]
609 // }
610 // dict entry {
611 // string "DevicePresentationHide"
612 // variant bool true
613 // }
614 // dict entry {
615 // string "DeviceSize"
616 // variant uint64 7998537728
617 // }
618 // dict entry {
619 // string "DriveIsRotational"
620 // variant bool false
621 // }
622 // dict entry {
623 // string "VendorId"
624 // variant string "18d1"
625 // }
626 // dict entry {
627 // string "VendorName"
628 // variant string "Google Inc."
629 // }
630 // dict entry {
631 // string "ProductId"
632 // variant string "4e11"
633 // }
634 // dict entry {
635 // string "ProductName"
636 // variant string "Nexus One"
637 // }
638 // dict entry {
639 // string "DriveModel"
640 // variant string "TransMemory"
641 // }
642 // dict entry {
643 // string "IdLabel"
644 // variant string ""
645 // }
646 // dict entry {
647 // string "IdUuid"
648 // variant string ""
649 // }
650 // dict entry {
651 // string "NativePath"
652 // variant string "/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-4/...
653 // }
654 // ]
InitializeFromResponse(dbus::Response * response)655 void DiskInfo::InitializeFromResponse(dbus::Response* response) {
656 dbus::MessageReader reader(response);
657 scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader));
658 base::DictionaryValue* properties = NULL;
659 if (!value || !value->GetAsDictionary(&properties))
660 return;
661
662 properties->GetBooleanWithoutPathExpansion(
663 cros_disks::kDeviceIsDrive, &is_drive_);
664 properties->GetBooleanWithoutPathExpansion(
665 cros_disks::kDeviceIsReadOnly, &is_read_only_);
666 properties->GetBooleanWithoutPathExpansion(
667 cros_disks::kDevicePresentationHide, &is_hidden_);
668 properties->GetBooleanWithoutPathExpansion(
669 cros_disks::kDeviceIsMediaAvailable, &has_media_);
670 properties->GetBooleanWithoutPathExpansion(
671 cros_disks::kDeviceIsOnBootDevice, &on_boot_device_);
672 properties->GetStringWithoutPathExpansion(
673 cros_disks::kNativePath, &system_path_);
674 properties->GetStringWithoutPathExpansion(
675 cros_disks::kDeviceFile, &file_path_);
676 properties->GetStringWithoutPathExpansion(cros_disks::kVendorId, &vendor_id_);
677 properties->GetStringWithoutPathExpansion(
678 cros_disks::kVendorName, &vendor_name_);
679 properties->GetStringWithoutPathExpansion(
680 cros_disks::kProductId, &product_id_);
681 properties->GetStringWithoutPathExpansion(
682 cros_disks::kProductName, &product_name_);
683 properties->GetStringWithoutPathExpansion(
684 cros_disks::kDriveModel, &drive_model_);
685 properties->GetStringWithoutPathExpansion(cros_disks::kIdLabel, &label_);
686 properties->GetStringWithoutPathExpansion(cros_disks::kIdUuid, &uuid_);
687
688 // dbus::PopDataAsValue() pops uint64 as double.
689 // The top 11 bits of uint64 are dropped by the use of double. But, this works
690 // unless the size exceeds 8 PB.
691 double device_size_double = 0;
692 if (properties->GetDoubleWithoutPathExpansion(cros_disks::kDeviceSize,
693 &device_size_double))
694 total_size_in_bytes_ = device_size_double;
695
696 // dbus::PopDataAsValue() pops uint32 as double.
697 double media_type_double = 0;
698 if (properties->GetDoubleWithoutPathExpansion(cros_disks::kDeviceMediaType,
699 &media_type_double))
700 device_type_ = DeviceMediaTypeToDeviceType(media_type_double);
701
702 base::ListValue* mount_paths = NULL;
703 if (properties->GetListWithoutPathExpansion(cros_disks::kDeviceMountPaths,
704 &mount_paths))
705 mount_paths->GetString(0, &mount_path_);
706 }
707
708 ////////////////////////////////////////////////////////////////////////////////
709 // CrosDisksClient
710
CrosDisksClient()711 CrosDisksClient::CrosDisksClient() {}
712
~CrosDisksClient()713 CrosDisksClient::~CrosDisksClient() {}
714
715 // static
Create(DBusClientImplementationType type)716 CrosDisksClient* CrosDisksClient::Create(DBusClientImplementationType type) {
717 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
718 return new CrosDisksClientImpl();
719 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
720 return new CrosDisksClientStubImpl();
721 }
722
723 // static
GetArchiveMountPoint()724 base::FilePath CrosDisksClient::GetArchiveMountPoint() {
725 return base::FilePath(base::SysInfo::IsRunningOnChromeOS() ?
726 FILE_PATH_LITERAL("/media/archive") :
727 FILE_PATH_LITERAL("/tmp/chromeos/media/archive"));
728 }
729
730 // static
GetRemovableDiskMountPoint()731 base::FilePath CrosDisksClient::GetRemovableDiskMountPoint() {
732 return base::FilePath(base::SysInfo::IsRunningOnChromeOS() ?
733 FILE_PATH_LITERAL("/media/removable") :
734 FILE_PATH_LITERAL("/tmp/chromeos/media/removable"));
735 }
736
737 } // namespace chromeos
738