diff options
Diffstat (limited to 'base')
-rw-r--r-- | base/message_pump_mac.h | 38 | ||||
-rw-r--r-- | base/message_pump_mac.mm | 51 | ||||
-rw-r--r-- | base/test/mock_chrome_application_mac.mm | 3 |
3 files changed, 78 insertions, 14 deletions
diff --git a/base/message_pump_mac.h b/base/message_pump_mac.h index 501d8c6..1f7ea10 100644 --- a/base/message_pump_mac.h +++ b/base/message_pump_mac.h @@ -232,10 +232,6 @@ class MessagePumpNSApplication : public MessagePumpCFRunLoopBase { virtual void DoRun(Delegate* delegate) OVERRIDE; virtual void Quit() OVERRIDE; - protected: - // Returns nil if NSApp is currently in the middle of calling -sendEvent. - virtual NSAutoreleasePool* CreateAutoreleasePool() OVERRIDE; - private: // False after Quit is called. bool keep_running_; @@ -249,12 +245,42 @@ class MessagePumpNSApplication : public MessagePumpCFRunLoopBase { DISALLOW_COPY_AND_ASSIGN(MessagePumpNSApplication); }; +class MessagePumpCrApplication : public MessagePumpNSApplication { + public: + MessagePumpCrApplication(); + + protected: + // Returns nil if NSApp is currently in the middle of calling + // -sendEvent. Requires NSApp implementing CrAppProtocol. + virtual NSAutoreleasePool* CreateAutoreleasePool() OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(MessagePumpCrApplication); +}; + class MessagePumpMac { public: - // Returns a new instance of MessagePumpNSApplication if called on the main - // thread. Otherwise, returns a new instance of MessagePumpNSRunLoop. + // If not on the main thread, returns a new instance of + // MessagePumpNSRunLoop. + // + // On the main thread, if NSApp exists and conforms to + // CrAppProtocol, creates an instances of MessagePumpCrApplication. + // + // Otherwise creates an instance of MessagePumpNSApplication using a + // default NSApplication. static MessagePump* Create(); + // If a pump is created before the required CrAppProtocol is + // created, the wrong MessagePump subclass could be used. + // UsingCrApp() returns false if the message pump was created before + // NSApp was initialized, or if NSApp does not implement + // CrAppProtocol. NSApp must be initialized before calling. + static bool UsingCrApp(); + + // Wrapper to query -[NSApp isHandlingSendEvent] from C++ code. + // Requires NSApp to implement CrAppProtocol. + static bool IsHandlingSendEvent(); + private: DISALLOW_IMPLICIT_CONSTRUCTORS(MessagePumpMac); }; diff --git a/base/message_pump_mac.mm b/base/message_pump_mac.mm index 2a50b64..615147c 100644 --- a/base/message_pump_mac.mm +++ b/base/message_pump_mac.mm @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/message_pump_mac.h" +#import "base/message_pump_mac.h" #import <AppKit/AppKit.h> #import <Foundation/Foundation.h> @@ -20,6 +20,10 @@ void NoOp(void* info) { const CFTimeInterval kCFTimeIntervalMax = std::numeric_limits<CFTimeInterval>::max(); +// Set to true if MessagePumpMac::Create() is called before NSApp is +// initialized. Only accessed from the main thread. +bool not_using_crapp = false; + } // namespace namespace base { @@ -591,6 +595,9 @@ void MessagePumpNSApplication::Quit() { atStart:NO]; } +MessagePumpCrApplication::MessagePumpCrApplication() { +} + // Prevents an autorelease pool from being created if the app is in the midst of // handling a UI event because various parts of AppKit depend on objects that // are created while handling a UI event to be autoreleased in the event loop. @@ -622,22 +629,50 @@ void MessagePumpNSApplication::Quit() { // CrApplication is responsible for setting handlingSendEvent to true just // before it sends the event through the event handling mechanism, and // returning it to its previous value once the event has been sent. -NSAutoreleasePool* MessagePumpNSApplication::CreateAutoreleasePool() { - NSAutoreleasePool* pool = nil; - DCHECK([NSApp conformsToProtocol:@protocol(CrAppProtocol)]); - if (![NSApp isHandlingSendEvent]) { - pool = MessagePumpCFRunLoopBase::CreateAutoreleasePool(); - } - return pool; +NSAutoreleasePool* MessagePumpCrApplication::CreateAutoreleasePool() { + if (MessagePumpMac::IsHandlingSendEvent()) + return nil; + return MessagePumpNSApplication::CreateAutoreleasePool(); } // static MessagePump* MessagePumpMac::Create() { if ([NSThread isMainThread]) { + if ([NSApp conformsToProtocol:@protocol(CrAppProtocol)]) + return new MessagePumpCrApplication; + + // The main-thread MessagePump implementations REQUIRE an NSApp. + // Executables which have specific requirements for their + // NSApplication subclass should initialize appropriately before + // creating an event loop. + [NSApplication sharedApplication]; + not_using_crapp = true; return new MessagePumpNSApplication; } return new MessagePumpNSRunLoop; } +// static +bool MessagePumpMac::UsingCrApp() { + DCHECK([NSThread isMainThread]); + + // If NSApp is still not initialized, then the subclass used cannot + // be determined. + DCHECK(NSApp); + + // The pump was created using MessagePumpNSApplication. + if (not_using_crapp) + return false; + + return [NSApp conformsToProtocol:@protocol(CrAppProtocol)]; +} + +// static +bool MessagePumpMac::IsHandlingSendEvent() { + DCHECK([NSApp conformsToProtocol:@protocol(CrAppProtocol)]); + NSObject<CrAppProtocol>* app = static_cast<NSObject<CrAppProtocol>*>(NSApp); + return [app isHandlingSendEvent]; +} + } // namespace base diff --git a/base/test/mock_chrome_application_mac.mm b/base/test/mock_chrome_application_mac.mm index b0b8617..9135293 100644 --- a/base/test/mock_chrome_application_mac.mm +++ b/base/test/mock_chrome_application_mac.mm @@ -14,6 +14,9 @@ DCHECK([app conformsToProtocol:@protocol(CrAppControlProtocol)]) << "Existing NSApp (class " << [[app className] UTF8String] << ") does not conform to required protocol."; + DCHECK(base::MessagePumpMac::UsingCrApp()) + << "MessagePumpMac::Create() was called before " + << "+[MockCrApp sharedApplication]"; return app; } |