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

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
30 typedef std::vector<FilePath> AttachedDevices;
31
24 namespace { 32 namespace {
25 33
26 using content::BrowserThread; 34 using content::BrowserThread;
27 using chrome::RemovableDeviceNotificationsWindowWin; 35
36 // Mtp device interface path constants.
37 const char16 kMtpDeviceWithInvalidInfo[] =
38 L"\\?\usb#vid_00&pid_00#0&2&1#{0000-0000-0000-0000-0000})";
39 const char16 kMtpDeviceWithValidInfo[] =
40 L"\\?\usb#vid_ff&pid_000f#32&2&1#{abcd-1234-ffde-1112-9172})";
41 const char16 kMtpDeviceWithMultipleStorageObjects[] =
42 L"\\?\usb#vid_ff&pid_18#32&2&1#{ab33-1de4-f22e-1882-9724})";
43
44 // Sample mtp device storage information.
45 const char16 kMtpDeviceFriendlyName[] = L"Camera V1.1";
46 const char16 kStorageLabelA[] = L"Camera V1.1 (s10001)";
47 const char16 kStorageLabelB[] = L"Camera V1.1 (s20001)";
48 const char16 kStorageObjectIdA[] = L"s10001";
49 const char16 kStorageObjectIdB[] = L"s20001";
50 const char kStorageUniqueIdA[] =
51 "mtp:StorageSerial:SID-{s10001, D, 12378}:123123";
52 const char kStorageUniqueIdB[] =
53 "mtp:StorageSerial:SID-{s20001, S, 2238}:123123";
28 54
29 // Inputs of 'A:\' - 'Z:\' are valid. 'N:\' is not removable. 55 // Inputs of 'A:\' - 'Z:\' are valid. 'N:\' is not removable.
30 bool GetDeviceDetails(const FilePath& device_path, string16* device_location, 56 bool GetMassStorageDeviceDetails(const FilePath& device_path,
31 std::string* unique_id, string16* name, bool* removable) { 57 string16* device_location,
58 std::string* unique_id,
59 string16* name,
60 bool* removable) {
32 if (device_path.value().length() != 3 || device_path.value()[0] < L'A' || 61 if (device_path.value().length() != 3 || device_path.value()[0] < L'A' ||
33 device_path.value()[0] > L'Z') { 62 device_path.value()[0] > L'Z') {
34 return false; 63 return false;
35 } 64 }
36 65
37 if (device_location) 66 if (device_location)
38 *device_location = device_path.value(); 67 *device_location = device_path.value();
39 if (unique_id) { 68 if (unique_id) {
40 *unique_id = "\\\\?\\Volume{00000000-0000-0000-0000-000000000000}\\"; 69 *unique_id = "\\\\?\\Volume{00000000-0000-0000-0000-000000000000}\\";
41 (*unique_id)[11] = device_path.value()[0]; 70 (*unique_id)[11] = device_path.value()[0];
42 } 71 }
43 if (name) 72 if (name)
44 *name = device_path.Append(L" Drive").LossyDisplayName(); 73 *name = device_path.Append(L" Drive").LossyDisplayName();
45 if (removable) 74 if (removable)
46 *removable = device_path.value()[0] != L'N'; 75 *removable = device_path.value()[0] != L'N';
47 return true; 76 return true;
48 } 77 }
49 78
50 FilePath DriveNumberToFilePath(int drive_number) { 79 FilePath DriveNumberToFilePath(int drive_number) {
51 FilePath::StringType path(L"_:\\"); 80 FilePath::StringType path(L"_:\\");
52 path[0] = L'A' + drive_number; 81 path[0] = L'A' + drive_number;
53 return FilePath(path); 82 return FilePath(path);
54 } 83 }
55 84
56 std::vector<FilePath> GetTestAttachedDevices() { 85 AttachedDevices GetTestAttachedDevices() {
57 std::vector<FilePath> result; 86 AttachedDevices result;
58 result.push_back(DriveNumberToFilePath(0)); 87 result.push_back(DriveNumberToFilePath(0));
59 result.push_back(DriveNumberToFilePath(1)); 88 result.push_back(DriveNumberToFilePath(1));
60 result.push_back(DriveNumberToFilePath(2)); 89 result.push_back(DriveNumberToFilePath(2));
61 result.push_back(DriveNumberToFilePath(3)); 90 result.push_back(DriveNumberToFilePath(3));
62 result.push_back(DriveNumberToFilePath(5)); 91 result.push_back(DriveNumberToFilePath(5));
63 result.push_back(DriveNumberToFilePath(7)); 92 result.push_back(DriveNumberToFilePath(7));
64 result.push_back(DriveNumberToFilePath(25)); 93 result.push_back(DriveNumberToFilePath(25));
65 return result; 94 return result;
66 } 95 }
67 96
97 // Returns the persistent storage unique id of the device specified by the
98 // |pnp_device_id|. |storage_object_id| specifies the temporary object
99 // identifier that uniquely identifies the object on the device.
100 std::string GetMtpStorageUniqueId(const string16& pnp_device_id,
101 const string16& storage_object_id) {
102 if (storage_object_id == kStorageObjectIdA)
103 return kStorageUniqueIdA;
104 return (storage_object_id == kStorageObjectIdB) ?
105 kStorageUniqueIdB : std::string();
Peter Kasting 2012/10/29 21:57:19 Nit: Indent 4 (2 places)
kmadhusu 2012/10/30 01:29:24 Done.
106 }
107
108 // Returns the storage name of the device specified by |pnp_device_id|.
109 // |storage_object_id| specifies the temporary object identifier that
110 // uniquely identifies the object on the device.
111 string16 GetMtpStorageName(const string16& pnp_device_id,
112 const string16& storage_object_id) {
113 if (pnp_device_id == kMtpDeviceWithInvalidInfo)
114 return string16();
115
116 if (storage_object_id == kStorageObjectIdA)
117 return kStorageLabelA;
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 PortableDeviceWatcherWin::StorageObjectIDs GetMtpStorageObjectIds(
125 const string16& pnp_device_id) {
126 PortableDeviceWatcherWin::StorageObjectIDs storage_object_ids;
127 storage_object_ids.push_back(kStorageObjectIdA);
128 if (pnp_device_id == kMtpDeviceWithMultipleStorageObjects)
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 *device_location = UTF8ToUTF16("\\\\" + storage_unique_id);
146
147 if (unique_id)
148 *unique_id = storage_unique_id;
149
150 if (name)
151 *name = GetMtpStorageName(pnp_device_id, storage_object_id);
152 }
153
154 // Returns a list of device storage details for the given device specified by
155 // |pnp_device_id|.
156 PortableDeviceWatcherWin::StorageObjects GetDeviceStorageObjects(
157 const string16& pnp_device_id) {
158 PortableDeviceWatcherWin::StorageObjects storage_objects;
159 PortableDeviceWatcherWin::StorageObjectIDs storage_object_ids =
160 GetMtpStorageObjectIds(pnp_device_id);
161 for (PortableDeviceWatcherWin::StorageObjectIDs::const_iterator it =
162 storage_object_ids.begin();
Peter Kasting 2012/10/29 21:57:19 Nit: Indent 1 more (for loop indenting is weird)
kmadhusu 2012/10/30 01:29:24 Fixed. Moved the iterator declaration outside the
Peter Kasting 2012/10/30 23:17:52 No, do not do that. Never declare loop variables
kmadhusu 2012/10/30 23:49:50 Fixed.
163 it != storage_object_ids.end(); ++it) {
164 storage_objects.push_back(PortableDeviceWatcherWin::DeviceStorageObject(
165 *it, GetMtpStorageUniqueId(pnp_device_id, *it)));
166 }
167 return storage_objects;
168 }
169
68 } // namespace 170 } // namespace
69 171
70 namespace chrome { 172 // TestPortableDeviceWatcherWin -----------------------------------------------
Peter Kasting 2012/10/29 21:57:19 Nit: Consider a blank line above these dividers (4
kmadhusu 2012/10/30 01:29:24 Done.
71 173
72 // Wrapper class for testing VolumeMountWatcherWin. 174 class TestPortableDeviceWatcherWin : public PortableDeviceWatcherWin {
175 public:
176 TestPortableDeviceWatcherWin();
177 virtual ~TestPortableDeviceWatcherWin();
178
179 private:
180 // Override PortableDeviceWatcherWin:
Peter Kasting 2012/10/29 21:57:19 Nit: Remove "override" (2 places)
kmadhusu 2012/10/30 01:29:24 Done.
181 virtual void EnumerateAttachedDevices() OVERRIDE;
182 virtual void HandleDeviceAttachEvent(const string16& pnp_device_id) OVERRIDE;
183
184 DISALLOW_COPY_AND_ASSIGN(TestPortableDeviceWatcherWin);
185 };
186
187 TestPortableDeviceWatcherWin::TestPortableDeviceWatcherWin() {
188 }
189
190 TestPortableDeviceWatcherWin::~TestPortableDeviceWatcherWin() {
191 }
192
193 void TestPortableDeviceWatcherWin::EnumerateAttachedDevices() {
194 }
195
196 void TestPortableDeviceWatcherWin::HandleDeviceAttachEvent(
197 const string16& pnp_device_id) {
198 DeviceDetails device_details = {
199 (pnp_device_id != kMtpDeviceWithInvalidInfo) ? kMtpDeviceFriendlyName :
Peter Kasting 2012/10/29 21:57:19 Nit: Break after ?, not : (2 places)
kmadhusu 2012/10/30 01:29:24 Done.
200 string16(),
201 pnp_device_id,
202 GetDeviceStorageObjects(pnp_device_id)
203 };
204 bool result(true);
Peter Kasting 2012/10/29 21:57:19 Nit: Don't use constructor-style initialization fo
kmadhusu 2012/10/30 01:29:24 Done.
205 OnDidHandleDeviceAttachEvent(&device_details, &result);
206 }
207
208 // TestVolumeMountWatcherWin --------------------------------------------------
209
73 class TestVolumeMountWatcherWin : public VolumeMountWatcherWin { 210 class TestVolumeMountWatcherWin : public VolumeMountWatcherWin {
74 public: 211 public:
75 TestVolumeMountWatcherWin() : pre_attach_devices_(false) { 212 TestVolumeMountWatcherWin();
76 }
77
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 213
93 void set_pre_attach_devices(bool pre_attach_devices) { 214 void set_pre_attach_devices(bool pre_attach_devices) {
94 pre_attach_devices_ = pre_attach_devices; 215 pre_attach_devices_ = pre_attach_devices;
95 } 216 }
96 217
97 private: 218 private:
98 // Private, this class is ref-counted. 219 // Private, this class is ref-counted.
99 virtual ~TestVolumeMountWatcherWin() { 220 virtual ~TestVolumeMountWatcherWin();
100 } 221
222 // Override VolumeMountWatcherWin:
223 virtual bool GetDeviceInfo(const FilePath& device_path,
224 string16* device_location,
225 std::string* unique_id,
226 string16* name,
227 bool* removable) OVERRIDE;
228 virtual AttachedDevices GetAttachedDevices() OVERRIDE;
101 229
102 // Set to true to pre-attach test devices. 230 // Set to true to pre-attach test devices.
103 bool pre_attach_devices_; 231 bool pre_attach_devices_;
232
233 DISALLOW_COPY_AND_ASSIGN(TestVolumeMountWatcherWin);
104 }; 234 };
105 235
106 // Wrapper class for testing RemovableDeviceNotificationsWindowWin. 236 TestVolumeMountWatcherWin::TestVolumeMountWatcherWin()
237 : pre_attach_devices_(false) {
238 }
239
240 TestVolumeMountWatcherWin::~TestVolumeMountWatcherWin() {
241 }
242
243 bool TestVolumeMountWatcherWin::GetDeviceInfo(const FilePath& device_path,
244 string16* device_location,
245 std::string* unique_id,
246 string16* name,
247 bool* removable) {
248 return GetMassStorageDeviceDetails(device_path, device_location, unique_id,
249 name, removable);
250 }
251
252 AttachedDevices TestVolumeMountWatcherWin::GetAttachedDevices() {
253 return pre_attach_devices_ ? GetTestAttachedDevices() :
254 std::vector<FilePath>();
Peter Kasting 2012/10/29 21:57:19 Nit: AttachedDevices()
kmadhusu 2012/10/30 01:29:24 Done.
255 }
256
257 // TestRemovableDeviceNotificationsWindowWin ------------
Peter Kasting 2012/10/29 21:57:19 Nit: More dashes
kmadhusu 2012/10/30 01:29:24 Done.
258
107 class TestRemovableDeviceNotificationsWindowWin 259 class TestRemovableDeviceNotificationsWindowWin
108 : public RemovableDeviceNotificationsWindowWin { 260 : public RemovableDeviceNotificationsWindowWin {
109 public: 261 public:
110 explicit TestRemovableDeviceNotificationsWindowWin( 262 TestRemovableDeviceNotificationsWindowWin(
111 TestVolumeMountWatcherWin* volume_mount_watcher) 263 TestVolumeMountWatcherWin* volume_mount_watcher,
112 : RemovableDeviceNotificationsWindowWin(volume_mount_watcher), 264 TestPortableDeviceWatcherWin* portable_device_watcher);
113 volume_mount_watcher_(volume_mount_watcher) {
114 DCHECK(volume_mount_watcher_);
115 }
116 265
117 virtual ~TestRemovableDeviceNotificationsWindowWin() { 266 virtual ~TestRemovableDeviceNotificationsWindowWin();
118 }
119 267
120 void InitWithTestData() { 268 void InitWithTestData(bool pre_attach_devices);
121 volume_mount_watcher_->set_pre_attach_devices(false); 269 void InjectDeviceChange(UINT event_type, DWORD data);
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 270
134 private: 271 private:
135 scoped_refptr<TestVolumeMountWatcherWin> volume_mount_watcher_; 272 scoped_refptr<TestVolumeMountWatcherWin> volume_mount_watcher_;
136 }; 273 };
137 274
275 TestRemovableDeviceNotificationsWindowWin::
276 TestRemovableDeviceNotificationsWindowWin(
277 TestVolumeMountWatcherWin* volume_mount_watcher,
278 TestPortableDeviceWatcherWin* portable_device_watcher)
279 : RemovableDeviceNotificationsWindowWin(volume_mount_watcher,
280 portable_device_watcher),
281 volume_mount_watcher_(volume_mount_watcher) {
282 DCHECK(volume_mount_watcher_);
283 }
284
285 TestRemovableDeviceNotificationsWindowWin::
286 ~TestRemovableDeviceNotificationsWindowWin() {
287 }
288
289 void TestRemovableDeviceNotificationsWindowWin::InitWithTestData(
290 bool pre_attach_devices) {
291 volume_mount_watcher_->set_pre_attach_devices(pre_attach_devices);
292 Init();
293 }
294
295 void TestRemovableDeviceNotificationsWindowWin::InjectDeviceChange(
296 UINT event_type, DWORD data) {
Peter Kasting 2012/10/29 21:57:19 Nit: One arg per line
kmadhusu 2012/10/30 01:29:24 Done.
297 OnDeviceChange(event_type, data);
298 }
299
300 // RemovableDeviceNotificationsWindowWinTest ----------------------------------
301
138 class RemovableDeviceNotificationsWindowWinTest : public testing::Test { 302 class RemovableDeviceNotificationsWindowWinTest : public testing::Test {
139 public: 303 public:
140 RemovableDeviceNotificationsWindowWinTest() 304 RemovableDeviceNotificationsWindowWinTest();
141 : ui_thread_(BrowserThread::UI, &message_loop_), 305 virtual ~RemovableDeviceNotificationsWindowWinTest();
142 file_thread_(BrowserThread::FILE, &message_loop_) { }
143 virtual ~RemovableDeviceNotificationsWindowWinTest() { }
144 306
145 protected: 307 protected:
146 virtual void SetUp() OVERRIDE { 308 // testing::Test:
147 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); 309 virtual void SetUp() OVERRIDE;
148 volume_mount_watcher_ = new TestVolumeMountWatcherWin; 310 virtual void TearDown() OVERRIDE;
149 window_.reset(new TestRemovableDeviceNotificationsWindowWin(
150 volume_mount_watcher_.get()));
151 window_->InitWithTestData();
152 message_loop_.RunAllPending();
153 system_monitor_.AddDevicesChangedObserver(&observer_);
154 }
155 311
156 virtual void TearDown() { 312 void AddMassStorageDeviceAttachExpectation(FilePath drive);
157 message_loop_.RunAllPending(); 313 void PreAttachDevices();
158 system_monitor_.RemoveDevicesChangedObserver(&observer_);
159 }
160 314
161 void AddAttachExpectation(FilePath drive) { 315 // Runs all the pending tasks on UI thread, FILE thread and blocking thread.
162 std::string unique_id; 316 void RunAllPending();
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 317
177 void PreAttachDevices() { 318 void DoMassStorageDeviceAttachedTest(const std::vector<int>& device_indices);
Peter Kasting 2012/10/29 21:57:19 Nit: Consider a vector<int> typedef
kmadhusu 2012/10/30 01:29:24 Done. typedef std::vector<int> DeviceIndices;
178 window_.reset(); 319 void DoMassStorageDevicesDetachedTest(const std::vector<int>& device_indices);
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 320
191 void DoDevicesAttachedTest(const std::vector<int>& device_indices); 321 // Helper function to test media transfer protocol device attach and detach
192 void DoDevicesDetachedTest(const std::vector<int>& device_indices); 322 // events. Set |attached| to true, to test device attach event else set to
323 // false.
Peter Kasting 2012/10/29 21:57:19 Nit: How about: Injects a device attach or detach
kmadhusu 2012/10/30 01:29:24 Done.
324 void DoMtpDeviceTest(const string16& pnp_device_id, bool attached);
Peter Kasting 2012/10/29 21:57:19 Nit: Consider renaming |attached| to |test_attach|
kmadhusu 2012/10/30 01:29:24 Done.
193 325
194 MessageLoopForUI message_loop_; 326 MessageLoopForUI message_loop_;
195 content::TestBrowserThread ui_thread_; 327 content::TestBrowserThread ui_thread_;
196 content::TestBrowserThread file_thread_; 328 content::TestBrowserThread file_thread_;
197 329
198 base::SystemMonitor system_monitor_; 330 base::SystemMonitor system_monitor_;
199 base::MockDevicesChangedObserver observer_; 331 base::MockDevicesChangedObserver observer_;
200 scoped_ptr<TestRemovableDeviceNotificationsWindowWin> window_; 332 scoped_ptr<TestRemovableDeviceNotificationsWindowWin> window_;
201 scoped_refptr<TestVolumeMountWatcherWin> volume_mount_watcher_; 333 scoped_refptr<TestVolumeMountWatcherWin> volume_mount_watcher_;
202 }; 334 };
203 335
204 void RemovableDeviceNotificationsWindowWinTest::DoDevicesAttachedTest( 336 RemovableDeviceNotificationsWindowWinTest::
205 const std::vector<int>& device_indices) { 337 RemovableDeviceNotificationsWindowWinTest()
338 : ui_thread_(BrowserThread::UI, &message_loop_),
339 file_thread_(BrowserThread::FILE, &message_loop_) {
340 }
341
342 RemovableDeviceNotificationsWindowWinTest::
343 ~RemovableDeviceNotificationsWindowWinTest() {
344 }
345
346 void RemovableDeviceNotificationsWindowWinTest::SetUp() {
347 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
348 volume_mount_watcher_ = new TestVolumeMountWatcherWin;
349 window_.reset(new TestRemovableDeviceNotificationsWindowWin(
350 volume_mount_watcher_.get(), new TestPortableDeviceWatcherWin));
351 window_->InitWithTestData(false);
352 RunAllPending();
353 system_monitor_.AddDevicesChangedObserver(&observer_);
354 }
355
356 void RemovableDeviceNotificationsWindowWinTest::TearDown() {
357 RunAllPending();
358 system_monitor_.RemoveDevicesChangedObserver(&observer_);
359 }
360
361 void RemovableDeviceNotificationsWindowWinTest::
362 AddMassStorageDeviceAttachExpectation(FilePath drive) {
363 std::string unique_id;
364 string16 device_name;
365 bool removable;
366 ASSERT_TRUE(GetMassStorageDeviceDetails(drive, NULL, &unique_id,
367 &device_name, &removable));
368 if (removable) {
369 MediaStorageUtil::Type type =
370 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM;
371 std::string device_id = MediaStorageUtil::MakeDeviceId(type, unique_id);
372 EXPECT_CALL(observer_, OnRemovableStorageAttached(device_id, device_name,
373 drive.value()))
374 .Times(1);
375 }
376 }
377
378 void RemovableDeviceNotificationsWindowWinTest::PreAttachDevices() {
379 window_.reset();
380 {
381 testing::InSequence sequence;
382 AttachedDevices initial_devices = GetTestAttachedDevices();
383 for (AttachedDevices::const_iterator it = initial_devices.begin();
384 it != initial_devices.end(); ++it) {
385 AddMassStorageDeviceAttachExpectation(*it);
386 }
387 }
388 window_.reset(new TestRemovableDeviceNotificationsWindowWin(
389 volume_mount_watcher_.get(), new TestPortableDeviceWatcherWin));
390 window_->InitWithTestData(true);
391 RunAllPending();
392 }
393
394 void RemovableDeviceNotificationsWindowWinTest::RunAllPending() {
395 message_loop_.RunAllPending();
396 }
397
398 void RemovableDeviceNotificationsWindowWinTest::
399 DoMassStorageDeviceAttachedTest(const std::vector<int>& device_indices) {
206 DEV_BROADCAST_VOLUME volume_broadcast; 400 DEV_BROADCAST_VOLUME volume_broadcast;
207 volume_broadcast.dbcv_size = sizeof(volume_broadcast); 401 volume_broadcast.dbcv_size = sizeof(volume_broadcast);
208 volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME; 402 volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME;
209 volume_broadcast.dbcv_unitmask = 0x0; 403 volume_broadcast.dbcv_unitmask = 0x0;
210 volume_broadcast.dbcv_flags = 0x0; 404 volume_broadcast.dbcv_flags = 0x0;
211 { 405 {
212 testing::InSequence sequence; 406 testing::InSequence sequence;
213 for (std::vector<int>::const_iterator it = device_indices.begin(); 407 for (std::vector<int>::const_iterator it = device_indices.begin();
214 it != device_indices.end(); 408 it != device_indices.end();
215 ++it) { 409 ++it) {
216 volume_broadcast.dbcv_unitmask |= 0x1 << *it; 410 volume_broadcast.dbcv_unitmask |= 0x1 << *it;
217 AddAttachExpectation(DriveNumberToFilePath(*it)); 411 AddMassStorageDeviceAttachExpectation(DriveNumberToFilePath(*it));
218 } 412 }
219 } 413 }
220 window_->InjectDeviceChange(DBT_DEVICEARRIVAL, 414 window_->InjectDeviceChange(DBT_DEVICEARRIVAL,
221 reinterpret_cast<DWORD>(&volume_broadcast)); 415 reinterpret_cast<DWORD>(&volume_broadcast));
222 message_loop_.RunAllPending(); 416 RunAllPending();
223 } 417 }
224 418
225 void RemovableDeviceNotificationsWindowWinTest::DoDevicesDetachedTest( 419 void RemovableDeviceNotificationsWindowWinTest::
226 const std::vector<int>& device_indices) { 420 DoMassStorageDevicesDetachedTest(const std::vector<int>& device_indices) {
227 DEV_BROADCAST_VOLUME volume_broadcast; 421 DEV_BROADCAST_VOLUME volume_broadcast;
228 volume_broadcast.dbcv_size = sizeof(volume_broadcast); 422 volume_broadcast.dbcv_size = sizeof(volume_broadcast);
229 volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME; 423 volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME;
230 volume_broadcast.dbcv_unitmask = 0x0; 424 volume_broadcast.dbcv_unitmask = 0x0;
231 volume_broadcast.dbcv_flags = 0x0; 425 volume_broadcast.dbcv_flags = 0x0;
232 { 426 {
233 testing::InSequence sequence; 427 testing::InSequence sequence;
234 for (std::vector<int>::const_iterator it = device_indices.begin(); 428 for (std::vector<int>::const_iterator it = device_indices.begin();
235 it != device_indices.end(); 429 it != device_indices.end();
236 ++it) { 430 ++it) {
237 volume_broadcast.dbcv_unitmask |= 0x1 << *it; 431 volume_broadcast.dbcv_unitmask |= 0x1 << *it;
238 std::string unique_id; 432 std::string unique_id;
239 bool removable; 433 bool removable;
240 ASSERT_TRUE(GetDeviceDetails(DriveNumberToFilePath(*it), NULL, &unique_id, 434 ASSERT_TRUE(GetMassStorageDeviceDetails(DriveNumberToFilePath(*it), NULL,
241 NULL, &removable)); 435 &unique_id, NULL, &removable));
242 if (removable) { 436 if (removable) {
243 MediaStorageUtil::Type type = 437 MediaStorageUtil::Type type =
244 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM; 438 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM;
245 std::string device_id = MediaStorageUtil::MakeDeviceId(type, unique_id); 439 std::string device_id = MediaStorageUtil::MakeDeviceId(type, unique_id);
246 EXPECT_CALL(observer_, OnRemovableStorageDetached(device_id)).Times(1); 440 EXPECT_CALL(observer_, OnRemovableStorageDetached(device_id)).Times(1);
247 } 441 }
248 } 442 }
249 } 443 }
250 window_->InjectDeviceChange(DBT_DEVICEREMOVECOMPLETE, 444 window_->InjectDeviceChange(DBT_DEVICEREMOVECOMPLETE,
251 reinterpret_cast<DWORD>(&volume_broadcast)); 445 reinterpret_cast<DWORD>(&volume_broadcast));
252 message_loop_.RunAllPending(); 446 RunAllPending();
447 }
448
449 void RemovableDeviceNotificationsWindowWinTest::DoMtpDeviceTest(
450 const string16& pnp_device_id, bool attached) {
451 GUID guidDevInterface = GUID_NULL;
452 HRESULT hr = CLSIDFromString(kWPDDevInterfaceGUID, &guidDevInterface);
453 if (FAILED(hr))
454 return;
455
456 size_t device_id_size = pnp_device_id.size() * sizeof(char16);
457 size_t size = sizeof(DEV_BROADCAST_DEVICEINTERFACE) + device_id_size;
458 scoped_ptr_malloc<DEV_BROADCAST_DEVICEINTERFACE> dev_interface_broadcast(
459 static_cast<DEV_BROADCAST_DEVICEINTERFACE*>(malloc(size)));
460 DCHECK(dev_interface_broadcast.get());
461 ZeroMemory(dev_interface_broadcast.get(), size);
462 dev_interface_broadcast->dbcc_size = size;
463 dev_interface_broadcast->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
464 dev_interface_broadcast->dbcc_classguid = guidDevInterface;
465 memcpy(dev_interface_broadcast->dbcc_name, pnp_device_id.data(),
466 device_id_size);
467 {
468 testing::InSequence sequence;
469 PortableDeviceWatcherWin::StorageObjectIDs storage_object_ids =
470 GetMtpStorageObjectIds(pnp_device_id);
471 for (PortableDeviceWatcherWin::StorageObjectIDs::const_iterator it =
472 storage_object_ids.begin();
473 it != storage_object_ids.end(); ++it) {
474 std::string unique_id;
475 string16 name;
476 string16 location;
477 GetMtpStorageDetails(pnp_device_id, *it, &location, &unique_id, &name);
478 if (attached) {
479 EXPECT_CALL(observer_, OnRemovableStorageAttached(unique_id, name,
480 location))
481 .Times((name.empty() || unique_id.empty()) ? 0 : 1);
482 } else {
483 EXPECT_CALL(observer_, OnRemovableStorageDetached(unique_id))
484 .Times((name.empty() || unique_id.empty()) ? 0 : 1);
485 }
486 }
487 }
488 window_->InjectDeviceChange(
489 attached ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE,
490 reinterpret_cast<DWORD>(dev_interface_broadcast.get()));
491 RunAllPending();
253 } 492 }
254 493
255 TEST_F(RemovableDeviceNotificationsWindowWinTest, RandomMessage) { 494 TEST_F(RemovableDeviceNotificationsWindowWinTest, RandomMessage) {
256 window_->InjectDeviceChange(DBT_DEVICEQUERYREMOVE, NULL); 495 window_->InjectDeviceChange(DBT_DEVICEQUERYREMOVE, NULL);
257 message_loop_.RunAllPending(); 496 RunAllPending();
258 } 497 }
259 498
260 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttached) { 499 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttached) {
261 std::vector<int> device_indices; 500 std::vector<int> device_indices;
262 device_indices.push_back(1); 501 device_indices.push_back(1);
263 device_indices.push_back(5); 502 device_indices.push_back(5);
264 device_indices.push_back(7); 503 device_indices.push_back(7);
265 device_indices.push_back(13); 504 device_indices.push_back(13);
266 505
267 DoDevicesAttachedTest(device_indices); 506 DoMassStorageDeviceAttachedTest(device_indices);
268 } 507 }
269 508
270 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedHighBoundary) { 509 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedHighBoundary) {
271 std::vector<int> device_indices; 510 std::vector<int> device_indices;
272 device_indices.push_back(25); 511 device_indices.push_back(25);
273 512
274 DoDevicesAttachedTest(device_indices); 513 DoMassStorageDeviceAttachedTest(device_indices);
275 } 514 }
276 515
277 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedLowBoundary) { 516 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedLowBoundary) {
278 std::vector<int> device_indices; 517 std::vector<int> device_indices;
279 device_indices.push_back(0); 518 device_indices.push_back(0);
280 519
281 DoDevicesAttachedTest(device_indices); 520 DoMassStorageDeviceAttachedTest(device_indices);
282 } 521 }
283 522
284 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedAdjacentBits) { 523 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesAttachedAdjacentBits) {
285 std::vector<int> device_indices; 524 std::vector<int> device_indices;
286 device_indices.push_back(0); 525 device_indices.push_back(0);
287 device_indices.push_back(1); 526 device_indices.push_back(1);
288 device_indices.push_back(2); 527 device_indices.push_back(2);
289 device_indices.push_back(3); 528 device_indices.push_back(3);
290 529
291 DoDevicesAttachedTest(device_indices); 530 DoMassStorageDeviceAttachedTest(device_indices);
292 } 531 }
293 532
294 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetached) { 533 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetached) {
295 PreAttachDevices(); 534 PreAttachDevices();
296 535
297 std::vector<int> device_indices; 536 std::vector<int> device_indices;
298 device_indices.push_back(1); 537 device_indices.push_back(1);
299 device_indices.push_back(5); 538 device_indices.push_back(5);
300 device_indices.push_back(7); 539 device_indices.push_back(7);
301 device_indices.push_back(13); 540 device_indices.push_back(13);
302 541
303 DoDevicesDetachedTest(device_indices); 542 DoMassStorageDevicesDetachedTest(device_indices);
304 } 543 }
305 544
306 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetachedHighBoundary) { 545 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetachedHighBoundary) {
307 PreAttachDevices(); 546 PreAttachDevices();
308 547
309 std::vector<int> device_indices; 548 std::vector<int> device_indices;
310 device_indices.push_back(25); 549 device_indices.push_back(25);
311 550
312 DoDevicesDetachedTest(device_indices); 551 DoMassStorageDevicesDetachedTest(device_indices);
313 } 552 }
314 553
315 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetachedLowBoundary) { 554 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetachedLowBoundary) {
316 PreAttachDevices(); 555 PreAttachDevices();
317 556
318 std::vector<int> device_indices; 557 std::vector<int> device_indices;
319 device_indices.push_back(0); 558 device_indices.push_back(0);
320 559
321 DoDevicesDetachedTest(device_indices); 560 DoMassStorageDevicesDetachedTest(device_indices);
322 } 561 }
323 562
324 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetachedAdjacentBits) { 563 TEST_F(RemovableDeviceNotificationsWindowWinTest, DevicesDetachedAdjacentBits) {
325 PreAttachDevices(); 564 PreAttachDevices();
326 565
327 std::vector<int> device_indices; 566 std::vector<int> device_indices;
328 device_indices.push_back(0); 567 device_indices.push_back(0);
329 device_indices.push_back(1); 568 device_indices.push_back(1);
330 device_indices.push_back(2); 569 device_indices.push_back(2);
331 device_indices.push_back(3); 570 device_indices.push_back(3);
332 571
333 DoDevicesDetachedTest(device_indices); 572 DoMassStorageDevicesDetachedTest(device_indices);
334 } 573 }
335 574
336 TEST_F(RemovableDeviceNotificationsWindowWinTest, DeviceInfoFoPath) { 575 TEST_F(RemovableDeviceNotificationsWindowWinTest, DeviceInfoFoPath) {
337 PreAttachDevices(); 576 PreAttachDevices();
338 577
339 // An invalid path. 578 // An invalid path.
340 EXPECT_FALSE(window_->GetDeviceInfoForPath(FilePath(L"COM1:\\"), NULL)); 579 EXPECT_FALSE(window_->GetDeviceInfoForPath(FilePath(L"COM1:\\"), NULL));
341 580
342 // An unconnected removable device. 581 // An unconnected removable device.
343 EXPECT_FALSE(window_->GetDeviceInfoForPath(FilePath(L"E:\\"), NULL)); 582 EXPECT_FALSE(window_->GetDeviceInfoForPath(FilePath(L"E:\\"), NULL));
344 583
345 // A connected removable device. 584 // A connected removable device.
346 FilePath removable_device(L"F:\\"); 585 FilePath removable_device(L"F:\\");
347 base::SystemMonitor::RemovableStorageInfo device_info; 586 base::SystemMonitor::RemovableStorageInfo device_info;
348 EXPECT_TRUE(window_->GetDeviceInfoForPath(removable_device, &device_info)); 587 EXPECT_TRUE(window_->GetDeviceInfoForPath(removable_device, &device_info));
349 588
350 std::string unique_id; 589 std::string unique_id;
351 string16 device_name; 590 string16 device_name;
352 bool removable; 591 bool removable;
353 ASSERT_TRUE(GetDeviceDetails(removable_device, NULL, &unique_id, &device_name, 592 ASSERT_TRUE(GetMassStorageDeviceDetails(removable_device, NULL, &unique_id,
354 &removable)); 593 &device_name, &removable));
355 EXPECT_TRUE(removable); 594 EXPECT_TRUE(removable);
356 std::string device_id = MediaStorageUtil::MakeDeviceId( 595 std::string device_id = MediaStorageUtil::MakeDeviceId(
357 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM, unique_id); 596 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM, unique_id);
358 EXPECT_EQ(device_id, device_info.device_id); 597 EXPECT_EQ(device_id, device_info.device_id);
359 EXPECT_EQ(device_name, device_info.name); 598 EXPECT_EQ(device_name, device_info.name);
360 EXPECT_EQ(removable_device.value(), device_info.location); 599 EXPECT_EQ(removable_device.value(), device_info.location);
361 600
362 // A fixed device. 601 // A fixed device.
363 FilePath fixed_device(L"N:\\"); 602 FilePath fixed_device(L"N:\\");
364 EXPECT_TRUE(window_->GetDeviceInfoForPath(fixed_device, &device_info)); 603 EXPECT_TRUE(window_->GetDeviceInfoForPath(fixed_device, &device_info));
365 604
366 ASSERT_TRUE(GetDeviceDetails(fixed_device, NULL, &unique_id, &device_name, 605 ASSERT_TRUE(GetMassStorageDeviceDetails(fixed_device, NULL, &unique_id,
367 &removable)); 606 &device_name, &removable));
368 EXPECT_FALSE(removable); 607 EXPECT_FALSE(removable);
369 device_id = MediaStorageUtil::MakeDeviceId( 608 device_id = MediaStorageUtil::MakeDeviceId(
370 MediaStorageUtil::FIXED_MASS_STORAGE, unique_id); 609 MediaStorageUtil::FIXED_MASS_STORAGE, unique_id);
371 EXPECT_EQ(device_id, device_info.device_id); 610 EXPECT_EQ(device_id, device_info.device_id);
372 EXPECT_EQ(device_name, device_info.name); 611 EXPECT_EQ(device_name, device_info.name);
373 EXPECT_EQ(fixed_device.value(), device_info.location); 612 EXPECT_EQ(fixed_device.value(), device_info.location);
374 } 613 }
375 614
615 // Test to verify basic mtp storage attach and detach notifications.
616 TEST_F(RemovableDeviceNotificationsWindowWinTest, MtpDeviceBasicAttachDetach) {
617 DoMtpDeviceTest(kMtpDeviceWithValidInfo, true);
618 DoMtpDeviceTest(kMtpDeviceWithValidInfo, false);
619 }
620
621 // When a mtp storage device with invalid storage label and id is
622 // attached/detached, there should not be any device attach/detach
623 // notifications.
624 TEST_F(RemovableDeviceNotificationsWindowWinTest, MtpDeviceWithInvalidInfo) {
625 DoMtpDeviceTest(kMtpDeviceWithInvalidInfo, true);
626 DoMtpDeviceTest(kMtpDeviceWithInvalidInfo, false);
627 }
628
629 // Attach a device with two data partitions. Verify that attach/detach
630 // notifications are sent out for each removable storage.
631 TEST_F(RemovableDeviceNotificationsWindowWinTest,
632 MtpDeviceWithMultipleStorageObjects) {
633 DoMtpDeviceTest(kMtpDeviceWithMultipleStorageObjects, true);
634 DoMtpDeviceTest(kMtpDeviceWithMultipleStorageObjects, false);
635 }
636
376 } // namespace chrome 637 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698