summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/message_pump_mac.h9
-rw-r--r--base/message_pump_mac.mm41
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;
}