| 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..1e8e4f1da76512b0e95fd021927a88512625a990 100644
|
| --- a/base/system_monitor/system_monitor_mac.mm
|
| +++ b/base/system_monitor/system_monitor_mac.mm
|
| @@ -1,4 +1,4 @@
|
| -// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| @@ -7,9 +7,15 @@
|
|
|
| #include "base/system_monitor/system_monitor.h"
|
|
|
| +#include <Carbon/Carbon.h>
|
| +#include <CoreFoundation/CoreFoundation.h>
|
| #include <IOKit/pwr_mgt/IOPMLib.h>
|
| #include <IOKit/IOMessage.h>
|
|
|
| +#include "base/file_path.h"
|
| +#include "base/mac/foundation_util.h"
|
| +#include "base/sys_string_conversions.h"
|
| +
|
| namespace base {
|
|
|
| namespace {
|
| @@ -37,6 +43,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 +142,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() {
|
|
|