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

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

Powered by Google App Engine
This is Rietveld 408576698