Chromium Code Reviews| Index: chrome/browser/system_monitor/removable_device_notifications_window_win.cc |
| diff --git a/chrome/browser/system_monitor/removable_device_notifications_window_win.cc b/chrome/browser/system_monitor/removable_device_notifications_window_win.cc |
| index 2f04fe968cca535ddfe7ddd48758bd7dcda516e1..7c059b431e78b1943ff6a4b0660bd0abc3317f21 100644 |
| --- a/chrome/browser/system_monitor/removable_device_notifications_window_win.cc |
| +++ b/chrome/browser/system_monitor/removable_device_notifications_window_win.cc |
| @@ -9,7 +9,7 @@ |
| #include <fileapi.h> |
| #include "base/file_path.h" |
| -#include "base/metrics/histogram.h" |
| +#include "base/i18n/case_conversion.h" |
| #include "base/string_number_conversions.h" |
| #include "base/string_util.h" |
| #include "base/system_monitor/system_monitor.h" |
| @@ -17,10 +17,12 @@ |
| #include "base/win/wrapped_window_proc.h" |
| #include "chrome/browser/system_monitor/media_device_notifications_utils.h" |
| #include "chrome/browser/system_monitor/media_storage_util.h" |
| +#include "chrome/browser/system_monitor/media_transfer_protocol_device_observer_win.h" |
| #include "content/public/browser/browser_thread.h" |
| using base::SystemMonitor; |
| using base::win::WrappedWindowProc; |
| +using chrome::mtp::MediaTransferProtocolDeviceObserverWin; |
| using content::BrowserThread; |
| namespace { |
| @@ -29,6 +31,9 @@ const DWORD kMaxPathBufLen = MAX_PATH + 1; |
| const char16 kWindowClassName[] = L"Chrome_RemovableDeviceNotificationWindow"; |
| +// Windows portable device interface GUID constant. |
| +const char16 kWPDDevInterfaceGUID[] = L"{6ac27878-a6fa-4155-ba85-f98f491d4f33}"; |
| + |
| static chrome::RemovableDeviceNotificationsWindowWin* |
| g_removable_device_notifications_window_win = NULL; |
| @@ -78,6 +83,39 @@ bool GetDeviceInfo(const FilePath& device_path, string16* device_location, |
| return true; |
| } |
| +// Returns true if |data| represents a logical volume structure. |
| +bool IsLogicalVolumeStructure(LPARAM data) { |
| + DEV_BROADCAST_HDR* broadcast_hdr = |
| + reinterpret_cast<DEV_BROADCAST_HDR*>(data); |
| + return broadcast_hdr != NULL && |
| + broadcast_hdr->dbch_devicetype == DBT_DEVTYP_VOLUME; |
| +} |
| + |
| +// Returns true if |data| represents a class of portable devices. |
| +bool IsPortableDeviceStructure(LPARAM data) { |
| + DEV_BROADCAST_HDR* broadcast_hdr = |
| + reinterpret_cast<DEV_BROADCAST_HDR*>(data); |
| + if (!broadcast_hdr || |
| + broadcast_hdr->dbch_devicetype != DBT_DEVTYP_DEVICEINTERFACE) { |
| + return false; |
| + } |
| + |
| + GUID guidDevInterface = GUID_NULL; |
| + CLSIDFromString(kWPDDevInterfaceGUID, &guidDevInterface); |
| + DEV_BROADCAST_DEVICEINTERFACE* dev_interface = |
| + reinterpret_cast<DEV_BROADCAST_DEVICEINTERFACE*>(data); |
| + return (IsEqualGUID(dev_interface->dbcc_classguid, guidDevInterface) != 0); |
| +} |
| + |
| +// Returns the portable device plug and play device ID string. |
| +string16 GetPnpDeviceId(LPARAM data) { |
| + DEV_BROADCAST_DEVICEINTERFACE* dev_interface = |
| + reinterpret_cast<DEV_BROADCAST_DEVICEINTERFACE*>(data); |
| + if (!dev_interface) |
| + return string16(); |
| + return base::i18n::ToLower(dev_interface->dbcc_name); |
| +} |
| + |
| std::vector<FilePath> GetAttachedDevices() { |
| std::vector<FilePath> result; |
| char16 volume_name[kMaxPathBufLen]; |
| @@ -202,30 +240,29 @@ void RemovableDeviceNotificationsWindowWin::OnDeviceChange(UINT event_type, |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| switch (event_type) { |
| case DBT_DEVICEARRIVAL: { |
| - DWORD unitmask = GetVolumeBitMaskFromBroadcastHeader(data); |
| - for (int i = 0; unitmask; ++i, unitmask >>= 1) { |
| - if (!(unitmask & 0x01)) |
| - continue; |
| - AddNewDevice(DriveNumberToFilePath(i)); |
| + if (IsLogicalVolumeStructure(data)) { |
| + DWORD unitmask = GetVolumeBitMaskFromBroadcastHeader(data); |
| + for (int i = 0; unitmask; ++i, unitmask >>= 1) { |
| + if (!(unitmask & 0x01)) |
| + continue; |
| + AddNewDevice(DriveNumberToFilePath(i)); |
| + } |
| + } else if (IsPortableDeviceStructure(data)) { |
| + HandleMtpDeviceEventOnUIThread(true, GetPnpDeviceId(data)); |
| } |
| break; |
| } |
| case DBT_DEVICEREMOVECOMPLETE: { |
| - DWORD unitmask = GetVolumeBitMaskFromBroadcastHeader(data); |
| - for (int i = 0; unitmask; ++i, unitmask >>= 1) { |
| - if (!(unitmask & 0x01)) |
| - continue; |
| - |
| - FilePath device = DriveNumberToFilePath(i); |
| - MountPointDeviceIdMap::const_iterator device_info = |
| - device_ids_.find(device); |
| - // If the devices isn't type removable (like a CD), it won't be there. |
| - if (device_info == device_ids_.end()) |
| - continue; |
| - |
| - SystemMonitor::Get()->ProcessRemovableStorageDetached( |
| - device_info->second); |
| - device_ids_.erase(device_info); |
| + if (IsLogicalVolumeStructure(data)) { |
| + DWORD unitmask = GetVolumeBitMaskFromBroadcastHeader(data); |
| + for (int i = 0; unitmask; ++i, unitmask >>= 1) { |
| + if (!(unitmask & 0x01)) |
| + continue; |
| + HandleMassStorageDeviceDetachEventOnUIThread( |
| + DriveNumberToFilePath(i).value()); |
| + } |
| + } else if (IsPortableDeviceStructure(data)) { |
| + HandleMtpDeviceEventOnUIThread(false, GetPnpDeviceId(data)); |
| } |
| break; |
| } |
| @@ -247,6 +284,23 @@ RemovableDeviceNotificationsWindowWin:: |
| // static |
| LRESULT CALLBACK RemovableDeviceNotificationsWindowWin::WndProcThunk( |
| HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { |
| +#if defined(DBT_DEVTYP_DEVICEINTERFACE) && defined(DEVICE_NOTIFY_WINDOW_HANDLE) |
| + static HDEVNOTIFY hDeviceNotify; |
| + 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
|
| + GUID guidDevInterface = GUID_NULL; |
| + HRESULT hr = CLSIDFromString(kWPDDevInterfaceGUID, &guidDevInterface); |
| + if (SUCCEEDED(hr)) { |
| + DEV_BROADCAST_DEVICEINTERFACE db = {0}; |
| + db.dbcc_size = sizeof(db); |
| + db.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; |
| + db.dbcc_classguid = guidDevInterface; |
| + hDeviceNotify = RegisterDeviceNotification(hwnd, &db, |
| + DEVICE_NOTIFY_WINDOW_HANDLE); |
| + } |
| + } else if (message == WM_CLOSE) { |
| + UnregisterDeviceNotification(hDeviceNotify); |
| + } |
| +#endif |
| RemovableDeviceNotificationsWindowWin* msg_wnd = |
| reinterpret_cast<RemovableDeviceNotificationsWindowWin*>( |
| GetWindowLongPtr(hwnd, GWLP_USERDATA)); |
| @@ -331,21 +385,48 @@ void RemovableDeviceNotificationsWindowWin::CheckDeviceTypeOnFileThread( |
| std::string device_id = MediaStorageUtil::MakeDeviceId(type, unique_id); |
| BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( |
| - &RemovableDeviceNotificationsWindowWin::ProcessDeviceAttachedOnUIThread, |
| - this, device_id, device_name, device)); |
| + &RemovableDeviceNotificationsWindowWin:: |
| + HandleMassStorageDeviceAttachEventOnUIThread, |
| + this, device_id, device_name, device.value())); |
| } |
| -void RemovableDeviceNotificationsWindowWin::ProcessDeviceAttachedOnUIThread( |
| +void RemovableDeviceNotificationsWindowWin:: |
| +HandleMassStorageDeviceAttachEventOnUIThread( |
| const std::string& device_id, |
| - const FilePath::StringType& device_name, |
| - const FilePath& device) { |
| + const string16& device_name, |
| + const string16& device_location) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| // TODO(kmadhusu) Record device info histogram. |
| - device_ids_[device] = device_id; |
| + device_ids_[device_location] = device_id; |
| SystemMonitor::Get()->ProcessRemovableStorageAttached(device_id, |
| device_name, |
| - device.value()); |
| + device_location); |
| +} |
| + |
| +void RemovableDeviceNotificationsWindowWin:: |
| +HandleMassStorageDeviceDetachEventOnUIThread(const string16& device_location) { |
| + MountPointDeviceIdMap::const_iterator device_info = |
| + device_ids_.find(device_location); |
| + // If the devices isn't type removable (like a CD), it won't be there. |
| + if (device_info == device_ids_.end()) |
| + return; |
| + |
| + SystemMonitor::Get()->ProcessRemovableStorageDetached(device_info->second); |
| + device_ids_.erase(device_info); |
| +} |
| + |
| +void RemovableDeviceNotificationsWindowWin:: |
| +HandleMtpDeviceEventOnUIThread(bool is_attach, const string16& pnp_device_id) { |
| + if (pnp_device_id.empty()) |
| + return; |
| + |
| + MediaTransferProtocolDeviceObserverWin* mtp_device_observer = |
| + MediaTransferProtocolDeviceObserverWin::GetInstance(); |
| + if (mtp_device_observer) { |
| + mtp_device_observer->HandleMtpDeviceEventOnUIThread(is_attach, |
| + pnp_device_id); |
| + } |
| } |
| } // namespace chrome |