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

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

Powered by Google App Engine
This is Rietveld 408576698