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