Home | History | Annotate | Download | only in storage_monitor
      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