• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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