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 |