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

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

Powered by Google App Engine
This is Rietveld 408576698