message_pump_mac.mm revision ddb351dbec246cf1fab5ec20d2d5520909041de1
1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_pump_mac.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#import <AppKit/AppKit.h> 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#import <Foundation/Foundation.h> 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <limits> 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/time.h" 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace { 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid NoOp(void* info) { 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst CFTimeInterval kCFTimeIntervalMax = 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::numeric_limits<CFTimeInterval>::max(); 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base { 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A scoper for autorelease pools created from message pump run loops. 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Avoids dirtying up the ScopedNSAutoreleasePool interface for the rare 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// case where an autorelease pool needs to be passed in. 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass MessagePumpScopedAutoreleasePool { 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit MessagePumpScopedAutoreleasePool(MessagePumpCFRunLoopBase* pump) : 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pool_(pump->CreateAutoreleasePool()) { 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~MessagePumpScopedAutoreleasePool() { 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott [pool_ drain]; 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NSAutoreleasePool* pool_; 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(MessagePumpScopedAutoreleasePool); 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Must be called on the run loop thread. 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase() 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : delegate_(NULL), 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delayed_work_fire_time_(kCFTimeIntervalMax), 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott nesting_level_(0), 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott run_nesting_level_(0), 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott deepest_nesting_level_(0), 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegateless_work_(false), 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegateless_idle_work_(false) { 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott run_loop_ = CFRunLoopGetCurrent(); 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRetain(run_loop_); 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Set a repeating timer with a preposterous firing time and interval. The 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // timer will effectively never fire as-is. The firing time will be adjusted 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // as needed when ScheduleDelayedWork is called. 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopTimerContext timer_context = CFRunLoopTimerContext(); 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott timer_context.info = this; 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delayed_work_timer_ = CFRunLoopTimerCreate(NULL, // allocator 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kCFTimeIntervalMax, // fire time 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kCFTimeIntervalMax, // interval 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0, // flags 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0, // priority 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RunDelayedWorkTimer, 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &timer_context); 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopAddTimer(run_loop_, delayed_work_timer_, kCFRunLoopCommonModes); 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopSourceContext source_context = CFRunLoopSourceContext(); 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott source_context.info = this; 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott source_context.perform = RunWorkSource; 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott work_source_ = CFRunLoopSourceCreate(NULL, // allocator 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1, // priority 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &source_context); 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopAddSource(run_loop_, work_source_, kCFRunLoopCommonModes); 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott source_context.perform = RunIdleWorkSource; 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott idle_work_source_ = CFRunLoopSourceCreate(NULL, // allocator 80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 2, // priority 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &source_context); 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopAddSource(run_loop_, idle_work_source_, kCFRunLoopCommonModes); 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott source_context.perform = RunNestingDeferredWorkSource; 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott nesting_deferred_work_source_ = CFRunLoopSourceCreate(NULL, // allocator 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0, // priority 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &source_context); 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopAddSource(run_loop_, nesting_deferred_work_source_, 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kCFRunLoopCommonModes); 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopObserverContext observer_context = CFRunLoopObserverContext(); 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott observer_context.info = this; 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pre_wait_observer_ = CFRunLoopObserverCreate(NULL, // allocator 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kCFRunLoopBeforeWaiting, 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott true, // repeat 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0, // priority 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PreWaitObserver, 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &observer_context); 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopAddObserver(run_loop_, pre_wait_observer_, kCFRunLoopCommonModes); 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pre_source_observer_ = CFRunLoopObserverCreate(NULL, // allocator 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kCFRunLoopBeforeSources, 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott true, // repeat 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0, // priority 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PreSourceObserver, 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &observer_context); 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopAddObserver(run_loop_, pre_source_observer_, kCFRunLoopCommonModes); 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott enter_exit_observer_ = CFRunLoopObserverCreate(NULL, // allocator 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kCFRunLoopEntry | 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kCFRunLoopExit, 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott true, // repeat 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0, // priority 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnterExitObserver, 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &observer_context); 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopAddObserver(run_loop_, enter_exit_observer_, kCFRunLoopCommonModes); 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Ideally called on the run loop thread. If other run loops were running 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// lower on the run loop thread's stack when this object was created, the 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// same number of run loops must be running when this object is destroyed. 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMessagePumpCFRunLoopBase::~MessagePumpCFRunLoopBase() { 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopRemoveObserver(run_loop_, enter_exit_observer_, 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kCFRunLoopCommonModes); 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRelease(enter_exit_observer_); 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopRemoveObserver(run_loop_, pre_source_observer_, 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kCFRunLoopCommonModes); 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRelease(pre_source_observer_); 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopRemoveObserver(run_loop_, pre_wait_observer_, 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kCFRunLoopCommonModes); 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRelease(pre_wait_observer_); 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopRemoveSource(run_loop_, nesting_deferred_work_source_, 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kCFRunLoopCommonModes); 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRelease(nesting_deferred_work_source_); 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopRemoveSource(run_loop_, idle_work_source_, kCFRunLoopCommonModes); 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRelease(idle_work_source_); 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopRemoveSource(run_loop_, work_source_, kCFRunLoopCommonModes); 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRelease(work_source_); 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopRemoveTimer(run_loop_, delayed_work_timer_, kCFRunLoopCommonModes); 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRelease(delayed_work_timer_); 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRelease(run_loop_); 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Must be called on the run loop thread. 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpCFRunLoopBase::Run(Delegate* delegate) { 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // nesting_level_ will be incremented in EnterExitRunLoop, so set 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // run_nesting_level_ accordingly. 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int last_run_nesting_level = run_nesting_level_; 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott run_nesting_level_ = nesting_level_ + 1; 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Delegate* last_delegate = delegate_; 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegate_ = delegate; 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (delegate) { 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If any work showed up but could not be dispatched for want of a 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // delegate, set it up for dispatch again now that a delegate is 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // available. 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (delegateless_work_) { 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopSourceSignal(work_source_); 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegateless_work_ = false; 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (delegateless_idle_work_) { 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopSourceSignal(idle_work_source_); 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegateless_idle_work_ = false; 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoRun(delegate); 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Restore the previous state of the object. 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegate_ = last_delegate; 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott run_nesting_level_ = last_run_nesting_level; 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// May be called on any thread. 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpCFRunLoopBase::ScheduleWork() { 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopSourceSignal(work_source_); 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopWakeUp(run_loop_); 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Must be called on the run loop thread. 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpCFRunLoopBase::ScheduleDelayedWork( 190513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const TimeTicks& delayed_work_time) { 191513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // TODO(jar): We may need a more efficient way to go between these times, but 192513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // the difference will change not only when we sleep/wake, it will also change 193513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // when the user changes the wall clock time :-/. 194513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Time absolute_work_time = 195513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (delayed_work_time - TimeTicks::Now()) + Time::Now(); 196513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Time::Exploded exploded; 198513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch absolute_work_time.UTCExplode(&exploded); 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott double seconds = exploded.second + 200513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (static_cast<double>((absolute_work_time.ToInternalValue()) % 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Time::kMicrosecondsPerSecond) / 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Time::kMicrosecondsPerSecond); 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFGregorianDate gregorian = { 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exploded.year, 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exploded.month, 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exploded.day_of_month, 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exploded.hour, 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exploded.minute, 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott seconds 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott }; 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delayed_work_fire_time_ = CFGregorianDateGetAbsoluteTime(gregorian, NULL); 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopTimerSetNextFireDate(delayed_work_timer_, delayed_work_fire_time_); 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Called from the run loop. 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpCFRunLoopBase::RunDelayedWorkTimer(CFRunLoopTimerRef timer, 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void* info) { 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The timer won't fire again until it's reset. 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott self->delayed_work_fire_time_ = kCFTimeIntervalMax; 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // CFRunLoopTimers fire outside of the priority scheme for CFRunLoopSources. 226dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // In order to establish the proper priority in which work and delayed work 227dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // are processed one for one, the timer used to schedule delayed work must 228dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // signal a CFRunLoopSource used to dispatch both work and delayed work. 229dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CFRunLoopSourceSignal(self->work_source_); 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Called from the run loop. 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpCFRunLoopBase::RunWorkSource(void* info) { 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott self->RunWork(); 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Called by MessagePumpCFRunLoopBase::RunWorkSource. 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool MessagePumpCFRunLoopBase::RunWork() { 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!delegate_) { 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This point can be reached with a NULL delegate_ if Run is not on the 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // stack but foreign code is spinning the CFRunLoop. Arrange to come back 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // here when a delegate is available. 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegateless_work_ = true; 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The NSApplication-based run loop only drains the autorelease pool at each 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // UI event (NSEvent). The autorelease pool is not drained for each 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // CFRunLoopSource target that's run. Use a local pool for any autoreleased 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // objects if the app is not currently handling a UI event to ensure they're 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // released promptly even in the absence of UI events. 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessagePumpScopedAutoreleasePool autorelease_pool(this); 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 256dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Call DoWork and DoDelayedWork once, and if something was done, arrange to 257dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // come back here again as long as the loop is still running. 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool did_work = delegate_->DoWork(); 259dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool resignal_work_source = did_work; 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 261513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch TimeTicks next_time; 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegate_->DoDelayedWork(&next_time); 263dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!did_work) { 264dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Determine whether there's more delayed work, and if so, if it needs to 265dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // be done at some point in the future or if it's already time to do it. 266dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Only do these checks if did_work is false. If did_work is true, this 267dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // function, and therefore any additional delayed work, will get another 268dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // chance to run before the loop goes to sleep. 269dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool more_delayed_work = !next_time.is_null(); 270dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (more_delayed_work) { 271dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen TimeDelta delay = next_time - TimeTicks::Now(); 272dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (delay > TimeDelta()) { 273dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // There's more delayed work to be done in the future. 274dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ScheduleDelayedWork(next_time); 275dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 276dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // There's more delayed work to be done, and its time is in the past. 277dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Arrange to come back here directly as long as the loop is still 278dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // running. 279dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen resignal_work_source = true; 280dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 284dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (resignal_work_source) { 285dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CFRunLoopSourceSignal(work_source_); 286dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 287dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 288dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return resignal_work_source; 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Called from the run loop. 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpCFRunLoopBase::RunIdleWorkSource(void* info) { 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott self->RunIdleWork(); 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Called by MessagePumpCFRunLoopBase::RunIdleWorkSource. 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool MessagePumpCFRunLoopBase::RunIdleWork() { 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!delegate_) { 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This point can be reached with a NULL delegate_ if Run is not on the 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // stack but foreign code is spinning the CFRunLoop. Arrange to come back 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // here when a delegate is available. 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegateless_idle_work_ = true; 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The NSApplication-based run loop only drains the autorelease pool at each 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // UI event (NSEvent). The autorelease pool is not drained for each 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // CFRunLoopSource target that's run. Use a local pool for any autoreleased 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // objects if the app is not currently handling a UI event to ensure they're 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // released promptly even in the absence of UI events. 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessagePumpScopedAutoreleasePool autorelease_pool(this); 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Call DoIdleWork once, and if something was done, arrange to come back here 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // again as long as the loop is still running. 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool did_work = delegate_->DoIdleWork(); 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (did_work) { 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopSourceSignal(idle_work_source_); 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return did_work; 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Called from the run loop. 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpCFRunLoopBase::RunNestingDeferredWorkSource(void* info) { 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott self->RunNestingDeferredWork(); 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Called by MessagePumpCFRunLoopBase::RunNestingDeferredWorkSource. 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool MessagePumpCFRunLoopBase::RunNestingDeferredWork() { 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!delegate_) { 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This point can be reached with a NULL delegate_ if Run is not on the 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // stack but foreign code is spinning the CFRunLoop. There's no sense in 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // attempting to do any work or signalling the work sources because 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // without a delegate, work is not possible. 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Immediately try work in priority order. 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!RunWork()) { 344dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!RunIdleWork()) { 345dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return false; 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 348dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Work was done. Arrange for the loop to try non-nestable idle work on 349dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // a subsequent pass. 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopSourceSignal(idle_work_source_); 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Called before the run loop goes to sleep or exits, or processes sources. 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpCFRunLoopBase::MaybeScheduleNestingDeferredWork() { 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // deepest_nesting_level_ is set as run loops are entered. If the deepest 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // level encountered is deeper than the current level, a nested loop 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // (relative to the current level) ran since the last time nesting-deferred 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // work was scheduled. When that situation is encountered, schedule 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // nesting-deferred work in case any work was deferred because nested work 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // was disallowed. 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (deepest_nesting_level_ > nesting_level_) { 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott deepest_nesting_level_ = nesting_level_; 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopSourceSignal(nesting_deferred_work_source_); 367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Called from the run loop. 371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpCFRunLoopBase::PreWaitObserver(CFRunLoopObserverRef observer, 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopActivity activity, 374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void* info) { 375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Attempt to do some idle work before going to sleep. 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott self->RunIdleWork(); 379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The run loop is about to go to sleep. If any of the work done since it 381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // started or woke up resulted in a nested run loop running, 382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // nesting-deferred work may have accumulated. Schedule it for processing 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // if appropriate. 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott self->MaybeScheduleNestingDeferredWork(); 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Called from the run loop. 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpCFRunLoopBase::PreSourceObserver(CFRunLoopObserverRef observer, 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopActivity activity, 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void* info) { 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The run loop has reached the top of the loop and is about to begin 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // processing sources. If the last iteration of the loop at this nesting 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // level did not sleep or exit, nesting-deferred work may have accumulated 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // if a nested loop ran. Schedule nesting-deferred work for processing if 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // appropriate. 399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott self->MaybeScheduleNestingDeferredWork(); 400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Called from the run loop. 403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer, 405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopActivity activity, 406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void* info) { 407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (activity) { 410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case kCFRunLoopEntry: 411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++self->nesting_level_; 412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (self->nesting_level_ > self->deepest_nesting_level_) { 413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott self->deepest_nesting_level_ = self->nesting_level_; 414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case kCFRunLoopExit: 418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Not all run loops go to sleep. If a run loop is stopped before it 419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // goes to sleep due to a CFRunLoopStop call, or if the timeout passed 420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // to CFRunLoopRunInMode expires, the run loop may proceed directly from 421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // handling sources to exiting without any sleep. This most commonly 422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // occurs when CFRunLoopRunInMode is passed a timeout of 0, causing it 423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // to make a single pass through the loop and exit without sleep. Some 424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // native loops use CFRunLoop in this way. Because PreWaitObserver will 425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // not be called in these case, MaybeScheduleNestingDeferredWork needs 426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // to be called here, as the run loop exits. 427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // MaybeScheduleNestingDeferredWork consults self->nesting_level_ 429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // to determine whether to schedule nesting-deferred work. It expects 430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the nesting level to be set to the depth of the loop that is going 431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // to sleep or exiting. It must be called before decrementing the 432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // value so that the value still corresponds to the level of the exiting 433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // loop. 434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott self->MaybeScheduleNestingDeferredWork(); 435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott --self->nesting_level_; 436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott self->EnterExitRunLoop(activity); 443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default 446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// implementation is a no-op. 447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpCFRunLoopBase::EnterExitRunLoop(CFRunLoopActivity activity) { 448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Base version returns a standard NSAutoreleasePool. 451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottNSAutoreleasePool* MessagePumpCFRunLoopBase::CreateAutoreleasePool() { 452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return [[NSAutoreleasePool alloc] init]; 453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMessagePumpCFRunLoop::MessagePumpCFRunLoop() 456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : quit_pending_(false) { 457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Called by MessagePumpCFRunLoopBase::DoRun. If other CFRunLoopRun loops were 460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// running lower on the run loop thread's stack when this object was created, 461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the same number of CFRunLoopRun loops must be running for the outermost call 462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// to Run. Run/DoRun are reentrant after that point. 463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpCFRunLoop::DoRun(Delegate* delegate) { 464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This is completely identical to calling CFRunLoopRun(), except autorelease 465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // pool management is introduced. 466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int result; 467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott do { 468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessagePumpScopedAutoreleasePool autorelease_pool(this); 469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kCFTimeIntervalMax, 471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott false); 472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } while (result != kCFRunLoopRunStopped && result != kCFRunLoopRunFinished); 473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Must be called on the run loop thread. 476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpCFRunLoop::Quit() { 477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Stop the innermost run loop managed by this MessagePumpCFRunLoop object. 478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (nesting_level() == run_nesting_level()) { 479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This object is running the innermost loop, just stop it. 480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopStop(run_loop()); 481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // There's another loop running inside the loop managed by this object. 483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // In other words, someone else called CFRunLoopRunInMode on the same 484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // thread, deeper on the stack than the deepest Run call. Don't preempt 485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // other run loops, just mark this object to quit the innermost Run as 486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // soon as the other inner loops not managed by Run are done. 487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott quit_pending_ = true; 488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Called by MessagePumpCFRunLoopBase::EnterExitObserver. 492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpCFRunLoop::EnterExitRunLoop(CFRunLoopActivity activity) { 493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (activity == kCFRunLoopExit && 494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott nesting_level() == run_nesting_level() && 495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott quit_pending_) { 496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Quit was called while loops other than those managed by this object 497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // were running further inside a run loop managed by this object. Now 498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // that all unmanaged inner run loops are gone, stop the loop running 499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // just inside Run. 500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopStop(run_loop()); 501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott quit_pending_ = false; 502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMessagePumpNSRunLoop::MessagePumpNSRunLoop() 506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : keep_running_(true) { 507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopSourceContext source_context = CFRunLoopSourceContext(); 508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott source_context.perform = NoOp; 509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott quit_source_ = CFRunLoopSourceCreate(NULL, // allocator 510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0, // priority 511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &source_context); 512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopAddSource(run_loop(), quit_source_, kCFRunLoopCommonModes); 513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMessagePumpNSRunLoop::~MessagePumpNSRunLoop() { 516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopRemoveSource(run_loop(), quit_source_, kCFRunLoopCommonModes); 517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRelease(quit_source_); 518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpNSRunLoop::DoRun(Delegate* delegate) { 521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (keep_running_) { 522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // NSRunLoop manages autorelease pools itself. 523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode 524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott beforeDate:[NSDate distantFuture]]; 525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott keep_running_ = true; 528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpNSRunLoop::Quit() { 531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott keep_running_ = false; 532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopSourceSignal(quit_source_); 533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFRunLoopWakeUp(run_loop()); 534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMessagePumpNSApplication::MessagePumpNSApplication() 537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : keep_running_(true), 538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott running_own_loop_(false) { 539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpNSApplication::DoRun(Delegate* delegate) { 542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool last_running_own_loop_ = running_own_loop_; 543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 544dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // NSApp must be initialized by calling: 545dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // [{some class which implements CrAppProtocol} sharedApplication] 546dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Most likely candidates are CrApplication or BrowserCrApplication. 547dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // These can be initialized from C++ code by calling 548dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // RegisterCrApp() or RegisterBrowserCrApp(). 549dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CHECK(NSApp); 550dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (![NSApp isRunning]) { 552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott running_own_loop_ = false; 553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // NSApplication manages autorelease pools itself when run this way. 554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott [NSApp run]; 555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott running_own_loop_ = true; 557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NSDate* distant_future = [NSDate distantFuture]; 558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (keep_running_) { 559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessagePumpScopedAutoreleasePool autorelease_pool(this); 560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask 561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott untilDate:distant_future 562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott inMode:NSDefaultRunLoopMode 563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dequeue:YES]; 564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event) { 565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott [NSApp sendEvent:event]; 566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott keep_running_ = true; 569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott running_own_loop_ = last_running_own_loop_; 572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpNSApplication::Quit() { 575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!running_own_loop_) { 576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott [NSApp stop:nil]; 577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott keep_running_ = false; 579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Send a fake event to wake the loop up. 582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined 583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott location:NSMakePoint(0, 0) 584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott modifierFlags:0 585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott timestamp:0 586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott windowNumber:0 587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott context:NULL 588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott subtype:0 589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott data1:0 590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott data2:0] 591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott atStart:NO]; 592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Prevents an autorelease pool from being created if the app is in the midst of 595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// handling a UI event because various parts of AppKit depend on objects that 596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// are created while handling a UI event to be autoreleased in the event loop. 597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// An example of this is NSWindowController. When a window with a window 598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// controller is closed it goes through a stack like this: 599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// (Several stack frames elided for clarity) 600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// #0 [NSWindowController autorelease] 602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// #1 DoAClose 603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// #2 MessagePumpCFRunLoopBase::DoWork() 604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// #3 [NSRunLoop run] 605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// #4 [NSButton performClick:] 606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// #5 [NSWindow sendEvent:] 607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// #6 [NSApp sendEvent:] 608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// #7 [NSApp run] 609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// -performClick: spins a nested run loop. If the pool created in DoWork was a 611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// standard NSAutoreleasePool, it would release the objects that were 612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// autoreleased into it once DoWork released it. This would cause the window 613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// controller, which autoreleased itself in frame #0, to release itself, and 614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// possibly free itself. Unfortunately this window controller controls the 615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// window in frame #5. When the stack is unwound to frame #5, the window would 616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// no longer exists and crashes may occur. Apple gets around this by never 617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// releasing the pool it creates in frame #4, and letting frame #7 clean it up 618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// when it cleans up the pool that wraps frame #7. When an autorelease pool is 619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// released it releases all other pools that were created after it on the 620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// autorelease pool stack. 621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// CrApplication is responsible for setting handlingSendEvent to true just 62321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// before it sends the event through the event handling mechanism, and 624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// returning it to its previous value once the event has been sent. 625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottNSAutoreleasePool* MessagePumpNSApplication::CreateAutoreleasePool() { 626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NSAutoreleasePool* pool = nil; 62721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK([NSApp conformsToProtocol:@protocol(CrAppProtocol)]); 62821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (![NSApp isHandlingSendEvent]) { 629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pool = MessagePumpCFRunLoopBase::CreateAutoreleasePool(); 630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return pool; 632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMessagePump* MessagePumpMac::Create() { 636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ([NSThread isMainThread]) { 637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return new MessagePumpNSApplication; 638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return new MessagePumpNSRunLoop; 641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace base 644