diff options
-rw-r--r-- | base/message_pump_mac.h | 9 | ||||
-rw-r--r-- | base/message_pump_mac.mm | 41 |
2 files changed, 37 insertions, 13 deletions
diff --git a/base/message_pump_mac.h b/base/message_pump_mac.h index 73a28e0..f7e9a83 100644 --- a/base/message_pump_mac.h +++ b/base/message_pump_mac.h @@ -128,6 +128,15 @@ class MessagePumpCFRunLoopBase : public MessagePump { // (weak) Delegate passed as an argument to the innermost Run call. Delegate* delegate_; + // "Delegateless" work flags are set when work is ready to be performed but + // must wait until a delegate is available to process it. This can happen + // when a MessagePumpCFRunLoopBase is instantiated and work arrives without + // any call to Run on the stack. The Run method will check for delegateless + // work on entry and redispatch it as needed once a delegate is available. + bool delegateless_work_; + bool delegateless_delayed_work_; + bool delegateless_idle_work_; + DISALLOW_COPY_AND_ASSIGN(MessagePumpCFRunLoopBase); }; diff --git a/base/message_pump_mac.mm b/base/message_pump_mac.mm index 3f94dc1..c9a0ea6 100644 --- a/base/message_pump_mac.mm +++ b/base/message_pump_mac.mm @@ -23,7 +23,10 @@ namespace base { // Must be called on the run loop thread. MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase() : nesting_level_(0), - delegate_(NULL) + delegate_(NULL), + delegateless_work_(false), + delegateless_delayed_work_(false), + delegateless_idle_work_(false) { run_loop_ = CFRunLoopGetCurrent(); CFRetain(run_loop_); @@ -125,6 +128,21 @@ void MessagePumpCFRunLoopBase::Run(Delegate* delegate) { Delegate* last_delegate = delegate_; delegate_ = delegate; + // If any work showed up but could not be dispatched for want of a delegate, + // set it up for dispatch again now that a delegate is available. + if (delegateless_work_) { + CFRunLoopSourceSignal(work_source_); + delegateless_work_ = false; + } + if (delegateless_delayed_work_) { + CFRunLoopSourceSignal(delayed_work_source_); + delegateless_delayed_work_ = false; + } + if (delegateless_idle_work_) { + CFRunLoopSourceSignal(idle_work_source_); + delegateless_idle_work_ = false; + } + DoRun(delegate); delegate_ = last_delegate; @@ -183,16 +201,9 @@ void MessagePumpCFRunLoopBase::RunWorkSource(void* info) { bool MessagePumpCFRunLoopBase::RunWork() { if (!delegate_) { // This point can be reached with a NULL delegate_ if Run is not on the - // stack but foreign code is spinning the CFRunLoop. - - // TODO(???): we get here while looping in our temporary 1st run - // dialog. If we simply return false, we choke rather brutally - // (we no longer do work ever again). For now, we simply - // re-signal ourself so we come around again. The problem only - // happens in a branded build if - // ~/Library/Preferences/com.google.Chrome.plist does not exist. - CFRunLoopSourceSignal(work_source_); - + // stack but foreign code is spinning the CFRunLoop. Arrange to come back + // here when a delegate is available. + delegateless_work_ = true; return false; } @@ -222,7 +233,9 @@ void MessagePumpCFRunLoopBase::RunDelayedWorkSource(void* info) { bool MessagePumpCFRunLoopBase::RunDelayedWork() { if (!delegate_) { // This point can be reached with a NULL delegate_ if Run is not on the - // stack but foreign code is spinning the CFRunLoop. + // stack but foreign code is spinning the CFRunLoop. Arrange to come back + // here when a delegate is available. + delegateless_delayed_work_ = true; return false; } @@ -262,7 +275,9 @@ void MessagePumpCFRunLoopBase::RunIdleWorkSource(void* info) { bool MessagePumpCFRunLoopBase::RunIdleWork() { if (!delegate_) { // This point can be reached with a NULL delegate_ if Run is not on the - // stack but foreign code is spinning the CFRunLoop. + // stack but foreign code is spinning the CFRunLoop. Arrange to come back + // here when a delegate is available. + delegateless_idle_work_ = true; return false; } |