// 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( scoped_ptr storage_monitor) { delete g_storage_monitor; g_storage_monitor = storage_monitor.release(); } std::vector StorageMonitor::GetAllAvailableStorages() const { std::vector 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 callback) { // Platform-specific implementations will override this method to // perform actual device ejection. callback.Run(EJECT_FAILURE); } StorageMonitor::StorageMonitor() : observer_list_( new base::ObserverListThreadSafe()), 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::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 (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