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#ifndef COMPONENTS_STORAGE_MONITOR_STORAGE_MONITOR_H_ 6#define COMPONENTS_STORAGE_MONITOR_STORAGE_MONITOR_H_ 7 8#include <map> 9#include <string> 10#include <vector> 11 12#include "base/callback.h" 13#include "base/files/file_path.h" 14#include "base/memory/scoped_ptr.h" 15#include "base/observer_list_threadsafe.h" 16#include "base/strings/string16.h" 17#include "base/synchronization/lock.h" 18#include "base/threading/thread_checker.h" 19#include "components/storage_monitor/storage_info.h" 20 21class MediaFileSystemRegistryTest; 22class MediaGalleriesPlatformAppBrowserTest; 23class SystemStorageApiTest; 24class SystemStorageEjectApiTest; 25 26namespace device { 27class MediaTransferProtocolManager; 28} 29 30namespace storage_monitor { 31 32class RemovableStorageObserver; 33class TransientDeviceIds; 34 35// Base class for platform-specific instances watching for removable storage 36// attachments/detachments. 37// Lifecycle contracts: This class is created in the browser process 38// before the profile is initialized, so listeners can be 39// created during profile construction. The platform-specific initialization, 40// which can lead to calling registered listeners with notifications of 41// attached volumes, are done lazily at first use through the async 42// |EnsureInitialized()| method. That must be done before any of the registered 43// listeners will receive updates or calls to other API methods return 44// meaningful results. 45// A post-initialization |GetAttachedStorage()| call coupled with a 46// registered listener will receive a complete set, albeit potentially with 47// duplicates. This is because there's no tracking between when listeners were 48// registered and the state of initialization, and the fact that platforms 49// behave differently in how these notifications are provided. 50class StorageMonitor { 51 public: 52 // This interface is provided to generators of storage notifications. 53 class Receiver { 54 public: 55 virtual ~Receiver(); 56 57 virtual void ProcessAttach(const StorageInfo& info) = 0; 58 virtual void ProcessDetach(const std::string& id) = 0; 59 virtual void MarkInitialized() = 0; 60 }; 61 62 // Status codes for the result of an EjectDevice() call. 63 enum EjectStatus { 64 EJECT_OK, 65 EJECT_IN_USE, 66 EJECT_NO_SUCH_DEVICE, 67 EJECT_FAILURE 68 }; 69 70 // Instantiates the StorageMonitor singleton. This function does not 71 // guarantee the complete initialization of the object. For that, see 72 // |EnsureInitialized|. 73 static void Create(); 74 75 // Destroys the StorageMonitor singleton. 76 static void Destroy(); 77 78 // Returns a pointer to an object owned by BrowserProcess, with lifetime 79 // starting before main message loop start, and ending after main message loop 80 // shutdown. Called outside it's lifetime (or with no browser process), 81 // returns NULL. 82 static StorageMonitor* GetInstance(); 83 84 static void SetStorageMonitorForTesting( 85 scoped_ptr<StorageMonitor> storage_monitor); 86 87 virtual ~StorageMonitor(); 88 89 // Ensures that the storage monitor is initialized. The provided callback, if 90 // non-null, will be called when initialization is complete. If initialization 91 // has already completed, this callback will be invoked within the calling 92 // stack. Before the callback is run, calls to |GetAllAvailableStorages| and 93 // |GetStorageInfoForPath| may not return the correct results. In addition, 94 // registered observers will not be notified on device attachment/detachment. 95 // Should be invoked on the UI thread; callbacks will be run on the UI thread. 96 void EnsureInitialized(base::Closure callback); 97 98 // Return true if the storage monitor has already been initialized. 99 bool IsInitialized() const; 100 101 // Finds the device that contains |path| and populates |device_info|. 102 // Should be able to handle any path on the local system, not just removable 103 // storage. Returns false if unable to find the device. 104 virtual bool GetStorageInfoForPath( 105 const base::FilePath& path, 106 StorageInfo* device_info) const = 0; 107 108// TODO(gbillock): make this either unnecessary (implementation-specific) or 109// platform-independent. 110#if defined(OS_WIN) 111 // Gets the MTP device storage information specified by |storage_device_id|. 112 // On success, returns true and fills in |device_location| with device 113 // interface details and |storage_object_id| with the string ID that 114 // uniquely identifies the object on the device. This ID need not be 115 // persistent across sessions. 116 virtual bool GetMTPStorageInfoFromDeviceId( 117 const std::string& storage_device_id, 118 base::string16* device_location, 119 base::string16* storage_object_id) const = 0; 120#endif 121 122#if defined(OS_LINUX) 123 virtual device::MediaTransferProtocolManager* 124 media_transfer_protocol_manager() = 0; 125#endif 126 127 // Returns information for all known storages on the system, 128 // including fixed and removable storages. 129 std::vector<StorageInfo> GetAllAvailableStorages() const; 130 131 void AddObserver(RemovableStorageObserver* obs); 132 void RemoveObserver(RemovableStorageObserver* obs); 133 134 std::string GetTransientIdForDeviceId(const std::string& device_id); 135 std::string GetDeviceIdForTransientId(const std::string& transient_id) const; 136 137 virtual void EjectDevice( 138 const std::string& device_id, 139 base::Callback<void(EjectStatus)> callback); 140 141 protected: 142 friend class ::MediaFileSystemRegistryTest; 143 friend class ::MediaGalleriesPlatformAppBrowserTest; 144 friend class ::SystemStorageApiTest; 145 friend class ::SystemStorageEjectApiTest; 146 147 StorageMonitor(); 148 149 virtual Receiver* receiver() const; 150 151 // Called to initialize the storage monitor. 152 virtual void Init() = 0; 153 154 // Called by subclasses to mark the storage monitor as 155 // fully initialized. Must be called on the UI thread. 156 void MarkInitialized(); 157 158 private: 159 // Internal method for creating platform specific StorageMonitor. 160 static StorageMonitor* CreateInternal(); 161 162 class ReceiverImpl; 163 friend class ReceiverImpl; 164 165 // Key: device id. 166 typedef std::map<std::string, StorageInfo> StorageMap; 167 168 void ProcessAttach(const StorageInfo& storage); 169 void ProcessDetach(const std::string& id); 170 171 scoped_ptr<Receiver> receiver_; 172 173 scoped_refptr<ObserverListThreadSafe<RemovableStorageObserver> > 174 observer_list_; 175 176 // Used to make sure we call initialize from the same thread as creation. 177 base::ThreadChecker thread_checker_; 178 179 bool initializing_; 180 bool initialized_; 181 std::vector<base::Closure> on_initialize_callbacks_; 182 183 // For manipulating storage_map_ structure. 184 mutable base::Lock storage_lock_; 185 186 // Map of all known storage devices,including fixed and removable storages. 187 StorageMap storage_map_; 188 189 scoped_ptr<TransientDeviceIds> transient_device_ids_; 190}; 191 192} // namespace storage_monitor 193 194#endif // COMPONENTS_STORAGE_MONITOR_STORAGE_MONITOR_H_ 195