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 21 class MediaFileSystemRegistryTest; 22 class MediaGalleriesPlatformAppBrowserTest; 23 class SystemStorageApiTest; 24 class SystemStorageEjectApiTest; 25 26 namespace device { 27 class MediaTransferProtocolManager; 28 } 29 30 namespace storage_monitor { 31 32 class RemovableStorageObserver; 33 class 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. 50 class 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