OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "chromeos/disks/disk_mount_manager.h" | 5 #include "chromeos/disks/disk_mount_manager.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <set> | 8 #include <set> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/memory/weak_ptr.h" | 11 #include "base/memory/weak_ptr.h" |
12 #include "base/observer_list.h" | 12 #include "base/observer_list.h" |
13 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
14 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
15 #include "chromeos/dbus/dbus_thread_manager.h" | 15 #include "chromeos/dbus/dbus_thread_manager.h" |
16 | 16 |
17 namespace chromeos { | 17 namespace chromeos { |
18 namespace disks { | 18 namespace disks { |
19 | 19 |
20 namespace { | 20 namespace { |
21 | 21 |
22 const char kDeviceNotFound[] = "Device could not be found"; | 22 const char kDeviceNotFound[] = "Device could not be found"; |
23 | 23 |
24 DiskMountManager* g_disk_mount_manager = NULL; | 24 DiskMountManager* g_disk_mount_manager = NULL; |
25 | 25 |
26 // The DiskMountManager implementation. | 26 // The DiskMountManager implementation. |
27 class DiskMountManagerImpl : public DiskMountManager { | 27 class DiskMountManagerImpl : public DiskMountManager { |
28 public: | 28 public: |
29 DiskMountManagerImpl() : weak_ptr_factory_(this) { | 29 DiskMountManagerImpl() : |
30 already_refreshed_(false), | |
31 weak_ptr_factory_(this) { | |
30 DBusThreadManager* dbus_thread_manager = DBusThreadManager::Get(); | 32 DBusThreadManager* dbus_thread_manager = DBusThreadManager::Get(); |
31 DCHECK(dbus_thread_manager); | 33 DCHECK(dbus_thread_manager); |
32 cros_disks_client_ = dbus_thread_manager->GetCrosDisksClient(); | 34 cros_disks_client_ = dbus_thread_manager->GetCrosDisksClient(); |
33 DCHECK(cros_disks_client_); | 35 DCHECK(cros_disks_client_); |
34 cros_disks_client_->SetMountEventHandler( | 36 cros_disks_client_->SetMountEventHandler( |
35 base::Bind(&DiskMountManagerImpl::OnMountEvent, | 37 base::Bind(&DiskMountManagerImpl::OnMountEvent, |
36 weak_ptr_factory_.GetWeakPtr())); | 38 weak_ptr_factory_.GetWeakPtr())); |
37 cros_disks_client_->SetMountCompletedHandler( | 39 cros_disks_client_->SetMountCompletedHandler( |
38 base::Bind(&DiskMountManagerImpl::OnMountCompleted, | 40 base::Bind(&DiskMountManagerImpl::OnMountCompleted, |
39 weak_ptr_factory_.GetWeakPtr())); | 41 weak_ptr_factory_.GetWeakPtr())); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
148 callback.Run(false); | 150 callback.Run(false); |
149 return; | 151 return; |
150 } | 152 } |
151 | 153 |
152 // Nothing to unmount. | 154 // Nothing to unmount. |
153 callback.Run(true); | 155 callback.Run(true); |
154 return; | 156 return; |
155 } | 157 } |
156 | 158 |
157 // We will send the same callback data object to all Unmount calls and use | 159 // We will send the same callback data object to all Unmount calls and use |
158 // it to syncronize callbacks. | 160 // it to synchronize callbacks. |
159 // Note: this implementation has a potential memory leak issue. For | 161 // Note: this implementation has a potential memory leak issue. For |
160 // example if this instance is destructed before all the callbacks for | 162 // example if this instance is destructed before all the callbacks for |
161 // Unmount are invoked, the memory pointed by |cb_data| will be leaked. | 163 // Unmount are invoked, the memory pointed by |cb_data| will be leaked. |
162 // It is because the UnmountDeviceRecursivelyCallbackData keeps how | 164 // It is because the UnmountDeviceRecursivelyCallbackData keeps how |
163 // many times OnUnmountDeviceRecursively callback is called and when | 165 // many times OnUnmountDeviceRecursively callback is called and when |
164 // all the callbacks are called, |cb_data| will be deleted in the method. | 166 // all the callbacks are called, |cb_data| will be deleted in the method. |
165 // However destructing the instance before all callback invocations will | 167 // However destructing the instance before all callback invocations will |
166 // cancel all pending callbacks, so that the |cb_data| would never be | 168 // cancel all pending callbacks, so that the |cb_data| would never be |
167 // deleted. | 169 // deleted. |
168 // Fortunately, in the real scenario, the instance will be destructed | 170 // Fortunately, in the real scenario, the instance will be destructed |
(...skipping 13 matching lines...) Expand all Loading... | |
182 devices_to_unmount[i]), | 184 devices_to_unmount[i]), |
183 base::Bind(&DiskMountManagerImpl::OnUnmountDeviceRecursively, | 185 base::Bind(&DiskMountManagerImpl::OnUnmountDeviceRecursively, |
184 weak_ptr_factory_.GetWeakPtr(), | 186 weak_ptr_factory_.GetWeakPtr(), |
185 cb_data, | 187 cb_data, |
186 false, | 188 false, |
187 devices_to_unmount[i])); | 189 devices_to_unmount[i])); |
188 } | 190 } |
189 } | 191 } |
190 | 192 |
191 // DiskMountManager override. | 193 // DiskMountManager override. |
192 virtual void RequestMountInfoRefresh() OVERRIDE { | 194 virtual void EnsureMountInfoRefreshed( |
193 cros_disks_client_->EnumerateAutoMountableDevices( | 195 const EnsureMountInfoRefreshedCallback& callback) OVERRIDE { |
194 base::Bind(&DiskMountManagerImpl::OnRequestMountInfo, | 196 if (already_refreshed_) { |
195 weak_ptr_factory_.GetWeakPtr()), | 197 callback.Run(true); |
196 base::Bind(&base::DoNothing)); | 198 return; |
199 } | |
200 | |
201 refresh_callbacks_.push_back(callback); | |
202 if (refresh_callbacks_.size() == 1) { | |
203 // If there's no in-flight refreshing task, start it. | |
204 cros_disks_client_->EnumerateAutoMountableDevices( | |
205 base::Bind(&DiskMountManagerImpl::RefreshAfterEnumerateDevices, | |
206 weak_ptr_factory_.GetWeakPtr()), | |
207 base::Bind(&DiskMountManagerImpl::RefreshCompleted, | |
208 weak_ptr_factory_.GetWeakPtr(), false)); | |
209 } | |
197 } | 210 } |
198 | 211 |
199 // DiskMountManager override. | 212 // DiskMountManager override. |
200 virtual const DiskMap& disks() const OVERRIDE { return disks_; } | 213 virtual const DiskMap& disks() const OVERRIDE { return disks_; } |
201 | 214 |
202 // DiskMountManager override. | 215 // DiskMountManager override. |
203 virtual const Disk* FindDiskBySourcePath(const std::string& source_path) | 216 virtual const Disk* FindDiskBySourcePath(const std::string& source_path) |
204 const OVERRIDE { | 217 const OVERRIDE { |
205 DiskMap::const_iterator disk_it = disks_.find(source_path); | 218 DiskMap::const_iterator disk_it = disks_.find(source_path); |
206 return disk_it == disks_.end() ? NULL : disk_it->second; | 219 return disk_it == disks_.end() ? NULL : disk_it->second; |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
407 void OnFormatStarted(const std::string& device_path) { | 420 void OnFormatStarted(const std::string& device_path) { |
408 NotifyFormatStatusUpdate(FORMAT_STARTED, FORMAT_ERROR_NONE, device_path); | 421 NotifyFormatStatusUpdate(FORMAT_STARTED, FORMAT_ERROR_NONE, device_path); |
409 } | 422 } |
410 | 423 |
411 // Callback to handle FormatCompleted signal and Format method call failure. | 424 // Callback to handle FormatCompleted signal and Format method call failure. |
412 void OnFormatCompleted(FormatError error_code, | 425 void OnFormatCompleted(FormatError error_code, |
413 const std::string& device_path) { | 426 const std::string& device_path) { |
414 NotifyFormatStatusUpdate(FORMAT_COMPLETED, error_code, device_path); | 427 NotifyFormatStatusUpdate(FORMAT_COMPLETED, error_code, device_path); |
415 } | 428 } |
416 | 429 |
417 // Callbcak for GetDeviceProperties. | 430 // Callback for GetDeviceProperties. |
418 void OnGetDeviceProperties(const DiskInfo& disk_info) { | 431 void OnGetDeviceProperties(const DiskInfo& disk_info) { |
419 // TODO(zelidrag): Find a better way to filter these out before we | 432 // TODO(zelidrag): Find a better way to filter these out before we |
420 // fetch the properties: | 433 // fetch the properties: |
421 // Ignore disks coming from the device we booted the system from. | 434 // Ignore disks coming from the device we booted the system from. |
422 if (disk_info.on_boot_device()) | 435 if (disk_info.on_boot_device()) |
423 return; | 436 return; |
424 | 437 |
425 LOG(WARNING) << "Found disk " << disk_info.device_path(); | 438 LOG(WARNING) << "Found disk " << disk_info.device_path(); |
426 // Delete previous disk info for this path: | 439 // Delete previous disk info for this path: |
427 bool is_new = true; | 440 bool is_new = true; |
(...skipping 19 matching lines...) Expand all Loading... | |
447 disk_info.total_size_in_bytes(), | 460 disk_info.total_size_in_bytes(), |
448 disk_info.is_drive(), | 461 disk_info.is_drive(), |
449 disk_info.is_read_only(), | 462 disk_info.is_read_only(), |
450 disk_info.has_media(), | 463 disk_info.has_media(), |
451 disk_info.on_boot_device(), | 464 disk_info.on_boot_device(), |
452 disk_info.is_hidden()); | 465 disk_info.is_hidden()); |
453 disks_.insert(std::make_pair(disk_info.device_path(), disk)); | 466 disks_.insert(std::make_pair(disk_info.device_path(), disk)); |
454 NotifyDiskStatusUpdate(is_new ? DISK_ADDED : DISK_CHANGED, disk); | 467 NotifyDiskStatusUpdate(is_new ? DISK_ADDED : DISK_CHANGED, disk); |
455 } | 468 } |
456 | 469 |
457 // Callbcak for RequestMountInfo. | 470 // Part of EnsureMountInfoRefrehsed(). Called after the list of devices are |
458 void OnRequestMountInfo(const std::vector<std::string>& devices) { | 471 // enumerated. |
459 std::set<std::string> current_device_set; | 472 void RefreshAfterEnumerateDevices(const std::vector<std::string>& devices) { |
460 if (!devices.empty()) { | 473 std::set<std::string> current_device_set(devices.begin(), devices.end()); |
461 // Initiate properties fetch for all removable disks, | |
462 for (size_t i = 0; i < devices.size(); i++) { | |
463 current_device_set.insert(devices[i]); | |
464 // Initiate disk property retrieval for each relevant device path. | |
465 cros_disks_client_->GetDeviceProperties( | |
466 devices[i], | |
467 base::Bind(&DiskMountManagerImpl::OnGetDeviceProperties, | |
468 weak_ptr_factory_.GetWeakPtr()), | |
469 base::Bind(&base::DoNothing)); | |
470 } | |
471 } | |
472 // Search and remove disks that are no longer present. | |
473 for (DiskMap::iterator iter = disks_.begin(); iter != disks_.end(); ) { | 474 for (DiskMap::iterator iter = disks_.begin(); iter != disks_.end(); ) { |
474 if (current_device_set.find(iter->first) == current_device_set.end()) { | 475 if (current_device_set.find(iter->first) == current_device_set.end()) { |
475 Disk* disk = iter->second; | |
476 NotifyDiskStatusUpdate(DISK_REMOVED, disk); | |
477 delete iter->second; | 476 delete iter->second; |
478 disks_.erase(iter++); | 477 disks_.erase(iter++); |
479 } else { | 478 } else { |
480 ++iter; | 479 ++iter; |
481 } | 480 } |
482 } | 481 } |
482 RefreshEachDevice(devices, 0); | |
483 } | |
484 | |
485 // Part of EnsureMountInfoRefrehsed(). Called for each device to refresh info. | |
486 void RefreshEachDevice(const std::vector<std::string>& devices, size_t i) { | |
Ben Chan
2014/07/10 00:07:12
i -> index
RefreshEachDevice seems like a misnome
kinaba
2014/07/10 01:36:32
Done.
| |
487 if (i == devices.size()) { | |
488 // All devices info retrieved. Proceed to enumerate mount point info. | |
489 cros_disks_client_->EnumerateMountEntries( | |
490 base::Bind(&DiskMountManagerImpl::RefreshAfterEnumerateMountEntries, | |
491 weak_ptr_factory_.GetWeakPtr()), | |
492 base::Bind(&DiskMountManagerImpl::RefreshCompleted, | |
493 weak_ptr_factory_.GetWeakPtr(), false)); | |
494 return; | |
495 } | |
496 | |
497 cros_disks_client_->GetDeviceProperties( | |
498 devices[i], | |
499 base::Bind(&DiskMountManagerImpl::RefreshAfterGetDeviceProperties, | |
500 weak_ptr_factory_.GetWeakPtr(), devices, i + 1), | |
501 base::Bind(&DiskMountManagerImpl::RefreshCompleted, | |
502 weak_ptr_factory_.GetWeakPtr(), false)); | |
503 } | |
504 | |
505 // Part of EnsureMountInfoRefrehsed(). | |
Ben Chan
2014/07/10 00:07:12
typo: EnsureMountInfoRefrehsed -> EnsureMountInfoR
kinaba
2014/07/10 01:36:32
Done. Good eye :)
| |
506 void RefreshAfterGetDeviceProperties(const std::vector<std::string>& devices, | |
507 size_t next_index, | |
508 const DiskInfo& disk_info) { | |
509 OnGetDeviceProperties(disk_info); | |
510 RefreshEachDevice(devices, next_index); | |
511 } | |
512 | |
513 // Part of EnsureMountInfoRefrehsed(). Called after mount entries are listed. | |
514 void RefreshAfterEnumerateMountEntries( | |
515 const std::vector<MountEntry>& entries) { | |
516 for (size_t i = 0; i < entries.size(); ++i) | |
517 OnMountCompleted(entries[i]); | |
518 RefreshCompleted(true); | |
519 } | |
520 | |
521 // Part of EnsureMountInfoRefrehsed(). Called when the refreshing is done. | |
522 void RefreshCompleted(bool success) { | |
523 already_refreshed_ = true; | |
524 for (size_t i = 0; i < refresh_callbacks_.size(); ++i) | |
525 refresh_callbacks_[i].Run(success); | |
526 refresh_callbacks_.clear(); | |
483 } | 527 } |
484 | 528 |
485 // Callback to handle mount event signals. | 529 // Callback to handle mount event signals. |
486 void OnMountEvent(MountEventType event, const std::string& device_path_arg) { | 530 void OnMountEvent(MountEventType event, const std::string& device_path_arg) { |
487 // Take a copy of the argument so we can modify it below. | 531 // Take a copy of the argument so we can modify it below. |
488 std::string device_path = device_path_arg; | 532 std::string device_path = device_path_arg; |
489 switch (event) { | 533 switch (event) { |
490 case CROS_DISKS_DISK_ADDED: { | 534 case CROS_DISKS_DISK_ADDED: { |
491 cros_disks_client_->GetDeviceProperties( | 535 cros_disks_client_->GetDeviceProperties( |
492 device_path, | 536 device_path, |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
573 CrosDisksClient* cros_disks_client_; | 617 CrosDisksClient* cros_disks_client_; |
574 | 618 |
575 // The list of disks found. | 619 // The list of disks found. |
576 DiskMountManager::DiskMap disks_; | 620 DiskMountManager::DiskMap disks_; |
577 | 621 |
578 DiskMountManager::MountPointMap mount_points_; | 622 DiskMountManager::MountPointMap mount_points_; |
579 | 623 |
580 typedef std::set<std::string> SystemPathPrefixSet; | 624 typedef std::set<std::string> SystemPathPrefixSet; |
581 SystemPathPrefixSet system_path_prefixes_; | 625 SystemPathPrefixSet system_path_prefixes_; |
582 | 626 |
627 bool already_refreshed_; | |
628 std::vector<EnsureMountInfoRefreshedCallback> refresh_callbacks_; | |
629 | |
583 base::WeakPtrFactory<DiskMountManagerImpl> weak_ptr_factory_; | 630 base::WeakPtrFactory<DiskMountManagerImpl> weak_ptr_factory_; |
584 | 631 |
585 DISALLOW_COPY_AND_ASSIGN(DiskMountManagerImpl); | 632 DISALLOW_COPY_AND_ASSIGN(DiskMountManagerImpl); |
586 }; | 633 }; |
587 | 634 |
588 } // namespace | 635 } // namespace |
589 | 636 |
590 DiskMountManager::Disk::Disk(const std::string& device_path, | 637 DiskMountManager::Disk::Disk(const std::string& device_path, |
591 const std::string& mount_path, | 638 const std::string& mount_path, |
592 const std::string& system_path, | 639 const std::string& system_path, |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
700 VLOG(1) << "DiskMountManager Shutdown completed"; | 747 VLOG(1) << "DiskMountManager Shutdown completed"; |
701 } | 748 } |
702 | 749 |
703 // static | 750 // static |
704 DiskMountManager* DiskMountManager::GetInstance() { | 751 DiskMountManager* DiskMountManager::GetInstance() { |
705 return g_disk_mount_manager; | 752 return g_disk_mount_manager; |
706 } | 753 } |
707 | 754 |
708 } // namespace disks | 755 } // namespace disks |
709 } // namespace chromeos | 756 } // namespace chromeos |
OLD | NEW |