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
3 // found in the LICENSE file.
5 #include "chrome/browser/system_monitor/removable_device_notifications_window_win.h"
12 #include "base/file_util.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop.h"
16 #include "base/scoped_temp_dir.h"
17 #include "base/system_monitor/system_monitor.h"
18 #include "base/test/mock_devices_changed_observer.h"
19 #include "base/utf_string_conversions.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"
23 #include "chrome/browser/system_monitor/volume_mount_watcher_win.h"
24 #include "content/public/test/test_browser_thread.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
30 typedef std::vector
<int> DeviceIndices
;
31 typedef std::vector
<FilePath
> AttachedDevices
;
35 using content::BrowserThread
;
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})";
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";
56 // Inputs of 'A:\' - 'Z:\' are valid. 'N:\' is not removable.
57 bool GetMassStorageDeviceDetails(const FilePath
& device_path
,
58 string16
* device_location
,
59 std::string
* unique_id
,
62 if (device_path
.value().length() != 3 || device_path
.value()[0] < L
'A' ||
63 device_path
.value()[0] > L
'Z') {
68 *device_location
= device_path
.value();
70 *unique_id
= "\\\\?\\Volume{00000000-0000-0000-0000-000000000000}\\";
71 (*unique_id
)[11] = device_path
.value()[0];
74 *name
= device_path
.Append(L
" Drive").LossyDisplayName();
76 *removable
= device_path
.value()[0] != L
'N';
80 FilePath
DriveNumberToFilePath(int drive_number
) {
81 FilePath::StringType
path(L
"_:\\");
82 path
[0] = L
'A' + drive_number
;
83 return FilePath(path
);
86 AttachedDevices
GetTestAttachedDevices() {
87 AttachedDevices result
;
88 result
.push_back(DriveNumberToFilePath(0));
89 result
.push_back(DriveNumberToFilePath(1));
90 result
.push_back(DriveNumberToFilePath(2));
91 result
.push_back(DriveNumberToFilePath(3));
92 result
.push_back(DriveNumberToFilePath(5));
93 result
.push_back(DriveNumberToFilePath(7));
94 result
.push_back(DriveNumberToFilePath(25));
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();
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
)
117 if (storage_object_id
== kStorageObjectIdA
)
118 return kStorageLabelA
;
119 return (storage_object_id
== kStorageObjectIdB
) ?
120 kStorageLabelB
: string16();
123 // Returns a list of storage object identifiers of the device given a
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
;
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
,
142 std::string storage_unique_id
= GetMTPStorageUniqueId(pnp_device_id
,
146 *device_location
= UTF8ToUTF16("\\\\" + storage_unique_id
);
149 *unique_id
= storage_unique_id
;
152 *name
= GetMTPStorageName(pnp_device_id
, storage_object_id
);
155 // Returns a list of device storage details for the given device specified by
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
)));
167 return storage_objects
;
173 // TestPortableDeviceWatcherWin -----------------------------------------------
175 class TestPortableDeviceWatcherWin
: public PortableDeviceWatcherWin
{
177 TestPortableDeviceWatcherWin();
178 virtual ~TestPortableDeviceWatcherWin();
181 // PortableDeviceWatcherWin:
182 virtual void EnumerateAttachedDevices() OVERRIDE
;
183 virtual void HandleDeviceAttachEvent(const string16
& pnp_device_id
) OVERRIDE
;
185 DISALLOW_COPY_AND_ASSIGN(TestPortableDeviceWatcherWin
);
188 TestPortableDeviceWatcherWin::TestPortableDeviceWatcherWin() {
191 TestPortableDeviceWatcherWin::~TestPortableDeviceWatcherWin() {
194 void TestPortableDeviceWatcherWin::EnumerateAttachedDevices() {
197 void TestPortableDeviceWatcherWin::HandleDeviceAttachEvent(
198 const string16
& pnp_device_id
) {
199 DeviceDetails device_details
= {
200 (pnp_device_id
!= kMTPDeviceWithInvalidInfo
) ?
201 kMTPDeviceFriendlyName
: string16(),
203 GetDeviceStorageObjects(pnp_device_id
)
205 OnDidHandleDeviceAttachEvent(&device_details
, true);
209 // TestVolumeMountWatcherWin --------------------------------------------------
211 class TestVolumeMountWatcherWin
: public VolumeMountWatcherWin
{
213 TestVolumeMountWatcherWin();
215 void set_pre_attach_devices(bool pre_attach_devices
) {
216 pre_attach_devices_
= pre_attach_devices
;
220 // Private, this class is ref-counted.
221 virtual ~TestVolumeMountWatcherWin();
223 // VolumeMountWatcherWin:
224 virtual bool GetDeviceInfo(const FilePath
& device_path
,
225 string16
* device_location
,
226 std::string
* unique_id
,
228 bool* removable
) OVERRIDE
;
229 virtual AttachedDevices
GetAttachedDevices() OVERRIDE
;
231 // Set to true to pre-attach test devices.
232 bool pre_attach_devices_
;
234 DISALLOW_COPY_AND_ASSIGN(TestVolumeMountWatcherWin
);
237 TestVolumeMountWatcherWin::TestVolumeMountWatcherWin()
238 : pre_attach_devices_(false) {
241 TestVolumeMountWatcherWin::~TestVolumeMountWatcherWin() {
244 bool TestVolumeMountWatcherWin::GetDeviceInfo(const FilePath
& device_path
,
245 string16
* device_location
,
246 std::string
* unique_id
,
249 return GetMassStorageDeviceDetails(device_path
, device_location
, unique_id
,
253 AttachedDevices
TestVolumeMountWatcherWin::GetAttachedDevices() {
254 return pre_attach_devices_
?
255 GetTestAttachedDevices() : AttachedDevices();
259 // TestRemovableDeviceNotificationsWindowWin -----------------------------------
261 class TestRemovableDeviceNotificationsWindowWin
262 : public RemovableDeviceNotificationsWindowWin
{
264 TestRemovableDeviceNotificationsWindowWin(
265 TestVolumeMountWatcherWin
* volume_mount_watcher
,
266 TestPortableDeviceWatcherWin
* portable_device_watcher
);
268 virtual ~TestRemovableDeviceNotificationsWindowWin();
270 void InitWithTestData(bool pre_attach_devices
);
271 void InjectDeviceChange(UINT event_type
, DWORD data
);
274 scoped_refptr
<TestVolumeMountWatcherWin
> volume_mount_watcher_
;
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_
);
287 TestRemovableDeviceNotificationsWindowWin::
288 ~TestRemovableDeviceNotificationsWindowWin() {
291 void TestRemovableDeviceNotificationsWindowWin::InitWithTestData(
292 bool pre_attach_devices
) {
293 volume_mount_watcher_
->set_pre_attach_devices(pre_attach_devices
);
297 void TestRemovableDeviceNotificationsWindowWin::InjectDeviceChange(
300 OnDeviceChange(event_type
, data
);
304 // RemovableDeviceNotificationsWindowWinTest -----------------------------------
306 class RemovableDeviceNotificationsWindowWinTest
: public testing::Test
{
308 RemovableDeviceNotificationsWindowWinTest();
309 virtual ~RemovableDeviceNotificationsWindowWinTest();
313 virtual void SetUp() OVERRIDE
;
314 virtual void TearDown() OVERRIDE
;
316 void AddMassStorageDeviceAttachExpectation(FilePath drive
);
317 void PreAttachDevices();
319 // Runs all the pending tasks on UI thread, FILE thread and blocking thread.
320 void RunAllPending();
322 void DoMassStorageDeviceAttachedTest(const DeviceIndices
& device_indices
);
323 void DoMassStorageDevicesDetachedTest(const DeviceIndices
& device_indices
);
325 // Injects a device attach or detach change (depending on the value of
326 // |test_attach|) and tests that the appropriate handler is called.
327 void DoMTPDeviceTest(const string16
& pnp_device_id
, bool test_attach
);
329 MessageLoopForUI message_loop_
;
330 content::TestBrowserThread ui_thread_
;
331 content::TestBrowserThread file_thread_
;
333 base::SystemMonitor system_monitor_
;
334 base::MockDevicesChangedObserver observer_
;
335 scoped_ptr
<TestRemovableDeviceNotificationsWindowWin
> window_
;
336 scoped_refptr
<TestVolumeMountWatcherWin
> volume_mount_watcher_
;
339 RemovableDeviceNotificationsWindowWinTest::
340 RemovableDeviceNotificationsWindowWinTest()
341 : ui_thread_(BrowserThread::UI
, &message_loop_
),
342 file_thread_(BrowserThread::FILE, &message_loop_
) {
345 RemovableDeviceNotificationsWindowWinTest::
346 ~RemovableDeviceNotificationsWindowWinTest() {
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);
356 system_monitor_
.AddDevicesChangedObserver(&observer_
);
359 void RemovableDeviceNotificationsWindowWinTest::TearDown() {
361 system_monitor_
.RemoveDevicesChangedObserver(&observer_
);
364 void RemovableDeviceNotificationsWindowWinTest::
365 AddMassStorageDeviceAttachExpectation(FilePath drive
) {
366 std::string unique_id
;
367 string16 device_name
;
369 ASSERT_TRUE(GetMassStorageDeviceDetails(drive
, NULL
, &unique_id
,
370 &device_name
, &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
,
381 void RemovableDeviceNotificationsWindowWinTest::PreAttachDevices() {
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
);
391 window_
.reset(new TestRemovableDeviceNotificationsWindowWin(
392 volume_mount_watcher_
.get(), new TestPortableDeviceWatcherWin
));
393 window_
->InitWithTestData(true);
397 void RemovableDeviceNotificationsWindowWinTest::RunAllPending() {
398 message_loop_
.RunAllPending();
401 void RemovableDeviceNotificationsWindowWinTest::
402 DoMassStorageDeviceAttachedTest(const DeviceIndices
& device_indices
) {
403 DEV_BROADCAST_VOLUME volume_broadcast
;
404 volume_broadcast
.dbcv_size
= sizeof(volume_broadcast
);
405 volume_broadcast
.dbcv_devicetype
= DBT_DEVTYP_VOLUME
;
406 volume_broadcast
.dbcv_unitmask
= 0x0;
407 volume_broadcast
.dbcv_flags
= 0x0;
409 testing::InSequence sequence
;
410 for (DeviceIndices::const_iterator it
= device_indices
.begin();
411 it
!= device_indices
.end(); ++it
) {
412 volume_broadcast
.dbcv_unitmask
|= 0x1 << *it
;
413 AddMassStorageDeviceAttachExpectation(DriveNumberToFilePath(*it
));
416 window_
->InjectDeviceChange(DBT_DEVICEARRIVAL
,
417 reinterpret_cast<DWORD
>(&volume_broadcast
));
421 void RemovableDeviceNotificationsWindowWinTest::
422 DoMassStorageDevicesDetachedTest(const DeviceIndices
& device_indices
) {
423 DEV_BROADCAST_VOLUME volume_broadcast
;
424 volume_broadcast
.dbcv_size
= sizeof(volume_broadcast
);
425 volume_broadcast
.dbcv_devicetype
= DBT_DEVTYP_VOLUME
;
426 volume_broadcast
.dbcv_unitmask
= 0x0;
427 volume_broadcast
.dbcv_flags
= 0x0;
429 testing::InSequence sequence
;
430 for (DeviceIndices::const_iterator it
= device_indices
.begin();
431 it
!= device_indices
.end(); ++it
) {
432 volume_broadcast
.dbcv_unitmask
|= 0x1 << *it
;
433 std::string unique_id
;
435 ASSERT_TRUE(GetMassStorageDeviceDetails(DriveNumberToFilePath(*it
), NULL
,
436 &unique_id
, NULL
, &removable
));
438 MediaStorageUtil::Type type
=
439 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM
;
440 std::string device_id
= MediaStorageUtil::MakeDeviceId(type
, unique_id
);
441 EXPECT_CALL(observer_
, OnRemovableStorageDetached(device_id
)).Times(1);
445 window_
->InjectDeviceChange(DBT_DEVICEREMOVECOMPLETE
,
446 reinterpret_cast<DWORD
>(&volume_broadcast
));
450 void RemovableDeviceNotificationsWindowWinTest::DoMTPDeviceTest(
451 const string16
& pnp_device_id
, bool test_attach
) {
452 GUID guidDevInterface
= GUID_NULL
;
453 HRESULT hr
= CLSIDFromString(kWPDDevInterfaceGUID
, &guidDevInterface
);
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(),
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
;
477 GetMTPStorageDetails(pnp_device_id
, *it
, &location
, &unique_id
, &name
);
479 EXPECT_CALL(observer_
, OnRemovableStorageAttached(unique_id
, name
,
481 .Times((name
.empty() || unique_id
.empty()) ? 0 : 1);
483 EXPECT_CALL(observer_
, OnRemovableStorageDetached(unique_id
))
484 .Times((name
.empty() || unique_id
.empty()) ? 0 : 1);
488 window_
->InjectDeviceChange(
489 test_attach
? DBT_DEVICEARRIVAL
: DBT_DEVICEREMOVECOMPLETE
,
490 reinterpret_cast<DWORD
>(dev_interface_broadcast
.get()));
494 TEST_F(RemovableDeviceNotificationsWindowWinTest
, RandomMessage
) {
495 window_
->InjectDeviceChange(DBT_DEVICEQUERYREMOVE
, NULL
);
499 TEST_F(RemovableDeviceNotificationsWindowWinTest
, DevicesAttached
) {
500 DeviceIndices device_indices
;
501 device_indices
.push_back(1);
502 device_indices
.push_back(5);
503 device_indices
.push_back(7);
504 device_indices
.push_back(13);
506 DoMassStorageDeviceAttachedTest(device_indices
);
509 TEST_F(RemovableDeviceNotificationsWindowWinTest
, DevicesAttachedHighBoundary
) {
510 DeviceIndices device_indices
;
511 device_indices
.push_back(25);
513 DoMassStorageDeviceAttachedTest(device_indices
);
516 TEST_F(RemovableDeviceNotificationsWindowWinTest
, DevicesAttachedLowBoundary
) {
517 DeviceIndices device_indices
;
518 device_indices
.push_back(0);
520 DoMassStorageDeviceAttachedTest(device_indices
);
523 TEST_F(RemovableDeviceNotificationsWindowWinTest
, DevicesAttachedAdjacentBits
) {
524 DeviceIndices device_indices
;
525 device_indices
.push_back(0);
526 device_indices
.push_back(1);
527 device_indices
.push_back(2);
528 device_indices
.push_back(3);
530 DoMassStorageDeviceAttachedTest(device_indices
);
533 // Disabled until http://crbug.com/155910 is resolved.
534 TEST_F(RemovableDeviceNotificationsWindowWinTest
, DISABLED_DevicesDetached
) {
537 DeviceIndices device_indices
;
538 device_indices
.push_back(1);
539 device_indices
.push_back(5);
540 device_indices
.push_back(7);
541 device_indices
.push_back(13);
543 DoMassStorageDeviceAttachedTest(device_indices
);
546 // Disabled until http://crbug.com/155910 is resolved.
547 TEST_F(RemovableDeviceNotificationsWindowWinTest
,
548 DISABLED_DevicesDetachedHighBoundary
) {
551 DeviceIndices device_indices
;
552 device_indices
.push_back(25);
554 DoMassStorageDeviceAttachedTest(device_indices
);
557 // Disabled until http://crbug.com/155910 is resolved.
558 TEST_F(RemovableDeviceNotificationsWindowWinTest
,
559 DISABLED_DevicesDetachedLowBoundary
) {
562 DeviceIndices device_indices
;
563 device_indices
.push_back(0);
565 DoMassStorageDeviceAttachedTest(device_indices
);
568 // Disabled until http://crbug.com/155910 is resolved.
569 TEST_F(RemovableDeviceNotificationsWindowWinTest
,
570 DISABLED_DevicesDetachedAdjacentBits
) {
573 DeviceIndices device_indices
;
574 device_indices
.push_back(0);
575 device_indices
.push_back(1);
576 device_indices
.push_back(2);
577 device_indices
.push_back(3);
579 DoMassStorageDeviceAttachedTest(device_indices
);
582 // Disabled until http://crbug.com/155910 is resolved.
583 TEST_F(RemovableDeviceNotificationsWindowWinTest
, DISABLED_DeviceInfoForPath
) {
587 EXPECT_FALSE(window_
->GetDeviceInfoForPath(FilePath(L
"COM1:\\"), NULL
));
589 // An unconnected removable device.
590 EXPECT_FALSE(window_
->GetDeviceInfoForPath(FilePath(L
"E:\\"), NULL
));
592 // A connected removable device.
593 FilePath
removable_device(L
"F:\\");
594 base::SystemMonitor::RemovableStorageInfo device_info
;
595 EXPECT_TRUE(window_
->GetDeviceInfoForPath(removable_device
, &device_info
));
597 std::string unique_id
;
598 string16 device_name
;
600 ASSERT_TRUE(GetMassStorageDeviceDetails(removable_device
, NULL
, &unique_id
,
601 &device_name
, &removable
));
602 EXPECT_TRUE(removable
);
603 std::string device_id
= MediaStorageUtil::MakeDeviceId(
604 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM
, unique_id
);
605 EXPECT_EQ(device_id
, device_info
.device_id
);
606 EXPECT_EQ(device_name
, device_info
.name
);
607 EXPECT_EQ(removable_device
.value(), device_info
.location
);
610 FilePath
fixed_device(L
"N:\\");
611 EXPECT_TRUE(window_
->GetDeviceInfoForPath(fixed_device
, &device_info
));
613 ASSERT_TRUE(GetMassStorageDeviceDetails(fixed_device
, NULL
, &unique_id
,
614 &device_name
, &removable
));
615 EXPECT_FALSE(removable
);
616 device_id
= MediaStorageUtil::MakeDeviceId(
617 MediaStorageUtil::FIXED_MASS_STORAGE
, unique_id
);
618 EXPECT_EQ(device_id
, device_info
.device_id
);
619 EXPECT_EQ(device_name
, device_info
.name
);
620 EXPECT_EQ(fixed_device
.value(), device_info
.location
);
623 // Test to verify basic MTP storage attach and detach notifications.
624 TEST_F(RemovableDeviceNotificationsWindowWinTest
, MTPDeviceBasicAttachDetach
) {
625 DoMTPDeviceTest(kMTPDeviceWithValidInfo
, true);
626 DoMTPDeviceTest(kMTPDeviceWithValidInfo
, false);
629 // When a MTP storage device with invalid storage label and id is
630 // attached/detached, there should not be any device attach/detach
632 TEST_F(RemovableDeviceNotificationsWindowWinTest
, MTPDeviceWithInvalidInfo
) {
633 DoMTPDeviceTest(kMTPDeviceWithInvalidInfo
, true);
634 DoMTPDeviceTest(kMTPDeviceWithInvalidInfo
, false);
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);
645 } // namespace chrome