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_PORTABLE_DEVICE_WATCHER_WIN_H_
6 #define COMPONENTS_STORAGE_MONITOR_PORTABLE_DEVICE_WATCHER_WIN_H_
7 
8 #include <portabledeviceapi.h>
9 
10 #include <map>
11 #include <string>
12 #include <vector>
13 
14 #include "base/macros.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/strings/string16.h"
18 #include "components/storage_monitor/storage_monitor.h"
19 
20 namespace base {
21 class SequencedTaskRunner;
22 }
23 
24 namespace storage_monitor {
25 
26 class TestPortableDeviceWatcherWin;
27 
28 // This class watches the portable device mount points and sends notifications
29 // about the attached/detached media transfer protocol (MTP) devices.
30 // This is a singleton class instantiated by StorageMonitorWin. This class is
31 // created, destroyed and operates on the UI thread, except for long running
32 // tasks it spins off to a SequencedTaskRunner.
33 class PortableDeviceWatcherWin {
34  public:
35   typedef std::vector<base::string16> StorageObjectIDs;
36 
37   struct DeviceStorageObject {
38     DeviceStorageObject(const base::string16& temporary_id,
39                         const std::string& persistent_id);
40 
41     // Storage object temporary identifier, e.g. "s10001". This string ID
42     // uniquely identifies the object on the device. This ID need not be
43     // persistent across sessions. This ID is obtained from WPD_OBJECT_ID
44     // property.
45     base::string16 object_temporary_id;
46 
47     // Storage object persistent identifier,
48     // e.g. "StorageSerial:<SID-{10001,D,31080448}>:<123456789>".
49     std::string object_persistent_id;
50   };
51   typedef std::vector<DeviceStorageObject> StorageObjects;
52 
53   // Struct to store attached MTP device details.
54   struct DeviceDetails {
55     DeviceDetails();
56     DeviceDetails(const DeviceDetails& other);
57     ~DeviceDetails();
58 
59     // Device name.
60     base::string16 name;
61 
62     // Device interface path.
63     base::string16 location;
64 
65     // Device storage details. A device can have multiple data partitions.
66     StorageObjects storage_objects;
67   };
68   typedef std::vector<DeviceDetails> Devices;
69 
70   // TODO(gbillock): Change to take the device notifications object as
71   // an argument.
72   PortableDeviceWatcherWin();
73   virtual ~PortableDeviceWatcherWin();
74 
75   // Must be called after the browser blocking pool is ready for use.
76   // StorageMonitorWin::Init() will call this function.
77   void Init(HWND hwnd);
78 
79   // Processes DEV_BROADCAST_DEVICEINTERFACE messages and triggers a
80   // notification if appropriate.
81   void OnWindowMessage(UINT event_type, LPARAM data);
82 
83   // Gets the information of the MTP storage specified by |storage_device_id|.
84   // On success, returns true and fills in |device_location| with device
85   // interface details and |storage_object_id| with storage object temporary
86   // identifier.
87   virtual bool GetMTPStorageInfoFromDeviceId(
88       const std::string& storage_device_id,
89       base::string16* device_location,
90       base::string16* storage_object_id) const;
91 
92   // Constructs and returns a storage path from storage unique identifier.
93   static base::string16 GetStoragePathFromStorageId(
94       const std::string& storage_unique_id);
95 
96   // Set the volume notifications object to be used when new
97   // devices are found.
98   void SetNotifications(StorageMonitor::Receiver* notifications);
99 
100   void EjectDevice(
101       const std::string& device_id,
102       base::OnceCallback<void(StorageMonitor::EjectStatus)> callback);
103 
104  private:
105   friend class TestPortableDeviceWatcherWin;
106 
107   // Key: MTP device storage unique id.
108   // Value: Metadata for the given storage.
109   typedef std::map<std::string, StorageInfo> MTPStorageMap;
110 
111   // Key: MTP device plug and play ID string.
112   // Value: Vector of device storage objects.
113   typedef std::map<base::string16, StorageObjects> MTPDeviceMap;
114 
115   // Helpers to enumerate existing MTP storage devices.
116   virtual void EnumerateAttachedDevices();
117   void OnDidEnumerateAttachedDevices(const Devices* devices,
118                                      const bool result);
119 
120   // Helpers to handle device attach event.
121   virtual void HandleDeviceAttachEvent(const base::string16& pnp_device_id);
122   void OnDidHandleDeviceAttachEvent(const DeviceDetails* device_details,
123                                     const bool result);
124 
125   // Handles the detach event of the device specified by |pnp_device_id|.
126   void HandleDeviceDetachEvent(const base::string16& pnp_device_id);
127 
128   // The portable device notifications handle.
129   HDEVNOTIFY notifications_;
130 
131   // Attached media transfer protocol device map.
132   MTPDeviceMap device_map_;
133 
134   // Attached media transfer protocol device storage objects map.
135   MTPStorageMap storage_map_;
136 
137   // The task runner used to execute tasks that may take a long time and thus
138   // should not be performed on the UI thread.
139   scoped_refptr<base::SequencedTaskRunner> media_task_runner_;
140 
141   // The notifications object to use to signal newly attached devices.
142   StorageMonitor::Receiver* storage_notifications_;
143 
144   // Used by |media_task_runner_| to create cancelable callbacks.
145   base::WeakPtrFactory<PortableDeviceWatcherWin> weak_ptr_factory_{this};
146 
147   DISALLOW_COPY_AND_ASSIGN(PortableDeviceWatcherWin);
148 };
149 
150 }  // namespace storage_monitor
151 
152 #endif  // COMPONENTS_STORAGE_MONITOR_PORTABLE_DEVICE_WATCHER_WIN_H_
153