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

Side by Side Diff: base/system_monitor/system_monitor_mac.mm

Issue 9363008: Add Media device notification to SystemMonitor and Mac impl (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Turns out, we want a number id on Windows too Created 8 years, 10 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 // Implementation based on sample code from 5 // Implementation based on sample code from
6 // http://developer.apple.com/library/mac/#qa/qa1340/_index.html. 6 // http://developer.apple.com/library/mac/#qa/qa1340/_index.html.
7 7
8 #include "base/system_monitor/system_monitor.h" 8 #include "base/system_monitor/system_monitor.h"
9 9
10 #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.
11 #include <CoreFoundation/CoreFoundation.h>
10 #include <IOKit/pwr_mgt/IOPMLib.h> 12 #include <IOKit/pwr_mgt/IOPMLib.h>
11 #include <IOKit/IOMessage.h> 13 #include <IOKit/IOMessage.h>
12 14
15 #include "base/mac/foundation_util.h"
16 #include "base/sys_string_conversions.h"
17
13 namespace base { 18 namespace base {
14 19
15 namespace { 20 namespace {
16 21
17 io_connect_t g_system_power_io_port = 0; 22 io_connect_t g_system_power_io_port = 0;
18 IONotificationPortRef g_notification_port_ref = 0; 23 IONotificationPortRef g_notification_port_ref = 0;
19 io_object_t g_notifier_object = 0; 24 io_object_t g_notifier_object = 0;
20 25
21 void SystemPowerEventCallback(void*, 26 void SystemPowerEventCallback(void*,
22 io_service_t service, 27 io_service_t service,
23 natural_t message_type, 28 natural_t message_type,
24 void* message_argument) { 29 void* message_argument) {
25 SystemMonitor* sys_monitor = SystemMonitor::Get(); 30 SystemMonitor* sys_monitor = SystemMonitor::Get();
26 DCHECK(sys_monitor); 31 DCHECK(sys_monitor);
27 switch (message_type) { 32 switch (message_type) {
28 case kIOMessageSystemWillSleep: 33 case kIOMessageSystemWillSleep:
29 sys_monitor->ProcessPowerMessage(SystemMonitor::SUSPEND_EVENT); 34 sys_monitor->ProcessPowerMessage(SystemMonitor::SUSPEND_EVENT);
30 IOAllowPowerChange(g_system_power_io_port, 35 IOAllowPowerChange(g_system_power_io_port,
31 reinterpret_cast<int>(message_argument)); 36 reinterpret_cast<int>(message_argument));
32 break; 37 break;
33 38
34 case kIOMessageSystemWillPowerOn: 39 case kIOMessageSystemWillPowerOn:
35 sys_monitor->ProcessPowerMessage(SystemMonitor::RESUME_EVENT); 40 sys_monitor->ProcessPowerMessage(SystemMonitor::RESUME_EVENT);
36 break; 41 break;
37 } 42 }
38 } 43 }
39 44
45 bool GetDeviceInfo(unsigned long device_number, std::string* name,
46 FilePath* location) {
47 ICACopyObjectPropertyDictionaryPB properties_request;
48 properties_request.object = device_number;
49 CFDictionaryRef device_properties;
50 properties_request.theDict = &device_properties;
51 OSErr ret = ICACopyObjectPropertyDictionary(&properties_request, NULL);
52 CHECK_EQ(ret, noErr);
53
54 // For now, we only support mass storage media devices.
55 CFStringRef volume = mac::GetValueFromDictionary<CFStringRef>(
56 device_properties, CFSTR("volume"));
57 if (volume == NULL) {
58 CFRelease(device_properties);
59 return false;
60 }
61 *location = FilePath("/Volumes/").Append(SysCFStringRefToUTF8(volume));
62
63 CFStringRef device_name = mac::GetValueFromDictionary<CFStringRef>(
64 device_properties, CFSTR("ICAUserAssignedDeviceNameKey"));
65 if (device_name == NULL) {
66 device_name = mac::GetValueFromDictionary<CFStringRef>(
67 device_properties, CFSTR("ifil"));
68 }
69 if (device_name == NULL) {
70 CFRelease(device_properties);
71 return false;
72 }
73 *name = SysCFStringRefToUTF8(device_name);
74
75 CFRelease(device_properties);
76 return true;
77 }
78
79 void MediaDeviceNotificationCallback(CFStringRef notification_type,
80 CFDictionaryRef notification_dictionary) {
81 bool attach = false;
82 if (CFStringCompare(notification_type, kICANotificationTypeDeviceAdded, 0) ==
83 kCFCompareEqualTo) {
84 attach = true;
85 } else if (CFStringCompare(notification_type,
86 kICANotificationTypeDeviceRemoved, 0) !=
87 kCFCompareEqualTo) {
88 return;
89 }
90 CFNumberRef refcon_object = mac::GetValueFromDictionary<CFNumberRef>(
91 notification_dictionary, kICARefconKey);
92 unsigned long refcon;
93 CFNumberGetValue(refcon_object, kCFNumberLongType, &refcon);
94 SystemMonitor* system_monitor = reinterpret_cast<SystemMonitor*>(refcon);
95
96 CFNumberRef device_number_object = mac::GetValueFromDictionary<CFNumberRef>(
97 notification_dictionary, kICANotificationDeviceICAObjectKey);
98 unsigned long device_number;
99 CFNumberGetValue(device_number_object, kCFNumberIntType, &device_number);
100 if (attach) {
101 std::string device_name;
102 FilePath location;
103 if (GetDeviceInfo(device_number, &device_name, &location)) {
104 system_monitor->ProcessMediaDeviceAttached(device_number, device_name,
105 location);
106 }
107 } else {
108 system_monitor->ProcessMediaDeviceDetached(device_number);
109 }
110 }
111
40 } // namespace 112 } // namespace
41 113
42 // The reason we can't include this code in the constructor is because 114 // The reason we can't include this code in the constructor is because
43 // PlatformInit() requires an active runloop and the IO port needs to be 115 // PlatformInit() requires an active runloop and the IO port needs to be
44 // allocated at sandbox initialization time, before there's a runloop. 116 // allocated at sandbox initialization time, before there's a runloop.
45 // See crbug.com/83783 . 117 // See crbug.com/83783 .
46 118
47 // static 119 // static
48 void SystemMonitor::AllocateSystemIOPorts() { 120 void SystemMonitor::AllocateSystemIOPorts() {
49 DCHECK_EQ(g_system_power_io_port, 0u); 121 DCHECK_EQ(g_system_power_io_port, 0u);
(...skipping 12 matching lines...) Expand all
62 // object. 134 // object.
63 DCHECK_NE(g_system_power_io_port, 0u); 135 DCHECK_NE(g_system_power_io_port, 0u);
64 if (g_system_power_io_port == 0) 136 if (g_system_power_io_port == 0)
65 return; 137 return;
66 138
67 // Add the notification port to the application runloop 139 // Add the notification port to the application runloop
68 CFRunLoopAddSource( 140 CFRunLoopAddSource(
69 CFRunLoopGetCurrent(), 141 CFRunLoopGetCurrent(),
70 IONotificationPortGetRunLoopSource(g_notification_port_ref), 142 IONotificationPortGetRunLoopSource(g_notification_port_ref),
71 kCFRunLoopCommonModes); 143 kCFRunLoopCommonModes);
144
145 ICARegisterForEventNotificationPB notification_request;
146 notification_request.header.refcon = reinterpret_cast<unsigned long>(this);
147 notification_request.objectOfInterest = 0; // Zero means all objects
148 CFStringRef events_of_interest_array[] = {kICANotificationTypeDeviceAdded,
149 kICANotificationTypeDeviceRemoved};
150 CFArrayRef events_of_interest =
151 CFArrayCreate(NULL, (const void**)&events_of_interest_array, 2,
152 &kCFTypeArrayCallBacks);
153 notification_request.eventsOfInterest = events_of_interest;
154 notification_request.notificationProc = &MediaDeviceNotificationCallback;
155 notification_request.options = NULL;
156 OSErr err = ICARegisterForEventNotification(&notification_request, NULL);
157 CHECK_EQ(err, noErr);
72 } 158 }
73 159
74 void SystemMonitor::PlatformDestroy() { 160 void SystemMonitor::PlatformDestroy() {
75 DCHECK_NE(g_system_power_io_port, 0u); 161 DCHECK_NE(g_system_power_io_port, 0u);
76 if (g_system_power_io_port == 0) 162 if (g_system_power_io_port == 0)
77 return; 163 return;
78 164
79 // Remove the sleep notification port from the application runloop 165 // Remove the sleep notification port from the application runloop
80 CFRunLoopRemoveSource( 166 CFRunLoopRemoveSource(
81 CFRunLoopGetCurrent(), 167 CFRunLoopGetCurrent(),
82 IONotificationPortGetRunLoopSource(g_notification_port_ref), 168 IONotificationPortGetRunLoopSource(g_notification_port_ref),
83 kCFRunLoopCommonModes); 169 kCFRunLoopCommonModes);
84 170
85 // Deregister for system sleep notifications 171 // Deregister for system sleep notifications
86 IODeregisterForSystemPower(&g_notifier_object); 172 IODeregisterForSystemPower(&g_notifier_object);
87 173
88 // IORegisterForSystemPower implicitly opens the Root Power Domain IOService, 174 // IORegisterForSystemPower implicitly opens the Root Power Domain IOService,
89 // so we close it here. 175 // so we close it here.
90 IOServiceClose(g_system_power_io_port); 176 IOServiceClose(g_system_power_io_port);
91 177
92 g_system_power_io_port = 0; 178 g_system_power_io_port = 0;
93 179
94 // Destroy the notification port allocated by IORegisterForSystemPower. 180 // Destroy the notification port allocated by IORegisterForSystemPower.
95 IONotificationPortDestroy(g_notification_port_ref); 181 IONotificationPortDestroy(g_notification_port_ref);
96 } 182 }
97 183
98 } // namespace base 184 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698