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 12 namespace storage_monitor { 13 14 namespace { 15 16 StorageMonitor* g_storage_monitor = NULL; 17 18 } // namespace 19 20 StorageMonitor::Receiver::~Receiver() { 21 } 22 23 class 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 40 void StorageMonitor::ReceiverImpl::ProcessAttach(const StorageInfo& info) { 41 notifications_->ProcessAttach(info); 42 } 43 44 void StorageMonitor::ReceiverImpl::ProcessDetach(const std::string& id) { 45 notifications_->ProcessDetach(id); 46 } 47 48 void StorageMonitor::ReceiverImpl::MarkInitialized() { 49 notifications_->MarkInitialized(); 50 } 51 52 // static 53 void StorageMonitor::Create() { 54 delete g_storage_monitor; 55 g_storage_monitor = CreateInternal(); 56 } 57 58 // static 59 void StorageMonitor::Destroy() { 60 delete g_storage_monitor; 61 g_storage_monitor = NULL; 62 } 63 64 StorageMonitor* StorageMonitor::GetInstance() { 65 return g_storage_monitor; 66 } 67 68 void StorageMonitor::SetStorageMonitorForTesting( 69 scoped_ptr<StorageMonitor> storage_monitor) { 70 delete g_storage_monitor; 71 g_storage_monitor = storage_monitor.release(); 72 } 73 74 std::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 86 void 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 105 bool StorageMonitor::IsInitialized() const { 106 return initialized_; 107 } 108 109 void StorageMonitor::AddObserver(RemovableStorageObserver* obs) { 110 observer_list_->AddObserver(obs); 111 } 112 113 void StorageMonitor::RemoveObserver( 114 RemovableStorageObserver* obs) { 115 observer_list_->RemoveObserver(obs); 116 } 117 118 std::string StorageMonitor::GetTransientIdForDeviceId( 119 const std::string& device_id) { 120 return transient_device_ids_->GetTransientIdForDeviceId(device_id); 121 } 122 123 std::string StorageMonitor::GetDeviceIdForTransientId( 124 const std::string& transient_id) const { 125 return transient_device_ids_->DeviceIdFromTransientId(transient_id); 126 } 127 128 void 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 136 StorageMonitor::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 144 StorageMonitor::~StorageMonitor() { 145 } 146 147 StorageMonitor::Receiver* StorageMonitor::receiver() const { 148 return receiver_.get(); 149 } 150 151 void 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 161 void 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 179 void 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