| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/cros/mount_library.h" | 5 #include "chrome/browser/chromeos/cros/mount_library.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 #include <vector> |
| 8 | 9 |
| 9 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| 10 #include "base/string_util.h" | 11 #include "base/string_util.h" |
| 11 #include "chrome/browser/chromeos/cros/cros_library.h" | 12 #include "chrome/browser/chromeos/cros/cros_library.h" |
| 12 #include "content/browser/browser_thread.h" | 13 #include "content/browser/browser_thread.h" |
| 13 | 14 |
| 14 const char* kLibraryNotLoaded = "Cros Library not loaded"; | 15 const char* kLibraryNotLoaded = "Cros Library not loaded"; |
| 15 const char* kDeviceNotFound = "Device could not be found"; | 16 const char* kDeviceNotFound = "Device could not be found"; |
| 16 | 17 |
| 17 namespace chromeos { | 18 namespace chromeos { |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 OnUnmountPath(mount_path, | 137 OnUnmountPath(mount_path, |
| 137 MOUNT_METHOD_ERROR_LOCAL, | 138 MOUNT_METHOD_ERROR_LOCAL, |
| 138 kLibraryNotLoaded); | 139 kLibraryNotLoaded); |
| 139 return; | 140 return; |
| 140 } | 141 } |
| 141 | 142 |
| 142 UnmountMountPoint(mount_path, &MountLibraryImpl::UnmountMountPointCallback, | 143 UnmountMountPoint(mount_path, &MountLibraryImpl::UnmountMountPointCallback, |
| 143 this); | 144 this); |
| 144 } | 145 } |
| 145 | 146 |
| 147 virtual void FormatUnmountedDevice(const char* file_path) OVERRIDE { |
| 148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 149 if (!CrosLibrary::Get()->EnsureLoaded()) { |
| 150 OnFormatDevice(file_path, |
| 151 false, |
| 152 MOUNT_METHOD_ERROR_LOCAL, |
| 153 kLibraryNotLoaded); |
| 154 return; |
| 155 } |
| 156 for (MountLibrary::DiskMap::iterator it = disks_.begin(); |
| 157 it != disks_.end(); ++it) { |
| 158 if (it->second->file_path().compare(file_path) == 0 && |
| 159 !it->second->mount_path().empty()) { |
| 160 OnFormatDevice(file_path, |
| 161 false, |
| 162 MOUNT_METHOD_ERROR_LOCAL, |
| 163 "Device is still mounted."); |
| 164 return; |
| 165 } |
| 166 } |
| 167 FormatDevice(file_path, |
| 168 "vfat", // currently format in vfat by default |
| 169 &MountLibraryImpl::FormatDeviceCallback, |
| 170 this); |
| 171 } |
| 172 |
| 173 virtual void FormatMountedDevice(const char* mount_path) OVERRIDE { |
| 174 DCHECK(mount_path); |
| 175 Disk* disk = NULL; |
| 176 for (MountLibrary::DiskMap::iterator it = disks_.begin(); |
| 177 it != disks_.end(); ++it) { |
| 178 if (it->second->mount_path().compare(mount_path) == 0) { |
| 179 disk = it->second; |
| 180 break; |
| 181 } |
| 182 } |
| 183 |
| 184 if (!disk) { |
| 185 OnFormatDevice(disk->device_path().c_str(), |
| 186 false, |
| 187 MOUNT_METHOD_ERROR_LOCAL, |
| 188 "Device with this mount path not found."); |
| 189 return; |
| 190 } |
| 191 if (formatting_pending_.find(disk->device_path()) != |
| 192 formatting_pending_.end()) { |
| 193 OnFormatDevice(disk->device_path().c_str(), |
| 194 false, |
| 195 MOUNT_METHOD_ERROR_LOCAL, |
| 196 "Formatting is already pending."); |
| 197 return; |
| 198 } |
| 199 // Formatting process continues, after unmounting. |
| 200 formatting_pending_[disk->device_path()] = disk->file_path(); |
| 201 UnmountPath(disk->mount_path().c_str()); |
| 202 } |
| 203 |
| 146 virtual void UnmountDeviceRecursive(const char* device_path, | 204 virtual void UnmountDeviceRecursive(const char* device_path, |
| 147 UnmountDeviceRecursiveCallbackType callback, void* user_data) | 205 UnmountDeviceRecursiveCallbackType callback, void* user_data) |
| 148 OVERRIDE { | 206 OVERRIDE { |
| 149 bool success = true; | 207 bool success = true; |
| 150 const char* error_message = NULL; | 208 const char* error_message = NULL; |
| 151 std::vector<const char*> devices_to_unmount; | 209 std::vector<const char*> devices_to_unmount; |
| 152 | 210 |
| 153 if (!CrosLibrary::Get()->EnsureLoaded()) { | 211 if (!CrosLibrary::Get()->EnsureLoaded()) { |
| 154 success = false; | 212 success = false; |
| 155 error_message = kLibraryNotLoaded; | 213 error_message = kLibraryNotLoaded; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 // Callback for UnmountRemovableDevice method. | 288 // Callback for UnmountRemovableDevice method. |
| 231 static void UnmountMountPointCallback(void* object, | 289 static void UnmountMountPointCallback(void* object, |
| 232 const char* mount_path, | 290 const char* mount_path, |
| 233 MountMethodErrorType error, | 291 MountMethodErrorType error, |
| 234 const char* error_message) { | 292 const char* error_message) { |
| 235 DCHECK(object); | 293 DCHECK(object); |
| 236 MountLibraryImpl* self = static_cast<MountLibraryImpl*>(object); | 294 MountLibraryImpl* self = static_cast<MountLibraryImpl*>(object); |
| 237 self->OnUnmountPath(mount_path, error, error_message); | 295 self->OnUnmountPath(mount_path, error, error_message); |
| 238 } | 296 } |
| 239 | 297 |
| 298 // Callback for FormatRemovableDevice method. |
| 299 static void FormatDeviceCallback(void* object, |
| 300 const char* device_path, |
| 301 bool success, |
| 302 MountMethodErrorType error, |
| 303 const char* error_message) { |
| 304 DCHECK(object); |
| 305 MountLibraryImpl* self = static_cast<MountLibraryImpl*>(object); |
| 306 self->OnFormatDevice(device_path, success, error, error_message); |
| 307 } |
| 308 |
| 240 // Callback for UnmountDeviceRecursive. | 309 // Callback for UnmountDeviceRecursive. |
| 241 static void UnmountDeviceRecursiveCallback(void* object, | 310 static void UnmountDeviceRecursiveCallback(void* object, |
| 242 const char* mount_path, | 311 const char* mount_path, |
| 243 MountMethodErrorType error, | 312 MountMethodErrorType error, |
| 244 const char* error_message) { | 313 const char* error_message) { |
| 245 DCHECK(object); | 314 DCHECK(object); |
| 246 UnmountDeviceRecursiveCallbackData* cb_data = | 315 UnmountDeviceRecursiveCallbackData* cb_data = |
| 247 static_cast<UnmountDeviceRecursiveCallbackData*>(object); | 316 static_cast<UnmountDeviceRecursiveCallbackData*>(object); |
| 248 | 317 |
| 249 // Do standard processing for Unmount event. | 318 // Do standard processing for Unmount event. |
| 250 cb_data->object->OnUnmountPath(mount_path, | 319 cb_data->object->OnUnmountPath(mount_path, |
| 251 error, | 320 error, |
| 252 error_message); | 321 error_message); |
| 253 if (error == MOUNT_METHOD_ERROR_LOCAL) { | 322 if (error == MOUNT_METHOD_ERROR_LOCAL) { |
| 254 cb_data->success = false; | 323 cb_data->success = false; |
| 255 } else if (error == MOUNT_METHOD_ERROR_NONE) { | 324 } else if (error == MOUNT_METHOD_ERROR_NONE) { |
| 256 LOG(INFO) << mount_path << " unmounted."; | 325 LOG(INFO) << mount_path << " unmounted."; |
| 257 } | 326 } |
| 258 | 327 |
| 259 // This is safe as long as all callbacks are called on the same thread as | 328 // This is safe as long as all callbacks are called on the same thread as |
| 260 // UnmountDeviceRecursive. | 329 // UnmountDeviceRecursive. |
| 261 cb_data->pending_callbacks_count--; | 330 cb_data->pending_callbacks_count--; |
| 262 | 331 |
| 263 if (cb_data->pending_callbacks_count == 0) { | 332 if (cb_data->pending_callbacks_count == 0) { |
| 264 cb_data->callback(cb_data->user_data, cb_data->success); | 333 cb_data->callback(cb_data->user_data, cb_data->success); |
| 265 delete cb_data; | 334 delete cb_data; |
| 266 } | 335 } |
| 267 } | 336 } |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 return; | 413 return; |
| 345 // TODO(tbarzic): Add separate, PathUnmounted event to Observer. | 414 // TODO(tbarzic): Add separate, PathUnmounted event to Observer. |
| 346 FireMountCompleted( | 415 FireMountCompleted( |
| 347 UNMOUNTING, | 416 UNMOUNTING, |
| 348 MOUNT_ERROR_NONE, | 417 MOUNT_ERROR_NONE, |
| 349 MountPointInfo(mount_points_it->second.source_path.c_str(), | 418 MountPointInfo(mount_points_it->second.source_path.c_str(), |
| 350 mount_points_it->second.mount_path.c_str(), | 419 mount_points_it->second.mount_path.c_str(), |
| 351 mount_points_it->second.mount_type)); | 420 mount_points_it->second.mount_type)); |
| 352 std::string path(mount_points_it->second.source_path); | 421 std::string path(mount_points_it->second.source_path); |
| 353 mount_points_.erase(mount_points_it); | 422 mount_points_.erase(mount_points_it); |
| 354 | |
| 355 DiskMap::iterator iter = disks_.find(path); | 423 DiskMap::iterator iter = disks_.find(path); |
| 356 if (iter == disks_.end()) { | 424 if (iter == disks_.end()) { |
| 357 // disk might have been removed by now? | 425 // disk might have been removed by now. |
| 358 return; | 426 return; |
| 359 } | 427 } |
| 360 Disk* disk = iter->second; | 428 Disk* disk = iter->second; |
| 361 DCHECK(disk); | 429 DCHECK(disk); |
| 362 disk->clear_mount_path(); | 430 disk->clear_mount_path(); |
| 363 FireDiskStatusUpdate(MOUNT_DISK_UNMOUNTED, disk); | 431 // Check if there is a formatting scheduled |
| 432 PathMap::iterator it = formatting_pending_.find(disk->device_path()); |
| 433 if (it != formatting_pending_.end()) { |
| 434 const std::string file_path = it->second; |
| 435 formatting_pending_.erase(it); |
| 436 FormatUnmountedDevice(file_path.c_str()); |
| 437 } |
| 364 } else { | 438 } else { |
| 365 LOG(WARNING) << "Unmount request failed for device " | 439 LOG(WARNING) << "Unmount request failed for device " |
| 366 << mount_path << ", with error: " | 440 << mount_path << ", with error: " |
| 367 << (error_message ? error_message : "Unknown"); | 441 << (error_message ? error_message : "Unknown"); |
| 368 } | 442 } |
| 369 } | 443 } |
| 370 | 444 |
| 445 void OnFormatDevice(const char* device_path, |
| 446 bool success, |
| 447 MountMethodErrorType error, |
| 448 const char* error_message) { |
| 449 DCHECK(device_path); |
| 450 if (error == MOUNT_METHOD_ERROR_NONE && device_path && success) { |
| 451 FireDeviceStatusUpdate(MOUNT_FORMATTING_STARTED, device_path); |
| 452 } else { |
| 453 FireDeviceStatusUpdate(MOUNT_FORMATTING_STARTED, |
| 454 std::string("!") + device_path); |
| 455 LOG(WARNING) << "Format request failed for device " |
| 456 << device_path << ", with error: " |
| 457 << (error_message ? error_message : "Unknown"); |
| 458 } |
| 459 } |
| 460 |
| 461 |
| 371 void OnGetDiskProperties(const char* device_path, | 462 void OnGetDiskProperties(const char* device_path, |
| 372 const DiskInfo* disk1, | 463 const DiskInfo* disk1, |
| 373 MountMethodErrorType error, | 464 MountMethodErrorType error, |
| 374 const char* error_message) { | 465 const char* error_message) { |
| 375 DCHECK(device_path); | 466 DCHECK(device_path); |
| 376 if (error == MOUNT_METHOD_ERROR_NONE && device_path) { | 467 if (error == MOUNT_METHOD_ERROR_NONE && device_path) { |
| 377 // TODO(zelidrag): Find a better way to filter these out before we | 468 // TODO(zelidrag): Find a better way to filter these out before we |
| 378 // fetch the properties: | 469 // fetch the properties: |
| 379 // Ignore disks coming from the device we booted the system from. | 470 // Ignore disks coming from the device we booted the system from. |
| 380 | 471 |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 break; | 607 break; |
| 517 } | 608 } |
| 518 case DEVICE_REMOVED: { | 609 case DEVICE_REMOVED: { |
| 519 type = MOUNT_DEVICE_REMOVED; | 610 type = MOUNT_DEVICE_REMOVED; |
| 520 break; | 611 break; |
| 521 } | 612 } |
| 522 case DEVICE_SCANNED: { | 613 case DEVICE_SCANNED: { |
| 523 type = MOUNT_DEVICE_SCANNED; | 614 type = MOUNT_DEVICE_SCANNED; |
| 524 break; | 615 break; |
| 525 } | 616 } |
| 617 case FORMATTING_FINISHED: { |
| 618 type = MOUNT_FORMATTING_FINISHED; |
| 619 break; |
| 620 } |
| 526 default: { | 621 default: { |
| 527 return; | 622 return; |
| 528 } | 623 } |
| 529 } | 624 } |
| 530 FireDeviceStatusUpdate(type, std::string(device_path)); | 625 FireDeviceStatusUpdate(type, std::string(device_path)); |
| 531 } | 626 } |
| 532 | 627 |
| 533 void Init() { | 628 void Init() { |
| 534 // Getting the monitor status so that the daemon starts up. | 629 // Getting the monitor status so that the daemon starts up. |
| 535 mount_status_connection_ = MonitorAllMountEvents( | 630 mount_status_connection_ = MonitorAllMountEvents( |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 567 ObserverList<Observer> observers_; | 662 ObserverList<Observer> observers_; |
| 568 | 663 |
| 569 // A reference to the mount api, to allow callbacks when the mount | 664 // A reference to the mount api, to allow callbacks when the mount |
| 570 // status changes. | 665 // status changes. |
| 571 MountEventConnection mount_status_connection_; | 666 MountEventConnection mount_status_connection_; |
| 572 | 667 |
| 573 // The list of disks found. | 668 // The list of disks found. |
| 574 MountLibrary::DiskMap disks_; | 669 MountLibrary::DiskMap disks_; |
| 575 | 670 |
| 576 MountLibrary::MountPointMap mount_points_; | 671 MountLibrary::MountPointMap mount_points_; |
| 672 // Set of devices that are supposed to be formated, but are currently waiting |
| 673 // to be unmounted. When device is in this map, the formatting process HAVEN'T |
| 674 // started yet. |
| 675 PathMap formatting_pending_; |
| 577 | 676 |
| 578 DISALLOW_COPY_AND_ASSIGN(MountLibraryImpl); | 677 DISALLOW_COPY_AND_ASSIGN(MountLibraryImpl); |
| 579 }; | 678 }; |
| 580 | 679 |
| 581 class MountLibraryStubImpl : public MountLibrary { | 680 class MountLibraryStubImpl : public MountLibrary { |
| 582 public: | 681 public: |
| 583 MountLibraryStubImpl() {} | 682 MountLibraryStubImpl() {} |
| 584 virtual ~MountLibraryStubImpl() {} | 683 virtual ~MountLibraryStubImpl() {} |
| 585 | 684 |
| 586 // MountLibrary overrides. | 685 // MountLibrary overrides. |
| 587 virtual void AddObserver(Observer* observer) OVERRIDE {} | 686 virtual void AddObserver(Observer* observer) OVERRIDE {} |
| 588 virtual void RemoveObserver(Observer* observer) OVERRIDE {} | 687 virtual void RemoveObserver(Observer* observer) OVERRIDE {} |
| 589 virtual const DiskMap& disks() const OVERRIDE { return disks_; } | 688 virtual const DiskMap& disks() const OVERRIDE { return disks_; } |
| 590 virtual const MountPointMap& mount_points() const OVERRIDE { | 689 virtual const MountPointMap& mount_points() const OVERRIDE { |
| 591 return mount_points_; | 690 return mount_points_; |
| 592 } | 691 } |
| 593 virtual void RequestMountInfoRefresh() OVERRIDE {} | 692 virtual void RequestMountInfoRefresh() OVERRIDE {} |
| 594 virtual void MountPath(const char* source_path, MountType type, | 693 virtual void MountPath(const char* source_path, MountType type, |
| 595 const MountPathOptions& options) OVERRIDE {} | 694 const MountPathOptions& options) OVERRIDE {} |
| 596 virtual void UnmountPath(const char* mount_path) OVERRIDE {} | 695 virtual void UnmountPath(const char* mount_path) OVERRIDE {} |
| 696 virtual void FormatUnmountedDevice(const char* device_path) OVERRIDE {} |
| 697 virtual void FormatMountedDevice(const char* mount_path) OVERRIDE {} |
| 597 virtual void UnmountDeviceRecursive(const char* device_path, | 698 virtual void UnmountDeviceRecursive(const char* device_path, |
| 598 UnmountDeviceRecursiveCallbackType callback, void* user_data) | 699 UnmountDeviceRecursiveCallbackType callback, void* user_data) |
| 599 OVERRIDE {} | 700 OVERRIDE {} |
| 600 | 701 |
| 601 private: | 702 private: |
| 602 // The list of disks found. | 703 // The list of disks found. |
| 603 DiskMap disks_; | 704 DiskMap disks_; |
| 604 MountPointMap mount_points_; | 705 MountPointMap mount_points_; |
| 605 | 706 |
| 606 DISALLOW_COPY_AND_ASSIGN(MountLibraryStubImpl); | 707 DISALLOW_COPY_AND_ASSIGN(MountLibraryStubImpl); |
| 607 }; | 708 }; |
| 608 | 709 |
| 609 // static | 710 // static |
| 610 MountLibrary* MountLibrary::GetImpl(bool stub) { | 711 MountLibrary* MountLibrary::GetImpl(bool stub) { |
| 611 if (stub) | 712 if (stub) |
| 612 return new MountLibraryStubImpl(); | 713 return new MountLibraryStubImpl(); |
| 613 else | 714 else |
| 614 return new MountLibraryImpl(); | 715 return new MountLibraryImpl(); |
| 615 } | 716 } |
| 616 | 717 |
| 617 } // namespace chromeos | 718 } // namespace chromeos |
| 618 | 719 |
| 619 // Allows InvokeLater without adding refcounting. This class is a Singleton and | 720 // Allows InvokeLater without adding refcounting. This class is a Singleton and |
| 620 // won't be deleted until it's last InvokeLater is run. | 721 // won't be deleted until it's last InvokeLater is run. |
| 621 DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::MountLibraryImpl); | 722 DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::MountLibraryImpl); |
| 622 | 723 |
| OLD | NEW |