Chromium Code Reviews| Index: base/system_monitor/system_monitor_mac.mm |
| diff --git a/base/system_monitor/system_monitor_mac.mm b/base/system_monitor/system_monitor_mac.mm |
| index baaadf052db913eb7f3c548f81c545901f6192e8..36b4e48cb1c5621565c1404aec32e17be060fb17 100644 |
| --- a/base/system_monitor/system_monitor_mac.mm |
| +++ b/base/system_monitor/system_monitor_mac.mm |
| @@ -7,9 +7,14 @@ |
| #include "base/system_monitor/system_monitor.h" |
| +#import <Carbon/Carbon.h> |
|
csilv
2012/02/13 05:49:28
use #include instead, #import only for pure obj-c
vandebo (ex-Chrome)
2012/02/14 21:23:23
Done.
|
| +#include <CoreFoundation/CoreFoundation.h> |
| #include <IOKit/pwr_mgt/IOPMLib.h> |
| #include <IOKit/IOMessage.h> |
| +#include "base/mac/foundation_util.h" |
| +#include "base/sys_string_conversions.h" |
| + |
| namespace base { |
| namespace { |
| @@ -37,6 +42,73 @@ void SystemPowerEventCallback(void*, |
| } |
| } |
| +bool GetDeviceInfo(unsigned long device_number, std::string* name, |
| + FilePath* location) { |
| + ICACopyObjectPropertyDictionaryPB properties_request; |
| + properties_request.object = device_number; |
| + CFDictionaryRef device_properties; |
| + properties_request.theDict = &device_properties; |
| + OSErr ret = ICACopyObjectPropertyDictionary(&properties_request, NULL); |
| + CHECK_EQ(ret, noErr); |
| + |
| + // For now, we only support mass storage media devices. |
| + CFStringRef volume = mac::GetValueFromDictionary<CFStringRef>( |
| + device_properties, CFSTR("volume")); |
| + if (volume == NULL) { |
| + CFRelease(device_properties); |
| + return false; |
| + } |
| + *location = FilePath("/Volumes/").Append(SysCFStringRefToUTF8(volume)); |
| + |
| + CFStringRef device_name = mac::GetValueFromDictionary<CFStringRef>( |
| + device_properties, CFSTR("ICAUserAssignedDeviceNameKey")); |
| + if (device_name == NULL) { |
| + device_name = mac::GetValueFromDictionary<CFStringRef>( |
| + device_properties, CFSTR("ifil")); |
| + } |
| + if (device_name == NULL) { |
| + CFRelease(device_properties); |
| + return false; |
| + } |
| + *name = SysCFStringRefToUTF8(device_name); |
| + |
| + CFRelease(device_properties); |
| + return true; |
| +} |
| + |
| +void MediaDeviceNotificationCallback(CFStringRef notification_type, |
| + CFDictionaryRef notification_dictionary) { |
| + bool attach = false; |
| + if (CFStringCompare(notification_type, kICANotificationTypeDeviceAdded, 0) == |
| + kCFCompareEqualTo) { |
| + attach = true; |
| + } else if (CFStringCompare(notification_type, |
| + kICANotificationTypeDeviceRemoved, 0) != |
| + kCFCompareEqualTo) { |
| + return; |
| + } |
| + CFNumberRef refcon_object = mac::GetValueFromDictionary<CFNumberRef>( |
| + notification_dictionary, kICARefconKey); |
| + unsigned long refcon; |
| + CFNumberGetValue(refcon_object, kCFNumberLongType, &refcon); |
| + SystemMonitor* system_monitor = reinterpret_cast<SystemMonitor*>(refcon); |
| + |
| + CFNumberRef device_number_object = mac::GetValueFromDictionary<CFNumberRef>( |
| + notification_dictionary, kICANotificationDeviceICAObjectKey); |
| + unsigned long device_number; |
| + CFNumberGetValue(device_number_object, kCFNumberIntType, &device_number); |
| + if (attach) { |
| + std::string device_name; |
| + FilePath location; |
| + if (GetDeviceInfo(device_number, &device_name, &location)) { |
| + system_monitor->ProcessMediaDeviceAttached(device_number, device_name, |
| + location); |
| + } |
| + } else { |
| + system_monitor->ProcessMediaDeviceDetached(device_number); |
| + } |
| +} |
| + |
| } // namespace |
| // The reason we can't include this code in the constructor is because |
| @@ -69,6 +141,20 @@ void SystemMonitor::PlatformInit() { |
| CFRunLoopGetCurrent(), |
| IONotificationPortGetRunLoopSource(g_notification_port_ref), |
| kCFRunLoopCommonModes); |
| + |
| + ICARegisterForEventNotificationPB notification_request; |
| + notification_request.header.refcon = reinterpret_cast<unsigned long>(this); |
| + notification_request.objectOfInterest = 0; // Zero means all objects |
| + CFStringRef events_of_interest_array[] = {kICANotificationTypeDeviceAdded, |
| + kICANotificationTypeDeviceRemoved}; |
| + CFArrayRef events_of_interest = |
| + CFArrayCreate(NULL, (const void**)&events_of_interest_array, 2, |
| + &kCFTypeArrayCallBacks); |
| + notification_request.eventsOfInterest = events_of_interest; |
| + notification_request.notificationProc = &MediaDeviceNotificationCallback; |
| + notification_request.options = NULL; |
| + OSErr err = ICARegisterForEventNotification(¬ification_request, NULL); |
| + CHECK_EQ(err, noErr); |
| } |
| void SystemMonitor::PlatformDestroy() { |