| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include <windows.h> | |
| 6 #include <dbt.h> | |
| 7 | |
| 8 #include <string> | |
| 9 #include <vector> | |
| 10 | |
| 11 #include "base/memory/ref_counted.h" | |
| 12 #include "base/memory/scoped_ptr.h" | |
| 13 #include "base/message_loop.h" | |
| 14 #include "base/synchronization/waitable_event.h" | |
| 15 #include "base/utf_string_conversions.h" | |
| 16 #include "chrome/browser/storage_monitor/media_storage_util.h" | |
| 17 #include "chrome/browser/storage_monitor/mock_removable_storage_observer.h" | |
| 18 #include "chrome/browser/storage_monitor/portable_device_watcher_win.h" | |
| 19 #include "chrome/browser/storage_monitor/removable_device_constants.h" | |
| 20 #include "chrome/browser/storage_monitor/removable_device_notifications_window_w
in.h" | |
| 21 #include "chrome/browser/storage_monitor/test_portable_device_watcher_win.h" | |
| 22 #include "chrome/browser/storage_monitor/test_removable_device_notifications_win
dow_win.h" | |
| 23 #include "chrome/browser/storage_monitor/test_volume_mount_watcher_win.h" | |
| 24 #include "chrome/browser/storage_monitor/volume_mount_watcher_win.h" | |
| 25 #include "content/public/test/test_browser_thread.h" | |
| 26 #include "testing/gtest/include/gtest/gtest.h" | |
| 27 | |
| 28 namespace chrome { | |
| 29 namespace test { | |
| 30 | |
| 31 using content::BrowserThread; | |
| 32 | |
| 33 typedef std::vector<int> DeviceIndices; | |
| 34 | |
| 35 // RemovableDeviceNotificationsWindowWinTest ----------------------------------- | |
| 36 | |
| 37 class RemovableDeviceNotificationsWindowWinTest : public testing::Test { | |
| 38 public: | |
| 39 RemovableDeviceNotificationsWindowWinTest(); | |
| 40 virtual ~RemovableDeviceNotificationsWindowWinTest(); | |
| 41 | |
| 42 protected: | |
| 43 // testing::Test: | |
| 44 virtual void SetUp() OVERRIDE; | |
| 45 virtual void TearDown() OVERRIDE; | |
| 46 | |
| 47 void PreAttachDevices(); | |
| 48 | |
| 49 // Runs all the pending tasks on UI thread, FILE thread and blocking thread. | |
| 50 void RunUntilIdle(); | |
| 51 | |
| 52 void DoMassStorageDeviceAttachedTest(const DeviceIndices& device_indices); | |
| 53 void DoMassStorageDevicesDetachedTest(const DeviceIndices& device_indices); | |
| 54 | |
| 55 // Injects a device attach or detach change (depending on the value of | |
| 56 // |test_attach|) and tests that the appropriate handler is called. | |
| 57 void DoMTPDeviceTest(const string16& pnp_device_id, bool test_attach); | |
| 58 | |
| 59 // Gets the MTP details of the storage specified by the |storage_device_id|. | |
| 60 // On success, returns true and fills in |pnp_device_id| and | |
| 61 // |storage_object_id|. | |
| 62 bool GetMTPStorageInfo(const std::string& storage_device_id, | |
| 63 string16* pnp_device_id, | |
| 64 string16* storage_object_id); | |
| 65 | |
| 66 scoped_ptr<TestRemovableDeviceNotificationsWindowWin> window_; | |
| 67 | |
| 68 // Weak pointer; owned by the device notifications class. | |
| 69 TestVolumeMountWatcherWin* volume_mount_watcher_; | |
| 70 | |
| 71 MockRemovableStorageObserver observer_; | |
| 72 | |
| 73 private: | |
| 74 MessageLoopForUI message_loop_; | |
| 75 content::TestBrowserThread ui_thread_; | |
| 76 content::TestBrowserThread file_thread_; | |
| 77 }; | |
| 78 | |
| 79 RemovableDeviceNotificationsWindowWinTest:: | |
| 80 RemovableDeviceNotificationsWindowWinTest() | |
| 81 : ui_thread_(BrowserThread::UI, &message_loop_), | |
| 82 file_thread_(BrowserThread::FILE, &message_loop_) { | |
| 83 } | |
| 84 | |
| 85 RemovableDeviceNotificationsWindowWinTest:: | |
| 86 ~RemovableDeviceNotificationsWindowWinTest() { | |
| 87 } | |
| 88 | |
| 89 void RemovableDeviceNotificationsWindowWinTest::SetUp() { | |
| 90 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 91 volume_mount_watcher_ = new TestVolumeMountWatcherWin; | |
| 92 window_.reset(new TestRemovableDeviceNotificationsWindowWin( | |
| 93 volume_mount_watcher_, new TestPortableDeviceWatcherWin)); | |
| 94 window_->Init(); | |
| 95 RunUntilIdle(); | |
| 96 window_->AddObserver(&observer_); | |
| 97 } | |
| 98 | |
| 99 void RemovableDeviceNotificationsWindowWinTest::TearDown() { | |
| 100 RunUntilIdle(); | |
| 101 window_->RemoveObserver(&observer_); | |
| 102 } | |
| 103 | |
| 104 void RemovableDeviceNotificationsWindowWinTest::PreAttachDevices() { | |
| 105 window_.reset(); | |
| 106 volume_mount_watcher_ = new TestVolumeMountWatcherWin; | |
| 107 volume_mount_watcher_->SetAttachedDevicesFake(); | |
| 108 | |
| 109 int expect_attach_calls = 0; | |
| 110 std::vector<base::FilePath> initial_devices = | |
| 111 volume_mount_watcher_->GetAttachedDevices(); | |
| 112 for (std::vector<base::FilePath>::const_iterator it = initial_devices.begin(); | |
| 113 it != initial_devices.end(); ++it) { | |
| 114 std::string unique_id; | |
| 115 string16 device_name; | |
| 116 bool removable; | |
| 117 ASSERT_TRUE(volume_mount_watcher_->GetRawDeviceInfo( | |
| 118 *it, NULL, &unique_id, &device_name, &removable, NULL)); | |
| 119 if (removable) | |
| 120 expect_attach_calls++; | |
| 121 } | |
| 122 | |
| 123 window_.reset(new TestRemovableDeviceNotificationsWindowWin( | |
| 124 volume_mount_watcher_, new TestPortableDeviceWatcherWin)); | |
| 125 window_->AddObserver(&observer_); | |
| 126 window_->Init(); | |
| 127 | |
| 128 EXPECT_EQ(0u, volume_mount_watcher_->devices_checked().size()); | |
| 129 | |
| 130 // This dance is because attachment bounces through a couple of | |
| 131 // closures, which need to be executed to finish the process. | |
| 132 RunUntilIdle(); | |
| 133 volume_mount_watcher_->FlushWorkerPoolForTesting(); | |
| 134 RunUntilIdle(); | |
| 135 | |
| 136 std::vector<base::FilePath> checked_devices = | |
| 137 volume_mount_watcher_->devices_checked(); | |
| 138 sort(checked_devices.begin(), checked_devices.end()); | |
| 139 EXPECT_EQ(initial_devices, checked_devices); | |
| 140 EXPECT_EQ(expect_attach_calls, observer_.attach_calls()); | |
| 141 EXPECT_EQ(0, observer_.detach_calls()); | |
| 142 } | |
| 143 | |
| 144 void RemovableDeviceNotificationsWindowWinTest::RunUntilIdle() { | |
| 145 volume_mount_watcher_->FlushWorkerPoolForTesting(); | |
| 146 message_loop_.RunUntilIdle(); | |
| 147 } | |
| 148 | |
| 149 void RemovableDeviceNotificationsWindowWinTest:: | |
| 150 DoMassStorageDeviceAttachedTest(const DeviceIndices& device_indices) { | |
| 151 DEV_BROADCAST_VOLUME volume_broadcast; | |
| 152 volume_broadcast.dbcv_size = sizeof(volume_broadcast); | |
| 153 volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME; | |
| 154 volume_broadcast.dbcv_unitmask = 0x0; | |
| 155 volume_broadcast.dbcv_flags = 0x0; | |
| 156 | |
| 157 int expect_attach_calls = 0; | |
| 158 for (DeviceIndices::const_iterator it = device_indices.begin(); | |
| 159 it != device_indices.end(); ++it) { | |
| 160 volume_broadcast.dbcv_unitmask |= 0x1 << *it; | |
| 161 bool removable; | |
| 162 ASSERT_TRUE(volume_mount_watcher_->GetDeviceInfo( | |
| 163 VolumeMountWatcherWin::DriveNumberToFilePath(*it), | |
| 164 NULL, NULL, NULL, &removable, NULL)); | |
| 165 if (removable) | |
| 166 expect_attach_calls++; | |
| 167 } | |
| 168 window_->InjectDeviceChange(DBT_DEVICEARRIVAL, | |
| 169 reinterpret_cast<DWORD>(&volume_broadcast)); | |
| 170 | |
| 171 RunUntilIdle(); | |
| 172 volume_mount_watcher_->FlushWorkerPoolForTesting(); | |
| 173 RunUntilIdle(); | |
| 174 | |
| 175 EXPECT_EQ(expect_attach_calls, observer_.attach_calls()); | |
| 176 EXPECT_EQ(0, observer_.detach_calls()); | |
| 177 } | |
| 178 | |
| 179 void RemovableDeviceNotificationsWindowWinTest:: | |
| 180 DoMassStorageDevicesDetachedTest(const DeviceIndices& device_indices) { | |
| 181 DEV_BROADCAST_VOLUME volume_broadcast; | |
| 182 volume_broadcast.dbcv_size = sizeof(volume_broadcast); | |
| 183 volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME; | |
| 184 volume_broadcast.dbcv_unitmask = 0x0; | |
| 185 volume_broadcast.dbcv_flags = 0x0; | |
| 186 | |
| 187 int pre_attach_calls = observer_.attach_calls(); | |
| 188 int expect_detach_calls = 0; | |
| 189 for (DeviceIndices::const_iterator it = device_indices.begin(); | |
| 190 it != device_indices.end(); ++it) { | |
| 191 volume_broadcast.dbcv_unitmask |= 0x1 << *it; | |
| 192 bool removable; | |
| 193 ASSERT_TRUE(volume_mount_watcher_->GetRawDeviceInfo( | |
| 194 VolumeMountWatcherWin::DriveNumberToFilePath(*it), NULL, NULL, | |
| 195 NULL, &removable, NULL)); | |
| 196 if (removable) | |
| 197 expect_detach_calls++; | |
| 198 } | |
| 199 window_->InjectDeviceChange(DBT_DEVICEREMOVECOMPLETE, | |
| 200 reinterpret_cast<DWORD>(&volume_broadcast)); | |
| 201 RunUntilIdle(); | |
| 202 EXPECT_EQ(pre_attach_calls, observer_.attach_calls()); | |
| 203 EXPECT_EQ(expect_detach_calls, observer_.detach_calls()); | |
| 204 } | |
| 205 | |
| 206 void RemovableDeviceNotificationsWindowWinTest::DoMTPDeviceTest( | |
| 207 const string16& pnp_device_id, bool test_attach) { | |
| 208 GUID guidDevInterface = GUID_NULL; | |
| 209 HRESULT hr = CLSIDFromString(kWPDDevInterfaceGUID, &guidDevInterface); | |
| 210 if (FAILED(hr)) | |
| 211 return; | |
| 212 | |
| 213 size_t device_id_size = pnp_device_id.size() * sizeof(char16); | |
| 214 size_t size = sizeof(DEV_BROADCAST_DEVICEINTERFACE) + device_id_size; | |
| 215 scoped_ptr_malloc<DEV_BROADCAST_DEVICEINTERFACE> dev_interface_broadcast( | |
| 216 static_cast<DEV_BROADCAST_DEVICEINTERFACE*>(malloc(size))); | |
| 217 DCHECK(dev_interface_broadcast.get()); | |
| 218 ZeroMemory(dev_interface_broadcast.get(), size); | |
| 219 dev_interface_broadcast->dbcc_size = size; | |
| 220 dev_interface_broadcast->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; | |
| 221 dev_interface_broadcast->dbcc_classguid = guidDevInterface; | |
| 222 memcpy(dev_interface_broadcast->dbcc_name, pnp_device_id.data(), | |
| 223 device_id_size); | |
| 224 | |
| 225 int expect_attach_calls = observer_.attach_calls(); | |
| 226 int expect_detach_calls = observer_.detach_calls(); | |
| 227 PortableDeviceWatcherWin::StorageObjectIDs storage_object_ids = | |
| 228 TestPortableDeviceWatcherWin::GetMTPStorageObjectIds(pnp_device_id); | |
| 229 for (PortableDeviceWatcherWin::StorageObjectIDs::const_iterator it = | |
| 230 storage_object_ids.begin(); it != storage_object_ids.end(); ++it) { | |
| 231 std::string unique_id; | |
| 232 string16 name; | |
| 233 string16 location; | |
| 234 TestPortableDeviceWatcherWin::GetMTPStorageDetails(pnp_device_id, *it, | |
| 235 &location, &unique_id, | |
| 236 &name); | |
| 237 if (test_attach && !name.empty() && !unique_id.empty()) | |
| 238 expect_attach_calls++; | |
| 239 else if (!name.empty() && !unique_id.empty()) | |
| 240 expect_detach_calls++; | |
| 241 } | |
| 242 | |
| 243 window_->InjectDeviceChange( | |
| 244 test_attach ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE, | |
| 245 reinterpret_cast<DWORD>(dev_interface_broadcast.get())); | |
| 246 | |
| 247 RunUntilIdle(); | |
| 248 EXPECT_EQ(expect_attach_calls, observer_.attach_calls()); | |
| 249 EXPECT_EQ(expect_detach_calls, observer_.detach_calls()); | |
| 250 } | |
| 251 | |
| 252 bool RemovableDeviceNotificationsWindowWinTest::GetMTPStorageInfo( | |
| 253 const std::string& storage_device_id, | |
| 254 string16* pnp_device_id, | |
| 255 string16* storage_object_id) { | |
| 256 return window_->GetMTPStorageInfoFromDeviceId(storage_device_id, | |
| 257 pnp_device_id, | |
| 258 storage_object_id); | |
| 259 } | |
| 260 | |
| 261 TEST_F(RemovableDeviceNotificationsWindowWinTest, RandomMessage) { | |
| 262 window_->InjectDeviceChange(DBT_DEVICEQUERYREMOVE, NULL); | |
| 263 RunUntilIdle(); | |
| 264 } | |
| 265 | |
| 266 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttached) { | |
| 267 DeviceIndices device_indices; | |
| 268 device_indices.push_back(1); // B | |
| 269 device_indices.push_back(5); // F | |
| 270 device_indices.push_back(7); // H | |
| 271 device_indices.push_back(13); // N | |
| 272 DoMassStorageDeviceAttachedTest(device_indices); | |
| 273 | |
| 274 string16 location; | |
| 275 std::string unique_id; | |
| 276 string16 name; | |
| 277 bool removable; | |
| 278 EXPECT_TRUE(window_->volume_mount_watcher()->GetDeviceInfo( | |
| 279 base::FilePath(ASCIIToUTF16("F:\\")), | |
| 280 &location, &unique_id, &name, &removable, NULL)); | |
| 281 EXPECT_EQ(ASCIIToUTF16("F:\\"), location); | |
| 282 EXPECT_EQ("\\\\?\\Volume{F0000000-0000-0000-0000-000000000000}\\", unique_id); | |
| 283 EXPECT_EQ(ASCIIToUTF16("F:\\ Drive"), name); | |
| 284 | |
| 285 StorageMonitor::StorageInfo info; | |
| 286 EXPECT_FALSE(window_->GetStorageInfoForPath( | |
| 287 base::FilePath(ASCIIToUTF16("G:\\")), &info)); | |
| 288 EXPECT_TRUE(window_->GetStorageInfoForPath( | |
| 289 base::FilePath(ASCIIToUTF16("F:\\")), &info)); | |
| 290 StorageMonitor::StorageInfo info1; | |
| 291 EXPECT_TRUE(window_->GetStorageInfoForPath( | |
| 292 base::FilePath(ASCIIToUTF16("F:\\subdir")), &info1)); | |
| 293 StorageMonitor::StorageInfo info2; | |
| 294 EXPECT_TRUE(window_->GetStorageInfoForPath( | |
| 295 base::FilePath(ASCIIToUTF16("F:\\subdir\\sub")), &info2)); | |
| 296 EXPECT_EQ(ASCIIToUTF16("F:\\ Drive"), info.name); | |
| 297 EXPECT_EQ(ASCIIToUTF16("F:\\ Drive"), info1.name); | |
| 298 EXPECT_EQ(ASCIIToUTF16("F:\\ Drive"), info2.name); | |
| 299 } | |
| 300 | |
| 301 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedHighBoundary) { | |
| 302 DeviceIndices device_indices; | |
| 303 device_indices.push_back(25); | |
| 304 | |
| 305 DoMassStorageDeviceAttachedTest(device_indices); | |
| 306 } | |
| 307 | |
| 308 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedLowBoundary) { | |
| 309 DeviceIndices device_indices; | |
| 310 device_indices.push_back(0); | |
| 311 | |
| 312 DoMassStorageDeviceAttachedTest(device_indices); | |
| 313 } | |
| 314 | |
| 315 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedAdjacentBits) { | |
| 316 DeviceIndices device_indices; | |
| 317 device_indices.push_back(0); | |
| 318 device_indices.push_back(1); | |
| 319 device_indices.push_back(2); | |
| 320 device_indices.push_back(3); | |
| 321 | |
| 322 DoMassStorageDeviceAttachedTest(device_indices); | |
| 323 } | |
| 324 | |
| 325 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetached) { | |
| 326 PreAttachDevices(); | |
| 327 | |
| 328 DeviceIndices device_indices; | |
| 329 device_indices.push_back(1); | |
| 330 device_indices.push_back(5); | |
| 331 device_indices.push_back(7); | |
| 332 device_indices.push_back(13); | |
| 333 | |
| 334 DoMassStorageDevicesDetachedTest(device_indices); | |
| 335 } | |
| 336 | |
| 337 TEST_F(RemovableDeviceNotificationsWindowWinTest, | |
| 338 DevicesDetachedHighBoundary) { | |
| 339 PreAttachDevices(); | |
| 340 | |
| 341 DeviceIndices device_indices; | |
| 342 device_indices.push_back(25); | |
| 343 | |
| 344 DoMassStorageDevicesDetachedTest(device_indices); | |
| 345 } | |
| 346 | |
| 347 TEST_F(RemovableDeviceNotificationsWindowWinTest, | |
| 348 DevicesDetachedLowBoundary) { | |
| 349 PreAttachDevices(); | |
| 350 | |
| 351 DeviceIndices device_indices; | |
| 352 device_indices.push_back(0); | |
| 353 | |
| 354 DoMassStorageDevicesDetachedTest(device_indices); | |
| 355 } | |
| 356 | |
| 357 TEST_F(RemovableDeviceNotificationsWindowWinTest, | |
| 358 DevicesDetachedAdjacentBits) { | |
| 359 PreAttachDevices(); | |
| 360 | |
| 361 DeviceIndices device_indices; | |
| 362 device_indices.push_back(0); | |
| 363 device_indices.push_back(1); | |
| 364 device_indices.push_back(2); | |
| 365 device_indices.push_back(3); | |
| 366 | |
| 367 DoMassStorageDevicesDetachedTest(device_indices); | |
| 368 } | |
| 369 | |
| 370 TEST_F(RemovableDeviceNotificationsWindowWinTest, | |
| 371 DuplicateAttachCheckSuppressed) { | |
| 372 volume_mount_watcher_->BlockDeviceCheckForTesting(); | |
| 373 base::FilePath kAttachedDevicePath = | |
| 374 VolumeMountWatcherWin::DriveNumberToFilePath(8); // I: | |
| 375 | |
| 376 DEV_BROADCAST_VOLUME volume_broadcast; | |
| 377 volume_broadcast.dbcv_size = sizeof(volume_broadcast); | |
| 378 volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME; | |
| 379 volume_broadcast.dbcv_flags = 0x0; | |
| 380 volume_broadcast.dbcv_unitmask = 0x100; // I: drive | |
| 381 window_->InjectDeviceChange(DBT_DEVICEARRIVAL, | |
| 382 reinterpret_cast<DWORD>(&volume_broadcast)); | |
| 383 | |
| 384 EXPECT_EQ(0u, volume_mount_watcher_->devices_checked().size()); | |
| 385 | |
| 386 // Re-attach the same volume. We haven't released the mock device check | |
| 387 // event, so there'll be pending calls in the UI thread to finish the | |
| 388 // device check notification, blocking the duplicate device injection. | |
| 389 window_->InjectDeviceChange(DBT_DEVICEARRIVAL, | |
| 390 reinterpret_cast<DWORD>(&volume_broadcast)); | |
| 391 | |
| 392 EXPECT_EQ(0u, volume_mount_watcher_->devices_checked().size()); | |
| 393 volume_mount_watcher_->ReleaseDeviceCheck(); | |
| 394 RunUntilIdle(); | |
| 395 volume_mount_watcher_->ReleaseDeviceCheck(); | |
| 396 | |
| 397 // Now let all attach notifications finish running. We'll only get one | |
| 398 // finish-attach call. | |
| 399 volume_mount_watcher_->FlushWorkerPoolForTesting(); | |
| 400 RunUntilIdle(); | |
| 401 | |
| 402 std::vector<base::FilePath> checked_devices = | |
| 403 volume_mount_watcher_->devices_checked(); | |
| 404 ASSERT_EQ(1u, checked_devices.size()); | |
| 405 EXPECT_EQ(kAttachedDevicePath, checked_devices[0]); | |
| 406 | |
| 407 // We'll receive a duplicate check now that the first check has fully cleared. | |
| 408 window_->InjectDeviceChange(DBT_DEVICEARRIVAL, | |
| 409 reinterpret_cast<DWORD>(&volume_broadcast)); | |
| 410 volume_mount_watcher_->FlushWorkerPoolForTesting(); | |
| 411 volume_mount_watcher_->ReleaseDeviceCheck(); | |
| 412 RunUntilIdle(); | |
| 413 | |
| 414 checked_devices = volume_mount_watcher_->devices_checked(); | |
| 415 ASSERT_EQ(2u, checked_devices.size()); | |
| 416 EXPECT_EQ(kAttachedDevicePath, checked_devices[0]); | |
| 417 EXPECT_EQ(kAttachedDevicePath, checked_devices[1]); | |
| 418 } | |
| 419 | |
| 420 TEST_F(RemovableDeviceNotificationsWindowWinTest, DeviceInfoForPath) { | |
| 421 PreAttachDevices(); | |
| 422 | |
| 423 // An invalid path. | |
| 424 EXPECT_FALSE(window_->GetStorageInfoForPath(base::FilePath(L"COM1:\\"), | |
| 425 NULL)); | |
| 426 | |
| 427 // An unconnected removable device. | |
| 428 EXPECT_FALSE(window_->GetStorageInfoForPath(base::FilePath(L"E:\\"), NULL)); | |
| 429 | |
| 430 // A connected removable device. | |
| 431 base::FilePath removable_device(L"F:\\"); | |
| 432 StorageMonitor::StorageInfo device_info; | |
| 433 EXPECT_TRUE(window_->GetStorageInfoForPath(removable_device, &device_info)); | |
| 434 | |
| 435 std::string unique_id; | |
| 436 string16 device_name; | |
| 437 string16 location; | |
| 438 bool removable; | |
| 439 uint64 total_size_in_bytes; | |
| 440 ASSERT_TRUE(volume_mount_watcher_->GetDeviceInfo( | |
| 441 removable_device, &location, &unique_id, &device_name, &removable, | |
| 442 &total_size_in_bytes)); | |
| 443 EXPECT_TRUE(removable); | |
| 444 std::string device_id = MediaStorageUtil::MakeDeviceId( | |
| 445 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM, unique_id); | |
| 446 EXPECT_EQ(device_id, device_info.device_id); | |
| 447 EXPECT_EQ(device_name, device_info.name); | |
| 448 EXPECT_EQ(removable_device.value(), device_info.location); | |
| 449 EXPECT_EQ(1000000, total_size_in_bytes); | |
| 450 | |
| 451 // A fixed device. | |
| 452 base::FilePath fixed_device(L"N:\\"); | |
| 453 EXPECT_TRUE(window_->GetStorageInfoForPath(fixed_device, &device_info)); | |
| 454 | |
| 455 ASSERT_TRUE(volume_mount_watcher_->GetDeviceInfo( | |
| 456 fixed_device, &location, &unique_id, &device_name, &removable, NULL)); | |
| 457 EXPECT_FALSE(removable); | |
| 458 device_id = MediaStorageUtil::MakeDeviceId( | |
| 459 MediaStorageUtil::FIXED_MASS_STORAGE, unique_id); | |
| 460 EXPECT_EQ(device_id, device_info.device_id); | |
| 461 EXPECT_EQ(device_name, device_info.name); | |
| 462 EXPECT_EQ(fixed_device.value(), device_info.location); | |
| 463 } | |
| 464 | |
| 465 // Test to verify basic MTP storage attach and detach notifications. | |
| 466 TEST_F(RemovableDeviceNotificationsWindowWinTest, MTPDeviceBasicAttachDetach) { | |
| 467 DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithValidInfo, true); | |
| 468 DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithValidInfo, false); | |
| 469 } | |
| 470 | |
| 471 // When a MTP storage device with invalid storage label and id is | |
| 472 // attached/detached, there should not be any device attach/detach | |
| 473 // notifications. | |
| 474 TEST_F(RemovableDeviceNotificationsWindowWinTest, MTPDeviceWithInvalidInfo) { | |
| 475 DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithInvalidInfo, | |
| 476 true); | |
| 477 DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithInvalidInfo, | |
| 478 false); | |
| 479 } | |
| 480 | |
| 481 // Attach a device with two data partitions. Verify that attach/detach | |
| 482 // notifications are sent out for each removable storage. | |
| 483 TEST_F(RemovableDeviceNotificationsWindowWinTest, | |
| 484 MTPDeviceWithMultipleStorageObjects) { | |
| 485 DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithMultipleStorages, | |
| 486 true); | |
| 487 DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithMultipleStorages, | |
| 488 false); | |
| 489 } | |
| 490 | |
| 491 TEST_F(RemovableDeviceNotificationsWindowWinTest, DriveNumberToFilePath) { | |
| 492 EXPECT_EQ(L"A:\\", VolumeMountWatcherWin::DriveNumberToFilePath(0).value()); | |
| 493 EXPECT_EQ(L"Y:\\", VolumeMountWatcherWin::DriveNumberToFilePath(24).value()); | |
| 494 EXPECT_EQ(L"", VolumeMountWatcherWin::DriveNumberToFilePath(-1).value()); | |
| 495 EXPECT_EQ(L"", VolumeMountWatcherWin::DriveNumberToFilePath(199).value()); | |
| 496 } | |
| 497 | |
| 498 // Given a MTP storage persistent id, GetMTPStorageInfo() should fetch the | |
| 499 // device interface path and local storage object identifier. | |
| 500 TEST_F(RemovableDeviceNotificationsWindowWinTest, | |
| 501 GetMTPStorageInfoFromDeviceId) { | |
| 502 DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithValidInfo, true); | |
| 503 PortableDeviceWatcherWin::StorageObjects storage_objects = | |
| 504 TestPortableDeviceWatcherWin::GetDeviceStorageObjects( | |
| 505 TestPortableDeviceWatcherWin::kMTPDeviceWithValidInfo); | |
| 506 for (PortableDeviceWatcherWin::StorageObjects::const_iterator it = | |
| 507 storage_objects.begin(); | |
| 508 it != storage_objects.end(); ++it) { | |
| 509 string16 pnp_device_id; | |
| 510 string16 storage_object_id; | |
| 511 ASSERT_TRUE(GetMTPStorageInfo(it->object_persistent_id, &pnp_device_id, | |
| 512 &storage_object_id)); | |
| 513 EXPECT_EQ(string16(TestPortableDeviceWatcherWin::kMTPDeviceWithValidInfo), | |
| 514 pnp_device_id); | |
| 515 EXPECT_EQ(it->object_persistent_id, | |
| 516 TestPortableDeviceWatcherWin::GetMTPStorageUniqueId( | |
| 517 pnp_device_id, storage_object_id)); | |
| 518 } | |
| 519 DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithValidInfo, false); | |
| 520 } | |
| 521 | |
| 522 } // namespace test | |
| 523 } // namespace chrome | |
| OLD | NEW |