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

Side by Side Diff: chrome/browser/system_monitor/removable_device_notifications_window_win.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: '' 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 <windows.h> 7 #include <windows.h>
8 #include <dbt.h> 8 #include <dbt.h>
9 #include <fileapi.h> 9 #include <fileapi.h>
10 10
11 #include "base/file_path.h" 11 #include "base/file_path.h"
12 #include "base/metrics/histogram.h" 12 #include "base/i18n/case_conversion.h"
13 #include "base/string_number_conversions.h" 13 #include "base/string_number_conversions.h"
14 #include "base/string_util.h" 14 #include "base/string_util.h"
15 #include "base/system_monitor/system_monitor.h" 15 #include "base/system_monitor/system_monitor.h"
16 #include "base/utf_string_conversions.h" 16 #include "base/utf_string_conversions.h"
17 #include "base/win/wrapped_window_proc.h" 17 #include "base/win/wrapped_window_proc.h"
18 #include "chrome/browser/system_monitor/media_device_notifications_utils.h" 18 #include "chrome/browser/system_monitor/media_device_notifications_utils.h"
19 #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/media_transfer_protocol_device_observer_ win.h"
20 #include "content/public/browser/browser_thread.h" 21 #include "content/public/browser/browser_thread.h"
21 22
22 using base::SystemMonitor; 23 using base::SystemMonitor;
23 using base::win::WrappedWindowProc; 24 using base::win::WrappedWindowProc;
25 using chrome::mtp::MediaTransferProtocolDeviceObserverWin;
24 using content::BrowserThread; 26 using content::BrowserThread;
25 27
26 namespace { 28 namespace {
27 29
28 const DWORD kMaxPathBufLen = MAX_PATH + 1; 30 const DWORD kMaxPathBufLen = MAX_PATH + 1;
29 31
30 const char16 kWindowClassName[] = L"Chrome_RemovableDeviceNotificationWindow"; 32 const char16 kWindowClassName[] = L"Chrome_RemovableDeviceNotificationWindow";
31 33
34 // Windows portable device interface GUID constant.
35 const char16 kWPDDevInterfaceGUID[] = L"{6ac27878-a6fa-4155-ba85-f98f491d4f33}";
36
32 static chrome::RemovableDeviceNotificationsWindowWin* 37 static chrome::RemovableDeviceNotificationsWindowWin*
33 g_removable_device_notifications_window_win = NULL; 38 g_removable_device_notifications_window_win = NULL;
34 39
35 bool IsRemovable(const char16* mount_point) { 40 bool IsRemovable(const char16* mount_point) {
36 if (GetDriveType(mount_point) != DRIVE_REMOVABLE) 41 if (GetDriveType(mount_point) != DRIVE_REMOVABLE)
37 return false; 42 return false;
38 43
39 // We don't consider floppy disks as removable, so check for that. 44 // We don't consider floppy disks as removable, so check for that.
40 string16 device = mount_point; 45 string16 device = mount_point;
41 if (EndsWith(device, L"\\", false)) 46 if (EndsWith(device, L"\\", false))
(...skipping 29 matching lines...) Expand all
71 76
72 if (name) 77 if (name)
73 *name = device_path.LossyDisplayName(); 78 *name = device_path.LossyDisplayName();
74 79
75 if (removable) 80 if (removable)
76 *removable = IsRemovable(mount_point); 81 *removable = IsRemovable(mount_point);
77 82
78 return true; 83 return true;
79 } 84 }
80 85
86 // Returns true if |data| represents a logical volume structure.
87 bool IsLogicalVolumeStructure(LPARAM data) {
88 DEV_BROADCAST_HDR* broadcast_hdr =
89 reinterpret_cast<DEV_BROADCAST_HDR*>(data);
90 return broadcast_hdr != NULL &&
91 broadcast_hdr->dbch_devicetype == DBT_DEVTYP_VOLUME;
92 }
93
94 // Returns true if |data| represents a class of portable devices.
95 bool IsPortableDeviceStructure(LPARAM data) {
96 DEV_BROADCAST_HDR* broadcast_hdr =
97 reinterpret_cast<DEV_BROADCAST_HDR*>(data);
98 if (!broadcast_hdr ||
99 broadcast_hdr->dbch_devicetype != DBT_DEVTYP_DEVICEINTERFACE) {
100 return false;
101 }
102
103 GUID guidDevInterface = GUID_NULL;
104 CLSIDFromString(kWPDDevInterfaceGUID, &guidDevInterface);
105 DEV_BROADCAST_DEVICEINTERFACE* dev_interface =
106 reinterpret_cast<DEV_BROADCAST_DEVICEINTERFACE*>(data);
107 return (IsEqualGUID(dev_interface->dbcc_classguid, guidDevInterface) != 0);
108 }
109
110 // Returns the portable device plug and play device ID string.
111 string16 GetPnpDeviceId(LPARAM data) {
112 DEV_BROADCAST_DEVICEINTERFACE* dev_interface =
113 reinterpret_cast<DEV_BROADCAST_DEVICEINTERFACE*>(data);
114 if (!dev_interface)
115 return string16();
116 return base::i18n::ToLower(dev_interface->dbcc_name);
117 }
118
81 std::vector<FilePath> GetAttachedDevices() { 119 std::vector<FilePath> GetAttachedDevices() {
82 std::vector<FilePath> result; 120 std::vector<FilePath> result;
83 char16 volume_name[kMaxPathBufLen]; 121 char16 volume_name[kMaxPathBufLen];
84 HANDLE find_handle = FindFirstVolume(volume_name, kMaxPathBufLen); 122 HANDLE find_handle = FindFirstVolume(volume_name, kMaxPathBufLen);
85 if (find_handle == INVALID_HANDLE_VALUE) 123 if (find_handle == INVALID_HANDLE_VALUE)
86 return result; 124 return result;
87 125
88 while (true) { 126 while (true) {
89 char16 volume_path[kMaxPathBufLen]; 127 char16 volume_path[kMaxPathBufLen];
90 DWORD return_count; 128 DWORD return_count;
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 GetAttachedDevicesFunc get_attached_devices_func) { 233 GetAttachedDevicesFunc get_attached_devices_func) {
196 get_device_info_func_ = get_device_info_func; 234 get_device_info_func_ = get_device_info_func;
197 DoInit(get_attached_devices_func); 235 DoInit(get_attached_devices_func);
198 } 236 }
199 237
200 void RemovableDeviceNotificationsWindowWin::OnDeviceChange(UINT event_type, 238 void RemovableDeviceNotificationsWindowWin::OnDeviceChange(UINT event_type,
201 LPARAM data) { 239 LPARAM data) {
202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 240 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
203 switch (event_type) { 241 switch (event_type) {
204 case DBT_DEVICEARRIVAL: { 242 case DBT_DEVICEARRIVAL: {
205 DWORD unitmask = GetVolumeBitMaskFromBroadcastHeader(data); 243 if (IsLogicalVolumeStructure(data)) {
206 for (int i = 0; unitmask; ++i, unitmask >>= 1) { 244 DWORD unitmask = GetVolumeBitMaskFromBroadcastHeader(data);
207 if (!(unitmask & 0x01)) 245 for (int i = 0; unitmask; ++i, unitmask >>= 1) {
208 continue; 246 if (!(unitmask & 0x01))
209 AddNewDevice(DriveNumberToFilePath(i)); 247 continue;
248 AddNewDevice(DriveNumberToFilePath(i));
249 }
250 } else if (IsPortableDeviceStructure(data)) {
251 HandleMtpDeviceEventOnUIThread(true, GetPnpDeviceId(data));
210 } 252 }
211 break; 253 break;
212 } 254 }
213 case DBT_DEVICEREMOVECOMPLETE: { 255 case DBT_DEVICEREMOVECOMPLETE: {
214 DWORD unitmask = GetVolumeBitMaskFromBroadcastHeader(data); 256 if (IsLogicalVolumeStructure(data)) {
215 for (int i = 0; unitmask; ++i, unitmask >>= 1) { 257 DWORD unitmask = GetVolumeBitMaskFromBroadcastHeader(data);
216 if (!(unitmask & 0x01)) 258 for (int i = 0; unitmask; ++i, unitmask >>= 1) {
217 continue; 259 if (!(unitmask & 0x01))
218 260 continue;
219 FilePath device = DriveNumberToFilePath(i); 261 HandleMassStorageDeviceDetachEventOnUIThread(
220 MountPointDeviceIdMap::const_iterator device_info = 262 DriveNumberToFilePath(i).value());
221 device_ids_.find(device); 263 }
222 // If the devices isn't type removable (like a CD), it won't be there. 264 } else if (IsPortableDeviceStructure(data)) {
223 if (device_info == device_ids_.end()) 265 HandleMtpDeviceEventOnUIThread(false, GetPnpDeviceId(data));
224 continue;
225
226 SystemMonitor::Get()->ProcessRemovableStorageDetached(
227 device_info->second);
228 device_ids_.erase(device_info);
229 } 266 }
230 break; 267 break;
231 } 268 }
232 } 269 }
233 } 270 }
234 271
235 RemovableDeviceNotificationsWindowWin:: 272 RemovableDeviceNotificationsWindowWin::
236 ~RemovableDeviceNotificationsWindowWin() { 273 ~RemovableDeviceNotificationsWindowWin() {
237 if (window_) 274 if (window_)
238 DestroyWindow(window_); 275 DestroyWindow(window_);
239 276
240 if (window_class_) 277 if (window_class_)
241 UnregisterClass(MAKEINTATOM(window_class_), instance_); 278 UnregisterClass(MAKEINTATOM(window_class_), instance_);
242 279
243 DCHECK_EQ(this, g_removable_device_notifications_window_win); 280 DCHECK_EQ(this, g_removable_device_notifications_window_win);
244 g_removable_device_notifications_window_win = NULL; 281 g_removable_device_notifications_window_win = NULL;
245 } 282 }
246 283
247 // static 284 // static
248 LRESULT CALLBACK RemovableDeviceNotificationsWindowWin::WndProcThunk( 285 LRESULT CALLBACK RemovableDeviceNotificationsWindowWin::WndProcThunk(
249 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { 286 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
287 #if defined(DBT_DEVTYP_DEVICEINTERFACE) && defined(DEVICE_NOTIFY_WINDOW_HANDLE)
288 static HDEVNOTIFY hDeviceNotify;
289 if (message == WM_CREATE) {
vandebo (ex-Chrome) 2012/10/16 17:42:36 content/browser/system_message_window_win.cc just
kmadhusu 2012/10/19 04:01:38 This code is very similar to the SystemMessageWind
290 GUID guidDevInterface = GUID_NULL;
291 HRESULT hr = CLSIDFromString(kWPDDevInterfaceGUID, &guidDevInterface);
292 if (SUCCEEDED(hr)) {
293 DEV_BROADCAST_DEVICEINTERFACE db = {0};
294 db.dbcc_size = sizeof(db);
295 db.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
296 db.dbcc_classguid = guidDevInterface;
297 hDeviceNotify = RegisterDeviceNotification(hwnd, &db,
298 DEVICE_NOTIFY_WINDOW_HANDLE);
299 }
300 } else if (message == WM_CLOSE) {
301 UnregisterDeviceNotification(hDeviceNotify);
302 }
303 #endif
250 RemovableDeviceNotificationsWindowWin* msg_wnd = 304 RemovableDeviceNotificationsWindowWin* msg_wnd =
251 reinterpret_cast<RemovableDeviceNotificationsWindowWin*>( 305 reinterpret_cast<RemovableDeviceNotificationsWindowWin*>(
252 GetWindowLongPtr(hwnd, GWLP_USERDATA)); 306 GetWindowLongPtr(hwnd, GWLP_USERDATA));
253 if (msg_wnd) 307 if (msg_wnd)
254 return msg_wnd->WndProc(hwnd, message, wparam, lparam); 308 return msg_wnd->WndProc(hwnd, message, wparam, lparam);
255 return ::DefWindowProc(hwnd, message, wparam, lparam); 309 return ::DefWindowProc(hwnd, message, wparam, lparam);
256 } 310 }
257 311
258 LRESULT CALLBACK RemovableDeviceNotificationsWindowWin::WndProc( 312 LRESULT CALLBACK RemovableDeviceNotificationsWindowWin::WndProc(
259 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { 313 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 const FilePath& device) { 378 const FilePath& device) {
325 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 379 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
326 380
327 MediaStorageUtil::Type type = 381 MediaStorageUtil::Type type =
328 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM; 382 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM;
329 if (IsMediaDevice(device.value())) 383 if (IsMediaDevice(device.value()))
330 type = MediaStorageUtil::REMOVABLE_MASS_STORAGE_WITH_DCIM; 384 type = MediaStorageUtil::REMOVABLE_MASS_STORAGE_WITH_DCIM;
331 std::string device_id = MediaStorageUtil::MakeDeviceId(type, unique_id); 385 std::string device_id = MediaStorageUtil::MakeDeviceId(type, unique_id);
332 386
333 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( 387 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
334 &RemovableDeviceNotificationsWindowWin::ProcessDeviceAttachedOnUIThread, 388 &RemovableDeviceNotificationsWindowWin::
335 this, device_id, device_name, device)); 389 HandleMassStorageDeviceAttachEventOnUIThread,
390 this, device_id, device_name, device.value()));
336 } 391 }
337 392
338 void RemovableDeviceNotificationsWindowWin::ProcessDeviceAttachedOnUIThread( 393 void RemovableDeviceNotificationsWindowWin::
394 HandleMassStorageDeviceAttachEventOnUIThread(
339 const std::string& device_id, 395 const std::string& device_id,
340 const FilePath::StringType& device_name, 396 const string16& device_name,
341 const FilePath& device) { 397 const string16& device_location) {
342 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 398 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
343 399
344 // TODO(kmadhusu) Record device info histogram. 400 // TODO(kmadhusu) Record device info histogram.
345 device_ids_[device] = device_id; 401 device_ids_[device_location] = device_id;
346 SystemMonitor::Get()->ProcessRemovableStorageAttached(device_id, 402 SystemMonitor::Get()->ProcessRemovableStorageAttached(device_id,
347 device_name, 403 device_name,
348 device.value()); 404 device_location);
405 }
406
407 void RemovableDeviceNotificationsWindowWin::
408 HandleMassStorageDeviceDetachEventOnUIThread(const string16& device_location) {
409 MountPointDeviceIdMap::const_iterator device_info =
410 device_ids_.find(device_location);
411 // If the devices isn't type removable (like a CD), it won't be there.
412 if (device_info == device_ids_.end())
413 return;
414
415 SystemMonitor::Get()->ProcessRemovableStorageDetached(device_info->second);
416 device_ids_.erase(device_info);
417 }
418
419 void RemovableDeviceNotificationsWindowWin::
420 HandleMtpDeviceEventOnUIThread(bool is_attach, const string16& pnp_device_id) {
421 if (pnp_device_id.empty())
422 return;
423
424 MediaTransferProtocolDeviceObserverWin* mtp_device_observer =
425 MediaTransferProtocolDeviceObserverWin::GetInstance();
426 if (mtp_device_observer) {
427 mtp_device_observer->HandleMtpDeviceEventOnUIThread(is_attach,
428 pnp_device_id);
429 }
349 } 430 }
350 431
351 } // namespace chrome 432 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698