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