| OLD | NEW |
| 1 // Copyright (c) 2012 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 #import "base/message_loop/message_pump_mac.h" | 5 #import "base/message_loop/message_pump_mac.h" |
| 6 | 6 |
| 7 #import <Foundation/Foundation.h> | 7 #import <Foundation/Foundation.h> |
| 8 | 8 |
| 9 #include <limits> | 9 #include <limits> |
| 10 | 10 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 // Mode that only sees Chrome work sources. | 37 // Mode that only sees Chrome work sources. |
| 38 kMessageLoopExclusiveRunLoopMode, | 38 kMessageLoopExclusiveRunLoopMode, |
| 39 | 39 |
| 40 // Process work when NSMenus are fading out. | 40 // Process work when NSMenus are fading out. |
| 41 CFSTR("com.apple.hitoolbox.windows.windowfadingmode"), | 41 CFSTR("com.apple.hitoolbox.windows.windowfadingmode"), |
| 42 | 42 |
| 43 // Process work when AppKit is highlighting an item on the main menubar. | 43 // Process work when AppKit is highlighting an item on the main menubar. |
| 44 CFSTR("NSUnhighlightMenuRunLoopMode"), | 44 CFSTR("NSUnhighlightMenuRunLoopMode"), |
| 45 }; | 45 }; |
| 46 | 46 |
| 47 void CFRunLoopAddSourceToAllModes(CFRunLoopRef rl, CFRunLoopSourceRef source) { | 47 // Mask that determines which modes in |kAllModes| to use. |
| 48 for (const CFStringRef& mode : kAllModes) | 48 enum { kCommonModeMask = 0x1, kAllModesMask = ~0 }; |
| 49 CFRunLoopAddSource(rl, source, mode); | |
| 50 } | |
| 51 | |
| 52 void CFRunLoopRemoveSourceFromAllModes(CFRunLoopRef rl, | |
| 53 CFRunLoopSourceRef source) { | |
| 54 for (const CFStringRef& mode : kAllModes) | |
| 55 CFRunLoopRemoveSource(rl, source, mode); | |
| 56 } | |
| 57 | |
| 58 void CFRunLoopAddTimerToAllModes(CFRunLoopRef rl, CFRunLoopTimerRef timer) { | |
| 59 for (const CFStringRef& mode : kAllModes) | |
| 60 CFRunLoopAddTimer(rl, timer, mode); | |
| 61 } | |
| 62 | |
| 63 void CFRunLoopRemoveTimerFromAllModes(CFRunLoopRef rl, | |
| 64 CFRunLoopTimerRef timer) { | |
| 65 for (const CFStringRef& mode : kAllModes) | |
| 66 CFRunLoopRemoveTimer(rl, timer, mode); | |
| 67 } | |
| 68 | |
| 69 void CFRunLoopAddObserverToAllModes(CFRunLoopRef rl, | |
| 70 CFRunLoopObserverRef observer) { | |
| 71 for (const CFStringRef& mode : kAllModes) | |
| 72 CFRunLoopAddObserver(rl, observer, mode); | |
| 73 } | |
| 74 | |
| 75 void CFRunLoopRemoveObserverFromAllModes(CFRunLoopRef rl, | |
| 76 CFRunLoopObserverRef observer) { | |
| 77 for (const CFStringRef& mode : kAllModes) | |
| 78 CFRunLoopRemoveObserver(rl, observer, mode); | |
| 79 } | |
| 80 | 49 |
| 81 void NoOp(void* info) { | 50 void NoOp(void* info) { |
| 82 } | 51 } |
| 83 | 52 |
| 84 const CFTimeInterval kCFTimeIntervalMax = | 53 const CFTimeInterval kCFTimeIntervalMax = |
| 85 std::numeric_limits<CFTimeInterval>::max(); | 54 std::numeric_limits<CFTimeInterval>::max(); |
| 86 | 55 |
| 87 #if !defined(OS_IOS) | 56 #if !defined(OS_IOS) |
| 88 // Set to true if MessagePumpMac::Create() is called before NSApp is | 57 // Set to true if MessagePumpMac::Create() is called before NSApp is |
| 89 // initialized. Only accessed from the main thread. | 58 // initialized. Only accessed from the main thread. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 } | 116 } |
| 148 ~MessagePumpScopedAutoreleasePool() { | 117 ~MessagePumpScopedAutoreleasePool() { |
| 149 [pool_ drain]; | 118 [pool_ drain]; |
| 150 } | 119 } |
| 151 | 120 |
| 152 private: | 121 private: |
| 153 NSAutoreleasePool* pool_; | 122 NSAutoreleasePool* pool_; |
| 154 DISALLOW_COPY_AND_ASSIGN(MessagePumpScopedAutoreleasePool); | 123 DISALLOW_COPY_AND_ASSIGN(MessagePumpScopedAutoreleasePool); |
| 155 }; | 124 }; |
| 156 | 125 |
| 157 #if !defined(OS_IOS) | 126 // Must be called on the run loop thread. |
| 158 // This function uses private API to modify a test timer's valid state and | 127 void MessagePumpCFRunLoopBase::Run(Delegate* delegate) { |
| 159 // uses public API to confirm that the private API changed the correct bit. | 128 // nesting_level_ will be incremented in EnterExitRunLoop, so set |
| 160 // static | 129 // run_nesting_level_ accordingly. |
| 161 bool MessagePumpCFRunLoopBase::CanInvalidateCFRunLoopTimers() { | 130 int last_run_nesting_level = run_nesting_level_; |
| 162 CFRunLoopTimerContext timer_context = CFRunLoopTimerContext(); | 131 run_nesting_level_ = nesting_level_ + 1; |
| 163 timer_context.info = nullptr; | 132 |
| 164 ScopedCFTypeRef<CFRunLoopTimerRef> test_timer( | 133 Delegate* last_delegate = delegate_; |
| 165 CFRunLoopTimerCreate(NULL, // allocator | 134 SetDelegate(delegate); |
| 166 kCFTimeIntervalMax, // fire time | 135 |
| 167 kCFTimeIntervalMax, // interval | 136 DoRun(delegate); |
| 168 0, // flags | 137 |
| 169 0, // priority | 138 // Restore the previous state of the object. |
| 170 nullptr, &timer_context)); | 139 SetDelegate(last_delegate); |
| 171 // Should be valid from the start. | 140 run_nesting_level_ = last_run_nesting_level; |
| 172 if (!CFRunLoopTimerIsValid(test_timer)) { | |
| 173 return false; | |
| 174 } | |
| 175 // Confirm that the private API can mark the timer invalid. | |
| 176 __ChromeCFRunLoopTimerSetValid(test_timer, false); | |
| 177 if (CFRunLoopTimerIsValid(test_timer)) { | |
| 178 return false; | |
| 179 } | |
| 180 // Confirm that the private API can mark the timer valid. | |
| 181 __ChromeCFRunLoopTimerSetValid(test_timer, true); | |
| 182 return CFRunLoopTimerIsValid(test_timer); | |
| 183 } | 141 } |
| 184 #endif // !defined(OS_IOS) | |
| 185 | 142 |
| 186 // static | 143 // May be called on any thread. |
| 187 void MessagePumpCFRunLoopBase::ChromeCFRunLoopTimerSetValid( | 144 void MessagePumpCFRunLoopBase::ScheduleWork() { |
| 188 CFRunLoopTimerRef timer, | 145 CFRunLoopSourceSignal(work_source_); |
| 189 bool valid) { | 146 CFRunLoopWakeUp(run_loop_); |
| 190 #if !defined(OS_IOS) | |
| 191 static bool can_invalidate_timers = CanInvalidateCFRunLoopTimers(); | |
| 192 if (can_invalidate_timers) { | |
| 193 __ChromeCFRunLoopTimerSetValid(timer, valid); | |
| 194 } | |
| 195 #endif // !defined(OS_IOS) | |
| 196 } | 147 } |
| 197 | 148 |
| 198 // Must be called on the run loop thread. | 149 // Must be called on the run loop thread. |
| 199 MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase() | 150 void MessagePumpCFRunLoopBase::ScheduleDelayedWork( |
| 200 : delegate_(NULL), | 151 const TimeTicks& delayed_work_time) { |
| 152 TimeDelta delta = delayed_work_time - TimeTicks::Now(); |
| 153 delayed_work_fire_time_ = CFAbsoluteTimeGetCurrent() + delta.InSecondsF(); |
| 154 |
| 155 // Flip the timer's validation bit just before setting the new fire time. Do |
| 156 // this now because CFRunLoopTimerSetNextFireDate() likely checks the validity |
| 157 // of a timer before proceeding to set its fire date. Making the timer valid |
| 158 // now won't have any side effects (such as a premature firing of the timer) |
| 159 // because we're only flipping a bit. |
| 160 // |
| 161 // Please see the comment in RunDelayedWorkTimer() for more info on the whys |
| 162 // of invalidation. |
| 163 ChromeCFRunLoopTimerSetValid(delayed_work_timer_, true); |
| 164 |
| 165 CFRunLoopTimerSetNextFireDate(delayed_work_timer_, delayed_work_fire_time_); |
| 166 if (timer_slack_ == TIMER_SLACK_MAXIMUM) { |
| 167 CFRunLoopTimerSetTolerance(delayed_work_timer_, delta.InSecondsF() * 0.5); |
| 168 } else { |
| 169 CFRunLoopTimerSetTolerance(delayed_work_timer_, 0); |
| 170 } |
| 171 } |
| 172 |
| 173 void MessagePumpCFRunLoopBase::SetTimerSlack(TimerSlack timer_slack) { |
| 174 timer_slack_ = timer_slack; |
| 175 } |
| 176 |
| 177 // Must be called on the run loop thread. |
| 178 MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase(int mode_mask) |
| 179 : mode_mask_(mode_mask), |
| 180 delegate_(NULL), |
| 201 delayed_work_fire_time_(kCFTimeIntervalMax), | 181 delayed_work_fire_time_(kCFTimeIntervalMax), |
| 202 timer_slack_(base::TIMER_SLACK_NONE), | 182 timer_slack_(base::TIMER_SLACK_NONE), |
| 203 nesting_level_(0), | 183 nesting_level_(0), |
| 204 run_nesting_level_(0), | 184 run_nesting_level_(0), |
| 205 deepest_nesting_level_(0), | 185 deepest_nesting_level_(0), |
| 206 delegateless_work_(false), | 186 delegateless_work_(false), |
| 207 delegateless_idle_work_(false) { | 187 delegateless_idle_work_(false) { |
| 208 run_loop_ = CFRunLoopGetCurrent(); | 188 run_loop_ = CFRunLoopGetCurrent(); |
| 209 CFRetain(run_loop_); | 189 CFRetain(run_loop_); |
| 210 | 190 |
| 211 // Set a repeating timer with a preposterous firing time and interval. The | 191 // Set a repeating timer with a preposterous firing time and interval. The |
| 212 // timer will effectively never fire as-is. The firing time will be adjusted | 192 // timer will effectively never fire as-is. The firing time will be adjusted |
| 213 // as needed when ScheduleDelayedWork is called. | 193 // as needed when ScheduleDelayedWork is called. |
| 214 CFRunLoopTimerContext timer_context = CFRunLoopTimerContext(); | 194 CFRunLoopTimerContext timer_context = CFRunLoopTimerContext(); |
| 215 timer_context.info = this; | 195 timer_context.info = this; |
| 216 delayed_work_timer_ = CFRunLoopTimerCreate(NULL, // allocator | 196 delayed_work_timer_ = CFRunLoopTimerCreate(NULL, // allocator |
| 217 kCFTimeIntervalMax, // fire time | 197 kCFTimeIntervalMax, // fire time |
| 218 kCFTimeIntervalMax, // interval | 198 kCFTimeIntervalMax, // interval |
| 219 0, // flags | 199 0, // flags |
| 220 0, // priority | 200 0, // priority |
| 221 RunDelayedWorkTimer, | 201 RunDelayedWorkTimer, |
| 222 &timer_context); | 202 &timer_context); |
| 223 CFRunLoopAddTimerToAllModes(run_loop_, delayed_work_timer_); | 203 InvokeForEnabledModes(&CFRunLoopAddTimer, delayed_work_timer_); |
| 224 | 204 |
| 225 CFRunLoopSourceContext source_context = CFRunLoopSourceContext(); | 205 CFRunLoopSourceContext source_context = CFRunLoopSourceContext(); |
| 226 source_context.info = this; | 206 source_context.info = this; |
| 227 source_context.perform = RunWorkSource; | 207 source_context.perform = RunWorkSource; |
| 228 work_source_ = CFRunLoopSourceCreate(NULL, // allocator | 208 work_source_ = CFRunLoopSourceCreate(NULL, // allocator |
| 229 1, // priority | 209 1, // priority |
| 230 &source_context); | 210 &source_context); |
| 231 CFRunLoopAddSourceToAllModes(run_loop_, work_source_); | 211 InvokeForEnabledModes(&CFRunLoopAddSource, work_source_); |
| 232 | 212 |
| 233 source_context.perform = RunIdleWorkSource; | 213 source_context.perform = RunIdleWorkSource; |
| 234 idle_work_source_ = CFRunLoopSourceCreate(NULL, // allocator | 214 idle_work_source_ = CFRunLoopSourceCreate(NULL, // allocator |
| 235 2, // priority | 215 2, // priority |
| 236 &source_context); | 216 &source_context); |
| 237 CFRunLoopAddSourceToAllModes(run_loop_, idle_work_source_); | 217 InvokeForEnabledModes(&CFRunLoopAddSource, idle_work_source_); |
| 238 | 218 |
| 239 source_context.perform = RunNestingDeferredWorkSource; | 219 source_context.perform = RunNestingDeferredWorkSource; |
| 240 nesting_deferred_work_source_ = CFRunLoopSourceCreate(NULL, // allocator | 220 nesting_deferred_work_source_ = CFRunLoopSourceCreate(NULL, // allocator |
| 241 0, // priority | 221 0, // priority |
| 242 &source_context); | 222 &source_context); |
| 243 CFRunLoopAddSourceToAllModes(run_loop_, nesting_deferred_work_source_); | 223 InvokeForEnabledModes(&CFRunLoopAddSource, nesting_deferred_work_source_); |
| 244 | 224 |
| 245 CFRunLoopObserverContext observer_context = CFRunLoopObserverContext(); | 225 CFRunLoopObserverContext observer_context = CFRunLoopObserverContext(); |
| 246 observer_context.info = this; | 226 observer_context.info = this; |
| 247 pre_wait_observer_ = CFRunLoopObserverCreate(NULL, // allocator | 227 pre_wait_observer_ = CFRunLoopObserverCreate(NULL, // allocator |
| 248 kCFRunLoopBeforeWaiting, | 228 kCFRunLoopBeforeWaiting, |
| 249 true, // repeat | 229 true, // repeat |
| 250 0, // priority | 230 0, // priority |
| 251 PreWaitObserver, | 231 PreWaitObserver, |
| 252 &observer_context); | 232 &observer_context); |
| 253 CFRunLoopAddObserverToAllModes(run_loop_, pre_wait_observer_); | 233 InvokeForEnabledModes(&CFRunLoopAddObserver, pre_wait_observer_); |
| 254 | 234 |
| 255 pre_source_observer_ = CFRunLoopObserverCreate(NULL, // allocator | 235 pre_source_observer_ = CFRunLoopObserverCreate(NULL, // allocator |
| 256 kCFRunLoopBeforeSources, | 236 kCFRunLoopBeforeSources, |
| 257 true, // repeat | 237 true, // repeat |
| 258 0, // priority | 238 0, // priority |
| 259 PreSourceObserver, | 239 PreSourceObserver, |
| 260 &observer_context); | 240 &observer_context); |
| 261 CFRunLoopAddObserverToAllModes(run_loop_, pre_source_observer_); | 241 InvokeForEnabledModes(&CFRunLoopAddObserver, pre_source_observer_); |
| 262 | 242 |
| 263 enter_exit_observer_ = CFRunLoopObserverCreate(NULL, // allocator | 243 enter_exit_observer_ = CFRunLoopObserverCreate(NULL, // allocator |
| 264 kCFRunLoopEntry | | 244 kCFRunLoopEntry | |
| 265 kCFRunLoopExit, | 245 kCFRunLoopExit, |
| 266 true, // repeat | 246 true, // repeat |
| 267 0, // priority | 247 0, // priority |
| 268 EnterExitObserver, | 248 EnterExitObserver, |
| 269 &observer_context); | 249 &observer_context); |
| 270 CFRunLoopAddObserverToAllModes(run_loop_, enter_exit_observer_); | 250 InvokeForEnabledModes(&CFRunLoopAddObserver, enter_exit_observer_); |
| 271 } | 251 } |
| 272 | 252 |
| 273 // Ideally called on the run loop thread. If other run loops were running | 253 // Ideally called on the run loop thread. If other run loops were running |
| 274 // lower on the run loop thread's stack when this object was created, the | 254 // lower on the run loop thread's stack when this object was created, the |
| 275 // same number of run loops must be running when this object is destroyed. | 255 // same number of run loops must be running when this object is destroyed. |
| 276 MessagePumpCFRunLoopBase::~MessagePumpCFRunLoopBase() { | 256 MessagePumpCFRunLoopBase::~MessagePumpCFRunLoopBase() { |
| 277 CFRunLoopRemoveObserverFromAllModes(run_loop_, enter_exit_observer_); | 257 for (const CFRunLoopObserverRef& observer : |
| 278 CFRelease(enter_exit_observer_); | 258 {enter_exit_observer_, pre_source_observer_, pre_wait_observer_}) { |
| 279 | 259 InvokeForEnabledModes(&CFRunLoopRemoveObserver, observer); |
| 280 CFRunLoopRemoveObserverFromAllModes(run_loop_, pre_source_observer_); | 260 CFRelease(observer); |
| 281 CFRelease(pre_source_observer_); | 261 } |
| 282 | 262 for (const CFRunLoopSourceRef& source : |
| 283 CFRunLoopRemoveObserverFromAllModes(run_loop_, pre_wait_observer_); | 263 {nesting_deferred_work_source_, idle_work_source_, work_source_}) { |
| 284 CFRelease(pre_wait_observer_); | 264 InvokeForEnabledModes(&CFRunLoopRemoveSource, source); |
| 285 | 265 CFRelease(source); |
| 286 CFRunLoopRemoveSourceFromAllModes(run_loop_, nesting_deferred_work_source_); | 266 } |
| 287 CFRelease(nesting_deferred_work_source_); | 267 InvokeForEnabledModes(&CFRunLoopRemoveTimer, delayed_work_timer_); |
| 288 | |
| 289 CFRunLoopRemoveSourceFromAllModes(run_loop_, idle_work_source_); | |
| 290 CFRelease(idle_work_source_); | |
| 291 | |
| 292 CFRunLoopRemoveSourceFromAllModes(run_loop_, work_source_); | |
| 293 CFRelease(work_source_); | |
| 294 | |
| 295 CFRunLoopRemoveTimerFromAllModes(run_loop_, delayed_work_timer_); | |
| 296 CFRelease(delayed_work_timer_); | 268 CFRelease(delayed_work_timer_); |
| 297 | |
| 298 CFRelease(run_loop_); | 269 CFRelease(run_loop_); |
| 299 } | 270 } |
| 300 | 271 |
| 301 // Must be called on the run loop thread. | |
| 302 void MessagePumpCFRunLoopBase::Run(Delegate* delegate) { | |
| 303 // nesting_level_ will be incremented in EnterExitRunLoop, so set | |
| 304 // run_nesting_level_ accordingly. | |
| 305 int last_run_nesting_level = run_nesting_level_; | |
| 306 run_nesting_level_ = nesting_level_ + 1; | |
| 307 | |
| 308 Delegate* last_delegate = delegate_; | |
| 309 SetDelegate(delegate); | |
| 310 | |
| 311 DoRun(delegate); | |
| 312 | |
| 313 // Restore the previous state of the object. | |
| 314 SetDelegate(last_delegate); | |
| 315 run_nesting_level_ = last_run_nesting_level; | |
| 316 } | |
| 317 | |
| 318 void MessagePumpCFRunLoopBase::SetDelegate(Delegate* delegate) { | 272 void MessagePumpCFRunLoopBase::SetDelegate(Delegate* delegate) { |
| 319 delegate_ = delegate; | 273 delegate_ = delegate; |
| 320 | 274 |
| 321 if (delegate) { | 275 if (delegate) { |
| 322 // If any work showed up but could not be dispatched for want of a | 276 // If any work showed up but could not be dispatched for want of a |
| 323 // delegate, set it up for dispatch again now that a delegate is | 277 // delegate, set it up for dispatch again now that a delegate is |
| 324 // available. | 278 // available. |
| 325 if (delegateless_work_) { | 279 if (delegateless_work_) { |
| 326 CFRunLoopSourceSignal(work_source_); | 280 CFRunLoopSourceSignal(work_source_); |
| 327 delegateless_work_ = false; | 281 delegateless_work_ = false; |
| 328 } | 282 } |
| 329 if (delegateless_idle_work_) { | 283 if (delegateless_idle_work_) { |
| 330 CFRunLoopSourceSignal(idle_work_source_); | 284 CFRunLoopSourceSignal(idle_work_source_); |
| 331 delegateless_idle_work_ = false; | 285 delegateless_idle_work_ = false; |
| 332 } | 286 } |
| 333 } | 287 } |
| 334 } | 288 } |
| 335 | 289 |
| 336 // May be called on any thread. | 290 // Base version returns a standard NSAutoreleasePool. |
| 337 void MessagePumpCFRunLoopBase::ScheduleWork() { | 291 AutoreleasePoolType* MessagePumpCFRunLoopBase::CreateAutoreleasePool() { |
| 338 CFRunLoopSourceSignal(work_source_); | 292 return [[NSAutoreleasePool alloc] init]; |
| 339 CFRunLoopWakeUp(run_loop_); | |
| 340 } | 293 } |
| 341 | 294 |
| 342 // Must be called on the run loop thread. | 295 template <typename Argument> |
| 343 void MessagePumpCFRunLoopBase::ScheduleDelayedWork( | 296 void MessagePumpCFRunLoopBase::InvokeForEnabledModes(void method(CFRunLoopRef, |
| 344 const TimeTicks& delayed_work_time) { | 297 Argument, |
| 345 TimeDelta delta = delayed_work_time - TimeTicks::Now(); | 298 CFStringRef), |
| 346 delayed_work_fire_time_ = CFAbsoluteTimeGetCurrent() + delta.InSecondsF(); | 299 Argument argument) { |
| 347 | 300 for (size_t i = 0; i < arraysize(kAllModes); ++i) { |
| 348 // Flip the timer's validation bit just before setting the new fire time. Do | 301 if (mode_mask_ & (0x1 << i)) |
| 349 // this now because CFRunLoopTimerSetNextFireDate() likely checks the validity | 302 method(run_loop_, argument, kAllModes[i]); |
| 350 // of a timer before proceeding to set its fire date. Making the timer valid | |
| 351 // now won't have any side effects (such as a premature firing of the timer) | |
| 352 // because we're only flipping a bit. | |
| 353 // | |
| 354 // Please see the comment in RunDelayedWorkTimer() for more info on the whys | |
| 355 // of invalidation. | |
| 356 ChromeCFRunLoopTimerSetValid(delayed_work_timer_, true); | |
| 357 | |
| 358 CFRunLoopTimerSetNextFireDate(delayed_work_timer_, delayed_work_fire_time_); | |
| 359 if (timer_slack_ == TIMER_SLACK_MAXIMUM) { | |
| 360 CFRunLoopTimerSetTolerance(delayed_work_timer_, delta.InSecondsF() * 0.5); | |
| 361 } else { | |
| 362 CFRunLoopTimerSetTolerance(delayed_work_timer_, 0); | |
| 363 } | 303 } |
| 364 } | 304 } |
| 365 | 305 |
| 366 void MessagePumpCFRunLoopBase::SetTimerSlack(TimerSlack timer_slack) { | 306 #if !defined(OS_IOS) |
| 367 timer_slack_ = timer_slack; | 307 // This function uses private API to modify a test timer's valid state and |
| 308 // uses public API to confirm that the private API changed the correct bit. |
| 309 // static |
| 310 bool MessagePumpCFRunLoopBase::CanInvalidateCFRunLoopTimers() { |
| 311 CFRunLoopTimerContext timer_context = CFRunLoopTimerContext(); |
| 312 timer_context.info = nullptr; |
| 313 ScopedCFTypeRef<CFRunLoopTimerRef> test_timer( |
| 314 CFRunLoopTimerCreate(NULL, // allocator |
| 315 kCFTimeIntervalMax, // fire time |
| 316 kCFTimeIntervalMax, // interval |
| 317 0, // flags |
| 318 0, // priority |
| 319 nullptr, &timer_context)); |
| 320 // Should be valid from the start. |
| 321 if (!CFRunLoopTimerIsValid(test_timer)) { |
| 322 return false; |
| 323 } |
| 324 // Confirm that the private API can mark the timer invalid. |
| 325 __ChromeCFRunLoopTimerSetValid(test_timer, false); |
| 326 if (CFRunLoopTimerIsValid(test_timer)) { |
| 327 return false; |
| 328 } |
| 329 // Confirm that the private API can mark the timer valid. |
| 330 __ChromeCFRunLoopTimerSetValid(test_timer, true); |
| 331 return CFRunLoopTimerIsValid(test_timer); |
| 332 } |
| 333 #endif // !defined(OS_IOS) |
| 334 |
| 335 // static |
| 336 void MessagePumpCFRunLoopBase::ChromeCFRunLoopTimerSetValid( |
| 337 CFRunLoopTimerRef timer, |
| 338 bool valid) { |
| 339 #if !defined(OS_IOS) |
| 340 static bool can_invalidate_timers = CanInvalidateCFRunLoopTimers(); |
| 341 if (can_invalidate_timers) { |
| 342 __ChromeCFRunLoopTimerSetValid(timer, valid); |
| 343 } |
| 344 #endif // !defined(OS_IOS) |
| 368 } | 345 } |
| 369 | 346 |
| 370 // Called from the run loop. | 347 // Called from the run loop. |
| 371 // static | 348 // static |
| 372 void MessagePumpCFRunLoopBase::RunDelayedWorkTimer(CFRunLoopTimerRef timer, | 349 void MessagePumpCFRunLoopBase::RunDelayedWorkTimer(CFRunLoopTimerRef timer, |
| 373 void* info) { | 350 void* info) { |
| 374 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); | 351 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); |
| 375 | 352 |
| 376 // The timer won't fire again until it's reset. | 353 // The timer won't fire again until it's reset. |
| 377 self->delayed_work_fire_time_ = kCFTimeIntervalMax; | 354 self->delayed_work_fire_time_ = kCFTimeIntervalMax; |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 632 base::mac::CallWithEHFrame(^{ | 609 base::mac::CallWithEHFrame(^{ |
| 633 self->EnterExitRunLoop(activity); | 610 self->EnterExitRunLoop(activity); |
| 634 }); | 611 }); |
| 635 } | 612 } |
| 636 | 613 |
| 637 // Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default | 614 // Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default |
| 638 // implementation is a no-op. | 615 // implementation is a no-op. |
| 639 void MessagePumpCFRunLoopBase::EnterExitRunLoop(CFRunLoopActivity activity) { | 616 void MessagePumpCFRunLoopBase::EnterExitRunLoop(CFRunLoopActivity activity) { |
| 640 } | 617 } |
| 641 | 618 |
| 642 // Base version returns a standard NSAutoreleasePool. | |
| 643 AutoreleasePoolType* MessagePumpCFRunLoopBase::CreateAutoreleasePool() { | |
| 644 return [[NSAutoreleasePool alloc] init]; | |
| 645 } | |
| 646 | |
| 647 MessagePumpCFRunLoop::MessagePumpCFRunLoop() | 619 MessagePumpCFRunLoop::MessagePumpCFRunLoop() |
| 648 : quit_pending_(false) { | 620 : MessagePumpCFRunLoopBase(kCommonModeMask), quit_pending_(false) {} |
| 649 } | |
| 650 | 621 |
| 651 MessagePumpCFRunLoop::~MessagePumpCFRunLoop() {} | 622 MessagePumpCFRunLoop::~MessagePumpCFRunLoop() {} |
| 652 | 623 |
| 653 // Called by MessagePumpCFRunLoopBase::DoRun. If other CFRunLoopRun loops were | 624 // Called by MessagePumpCFRunLoopBase::DoRun. If other CFRunLoopRun loops were |
| 654 // running lower on the run loop thread's stack when this object was created, | 625 // running lower on the run loop thread's stack when this object was created, |
| 655 // the same number of CFRunLoopRun loops must be running for the outermost call | 626 // the same number of CFRunLoopRun loops must be running for the outermost call |
| 656 // to Run. Run/DoRun are reentrant after that point. | 627 // to Run. Run/DoRun are reentrant after that point. |
| 657 void MessagePumpCFRunLoop::DoRun(Delegate* delegate) { | 628 void MessagePumpCFRunLoop::DoRun(Delegate* delegate) { |
| 658 // This is completely identical to calling CFRunLoopRun(), except autorelease | 629 // This is completely identical to calling CFRunLoopRun(), except autorelease |
| 659 // pool management is introduced. | 630 // pool management is introduced. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 690 // Quit was called while loops other than those managed by this object | 661 // Quit was called while loops other than those managed by this object |
| 691 // were running further inside a run loop managed by this object. Now | 662 // were running further inside a run loop managed by this object. Now |
| 692 // that all unmanaged inner run loops are gone, stop the loop running | 663 // that all unmanaged inner run loops are gone, stop the loop running |
| 693 // just inside Run. | 664 // just inside Run. |
| 694 CFRunLoopStop(run_loop()); | 665 CFRunLoopStop(run_loop()); |
| 695 quit_pending_ = false; | 666 quit_pending_ = false; |
| 696 } | 667 } |
| 697 } | 668 } |
| 698 | 669 |
| 699 MessagePumpNSRunLoop::MessagePumpNSRunLoop() | 670 MessagePumpNSRunLoop::MessagePumpNSRunLoop() |
| 700 : keep_running_(true) { | 671 : MessagePumpCFRunLoopBase(kCommonModeMask), keep_running_(true) { |
| 701 CFRunLoopSourceContext source_context = CFRunLoopSourceContext(); | 672 CFRunLoopSourceContext source_context = CFRunLoopSourceContext(); |
| 702 source_context.perform = NoOp; | 673 source_context.perform = NoOp; |
| 703 quit_source_ = CFRunLoopSourceCreate(NULL, // allocator | 674 quit_source_ = CFRunLoopSourceCreate(NULL, // allocator |
| 704 0, // priority | 675 0, // priority |
| 705 &source_context); | 676 &source_context); |
| 706 CFRunLoopAddSourceToAllModes(run_loop(), quit_source_); | 677 InvokeForEnabledModes(&CFRunLoopAddSource, quit_source_); |
| 707 } | 678 } |
| 708 | 679 |
| 709 MessagePumpNSRunLoop::~MessagePumpNSRunLoop() { | 680 MessagePumpNSRunLoop::~MessagePumpNSRunLoop() { |
| 710 CFRunLoopRemoveSourceFromAllModes(run_loop(), quit_source_); | 681 InvokeForEnabledModes(&CFRunLoopRemoveSource, quit_source_); |
| 711 CFRelease(quit_source_); | 682 CFRelease(quit_source_); |
| 712 } | 683 } |
| 713 | 684 |
| 714 void MessagePumpNSRunLoop::DoRun(Delegate* delegate) { | 685 void MessagePumpNSRunLoop::DoRun(Delegate* delegate) { |
| 715 while (keep_running_) { | 686 while (keep_running_) { |
| 716 // NSRunLoop manages autorelease pools itself. | 687 // NSRunLoop manages autorelease pools itself. |
| 717 [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode | 688 [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode |
| 718 beforeDate:[NSDate distantFuture]]; | 689 beforeDate:[NSDate distantFuture]]; |
| 719 } | 690 } |
| 720 | 691 |
| 721 keep_running_ = true; | 692 keep_running_ = true; |
| 722 } | 693 } |
| 723 | 694 |
| 724 void MessagePumpNSRunLoop::Quit() { | 695 void MessagePumpNSRunLoop::Quit() { |
| 725 keep_running_ = false; | 696 keep_running_ = false; |
| 726 CFRunLoopSourceSignal(quit_source_); | 697 CFRunLoopSourceSignal(quit_source_); |
| 727 CFRunLoopWakeUp(run_loop()); | 698 CFRunLoopWakeUp(run_loop()); |
| 728 } | 699 } |
| 729 | 700 |
| 730 #if defined(OS_IOS) | 701 #if defined(OS_IOS) |
| 731 MessagePumpUIApplication::MessagePumpUIApplication() | 702 MessagePumpUIApplication::MessagePumpUIApplication() |
| 732 : run_loop_(NULL) { | 703 : MessagePumpCFRunLoopBase(kCommonModeMask), run_loop_(NULL) {} |
| 733 } | |
| 734 | 704 |
| 735 MessagePumpUIApplication::~MessagePumpUIApplication() {} | 705 MessagePumpUIApplication::~MessagePumpUIApplication() {} |
| 736 | 706 |
| 737 void MessagePumpUIApplication::DoRun(Delegate* delegate) { | 707 void MessagePumpUIApplication::DoRun(Delegate* delegate) { |
| 738 NOTREACHED(); | 708 NOTREACHED(); |
| 739 } | 709 } |
| 740 | 710 |
| 741 void MessagePumpUIApplication::Quit() { | 711 void MessagePumpUIApplication::Quit() { |
| 742 NOTREACHED(); | 712 NOTREACHED(); |
| 743 } | 713 } |
| 744 | 714 |
| 745 void MessagePumpUIApplication::Attach(Delegate* delegate) { | 715 void MessagePumpUIApplication::Attach(Delegate* delegate) { |
| 746 DCHECK(!run_loop_); | 716 DCHECK(!run_loop_); |
| 747 run_loop_ = new RunLoop(); | 717 run_loop_ = new RunLoop(); |
| 748 CHECK(run_loop_->BeforeRun()); | 718 CHECK(run_loop_->BeforeRun()); |
| 749 SetDelegate(delegate); | 719 SetDelegate(delegate); |
| 750 } | 720 } |
| 751 | 721 |
| 752 #else | 722 #else |
| 753 | 723 |
| 754 MessagePumpNSApplication::MessagePumpNSApplication() | 724 MessagePumpNSApplication::MessagePumpNSApplication() |
| 755 : keep_running_(true), | 725 : MessagePumpCFRunLoopBase(kAllModesMask), |
| 756 running_own_loop_(false) { | 726 keep_running_(true), |
| 757 } | 727 running_own_loop_(false) {} |
| 758 | 728 |
| 759 MessagePumpNSApplication::~MessagePumpNSApplication() {} | 729 MessagePumpNSApplication::~MessagePumpNSApplication() {} |
| 760 | 730 |
| 761 void MessagePumpNSApplication::DoRun(Delegate* delegate) { | 731 void MessagePumpNSApplication::DoRun(Delegate* delegate) { |
| 762 bool last_running_own_loop_ = running_own_loop_; | 732 bool last_running_own_loop_ = running_own_loop_; |
| 763 | 733 |
| 764 // NSApp must be initialized by calling: | 734 // NSApp must be initialized by calling: |
| 765 // [{some class which implements CrAppProtocol} sharedApplication] | 735 // [{some class which implements CrAppProtocol} sharedApplication] |
| 766 // Most likely candidates are CrApplication or BrowserCrApplication. | 736 // Most likely candidates are CrApplication or BrowserCrApplication. |
| 767 // These can be initialized from C++ code by calling | 737 // These can be initialized from C++ code by calling |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 [NSApplication sharedApplication]; | 863 [NSApplication sharedApplication]; |
| 894 g_not_using_cr_app = true; | 864 g_not_using_cr_app = true; |
| 895 return new MessagePumpNSApplication; | 865 return new MessagePumpNSApplication; |
| 896 #endif | 866 #endif |
| 897 } | 867 } |
| 898 | 868 |
| 899 return new MessagePumpNSRunLoop; | 869 return new MessagePumpNSRunLoop; |
| 900 } | 870 } |
| 901 | 871 |
| 902 } // namespace base | 872 } // namespace base |
| OLD | NEW |