1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "components/storage_monitor/storage_monitor.h" 6 7#include "base/stl_util.h" 8#include "base/strings/utf_string_conversions.h" 9#include "components/storage_monitor/removable_storage_observer.h" 10#include "components/storage_monitor/transient_device_ids.h" 11 12namespace storage_monitor { 13 14namespace { 15 16StorageMonitor* g_storage_monitor = NULL; 17 18} // namespace 19 20StorageMonitor::Receiver::~Receiver() { 21} 22 23class StorageMonitor::ReceiverImpl : public StorageMonitor::Receiver { 24 public: 25 explicit ReceiverImpl(StorageMonitor* notifications) 26 : notifications_(notifications) {} 27 28 virtual ~ReceiverImpl() {} 29 30 virtual void ProcessAttach(const StorageInfo& info) OVERRIDE; 31 32 virtual void ProcessDetach(const std::string& id) OVERRIDE; 33 34 virtual void MarkInitialized() OVERRIDE; 35 36 private: 37 StorageMonitor* notifications_; 38}; 39 40void StorageMonitor::ReceiverImpl::ProcessAttach(const StorageInfo& info) { 41 notifications_->ProcessAttach(info); 42} 43 44void StorageMonitor::ReceiverImpl::ProcessDetach(const std::string& id) { 45 notifications_->ProcessDetach(id); 46} 47 48void StorageMonitor::ReceiverImpl::MarkInitialized() { 49 notifications_->MarkInitialized(); 50} 51 52// static 53void StorageMonitor::Create() { 54 delete g_storage_monitor; 55 g_storage_monitor = CreateInternal(); 56} 57 58// static 59void StorageMonitor::Destroy() { 60 delete g_storage_monitor; 61 g_storage_monitor = NULL; 62} 63 64StorageMonitor* StorageMonitor::GetInstance() { 65 return g_storage_monitor; 66} 67 68void StorageMonitor::SetStorageMonitorForTesting( 69 scoped_ptr<StorageMonitor> storage_monitor) { 70 delete g_storage_monitor; 71 g_storage_monitor = storage_monitor.release(); 72} 73 74std::vector<StorageInfo> StorageMonitor::GetAllAvailableStorages() const { 75 std::vector<StorageInfo> results; 76 77 base::AutoLock lock(storage_lock_); 78 for (StorageMap::const_iterator it = storage_map_.begin(); 79 it != storage_map_.end(); 80 ++it) { 81 results.push_back(it->second); 82 } 83 return results; 84} 85 86void StorageMonitor::EnsureInitialized(base::Closure callback) { 87 DCHECK(thread_checker_.CalledOnValidThread()); 88 if (initialized_) { 89 if (!callback.is_null()) 90 callback.Run(); 91 return; 92 } 93 94 if (!callback.is_null()) { 95 on_initialize_callbacks_.push_back(callback); 96 } 97 98 if (initializing_) 99 return; 100 101 initializing_ = true; 102 Init(); 103} 104 105bool StorageMonitor::IsInitialized() const { 106 return initialized_; 107} 108 109void StorageMonitor::AddObserver(RemovableStorageObserver* obs) { 110 observer_list_->AddObserver(obs); 111} 112 113void StorageMonitor::RemoveObserver( 114 RemovableStorageObserver* obs) { 115 observer_list_->RemoveObserver(obs); 116} 117 118std::string StorageMonitor::GetTransientIdForDeviceId( 119 const std::string& device_id) { 120 return transient_device_ids_->GetTransientIdForDeviceId(device_id); 121} 122 123std::string StorageMonitor::GetDeviceIdForTransientId( 124 const std::string& transient_id) const { 125 return transient_device_ids_->DeviceIdFromTransientId(transient_id); 126} 127 128void StorageMonitor::EjectDevice( 129 const std::string& device_id, 130 base::Callback<void(EjectStatus)> callback) { 131 // Platform-specific implementations will override this method to 132 // perform actual device ejection. 133 callback.Run(EJECT_FAILURE); 134} 135 136StorageMonitor::StorageMonitor() 137 : observer_list_(new ObserverListThreadSafe<RemovableStorageObserver>()), 138 initializing_(false), 139 initialized_(false), 140 transient_device_ids_(new TransientDeviceIds) { 141 receiver_.reset(new ReceiverImpl(this)); 142} 143 144StorageMonitor::~StorageMonitor() { 145} 146 147StorageMonitor::Receiver* StorageMonitor::receiver() const { 148 return receiver_.get(); 149} 150 151void StorageMonitor::MarkInitialized() { 152 initialized_ = true; 153 for (std::vector<base::Closure>::iterator iter = 154 on_initialize_callbacks_.begin(); 155 iter != on_initialize_callbacks_.end(); ++iter) { 156 iter->Run(); 157 } 158 on_initialize_callbacks_.clear(); 159} 160 161void StorageMonitor::ProcessAttach(const StorageInfo& info) { 162 { 163 base::AutoLock lock(storage_lock_); 164 if (ContainsKey(storage_map_, info.device_id())) { 165 // This can happen if our unique id scheme fails. Ignore the incoming 166 // non-unique attachment. 167 return; 168 } 169 storage_map_.insert(std::make_pair(info.device_id(), info)); 170 } 171 172 DVLOG(1) << "StorageAttached id " << info.device_id(); 173 if (StorageInfo::IsRemovableDevice(info.device_id())) { 174 observer_list_->Notify( 175 &RemovableStorageObserver::OnRemovableStorageAttached, info); 176 } 177} 178 179void StorageMonitor::ProcessDetach(const std::string& id) { 180 StorageInfo info; 181 { 182 base::AutoLock lock(storage_lock_); 183 StorageMap::iterator it = storage_map_.find(id); 184 if (it == storage_map_.end()) 185 return; 186 info = it->second; 187 storage_map_.erase(it); 188 } 189 190 DVLOG(1) << "StorageDetached for id " << id; 191 if (StorageInfo::IsRemovableDevice(info.device_id())) { 192 observer_list_->Notify( 193 &RemovableStorageObserver::OnRemovableStorageDetached, info); 194 } 195} 196 197} // namespace storage_monitor 198