OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "app/l10n_util_mac.h" | 8 #include "app/l10n_util_mac.h" |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
11 #include "base/file_path.h" | 11 #include "base/file_path.h" |
12 #include "base/mac_util.h" | 12 #include "base/mac_util.h" |
13 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
14 #include "base/string_number_conversions.h" | 14 #include "base/string_number_conversions.h" |
15 #include "base/sys_string_conversions.h" | 15 #include "base/sys_string_conversions.h" |
16 #include "chrome/app/chrome_dll_resource.h" | 16 #include "chrome/app/chrome_dll_resource.h" |
17 #include "chrome/browser/browser.h" | 17 #include "chrome/browser/browser.h" |
18 #include "chrome/browser/browser_init.h" | 18 #include "chrome/browser/browser_init.h" |
19 #include "chrome/browser/browser_list.h" | 19 #include "chrome/browser/browser_list.h" |
20 #include "chrome/browser/browser_process.h" | 20 #include "chrome/browser/browser_process.h" |
21 #include "chrome/browser/browser_shutdown.h" | 21 #include "chrome/browser/browser_shutdown.h" |
22 #include "chrome/browser/browser_thread.h" | 22 #include "chrome/browser/browser_thread.h" |
23 #include "chrome/browser/browser_window.h" | 23 #include "chrome/browser/browser_window.h" |
24 #import "chrome/browser/cocoa/about_window_controller.h" | 24 #import "chrome/browser/cocoa/about_window_controller.h" |
25 #import "chrome/browser/cocoa/bookmarks/bookmark_menu_bridge.h" | 25 #import "chrome/browser/cocoa/bookmarks/bookmark_menu_bridge.h" |
26 #import "chrome/browser/cocoa/browser_window_cocoa.h" | 26 #import "chrome/browser/cocoa/browser_window_cocoa.h" |
27 #import "chrome/browser/cocoa/browser_window_controller.h" | 27 #import "chrome/browser/cocoa/browser_window_controller.h" |
28 #import "chrome/browser/cocoa/bug_report_window_controller.h" | 28 #import "chrome/browser/cocoa/bug_report_window_controller.h" |
29 #import "chrome/browser/cocoa/clear_browsing_data_controller.h" | 29 #import "chrome/browser/cocoa/clear_browsing_data_controller.h" |
30 #import "chrome/browser/cocoa/confirm_quit_panel_controller.h" | |
30 #import "chrome/browser/cocoa/encoding_menu_controller_delegate_mac.h" | 31 #import "chrome/browser/cocoa/encoding_menu_controller_delegate_mac.h" |
31 #import "chrome/browser/cocoa/history_menu_bridge.h" | 32 #import "chrome/browser/cocoa/history_menu_bridge.h" |
32 #import "chrome/browser/cocoa/import_settings_dialog.h" | 33 #import "chrome/browser/cocoa/import_settings_dialog.h" |
33 #import "chrome/browser/cocoa/preferences_window_controller.h" | 34 #import "chrome/browser/cocoa/preferences_window_controller.h" |
34 #import "chrome/browser/cocoa/tab_strip_controller.h" | 35 #import "chrome/browser/cocoa/tab_strip_controller.h" |
35 #import "chrome/browser/cocoa/tab_window_controller.h" | 36 #import "chrome/browser/cocoa/tab_window_controller.h" |
36 #include "chrome/browser/cocoa/task_manager_mac.h" | 37 #include "chrome/browser/cocoa/task_manager_mac.h" |
37 #include "chrome/browser/command_updater.h" | 38 #include "chrome/browser/command_updater.h" |
38 #include "chrome/browser/download/download_manager.h" | 39 #include "chrome/browser/download/download_manager.h" |
39 #include "chrome/browser/metrics/user_metrics.h" | 40 #include "chrome/browser/metrics/user_metrics.h" |
(...skipping 195 matching lines...) Loading... | |
235 // shutting down, else the user might be prompted multiple times if the | 236 // shutting down, else the user might be prompted multiple times if the |
236 // download isn't stopped before terminate is called again. | 237 // download isn't stopped before terminate is called again. |
237 if (!browser_shutdown::IsTryingToQuit() && | 238 if (!browser_shutdown::IsTryingToQuit() && |
238 ![self shouldQuitWithInProgressDownloads]) | 239 ![self shouldQuitWithInProgressDownloads]) |
239 return NO; | 240 return NO; |
240 | 241 |
241 // TODO(viettrungluu): Remove Apple Event handlers here? (It's safe to leave | 242 // TODO(viettrungluu): Remove Apple Event handlers here? (It's safe to leave |
242 // them in, but I'm not sure about UX; we'd also want to disable other things | 243 // them in, but I'm not sure about UX; we'd also want to disable other things |
243 // though.) http://crbug.com/40861 | 244 // though.) http://crbug.com/40861 |
244 | 245 |
246 // Check if the user really wants to quit by employing the confirm-to-quit | |
247 // mechanism. | |
248 if (!browser_shutdown::IsTryingToQuit() && | |
249 [self applicationShouldTerminate:app] != NSTerminateNow) | |
250 return NO; | |
251 | |
245 size_t num_browsers = BrowserList::size(); | 252 size_t num_browsers = BrowserList::size(); |
246 | 253 |
247 // Give any print jobs in progress time to finish. | 254 // Give any print jobs in progress time to finish. |
248 if (!browser_shutdown::IsTryingToQuit()) | 255 if (!browser_shutdown::IsTryingToQuit()) |
249 g_browser_process->print_job_manager()->StopJobs(true); | 256 g_browser_process->print_job_manager()->StopJobs(true); |
250 | 257 |
251 // Initiate a shutdown (via BrowserList::CloseAllBrowsers()) if we aren't | 258 // Initiate a shutdown (via BrowserList::CloseAllBrowsers()) if we aren't |
252 // already shutting down. | 259 // already shutting down. |
253 if (!browser_shutdown::IsTryingToQuit()) | 260 if (!browser_shutdown::IsTryingToQuit()) |
254 BrowserList::CloseAllBrowsers(); | 261 BrowserList::CloseAllBrowsers(); |
255 | 262 |
256 return num_browsers == 0 ? YES : NO; | 263 return num_browsers == 0 ? YES : NO; |
257 } | 264 } |
258 | 265 |
259 - (void)stopTryingToTerminateApplication:(NSApplication*)app { | 266 - (void)stopTryingToTerminateApplication:(NSApplication*)app { |
260 if (browser_shutdown::IsTryingToQuit()) { | 267 if (browser_shutdown::IsTryingToQuit()) { |
261 // Reset the "trying to quit" state, so that closing all browser windows | 268 // Reset the "trying to quit" state, so that closing all browser windows |
262 // will no longer lead to termination. | 269 // will no longer lead to termination. |
263 browser_shutdown::SetTryingToQuit(false); | 270 browser_shutdown::SetTryingToQuit(false); |
264 | 271 |
265 // TODO(viettrungluu): Were we to remove Apple Event handlers above, we | 272 // TODO(viettrungluu): Were we to remove Apple Event handlers above, we |
266 // would have to reinstall them here. http://crbug.com/40861 | 273 // would have to reinstall them here. http://crbug.com/40861 |
267 } | 274 } |
268 } | 275 } |
269 | 276 |
277 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)app { | |
278 // Check if the experiment is enabled. | |
viettrungluu
2010/11/02 17:28:13
Probably you should say which experiment.
| |
279 const CommandLine* commandLine(CommandLine::ForCurrentProcess()); | |
280 if (!commandLine->HasSwitch(switches::kEnableConfirmToQuit)) | |
281 return NSTerminateNow; | |
282 | |
283 // If the application is going to terminate as the result of a Cmd+Q | |
284 // invocation, use the special sauce to prevent accidental quitting. | |
285 // http://dev.chromium.org/developers/design-documents/confirm-to-quit-experim ent | |
286 NSEvent* currentEvent = [app currentEvent]; | |
287 if ([currentEvent type] == NSKeyDown) { | |
288 ConfirmQuitPanelController* quitPanel = | |
289 [[ConfirmQuitPanelController alloc] init]; // Releases self. | |
290 // Show the info panel that explains what the user must to do confirm quit. | |
291 [quitPanel showWindow:self]; | |
292 | |
293 // How long the user must hold down Cmd+Q to confirm the quit. | |
294 const NSTimeInterval kTimeToConfirmQuit = 1.5; | |
295 // Leeway between the |targetDate| and the current time that will confirm a | |
296 // quit. | |
297 const NSTimeInterval kTimeDeltaFuzzFactor = 1.0; | |
298 // Duration of the window fade out animation. | |
299 const NSTimeInterval kWindowFadeAnimationDuration = 0.2; | |
300 | |
301 // Spin a nested run loop until the |targetDate| is reached or a KeyUp event | |
302 // is sent. | |
303 NSDate* targetDate = | |
304 [NSDate dateWithTimeIntervalSinceNow:kTimeToConfirmQuit]; | |
305 BOOL willQuit = NO; | |
306 NSEvent* nextEvent = nil; | |
307 do { | |
viettrungluu
2010/11/02 17:28:13
Generically, I'm kind of scared of this, though I
Robert Sesek
2010/11/02 20:05:58
Open new window: OK
Extension close window: OK
JS
| |
308 // Dequeue events until a key up is received. | |
309 nextEvent = [app nextEventMatchingMask:NSKeyUpMask | |
310 untilDate:nil | |
311 inMode:NSEventTrackingRunLoopMode | |
312 dequeue:YES]; | |
313 | |
314 // Wait for the time expiry to happen. Once past the hold threshold, | |
315 // commit to quitting and hide all the open windows. | |
316 if (!willQuit) { | |
317 NSDate* now = [NSDate date]; | |
318 NSTimeInterval difference = [targetDate timeIntervalSinceDate:now]; | |
319 if (difference < kTimeDeltaFuzzFactor) { | |
320 willQuit = YES; | |
321 | |
322 // At this point, the quit has been confirmed and windows should all | |
323 // fade out to convince the user to release the key combo to finalize | |
324 // the quit. | |
325 [NSAnimationContext beginGrouping]; | |
326 [[NSAnimationContext currentContext] setDuration: | |
327 kWindowFadeAnimationDuration]; | |
328 for (NSWindow* aWindow in [app windows]) { | |
329 // Windows that are set to animate and have a delegate do not | |
330 // expect to be animated by other things and could result in an | |
331 // invalid state. If a window is set up like so, just force the | |
332 // alpha value to 0. Otherwise, animate all pretty and stuff. | |
333 if (![[aWindow animationForKey:@"alphaValue"] delegate]) { | |
334 [[aWindow animator] setAlphaValue:0.0]; | |
335 } else { | |
336 [aWindow setAlphaValue:0.0]; | |
337 } | |
338 } | |
339 [NSAnimationContext endGrouping]; | |
340 } | |
341 } | |
342 } while (!nextEvent); | |
343 | |
344 // The user has released the key combo. Discard any events (i.e. the | |
345 // repeated KeyDown Cmd+Q). | |
346 [app discardEventsMatchingMask:NSAnyEventMask beforeEvent:nextEvent]; | |
347 if (willQuit) { | |
348 // The user held down the combination long enough that quitting should | |
349 // happen. | |
350 return NSTerminateNow; | |
351 } else { | |
352 // Slowly fade the confirm window out in case the user doesn't | |
353 // understand what they have to do to quit. | |
354 [quitPanel dismissPanel]; | |
355 return NSTerminateCancel; | |
356 } | |
357 } // if event type is KeyDown | |
358 | |
359 // Default case: terminate. | |
360 return NSTerminateNow; | |
361 } | |
362 | |
270 // Called when the app is shutting down. Clean-up as appropriate. | 363 // Called when the app is shutting down. Clean-up as appropriate. |
271 - (void)applicationWillTerminate:(NSNotification*)aNotification { | 364 - (void)applicationWillTerminate:(NSNotification*)aNotification { |
272 NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; | 365 NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; |
273 [em removeEventHandlerForEventClass:kInternetEventClass | 366 [em removeEventHandlerForEventClass:kInternetEventClass |
274 andEventID:kAEGetURL]; | 367 andEventID:kAEGetURL]; |
275 [em removeEventHandlerForEventClass:'WWW!' | 368 [em removeEventHandlerForEventClass:'WWW!' |
276 andEventID:'OURL']; | 369 andEventID:'OURL']; |
277 | 370 |
278 // There better be no browser windows left at this point. | 371 // There better be no browser windows left at this point. |
279 CHECK_EQ(BrowserList::size(), 0u); | 372 CHECK_EQ(BrowserList::size(), 0u); |
(...skipping 822 matching lines...) Loading... | |
1102 [appController showPreferencesWindow:nil page:page profile:profile]; | 1195 [appController showPreferencesWindow:nil page:page profile:profile]; |
1103 } | 1196 } |
1104 | 1197 |
1105 namespace app_controller_mac { | 1198 namespace app_controller_mac { |
1106 | 1199 |
1107 bool IsOpeningNewWindow() { | 1200 bool IsOpeningNewWindow() { |
1108 return g_is_opening_new_window; | 1201 return g_is_opening_new_window; |
1109 } | 1202 } |
1110 | 1203 |
1111 } // namespace app_controller_mac | 1204 } // namespace app_controller_mac |
OLD | NEW |