15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <windows.h>
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <dbt.h>
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/ref_counted.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/run_loop.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/synchronization/waitable_event.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/storage_monitor/mock_removable_storage_observer.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/storage_monitor/portable_device_watcher_win.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/storage_monitor/removable_device_constants.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/storage_monitor/storage_info.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/storage_monitor/storage_monitor_win.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/storage_monitor/test_portable_device_watcher_win.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/storage_monitor/test_storage_monitor.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/storage_monitor/test_storage_monitor_win.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/storage_monitor/test_volume_mount_watcher_win.h"
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/storage_monitor/volume_mount_watcher_win.h"
261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "content/public/test/test_browser_thread_bundle.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::ASCIIToUTF16;
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread;
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef std::vector<int> DeviceIndices;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// StorageMonitorWinTest -------------------------------------------------------
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace storage_monitor {
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class StorageMonitorWinTest : public testing::Test {
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StorageMonitorWinTest();
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~StorageMonitorWinTest();
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // testing::Test:
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUp() OVERRIDE;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void TearDown() OVERRIDE;
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void PreAttachDevices();
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Runs all the pending tasks on UI thread, FILE thread and blocking thread.
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void RunUntilIdle();
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void DoMassStorageDeviceAttachedTest(const DeviceIndices& device_indices);
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void DoMassStorageDevicesDetachedTest(const DeviceIndices& device_indices);
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Injects a device attach or detach change (depending on the value of
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |test_attach|) and tests that the appropriate handler is called.
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void DoMTPDeviceTest(const base::string16& pnp_device_id, bool test_attach);
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Gets the MTP details of the storage specified by the |storage_device_id|.
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // On success, returns true and fills in |pnp_device_id| and
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |storage_object_id|.
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool GetMTPStorageInfo(const std::string& storage_device_id,
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         base::string16* pnp_device_id,
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         base::string16* storage_object_id);
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<TestStorageMonitorWin> monitor_;
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Weak pointer; owned by the device notifications class.
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestVolumeMountWatcherWin* volume_mount_watcher_;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRemovableStorageObserver observer_;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  content::TestBrowserThreadBundle thread_bundle_;
771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(StorageMonitorWinTest);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)StorageMonitorWinTest::StorageMonitorWinTest() {
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)StorageMonitorWinTest::~StorageMonitorWinTest() {
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StorageMonitorWinTest::SetUp() {
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_mount_watcher_ = new TestVolumeMountWatcherWin;
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  monitor_.reset(new TestStorageMonitorWin(volume_mount_watcher_,
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                           new TestPortableDeviceWatcherWin));
91ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  monitor_->Init();
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunUntilIdle();
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  monitor_->AddObserver(&observer_);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StorageMonitorWinTest::TearDown() {
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunUntilIdle();
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  monitor_->RemoveObserver(&observer_);
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_mount_watcher_->ShutdownWorkerPool();
101ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
102ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Windows storage monitor must be destroyed on the same thread
103ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // as construction.
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  monitor_.reset();
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StorageMonitorWinTest::PreAttachDevices() {
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  monitor_.reset();
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_mount_watcher_ = new TestVolumeMountWatcherWin;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_mount_watcher_->SetAttachedDevicesFake();
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int expect_attach_calls = 0;
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<base::FilePath> initial_devices =
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      volume_mount_watcher_->GetAttachedDevicesCallback().Run();
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::vector<base::FilePath>::const_iterator it = initial_devices.begin();
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != initial_devices.end(); ++it) {
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool removable;
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_TRUE(volume_mount_watcher_->GetDeviceRemovable(*it, &removable));
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (removable)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      expect_attach_calls++;
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  monitor_.reset(new TestStorageMonitorWin(volume_mount_watcher_,
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                           new TestPortableDeviceWatcherWin));
125ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  monitor_->AddObserver(&observer_);
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  monitor_->Init();
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, volume_mount_watcher_->devices_checked().size());
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This dance is because attachment bounces through a couple of
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // closures, which need to be executed to finish the process.
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunUntilIdle();
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_mount_watcher_->FlushWorkerPoolForTesting();
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunUntilIdle();
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<base::FilePath> checked_devices =
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      volume_mount_watcher_->devices_checked();
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sort(checked_devices.begin(), checked_devices.end());
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(initial_devices, checked_devices);
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expect_attach_calls, observer_.attach_calls());
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, observer_.detach_calls());
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StorageMonitorWinTest::RunUntilIdle() {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_mount_watcher_->FlushWorkerPoolForTesting();
1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StorageMonitorWinTest::DoMassStorageDeviceAttachedTest(
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const DeviceIndices& device_indices) {
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DEV_BROADCAST_VOLUME volume_broadcast;
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_broadcast.dbcv_size = sizeof(volume_broadcast);
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME;
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_broadcast.dbcv_unitmask = 0x0;
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_broadcast.dbcv_flags = 0x0;
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int expect_attach_calls = observer_.attach_calls();
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (DeviceIndices::const_iterator it = device_indices.begin();
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != device_indices.end(); ++it) {
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    volume_broadcast.dbcv_unitmask |= 0x1 << *it;
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool removable;
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_TRUE(volume_mount_watcher_->GetDeviceRemovable(
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        VolumeMountWatcherWin::DriveNumberToFilePath(*it), &removable));
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (removable)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      expect_attach_calls++;
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  monitor_->InjectDeviceChange(DBT_DEVICEARRIVAL,
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               reinterpret_cast<DWORD>(&volume_broadcast));
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunUntilIdle();
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_mount_watcher_->FlushWorkerPoolForTesting();
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunUntilIdle();
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expect_attach_calls, observer_.attach_calls());
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, observer_.detach_calls());
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StorageMonitorWinTest::DoMassStorageDevicesDetachedTest(
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const DeviceIndices& device_indices) {
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DEV_BROADCAST_VOLUME volume_broadcast;
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_broadcast.dbcv_size = sizeof(volume_broadcast);
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME;
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_broadcast.dbcv_unitmask = 0x0;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_broadcast.dbcv_flags = 0x0;
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int pre_attach_calls = observer_.attach_calls();
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int expect_detach_calls = 0;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (DeviceIndices::const_iterator it = device_indices.begin();
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != device_indices.end(); ++it) {
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    volume_broadcast.dbcv_unitmask |= 0x1 << *it;
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StorageInfo info;
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(volume_mount_watcher_->GetDeviceInfo(
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        VolumeMountWatcherWin::DriveNumberToFilePath(*it), &info));
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (StorageInfo::IsRemovableDevice(info.device_id()))
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      ++expect_detach_calls;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  monitor_->InjectDeviceChange(DBT_DEVICEREMOVECOMPLETE,
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               reinterpret_cast<DWORD>(&volume_broadcast));
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunUntilIdle();
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(pre_attach_calls, observer_.attach_calls());
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expect_detach_calls, observer_.detach_calls());
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void StorageMonitorWinTest::DoMTPDeviceTest(const base::string16& pnp_device_id,
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            bool test_attach) {
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GUID guidDevInterface = GUID_NULL;
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HRESULT hr = CLSIDFromString(kWPDDevInterfaceGUID, &guidDevInterface);
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (FAILED(hr))
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  size_t device_id_size = pnp_device_id.size() * sizeof(base::char16);
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t size = sizeof(DEV_BROADCAST_DEVICEINTERFACE) + device_id_size;
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<DEV_BROADCAST_DEVICEINTERFACE, base::FreeDeleter>
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      dev_interface_broadcast(
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          static_cast<DEV_BROADCAST_DEVICEINTERFACE*>(malloc(size)));
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(dev_interface_broadcast.get());
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ZeroMemory(dev_interface_broadcast.get(), size);
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dev_interface_broadcast->dbcc_size = size;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dev_interface_broadcast->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dev_interface_broadcast->dbcc_classguid = guidDevInterface;
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  memcpy(dev_interface_broadcast->dbcc_name, pnp_device_id.data(),
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         device_id_size);
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int expect_attach_calls = observer_.attach_calls();
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int expect_detach_calls = observer_.detach_calls();
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PortableDeviceWatcherWin::StorageObjectIDs storage_object_ids =
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      TestPortableDeviceWatcherWin::GetMTPStorageObjectIds(pnp_device_id);
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (PortableDeviceWatcherWin::StorageObjectIDs::const_iterator it =
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       storage_object_ids.begin(); it != storage_object_ids.end(); ++it) {
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string unique_id;
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::string16 name;
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::string16 location;
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TestPortableDeviceWatcherWin::GetMTPStorageDetails(pnp_device_id, *it,
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                       &location, &unique_id,
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                       &name);
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (test_attach && !name.empty() && !unique_id.empty())
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      expect_attach_calls++;
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else if (!name.empty() && !unique_id.empty())
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      expect_detach_calls++;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  monitor_->InjectDeviceChange(
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_attach ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE,
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      reinterpret_cast<DWORD>(dev_interface_broadcast.get()));
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunUntilIdle();
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expect_attach_calls, observer_.attach_calls());
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expect_detach_calls, observer_.detach_calls());
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool StorageMonitorWinTest::GetMTPStorageInfo(
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& storage_device_id,
254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::string16* pnp_device_id,
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::string16* storage_object_id) {
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return monitor_->GetMTPStorageInfoFromDeviceId(storage_device_id,
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 pnp_device_id,
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 storage_object_id);
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(StorageMonitorWinTest, RandomMessage) {
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  monitor_->InjectDeviceChange(DBT_DEVICEQUERYREMOVE, NULL);
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunUntilIdle();
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(StorageMonitorWinTest, DevicesAttached) {
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeviceIndices device_indices;
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(1);  // B
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(5);  // F
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(7);  // H
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(13);  // N
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DoMassStorageDeviceAttachedTest(device_indices);
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StorageInfo info;
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(monitor_->volume_mount_watcher()->GetDeviceInfo(
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::FilePath(ASCIIToUTF16("F:\\")), &info));
27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("F:\\"), info.location());
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ("dcim:\\\\?\\Volume{F0000000-0000-0000-0000-000000000000}\\",
27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            info.device_id());
28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("F:\\ Drive"), info.storage_label());
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(monitor_->GetStorageInfoForPath(
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath(ASCIIToUTF16("G:\\")), &info));
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(monitor_->GetStorageInfoForPath(
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath(ASCIIToUTF16("F:\\")), &info));
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StorageInfo info1;
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(monitor_->GetStorageInfoForPath(
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath(ASCIIToUTF16("F:\\subdir")), &info1));
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StorageInfo info2;
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(monitor_->GetStorageInfoForPath(
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath(ASCIIToUTF16("F:\\subdir\\sub")), &info2));
29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("F:\\ Drive"), info.storage_label());
29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("F:\\ Drive"), info1.storage_label());
29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("F:\\ Drive"), info2.storage_label());
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(StorageMonitorWinTest, PathMountDevices) {
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PreAttachDevices();
2997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  int init_storages = monitor_->GetAllAvailableStorages().size();
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  volume_mount_watcher_->AddDeviceForTesting(
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::FilePath(FILE_PATH_LITERAL("F:\\mount1")),
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "dcim:mount1", L"mount1", 100);
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  volume_mount_watcher_->AddDeviceForTesting(
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::FilePath(FILE_PATH_LITERAL("F:\\mount1\\subdir")),
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "dcim:mount1subdir", L"mount1subdir", 100);
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  volume_mount_watcher_->AddDeviceForTesting(
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::FilePath(FILE_PATH_LITERAL("F:\\mount2")),
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "dcim:mount2", L"mount2", 100);
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RunUntilIdle();
3117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(init_storages + 3, monitor_->GetAllAvailableStorages().size());
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StorageInfo info;
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(monitor_->GetStorageInfoForPath(
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::FilePath(ASCIIToUTF16("F:\\dir")), &info));
316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(L"F:\\ Drive", info.GetDisplayName(false));
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(monitor_->GetStorageInfoForPath(
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::FilePath(ASCIIToUTF16("F:\\mount1")), &info));
319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(L"mount1", info.GetDisplayName(false));
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(monitor_->GetStorageInfoForPath(
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::FilePath(ASCIIToUTF16("F:\\mount1\\dir")), &info));
322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(L"mount1", info.GetDisplayName(false));
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(monitor_->GetStorageInfoForPath(
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::FilePath(ASCIIToUTF16("F:\\mount2\\dir")), &info));
325a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(L"mount2", info.GetDisplayName(false));
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(monitor_->GetStorageInfoForPath(
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::FilePath(ASCIIToUTF16("F:\\mount1\\subdir")), &info));
328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(L"mount1subdir", info.GetDisplayName(false));
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(monitor_->GetStorageInfoForPath(
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::FilePath(ASCIIToUTF16("F:\\mount1\\subdir\\dir")), &info));
331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(L"mount1subdir", info.GetDisplayName(false));
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(monitor_->GetStorageInfoForPath(
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::FilePath(ASCIIToUTF16("F:\\mount1\\subdir\\dir\\dir")), &info));
334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(L"mount1subdir", info.GetDisplayName(false));
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(StorageMonitorWinTest, DevicesAttachedHighBoundary) {
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeviceIndices device_indices;
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(25);
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DoMassStorageDeviceAttachedTest(device_indices);
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(StorageMonitorWinTest, DevicesAttachedLowBoundary) {
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeviceIndices device_indices;
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(0);
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DoMassStorageDeviceAttachedTest(device_indices);
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(StorageMonitorWinTest, DevicesAttachedAdjacentBits) {
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeviceIndices device_indices;
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(0);
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(1);
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(2);
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(3);
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DoMassStorageDeviceAttachedTest(device_indices);
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(StorageMonitorWinTest, DevicesDetached) {
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PreAttachDevices();
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeviceIndices device_indices;
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(1);
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(5);
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(7);
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(13);
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DoMassStorageDevicesDetachedTest(device_indices);
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(StorageMonitorWinTest, DevicesDetachedHighBoundary) {
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PreAttachDevices();
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeviceIndices device_indices;
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(25);
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DoMassStorageDevicesDetachedTest(device_indices);
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(StorageMonitorWinTest, DevicesDetachedLowBoundary) {
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PreAttachDevices();
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeviceIndices device_indices;
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(0);
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DoMassStorageDevicesDetachedTest(device_indices);
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(StorageMonitorWinTest, DevicesDetachedAdjacentBits) {
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PreAttachDevices();
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeviceIndices device_indices;
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(0);
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(1);
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(2);
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_indices.push_back(3);
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DoMassStorageDevicesDetachedTest(device_indices);
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(StorageMonitorWinTest, DuplicateAttachCheckSuppressed) {
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Make sure the original C: mount notification makes it all the
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // way through.
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RunUntilIdle();
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  volume_mount_watcher_->FlushWorkerPoolForTesting();
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RunUntilIdle();
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_mount_watcher_->BlockDeviceCheckForTesting();
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath kAttachedDevicePath =
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      VolumeMountWatcherWin::DriveNumberToFilePath(8);  // I:
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DEV_BROADCAST_VOLUME volume_broadcast;
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_broadcast.dbcv_size = sizeof(volume_broadcast);
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME;
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_broadcast.dbcv_flags = 0x0;
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_broadcast.dbcv_unitmask = 0x100;  // I: drive
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  monitor_->InjectDeviceChange(DBT_DEVICEARRIVAL,
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               reinterpret_cast<DWORD>(&volume_broadcast));
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, volume_mount_watcher_->devices_checked().size());
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Re-attach the same volume. We haven't released the mock device check
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // event, so there'll be pending calls in the UI thread to finish the
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // device check notification, blocking the duplicate device injection.
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  monitor_->InjectDeviceChange(DBT_DEVICEARRIVAL,
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               reinterpret_cast<DWORD>(&volume_broadcast));
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, volume_mount_watcher_->devices_checked().size());
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_mount_watcher_->ReleaseDeviceCheck();
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunUntilIdle();
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_mount_watcher_->ReleaseDeviceCheck();
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Now let all attach notifications finish running. We'll only get one
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // finish-attach call.
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_mount_watcher_->FlushWorkerPoolForTesting();
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunUntilIdle();
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const std::vector<base::FilePath>& checked_devices =
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      volume_mount_watcher_->devices_checked();
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(1u, checked_devices.size());
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kAttachedDevicePath, checked_devices[0]);
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We'll receive a duplicate check now that the first check has fully cleared.
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  monitor_->InjectDeviceChange(DBT_DEVICEARRIVAL,
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               reinterpret_cast<DWORD>(&volume_broadcast));
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_mount_watcher_->FlushWorkerPoolForTesting();
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_mount_watcher_->ReleaseDeviceCheck();
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunUntilIdle();
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(2u, checked_devices.size());
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kAttachedDevicePath, checked_devices[0]);
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kAttachedDevicePath, checked_devices[1]);
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(StorageMonitorWinTest, DeviceInfoForPath) {
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PreAttachDevices();
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
46090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  StorageInfo device_info;
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // An invalid path.
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(monitor_->GetStorageInfoForPath(base::FilePath(L"COM1:\\"),
46390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                               &device_info));
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // An unconnected removable device.
46690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_FALSE(monitor_->GetStorageInfoForPath(base::FilePath(L"E:\\"),
46790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                               &device_info));
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // A connected removable device.
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath removable_device(L"F:\\");
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(monitor_->GetStorageInfoForPath(removable_device, &device_info));
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StorageInfo info;
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(volume_mount_watcher_->GetDeviceInfo(removable_device, &info));
47590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(StorageInfo::IsRemovableDevice(info.device_id()));
47690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(info.device_id(), device_info.device_id());
477a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(info.GetDisplayName(false), device_info.GetDisplayName(false));
47890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(info.location(), device_info.location());
47990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(1000000, info.total_size_in_bytes());
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // A fixed device.
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath fixed_device(L"N:\\");
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(monitor_->GetStorageInfoForPath(fixed_device, &device_info));
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(volume_mount_watcher_->GetDeviceInfo(
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      fixed_device, &info));
48790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_FALSE(StorageInfo::IsRemovableDevice(info.device_id()));
48890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(info.device_id(), device_info.device_id());
489a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(info.GetDisplayName(false), device_info.GetDisplayName(false));
49090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(info.location(), device_info.location());
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Test to verify basic MTP storage attach and detach notifications.
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(StorageMonitorWinTest, MTPDeviceBasicAttachDetach) {
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithValidInfo, true);
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithValidInfo, false);
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// When a MTP storage device with invalid storage label and id is
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// attached/detached, there should not be any device attach/detach
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// notifications.
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(StorageMonitorWinTest, MTPDeviceWithInvalidInfo) {
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithInvalidInfo,
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  true);
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithInvalidInfo,
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  false);
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Attach a device with two data partitions. Verify that attach/detach
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// notifications are sent out for each removable storage.
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(StorageMonitorWinTest, MTPDeviceWithMultipleStorageObjects) {
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithMultipleStorages,
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  true);
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithMultipleStorages,
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  false);
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(StorageMonitorWinTest, DriveNumberToFilePath) {
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(L"A:\\", VolumeMountWatcherWin::DriveNumberToFilePath(0).value());
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(L"Y:\\", VolumeMountWatcherWin::DriveNumberToFilePath(24).value());
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(L"", VolumeMountWatcherWin::DriveNumberToFilePath(-1).value());
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(L"", VolumeMountWatcherWin::DriveNumberToFilePath(199).value());
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Given a MTP storage persistent id, GetMTPStorageInfo() should fetch the
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// device interface path and local storage object identifier.
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(StorageMonitorWinTest, GetMTPStorageInfoFromDeviceId) {
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithValidInfo, true);
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PortableDeviceWatcherWin::StorageObjects storage_objects =
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      TestPortableDeviceWatcherWin::GetDeviceStorageObjects(
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          TestPortableDeviceWatcherWin::kMTPDeviceWithValidInfo);
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (PortableDeviceWatcherWin::StorageObjects::const_iterator it =
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           storage_objects.begin();
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != storage_objects.end(); ++it) {
535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::string16 pnp_device_id;
536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::string16 storage_object_id;
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(GetMTPStorageInfo(it->object_persistent_id, &pnp_device_id,
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  &storage_object_id));
539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::string16 expected(
540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        TestPortableDeviceWatcherWin::kMTPDeviceWithValidInfo);
541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_EQ(expected, pnp_device_id);
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(it->object_persistent_id,
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              TestPortableDeviceWatcherWin::GetMTPStorageUniqueId(
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  pnp_device_id, storage_object_id));
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithValidInfo, false);
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
548a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
549a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace storage_monitor
550