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> | |
9 | 8 |
10 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
11 #include "base/string_util.h" | 10 #include "base/string_util.h" |
12 #include "chrome/browser/chromeos/cros/cros_library.h" | 11 #include "chrome/browser/chromeos/cros/cros_library.h" |
13 #include "content/browser/browser_thread.h" | 12 #include "content/browser/browser_thread.h" |
14 | 13 |
15 const char* kLibraryNotLoaded = "Cros Library not loaded"; | 14 const char* kLibraryNotLoaded = "Cros Library not loaded"; |
16 const char* kDeviceNotFound = "Device could not be found"; | 15 const char* kDeviceNotFound = "Device could not be found"; |
17 | 16 |
18 namespace chromeos { | 17 namespace chromeos { |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 137 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
139 if (!CrosLibrary::Get()->EnsureLoaded()) { | 138 if (!CrosLibrary::Get()->EnsureLoaded()) { |
140 OnUnmountPath(path, | 139 OnUnmountPath(path, |
141 MOUNT_METHOD_ERROR_LOCAL, | 140 MOUNT_METHOD_ERROR_LOCAL, |
142 kLibraryNotLoaded); | 141 kLibraryNotLoaded); |
143 return; | 142 return; |
144 } | 143 } |
145 UnmountMountPoint(path, &MountLibraryImpl::UnmountMountPointCallback, this); | 144 UnmountMountPoint(path, &MountLibraryImpl::UnmountMountPointCallback, this); |
146 } | 145 } |
147 | 146 |
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 | |
204 virtual void UnmountDeviceRecursive(const char* device_path, | 147 virtual void UnmountDeviceRecursive(const char* device_path, |
205 UnmountDeviceRecursiveCallbackType callback, void* user_data) | 148 UnmountDeviceRecursiveCallbackType callback, void* user_data) |
206 OVERRIDE { | 149 OVERRIDE { |
207 bool success = true; | 150 bool success = true; |
208 const char* error_message = NULL; | 151 const char* error_message = NULL; |
209 std::vector<const char*> devices_to_unmount; | 152 std::vector<const char*> devices_to_unmount; |
210 | 153 |
211 if (!CrosLibrary::Get()->EnsureLoaded()) { | 154 if (!CrosLibrary::Get()->EnsureLoaded()) { |
212 success = false; | 155 success = false; |
213 error_message = kLibraryNotLoaded; | 156 error_message = kLibraryNotLoaded; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 // Callback for UnmountRemovableDevice method. | 224 // Callback for UnmountRemovableDevice method. |
282 static void UnmountMountPointCallback(void* object, | 225 static void UnmountMountPointCallback(void* object, |
283 const char* device_path, | 226 const char* device_path, |
284 MountMethodErrorType error, | 227 MountMethodErrorType error, |
285 const char* error_message) { | 228 const char* error_message) { |
286 DCHECK(object); | 229 DCHECK(object); |
287 MountLibraryImpl* self = static_cast<MountLibraryImpl*>(object); | 230 MountLibraryImpl* self = static_cast<MountLibraryImpl*>(object); |
288 self->OnUnmountPath(device_path, error, error_message); | 231 self->OnUnmountPath(device_path, error, error_message); |
289 } | 232 } |
290 | 233 |
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 | |
302 // Callback for UnmountDeviceRecursive. | 234 // Callback for UnmountDeviceRecursive. |
303 static void UnmountDeviceRecursiveCallback(void* object, | 235 static void UnmountDeviceRecursiveCallback(void* object, |
304 const char* device_path, | 236 const char* device_path, |
305 MountMethodErrorType error, | 237 MountMethodErrorType error, |
306 const char* error_message) { | 238 const char* error_message) { |
307 DCHECK(object); | 239 DCHECK(object); |
308 UnmountDeviceRecursiveCallbackData* cb_data = | 240 UnmountDeviceRecursiveCallbackData* cb_data = |
309 static_cast<UnmountDeviceRecursiveCallbackData*>(object); | 241 static_cast<UnmountDeviceRecursiveCallbackData*>(object); |
310 | 242 |
311 // Do standard processing for Unmount event. | 243 // Do standard processing for Unmount event. |
312 cb_data->object->OnUnmountPath(device_path, | 244 cb_data->object->OnUnmountPath(device_path, |
313 error, | 245 error, |
314 error_message); | 246 error_message); |
315 if (error == MOUNT_METHOD_ERROR_LOCAL) { | 247 if (error == MOUNT_METHOD_ERROR_LOCAL) { |
316 cb_data->success = false; | 248 cb_data->success = false; |
317 } else if (error == MOUNT_METHOD_ERROR_NONE) { | 249 } else if (error == MOUNT_METHOD_ERROR_NONE) { |
318 LOG(WARNING) << device_path << " unmounted."; | 250 LOG(WARNING) << device_path << " unmounted."; |
319 } | 251 } |
320 | 252 |
321 // This is safe as long as all callbacks are called on the same thread as | 253 // This is safe as long as all callbacks are called on the same thread as |
322 // UnmountDeviceRecursive. | 254 // UnmountDeviceRecursive. |
323 cb_data->pending_callbacks_count--; | 255 cb_data->pending_callbacks_count--; |
324 | 256 |
325 if (cb_data->pending_callbacks_count == 0) { | 257 if (cb_data->pending_callbacks_count == 0) { |
326 cb_data->callback(cb_data->user_data, cb_data->success); | 258 cb_data->callback(cb_data->user_data, cb_data->success); |
327 delete cb_data; | 259 delete cb_data; |
328 } | 260 } |
329 } | 261 } |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 std::string path(source_path); | 351 std::string path(source_path); |
420 DiskMap::iterator iter = disks_.find(path); | 352 DiskMap::iterator iter = disks_.find(path); |
421 if (iter == disks_.end()) { | 353 if (iter == disks_.end()) { |
422 // disk might have been removed by now? | 354 // disk might have been removed by now? |
423 return; | 355 return; |
424 } | 356 } |
425 Disk* disk = iter->second; | 357 Disk* disk = iter->second; |
426 DCHECK(disk); | 358 DCHECK(disk); |
427 disk->clear_mount_path(); | 359 disk->clear_mount_path(); |
428 FireDiskStatusUpdate(MOUNT_DISK_UNMOUNTED, disk); | 360 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 } | |
436 } else { | 361 } else { |
437 LOG(WARNING) << "Unmount request failed for device " | 362 LOG(WARNING) << "Unmount request failed for device " |
438 << source_path << ", with error: " | 363 << source_path << ", with error: " |
439 << (error_message ? error_message : "Unknown"); | 364 << (error_message ? error_message : "Unknown"); |
440 } | 365 } |
441 } | 366 } |
442 | 367 |
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 | |
461 void OnGetDiskProperties(const char* device_path, | 368 void OnGetDiskProperties(const char* device_path, |
462 const DiskInfo* disk1, | 369 const DiskInfo* disk1, |
463 MountMethodErrorType error, | 370 MountMethodErrorType error, |
464 const char* error_message) { | 371 const char* error_message) { |
465 DCHECK(device_path); | 372 DCHECK(device_path); |
466 if (error == MOUNT_METHOD_ERROR_NONE && device_path) { | 373 if (error == MOUNT_METHOD_ERROR_NONE && device_path) { |
467 // TODO(zelidrag): Find a better way to filter these out before we | 374 // TODO(zelidrag): Find a better way to filter these out before we |
468 // fetch the properties: | 375 // fetch the properties: |
469 // Ignore disks coming from the device we booted the system from. | 376 // Ignore disks coming from the device we booted the system from. |
470 | 377 |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 break; | 513 break; |
607 } | 514 } |
608 case DEVICE_REMOVED: { | 515 case DEVICE_REMOVED: { |
609 type = MOUNT_DEVICE_REMOVED; | 516 type = MOUNT_DEVICE_REMOVED; |
610 break; | 517 break; |
611 } | 518 } |
612 case DEVICE_SCANNED: { | 519 case DEVICE_SCANNED: { |
613 type = MOUNT_DEVICE_SCANNED; | 520 type = MOUNT_DEVICE_SCANNED; |
614 break; | 521 break; |
615 } | 522 } |
616 case FORMATTING_FINISHED: { | |
617 type = MOUNT_FORMATTING_FINISHED; | |
618 break; | |
619 } | |
620 default: { | 523 default: { |
621 return; | 524 return; |
622 } | 525 } |
623 } | 526 } |
624 FireDeviceStatusUpdate(type, std::string(device_path)); | 527 FireDeviceStatusUpdate(type, std::string(device_path)); |
625 } | 528 } |
626 | 529 |
627 void Init() { | 530 void Init() { |
628 // Getting the monitor status so that the daemon starts up. | 531 // Getting the monitor status so that the daemon starts up. |
629 mount_status_connection_ = MonitorAllMountEvents( | 532 mount_status_connection_ = MonitorAllMountEvents( |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
661 ObserverList<Observer> observers_; | 564 ObserverList<Observer> observers_; |
662 | 565 |
663 // A reference to the mount api, to allow callbacks when the mount | 566 // A reference to the mount api, to allow callbacks when the mount |
664 // status changes. | 567 // status changes. |
665 MountEventConnection mount_status_connection_; | 568 MountEventConnection mount_status_connection_; |
666 | 569 |
667 // The list of disks found. | 570 // The list of disks found. |
668 MountLibrary::DiskMap disks_; | 571 MountLibrary::DiskMap disks_; |
669 | 572 |
670 MountLibrary::MountPointMap mount_points_; | 573 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_; | |
675 | 574 |
676 DISALLOW_COPY_AND_ASSIGN(MountLibraryImpl); | 575 DISALLOW_COPY_AND_ASSIGN(MountLibraryImpl); |
677 }; | 576 }; |
678 | 577 |
679 class MountLibraryStubImpl : public MountLibrary { | 578 class MountLibraryStubImpl : public MountLibrary { |
680 public: | 579 public: |
681 MountLibraryStubImpl() {} | 580 MountLibraryStubImpl() {} |
682 virtual ~MountLibraryStubImpl() {} | 581 virtual ~MountLibraryStubImpl() {} |
683 | 582 |
684 // MountLibrary overrides. | 583 // MountLibrary overrides. |
685 virtual void AddObserver(Observer* observer) OVERRIDE {} | 584 virtual void AddObserver(Observer* observer) OVERRIDE {} |
686 virtual void RemoveObserver(Observer* observer) OVERRIDE {} | 585 virtual void RemoveObserver(Observer* observer) OVERRIDE {} |
687 virtual const DiskMap& disks() const OVERRIDE { return disks_; } | 586 virtual const DiskMap& disks() const OVERRIDE { return disks_; } |
688 virtual const MountPointMap& mount_points() const OVERRIDE { | 587 virtual const MountPointMap& mount_points() const OVERRIDE { |
689 return mount_points_; | 588 return mount_points_; |
690 } | 589 } |
691 virtual void RequestMountInfoRefresh() OVERRIDE {} | 590 virtual void RequestMountInfoRefresh() OVERRIDE {} |
692 virtual void MountPath(const char* source_path, MountType type, | 591 virtual void MountPath(const char* source_path, MountType type, |
693 const MountPathOptions& options) OVERRIDE {} | 592 const MountPathOptions& options) OVERRIDE {} |
694 virtual void UnmountPath(const char* path) OVERRIDE {} | 593 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 {} | |
697 virtual void UnmountDeviceRecursive(const char* device_path, | 594 virtual void UnmountDeviceRecursive(const char* device_path, |
698 UnmountDeviceRecursiveCallbackType callback, void* user_data) | 595 UnmountDeviceRecursiveCallbackType callback, void* user_data) |
699 OVERRIDE {} | 596 OVERRIDE {} |
700 | 597 |
701 private: | 598 private: |
702 // The list of disks found. | 599 // The list of disks found. |
703 DiskMap disks_; | 600 DiskMap disks_; |
704 MountPointMap mount_points_; | 601 MountPointMap mount_points_; |
705 | 602 |
706 DISALLOW_COPY_AND_ASSIGN(MountLibraryStubImpl); | 603 DISALLOW_COPY_AND_ASSIGN(MountLibraryStubImpl); |
707 }; | 604 }; |
708 | 605 |
709 // static | 606 // static |
710 MountLibrary* MountLibrary::GetImpl(bool stub) { | 607 MountLibrary* MountLibrary::GetImpl(bool stub) { |
711 if (stub) | 608 if (stub) |
712 return new MountLibraryStubImpl(); | 609 return new MountLibraryStubImpl(); |
713 else | 610 else |
714 return new MountLibraryImpl(); | 611 return new MountLibraryImpl(); |
715 } | 612 } |
716 | 613 |
717 } // namespace chromeos | 614 } // namespace chromeos |
718 | 615 |
719 // Allows InvokeLater without adding refcounting. This class is a Singleton and | 616 // Allows InvokeLater without adding refcounting. This class is a Singleton and |
720 // won't be deleted until it's last InvokeLater is run. | 617 // won't be deleted until it's last InvokeLater is run. |
721 DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::MountLibraryImpl); | 618 DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::MountLibraryImpl); |
722 | 619 |
OLD | NEW |