• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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()20 StorageMonitor::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)40 void StorageMonitor::ReceiverImpl::ProcessAttach(const StorageInfo& info) {
41   notifications_->ProcessAttach(info);
42 }
43 
ProcessDetach(const std::string & id)44 void StorageMonitor::ReceiverImpl::ProcessDetach(const std::string& id) {
45   notifications_->ProcessDetach(id);
46 }
47 
MarkInitialized()48 void StorageMonitor::ReceiverImpl::MarkInitialized() {
49   notifications_->MarkInitialized();
50 }
51 
52 // static
Create()53 void StorageMonitor::Create() {
54   delete g_storage_monitor;
55   g_storage_monitor = CreateInternal();
56 }
57 
58 // static
Destroy()59 void StorageMonitor::Destroy() {
60   delete g_storage_monitor;
61   g_storage_monitor = NULL;
62 }
63 
GetInstance()64 StorageMonitor* StorageMonitor::GetInstance() {
65   return g_storage_monitor;
66 }
67 
SetStorageMonitorForTesting(scoped_ptr<StorageMonitor> storage_monitor)68 void StorageMonitor::SetStorageMonitorForTesting(
69     scoped_ptr<StorageMonitor> storage_monitor) {
70   delete g_storage_monitor;
71   g_storage_monitor = storage_monitor.release();
72 }
73 
GetAllAvailableStorages() const74 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 
EnsureInitialized(base::Closure callback)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 
IsInitialized() const105 bool StorageMonitor::IsInitialized() const {
106   return initialized_;
107 }
108 
AddObserver(RemovableStorageObserver * obs)109 void StorageMonitor::AddObserver(RemovableStorageObserver* obs) {
110   observer_list_->AddObserver(obs);
111 }
112 
RemoveObserver(RemovableStorageObserver * obs)113 void StorageMonitor::RemoveObserver(
114     RemovableStorageObserver* obs) {
115   observer_list_->RemoveObserver(obs);
116 }
117 
GetTransientIdForDeviceId(const std::string & device_id)118 std::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) const123 std::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)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 
StorageMonitor()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 
~StorageMonitor()144 StorageMonitor::~StorageMonitor() {
145 }
146 
receiver() const147 StorageMonitor::Receiver* StorageMonitor::receiver() const {
148   return receiver_.get();
149 }
150 
MarkInitialized()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 
ProcessAttach(const StorageInfo & info)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 
ProcessDetach(const std::string & id)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