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

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: Rebase 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 PortableDeviceWatcherWin::StorageObjectIDs::const_iterator it =
163 storage_object_ids.begin();
164 for (; it != storage_object_ids.end(); ++it) {
165 storage_objects.push_back(PortableDeviceWatcherWin::DeviceStorageObject(
166 *it, GetMTPStorageUniqueId(pnp_device_id, *it)));
167 }
168 return storage_objects;
169 }
170
68 } // namespace 171 } // namespace
69 172
70 namespace chrome {
71 173
72 // Wrapper class for testing VolumeMountWatcherWin. 174 // TestPortableDeviceWatcherWin -----------------------------------------------
175
176 class TestPortableDeviceWatcherWin : public PortableDeviceWatcherWin {
177 public:
178 TestPortableDeviceWatcherWin();
179 virtual ~TestPortableDeviceWatcherWin();
180
181 private:
182 // PortableDeviceWatcherWin:
183 virtual void EnumerateAttachedDevices() OVERRIDE;
184 virtual void HandleDeviceAttachEvent(const string16& pnp_device_id) OVERRIDE;
185
186 DISALLOW_COPY_AND_ASSIGN(TestPortableDeviceWatcherWin);
187 };
188
189 TestPortableDeviceWatcherWin::TestPortableDeviceWatcherWin() {
190 }
191
192 TestPortableDeviceWatcherWin::~TestPortableDeviceWatcherWin() {
193 }
194
195 void TestPortableDeviceWatcherWin::EnumerateAttachedDevices() {
196 }
197
198 void TestPortableDeviceWatcherWin::HandleDeviceAttachEvent(
199 const string16& pnp_device_id) {
200 DeviceDetails device_details = {
201 (pnp_device_id != kMTPDeviceWithInvalidInfo) ?
202 kMTPDeviceFriendlyName : string16(),
203 pnp_device_id,
204 GetDeviceStorageObjects(pnp_device_id)
205 };
206 OnDidHandleDeviceAttachEvent(&device_details, true);
207 }
208
209
210 // TestVolumeMountWatcherWin --------------------------------------------------
211
73 class TestVolumeMountWatcherWin : public VolumeMountWatcherWin { 212 class TestVolumeMountWatcherWin : public VolumeMountWatcherWin {
74 public: 213 public:
75 TestVolumeMountWatcherWin() : pre_attach_devices_(false) { 214 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 215
93 void set_pre_attach_devices(bool pre_attach_devices) { 216 void set_pre_attach_devices(bool pre_attach_devices) {
94 pre_attach_devices_ = pre_attach_devices; 217 pre_attach_devices_ = pre_attach_devices;
95 } 218 }
96 219
97 private: 220 private:
98 // Private, this class is ref-counted. 221 // Private, this class is ref-counted.
99 virtual ~TestVolumeMountWatcherWin() { 222 virtual ~TestVolumeMountWatcherWin();
100 } 223
224 // VolumeMountWatcherWin:
225 virtual bool GetDeviceInfo(const FilePath& device_path,
226 string16* device_location,
227 std::string* unique_id,
228 string16* name,
229 bool* removable) OVERRIDE;
230 virtual AttachedDevices GetAttachedDevices() OVERRIDE;
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_;
234
235 DISALLOW_COPY_AND_ASSIGN(TestVolumeMountWatcherWin);
104 }; 236 };
105 237
106 // Wrapper class for testing RemovableDeviceNotificationsWindowWin. 238 TestVolumeMountWatcherWin::TestVolumeMountWatcherWin()
239 : pre_attach_devices_(false) {
240 }
241
242 TestVolumeMountWatcherWin::~TestVolumeMountWatcherWin() {
243 }
244
245 bool TestVolumeMountWatcherWin::GetDeviceInfo(const FilePath& device_path,
246 string16* device_location,
247 std::string* unique_id,
248 string16* name,
249 bool* removable) {
250 return GetMassStorageDeviceDetails(device_path, device_location, unique_id,
251 name, removable);
252 }
253
254 AttachedDevices TestVolumeMountWatcherWin::GetAttachedDevices() {
255 return pre_attach_devices_ ?
256 GetTestAttachedDevices() : AttachedDevices();
257 }
258
259
260 // TestRemovableDeviceNotificationsWindowWin -----------------------------------
261
107 class TestRemovableDeviceNotificationsWindowWin 262 class TestRemovableDeviceNotificationsWindowWin
108 : public RemovableDeviceNotificationsWindowWin { 263 : public RemovableDeviceNotificationsWindowWin {
109 public: 264 public:
110 explicit TestRemovableDeviceNotificationsWindowWin( 265 TestRemovableDeviceNotificationsWindowWin(
111 TestVolumeMountWatcherWin* volume_mount_watcher) 266 TestVolumeMountWatcherWin* volume_mount_watcher,
112 : RemovableDeviceNotificationsWindowWin(volume_mount_watcher), 267 TestPortableDeviceWatcherWin* portable_device_watcher);
113 volume_mount_watcher_(volume_mount_watcher) {
114 DCHECK(volume_mount_watcher_);
115 }
116 268
117 virtual ~TestRemovableDeviceNotificationsWindowWin() { 269 virtual ~TestRemovableDeviceNotificationsWindowWin();
118 }
119 270
120 void InitWithTestData() { 271 void InitWithTestData(bool pre_attach_devices);
121 volume_mount_watcher_->set_pre_attach_devices(false); 272 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 273
134 private: 274 private:
135 scoped_refptr<TestVolumeMountWatcherWin> volume_mount_watcher_; 275 scoped_refptr<TestVolumeMountWatcherWin> volume_mount_watcher_;
136 }; 276 };
137 277
278 TestRemovableDeviceNotificationsWindowWin::
279 TestRemovableDeviceNotificationsWindowWin(
280 TestVolumeMountWatcherWin* volume_mount_watcher,
281 TestPortableDeviceWatcherWin* portable_device_watcher)
282 : RemovableDeviceNotificationsWindowWin(volume_mount_watcher,
283 portable_device_watcher),
284 volume_mount_watcher_(volume_mount_watcher) {
285 DCHECK(volume_mount_watcher_);
286 }
287
288 TestRemovableDeviceNotificationsWindowWin::
289 ~TestRemovableDeviceNotificationsWindowWin() {
290 }
291
292 void TestRemovableDeviceNotificationsWindowWin::InitWithTestData(
293 bool pre_attach_devices) {
294 volume_mount_watcher_->set_pre_attach_devices(pre_attach_devices);
295 Init();
296 }
297
298 void TestRemovableDeviceNotificationsWindowWin::InjectDeviceChange(
299 UINT event_type,
300 DWORD data) {
301 OnDeviceChange(event_type, data);
302 }
303
304
305 // RemovableDeviceNotificationsWindowWinTest -----------------------------------
306
138 class RemovableDeviceNotificationsWindowWinTest : public testing::Test { 307 class RemovableDeviceNotificationsWindowWinTest : public testing::Test {
139 public: 308 public:
140 RemovableDeviceNotificationsWindowWinTest() 309 RemovableDeviceNotificationsWindowWinTest();
141 : ui_thread_(BrowserThread::UI, &message_loop_), 310 virtual ~RemovableDeviceNotificationsWindowWinTest();
142 file_thread_(BrowserThread::FILE, &message_loop_) { }
143 virtual ~RemovableDeviceNotificationsWindowWinTest() { }
144 311
145 protected: 312 protected:
146 virtual void SetUp() OVERRIDE { 313 // testing::Test:
147 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); 314 virtual void SetUp() OVERRIDE;
148 volume_mount_watcher_ = new TestVolumeMountWatcherWin; 315 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 316
156 virtual void TearDown() { 317 void AddMassStorageDeviceAttachExpectation(FilePath drive);
157 message_loop_.RunAllPending(); 318 void PreAttachDevices();
158 system_monitor_.RemoveDevicesChangedObserver(&observer_);
159 }
160 319
161 void AddAttachExpectation(FilePath drive) { 320 // Runs all the pending tasks on UI thread, FILE thread and blocking thread.
162 std::string unique_id; 321 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 322
177 void PreAttachDevices() { 323 void DoMassStorageDeviceAttachedTest(const DeviceIndices& device_indices);
178 window_.reset(); 324 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 325
191 void DoDevicesAttachedTest(const std::vector<int>& device_indices); 326 // Injects a device attach or detach change (depending on the value of
192 void DoDevicesDetachedTest(const std::vector<int>& device_indices); 327 // |test_attach|) and tests that the appropriate handler is called.
328 void DoMTPDeviceTest(const string16& pnp_device_id, bool test_attach);
193 329
194 MessageLoopForUI message_loop_; 330 MessageLoopForUI message_loop_;
195 content::TestBrowserThread ui_thread_; 331 content::TestBrowserThread ui_thread_;
196 content::TestBrowserThread file_thread_; 332 content::TestBrowserThread file_thread_;
197 333
198 base::SystemMonitor system_monitor_; 334 base::SystemMonitor system_monitor_;
199 base::MockDevicesChangedObserver observer_; 335 base::MockDevicesChangedObserver observer_;
200 scoped_ptr<TestRemovableDeviceNotificationsWindowWin> window_; 336 scoped_ptr<TestRemovableDeviceNotificationsWindowWin> window_;
201 scoped_refptr<TestVolumeMountWatcherWin> volume_mount_watcher_; 337 scoped_refptr<TestVolumeMountWatcherWin> volume_mount_watcher_;
202 }; 338 };
203 339
204 void RemovableDeviceNotificationsWindowWinTest::DoDevicesAttachedTest( 340 RemovableDeviceNotificationsWindowWinTest::
205 const std::vector<int>& device_indices) { 341 RemovableDeviceNotificationsWindowWinTest()
342 : ui_thread_(BrowserThread::UI, &message_loop_),
343 file_thread_(BrowserThread::FILE, &message_loop_) {
344 }
345
346 RemovableDeviceNotificationsWindowWinTest::
347 ~RemovableDeviceNotificationsWindowWinTest() {
348 }
349
350 void RemovableDeviceNotificationsWindowWinTest::SetUp() {
351 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
352 volume_mount_watcher_ = new TestVolumeMountWatcherWin;
353 window_.reset(new TestRemovableDeviceNotificationsWindowWin(
354 volume_mount_watcher_.get(), new TestPortableDeviceWatcherWin));
355 window_->InitWithTestData(false);
356 RunAllPending();
357 system_monitor_.AddDevicesChangedObserver(&observer_);
358 }
359
360 void RemovableDeviceNotificationsWindowWinTest::TearDown() {
361 RunAllPending();
362 system_monitor_.RemoveDevicesChangedObserver(&observer_);
363 }
364
365 void RemovableDeviceNotificationsWindowWinTest::
366 AddMassStorageDeviceAttachExpectation(FilePath drive) {
367 std::string unique_id;
368 string16 device_name;
369 bool removable;
370 ASSERT_TRUE(GetMassStorageDeviceDetails(drive, NULL, &unique_id,
371 &device_name, &removable));
372 if (removable) {
373 MediaStorageUtil::Type type =
374 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM;
375 std::string device_id = MediaStorageUtil::MakeDeviceId(type, unique_id);
376 EXPECT_CALL(observer_, OnRemovableStorageAttached(device_id, device_name,
377 drive.value()))
378 .Times(1);
379 }
380 }
381
382 void RemovableDeviceNotificationsWindowWinTest::PreAttachDevices() {
383 window_.reset();
384 {
385 testing::InSequence sequence;
386 AttachedDevices initial_devices = GetTestAttachedDevices();
387 for (AttachedDevices::const_iterator it = initial_devices.begin();
388 it != initial_devices.end(); ++it) {
389 AddMassStorageDeviceAttachExpectation(*it);
390 }
391 }
392 window_.reset(new TestRemovableDeviceNotificationsWindowWin(
393 volume_mount_watcher_.get(), new TestPortableDeviceWatcherWin));
394 window_->InitWithTestData(true);
395 RunAllPending();
396 }
397
398 void RemovableDeviceNotificationsWindowWinTest::RunAllPending() {
399 message_loop_.RunAllPending();
400 }
401
402 void RemovableDeviceNotificationsWindowWinTest::
403 DoMassStorageDeviceAttachedTest(const DeviceIndices& 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 (DeviceIndices::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 DeviceIndices& 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 (DeviceIndices::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::DoMTPDeviceTest(
454 const string16& pnp_device_id, bool test_attach) {
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 PortableDeviceWatcherWin::StorageObjectIDs storage_object_ids =
474 GetMTPStorageObjectIds(pnp_device_id);
475 PortableDeviceWatcherWin::StorageObjectIDs::const_iterator it =
476 storage_object_ids.begin();
477 for (; it != storage_object_ids.end(); ++it) {
478 std::string unique_id;
479 string16 name;
480 string16 location;
481 GetMTPStorageDetails(pnp_device_id, *it, &location, &unique_id, &name);
482 if (test_attach) {
483 EXPECT_CALL(observer_, OnRemovableStorageAttached(unique_id, name,
484 location))
485 .Times((name.empty() || unique_id.empty()) ? 0 : 1);
486 } else {
487 EXPECT_CALL(observer_, OnRemovableStorageDetached(unique_id))
488 .Times((name.empty() || unique_id.empty()) ? 0 : 1);
489 }
490 }
491 }
492 window_->InjectDeviceChange(
493 test_attach ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE,
494 reinterpret_cast<DWORD>(dev_interface_broadcast.get()));
495 RunAllPending();
253 } 496 }
254 497
255 TEST_F(RemovableDeviceNotificationsWindowWinTest, RandomMessage) { 498 TEST_F(RemovableDeviceNotificationsWindowWinTest, RandomMessage) {
256 window_->InjectDeviceChange(DBT_DEVICEQUERYREMOVE, NULL); 499 window_->InjectDeviceChange(DBT_DEVICEQUERYREMOVE, NULL);
257 message_loop_.RunAllPending(); 500 RunAllPending();
258 } 501 }
259 502
260 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttached) { 503 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttached) {
261 std::vector<int> device_indices; 504 DeviceIndices device_indices;
262 device_indices.push_back(1); 505 device_indices.push_back(1);
263 device_indices.push_back(5); 506 device_indices.push_back(5);
264 device_indices.push_back(7); 507 device_indices.push_back(7);
265 device_indices.push_back(13); 508 device_indices.push_back(13);
266 509
267 DoDevicesAttachedTest(device_indices); 510 DoMassStorageDeviceAttachedTest(device_indices);
268 } 511 }
269 512
270 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedHighBoundary) { 513 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedHighBoundary) {
271 std::vector<int> device_indices; 514 DeviceIndices device_indices;
272 device_indices.push_back(25); 515 device_indices.push_back(25);
273 516
274 DoDevicesAttachedTest(device_indices); 517 DoMassStorageDeviceAttachedTest(device_indices);
275 } 518 }
276 519
277 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedLowBoundary) { 520 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedLowBoundary) {
278 std::vector<int> device_indices; 521 DeviceIndices device_indices;
279 device_indices.push_back(0); 522 device_indices.push_back(0);
280 523
281 DoDevicesAttachedTest(device_indices); 524 DoMassStorageDeviceAttachedTest(device_indices);
282 } 525 }
283 526
284 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedAdjacentBits) { 527 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedAdjacentBits) {
285 std::vector<int> device_indices; 528 DeviceIndices device_indices;
286 device_indices.push_back(0); 529 device_indices.push_back(0);
287 device_indices.push_back(1); 530 device_indices.push_back(1);
288 device_indices.push_back(2); 531 device_indices.push_back(2);
289 device_indices.push_back(3); 532 device_indices.push_back(3);
290 533
291 DoDevicesAttachedTest(device_indices); 534 DoMassStorageDeviceAttachedTest(device_indices);
292 } 535 }
293 536
294 // Disabled until http://crbug.com/155910 is resolved. 537 // Disabled until http://crbug.com/155910 is resolved.
295 TEST_F(RemovableDeviceNotificationsWindowWinTest, DISABLED_DevicesDetached) { 538 TEST_F(RemovableDeviceNotificationsWindowWinTest, DISABLED_DevicesDetached) {
296 PreAttachDevices(); 539 PreAttachDevices();
297 540
298 std::vector<int> device_indices; 541 DeviceIndices device_indices;
299 device_indices.push_back(1); 542 device_indices.push_back(1);
300 device_indices.push_back(5); 543 device_indices.push_back(5);
301 device_indices.push_back(7); 544 device_indices.push_back(7);
302 device_indices.push_back(13); 545 device_indices.push_back(13);
303 546
304 DoDevicesDetachedTest(device_indices); 547 DoMassStorageDeviceAttachedTest(device_indices);
305 } 548 }
306 549
307 // Disabled until http://crbug.com/155910 is resolved. 550 // Disabled until http://crbug.com/155910 is resolved.
308 TEST_F(RemovableDeviceNotificationsWindowWinTest, 551 TEST_F(RemovableDeviceNotificationsWindowWinTest,
309 DISABLED_DevicesDetachedHighBoundary) { 552 DISABLED_DevicesDetachedHighBoundary) {
310 PreAttachDevices(); 553 PreAttachDevices();
311 554
312 std::vector<int> device_indices; 555 DeviceIndices device_indices;
313 device_indices.push_back(25); 556 device_indices.push_back(25);
314 557
315 DoDevicesDetachedTest(device_indices); 558 DoMassStorageDeviceAttachedTest(device_indices);
316 } 559 }
317 560
318 // Disabled until http://crbug.com/155910 is resolved. 561 // Disabled until http://crbug.com/155910 is resolved.
319 TEST_F(RemovableDeviceNotificationsWindowWinTest, 562 TEST_F(RemovableDeviceNotificationsWindowWinTest,
320 DISABLED_DevicesDetachedLowBoundary) { 563 DISABLED_DevicesDetachedLowBoundary) {
321 PreAttachDevices(); 564 PreAttachDevices();
322 565
323 std::vector<int> device_indices; 566 DeviceIndices device_indices;
324 device_indices.push_back(0); 567 device_indices.push_back(0);
325 568
326 DoDevicesDetachedTest(device_indices); 569 DoMassStorageDeviceAttachedTest(device_indices);
327 } 570 }
328 571
329 // Disabled until http://crbug.com/155910 is resolved. 572 // Disabled until http://crbug.com/155910 is resolved.
330 TEST_F(RemovableDeviceNotificationsWindowWinTest, 573 TEST_F(RemovableDeviceNotificationsWindowWinTest,
331 DISABLED_DevicesDetachedAdjacentBits) { 574 DISABLED_DevicesDetachedAdjacentBits) {
332 PreAttachDevices(); 575 PreAttachDevices();
333 576
334 std::vector<int> device_indices; 577 DeviceIndices device_indices;
335 device_indices.push_back(0); 578 device_indices.push_back(0);
336 device_indices.push_back(1); 579 device_indices.push_back(1);
337 device_indices.push_back(2); 580 device_indices.push_back(2);
338 device_indices.push_back(3); 581 device_indices.push_back(3);
339 582
340 DoDevicesDetachedTest(device_indices); 583 DoMassStorageDeviceAttachedTest(device_indices);
341 } 584 }
342 585
343 // Disabled until http://crbug.com/155910 is resolved. 586 // Disabled until http://crbug.com/155910 is resolved.
344 TEST_F(RemovableDeviceNotificationsWindowWinTest, DISABLED_DeviceInfoForPath) { 587 TEST_F(RemovableDeviceNotificationsWindowWinTest, DISABLED_DeviceInfoForPath) {
345 PreAttachDevices(); 588 PreAttachDevices();
346 589
347 // An invalid path. 590 // An invalid path.
348 EXPECT_FALSE(window_->GetDeviceInfoForPath(FilePath(L"COM1:\\"), NULL)); 591 EXPECT_FALSE(window_->GetDeviceInfoForPath(FilePath(L"COM1:\\"), NULL));
349 592
350 // An unconnected removable device. 593 // An unconnected removable device.
351 EXPECT_FALSE(window_->GetDeviceInfoForPath(FilePath(L"E:\\"), NULL)); 594 EXPECT_FALSE(window_->GetDeviceInfoForPath(FilePath(L"E:\\"), NULL));
352 595
353 // A connected removable device. 596 // A connected removable device.
354 FilePath removable_device(L"F:\\"); 597 FilePath removable_device(L"F:\\");
355 base::SystemMonitor::RemovableStorageInfo device_info; 598 base::SystemMonitor::RemovableStorageInfo device_info;
356 EXPECT_TRUE(window_->GetDeviceInfoForPath(removable_device, &device_info)); 599 EXPECT_TRUE(window_->GetDeviceInfoForPath(removable_device, &device_info));
357 600
358 std::string unique_id; 601 std::string unique_id;
359 string16 device_name; 602 string16 device_name;
360 bool removable; 603 bool removable;
361 ASSERT_TRUE(GetDeviceDetails(removable_device, NULL, &unique_id, &device_name, 604 ASSERT_TRUE(GetMassStorageDeviceDetails(removable_device, NULL, &unique_id,
362 &removable)); 605 &device_name, &removable));
363 EXPECT_TRUE(removable); 606 EXPECT_TRUE(removable);
364 std::string device_id = MediaStorageUtil::MakeDeviceId( 607 std::string device_id = MediaStorageUtil::MakeDeviceId(
365 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM, unique_id); 608 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM, unique_id);
366 EXPECT_EQ(device_id, device_info.device_id); 609 EXPECT_EQ(device_id, device_info.device_id);
367 EXPECT_EQ(device_name, device_info.name); 610 EXPECT_EQ(device_name, device_info.name);
368 EXPECT_EQ(removable_device.value(), device_info.location); 611 EXPECT_EQ(removable_device.value(), device_info.location);
369 612
370 // A fixed device. 613 // A fixed device.
371 FilePath fixed_device(L"N:\\"); 614 FilePath fixed_device(L"N:\\");
372 EXPECT_TRUE(window_->GetDeviceInfoForPath(fixed_device, &device_info)); 615 EXPECT_TRUE(window_->GetDeviceInfoForPath(fixed_device, &device_info));
373 616
374 ASSERT_TRUE(GetDeviceDetails(fixed_device, NULL, &unique_id, &device_name, 617 ASSERT_TRUE(GetMassStorageDeviceDetails(fixed_device, NULL, &unique_id,
375 &removable)); 618 &device_name, &removable));
376 EXPECT_FALSE(removable); 619 EXPECT_FALSE(removable);
377 device_id = MediaStorageUtil::MakeDeviceId( 620 device_id = MediaStorageUtil::MakeDeviceId(
378 MediaStorageUtil::FIXED_MASS_STORAGE, unique_id); 621 MediaStorageUtil::FIXED_MASS_STORAGE, unique_id);
379 EXPECT_EQ(device_id, device_info.device_id); 622 EXPECT_EQ(device_id, device_info.device_id);
380 EXPECT_EQ(device_name, device_info.name); 623 EXPECT_EQ(device_name, device_info.name);
381 EXPECT_EQ(fixed_device.value(), device_info.location); 624 EXPECT_EQ(fixed_device.value(), device_info.location);
382 } 625 }
383 626
627 // Test to verify basic MTP storage attach and detach notifications.
628 TEST_F(RemovableDeviceNotificationsWindowWinTest, MTPDeviceBasicAttachDetach) {
629 DoMTPDeviceTest(kMTPDeviceWithValidInfo, true);
630 DoMTPDeviceTest(kMTPDeviceWithValidInfo, false);
631 }
632
633 // When a MTP storage device with invalid storage label and id is
634 // attached/detached, there should not be any device attach/detach
635 // notifications.
636 TEST_F(RemovableDeviceNotificationsWindowWinTest, MTPDeviceWithInvalidInfo) {
637 DoMTPDeviceTest(kMTPDeviceWithInvalidInfo, true);
638 DoMTPDeviceTest(kMTPDeviceWithInvalidInfo, false);
639 }
640
641 // Attach a device with two data partitions. Verify that attach/detach
642 // notifications are sent out for each removable storage.
643 TEST_F(RemovableDeviceNotificationsWindowWinTest,
644 MTPDeviceWithMultipleStorageObjects) {
645 DoMTPDeviceTest(kMTPDeviceWithMultipleStorageObjects, true);
646 DoMTPDeviceTest(kMTPDeviceWithMultipleStorageObjects, false);
647 }
648
384 } // namespace chrome 649 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698