OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/chrome_browser_application_mac.h" | 5 #import "chrome/browser/chrome_browser_application_mac.h" |
6 | 6 |
7 #import "base/logging.h" | 7 #import "base/logging.h" |
8 #include "base/mac/crash_logging.h" | 8 #include "base/mac/crash_logging.h" |
9 #import "base/mac/scoped_nsexception_enabler.h" | 9 #import "base/mac/scoped_nsexception_enabler.h" |
10 #import "base/metrics/histogram.h" | 10 #import "base/metrics/histogram.h" |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 } | 214 } |
215 | 215 |
216 - (id)init { | 216 - (id)init { |
217 SwizzleInit(); | 217 SwizzleInit(); |
218 if ((self = [super init])) { | 218 if ((self = [super init])) { |
219 eventHooks_.reset([[NSMutableArray alloc] init]); | 219 eventHooks_.reset([[NSMutableArray alloc] init]); |
220 } | 220 } |
221 return self; | 221 return self; |
222 } | 222 } |
223 | 223 |
| 224 // Initialize NSApplication using the custom subclass. Check whether NSApp |
| 225 // was already initialized using another class, because that would break |
| 226 // some things. |
| 227 + (NSApplication*)sharedApplication { |
| 228 NSApplication* app = [super sharedApplication]; |
| 229 |
| 230 // +sharedApplication initializes the global NSApp, so if a specific |
| 231 // NSApplication subclass is requested, require that to be the one |
| 232 // delivered. The practical effect is to require a consistent NSApp |
| 233 // across the executable. |
| 234 CHECK([NSApp isKindOfClass:self]) |
| 235 << "NSApp must be of type " << [[self className] UTF8String] |
| 236 << ", not " << [[NSApp className] UTF8String]; |
| 237 |
| 238 // If the message loop was initialized before NSApp is setup, the |
| 239 // message pump will be setup incorrectly. Failing this implies |
| 240 // that RegisterBrowserCrApp() should be called earlier. |
| 241 CHECK(base::MessagePumpMac::UsingCrApp()) |
| 242 << "MessagePumpMac::Create() is using the wrong pump implementation" |
| 243 << " for " << [[self className] UTF8String]; |
| 244 |
| 245 return app; |
| 246 } |
| 247 |
224 //////////////////////////////////////////////////////////////////////////////// | 248 //////////////////////////////////////////////////////////////////////////////// |
225 // HISTORICAL COMMENT (by viettrungluu, from | 249 // HISTORICAL COMMENT (by viettrungluu, from |
226 // http://codereview.chromium.org/1520006 with mild editing): | 250 // http://codereview.chromium.org/1520006 with mild editing): |
227 // | 251 // |
228 // A quick summary of the state of things (before the changes to shutdown): | 252 // A quick summary of the state of things (before the changes to shutdown): |
229 // | 253 // |
230 // Currently, we are totally hosed (put in a bad state in which Cmd-W does the | 254 // Currently, we are totally hosed (put in a bad state in which Cmd-W does the |
231 // wrong thing, and which will probably eventually lead to a crash) if we begin | 255 // wrong thing, and which will probably eventually lead to a crash) if we begin |
232 // quitting but termination is aborted for some reason. | 256 // quitting but termination is aborted for some reason. |
233 // | 257 // |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 } | 385 } |
362 | 386 |
363 - (void)addEventHook:(id<CrApplicationEventHookProtocol>)handler { | 387 - (void)addEventHook:(id<CrApplicationEventHookProtocol>)handler { |
364 [eventHooks_ addObject:handler]; | 388 [eventHooks_ addObject:handler]; |
365 } | 389 } |
366 | 390 |
367 - (void)removeEventHook:(id<CrApplicationEventHookProtocol>)handler { | 391 - (void)removeEventHook:(id<CrApplicationEventHookProtocol>)handler { |
368 [eventHooks_ removeObject:handler]; | 392 [eventHooks_ removeObject:handler]; |
369 } | 393 } |
370 | 394 |
| 395 - (BOOL)isHandlingSendEvent { |
| 396 return handlingSendEvent_; |
| 397 } |
| 398 |
| 399 - (void)setHandlingSendEvent:(BOOL)handlingSendEvent { |
| 400 handlingSendEvent_ = handlingSendEvent; |
| 401 } |
| 402 |
371 - (void)sendEvent:(NSEvent*)event { | 403 - (void)sendEvent:(NSEvent*)event { |
372 base::mac::ScopedSendingEvent sendingEventScoper; | 404 base::mac::ScopedSendingEvent sendingEventScoper; |
373 for (id<CrApplicationEventHookProtocol> handler in eventHooks_.get()) { | 405 for (id<CrApplicationEventHookProtocol> handler in eventHooks_.get()) { |
374 [handler hookForEvent:event]; | 406 [handler hookForEvent:event]; |
375 } | 407 } |
376 [super sendEvent:event]; | 408 [super sendEvent:event]; |
377 } | 409 } |
378 | 410 |
379 // NSExceptions which are caught by the event loop are logged here. | 411 // NSExceptions which are caught by the event loop are logged here. |
380 // NSException uses setjmp/longjmp, which can be very bad for C++, so | 412 // NSException uses setjmp/longjmp, which can be very bad for C++, so |
381 // we attempt to track and report them. | 413 // we attempt to track and report them. |
382 - (void)reportException:(NSException *)anException { | 414 - (void)reportException:(NSException *)anException { |
383 // If we throw an exception in this code, we can create an infinite | 415 // If we throw an exception in this code, we can create an infinite |
384 // loop. If we throw out of the if() without resetting | 416 // loop. If we throw out of the if() without resetting |
385 // |reportException|, we'll stop reporting exceptions for this run. | 417 // |reportException|, we'll stop reporting exceptions for this run. |
386 static BOOL reportingException = NO; | 418 static BOOL reportingException = NO; |
387 DCHECK(!reportingException); | 419 DCHECK(!reportingException); |
388 if (!reportingException) { | 420 if (!reportingException) { |
389 reportingException = YES; | 421 reportingException = YES; |
390 chrome_browser_application_mac::RecordExceptionWithUma(anException); | 422 chrome_browser_application_mac::RecordExceptionWithUma(anException); |
391 | 423 |
392 // http://crbug.com/45928 is a bug about needing to double-close | 424 // http://crbug.com/45928 is a bug about needing to double-close |
393 // windows sometimes. One theory is that |-isHandlingSendEvent| | 425 // windows sometimes. One theory is that |-isHandlingSendEvent| |
394 // gets latched to always return |YES|. Since scopers are used to | 426 // gets latched to always return |YES|. Since scopers are used to |
395 // manipulate that value, that should not be possible. One way to | 427 // manipulate that value, that should not be possible. One way to |
396 // sidestep scopers is setjmp/longjmp (see above). The following | 428 // sidestep scopers is setjmp/longjmp (see above). The following |
397 // is to "fix" this while the more fundamental concern is | 429 // is to "fix" this while the more fundamental concern is |
398 // addressed elsewhere. | 430 // addressed elsewhere. |
399 [self clearIsHandlingSendEvent]; | 431 [self setHandlingSendEvent:NO]; |
400 | 432 |
401 // If |ScopedNSExceptionEnabler| is used to allow exceptions, and an | 433 // If |ScopedNSExceptionEnabler| is used to allow exceptions, and an |
402 // uncaught exception is thrown, it will throw past all of the scopers. | 434 // uncaught exception is thrown, it will throw past all of the scopers. |
403 // Reset the flag so that future exceptions are not masked. | 435 // Reset the flag so that future exceptions are not masked. |
404 base::mac::SetNSExceptionsAllowed(false); | 436 base::mac::SetNSExceptionsAllowed(false); |
405 | 437 |
406 // Store some human-readable information in breakpad keys in case | 438 // Store some human-readable information in breakpad keys in case |
407 // there is a crash. Since breakpad does not provide infinite | 439 // there is a crash. Since breakpad does not provide infinite |
408 // storage, we track two exceptions. The first exception thrown | 440 // storage, we track two exceptions. The first exception thrown |
409 // is tracked because it may be the one which caused the system to | 441 // is tracked because it may be the one which caused the system to |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
448 if (RenderViewHost* rvh = contents->render_view_host()) { | 480 if (RenderViewHost* rvh = contents->render_view_host()) { |
449 rvh->EnableRendererAccessibility(); | 481 rvh->EnableRendererAccessibility(); |
450 } | 482 } |
451 } | 483 } |
452 } | 484 } |
453 } | 485 } |
454 return [super accessibilitySetValue:value forAttribute:attribute]; | 486 return [super accessibilitySetValue:value forAttribute:attribute]; |
455 } | 487 } |
456 | 488 |
457 @end | 489 @end |
OLD | NEW |