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