summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/app-Info.plist2
-rw-r--r--chrome/app/nibs/MainMenu.xib60
-rw-r--r--chrome/browser/app_controller_mac.h3
-rw-r--r--chrome/browser/app_controller_mac.mm78
-rw-r--r--chrome/browser/automation/automation_provider_list_mac.mm4
-rw-r--r--chrome/browser/browser_main.cc2
-rw-r--r--chrome/browser/browser_main.h2
-rw-r--r--chrome/browser/browser_main_gtk.cc2
-rw-r--r--chrome/browser/browser_main_mac.mm38
-rw-r--r--chrome/browser/browser_main_win.cc2
-rw-r--r--chrome/browser/chrome_application_mac.h13
-rw-r--r--chrome/browser/chrome_application_mac.mm61
-rw-r--r--chrome/chrome.gyp2
13 files changed, 169 insertions, 100 deletions
diff --git a/chrome/app/app-Info.plist b/chrome/app/app-Info.plist
index 7ca9989..5390a70 100644
--- a/chrome/app/app-Info.plist
+++ b/chrome/app/app-Info.plist
@@ -187,7 +187,7 @@
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
- <string>NSApplication</string>
+ <string>CrApplication</string>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
diff --git a/chrome/app/nibs/MainMenu.xib b/chrome/app/nibs/MainMenu.xib
index dbc39c5..55d33e2 100644
--- a/chrome/app/nibs/MainMenu.xib
+++ b/chrome/app/nibs/MainMenu.xib
@@ -8,7 +8,7 @@
<string key="IBDocument.HIToolboxVersion">353.00</string>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
- <integer value="81"/>
+ <integer value="29"/>
</object>
<object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -26,13 +26,13 @@
<object class="NSMutableArray" key="IBDocument.RootObjects" id="1048">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSCustomObject" id="1021">
- <string key="NSClassName">NSApplication</string>
+ <string key="NSClassName">CrApplication</string>
</object>
<object class="NSCustomObject" id="1014">
<string key="NSClassName">FirstResponder</string>
</object>
<object class="NSCustomObject" id="1050">
- <string key="NSClassName">NSApplication</string>
+ <string key="NSClassName">CrApplication</string>
</object>
<object class="NSCustomObject" id="163992474">
<string key="NSClassName">NSFontManager</string>
@@ -43,7 +43,7 @@
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMenuItem" id="694149608">
<reference key="NSMenu" ref="649796088"/>
- <string key="NSTitle">Chromium</string>
+ <string key="NSTitle">^IDS_SHORT_PRODUCT_NAME</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<object class="NSCustomResource" key="NSOnImage" id="353210768">
@@ -56,7 +56,7 @@
</object>
<string key="NSAction">submenuAction:</string>
<object class="NSMenu" key="NSSubmenu" id="110575045">
- <string key="NSTitle">Chromium</string>
+ <string key="NSTitle">^IDS_SHORT_PRODUCT_NAME</string>
<object class="NSMutableArray" key="NSMenuItems">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMenuItem" id="238522557">
@@ -1232,14 +1232,6 @@
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
- <string key="label">quit:</string>
- <reference key="source" ref="168151378"/>
- <reference key="destination" ref="632727374"/>
- </object>
- <int key="connectionID">489</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
<string key="label">commandDispatch:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="705341025"/>
@@ -1534,13 +1526,21 @@
</object>
<int key="connectionID">646</int>
</object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">terminate:</string>
+ <reference key="source" ref="1050"/>
+ <reference key="destination" ref="632727374"/>
+ </object>
+ <int key="connectionID">647</int>
+ </object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBObjectRecord">
<int key="objectID">0</int>
- <object class="NSArray" key="object" id="276974574">
+ <object class="NSArray" key="object" id="470821800">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<reference key="children" ref="1048"/>
@@ -1549,19 +1549,19 @@
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="1021"/>
- <reference key="parent" ref="276974574"/>
+ <reference key="parent" ref="470821800"/>
<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="1014"/>
- <reference key="parent" ref="276974574"/>
+ <reference key="parent" ref="470821800"/>
<string key="objectName">First Responder</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-3</int>
<reference key="object" ref="1050"/>
- <reference key="parent" ref="276974574"/>
+ <reference key="parent" ref="470821800"/>
<string key="objectName">Application</string>
</object>
<object class="IBObjectRecord">
@@ -1578,7 +1578,7 @@
<reference ref="586577488"/>
<reference ref="445514911"/>
</object>
- <reference key="parent" ref="276974574"/>
+ <reference key="parent" ref="470821800"/>
<string key="objectName">Main Menu</string>
</object>
<object class="IBObjectRecord">
@@ -2013,7 +2013,7 @@
<object class="IBObjectRecord">
<int key="objectID">373</int>
<reference key="object" ref="163992474"/>
- <reference key="parent" ref="276974574"/>
+ <reference key="parent" ref="470821800"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">449</int>
@@ -2104,7 +2104,7 @@
<object class="IBObjectRecord">
<int key="objectID">483</int>
<reference key="object" ref="168151378"/>
- <reference key="parent" ref="276974574"/>
+ <reference key="parent" ref="470821800"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">492</int>
@@ -2315,7 +2315,7 @@
<object class="IBObjectRecord">
<int key="objectID">641</int>
<reference key="object" ref="979722531"/>
- <reference key="parent" ref="276974574"/>
+ <reference key="parent" ref="470821800"/>
</object>
</object>
</object>
@@ -2622,7 +2622,7 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>{{525, 802}, {197, 73}}</string>
- <string>{{0, 482}, {1437, 20}}</string>
+ <string>{{0, 337}, {1578, 20}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>{74, 862}</string>
@@ -2687,7 +2687,7 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
- <string>{{222, 551}, {385, 213}}</string>
+ <string>{{12, 124}, {385, 213}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>{{23, 794}, {245, 183}}</string>
@@ -2714,7 +2714,7 @@
<reference ref="9"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
- <string>{{106, 179}, {353, 303}}</string>
+ <string>{{106, 34}, {350, 303}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>{{323, 672}, {199, 203}}</string>
@@ -2746,7 +2746,7 @@
</object>
</object>
<nil key="sourceID"/>
- <int key="maxID">646</int>
+ <int key="maxID">647</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
@@ -2759,14 +2759,12 @@
<object class="NSMutableArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>orderFrontStandardAboutPanel:</string>
- <string>quit:</string>
<string>showPreferences:</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>id</string>
<string>id</string>
- <string>id</string>
</object>
</object>
<object class="NSMutableDictionary" key="outlets">
@@ -2796,6 +2794,14 @@
</object>
</object>
<object class="IBPartialClassDescription">
+ <string key="className">CrApplication</string>
+ <string key="superclassName">NSApplication</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/chrome_application_mac.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
<string key="className">DownloadShelfController</string>
<string key="superclassName">NSViewController</string>
<object class="NSMutableDictionary" key="actions">
diff --git a/chrome/browser/app_controller_mac.h b/chrome/browser/app_controller_mac.h
index 091891c..cb3785f 100644
--- a/chrome/browser/app_controller_mac.h
+++ b/chrome/browser/app_controller_mac.h
@@ -14,6 +14,7 @@
@class AboutWindowController;
class BookmarkMenuBridge;
class CommandUpdater;
+@class CrApplication;
class GURL;
class HistoryMenuBridge;
@class PreferencesWindowController;
@@ -45,7 +46,7 @@ class Profile;
BOOL fileMenuUpdatePending_; // ensure we only do this once per notificaion.
}
-- (IBAction)quit:(id)sender;
+- (void)didEndMainMessageLoop;
- (Profile*)defaultProfile;
// Show the preferences window, or bring it to the front if it's already
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm
index b7a062f..ccfb0eb 100644
--- a/chrome/browser/app_controller_mac.mm
+++ b/chrome/browser/app_controller_mac.mm
@@ -16,6 +16,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/browser_window.h"
+#import "chrome/browser/chrome_application_mac.h"
#import "chrome/browser/cocoa/about_window_controller.h"
#import "chrome/browser/cocoa/bookmark_menu_bridge.h"
#import "chrome/browser/cocoa/browser_window_cocoa.h"
@@ -144,9 +145,6 @@
return YES;
}
-// We do not use the normal application teardown process -- this function is
-// not called by the system but by us in |quit:|. |NSTerminateLater| is not a
-// return value that is supported by |quit:|.
- (NSApplicationTerminateReply)applicationShouldTerminate:
(NSApplication *)sender {
// Do not quit if any per-tab sheets are open, as required by
@@ -164,17 +162,38 @@
// Called when the app is shutting down. Clean-up as appropriate.
- (void)applicationWillTerminate:(NSNotification *)aNotification {
+ NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager];
+ [em removeEventHandlerForEventClass:kInternetEventClass
+ andEventID:kAEGetURL];
+ [em removeEventHandlerForEventClass:'WWW!'
+ andEventID:'OURL'];
+ [em removeEventHandlerForEventClass:kCoreEventClass
+ andEventID:kAEOpenDocuments];
+
+ // Close all the windows.
+ BrowserList::CloseAllBrowsers(true);
+
+ // On Windows, this is done in Browser::OnWindowClosing, but that's not
+ // appropriate on Mac since we don't shut down when we reach zero windows.
+ browser_shutdown::OnShutdownStarting(browser_shutdown::BROWSER_EXIT);
+
+ // Release the reference to the browser process. Once all the browsers get
+ // dealloc'd, it will stop the RunLoop and fall back into main().
+ g_browser_process->ReleaseModule();
+
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+- (void)didEndMainMessageLoop {
DCHECK(!BrowserList::HasBrowserWithProfile([self defaultProfile]));
if (!BrowserList::HasBrowserWithProfile([self defaultProfile])) {
- // As we're shutting down, we need to nuke the TabRestoreService, which will
- // start the shutdown of the NavigationControllers and allow for proper
- // shutdown. If we don't do this chrome won't shutdown cleanly, and may end
- // up crashing when some thread tries to use the IO thread (or another
- // thread) that is no longer valid.
+ // As we're shutting down, we need to nuke the TabRestoreService, which
+ // will start the shutdown of the NavigationControllers and allow for
+ // proper shutdown. If we don't do this, Chrome won't shut down cleanly,
+ // and may end up crashing when some thread tries to use the IO thread (or
+ // another thread) that is no longer valid.
[self defaultProfile]->ResetTabRestoreService();
}
-
- [[NSNotificationCenter defaultCenter] removeObserver:self];
}
// Helper routine to get the window controller if the key window is a tabbed
@@ -380,43 +399,6 @@
return YES;
}
-// We can't use the standard terminate: method because it will abruptly exit
-// the app and leave things on the stack in an unfinalized state. We need to
-// post a quit message to our run loop so the stack can gracefully unwind.
-- (IBAction)quit:(id)sender {
- if ([self applicationShouldTerminate:NSApp] == NSTerminateCancel)
- return;
-
- // TODO(pinkerton):
- // since we have to roll it ourselves, ask the delegate (ourselves, really)
- // if we should terminate. For example, we might not want to if the user
- // has ongoing downloads or multiple windows/tabs open. However, this would
- // require posting UI and may require spinning up another run loop to
- // handle it. If it says to continue, post the quit message, otherwise
- // go back to normal.
-
- NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager];
- [em removeEventHandlerForEventClass:kInternetEventClass
- andEventID:kAEGetURL];
- [em removeEventHandlerForEventClass:'WWW!'
- andEventID:'OURL'];
- [em removeEventHandlerForEventClass:kCoreEventClass
- andEventID:kAEOpenDocuments];
-
- // TODO(pinkerton): Not sure where this should live, including it here
- // causes all sorts of asserts from the open renderers. On Windows, it
- // lives in Browser::OnWindowClosing, but that's not appropriate on Mac
- // since we don't shut down when we reach zero windows.
- // browser_shutdown::OnShutdownStarting(browser_shutdown::WINDOW_CLOSE);
-
- // Close all the windows.
- BrowserList::CloseAllBrowsers(true);
-
- // Release the reference to the browser process. Once all the browsers get
- // dealloc'd, it will stop the RunLoop and fall back into main().
- g_browser_process->ReleaseModule();
-}
-
// Called to determine if we should enable the "restore tab" menu item.
// Checks with the TabRestoreService to see if there's anything there to
// restore and returns YES if so.
@@ -445,7 +427,7 @@
enable = menuState_->IsCommandEnabled(tag) ? YES : NO;
}
}
- } else if (action == @selector(quit:)) {
+ } else if (action == @selector(terminate:)) {
enable = YES;
} else if (action == @selector(showPreferences:)) {
enable = YES;
diff --git a/chrome/browser/automation/automation_provider_list_mac.mm b/chrome/browser/automation/automation_provider_list_mac.mm
index 4d408fd..2cfdb3f 100644
--- a/chrome/browser/automation/automation_provider_list_mac.mm
+++ b/chrome/browser/automation/automation_provider_list_mac.mm
@@ -4,10 +4,10 @@
#include "chrome/browser/automation/automation_provider_list.h"
-#import "chrome/browser/app_controller_mac.h"
+#import <AppKit/AppKit.h>
void AutomationProviderList::OnLastProviderRemoved() {
// We need to explicitly quit the application here because on Mac
// the controller holds an additional reference to g_browser_process.
- [[NSApp delegate] quit:nil];
+ [NSApp terminate:nil];
}
diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc
index c20c7a3..97b589a 100644
--- a/chrome/browser/browser_main.cc
+++ b/chrome/browser/browser_main.cc
@@ -836,7 +836,7 @@ int BrowserMain(const MainFunctionParams& parameters) {
process_singleton.Cleanup();
- Platform::WillTerminate();
+ Platform::DidEndMainMessageLoop();
if (metrics)
metrics->Stop();
diff --git a/chrome/browser/browser_main.h b/chrome/browser/browser_main.h
index 2044670..44bc6ab 100644
--- a/chrome/browser/browser_main.h
+++ b/chrome/browser/browser_main.h
@@ -18,7 +18,7 @@ void WillInitializeMainMessageLoop(const MainFunctionParams& parameters);
// Perform platform-specific work that needs to be done after the main event
// loop has ended.
-void WillTerminate();
+void DidEndMainMessageLoop();
// Records the conditions that can prevent Breakpad from generating and
// sending crash reports. The presence of a Breakpad handler (after
diff --git a/chrome/browser/browser_main_gtk.cc b/chrome/browser/browser_main_gtk.cc
index 6bfa6de..beeb702 100644
--- a/chrome/browser/browser_main_gtk.cc
+++ b/chrome/browser/browser_main_gtk.cc
@@ -13,7 +13,7 @@ namespace Platform {
void WillInitializeMainMessageLoop(const MainFunctionParams& parameters) {
}
-void WillTerminate() {
+void DidEndMainMessageLoop() {
}
void RecordBreakpadStatusUMA(MetricsService* metrics) {
diff --git a/chrome/browser/browser_main_mac.mm b/chrome/browser/browser_main_mac.mm
index ca6d346..8ed837f 100644
--- a/chrome/browser/browser_main_mac.mm
+++ b/chrome/browser/browser_main_mac.mm
@@ -11,25 +11,33 @@
#include "base/debug_util.h"
#include "chrome/app/breakpad_mac.h"
#import "chrome/app/keystone_glue.h"
+#import "chrome/browser/app_controller_mac.h"
#include "chrome/browser/browser_main_win.h"
+#import "chrome/browser/chrome_application_mac.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/common/main_function_params.h"
#include "chrome/common/result_codes.h"
namespace Platform {
-// Perform any platform-specific work that needs to be done before the main
-// message loop is created and initialized.
-//
-// For Mac, this involves telling Cooca to finish its initalization, which we
-// want to do manually instead of calling NSApplicationMain(). The primary
-// reason is that NSAM() never returns, which would leave all the objects
-// currently on the stack in scoped_ptrs hanging and never cleaned up. We then
-// load the main nib directly. The main event loop is run from common code using
-// the MessageLoop API, which works out ok for us because it's a wrapper around
+// Tell Cooca to finish its initalization, which we want to do manually
+// instead of calling NSApplicationMain(). The primary reason is that NSAM()
+// never returns, which would leave all the objects currently on the stack
+// in scoped_ptrs hanging and never cleaned up. We then load the main nib
+// directly. The main event loop is run from common code using the
+// MessageLoop API, which works out ok for us because it's a wrapper around
// CFRunLoop.
void WillInitializeMainMessageLoop(const MainFunctionParams& parameters) {
- [NSApplication sharedApplication];
+ // Initialize NSApplication using the custom subclass. Check whether NSApp
+ // was already initialized using another class, because that would break
+ // some things.
+ [CrApplication sharedApplication];
+ if (![NSApp isKindOfClass:[CrApplication class]]) {
+ LOG(ERROR) << "NSApp should be of type CrApplication, not "
+ << [[NSApp className] UTF8String];
+ DCHECK(false) << "NSApp is of wrong type";
+ }
+
// Before we load the nib, we need to start up the resource bundle so we have
// the strings avaiable for localization.
if (!parameters.ui_task) {
@@ -46,13 +54,9 @@ void WillInitializeMainMessageLoop(const MainFunctionParams& parameters) {
[[KeystoneGlue defaultKeystoneGlue] registerWithKeystone];
}
-// Perform platform-specific work that needs to be done after the main event
-// loop has ended. We need to send the notifications that Cooca normally would
-// telling everyone the app is about to end.
-void WillTerminate() {
- [[NSNotificationCenter defaultCenter]
- postNotificationName:NSApplicationWillTerminateNotification
- object:NSApp];
+void DidEndMainMessageLoop() {
+ AppController* appController = [NSApp delegate];
+ [appController didEndMainMessageLoop];
}
void RecordBreakpadStatusUMA(MetricsService* metrics) {
diff --git a/chrome/browser/browser_main_win.cc b/chrome/browser/browser_main_win.cc
index b59572f..dca1bba 100644
--- a/chrome/browser/browser_main_win.cc
+++ b/chrome/browser/browser_main_win.cc
@@ -33,7 +33,7 @@ namespace Platform {
void WillInitializeMainMessageLoop(const MainFunctionParams& parameters) {
}
-void WillTerminate() {
+void DidEndMainMessageLoop() {
}
void RecordBreakpadStatusUMA(MetricsService* metrics) {
diff --git a/chrome/browser/chrome_application_mac.h b/chrome/browser/chrome_application_mac.h
new file mode 100644
index 0000000..b09af38
--- /dev/null
+++ b/chrome/browser/chrome_application_mac.h
@@ -0,0 +1,13 @@
+// Copyright (c) 2009 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 CHROME_BROWSER_CHROME_APPLICATION_MAC_H_
+#define CHROME_BROWSER_CHROME_APPLICATION_MAC_H_
+
+#import <AppKit/AppKit.h>
+
+@interface CrApplication : NSApplication
+@end
+
+#endif // CHROME_BROWSER_CHROME_APPLICATION_MAC_H_
diff --git a/chrome/browser/chrome_application_mac.mm b/chrome/browser/chrome_application_mac.mm
new file mode 100644
index 0000000..8c7d860
--- /dev/null
+++ b/chrome/browser/chrome_application_mac.mm
@@ -0,0 +1,61 @@
+// Copyright (c) 2009 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 "chrome/browser/chrome_application_mac.h"
+
+@implementation CrApplication
+
+// -terminate: is the entry point for orderly "quit" operations in Cocoa.
+// This includes the application menu's quit menu item and keyboard
+// equivalent, the application's dock icon menu's quit menu item, "quit" (not
+// "force quit") in the Activity Monitor, and quits triggered by user logout
+// and system restart and shutdown.
+//
+// The default NSApplication -terminate: implementation will end the process
+// by calling exit(), and thus never leave the main run loop. This is
+// unsuitable for Chrome's purposes. Chrome depends on leaving the main
+// run loop to perform a proper orderly shutdown. This design is ingrained
+// in the application and the assumptions that its code makes, and is
+// entirely reasonable and works well on other platforms, but it's not
+// compatible with the standard Cocoa quit sequence. Quits originated from
+// within the application can be redirected to not use -terminate:, but
+// quits from elsewhere cannot be.
+//
+// To allow the Cocoa-based Chrome to support the standard Cocoa -terminate:
+// interface, and allow all quits to cause Chrome to shut down properly
+// regardless of their origin, -terminate: is overriden. The custom
+// -terminate: does not end the application with exit(). Instead, it simply
+// returns after posting the normal NSApplicationWillTerminateNotification
+// notification. The application is responsible for exiting on its own in
+// whatever way it deems appropriate. In Chrome's case, the main run loop will
+// end and the applicaton will exit by returning from main().
+//
+// This implementation of -terminate: is scaled back and is not as
+// fully-featured as the implementation in NSApplication, nor is it a direct
+// drop-in replacement -terminate: in most applications. It is
+// purpose-specific to Chrome.
+- (void)terminate:(id)sender {
+ NSApplicationTerminateReply shouldTerminate = NSTerminateNow;
+ SEL selector = @selector(applicationShouldTerminate:);
+ if ([[self delegate] respondsToSelector:selector])
+ shouldTerminate = [[self delegate] applicationShouldTerminate:self];
+
+ // If shouldTerminate is NSTerminateLater, the application is expected to
+ // call -replyToApplicationShouldTerminate: when it knows whether or not it
+ // should terminate. If the argument is YES,
+ // -replyToApplicationShouldTerminate: will call -terminate:. This will
+ // result in another call to the delegate's -applicationShouldTerminate:,
+ // which would be expected to return NSTerminateNow at that point.
+ if (shouldTerminate != NSTerminateNow)
+ return;
+
+ [[NSNotificationCenter defaultCenter]
+ postNotificationName:NSApplicationWillTerminateNotification
+ object:self];
+
+ // Return, don't exit. The application is responsible for exiting on its
+ // own.
+}
+
+@end
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 5066b65..a9fce17 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -845,6 +845,8 @@
'browser/character_encoding.h',
'browser/child_process_security_policy.cc',
'browser/child_process_security_policy.h',
+ 'browser/chrome_application_mac.h',
+ 'browser/chrome_application_mac.mm',
'browser/chrome_plugin_browsing_context.cc',
'browser/chrome_plugin_browsing_context.h',
'browser/chrome_plugin_host.cc',