OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/system_monitor/removable_device_notifications_window_wi n.h" | 5 #include "chrome/browser/system_monitor/removable_device_notifications_window_wi n.h" |
6 | 6 |
7 #include <dbt.h> | 7 #include <dbt.h> |
8 | 8 |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/file_util.h" | 12 #include "base/file_util.h" |
13 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
14 #include "base/message_loop.h" | 14 #include "base/message_loop.h" |
15 #include "base/scoped_temp_dir.h" | 15 #include "base/scoped_temp_dir.h" |
16 #include "base/system_monitor/system_monitor.h" | 16 #include "base/system_monitor/system_monitor.h" |
17 #include "base/test/mock_devices_changed_observer.h" | 17 #include "base/test/mock_devices_changed_observer.h" |
18 #include "base/threading/sequenced_worker_pool.h" | |
18 #include "chrome/browser/system_monitor/media_storage_util.h" | 19 #include "chrome/browser/system_monitor/media_storage_util.h" |
20 #include "chrome/browser/system_monitor/removable_device_constants.h" | |
19 #include "chrome/browser/system_monitor/volume_mount_watcher_win.h" | 21 #include "chrome/browser/system_monitor/volume_mount_watcher_win.h" |
20 #include "content/public/test/test_browser_thread.h" | 22 #include "content/public/test/test_browser_thread.h" |
21 #include "testing/gmock/include/gmock/gmock.h" | 23 #include "testing/gmock/include/gmock/gmock.h" |
22 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
23 | 25 |
24 namespace { | 26 namespace { |
25 | 27 |
26 using content::BrowserThread; | 28 using content::BrowserThread; |
27 using chrome::RemovableDeviceNotificationsWindowWin; | 29 using chrome::RemovableDeviceNotificationsWindowWin; |
28 | 30 |
31 // Mtp device interface path constants. | |
32 const char16 kMtpDeviceWithInvalidInfo[] = | |
33 L"\\?\usb#vid_00&pid_00#0&2&1#{0000-0000-0000-0000-0000})"; | |
34 const char16 kMtpDeviceWithValidInfo[] = | |
35 L"\\?\usb#vid_ff&pid_000f#32&2&1#{abcd-1234-ffde-1112-9172})"; | |
36 const char16 kMtpDeviceWithMultipleStorage[] = | |
37 L"\\?\usb#vid_ff&pid_18#32&2&1#{ab33-1de4-f22e-1882-9724})"; | |
38 | |
39 // Sample mtp device storage information. | |
40 const char16 kMtpDeviceFriendlyName[] = L"Camera V1.1"; | |
41 const char16 kStorageLabelA[] = L"Camera V1.1 (s10001)"; | |
42 const char16 kStorageLabelB[] = L"Camera V1.1 (s20001)"; | |
43 const char16 kStorageObjectIdA[] = L"s10001"; | |
44 const char16 kStorageObjectIdB[] = L"s20001"; | |
45 const char kStorageUniqueIdA[] = | |
46 "mtp:StorageSerial:SID-{s10001, D, 12378}:123123"; | |
47 const char kStorageUniqueIdB[] = | |
48 "mtp:StorageSerial:SID-{s20001, S, 2238}:123123"; | |
49 | |
29 // Inputs of 'A:\' - 'Z:\' are valid. 'N:\' is not removable. | 50 // Inputs of 'A:\' - 'Z:\' are valid. 'N:\' is not removable. |
30 bool GetDeviceDetails(const FilePath& device_path, string16* device_location, | 51 bool GetMassStorageDeviceDetails(const FilePath& device_path, |
31 std::string* unique_id, string16* name, bool* removable) { | 52 string16* device_location, std::string* unique_id, string16* name, |
53 bool* removable) { | |
Peter Kasting
2012/10/19 21:31:12
Nit: One arg per line, indented even (several plac
kmadhusu
2012/10/23 23:44:17
Done.
| |
32 if (device_path.value().length() != 3 || device_path.value()[0] < L'A' || | 54 if (device_path.value().length() != 3 || device_path.value()[0] < L'A' || |
33 device_path.value()[0] > L'Z') { | 55 device_path.value()[0] > L'Z') { |
34 return false; | 56 return false; |
35 } | 57 } |
36 | 58 |
37 if (device_location) | 59 if (device_location) |
38 *device_location = device_path.value(); | 60 *device_location = device_path.value(); |
39 if (unique_id) { | 61 if (unique_id) { |
40 *unique_id = "\\\\?\\Volume{00000000-0000-0000-0000-000000000000}\\"; | 62 *unique_id = "\\\\?\\Volume{00000000-0000-0000-0000-000000000000}\\"; |
41 (*unique_id)[11] = device_path.value()[0]; | 63 (*unique_id)[11] = device_path.value()[0]; |
(...skipping 16 matching lines...) Expand all Loading... | |
58 result.push_back(DriveNumberToFilePath(0)); | 80 result.push_back(DriveNumberToFilePath(0)); |
59 result.push_back(DriveNumberToFilePath(1)); | 81 result.push_back(DriveNumberToFilePath(1)); |
60 result.push_back(DriveNumberToFilePath(2)); | 82 result.push_back(DriveNumberToFilePath(2)); |
61 result.push_back(DriveNumberToFilePath(3)); | 83 result.push_back(DriveNumberToFilePath(3)); |
62 result.push_back(DriveNumberToFilePath(5)); | 84 result.push_back(DriveNumberToFilePath(5)); |
63 result.push_back(DriveNumberToFilePath(7)); | 85 result.push_back(DriveNumberToFilePath(7)); |
64 result.push_back(DriveNumberToFilePath(25)); | 86 result.push_back(DriveNumberToFilePath(25)); |
65 return result; | 87 return result; |
66 } | 88 } |
67 | 89 |
90 // Returns the persistent storage unique id of the device specified by the | |
91 // |pnp_device_id|. |storage_object_id| specifies the temporary object | |
92 // identifier that uniquely identifies the object on the device. | |
93 std::string GetMtpStorageUniqueId(const string16& pnp_device_id, | |
94 const string16& storage_object_id) { | |
95 if (pnp_device_id == string16(kMtpDeviceWithInvalidInfo)) | |
Peter Kasting
2012/10/19 21:31:12
Nit: No need for explicit string16 construction (m
kmadhusu
2012/10/23 23:44:17
Done.
| |
96 return std::string(); | |
97 | |
98 if (storage_object_id == string16(kStorageObjectIdA)) | |
99 return kStorageUniqueIdA; | |
100 | |
101 if (storage_object_id == string16(kStorageObjectIdB)) | |
102 return kStorageUniqueIdB; | |
103 return std::string(); | |
Peter Kasting
2012/10/19 21:31:12
Nit: Or just:
return (storage_object_id == kSto
kmadhusu
2012/10/23 23:44:17
Done.
| |
104 } | |
105 | |
106 // Returns the storage name of the device specified by |pnp_device_id|. | |
107 // |storage_object_id| specifies the temporary object identifier that | |
108 // uniquely identifies the object on the device. | |
109 string16 GetMtpStorageName(const string16& pnp_device_id, | |
110 const string16& storage_object_id) { | |
111 if (pnp_device_id == string16(kMtpDeviceWithInvalidInfo)) | |
112 return string16(); | |
113 | |
114 if (storage_object_id == string16(kStorageObjectIdA)) | |
115 return string16(kStorageLabelA); | |
116 | |
117 if (storage_object_id == string16(kStorageObjectIdB)) | |
118 return string16(kStorageLabelB); | |
119 return string16(); | |
120 } | |
121 | |
122 // Returns a list of storage object identifiers of the device given a | |
123 // |pnp_device_id|. | |
124 std::vector<string16> GetMtpStorageObjectId(const string16& pnp_device_id) { | |
Peter Kasting
2012/10/19 21:31:12
Nit: GetMtpStorageObjectIds?
kmadhusu
2012/10/23 23:44:17
Done.
| |
125 if (pnp_device_id == string16(kMtpDeviceWithInvalidInfo)) | |
126 return std::vector<string16>(); | |
127 | |
128 std::vector<string16> storage_object_ids; | |
129 storage_object_ids.push_back(string16(kStorageObjectIdA)); | |
130 | |
131 if (pnp_device_id == string16(kMtpDeviceWithMultipleStorage)) | |
132 storage_object_ids.push_back(string16(kStorageObjectIdB)); | |
133 return storage_object_ids; | |
134 } | |
135 | |
136 // Gets the mtp device storage details given a |pnp_device_id| and | |
137 // |storage_object_id|. On success, returns true and fills in | |
138 // |device_location|, |unique_id| and |name|. | |
139 bool GetMtpStorageDetails( | |
Peter Kasting
2012/10/19 21:31:12
This method can't fail, so return void.
kmadhusu
2012/10/23 23:44:17
Done.
| |
140 const string16& pnp_device_id, const string16& storage_object_id, | |
141 string16* device_location, std::string* unique_id, string16* name) { | |
142 if (device_location) | |
143 *device_location = pnp_device_id; | |
144 | |
145 if (unique_id) | |
146 *unique_id = GetMtpStorageUniqueId(pnp_device_id, storage_object_id); | |
147 | |
148 if (name) | |
149 *name = GetMtpStorageName(pnp_device_id, storage_object_id); | |
150 return true; | |
151 } | |
152 | |
68 } // namespace | 153 } // namespace |
69 | 154 |
70 namespace chrome { | 155 namespace chrome { |
71 | 156 |
157 // Wrapper class for testing PortableDeviceWatcherWin. | |
158 class TestPortableDeviceWatcherWin : public PortableDeviceWatcherWin { | |
159 public: | |
160 TestPortableDeviceWatcherWin() { | |
161 } | |
Peter Kasting
2012/10/19 21:31:12
Nit: Do not define functions inline in class decla
kmadhusu
2012/10/23 23:44:17
Done.
| |
162 | |
163 private: | |
164 // Avoids code deleting the object while there are references to it. | |
165 // Aside from the base::RefCountedThreadSafe friend class, any attempts to | |
166 // call this dtor will result in a compile-time error. | |
167 virtual ~TestPortableDeviceWatcherWin() { | |
168 } | |
169 | |
170 // Override PortableDeviceWatcherWin::InitOnBlockingThread. | |
Peter Kasting
2012/10/19 21:31:12
Nit: Don't comment individual function overrides t
kmadhusu
2012/10/23 23:44:17
Done.
| |
171 void InitOnBlockingThread() OVERRIDE { | |
172 } | |
173 | |
174 // Override PortableDeviceWatcherWin::GetDeviceName. | |
175 virtual string16 GetDeviceName(const string16& pnp_device_id) OVERRIDE { | |
176 if (pnp_device_id == string16(kMtpDeviceWithInvalidInfo)) | |
177 return string16(); | |
178 return string16(kMtpDeviceFriendlyName); | |
179 } | |
180 | |
181 // Override PortableDeviceWatcherWin::GetStorages. | |
182 virtual bool GetStorages(const string16& pnp_device_id, | |
183 std::vector<DeviceStorageInfo>* storages) OVERRIDE { | |
184 if (pnp_device_id == string16(kMtpDeviceWithInvalidInfo)) | |
185 return false; | |
186 | |
187 std::vector<string16> storage_object_ids = | |
188 GetMtpStorageObjectId(pnp_device_id); | |
189 for (size_t index = 0; index < storage_object_ids.size(); ++index) { | |
190 DeviceStorageInfo storage; | |
191 storage.unique_id = GetMtpStorageUniqueId(pnp_device_id, | |
192 storage_object_ids[index]); | |
193 storage.storage_object_id = storage_object_ids[index]; | |
194 storages->push_back(storage); | |
195 } | |
196 return true; | |
197 } | |
198 | |
199 DISALLOW_COPY_AND_ASSIGN(TestPortableDeviceWatcherWin); | |
200 }; | |
201 | |
72 // Wrapper class for testing VolumeMountWatcherWin. | 202 // Wrapper class for testing VolumeMountWatcherWin. |
73 class TestVolumeMountWatcherWin : public VolumeMountWatcherWin { | 203 class TestVolumeMountWatcherWin : public VolumeMountWatcherWin { |
74 public: | 204 public: |
75 TestVolumeMountWatcherWin() : pre_attach_devices_(false) { | 205 TestVolumeMountWatcherWin() : pre_attach_devices_(false) { |
76 } | 206 } |
77 | 207 |
78 // Override VolumeMountWatcherWin::GetDeviceInfo(). | 208 // Override VolumeMountWatcherWin::GetDeviceInfo(). |
79 virtual bool GetDeviceInfo(const FilePath& device_path, | 209 virtual bool GetDeviceInfo(const FilePath& device_path, |
80 string16* device_location, std::string* unique_id, string16* name, | 210 string16* device_location, std::string* unique_id, string16* name, |
81 bool* removable) OVERRIDE { | 211 bool* removable) OVERRIDE { |
82 return GetDeviceDetails(device_path, device_location, unique_id, name, | 212 return GetMassStorageDeviceDetails(device_path, device_location, unique_id, |
83 removable); | 213 name, removable); |
84 } | 214 } |
85 | 215 |
86 // Override VolumeMountWatcherWin::GetAttachedDevices(). | 216 // Override VolumeMountWatcherWin::GetAttachedDevices(). |
87 virtual std::vector<FilePath> GetAttachedDevices() OVERRIDE{ | 217 virtual std::vector<FilePath> GetAttachedDevices() OVERRIDE{ |
88 if (pre_attach_devices_) | 218 if (pre_attach_devices_) |
89 return GetTestAttachedDevices(); | 219 return GetTestAttachedDevices(); |
90 return std::vector<FilePath>(); | 220 return std::vector<FilePath>(); |
91 } | 221 } |
92 | 222 |
93 void set_pre_attach_devices(bool pre_attach_devices) { | 223 void set_pre_attach_devices(bool pre_attach_devices) { |
94 pre_attach_devices_ = pre_attach_devices; | 224 pre_attach_devices_ = pre_attach_devices; |
95 } | 225 } |
96 | 226 |
97 private: | 227 private: |
98 // Private, this class is ref-counted. | 228 // Private, this class is ref-counted. |
99 virtual ~TestVolumeMountWatcherWin() { | 229 virtual ~TestVolumeMountWatcherWin() { |
100 } | 230 } |
101 | 231 |
102 // Set to true to pre-attach test devices. | 232 // Set to true to pre-attach test devices. |
103 bool pre_attach_devices_; | 233 bool pre_attach_devices_; |
104 }; | 234 }; |
105 | 235 |
106 // Wrapper class for testing RemovableDeviceNotificationsWindowWin. | 236 // Wrapper class for testing RemovableDeviceNotificationsWindowWin. |
107 class TestRemovableDeviceNotificationsWindowWin | 237 class TestRemovableDeviceNotificationsWindowWin |
108 : public RemovableDeviceNotificationsWindowWin { | 238 : public RemovableDeviceNotificationsWindowWin { |
109 public: | 239 public: |
110 explicit TestRemovableDeviceNotificationsWindowWin( | 240 explicit TestRemovableDeviceNotificationsWindowWin( |
111 TestVolumeMountWatcherWin* volume_mount_watcher) | 241 TestVolumeMountWatcherWin* volume_mount_watcher, |
112 : RemovableDeviceNotificationsWindowWin(volume_mount_watcher), | 242 TestPortableDeviceWatcherWin* portable_device_watcher) |
243 : RemovableDeviceNotificationsWindowWin( | |
244 volume_mount_watcher, portable_device_watcher), | |
113 volume_mount_watcher_(volume_mount_watcher) { | 245 volume_mount_watcher_(volume_mount_watcher) { |
114 DCHECK(volume_mount_watcher_); | 246 DCHECK(volume_mount_watcher_); |
115 } | 247 } |
116 | 248 |
117 virtual ~TestRemovableDeviceNotificationsWindowWin() { | 249 virtual ~TestRemovableDeviceNotificationsWindowWin() { |
118 } | 250 } |
119 | 251 |
120 void InitWithTestData() { | 252 void InitWithTestData() { |
121 volume_mount_watcher_->set_pre_attach_devices(false); | 253 volume_mount_watcher_->set_pre_attach_devices(false); |
122 Init(); | 254 Init(); |
(...skipping 16 matching lines...) Expand all Loading... | |
139 public: | 271 public: |
140 RemovableDeviceNotificationsWindowWinTest() | 272 RemovableDeviceNotificationsWindowWinTest() |
141 : ui_thread_(BrowserThread::UI, &message_loop_), | 273 : ui_thread_(BrowserThread::UI, &message_loop_), |
142 file_thread_(BrowserThread::FILE, &message_loop_) { } | 274 file_thread_(BrowserThread::FILE, &message_loop_) { } |
143 virtual ~RemovableDeviceNotificationsWindowWinTest() { } | 275 virtual ~RemovableDeviceNotificationsWindowWinTest() { } |
144 | 276 |
145 protected: | 277 protected: |
146 virtual void SetUp() OVERRIDE { | 278 virtual void SetUp() OVERRIDE { |
147 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 279 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
148 volume_mount_watcher_ = new TestVolumeMountWatcherWin; | 280 volume_mount_watcher_ = new TestVolumeMountWatcherWin; |
281 portable_device_watcher_ = new TestPortableDeviceWatcherWin; | |
149 window_.reset(new TestRemovableDeviceNotificationsWindowWin( | 282 window_.reset(new TestRemovableDeviceNotificationsWindowWin( |
150 volume_mount_watcher_.get())); | 283 volume_mount_watcher_.get(), portable_device_watcher_.get())); |
151 window_->InitWithTestData(); | 284 window_->InitWithTestData(); |
152 message_loop_.RunAllPending(); | 285 RunAllPending(); |
153 system_monitor_.AddDevicesChangedObserver(&observer_); | 286 system_monitor_.AddDevicesChangedObserver(&observer_); |
154 } | 287 } |
155 | 288 |
156 virtual void TearDown() { | 289 virtual void TearDown() { |
157 message_loop_.RunAllPending(); | 290 RunAllPending(); |
158 system_monitor_.RemoveDevicesChangedObserver(&observer_); | 291 system_monitor_.RemoveDevicesChangedObserver(&observer_); |
159 } | 292 } |
160 | 293 |
161 void AddAttachExpectation(FilePath drive) { | 294 void AddAttachExpectation(FilePath drive) { |
162 std::string unique_id; | 295 std::string unique_id; |
163 string16 device_name; | 296 string16 device_name; |
164 bool removable; | 297 bool removable; |
165 ASSERT_TRUE(GetDeviceDetails(drive, NULL, &unique_id, &device_name, | 298 ASSERT_TRUE(GetMassStorageDeviceDetails(drive, NULL, &unique_id, |
166 &removable)); | 299 &device_name, &removable)); |
167 if (removable) { | 300 if (removable) { |
168 MediaStorageUtil::Type type = | 301 MediaStorageUtil::Type type = |
169 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM; | 302 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM; |
170 std::string device_id = MediaStorageUtil::MakeDeviceId(type, unique_id); | 303 std::string device_id = MediaStorageUtil::MakeDeviceId(type, unique_id); |
171 EXPECT_CALL(observer_, OnRemovableStorageAttached(device_id, device_name, | 304 EXPECT_CALL(observer_, OnRemovableStorageAttached(device_id, device_name, |
172 drive.value())) | 305 drive.value())) |
173 .Times(1); | 306 .Times(1); |
174 } | 307 } |
175 } | 308 } |
176 | 309 |
177 void PreAttachDevices() { | 310 void PreAttachDevices() { |
178 window_.reset(); | 311 window_.reset(); |
179 { | 312 { |
180 testing::InSequence sequence; | 313 testing::InSequence sequence; |
181 std::vector<FilePath> initial_devices = GetTestAttachedDevices(); | 314 std::vector<FilePath> initial_devices = GetTestAttachedDevices(); |
182 for (size_t i = 0; i < initial_devices.size(); i++) | 315 for (size_t i = 0; i < initial_devices.size(); i++) |
183 AddAttachExpectation(initial_devices[i]); | 316 AddAttachExpectation(initial_devices[i]); |
184 } | 317 } |
185 window_.reset(new TestRemovableDeviceNotificationsWindowWin( | 318 window_.reset(new TestRemovableDeviceNotificationsWindowWin( |
186 volume_mount_watcher_.get())); | 319 volume_mount_watcher_.get(), portable_device_watcher_.get())); |
187 window_->InitWithTestDataAndAttachedDevices(); | 320 window_->InitWithTestDataAndAttachedDevices(); |
321 RunAllPending(); | |
322 } | |
323 | |
324 // Runs all the pending tasks on UI thread and blocking thread. | |
325 void RunAllPending() { | |
326 message_loop_.RunAllPending(); | |
327 content::BrowserThread::GetBlockingPool()->FlushForTesting(); | |
188 message_loop_.RunAllPending(); | 328 message_loop_.RunAllPending(); |
189 } | 329 } |
190 | 330 |
191 void DoDevicesAttachedTest(const std::vector<int>& device_indices); | 331 void DoMassStorageDeviceAttachedTest(const std::vector<int>& device_indices); |
192 void DoDevicesDetachedTest(const std::vector<int>& device_indices); | 332 void DoMassStorageDevicesDetachedTest(const std::vector<int>& device_indices); |
333 void DoMtpDeviceAttachedTest(const string16& pnp_device_id); | |
334 void DoMtpDeviceDetachedTest(const string16& pnp_device_id); | |
193 | 335 |
194 MessageLoopForUI message_loop_; | 336 MessageLoopForUI message_loop_; |
195 content::TestBrowserThread ui_thread_; | 337 content::TestBrowserThread ui_thread_; |
196 content::TestBrowserThread file_thread_; | 338 content::TestBrowserThread file_thread_; |
197 | 339 |
198 base::SystemMonitor system_monitor_; | 340 base::SystemMonitor system_monitor_; |
199 base::MockDevicesChangedObserver observer_; | 341 base::MockDevicesChangedObserver observer_; |
200 scoped_ptr<TestRemovableDeviceNotificationsWindowWin> window_; | 342 scoped_ptr<TestRemovableDeviceNotificationsWindowWin> window_; |
201 scoped_refptr<TestVolumeMountWatcherWin> volume_mount_watcher_; | 343 scoped_refptr<TestVolumeMountWatcherWin> volume_mount_watcher_; |
344 scoped_refptr<TestPortableDeviceWatcherWin> portable_device_watcher_; | |
202 }; | 345 }; |
203 | 346 |
204 void RemovableDeviceNotificationsWindowWinTest::DoDevicesAttachedTest( | 347 void RemovableDeviceNotificationsWindowWinTest:: |
348 DoMassStorageDeviceAttachedTest( | |
205 const std::vector<int>& device_indices) { | 349 const std::vector<int>& device_indices) { |
206 DEV_BROADCAST_VOLUME volume_broadcast; | 350 DEV_BROADCAST_VOLUME volume_broadcast; |
207 volume_broadcast.dbcv_size = sizeof(volume_broadcast); | 351 volume_broadcast.dbcv_size = sizeof(volume_broadcast); |
208 volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME; | 352 volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME; |
209 volume_broadcast.dbcv_unitmask = 0x0; | 353 volume_broadcast.dbcv_unitmask = 0x0; |
210 volume_broadcast.dbcv_flags = 0x0; | 354 volume_broadcast.dbcv_flags = 0x0; |
211 { | 355 { |
212 testing::InSequence sequence; | 356 testing::InSequence sequence; |
213 for (std::vector<int>::const_iterator it = device_indices.begin(); | 357 for (std::vector<int>::const_iterator it = device_indices.begin(); |
214 it != device_indices.end(); | 358 it != device_indices.end(); |
215 ++it) { | 359 ++it) { |
216 volume_broadcast.dbcv_unitmask |= 0x1 << *it; | 360 volume_broadcast.dbcv_unitmask |= 0x1 << *it; |
217 AddAttachExpectation(DriveNumberToFilePath(*it)); | 361 AddAttachExpectation(DriveNumberToFilePath(*it)); |
218 } | 362 } |
219 } | 363 } |
220 window_->InjectDeviceChange(DBT_DEVICEARRIVAL, | 364 window_->InjectDeviceChange(DBT_DEVICEARRIVAL, |
221 reinterpret_cast<DWORD>(&volume_broadcast)); | 365 reinterpret_cast<DWORD>(&volume_broadcast)); |
222 message_loop_.RunAllPending(); | 366 RunAllPending(); |
223 } | 367 } |
224 | 368 |
225 void RemovableDeviceNotificationsWindowWinTest::DoDevicesDetachedTest( | 369 void RemovableDeviceNotificationsWindowWinTest:: |
370 DoMassStorageDevicesDetachedTest( | |
226 const std::vector<int>& device_indices) { | 371 const std::vector<int>& device_indices) { |
227 DEV_BROADCAST_VOLUME volume_broadcast; | 372 DEV_BROADCAST_VOLUME volume_broadcast; |
228 volume_broadcast.dbcv_size = sizeof(volume_broadcast); | 373 volume_broadcast.dbcv_size = sizeof(volume_broadcast); |
229 volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME; | 374 volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME; |
230 volume_broadcast.dbcv_unitmask = 0x0; | 375 volume_broadcast.dbcv_unitmask = 0x0; |
231 volume_broadcast.dbcv_flags = 0x0; | 376 volume_broadcast.dbcv_flags = 0x0; |
232 { | 377 { |
233 testing::InSequence sequence; | 378 testing::InSequence sequence; |
234 for (std::vector<int>::const_iterator it = device_indices.begin(); | 379 for (std::vector<int>::const_iterator it = device_indices.begin(); |
235 it != device_indices.end(); | 380 it != device_indices.end(); |
236 ++it) { | 381 ++it) { |
237 volume_broadcast.dbcv_unitmask |= 0x1 << *it; | 382 volume_broadcast.dbcv_unitmask |= 0x1 << *it; |
238 std::string unique_id; | 383 std::string unique_id; |
239 bool removable; | 384 bool removable; |
240 ASSERT_TRUE(GetDeviceDetails(DriveNumberToFilePath(*it), NULL, &unique_id, | 385 ASSERT_TRUE(GetMassStorageDeviceDetails(DriveNumberToFilePath(*it), NULL, |
241 NULL, &removable)); | 386 &unique_id, NULL, &removable)); |
242 if (removable) { | 387 if (removable) { |
243 MediaStorageUtil::Type type = | 388 MediaStorageUtil::Type type = |
244 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM; | 389 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM; |
245 std::string device_id = MediaStorageUtil::MakeDeviceId(type, unique_id); | 390 std::string device_id = MediaStorageUtil::MakeDeviceId(type, unique_id); |
246 EXPECT_CALL(observer_, OnRemovableStorageDetached(device_id)).Times(1); | 391 EXPECT_CALL(observer_, OnRemovableStorageDetached(device_id)).Times(1); |
247 } | 392 } |
248 } | 393 } |
249 } | 394 } |
250 window_->InjectDeviceChange(DBT_DEVICEREMOVECOMPLETE, | 395 window_->InjectDeviceChange(DBT_DEVICEREMOVECOMPLETE, |
251 reinterpret_cast<DWORD>(&volume_broadcast)); | 396 reinterpret_cast<DWORD>(&volume_broadcast)); |
252 message_loop_.RunAllPending(); | 397 RunAllPending(); |
398 } | |
399 | |
400 void RemovableDeviceNotificationsWindowWinTest::DoMtpDeviceAttachedTest( | |
401 const string16& pnp_device_id) { | |
402 GUID guidDevInterface = GUID_NULL; | |
403 HRESULT hr = CLSIDFromString(kWPDDevInterfaceGUID, &guidDevInterface); | |
404 if (FAILED(hr)) | |
405 return; | |
406 | |
407 size_t device_id_size = pnp_device_id.size() * sizeof(char16); | |
408 size_t dbcc_name_size = device_id_size + sizeof(char16); | |
Peter Kasting
2012/10/19 21:31:12
Nit: Inline into next statement (2 places)
kmadhusu
2012/10/23 23:44:17
I would like to leave this as it is. To me, this i
Peter Kasting
2012/10/24 00:06:32
Actually, now that I look closer, this statement i
| |
409 size_t size = sizeof(DEV_BROADCAST_DEVICEINTERFACE) + dbcc_name_size; | |
410 scoped_ptr_malloc<DEV_BROADCAST_DEVICEINTERFACE> dev_interface_broadcast( | |
Peter Kasting
2012/10/19 21:31:12
Ugh, why are you using scoped_ptr_malloc<> and Zer
kmadhusu
2012/10/23 23:44:17
By default, DEV_BROADCAST_DEVICEINTERFACE dbcc_nam
Peter Kasting
2012/10/24 00:06:32
Yeah, you're fine. I didn't really realize this s
| |
411 static_cast<DEV_BROADCAST_DEVICEINTERFACE*>(malloc(size))); | |
412 DCHECK(dev_interface_broadcast.get()); | |
413 ZeroMemory(dev_interface_broadcast.get(), size); | |
414 dev_interface_broadcast->dbcc_size = size; | |
415 dev_interface_broadcast->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; | |
416 dev_interface_broadcast->dbcc_classguid = guidDevInterface; | |
417 memcpy(dev_interface_broadcast->dbcc_name, pnp_device_id.data(), | |
418 device_id_size); | |
419 { | |
420 testing::InSequence sequence; | |
421 std::vector<string16> storages = GetMtpStorageObjectId(pnp_device_id); | |
422 for (size_t index = 0; index < storages.size(); ++index) { | |
423 std::string unique_id; | |
424 string16 name; | |
425 string16 location; | |
426 ASSERT_TRUE(GetMtpStorageDetails(pnp_device_id, storages[index], | |
427 &location, &unique_id, &name)); | |
428 int cardinality = 1; | |
429 if (name.empty() || unique_id.empty()) | |
430 cardinality = 0; | |
431 EXPECT_CALL(observer_, OnRemovableStorageAttached(unique_id, name, | |
432 location)) | |
433 .Times(cardinality); | |
434 } | |
435 } | |
436 window_->InjectDeviceChange( | |
437 DBT_DEVICEARRIVAL, | |
438 reinterpret_cast<DWORD>(dev_interface_broadcast.get())); | |
439 RunAllPending(); | |
440 } | |
441 | |
442 void RemovableDeviceNotificationsWindowWinTest::DoMtpDeviceDetachedTest( | |
443 const string16& pnp_device_id) { | |
444 GUID guidDevInterface = GUID_NULL; | |
445 HRESULT hr = CLSIDFromString(kWPDDevInterfaceGUID, &guidDevInterface); | |
446 if (FAILED(hr)) | |
447 return; | |
448 | |
449 size_t device_id_size = pnp_device_id.size() * sizeof(char16); | |
450 size_t dbcc_name_size = device_id_size + sizeof(char16); | |
451 size_t size = sizeof(DEV_BROADCAST_DEVICEINTERFACE) + dbcc_name_size; | |
452 scoped_ptr_malloc<DEV_BROADCAST_DEVICEINTERFACE> dev_interface_broadcast( | |
453 static_cast<DEV_BROADCAST_DEVICEINTERFACE*>(malloc(size))); | |
454 DCHECK(dev_interface_broadcast.get()); | |
455 ZeroMemory(dev_interface_broadcast.get(), size); | |
456 dev_interface_broadcast->dbcc_size = size; | |
457 dev_interface_broadcast->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; | |
458 dev_interface_broadcast->dbcc_classguid = guidDevInterface; | |
459 memcpy(dev_interface_broadcast->dbcc_name, pnp_device_id.data(), | |
460 device_id_size); | |
461 { | |
462 testing::InSequence sequence; | |
463 std::vector<string16> storages = GetMtpStorageObjectId(pnp_device_id); | |
464 for (size_t index = 0; index < storages.size(); ++index) { | |
465 std::string unique_id; | |
466 string16 name; | |
467 ASSERT_TRUE(GetMtpStorageDetails(pnp_device_id, storages[index], NULL, | |
468 &unique_id, &name)); | |
469 int cardinality = 1; | |
470 if (name.empty() || unique_id.empty()) | |
471 cardinality = 0; | |
472 EXPECT_CALL(observer_, OnRemovableStorageDetached(unique_id)) | |
473 .Times(cardinality); | |
474 } | |
475 } | |
476 window_->InjectDeviceChange( | |
477 DBT_DEVICEREMOVECOMPLETE, | |
478 reinterpret_cast<DWORD>(dev_interface_broadcast.get())); | |
479 RunAllPending(); | |
253 } | 480 } |
254 | 481 |
255 TEST_F(RemovableDeviceNotificationsWindowWinTest, RandomMessage) { | 482 TEST_F(RemovableDeviceNotificationsWindowWinTest, RandomMessage) { |
256 window_->InjectDeviceChange(DBT_DEVICEQUERYREMOVE, NULL); | 483 window_->InjectDeviceChange(DBT_DEVICEQUERYREMOVE, NULL); |
257 message_loop_.RunAllPending(); | 484 RunAllPending(); |
258 } | 485 } |
259 | 486 |
260 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttached) { | 487 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttached) { |
261 std::vector<int> device_indices; | 488 std::vector<int> device_indices; |
262 device_indices.push_back(1); | 489 device_indices.push_back(1); |
263 device_indices.push_back(5); | 490 device_indices.push_back(5); |
264 device_indices.push_back(7); | 491 device_indices.push_back(7); |
265 device_indices.push_back(13); | 492 device_indices.push_back(13); |
266 | 493 |
267 DoDevicesAttachedTest(device_indices); | 494 DoMassStorageDeviceAttachedTest(device_indices); |
268 } | 495 } |
269 | 496 |
270 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedHighBoundary) { | 497 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedHighBoundary) { |
271 std::vector<int> device_indices; | 498 std::vector<int> device_indices; |
272 device_indices.push_back(25); | 499 device_indices.push_back(25); |
273 | 500 |
274 DoDevicesAttachedTest(device_indices); | 501 DoMassStorageDeviceAttachedTest(device_indices); |
275 } | 502 } |
276 | 503 |
277 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedLowBoundary) { | 504 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedLowBoundary) { |
278 std::vector<int> device_indices; | 505 std::vector<int> device_indices; |
279 device_indices.push_back(0); | 506 device_indices.push_back(0); |
280 | 507 |
281 DoDevicesAttachedTest(device_indices); | 508 DoMassStorageDeviceAttachedTest(device_indices); |
282 } | 509 } |
283 | 510 |
284 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedAdjacentBits) { | 511 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedAdjacentBits) { |
285 std::vector<int> device_indices; | 512 std::vector<int> device_indices; |
286 device_indices.push_back(0); | 513 device_indices.push_back(0); |
287 device_indices.push_back(1); | 514 device_indices.push_back(1); |
288 device_indices.push_back(2); | 515 device_indices.push_back(2); |
289 device_indices.push_back(3); | 516 device_indices.push_back(3); |
290 | 517 |
291 DoDevicesAttachedTest(device_indices); | 518 DoMassStorageDeviceAttachedTest(device_indices); |
292 } | 519 } |
293 | 520 |
294 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetached) { | 521 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetached) { |
295 PreAttachDevices(); | 522 PreAttachDevices(); |
296 | 523 |
297 std::vector<int> device_indices; | 524 std::vector<int> device_indices; |
298 device_indices.push_back(1); | 525 device_indices.push_back(1); |
299 device_indices.push_back(5); | 526 device_indices.push_back(5); |
300 device_indices.push_back(7); | 527 device_indices.push_back(7); |
301 device_indices.push_back(13); | 528 device_indices.push_back(13); |
302 | 529 |
303 DoDevicesDetachedTest(device_indices); | 530 DoMassStorageDevicesDetachedTest(device_indices); |
304 } | 531 } |
305 | 532 |
306 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetachedHighBoundary) { | 533 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetachedHighBoundary) { |
307 PreAttachDevices(); | 534 PreAttachDevices(); |
308 | 535 |
309 std::vector<int> device_indices; | 536 std::vector<int> device_indices; |
310 device_indices.push_back(25); | 537 device_indices.push_back(25); |
311 | 538 |
312 DoDevicesDetachedTest(device_indices); | 539 DoMassStorageDevicesDetachedTest(device_indices); |
313 } | 540 } |
314 | 541 |
315 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetachedLowBoundary) { | 542 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetachedLowBoundary) { |
316 PreAttachDevices(); | 543 PreAttachDevices(); |
317 | 544 |
318 std::vector<int> device_indices; | 545 std::vector<int> device_indices; |
319 device_indices.push_back(0); | 546 device_indices.push_back(0); |
320 | 547 |
321 DoDevicesDetachedTest(device_indices); | 548 DoMassStorageDevicesDetachedTest(device_indices); |
322 } | 549 } |
323 | 550 |
324 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetachedAdjacentBits) { | 551 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetachedAdjacentBits) { |
325 PreAttachDevices(); | 552 PreAttachDevices(); |
326 | 553 |
327 std::vector<int> device_indices; | 554 std::vector<int> device_indices; |
328 device_indices.push_back(0); | 555 device_indices.push_back(0); |
329 device_indices.push_back(1); | 556 device_indices.push_back(1); |
330 device_indices.push_back(2); | 557 device_indices.push_back(2); |
331 device_indices.push_back(3); | 558 device_indices.push_back(3); |
332 | 559 |
333 DoDevicesDetachedTest(device_indices); | 560 DoMassStorageDevicesDetachedTest(device_indices); |
334 } | 561 } |
335 | 562 |
336 TEST_F(RemovableDeviceNotificationsWindowWinTest, DeviceInfoFoPath) { | 563 TEST_F(RemovableDeviceNotificationsWindowWinTest, DeviceInfoFoPath) { |
337 PreAttachDevices(); | 564 PreAttachDevices(); |
338 | 565 |
339 // An invalid path. | 566 // An invalid path. |
340 EXPECT_FALSE(window_->GetDeviceInfoForPath(FilePath(L"COM1:\\"), NULL)); | 567 EXPECT_FALSE(window_->GetDeviceInfoForPath(FilePath(L"COM1:\\"), NULL)); |
341 | 568 |
342 // An unconnected removable device. | 569 // An unconnected removable device. |
343 EXPECT_FALSE(window_->GetDeviceInfoForPath(FilePath(L"E:\\"), NULL)); | 570 EXPECT_FALSE(window_->GetDeviceInfoForPath(FilePath(L"E:\\"), NULL)); |
344 | 571 |
345 // A connected removable device. | 572 // A connected removable device. |
346 FilePath removable_device(L"F:\\"); | 573 FilePath removable_device(L"F:\\"); |
347 base::SystemMonitor::RemovableStorageInfo device_info; | 574 base::SystemMonitor::RemovableStorageInfo device_info; |
348 EXPECT_TRUE(window_->GetDeviceInfoForPath(removable_device, &device_info)); | 575 EXPECT_TRUE(window_->GetDeviceInfoForPath(removable_device, &device_info)); |
349 | 576 |
350 std::string unique_id; | 577 std::string unique_id; |
351 string16 device_name; | 578 string16 device_name; |
352 bool removable; | 579 bool removable; |
353 ASSERT_TRUE(GetDeviceDetails(removable_device, NULL, &unique_id, &device_name, | 580 ASSERT_TRUE(GetMassStorageDeviceDetails(removable_device, NULL, &unique_id, |
354 &removable)); | 581 &device_name, &removable)); |
355 EXPECT_TRUE(removable); | 582 EXPECT_TRUE(removable); |
356 std::string device_id = MediaStorageUtil::MakeDeviceId( | 583 std::string device_id = MediaStorageUtil::MakeDeviceId( |
357 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM, unique_id); | 584 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM, unique_id); |
358 EXPECT_EQ(device_id, device_info.device_id); | 585 EXPECT_EQ(device_id, device_info.device_id); |
359 EXPECT_EQ(device_name, device_info.name); | 586 EXPECT_EQ(device_name, device_info.name); |
360 EXPECT_EQ(removable_device.value(), device_info.location); | 587 EXPECT_EQ(removable_device.value(), device_info.location); |
361 | 588 |
362 // A fixed device. | 589 // A fixed device. |
363 FilePath fixed_device(L"N:\\"); | 590 FilePath fixed_device(L"N:\\"); |
364 EXPECT_TRUE(window_->GetDeviceInfoForPath(fixed_device, &device_info)); | 591 EXPECT_TRUE(window_->GetDeviceInfoForPath(fixed_device, &device_info)); |
365 | 592 |
366 ASSERT_TRUE(GetDeviceDetails(fixed_device, NULL, &unique_id, &device_name, | 593 ASSERT_TRUE(GetMassStorageDeviceDetails(fixed_device, NULL, &unique_id, |
367 &removable)); | 594 &device_name, &removable)); |
368 EXPECT_FALSE(removable); | 595 EXPECT_FALSE(removable); |
369 device_id = MediaStorageUtil::MakeDeviceId( | 596 device_id = MediaStorageUtil::MakeDeviceId( |
370 MediaStorageUtil::FIXED_MASS_STORAGE, unique_id); | 597 MediaStorageUtil::FIXED_MASS_STORAGE, unique_id); |
371 EXPECT_EQ(device_id, device_info.device_id); | 598 EXPECT_EQ(device_id, device_info.device_id); |
372 EXPECT_EQ(device_name, device_info.name); | 599 EXPECT_EQ(device_name, device_info.name); |
373 EXPECT_EQ(fixed_device.value(), device_info.location); | 600 EXPECT_EQ(fixed_device.value(), device_info.location); |
374 } | 601 } |
375 | 602 |
603 // Test to verify basic mtp storage attach and detach notifications. | |
604 TEST_F(RemovableDeviceNotificationsWindowWinTest, MtpDeviceBasicAttachDetach) { | |
605 // Attach a mtp device. | |
606 DoMtpDeviceAttachedTest(kMtpDeviceWithValidInfo); | |
607 | |
608 // Detach the attached device. | |
609 DoMtpDeviceDetachedTest(kMtpDeviceWithValidInfo); | |
610 } | |
611 | |
612 // When a mtp storage device with invalid storage label and id is | |
613 // attached/detached, there should not be any device attach/detach | |
614 // notifications. | |
615 TEST_F(RemovableDeviceNotificationsWindowWinTest, MtpDeviceWithInvalidInfo) { | |
616 // Attach the mtp storage with invalid storage info. | |
617 DoMtpDeviceAttachedTest(kMtpDeviceWithInvalidInfo); | |
618 | |
619 // Detach the attached storage. | |
620 DoMtpDeviceDetachedTest(kMtpDeviceWithInvalidInfo); | |
621 } | |
622 | |
623 // Attach a device with two data storages. Verify that attach/detach | |
624 // notifications are sent out for each removable storage. | |
625 TEST_F(RemovableDeviceNotificationsWindowWinTest, | |
626 MtpDeviceWithMultipleStorages) { | |
627 // Attach the mtp device with multiple storage. | |
628 DoMtpDeviceAttachedTest(kMtpDeviceWithMultipleStorage); | |
629 | |
630 // Detach the attached device. | |
631 DoMtpDeviceDetachedTest(kMtpDeviceWithMultipleStorage); | |
632 } | |
633 | |
376 } // namespace chrome | 634 } // namespace chrome |
OLD | NEW |