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 6192a2692429bb76d539782a6e89205e7ad980b0..baaadf052db913eb7f3c548f81c545901f6192e8 100644 |
--- a/base/system_monitor/system_monitor_mac.mm |
+++ b/base/system_monitor/system_monitor_mac.mm |
@@ -15,13 +15,15 @@ namespace base { |
namespace { |
io_connect_t g_system_power_io_port = 0; |
+IONotificationPortRef g_notification_port_ref = 0; |
+io_object_t g_notifier_object = 0; |
-void SystemPowerEventCallback(void* system_monitor, |
+void SystemPowerEventCallback(void*, |
io_service_t service, |
natural_t message_type, |
void* message_argument) { |
- DCHECK(system_monitor); |
- SystemMonitor* sys_monitor = reinterpret_cast<SystemMonitor*>(system_monitor); |
+ SystemMonitor* sys_monitor = SystemMonitor::Get(); |
+ DCHECK(sys_monitor); |
switch (message_type) { |
case kIOMessageSystemWillSleep: |
sys_monitor->ProcessPowerMessage(SystemMonitor::SUSPEND_EVENT); |
@@ -37,22 +39,36 @@ void SystemPowerEventCallback(void* system_monitor, |
} // namespace |
-void SystemMonitor::PlatformInit() { |
+// The reason we can't include this code in the constructor is because |
+// PlatformInit() requires an active runloop and the IO port needs to be |
+// allocated at sandbox initialization time, before there's a runloop. |
+// See crbug.com/83783 . |
+ |
+// static |
+void SystemMonitor::AllocateSystemIOPorts() { |
DCHECK_EQ(g_system_power_io_port, 0u); |
// Notification port allocated by IORegisterForSystemPower. |
g_system_power_io_port = IORegisterForSystemPower( |
- this, ¬ification_port_ref_, SystemPowerEventCallback, |
- ¬ifier_object_); |
+ NULL, &g_notification_port_ref, SystemPowerEventCallback, |
+ &g_notifier_object); |
+ |
+ DCHECK_NE(g_system_power_io_port, 0u); |
+} |
+ |
+void SystemMonitor::PlatformInit() { |
+ // Need to call AllocateSystemIOPorts() before constructing a SystemMonitor |
+ // object. |
DCHECK_NE(g_system_power_io_port, 0u); |
if (g_system_power_io_port == 0) |
return; |
// Add the notification port to the application runloop |
- CFRunLoopAddSource(CFRunLoopGetCurrent(), |
- IONotificationPortGetRunLoopSource(notification_port_ref_), |
- kCFRunLoopCommonModes); |
+ CFRunLoopAddSource( |
+ CFRunLoopGetCurrent(), |
+ IONotificationPortGetRunLoopSource(g_notification_port_ref), |
+ kCFRunLoopCommonModes); |
} |
void SystemMonitor::PlatformDestroy() { |
@@ -63,11 +79,11 @@ void SystemMonitor::PlatformDestroy() { |
// Remove the sleep notification port from the application runloop |
CFRunLoopRemoveSource( |
CFRunLoopGetCurrent(), |
- IONotificationPortGetRunLoopSource(notification_port_ref_), |
+ IONotificationPortGetRunLoopSource(g_notification_port_ref), |
kCFRunLoopCommonModes); |
// Deregister for system sleep notifications |
- IODeregisterForSystemPower(¬ifier_object_); |
+ IODeregisterForSystemPower(&g_notifier_object); |
// IORegisterForSystemPower implicitly opens the Root Power Domain IOService, |
// so we close it here. |
@@ -76,7 +92,7 @@ void SystemMonitor::PlatformDestroy() { |
g_system_power_io_port = 0; |
// Destroy the notification port allocated by IORegisterForSystemPower. |
- IONotificationPortDestroy(notification_port_ref_); |
+ IONotificationPortDestroy(g_notification_port_ref); |
} |
} // namespace base |