Commit d7de5787 authored by shess@chromium.org's avatar shess@chromium.org

[Mac] Remove content/ CrApplication.

Pull the CrAppProtocol autorelease-pool handling down into 
MessagePumpCrApplication, which is selected at Create() if NSApp 
implements the right protocol. UsingCrApp() allows clients to 
confirm the correct setup (unfortunately, synchronizing NSApp 
initialization and MessagePump::Create() would be intrusive).

Also push CrAppProtocol and CrAppControlProtocol implementation into
BrowserCrApplication, and reparent that class from NSApplication.

Reparent ServiceCrApplication on NSApplication and rename.

Remove CrApplication registration from gpu, plugin, and renderer
mains.

Remove MockCrApp dependency from remoting sample code.

BUG=102224


Review URL: http://codereview.chromium.org/8771028

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@113281 0039d316-1c4b-4281-b951-d872f2087c98
parent 5179b914
......@@ -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);
};
......
......@@ -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
......@@ -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;
}
......
......@@ -31,7 +31,6 @@ include_rules = [
"-content/common",
# TODO(jam): remove all the exceptions. BUG=98716
"+content/common/chrome_application_mac.h",
"+content/common/view_messages.h",
# Other libraries.
......
......@@ -8,15 +8,22 @@
#ifdef __OBJC__
#import "content/common/chrome_application_mac.h"
#import <AppKit/AppKit.h>
#import "base/mac/scoped_sending_event.h"
#import "base/memory/scoped_nsobject.h"
#import "base/message_pump_mac.h"
// Event hooks must implement this protocol.
@protocol CrApplicationEventHookProtocol
- (void)hookForEvent:(NSEvent*)theEvent;
@end
@interface BrowserCrApplication : CrApplication {
@interface BrowserCrApplication : NSApplication<CrAppProtocol,
CrAppControlProtocol> {
@private
BOOL handlingSendEvent_;
// Array of objects implementing CrApplicationEventHookProtocol.
scoped_nsobject<NSMutableArray> eventHooks_;
}
......
......@@ -221,6 +221,30 @@ void SwizzleInit() {
return self;
}
// Initialize NSApplication using the custom subclass. Check whether NSApp
// was already initialized using another class, because that would break
// some things.
+ (NSApplication*)sharedApplication {
NSApplication* app = [super sharedApplication];
// +sharedApplication initializes the global NSApp, so if a specific
// NSApplication subclass is requested, require that to be the one
// delivered. The practical effect is to require a consistent NSApp
// across the executable.
CHECK([NSApp isKindOfClass:self])
<< "NSApp must be of type " << [[self className] UTF8String]
<< ", not " << [[NSApp className] UTF8String];
// If the message loop was initialized before NSApp is setup, the
// message pump will be setup incorrectly. Failing this implies
// that RegisterBrowserCrApp() should be called earlier.
CHECK(base::MessagePumpMac::UsingCrApp())
<< "MessagePumpMac::Create() is using the wrong pump implementation"
<< " for " << [[self className] UTF8String];
return app;
}
////////////////////////////////////////////////////////////////////////////////
// HISTORICAL COMMENT (by viettrungluu, from
// http://codereview.chromium.org/1520006 with mild editing):
......@@ -368,6 +392,14 @@ void SwizzleInit() {
[eventHooks_ removeObject:handler];
}
- (BOOL)isHandlingSendEvent {
return handlingSendEvent_;
}
- (void)setHandlingSendEvent:(BOOL)handlingSendEvent {
handlingSendEvent_ = handlingSendEvent;
}
- (void)sendEvent:(NSEvent*)event {
base::mac::ScopedSendingEvent sendingEventScoper;
for (id<CrApplicationEventHookProtocol> handler in eventHooks_.get()) {
......@@ -396,7 +428,7 @@ void SwizzleInit() {
// sidestep scopers is setjmp/longjmp (see above). The following
// is to "fix" this while the more fundamental concern is
// addressed elsewhere.
[self clearIsHandlingSendEvent];
[self setHandlingSendEvent:NO];
// If |ScopedNSExceptionEnabler| is used to allow exceptions, and an
// uncaught exception is thrown, it will throw past all of the scopers.
......
......@@ -4,8 +4,8 @@
#import <Cocoa/Cocoa.h>
#include "base/metrics/histogram.h"
#import "base/mac/scoped_nsexception_enabler.h"
#include "base/metrics/histogram.h"
#import "chrome/browser/chrome_browser_application_mac.h"
#include "testing/gtest/include/gtest/gtest.h"
......
......@@ -71,7 +71,7 @@ void ChromeBrowserMainPartsMac::PreMainMessageLoopStart() {
// CFRunLoop.
// Initialize NSApplication using the custom subclass.
[BrowserCrApplication sharedApplication];
chrome_browser_application_mac::RegisterBrowserCrApp();
// If ui_task is not NULL, the app is actually a browser_test, so startup is
// handled outside of BrowserMain (which is what called this).
......
......@@ -9,6 +9,7 @@
#include <string>
#import "base/mac/scoped_sending_event.h"
#import "base/message_pump_mac.h"
#import "chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.h"
#include "chrome/browser/tab_contents/render_view_context_menu_mac.h"
#include "chrome/browser/tab_contents/web_drag_bookmark_handler_mac.h"
......@@ -23,7 +24,6 @@
#include "content/browser/tab_contents/tab_contents_delegate.h"
#import "content/browser/tab_contents/web_drag_dest_mac.h"
#import "content/browser/tab_contents/web_drag_source_mac.h"
#import "content/common/chrome_application_mac.h"
#include "content/common/view_messages.h"
#include "skia/ext/skia_utils_mac.h"
#import "third_party/mozilla/NSPasteboard+Utils.h"
......@@ -369,11 +369,7 @@ void TabContentsViewMac::ShowPopupMenu(
}
bool TabContentsViewMac::IsEventTracking() const {
if ([NSApp isKindOfClass:[CrApplication class]] &&
[static_cast<CrApplication*>(NSApp) isHandlingSendEvent]) {
return true;
}
return false;
return base::MessagePumpMac::IsHandlingSendEvent();
}
// Arrange to call CloseTab() after we're back to the main event loop.
......
......@@ -8,7 +8,6 @@
#include "base/memory/scoped_nsobject.h"
#include "base/memory/scoped_ptr.h"
#include "base/test/mock_chrome_application_mac.h"
#include "testing/platform_test.h"
#include "ui/gfx/rect.h"
......
......@@ -4428,9 +4428,6 @@
'../third_party/mozilla/NSURL+Utils.m',
'../third_party/mozilla/NSWorkspace+Utils.h',
'../third_party/mozilla/NSWorkspace+Utils.m',
# Headers so that IB can find classes it needs to resolve classes
# in XIB files.
'common/chrome_application_mac.h',
],
'include_dirs': [
'../third_party/apple',
......
......@@ -8,10 +8,10 @@
#ifdef __OBJC__
#import "content/common/chrome_application_mac.h"
#import <AppKit/AppKit.h>
// Top level Mac Application for the service process.
@interface ServiceCrApplication : CrApplication
@interface ServiceApplication : NSApplication
@end
......@@ -19,9 +19,9 @@
namespace chrome_service_application_mac {
// To be used to instantiate ServiceCrApplication from C++ code.
void RegisterServiceCrApp();
// To be used to instantiate ServiceApplication from C++ code.
void RegisterServiceApp();
} // namespace chrome_service_application_mac
#endif // CHROME_SERVICE_CHROME_SERVICE_APPLICATION_MAC_H_
......@@ -9,14 +9,14 @@
#import "chrome/common/cloud_print/cloud_print_class_mac.h"
#include "chrome/common/chrome_switches.h"
@interface ServiceCrApplication ()
@interface ServiceApplication ()
- (void)setCloudPrintHandler;
- (void)submitPrint:(NSAppleEventDescriptor*)event;
@end
@implementation ServiceCrApplication
@implementation ServiceApplication
-(void)setCloudPrintHandler {
- (void)setCloudPrintHandler {
NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager];
[em setEventHandler:self
andSelector:@selector(submitPrint:)
......@@ -90,10 +90,10 @@
namespace chrome_service_application_mac {
void RegisterServiceCrApp() {
ServiceCrApplication* var =
static_cast<ServiceCrApplication*>
([ServiceCrApplication sharedApplication]);
void RegisterServiceApp() {
ServiceApplication* var =
base::mac::ObjCCastStrict<ServiceApplication>(
[ServiceApplication sharedApplication]);
[var setCloudPrintHandler];
}
......
......@@ -18,6 +18,10 @@
// Mainline routine for running as the service process.
int ServiceProcessMain(const content::MainFunctionParams& parameters) {
#if defined(OS_MACOSX)
chrome_service_application_mac::RegisterServiceApp();
#endif
MessageLoopForUI main_message_loop;
main_message_loop.set_thread_name("MainThread");
if (parameters.command_line.HasSwitch(switches::kWaitForDebugger)) {
......@@ -27,10 +31,6 @@ int ServiceProcessMain(const content::MainFunctionParams& parameters) {
VLOG(1) << "Service process launched: "
<< parameters.command_line.GetCommandLineString();
#if defined(OS_MACOSX)
chrome_service_application_mac::RegisterServiceCrApp();
#endif
base::PlatformThread::SetName("CrServiceMain");
// If there is already a service process running, quit now.
......
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_COMMON_CHROME_APPLICATION_MAC_H_
#define CONTENT_COMMON_CHROME_APPLICATION_MAC_H_
#pragma once
#if defined(__OBJC__)
#import <AppKit/AppKit.h>
#include "base/basictypes.h"
#import "base/mac/scoped_sending_event.h"
@interface CrApplication : NSApplication<CrAppControlProtocol> {
@private
BOOL handlingSendEvent_;
}
- (BOOL)isHandlingSendEvent;
// Unconditionally clears |handlingSendEvent_|. This should not be
// used except in recovering from some sort of exceptional condition.
- (void)clearIsHandlingSendEvent;
+ (NSApplication*)sharedApplication;
@end
#endif // defined(__OBJC__)
namespace chrome_application_mac {
// To be used to instantiate CrApplication from C++ code.
void RegisterCrApp();
} // namespace chrome_application_mac
#endif // CONTENT_COMMON_CHROME_APPLICATION_MAC_H_
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "content/common/chrome_application_mac.h"
#include "base/logging.h"
@interface CrApplication ()
- (void)setHandlingSendEvent:(BOOL)handlingSendEvent;
@end
@implementation CrApplication
// Initialize NSApplication using the custom subclass. Check whether NSApp
// was already initialized using another class, because that would break
// some things.
+ (NSApplication*)sharedApplication {
NSApplication* app = [super sharedApplication];
if (![NSApp isKindOfClass:self]) {
DLOG(ERROR) << "NSApp should be of type " << [[self className] UTF8String]
<< ", not " << [[NSApp className] UTF8String];
DCHECK(false) << "NSApp is of wrong type";
}
return app;
}
- (BOOL)isHandlingSendEvent {
return handlingSendEvent_;
}
- (void)setHandlingSendEvent:(BOOL)handlingSendEvent {
handlingSendEvent_ = handlingSendEvent;
}
- (void)clearIsHandlingSendEvent {
[self setHandlingSendEvent:NO];
}
- (void)sendEvent:(NSEvent*)event {
base::mac::ScopedSendingEvent sendingEventScoper;
[super sendEvent:event];
}
@end
namespace chrome_application_mac {
void RegisterCrApp() {
[CrApplication sharedApplication];
}
} // namespace chrome_application_mac
......@@ -27,7 +27,6 @@ extern "C" {
#include "base/sys_info.h"
#include "base/sys_string_conversions.h"
#include "base/utf_string_conversions.h"
#include "content/common/chrome_application_mac.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "grit/content_resources.h"
......
......@@ -93,8 +93,6 @@
'common/child_thread.h',
'common/child_trace_message_filter.cc',
'common/child_trace_message_filter.h',
'common/chrome_application_mac.h',
'common/chrome_application_mac.mm',
'common/chrome_descriptors.h',
'common/clipboard_messages.h',
'common/content_message_generator.cc',
......
......@@ -22,9 +22,7 @@
#include "ui/gfx/gl/gl_surface.h"
#include "ui/gfx/gl/gl_switches.h"
#if defined(OS_MACOSX)
#include "content/common/chrome_application_mac.h"
#elif defined(OS_WIN)
#if defined(OS_WIN)
#include "sandbox/src/sandbox.h"
#endif
......@@ -85,10 +83,6 @@ int GpuMain(const content::MainFunctionParams& parameters) {
target_services->LowerToken();
#endif
#if defined(OS_MACOSX)
chrome_application_mac::RegisterCrApp();
#endif
MessageLoop::Type message_loop_type = MessageLoop::TYPE_UI;
#if defined(OS_WIN)
// Unless we're running on desktop GL, we don't need a UI message
......
......@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <AppKit/AppKit.h>
#include "base/environment.h"
#include "base/memory/scoped_ptr.h"
#include "base/string_util.h"
#include "content/common/chrome_application_mac.h"
#include "content/common/plugin_carbon_interpose_constants_mac.h"
#include "content/plugin/plugin_interpose_util_mac.h"
......@@ -44,7 +45,6 @@ void TrimInterposeEnvironment() {
#endif
void InitializeChromeApplication() {
[CrApplication sharedApplication];
[NSApplication sharedApplication];
mac_plugin_interposing::SetUpCocoaInterposing();
}
......@@ -11,7 +11,6 @@
#include "base/logging.h"
#include "base/sys_string_conversions.h"
#import "chrome/test/security_tests/renderer_sandbox_tests_mac.h"
#import "content/common/chrome_application_mac.h"
#include "content/common/sandbox_mac.h"
#include "content/public/common/content_switches.h"
#include "content/common/sandbox_init_mac.h"
......@@ -29,9 +28,9 @@ RendererMainPlatformDelegate::~RendererMainPlatformDelegate() {
// running a renderer needs to also be reflected in chrome_main.cc for
// --single-process support.
void RendererMainPlatformDelegate::PlatformInitialize() {
// Initialize NSApplication using the custom subclass. Without this call,
// drawing of native UI elements (e.g. buttons) in WebKit will explode.
[CrApplication sharedApplication];
// Initialize NSApplication up front. Without this call, drawing of
// native UI elements (e.g. buttons) in WebKit will explode.
[NSApplication sharedApplication];
// Load WebKit system interfaces.
InitWebCoreSystemInterface();
......
......@@ -28,7 +28,6 @@
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/test/mock_chrome_application_mac.h"
#include "base/threading/thread.h"
#include "crypto/nss_util.h"
#include "remoting/base/constants.h"
......@@ -262,7 +261,6 @@ int main(int argc, char** argv) {
#if defined(OS_MACOSX)
// Needed so we don't leak objects when threads are created.
base::mac::ScopedNSAutoreleasePool pool;
mock_cr_app::RegisterMockCrApp();
#endif
CommandLine::Init(argc, argv);
......
......@@ -669,8 +669,6 @@
'host/it2me_host_user_interface.cc',
'host/it2me_host_user_interface.h',
'host/simple_host_process.cc',
'../base/test/mock_chrome_application_mac.mm',
'../base/test/mock_chrome_application_mac.h',
],
}, # end of target 'remoting_simple_host'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment