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