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

Side by Side Diff: chrome/browser/system_monitor/removable_device_notifications_window_win_unittest.cc

Issue 11088012: [Win, MediaGallery] Enumerate and handle mtp device attach/detach events. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed review comments Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/system_monitor/removable_device_notifications_window_wi n.h" 5 #include "chrome/browser/system_monitor/removable_device_notifications_window_wi n.h"
6 6
7 #include <dbt.h> 7 #include <dbt.h>
8 8
9 #include <string> 9 #include <string>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/file_util.h" 12 #include "base/file_util.h"
13 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/scoped_ptr.h"
14 #include "base/message_loop.h" 14 #include "base/message_loop.h"
15 #include "base/scoped_temp_dir.h" 15 #include "base/scoped_temp_dir.h"
16 #include "base/system_monitor/system_monitor.h" 16 #include "base/system_monitor/system_monitor.h"
17 #include "base/test/mock_devices_changed_observer.h" 17 #include "base/test/mock_devices_changed_observer.h"
18 #include "base/threading/sequenced_worker_pool.h"
18 #include "chrome/browser/system_monitor/media_storage_util.h" 19 #include "chrome/browser/system_monitor/media_storage_util.h"
20 #include "chrome/browser/system_monitor/removable_device_constants.h"
19 #include "chrome/browser/system_monitor/volume_mount_watcher_win.h" 21 #include "chrome/browser/system_monitor/volume_mount_watcher_win.h"
20 #include "content/public/test/test_browser_thread.h" 22 #include "content/public/test/test_browser_thread.h"
21 #include "testing/gmock/include/gmock/gmock.h" 23 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h" 24 #include "testing/gtest/include/gtest/gtest.h"
23 25
24 namespace { 26 namespace {
25 27
26 using content::BrowserThread; 28 using content::BrowserThread;
27 using chrome::RemovableDeviceNotificationsWindowWin; 29 using chrome::RemovableDeviceNotificationsWindowWin;
28 30
31 // Mtp device interface path constants.
32 const char16 kMtpDeviceWithInvalidInfo[] =
33 L"\\?\usb#vid_00&pid_00#0&2&1#{0000-0000-0000-0000-0000})";
34 const char16 kMtpDeviceWithValidInfo[] =
35 L"\\?\usb#vid_ff&pid_000f#32&2&1#{abcd-1234-ffde-1112-9172})";
36 const char16 kMtpDeviceWithMultipleStorage[] =
37 L"\\?\usb#vid_ff&pid_18#32&2&1#{ab33-1de4-f22e-1882-9724})";
38
39 // Sample mtp device storage information.
40 const char16 kMtpDeviceFriendlyName[] = L"Camera V1.1";
41 const char16 kStorageLabelA[] = L"Camera V1.1 (s10001)";
42 const char16 kStorageLabelB[] = L"Camera V1.1 (s20001)";
43 const char16 kStorageObjectIdA[] = L"s10001";
44 const char16 kStorageObjectIdB[] = L"s20001";
45 const char kStorageUniqueIdA[] =
46 "mtp:StorageSerial:SID-{s10001, D, 12378}:123123";
47 const char kStorageUniqueIdB[] =
48 "mtp:StorageSerial:SID-{s20001, S, 2238}:123123";
49
29 // Inputs of 'A:\' - 'Z:\' are valid. 'N:\' is not removable. 50 // Inputs of 'A:\' - 'Z:\' are valid. 'N:\' is not removable.
30 bool GetDeviceDetails(const FilePath& device_path, string16* device_location, 51 bool GetMassStorageDeviceDetails(const FilePath& device_path,
31 std::string* unique_id, string16* name, bool* removable) { 52 string16* device_location, std::string* unique_id, string16* name,
53 bool* removable) {
Peter Kasting 2012/10/19 21:31:12 Nit: One arg per line, indented even (several plac
kmadhusu 2012/10/23 23:44:17 Done.
32 if (device_path.value().length() != 3 || device_path.value()[0] < L'A' || 54 if (device_path.value().length() != 3 || device_path.value()[0] < L'A' ||
33 device_path.value()[0] > L'Z') { 55 device_path.value()[0] > L'Z') {
34 return false; 56 return false;
35 } 57 }
36 58
37 if (device_location) 59 if (device_location)
38 *device_location = device_path.value(); 60 *device_location = device_path.value();
39 if (unique_id) { 61 if (unique_id) {
40 *unique_id = "\\\\?\\Volume{00000000-0000-0000-0000-000000000000}\\"; 62 *unique_id = "\\\\?\\Volume{00000000-0000-0000-0000-000000000000}\\";
41 (*unique_id)[11] = device_path.value()[0]; 63 (*unique_id)[11] = device_path.value()[0];
(...skipping 16 matching lines...) Expand all
58 result.push_back(DriveNumberToFilePath(0)); 80 result.push_back(DriveNumberToFilePath(0));
59 result.push_back(DriveNumberToFilePath(1)); 81 result.push_back(DriveNumberToFilePath(1));
60 result.push_back(DriveNumberToFilePath(2)); 82 result.push_back(DriveNumberToFilePath(2));
61 result.push_back(DriveNumberToFilePath(3)); 83 result.push_back(DriveNumberToFilePath(3));
62 result.push_back(DriveNumberToFilePath(5)); 84 result.push_back(DriveNumberToFilePath(5));
63 result.push_back(DriveNumberToFilePath(7)); 85 result.push_back(DriveNumberToFilePath(7));
64 result.push_back(DriveNumberToFilePath(25)); 86 result.push_back(DriveNumberToFilePath(25));
65 return result; 87 return result;
66 } 88 }
67 89
90 // Returns the persistent storage unique id of the device specified by the
91 // |pnp_device_id|. |storage_object_id| specifies the temporary object
92 // identifier that uniquely identifies the object on the device.
93 std::string GetMtpStorageUniqueId(const string16& pnp_device_id,
94 const string16& storage_object_id) {
95 if (pnp_device_id == string16(kMtpDeviceWithInvalidInfo))
Peter Kasting 2012/10/19 21:31:12 Nit: No need for explicit string16 construction (m
kmadhusu 2012/10/23 23:44:17 Done.
96 return std::string();
97
98 if (storage_object_id == string16(kStorageObjectIdA))
99 return kStorageUniqueIdA;
100
101 if (storage_object_id == string16(kStorageObjectIdB))
102 return kStorageUniqueIdB;
103 return std::string();
Peter Kasting 2012/10/19 21:31:12 Nit: Or just: return (storage_object_id == kSto
kmadhusu 2012/10/23 23:44:17 Done.
104 }
105
106 // Returns the storage name of the device specified by |pnp_device_id|.
107 // |storage_object_id| specifies the temporary object identifier that
108 // uniquely identifies the object on the device.
109 string16 GetMtpStorageName(const string16& pnp_device_id,
110 const string16& storage_object_id) {
111 if (pnp_device_id == string16(kMtpDeviceWithInvalidInfo))
112 return string16();
113
114 if (storage_object_id == string16(kStorageObjectIdA))
115 return string16(kStorageLabelA);
116
117 if (storage_object_id == string16(kStorageObjectIdB))
118 return string16(kStorageLabelB);
119 return string16();
120 }
121
122 // Returns a list of storage object identifiers of the device given a
123 // |pnp_device_id|.
124 std::vector<string16> GetMtpStorageObjectId(const string16& pnp_device_id) {
Peter Kasting 2012/10/19 21:31:12 Nit: GetMtpStorageObjectIds?
kmadhusu 2012/10/23 23:44:17 Done.
125 if (pnp_device_id == string16(kMtpDeviceWithInvalidInfo))
126 return std::vector<string16>();
127
128 std::vector<string16> storage_object_ids;
129 storage_object_ids.push_back(string16(kStorageObjectIdA));
130
131 if (pnp_device_id == string16(kMtpDeviceWithMultipleStorage))
132 storage_object_ids.push_back(string16(kStorageObjectIdB));
133 return storage_object_ids;
134 }
135
136 // Gets the mtp device storage details given a |pnp_device_id| and
137 // |storage_object_id|. On success, returns true and fills in
138 // |device_location|, |unique_id| and |name|.
139 bool GetMtpStorageDetails(
Peter Kasting 2012/10/19 21:31:12 This method can't fail, so return void.
kmadhusu 2012/10/23 23:44:17 Done.
140 const string16& pnp_device_id, const string16& storage_object_id,
141 string16* device_location, std::string* unique_id, string16* name) {
142 if (device_location)
143 *device_location = pnp_device_id;
144
145 if (unique_id)
146 *unique_id = GetMtpStorageUniqueId(pnp_device_id, storage_object_id);
147
148 if (name)
149 *name = GetMtpStorageName(pnp_device_id, storage_object_id);
150 return true;
151 }
152
68 } // namespace 153 } // namespace
69 154
70 namespace chrome { 155 namespace chrome {
71 156
157 // Wrapper class for testing PortableDeviceWatcherWin.
158 class TestPortableDeviceWatcherWin : public PortableDeviceWatcherWin {
159 public:
160 TestPortableDeviceWatcherWin() {
161 }
Peter Kasting 2012/10/19 21:31:12 Nit: Do not define functions inline in class decla
kmadhusu 2012/10/23 23:44:17 Done.
162
163 private:
164 // Avoids code deleting the object while there are references to it.
165 // Aside from the base::RefCountedThreadSafe friend class, any attempts to
166 // call this dtor will result in a compile-time error.
167 virtual ~TestPortableDeviceWatcherWin() {
168 }
169
170 // Override PortableDeviceWatcherWin::InitOnBlockingThread.
Peter Kasting 2012/10/19 21:31:12 Nit: Don't comment individual function overrides t
kmadhusu 2012/10/23 23:44:17 Done.
171 void InitOnBlockingThread() OVERRIDE {
172 }
173
174 // Override PortableDeviceWatcherWin::GetDeviceName.
175 virtual string16 GetDeviceName(const string16& pnp_device_id) OVERRIDE {
176 if (pnp_device_id == string16(kMtpDeviceWithInvalidInfo))
177 return string16();
178 return string16(kMtpDeviceFriendlyName);
179 }
180
181 // Override PortableDeviceWatcherWin::GetStorages.
182 virtual bool GetStorages(const string16& pnp_device_id,
183 std::vector<DeviceStorageInfo>* storages) OVERRIDE {
184 if (pnp_device_id == string16(kMtpDeviceWithInvalidInfo))
185 return false;
186
187 std::vector<string16> storage_object_ids =
188 GetMtpStorageObjectId(pnp_device_id);
189 for (size_t index = 0; index < storage_object_ids.size(); ++index) {
190 DeviceStorageInfo storage;
191 storage.unique_id = GetMtpStorageUniqueId(pnp_device_id,
192 storage_object_ids[index]);
193 storage.storage_object_id = storage_object_ids[index];
194 storages->push_back(storage);
195 }
196 return true;
197 }
198
199 DISALLOW_COPY_AND_ASSIGN(TestPortableDeviceWatcherWin);
200 };
201
72 // Wrapper class for testing VolumeMountWatcherWin. 202 // Wrapper class for testing VolumeMountWatcherWin.
73 class TestVolumeMountWatcherWin : public VolumeMountWatcherWin { 203 class TestVolumeMountWatcherWin : public VolumeMountWatcherWin {
74 public: 204 public:
75 TestVolumeMountWatcherWin() : pre_attach_devices_(false) { 205 TestVolumeMountWatcherWin() : pre_attach_devices_(false) {
76 } 206 }
77 207
78 // Override VolumeMountWatcherWin::GetDeviceInfo(). 208 // Override VolumeMountWatcherWin::GetDeviceInfo().
79 virtual bool GetDeviceInfo(const FilePath& device_path, 209 virtual bool GetDeviceInfo(const FilePath& device_path,
80 string16* device_location, std::string* unique_id, string16* name, 210 string16* device_location, std::string* unique_id, string16* name,
81 bool* removable) OVERRIDE { 211 bool* removable) OVERRIDE {
82 return GetDeviceDetails(device_path, device_location, unique_id, name, 212 return GetMassStorageDeviceDetails(device_path, device_location, unique_id,
83 removable); 213 name, removable);
84 } 214 }
85 215
86 // Override VolumeMountWatcherWin::GetAttachedDevices(). 216 // Override VolumeMountWatcherWin::GetAttachedDevices().
87 virtual std::vector<FilePath> GetAttachedDevices() OVERRIDE{ 217 virtual std::vector<FilePath> GetAttachedDevices() OVERRIDE{
88 if (pre_attach_devices_) 218 if (pre_attach_devices_)
89 return GetTestAttachedDevices(); 219 return GetTestAttachedDevices();
90 return std::vector<FilePath>(); 220 return std::vector<FilePath>();
91 } 221 }
92 222
93 void set_pre_attach_devices(bool pre_attach_devices) { 223 void set_pre_attach_devices(bool pre_attach_devices) {
94 pre_attach_devices_ = pre_attach_devices; 224 pre_attach_devices_ = pre_attach_devices;
95 } 225 }
96 226
97 private: 227 private:
98 // Private, this class is ref-counted. 228 // Private, this class is ref-counted.
99 virtual ~TestVolumeMountWatcherWin() { 229 virtual ~TestVolumeMountWatcherWin() {
100 } 230 }
101 231
102 // Set to true to pre-attach test devices. 232 // Set to true to pre-attach test devices.
103 bool pre_attach_devices_; 233 bool pre_attach_devices_;
104 }; 234 };
105 235
106 // Wrapper class for testing RemovableDeviceNotificationsWindowWin. 236 // Wrapper class for testing RemovableDeviceNotificationsWindowWin.
107 class TestRemovableDeviceNotificationsWindowWin 237 class TestRemovableDeviceNotificationsWindowWin
108 : public RemovableDeviceNotificationsWindowWin { 238 : public RemovableDeviceNotificationsWindowWin {
109 public: 239 public:
110 explicit TestRemovableDeviceNotificationsWindowWin( 240 explicit TestRemovableDeviceNotificationsWindowWin(
111 TestVolumeMountWatcherWin* volume_mount_watcher) 241 TestVolumeMountWatcherWin* volume_mount_watcher,
112 : RemovableDeviceNotificationsWindowWin(volume_mount_watcher), 242 TestPortableDeviceWatcherWin* portable_device_watcher)
243 : RemovableDeviceNotificationsWindowWin(
244 volume_mount_watcher, portable_device_watcher),
113 volume_mount_watcher_(volume_mount_watcher) { 245 volume_mount_watcher_(volume_mount_watcher) {
114 DCHECK(volume_mount_watcher_); 246 DCHECK(volume_mount_watcher_);
115 } 247 }
116 248
117 virtual ~TestRemovableDeviceNotificationsWindowWin() { 249 virtual ~TestRemovableDeviceNotificationsWindowWin() {
118 } 250 }
119 251
120 void InitWithTestData() { 252 void InitWithTestData() {
121 volume_mount_watcher_->set_pre_attach_devices(false); 253 volume_mount_watcher_->set_pre_attach_devices(false);
122 Init(); 254 Init();
(...skipping 16 matching lines...) Expand all
139 public: 271 public:
140 RemovableDeviceNotificationsWindowWinTest() 272 RemovableDeviceNotificationsWindowWinTest()
141 : ui_thread_(BrowserThread::UI, &message_loop_), 273 : ui_thread_(BrowserThread::UI, &message_loop_),
142 file_thread_(BrowserThread::FILE, &message_loop_) { } 274 file_thread_(BrowserThread::FILE, &message_loop_) { }
143 virtual ~RemovableDeviceNotificationsWindowWinTest() { } 275 virtual ~RemovableDeviceNotificationsWindowWinTest() { }
144 276
145 protected: 277 protected:
146 virtual void SetUp() OVERRIDE { 278 virtual void SetUp() OVERRIDE {
147 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); 279 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
148 volume_mount_watcher_ = new TestVolumeMountWatcherWin; 280 volume_mount_watcher_ = new TestVolumeMountWatcherWin;
281 portable_device_watcher_ = new TestPortableDeviceWatcherWin;
149 window_.reset(new TestRemovableDeviceNotificationsWindowWin( 282 window_.reset(new TestRemovableDeviceNotificationsWindowWin(
150 volume_mount_watcher_.get())); 283 volume_mount_watcher_.get(), portable_device_watcher_.get()));
151 window_->InitWithTestData(); 284 window_->InitWithTestData();
152 message_loop_.RunAllPending(); 285 RunAllPending();
153 system_monitor_.AddDevicesChangedObserver(&observer_); 286 system_monitor_.AddDevicesChangedObserver(&observer_);
154 } 287 }
155 288
156 virtual void TearDown() { 289 virtual void TearDown() {
157 message_loop_.RunAllPending(); 290 RunAllPending();
158 system_monitor_.RemoveDevicesChangedObserver(&observer_); 291 system_monitor_.RemoveDevicesChangedObserver(&observer_);
159 } 292 }
160 293
161 void AddAttachExpectation(FilePath drive) { 294 void AddAttachExpectation(FilePath drive) {
162 std::string unique_id; 295 std::string unique_id;
163 string16 device_name; 296 string16 device_name;
164 bool removable; 297 bool removable;
165 ASSERT_TRUE(GetDeviceDetails(drive, NULL, &unique_id, &device_name, 298 ASSERT_TRUE(GetMassStorageDeviceDetails(drive, NULL, &unique_id,
166 &removable)); 299 &device_name, &removable));
167 if (removable) { 300 if (removable) {
168 MediaStorageUtil::Type type = 301 MediaStorageUtil::Type type =
169 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM; 302 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM;
170 std::string device_id = MediaStorageUtil::MakeDeviceId(type, unique_id); 303 std::string device_id = MediaStorageUtil::MakeDeviceId(type, unique_id);
171 EXPECT_CALL(observer_, OnRemovableStorageAttached(device_id, device_name, 304 EXPECT_CALL(observer_, OnRemovableStorageAttached(device_id, device_name,
172 drive.value())) 305 drive.value()))
173 .Times(1); 306 .Times(1);
174 } 307 }
175 } 308 }
176 309
177 void PreAttachDevices() { 310 void PreAttachDevices() {
178 window_.reset(); 311 window_.reset();
179 { 312 {
180 testing::InSequence sequence; 313 testing::InSequence sequence;
181 std::vector<FilePath> initial_devices = GetTestAttachedDevices(); 314 std::vector<FilePath> initial_devices = GetTestAttachedDevices();
182 for (size_t i = 0; i < initial_devices.size(); i++) 315 for (size_t i = 0; i < initial_devices.size(); i++)
183 AddAttachExpectation(initial_devices[i]); 316 AddAttachExpectation(initial_devices[i]);
184 } 317 }
185 window_.reset(new TestRemovableDeviceNotificationsWindowWin( 318 window_.reset(new TestRemovableDeviceNotificationsWindowWin(
186 volume_mount_watcher_.get())); 319 volume_mount_watcher_.get(), portable_device_watcher_.get()));
187 window_->InitWithTestDataAndAttachedDevices(); 320 window_->InitWithTestDataAndAttachedDevices();
321 RunAllPending();
322 }
323
324 // Runs all the pending tasks on UI thread and blocking thread.
325 void RunAllPending() {
326 message_loop_.RunAllPending();
327 content::BrowserThread::GetBlockingPool()->FlushForTesting();
188 message_loop_.RunAllPending(); 328 message_loop_.RunAllPending();
189 } 329 }
190 330
191 void DoDevicesAttachedTest(const std::vector<int>& device_indices); 331 void DoMassStorageDeviceAttachedTest(const std::vector<int>& device_indices);
192 void DoDevicesDetachedTest(const std::vector<int>& device_indices); 332 void DoMassStorageDevicesDetachedTest(const std::vector<int>& device_indices);
333 void DoMtpDeviceAttachedTest(const string16& pnp_device_id);
334 void DoMtpDeviceDetachedTest(const string16& pnp_device_id);
193 335
194 MessageLoopForUI message_loop_; 336 MessageLoopForUI message_loop_;
195 content::TestBrowserThread ui_thread_; 337 content::TestBrowserThread ui_thread_;
196 content::TestBrowserThread file_thread_; 338 content::TestBrowserThread file_thread_;
197 339
198 base::SystemMonitor system_monitor_; 340 base::SystemMonitor system_monitor_;
199 base::MockDevicesChangedObserver observer_; 341 base::MockDevicesChangedObserver observer_;
200 scoped_ptr<TestRemovableDeviceNotificationsWindowWin> window_; 342 scoped_ptr<TestRemovableDeviceNotificationsWindowWin> window_;
201 scoped_refptr<TestVolumeMountWatcherWin> volume_mount_watcher_; 343 scoped_refptr<TestVolumeMountWatcherWin> volume_mount_watcher_;
344 scoped_refptr<TestPortableDeviceWatcherWin> portable_device_watcher_;
202 }; 345 };
203 346
204 void RemovableDeviceNotificationsWindowWinTest::DoDevicesAttachedTest( 347 void RemovableDeviceNotificationsWindowWinTest::
348 DoMassStorageDeviceAttachedTest(
205 const std::vector<int>& device_indices) { 349 const std::vector<int>& device_indices) {
206 DEV_BROADCAST_VOLUME volume_broadcast; 350 DEV_BROADCAST_VOLUME volume_broadcast;
207 volume_broadcast.dbcv_size = sizeof(volume_broadcast); 351 volume_broadcast.dbcv_size = sizeof(volume_broadcast);
208 volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME; 352 volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME;
209 volume_broadcast.dbcv_unitmask = 0x0; 353 volume_broadcast.dbcv_unitmask = 0x0;
210 volume_broadcast.dbcv_flags = 0x0; 354 volume_broadcast.dbcv_flags = 0x0;
211 { 355 {
212 testing::InSequence sequence; 356 testing::InSequence sequence;
213 for (std::vector<int>::const_iterator it = device_indices.begin(); 357 for (std::vector<int>::const_iterator it = device_indices.begin();
214 it != device_indices.end(); 358 it != device_indices.end();
215 ++it) { 359 ++it) {
216 volume_broadcast.dbcv_unitmask |= 0x1 << *it; 360 volume_broadcast.dbcv_unitmask |= 0x1 << *it;
217 AddAttachExpectation(DriveNumberToFilePath(*it)); 361 AddAttachExpectation(DriveNumberToFilePath(*it));
218 } 362 }
219 } 363 }
220 window_->InjectDeviceChange(DBT_DEVICEARRIVAL, 364 window_->InjectDeviceChange(DBT_DEVICEARRIVAL,
221 reinterpret_cast<DWORD>(&volume_broadcast)); 365 reinterpret_cast<DWORD>(&volume_broadcast));
222 message_loop_.RunAllPending(); 366 RunAllPending();
223 } 367 }
224 368
225 void RemovableDeviceNotificationsWindowWinTest::DoDevicesDetachedTest( 369 void RemovableDeviceNotificationsWindowWinTest::
370 DoMassStorageDevicesDetachedTest(
226 const std::vector<int>& device_indices) { 371 const std::vector<int>& device_indices) {
227 DEV_BROADCAST_VOLUME volume_broadcast; 372 DEV_BROADCAST_VOLUME volume_broadcast;
228 volume_broadcast.dbcv_size = sizeof(volume_broadcast); 373 volume_broadcast.dbcv_size = sizeof(volume_broadcast);
229 volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME; 374 volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME;
230 volume_broadcast.dbcv_unitmask = 0x0; 375 volume_broadcast.dbcv_unitmask = 0x0;
231 volume_broadcast.dbcv_flags = 0x0; 376 volume_broadcast.dbcv_flags = 0x0;
232 { 377 {
233 testing::InSequence sequence; 378 testing::InSequence sequence;
234 for (std::vector<int>::const_iterator it = device_indices.begin(); 379 for (std::vector<int>::const_iterator it = device_indices.begin();
235 it != device_indices.end(); 380 it != device_indices.end();
236 ++it) { 381 ++it) {
237 volume_broadcast.dbcv_unitmask |= 0x1 << *it; 382 volume_broadcast.dbcv_unitmask |= 0x1 << *it;
238 std::string unique_id; 383 std::string unique_id;
239 bool removable; 384 bool removable;
240 ASSERT_TRUE(GetDeviceDetails(DriveNumberToFilePath(*it), NULL, &unique_id, 385 ASSERT_TRUE(GetMassStorageDeviceDetails(DriveNumberToFilePath(*it), NULL,
241 NULL, &removable)); 386 &unique_id, NULL, &removable));
242 if (removable) { 387 if (removable) {
243 MediaStorageUtil::Type type = 388 MediaStorageUtil::Type type =
244 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM; 389 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM;
245 std::string device_id = MediaStorageUtil::MakeDeviceId(type, unique_id); 390 std::string device_id = MediaStorageUtil::MakeDeviceId(type, unique_id);
246 EXPECT_CALL(observer_, OnRemovableStorageDetached(device_id)).Times(1); 391 EXPECT_CALL(observer_, OnRemovableStorageDetached(device_id)).Times(1);
247 } 392 }
248 } 393 }
249 } 394 }
250 window_->InjectDeviceChange(DBT_DEVICEREMOVECOMPLETE, 395 window_->InjectDeviceChange(DBT_DEVICEREMOVECOMPLETE,
251 reinterpret_cast<DWORD>(&volume_broadcast)); 396 reinterpret_cast<DWORD>(&volume_broadcast));
252 message_loop_.RunAllPending(); 397 RunAllPending();
398 }
399
400 void RemovableDeviceNotificationsWindowWinTest::DoMtpDeviceAttachedTest(
401 const string16& pnp_device_id) {
402 GUID guidDevInterface = GUID_NULL;
403 HRESULT hr = CLSIDFromString(kWPDDevInterfaceGUID, &guidDevInterface);
404 if (FAILED(hr))
405 return;
406
407 size_t device_id_size = pnp_device_id.size() * sizeof(char16);
408 size_t dbcc_name_size = device_id_size + sizeof(char16);
Peter Kasting 2012/10/19 21:31:12 Nit: Inline into next statement (2 places)
kmadhusu 2012/10/23 23:44:17 I would like to leave this as it is. To me, this i
Peter Kasting 2012/10/24 00:06:32 Actually, now that I look closer, this statement i
409 size_t size = sizeof(DEV_BROADCAST_DEVICEINTERFACE) + dbcc_name_size;
410 scoped_ptr_malloc<DEV_BROADCAST_DEVICEINTERFACE> dev_interface_broadcast(
Peter Kasting 2012/10/19 21:31:12 Ugh, why are you using scoped_ptr_malloc<> and Zer
kmadhusu 2012/10/23 23:44:17 By default, DEV_BROADCAST_DEVICEINTERFACE dbcc_nam
Peter Kasting 2012/10/24 00:06:32 Yeah, you're fine. I didn't really realize this s
411 static_cast<DEV_BROADCAST_DEVICEINTERFACE*>(malloc(size)));
412 DCHECK(dev_interface_broadcast.get());
413 ZeroMemory(dev_interface_broadcast.get(), size);
414 dev_interface_broadcast->dbcc_size = size;
415 dev_interface_broadcast->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
416 dev_interface_broadcast->dbcc_classguid = guidDevInterface;
417 memcpy(dev_interface_broadcast->dbcc_name, pnp_device_id.data(),
418 device_id_size);
419 {
420 testing::InSequence sequence;
421 std::vector<string16> storages = GetMtpStorageObjectId(pnp_device_id);
422 for (size_t index = 0; index < storages.size(); ++index) {
423 std::string unique_id;
424 string16 name;
425 string16 location;
426 ASSERT_TRUE(GetMtpStorageDetails(pnp_device_id, storages[index],
427 &location, &unique_id, &name));
428 int cardinality = 1;
429 if (name.empty() || unique_id.empty())
430 cardinality = 0;
431 EXPECT_CALL(observer_, OnRemovableStorageAttached(unique_id, name,
432 location))
433 .Times(cardinality);
434 }
435 }
436 window_->InjectDeviceChange(
437 DBT_DEVICEARRIVAL,
438 reinterpret_cast<DWORD>(dev_interface_broadcast.get()));
439 RunAllPending();
440 }
441
442 void RemovableDeviceNotificationsWindowWinTest::DoMtpDeviceDetachedTest(
443 const string16& pnp_device_id) {
444 GUID guidDevInterface = GUID_NULL;
445 HRESULT hr = CLSIDFromString(kWPDDevInterfaceGUID, &guidDevInterface);
446 if (FAILED(hr))
447 return;
448
449 size_t device_id_size = pnp_device_id.size() * sizeof(char16);
450 size_t dbcc_name_size = device_id_size + sizeof(char16);
451 size_t size = sizeof(DEV_BROADCAST_DEVICEINTERFACE) + dbcc_name_size;
452 scoped_ptr_malloc<DEV_BROADCAST_DEVICEINTERFACE> dev_interface_broadcast(
453 static_cast<DEV_BROADCAST_DEVICEINTERFACE*>(malloc(size)));
454 DCHECK(dev_interface_broadcast.get());
455 ZeroMemory(dev_interface_broadcast.get(), size);
456 dev_interface_broadcast->dbcc_size = size;
457 dev_interface_broadcast->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
458 dev_interface_broadcast->dbcc_classguid = guidDevInterface;
459 memcpy(dev_interface_broadcast->dbcc_name, pnp_device_id.data(),
460 device_id_size);
461 {
462 testing::InSequence sequence;
463 std::vector<string16> storages = GetMtpStorageObjectId(pnp_device_id);
464 for (size_t index = 0; index < storages.size(); ++index) {
465 std::string unique_id;
466 string16 name;
467 ASSERT_TRUE(GetMtpStorageDetails(pnp_device_id, storages[index], NULL,
468 &unique_id, &name));
469 int cardinality = 1;
470 if (name.empty() || unique_id.empty())
471 cardinality = 0;
472 EXPECT_CALL(observer_, OnRemovableStorageDetached(unique_id))
473 .Times(cardinality);
474 }
475 }
476 window_->InjectDeviceChange(
477 DBT_DEVICEREMOVECOMPLETE,
478 reinterpret_cast<DWORD>(dev_interface_broadcast.get()));
479 RunAllPending();
253 } 480 }
254 481
255 TEST_F(RemovableDeviceNotificationsWindowWinTest, RandomMessage) { 482 TEST_F(RemovableDeviceNotificationsWindowWinTest, RandomMessage) {
256 window_->InjectDeviceChange(DBT_DEVICEQUERYREMOVE, NULL); 483 window_->InjectDeviceChange(DBT_DEVICEQUERYREMOVE, NULL);
257 message_loop_.RunAllPending(); 484 RunAllPending();
258 } 485 }
259 486
260 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttached) { 487 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttached) {
261 std::vector<int> device_indices; 488 std::vector<int> device_indices;
262 device_indices.push_back(1); 489 device_indices.push_back(1);
263 device_indices.push_back(5); 490 device_indices.push_back(5);
264 device_indices.push_back(7); 491 device_indices.push_back(7);
265 device_indices.push_back(13); 492 device_indices.push_back(13);
266 493
267 DoDevicesAttachedTest(device_indices); 494 DoMassStorageDeviceAttachedTest(device_indices);
268 } 495 }
269 496
270 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedHighBoundary) { 497 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedHighBoundary) {
271 std::vector<int> device_indices; 498 std::vector<int> device_indices;
272 device_indices.push_back(25); 499 device_indices.push_back(25);
273 500
274 DoDevicesAttachedTest(device_indices); 501 DoMassStorageDeviceAttachedTest(device_indices);
275 } 502 }
276 503
277 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedLowBoundary) { 504 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedLowBoundary) {
278 std::vector<int> device_indices; 505 std::vector<int> device_indices;
279 device_indices.push_back(0); 506 device_indices.push_back(0);
280 507
281 DoDevicesAttachedTest(device_indices); 508 DoMassStorageDeviceAttachedTest(device_indices);
282 } 509 }
283 510
284 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedAdjacentBits) { 511 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedAdjacentBits) {
285 std::vector<int> device_indices; 512 std::vector<int> device_indices;
286 device_indices.push_back(0); 513 device_indices.push_back(0);
287 device_indices.push_back(1); 514 device_indices.push_back(1);
288 device_indices.push_back(2); 515 device_indices.push_back(2);
289 device_indices.push_back(3); 516 device_indices.push_back(3);
290 517
291 DoDevicesAttachedTest(device_indices); 518 DoMassStorageDeviceAttachedTest(device_indices);
292 } 519 }
293 520
294 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetached) { 521 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetached) {
295 PreAttachDevices(); 522 PreAttachDevices();
296 523
297 std::vector<int> device_indices; 524 std::vector<int> device_indices;
298 device_indices.push_back(1); 525 device_indices.push_back(1);
299 device_indices.push_back(5); 526 device_indices.push_back(5);
300 device_indices.push_back(7); 527 device_indices.push_back(7);
301 device_indices.push_back(13); 528 device_indices.push_back(13);
302 529
303 DoDevicesDetachedTest(device_indices); 530 DoMassStorageDevicesDetachedTest(device_indices);
304 } 531 }
305 532
306 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetachedHighBoundary) { 533 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetachedHighBoundary) {
307 PreAttachDevices(); 534 PreAttachDevices();
308 535
309 std::vector<int> device_indices; 536 std::vector<int> device_indices;
310 device_indices.push_back(25); 537 device_indices.push_back(25);
311 538
312 DoDevicesDetachedTest(device_indices); 539 DoMassStorageDevicesDetachedTest(device_indices);
313 } 540 }
314 541
315 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetachedLowBoundary) { 542 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetachedLowBoundary) {
316 PreAttachDevices(); 543 PreAttachDevices();
317 544
318 std::vector<int> device_indices; 545 std::vector<int> device_indices;
319 device_indices.push_back(0); 546 device_indices.push_back(0);
320 547
321 DoDevicesDetachedTest(device_indices); 548 DoMassStorageDevicesDetachedTest(device_indices);
322 } 549 }
323 550
324 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetachedAdjacentBits) { 551 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetachedAdjacentBits) {
325 PreAttachDevices(); 552 PreAttachDevices();
326 553
327 std::vector<int> device_indices; 554 std::vector<int> device_indices;
328 device_indices.push_back(0); 555 device_indices.push_back(0);
329 device_indices.push_back(1); 556 device_indices.push_back(1);
330 device_indices.push_back(2); 557 device_indices.push_back(2);
331 device_indices.push_back(3); 558 device_indices.push_back(3);
332 559
333 DoDevicesDetachedTest(device_indices); 560 DoMassStorageDevicesDetachedTest(device_indices);
334 } 561 }
335 562
336 TEST_F(RemovableDeviceNotificationsWindowWinTest, DeviceInfoFoPath) { 563 TEST_F(RemovableDeviceNotificationsWindowWinTest, DeviceInfoFoPath) {
337 PreAttachDevices(); 564 PreAttachDevices();
338 565
339 // An invalid path. 566 // An invalid path.
340 EXPECT_FALSE(window_->GetDeviceInfoForPath(FilePath(L"COM1:\\"), NULL)); 567 EXPECT_FALSE(window_->GetDeviceInfoForPath(FilePath(L"COM1:\\"), NULL));
341 568
342 // An unconnected removable device. 569 // An unconnected removable device.
343 EXPECT_FALSE(window_->GetDeviceInfoForPath(FilePath(L"E:\\"), NULL)); 570 EXPECT_FALSE(window_->GetDeviceInfoForPath(FilePath(L"E:\\"), NULL));
344 571
345 // A connected removable device. 572 // A connected removable device.
346 FilePath removable_device(L"F:\\"); 573 FilePath removable_device(L"F:\\");
347 base::SystemMonitor::RemovableStorageInfo device_info; 574 base::SystemMonitor::RemovableStorageInfo device_info;
348 EXPECT_TRUE(window_->GetDeviceInfoForPath(removable_device, &device_info)); 575 EXPECT_TRUE(window_->GetDeviceInfoForPath(removable_device, &device_info));
349 576
350 std::string unique_id; 577 std::string unique_id;
351 string16 device_name; 578 string16 device_name;
352 bool removable; 579 bool removable;
353 ASSERT_TRUE(GetDeviceDetails(removable_device, NULL, &unique_id, &device_name, 580 ASSERT_TRUE(GetMassStorageDeviceDetails(removable_device, NULL, &unique_id,
354 &removable)); 581 &device_name, &removable));
355 EXPECT_TRUE(removable); 582 EXPECT_TRUE(removable);
356 std::string device_id = MediaStorageUtil::MakeDeviceId( 583 std::string device_id = MediaStorageUtil::MakeDeviceId(
357 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM, unique_id); 584 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM, unique_id);
358 EXPECT_EQ(device_id, device_info.device_id); 585 EXPECT_EQ(device_id, device_info.device_id);
359 EXPECT_EQ(device_name, device_info.name); 586 EXPECT_EQ(device_name, device_info.name);
360 EXPECT_EQ(removable_device.value(), device_info.location); 587 EXPECT_EQ(removable_device.value(), device_info.location);
361 588
362 // A fixed device. 589 // A fixed device.
363 FilePath fixed_device(L"N:\\"); 590 FilePath fixed_device(L"N:\\");
364 EXPECT_TRUE(window_->GetDeviceInfoForPath(fixed_device, &device_info)); 591 EXPECT_TRUE(window_->GetDeviceInfoForPath(fixed_device, &device_info));
365 592
366 ASSERT_TRUE(GetDeviceDetails(fixed_device, NULL, &unique_id, &device_name, 593 ASSERT_TRUE(GetMassStorageDeviceDetails(fixed_device, NULL, &unique_id,
367 &removable)); 594 &device_name, &removable));
368 EXPECT_FALSE(removable); 595 EXPECT_FALSE(removable);
369 device_id = MediaStorageUtil::MakeDeviceId( 596 device_id = MediaStorageUtil::MakeDeviceId(
370 MediaStorageUtil::FIXED_MASS_STORAGE, unique_id); 597 MediaStorageUtil::FIXED_MASS_STORAGE, unique_id);
371 EXPECT_EQ(device_id, device_info.device_id); 598 EXPECT_EQ(device_id, device_info.device_id);
372 EXPECT_EQ(device_name, device_info.name); 599 EXPECT_EQ(device_name, device_info.name);
373 EXPECT_EQ(fixed_device.value(), device_info.location); 600 EXPECT_EQ(fixed_device.value(), device_info.location);
374 } 601 }
375 602
603 // Test to verify basic mtp storage attach and detach notifications.
604 TEST_F(RemovableDeviceNotificationsWindowWinTest, MtpDeviceBasicAttachDetach) {
605 // Attach a mtp device.
606 DoMtpDeviceAttachedTest(kMtpDeviceWithValidInfo);
607
608 // Detach the attached device.
609 DoMtpDeviceDetachedTest(kMtpDeviceWithValidInfo);
610 }
611
612 // When a mtp storage device with invalid storage label and id is
613 // attached/detached, there should not be any device attach/detach
614 // notifications.
615 TEST_F(RemovableDeviceNotificationsWindowWinTest, MtpDeviceWithInvalidInfo) {
616 // Attach the mtp storage with invalid storage info.
617 DoMtpDeviceAttachedTest(kMtpDeviceWithInvalidInfo);
618
619 // Detach the attached storage.
620 DoMtpDeviceDetachedTest(kMtpDeviceWithInvalidInfo);
621 }
622
623 // Attach a device with two data storages. Verify that attach/detach
624 // notifications are sent out for each removable storage.
625 TEST_F(RemovableDeviceNotificationsWindowWinTest,
626 MtpDeviceWithMultipleStorages) {
627 // Attach the mtp device with multiple storage.
628 DoMtpDeviceAttachedTest(kMtpDeviceWithMultipleStorage);
629
630 // Detach the attached device.
631 DoMtpDeviceDetachedTest(kMtpDeviceWithMultipleStorage);
632 }
633
376 } // namespace chrome 634 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698