| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/storage_monitor/storage_monitor.h" |
| |
| #include "base/stl_util.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "components/storage_monitor/removable_storage_observer.h" |
| #include "components/storage_monitor/transient_device_ids.h" |
| |
| namespace storage_monitor { |
| |
| namespace { |
| |
| StorageMonitor* g_storage_monitor = NULL; |
| |
| } // namespace |
| |
| StorageMonitor::Receiver::~Receiver() { |
| } |
| |
| class StorageMonitor::ReceiverImpl : public StorageMonitor::Receiver { |
| public: |
| explicit ReceiverImpl(StorageMonitor* notifications) |
| : notifications_(notifications) {} |
| |
| ~ReceiverImpl() override {} |
| |
| void ProcessAttach(const StorageInfo& info) override; |
| |
| void ProcessDetach(const std::string& id) override; |
| |
| void MarkInitialized() override; |
| |
| private: |
| StorageMonitor* notifications_; |
| }; |
| |
| void StorageMonitor::ReceiverImpl::ProcessAttach(const StorageInfo& info) { |
| notifications_->ProcessAttach(info); |
| } |
| |
| void StorageMonitor::ReceiverImpl::ProcessDetach(const std::string& id) { |
| notifications_->ProcessDetach(id); |
| } |
| |
| void StorageMonitor::ReceiverImpl::MarkInitialized() { |
| notifications_->MarkInitialized(); |
| } |
| |
| // static |
| void StorageMonitor::Create() { |
| delete g_storage_monitor; |
| g_storage_monitor = CreateInternal(); |
| } |
| |
| // static |
| void StorageMonitor::Destroy() { |
| delete g_storage_monitor; |
| g_storage_monitor = NULL; |
| } |
| |
| StorageMonitor* StorageMonitor::GetInstance() { |
| return g_storage_monitor; |
| } |
| |
| void StorageMonitor::SetStorageMonitorForTesting( |
| std::unique_ptr<StorageMonitor> storage_monitor) { |
| delete g_storage_monitor; |
| g_storage_monitor = storage_monitor.release(); |
| } |
| |
| std::vector<StorageInfo> StorageMonitor::GetAllAvailableStorages() const { |
| std::vector<StorageInfo> results; |
| |
| base::AutoLock lock(storage_lock_); |
| for (StorageMap::const_iterator it = storage_map_.begin(); |
| it != storage_map_.end(); |
| ++it) { |
| results.push_back(it->second); |
| } |
| return results; |
| } |
| |
| void StorageMonitor::EnsureInitialized(base::Closure callback) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| if (initialized_) { |
| if (!callback.is_null()) |
| callback.Run(); |
| return; |
| } |
| |
| if (!callback.is_null()) { |
| on_initialize_callbacks_.push_back(callback); |
| } |
| |
| if (initializing_) |
| return; |
| |
| initializing_ = true; |
| Init(); |
| } |
| |
| bool StorageMonitor::IsInitialized() const { |
| return initialized_; |
| } |
| |
| void StorageMonitor::AddObserver(RemovableStorageObserver* obs) { |
| observer_list_->AddObserver(obs); |
| } |
| |
| void StorageMonitor::RemoveObserver( |
| RemovableStorageObserver* obs) { |
| observer_list_->RemoveObserver(obs); |
| } |
| |
| std::string StorageMonitor::GetTransientIdForDeviceId( |
| const std::string& device_id) { |
| return transient_device_ids_->GetTransientIdForDeviceId(device_id); |
| } |
| |
| std::string StorageMonitor::GetDeviceIdForTransientId( |
| const std::string& transient_id) const { |
| return transient_device_ids_->DeviceIdFromTransientId(transient_id); |
| } |
| |
| void StorageMonitor::EjectDevice( |
| const std::string& device_id, |
| base::Callback<void(EjectStatus)> callback) { |
| // Platform-specific implementations will override this method to |
| // perform actual device ejection. |
| callback.Run(EJECT_FAILURE); |
| } |
| |
| StorageMonitor::StorageMonitor() |
| : observer_list_( |
| new base::ObserverListThreadSafe<RemovableStorageObserver>()), |
| initializing_(false), |
| initialized_(false), |
| transient_device_ids_(new TransientDeviceIds) { |
| receiver_.reset(new ReceiverImpl(this)); |
| } |
| |
| StorageMonitor::~StorageMonitor() { |
| } |
| |
| StorageMonitor::Receiver* StorageMonitor::receiver() const { |
| return receiver_.get(); |
| } |
| |
| void StorageMonitor::MarkInitialized() { |
| initialized_ = true; |
| for (std::vector<base::Closure>::iterator iter = |
| on_initialize_callbacks_.begin(); |
| iter != on_initialize_callbacks_.end(); ++iter) { |
| iter->Run(); |
| } |
| on_initialize_callbacks_.clear(); |
| } |
| |
| void StorageMonitor::ProcessAttach(const StorageInfo& info) { |
| { |
| base::AutoLock lock(storage_lock_); |
| if (base::ContainsKey(storage_map_, info.device_id())) { |
| // This can happen if our unique id scheme fails. Ignore the incoming |
| // non-unique attachment. |
| return; |
| } |
| storage_map_.insert(std::make_pair(info.device_id(), info)); |
| } |
| |
| DVLOG(1) << "StorageAttached id " << info.device_id(); |
| if (StorageInfo::IsRemovableDevice(info.device_id())) { |
| observer_list_->Notify( |
| FROM_HERE, &RemovableStorageObserver::OnRemovableStorageAttached, info); |
| } |
| } |
| |
| void StorageMonitor::ProcessDetach(const std::string& id) { |
| StorageInfo info; |
| { |
| base::AutoLock lock(storage_lock_); |
| StorageMap::iterator it = storage_map_.find(id); |
| if (it == storage_map_.end()) |
| return; |
| info = it->second; |
| storage_map_.erase(it); |
| } |
| |
| DVLOG(1) << "StorageDetached for id " << id; |
| if (StorageInfo::IsRemovableDevice(info.device_id())) { |
| observer_list_->Notify( |
| FROM_HERE, &RemovableStorageObserver::OnRemovableStorageDetached, info); |
| } |
| } |
| |
| } // namespace storage_monitor |