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 ~Receiver()20StorageMonitor::Receiver::~Receiver() { 21 } 22 23 class StorageMonitor::ReceiverImpl : public StorageMonitor::Receiver { 24 public: ReceiverImpl(StorageMonitor * notifications)25 explicit ReceiverImpl(StorageMonitor* notifications) 26 : notifications_(notifications) {} 27 ~ReceiverImpl()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 ProcessAttach(const StorageInfo & info)40void StorageMonitor::ReceiverImpl::ProcessAttach(const StorageInfo& info) { 41 notifications_->ProcessAttach(info); 42 } 43 ProcessDetach(const std::string & id)44void StorageMonitor::ReceiverImpl::ProcessDetach(const std::string& id) { 45 notifications_->ProcessDetach(id); 46 } 47 MarkInitialized()48void StorageMonitor::ReceiverImpl::MarkInitialized() { 49 notifications_->MarkInitialized(); 50 } 51 52 // static Create()53void StorageMonitor::Create() { 54 delete g_storage_monitor; 55 g_storage_monitor = CreateInternal(); 56 } 57 58 // static Destroy()59void StorageMonitor::Destroy() { 60 delete g_storage_monitor; 61 g_storage_monitor = NULL; 62 } 63 GetInstance()64StorageMonitor* StorageMonitor::GetInstance() { 65 return g_storage_monitor; 66 } 67 SetStorageMonitorForTesting(scoped_ptr<StorageMonitor> storage_monitor)68void StorageMonitor::SetStorageMonitorForTesting( 69 scoped_ptr<StorageMonitor> storage_monitor) { 70 delete g_storage_monitor; 71 g_storage_monitor = storage_monitor.release(); 72 } 73 GetAllAvailableStorages() const74std::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 EnsureInitialized(base::Closure callback)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 IsInitialized() const105bool StorageMonitor::IsInitialized() const { 106 return initialized_; 107 } 108 AddObserver(RemovableStorageObserver * obs)109void StorageMonitor::AddObserver(RemovableStorageObserver* obs) { 110 observer_list_->AddObserver(obs); 111 } 112 RemoveObserver(RemovableStorageObserver * obs)113void StorageMonitor::RemoveObserver( 114 RemovableStorageObserver* obs) { 115 observer_list_->RemoveObserver(obs); 116 } 117 GetTransientIdForDeviceId(const std::string & device_id)118std::string StorageMonitor::GetTransientIdForDeviceId( 119 const std::string& device_id) { 120 return transient_device_ids_->GetTransientIdForDeviceId(device_id); 121 } 122 GetDeviceIdForTransientId(const std::string & transient_id) const123std::string StorageMonitor::GetDeviceIdForTransientId( 124 const std::string& transient_id) const { 125 return transient_device_ids_->DeviceIdFromTransientId(transient_id); 126 } 127 EjectDevice(const std::string & device_id,base::Callback<void (EjectStatus)> callback)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 StorageMonitor()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 ~StorageMonitor()144StorageMonitor::~StorageMonitor() { 145 } 146 receiver() const147StorageMonitor::Receiver* StorageMonitor::receiver() const { 148 return receiver_.get(); 149 } 150 MarkInitialized()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 ProcessAttach(const StorageInfo & info)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 ProcessDetach(const std::string & id)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