| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef COMPONENTS_STORAGE_MONITOR_STORAGE_MONITOR_H_ |
| #define COMPONENTS_STORAGE_MONITOR_STORAGE_MONITOR_H_ |
| |
| #include <map> |
| #include <string> |
| #include <vector> |
| |
| #include "base/callback.h" |
| #include "base/files/file_path.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/observer_list_threadsafe.h" |
| #include "base/strings/string16.h" |
| #include "base/synchronization/lock.h" |
| #include "base/threading/thread_checker.h" |
| #include "components/storage_monitor/storage_info.h" |
| |
| class MediaFileSystemRegistryTest; |
| class MediaGalleriesPlatformAppBrowserTest; |
| class SystemStorageApiTest; |
| class SystemStorageEjectApiTest; |
| |
| namespace device { |
| class MediaTransferProtocolManager; |
| } |
| |
| namespace storage_monitor { |
| |
| class RemovableStorageObserver; |
| class TransientDeviceIds; |
| |
| // Base class for platform-specific instances watching for removable storage |
| // attachments/detachments. |
| // Lifecycle contracts: This class is created in the browser process |
| // before the profile is initialized, so listeners can be |
| // created during profile construction. The platform-specific initialization, |
| // which can lead to calling registered listeners with notifications of |
| // attached volumes, are done lazily at first use through the async |
| // |EnsureInitialized()| method. That must be done before any of the registered |
| // listeners will receive updates or calls to other API methods return |
| // meaningful results. |
| // A post-initialization |GetAttachedStorage()| call coupled with a |
| // registered listener will receive a complete set, albeit potentially with |
| // duplicates. This is because there's no tracking between when listeners were |
| // registered and the state of initialization, and the fact that platforms |
| // behave differently in how these notifications are provided. |
| class StorageMonitor { |
| public: |
| // This interface is provided to generators of storage notifications. |
| class Receiver { |
| public: |
| virtual ~Receiver(); |
| |
| virtual void ProcessAttach(const StorageInfo& info) = 0; |
| virtual void ProcessDetach(const std::string& id) = 0; |
| virtual void MarkInitialized() = 0; |
| }; |
| |
| // Status codes for the result of an EjectDevice() call. |
| enum EjectStatus { |
| EJECT_OK, |
| EJECT_IN_USE, |
| EJECT_NO_SUCH_DEVICE, |
| EJECT_FAILURE |
| }; |
| |
| // Instantiates the StorageMonitor singleton. This function does not |
| // guarantee the complete initialization of the object. For that, see |
| // |EnsureInitialized|. |
| static void Create(); |
| |
| // Destroys the StorageMonitor singleton. |
| static void Destroy(); |
| |
| // Returns a pointer to an object owned by BrowserProcess, with lifetime |
| // starting before main message loop start, and ending after main message loop |
| // shutdown. Called outside it's lifetime (or with no browser process), |
| // returns NULL. |
| static StorageMonitor* GetInstance(); |
| |
| static void SetStorageMonitorForTesting( |
| scoped_ptr<StorageMonitor> storage_monitor); |
| |
| virtual ~StorageMonitor(); |
| |
| // Ensures that the storage monitor is initialized. The provided callback, if |
| // non-null, will be called when initialization is complete. If initialization |
| // has already completed, this callback will be invoked within the calling |
| // stack. Before the callback is run, calls to |GetAllAvailableStorages| and |
| // |GetStorageInfoForPath| may not return the correct results. In addition, |
| // registered observers will not be notified on device attachment/detachment. |
| // Should be invoked on the UI thread; callbacks will be run on the UI thread. |
| void EnsureInitialized(base::Closure callback); |
| |
| // Return true if the storage monitor has already been initialized. |
| bool IsInitialized() const; |
| |
| // Finds the device that contains |path| and populates |device_info|. |
| // Should be able to handle any path on the local system, not just removable |
| // storage. Returns false if unable to find the device. |
| virtual bool GetStorageInfoForPath( |
| const base::FilePath& path, |
| StorageInfo* device_info) const = 0; |
| |
| // TODO(gbillock): make this either unnecessary (implementation-specific) or |
| // platform-independent. |
| #if defined(OS_WIN) |
| // Gets the MTP device storage information specified by |storage_device_id|. |
| // On success, returns true and fills in |device_location| with device |
| // interface details and |storage_object_id| with the string ID that |
| // uniquely identifies the object on the device. This ID need not be |
| // persistent across sessions. |
| virtual bool GetMTPStorageInfoFromDeviceId( |
| const std::string& storage_device_id, |
| base::string16* device_location, |
| base::string16* storage_object_id) const = 0; |
| #endif |
| |
| #if defined(OS_LINUX) |
| virtual device::MediaTransferProtocolManager* |
| media_transfer_protocol_manager() = 0; |
| #endif |
| |
| // Returns information for all known storages on the system, |
| // including fixed and removable storages. |
| std::vector<StorageInfo> GetAllAvailableStorages() const; |
| |
| void AddObserver(RemovableStorageObserver* obs); |
| void RemoveObserver(RemovableStorageObserver* obs); |
| |
| std::string GetTransientIdForDeviceId(const std::string& device_id); |
| std::string GetDeviceIdForTransientId(const std::string& transient_id) const; |
| |
| virtual void EjectDevice( |
| const std::string& device_id, |
| base::Callback<void(EjectStatus)> callback); |
| |
| protected: |
| friend class ::MediaFileSystemRegistryTest; |
| friend class ::MediaGalleriesPlatformAppBrowserTest; |
| friend class ::SystemStorageApiTest; |
| friend class ::SystemStorageEjectApiTest; |
| |
| StorageMonitor(); |
| |
| virtual Receiver* receiver() const; |
| |
| // Called to initialize the storage monitor. |
| virtual void Init() = 0; |
| |
| // Called by subclasses to mark the storage monitor as |
| // fully initialized. Must be called on the UI thread. |
| void MarkInitialized(); |
| |
| private: |
| // Internal method for creating platform specific StorageMonitor. |
| static StorageMonitor* CreateInternal(); |
| |
| class ReceiverImpl; |
| friend class ReceiverImpl; |
| |
| // Key: device id. |
| typedef std::map<std::string, StorageInfo> StorageMap; |
| |
| void ProcessAttach(const StorageInfo& storage); |
| void ProcessDetach(const std::string& id); |
| |
| scoped_ptr<Receiver> receiver_; |
| |
| scoped_refptr<ObserverListThreadSafe<RemovableStorageObserver> > |
| observer_list_; |
| |
| // Used to make sure we call initialize from the same thread as creation. |
| base::ThreadChecker thread_checker_; |
| |
| bool initializing_; |
| bool initialized_; |
| std::vector<base::Closure> on_initialize_callbacks_; |
| |
| // For manipulating storage_map_ structure. |
| mutable base::Lock storage_lock_; |
| |
| // Map of all known storage devices,including fixed and removable storages. |
| StorageMap storage_map_; |
| |
| scoped_ptr<TransientDeviceIds> transient_device_ids_; |
| }; |
| |
| } // namespace storage_monitor |
| |
| #endif // COMPONENTS_STORAGE_MONITOR_STORAGE_MONITOR_H_ |