Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(314)

Side by Side Diff: chrome/browser/system_monitor/removable_device_notifications_window_win_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698