| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "chrome/browser/app_controller_mac.h" | 5 #import "chrome/browser/app_controller_mac.h" |
| 6 | 6 |
| 7 #include "app/l10n_util.h" | 7 #include "app/l10n_util.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/mac_util.h" | 9 #include "base/mac_util.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| 11 #include "base/sys_string_conversions.h" | 11 #include "base/sys_string_conversions.h" |
| 12 #include "chrome/app/chrome_dll_resource.h" | 12 #include "chrome/app/chrome_dll_resource.h" |
| 13 #include "chrome/browser/browser.h" | 13 #include "chrome/browser/browser.h" |
| 14 #include "chrome/browser/browser_init.h" | 14 #include "chrome/browser/browser_init.h" |
| 15 #include "chrome/browser/browser_list.h" | 15 #include "chrome/browser/browser_list.h" |
| 16 #include "chrome/browser/browser_process.h" | 16 #include "chrome/browser/browser_process.h" |
| 17 #include "chrome/browser/browser_shutdown.h" | 17 #include "chrome/browser/browser_shutdown.h" |
| 18 #include "chrome/browser/browser_window.h" | 18 #include "chrome/browser/browser_window.h" |
| 19 #import "chrome/browser/cocoa/about_window_controller.h" | 19 #import "chrome/browser/cocoa/about_window_controller.h" |
| 20 #import "chrome/browser/cocoa/bookmark_menu_bridge.h" | 20 #import "chrome/browser/cocoa/bookmark_menu_bridge.h" |
| 21 #import "chrome/browser/cocoa/browser_window_cocoa.h" |
| 22 #import "chrome/browser/cocoa/browser_window_controller.h" |
| 21 #import "chrome/browser/cocoa/history_menu_bridge.h" | 23 #import "chrome/browser/cocoa/history_menu_bridge.h" |
| 22 #import "chrome/browser/cocoa/clear_browsing_data_controller.h" | 24 #import "chrome/browser/cocoa/clear_browsing_data_controller.h" |
| 23 #import "chrome/browser/cocoa/encoding_menu_controller_delegate_mac.h" | 25 #import "chrome/browser/cocoa/encoding_menu_controller_delegate_mac.h" |
| 24 #import "chrome/browser/cocoa/preferences_window_controller.h" | 26 #import "chrome/browser/cocoa/preferences_window_controller.h" |
| 25 #import "chrome/browser/cocoa/tab_strip_controller.h" | 27 #import "chrome/browser/cocoa/tab_strip_controller.h" |
| 26 #import "chrome/browser/cocoa/tab_window_controller.h" | 28 #import "chrome/browser/cocoa/tab_window_controller.h" |
| 27 #import "chrome/browser/cocoa/ui_localizer.h" | 29 #import "chrome/browser/cocoa/ui_localizer.h" |
| 28 #include "chrome/browser/command_updater.h" | 30 #include "chrome/browser/command_updater.h" |
| 29 #include "chrome/browser/download/download_manager.h" | 31 #include "chrome/browser/download/download_manager.h" |
| 32 #include "chrome/browser/tab_contents/tab_contents.h" |
| 30 #include "chrome/browser/sessions/tab_restore_service.h" | 33 #include "chrome/browser/sessions/tab_restore_service.h" |
| 31 #include "chrome/common/pref_names.h" | 34 #include "chrome/common/pref_names.h" |
| 32 #include "chrome/common/pref_service.h" | 35 #include "chrome/common/pref_service.h" |
| 33 #include "chrome/browser/profile_manager.h" | 36 #include "chrome/browser/profile_manager.h" |
| 34 #include "chrome/common/temp_scaffolding_stubs.h" | 37 #include "chrome/common/temp_scaffolding_stubs.h" |
| 35 #include "grit/generated_resources.h" | 38 #include "grit/generated_resources.h" |
| 36 | 39 |
| 37 @interface AppController(PRIVATE) | 40 @interface AppController(PRIVATE) |
| 38 - (void)initMenuState; | 41 - (void)initMenuState; |
| 39 - (void)openURLs:(const std::vector<GURL>&)urls; | 42 - (void)openURLs:(const std::vector<GURL>&)urls; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 [notificationCenter | 104 [notificationCenter |
| 102 addObserver:self | 105 addObserver:self |
| 103 selector:@selector(tabsChanged:) | 106 selector:@selector(tabsChanged:) |
| 104 name:kTabStripNumberOfTabsChanged | 107 name:kTabStripNumberOfTabsChanged |
| 105 object:nil]; | 108 object:nil]; |
| 106 | 109 |
| 107 // Set up the command updater for when there are no windows open | 110 // Set up the command updater for when there are no windows open |
| 108 [self initMenuState]; | 111 [self initMenuState]; |
| 109 } | 112 } |
| 110 | 113 |
| 114 // Checks if there are any tabs with sheets open, and if so, raises one of |
| 115 // the tabs with a sheet and returns NO. |
| 116 - (BOOL)shouldQuitWithOpenPerTabSheets { |
| 117 BrowserList::const_iterator it = BrowserList::begin(); |
| 118 for (; it != BrowserList::end(); ++it) { |
| 119 Browser* browser = *it; |
| 120 BrowserWindowCocoa* window = |
| 121 static_cast<BrowserWindowCocoa*>(browser->window()); |
| 122 |
| 123 // Could do this more nicely with a method e.g. on BWC. If I decide for |
| 124 // keeping it this way, at least add a DCHECK(). |
| 125 BrowserWindowController* controller = |
| 126 (BrowserWindowController*)[window->GetNativeHandle() windowController]; |
| 127 |
| 128 if (![controller shouldCloseWithOpenPerTabSheets]) |
| 129 return NO; |
| 130 } |
| 131 |
| 132 return YES; |
| 133 } |
| 134 |
| 135 // We do not use the normal application teardown process -- this function is |
| 136 // not called by the system but by us in |quit:|. |NSTerminateLater| is not a |
| 137 // return value that is supported by |quit:|. |
| 138 - (NSApplicationTerminateReply)applicationShouldTerminate: |
| 139 (NSApplication *)sender { |
| 140 // Do not quit if any per-tab sheets are open, as required by |
| 141 // GTMWindowSheetController. |
| 142 if (![self shouldQuitWithOpenPerTabSheets]) |
| 143 return NSTerminateCancel; |
| 144 |
| 145 // Check for in-progress downloads, and prompt the user if they really want to |
| 146 // quit (and thus cancel the downloads). |
| 147 if (![self shouldQuitWithInProgressDownloads]) |
| 148 return NSTerminateCancel; |
| 149 |
| 150 return NSTerminateNow; |
| 151 } |
| 152 |
| 111 // Called when the app is shutting down. Clean-up as appropriate. | 153 // Called when the app is shutting down. Clean-up as appropriate. |
| 112 - (void)applicationWillTerminate:(NSNotification *)aNotification { | 154 - (void)applicationWillTerminate:(NSNotification *)aNotification { |
| 113 DCHECK(!BrowserList::HasBrowserWithProfile([self defaultProfile])); | 155 DCHECK(!BrowserList::HasBrowserWithProfile([self defaultProfile])); |
| 114 if (!BrowserList::HasBrowserWithProfile([self defaultProfile])) { | 156 if (!BrowserList::HasBrowserWithProfile([self defaultProfile])) { |
| 115 // As we're shutting down, we need to nuke the TabRestoreService, which will | 157 // As we're shutting down, we need to nuke the TabRestoreService, which will |
| 116 // start the shutdown of the NavigationControllers and allow for proper | 158 // start the shutdown of the NavigationControllers and allow for proper |
| 117 // shutdown. If we don't do this chrome won't shutdown cleanly, and may end | 159 // shutdown. If we don't do this chrome won't shutdown cleanly, and may end |
| 118 // up crashing when some thread tries to use the IO thread (or another | 160 // up crashing when some thread tries to use the IO thread (or another |
| 119 // thread) that is no longer valid. | 161 // thread) that is no longer valid. |
| 120 [self defaultProfile]->ResetTabRestoreService(); | 162 [self defaultProfile]->ResetTabRestoreService(); |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 } | 373 } |
| 332 | 374 |
| 333 // No profiles or active downloads found, okay to exit. | 375 // No profiles or active downloads found, okay to exit. |
| 334 return YES; | 376 return YES; |
| 335 } | 377 } |
| 336 | 378 |
| 337 // We can't use the standard terminate: method because it will abruptly exit | 379 // We can't use the standard terminate: method because it will abruptly exit |
| 338 // the app and leave things on the stack in an unfinalized state. We need to | 380 // the app and leave things on the stack in an unfinalized state. We need to |
| 339 // post a quit message to our run loop so the stack can gracefully unwind. | 381 // post a quit message to our run loop so the stack can gracefully unwind. |
| 340 - (IBAction)quit:(id)sender { | 382 - (IBAction)quit:(id)sender { |
| 383 if ([self applicationShouldTerminate:NSApp] == NSTerminateCancel) |
| 384 return; |
| 385 |
| 341 // TODO(pinkerton): | 386 // TODO(pinkerton): |
| 342 // since we have to roll it ourselves, ask the delegate (ourselves, really) | 387 // since we have to roll it ourselves, ask the delegate (ourselves, really) |
| 343 // if we should terminate. For example, we might not want to if the user | 388 // if we should terminate. For example, we might not want to if the user |
| 344 // has ongoing downloads or multiple windows/tabs open. However, this would | 389 // has ongoing downloads or multiple windows/tabs open. However, this would |
| 345 // require posting UI and may require spinning up another run loop to | 390 // require posting UI and may require spinning up another run loop to |
| 346 // handle it. If it says to continue, post the quit message, otherwise | 391 // handle it. If it says to continue, post the quit message, otherwise |
| 347 // go back to normal. | 392 // go back to normal. |
| 348 | 393 |
| 349 // Check for in-progress downloads, and prompt the user if they really want to | |
| 350 // quit (and thus cancel the downloads). | |
| 351 if (![self shouldQuitWithInProgressDownloads]) | |
| 352 return; | |
| 353 | |
| 354 NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; | 394 NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; |
| 355 [em removeEventHandlerForEventClass:kInternetEventClass | 395 [em removeEventHandlerForEventClass:kInternetEventClass |
| 356 andEventID:kAEGetURL]; | 396 andEventID:kAEGetURL]; |
| 357 [em removeEventHandlerForEventClass:'WWW!' | 397 [em removeEventHandlerForEventClass:'WWW!' |
| 358 andEventID:'OURL']; | 398 andEventID:'OURL']; |
| 359 [em removeEventHandlerForEventClass:kCoreEventClass | 399 [em removeEventHandlerForEventClass:kCoreEventClass |
| 360 andEventID:kAEOpenDocuments]; | 400 andEventID:kAEOpenDocuments]; |
| 361 | 401 |
| 362 // TODO(pinkerton): Not sure where this should live, including it here | 402 // TODO(pinkerton): Not sure where this should live, including it here |
| 363 // causes all sorts of asserts from the open renderers. On Windows, it | 403 // causes all sorts of asserts from the open renderers. On Windows, it |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 name:kUserClosedAboutNotification | 665 name:kUserClosedAboutNotification |
| 626 object:aboutController_.get()]; | 666 object:aboutController_.get()]; |
| 627 } | 667 } |
| 628 if (![[aboutController_ window] isVisible]) | 668 if (![[aboutController_ window] isVisible]) |
| 629 [[aboutController_ window] center]; | 669 [[aboutController_ window] center]; |
| 630 [aboutController_ showWindow:self]; | 670 [aboutController_ showWindow:self]; |
| 631 #endif | 671 #endif |
| 632 } | 672 } |
| 633 | 673 |
| 634 @end | 674 @end |
| OLD | NEW |