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. 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. 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: 82 CrosDisksClientImpl() : proxy_(NULL), weak_ptr_factory_(this) {} 83 84 // CrosDisksClient override. 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. 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. 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. 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. 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. 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: 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|. 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|. 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|. 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|. 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|. 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|. 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|. 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. 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: 379 CrosDisksClientStubImpl() 380 : weak_ptr_factory_(this) {} 381 382 virtual ~CrosDisksClientStubImpl() {} 383 384 // CrosDisksClient overrides: 385 virtual void Init(dbus::Bus* bus) OVERRIDE {} 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 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 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 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 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 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(). 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. 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. 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 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 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 // ] 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 711 CrosDisksClient::CrosDisksClient() {} 712 713 CrosDisksClient::~CrosDisksClient() {} 714 715 // static 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 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 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