Chromium Code Reviews| 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 #import "base/mac/scoped_nsexception_enabler.h" | |
| 8 #import "base/metrics/histogram.h" | 9 #import "base/metrics/histogram.h" |
| 9 #import "base/memory/scoped_nsobject.h" | 10 #import "base/memory/scoped_nsobject.h" |
| 10 #import "base/sys_string_conversions.h" | 11 #import "base/sys_string_conversions.h" |
| 11 #import "chrome/app/breakpad_mac.h" | 12 #import "chrome/app/breakpad_mac.h" |
| 12 #include "chrome/browser/accessibility/browser_accessibility_state.h" | 13 #include "chrome/browser/accessibility/browser_accessibility_state.h" |
| 13 #import "chrome/browser/app_controller_mac.h" | 14 #import "chrome/browser/app_controller_mac.h" |
| 14 #include "chrome/browser/ui/browser_list.h" | 15 #include "chrome/browser/ui/browser_list.h" |
| 15 #import "chrome/browser/ui/cocoa/objc_method_swizzle.h" | 16 #import "chrome/browser/ui/cocoa/objc_method_swizzle.h" |
| 16 #import "chrome/browser/ui/cocoa/objc_zombie.h" | 17 #import "chrome/browser/ui/cocoa/objc_zombie.h" |
| 17 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 18 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 86 if (aName == NSInvalidArgumentException) { | 87 if (aName == NSInvalidArgumentException) { |
| 87 fatal = YES; | 88 fatal = YES; |
| 88 } | 89 } |
| 89 | 90 |
| 90 // Dear reader: Something you just did provoked an NSException. | 91 // Dear reader: Something you just did provoked an NSException. |
| 91 // NSException is implemented in terms of setjmp()/longjmp(), | 92 // NSException is implemented in terms of setjmp()/longjmp(), |
| 92 // which does poor things when combined with C++ scoping | 93 // which does poor things when combined with C++ scoping |
| 93 // (destructors are skipped). Chrome should be NSException-free, | 94 // (destructors are skipped). Chrome should be NSException-free, |
| 94 // please check your backtrace and see if you can't file a bug | 95 // please check your backtrace and see if you can't file a bug |
| 95 // with a repro case. | 96 // with a repro case. |
| 96 if (fatal) { | 97 const bool allow = base::mac::GetNSExceptionsAllowed(); |
| 98 if (fatal && !allow) { | |
| 97 LOG(FATAL) << "Someone is trying to raise an exception! " | 99 LOG(FATAL) << "Someone is trying to raise an exception! " |
| 98 << base::SysNSStringToUTF8(value); | 100 << base::SysNSStringToUTF8(value); |
| 99 } else { | 101 } else { |
| 100 // Make sure that developers see when their code throws | 102 // Make sure that developers see when their code throws |
| 101 // exceptions. | 103 // exceptions. |
| 102 DLOG(ERROR) << "Someone is trying to raise an exception! " | 104 DLOG(ERROR) << "Someone is trying to raise an exception! " |
| 103 << base::SysNSStringToUTF8(value); | 105 << base::SysNSStringToUTF8(value); |
| 104 NOTREACHED(); | 106 DCHECK(allow); |
| 105 } | 107 } |
| 106 } | 108 } |
| 107 | 109 |
| 108 // Forward to the original version. | 110 // Forward to the original version. |
| 109 return gOriginalInitIMP(self, _cmd, aName, aReason, someUserInfo); | 111 return gOriginalInitIMP(self, _cmd, aName, aReason, someUserInfo); |
| 110 } | 112 } |
| 111 @end | 113 @end |
| 112 | 114 |
| 113 namespace chrome_browser_application_mac { | 115 namespace chrome_browser_application_mac { |
| 114 | 116 |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 321 } | 323 } |
| 322 } else if ([sender isKindOfClass:[NSMenuItem class]]) { | 324 } else if ([sender isKindOfClass:[NSMenuItem class]]) { |
| 323 tag = [sender tag]; | 325 tag = [sender tag]; |
| 324 } | 326 } |
| 325 | 327 |
| 326 NSString* actionString = NSStringFromSelector(anAction); | 328 NSString* actionString = NSStringFromSelector(anAction); |
| 327 NSString* value = | 329 NSString* value = |
| 328 [NSString stringWithFormat:@"%@ tag %d sending %@ to %p", | 330 [NSString stringWithFormat:@"%@ tag %d sending %@ to %p", |
| 329 [sender className], tag, actionString, aTarget]; | 331 [sender className], tag, actionString, aTarget]; |
| 330 | 332 |
| 333 // Certain third-party code, such as print drivers, can still throw | |
| 334 // exceptions and Chromium cannot fix them. This provides a way to | |
| 335 // work around those on a spot basis. | |
| 336 bool enableNSExceptions = false; | |
| 337 | |
| 338 // http://crbug.com/80686 , an Epson printer driver. | |
| 339 if (anAction == @selector(selectPDE:)) { | |
| 340 enableNSExceptions = true; | |
| 341 } | |
| 342 | |
| 343 // These should be as close to the super call as reasonable. | |
| 344 base::mac::ScopedNSExceptionEnabler enabler(enableNSExceptions); | |
| 331 ScopedCrashKey key(kActionKey, value); | 345 ScopedCrashKey key(kActionKey, value); |
|
Mark Mentovai
2011/05/17 22:23:27
Can’t this precede ScopedNSExceptionEnabler? You c
Scott Hess - ex-Googler
2011/05/17 22:48:30
I'm not entirely sure I understand what you'd like
| |
| 346 | |
| 332 return [super sendAction:anAction to:aTarget from:sender]; | 347 return [super sendAction:anAction to:aTarget from:sender]; |
| 333 } | 348 } |
| 334 | 349 |
| 335 // NSExceptions which are caught by the event loop are logged here. | 350 // NSExceptions which are caught by the event loop are logged here. |
| 336 // NSException uses setjmp/longjmp, which can be very bad for C++, so | 351 // NSException uses setjmp/longjmp, which can be very bad for C++, so |
| 337 // we attempt to track and report them. | 352 // we attempt to track and report them. |
| 338 - (void)reportException:(NSException *)anException { | 353 - (void)reportException:(NSException *)anException { |
| 339 // If we throw an exception in this code, we can create an infinite | 354 // If we throw an exception in this code, we can create an infinite |
| 340 // loop. If we throw out of the if() without resetting | 355 // loop. If we throw out of the if() without resetting |
| 341 // |reportException|, we'll stop reporting exceptions for this run. | 356 // |reportException|, we'll stop reporting exceptions for this run. |
| 342 static BOOL reportingException = NO; | 357 static BOOL reportingException = NO; |
| 343 DCHECK(!reportingException); | 358 DCHECK(!reportingException); |
| 344 if (!reportingException) { | 359 if (!reportingException) { |
| 345 reportingException = YES; | 360 reportingException = YES; |
| 346 chrome_browser_application_mac::RecordExceptionWithUma(anException); | 361 chrome_browser_application_mac::RecordExceptionWithUma(anException); |
| 347 | 362 |
| 348 // http://crbug.com/45928 is a bug about needing to double-close | 363 // http://crbug.com/45928 is a bug about needing to double-close |
| 349 // windows sometimes. One theory is that |-isHandlingSendEvent| | 364 // windows sometimes. One theory is that |-isHandlingSendEvent| |
| 350 // gets latched to always return |YES|. Since scopers are used to | 365 // gets latched to always return |YES|. Since scopers are used to |
| 351 // manipulate that value, that should not be possible. One way to | 366 // manipulate that value, that should not be possible. One way to |
| 352 // sidestep scopers is setjmp/longjmp (see above). The following | 367 // sidestep scopers is setjmp/longjmp (see above). The following |
| 353 // is to "fix" this while the more fundamental concern is | 368 // is to "fix" this while the more fundamental concern is |
| 354 // addressed elsewhere. | 369 // addressed elsewhere. |
| 355 [self clearIsHandlingSendEvent]; | 370 [self clearIsHandlingSendEvent]; |
| 356 | 371 |
| 372 // If |ScopedNSExceptionEnabler| is used to allow exceptions, and | |
| 373 // an uncaught exception is thrown, the flag must be reset so that | |
| 374 // future exceptions are not masked. | |
|
Mark Mentovai
2011/05/17 22:23:27
Can you at least say here that stuff will have unw
Scott Hess - ex-Googler
2011/05/17 22:48:30
OK.
| |
| 375 base::mac::SetNSExceptionsAllowed(false); | |
| 376 | |
| 357 // Store some human-readable information in breakpad keys in case | 377 // Store some human-readable information in breakpad keys in case |
| 358 // there is a crash. Since breakpad does not provide infinite | 378 // there is a crash. Since breakpad does not provide infinite |
| 359 // storage, we track two exceptions. The first exception thrown | 379 // storage, we track two exceptions. The first exception thrown |
| 360 // is tracked because it may be the one which caused the system to | 380 // is tracked because it may be the one which caused the system to |
| 361 // go off the rails. The last exception thrown is tracked because | 381 // go off the rails. The last exception thrown is tracked because |
| 362 // it may be the one most directly associated with the crash. | 382 // it may be the one most directly associated with the crash. |
| 363 static NSString* const kFirstExceptionKey = @"firstexception"; | 383 static NSString* const kFirstExceptionKey = @"firstexception"; |
| 364 static BOOL trackedFirstException = NO; | 384 static BOOL trackedFirstException = NO; |
| 365 static NSString* const kLastExceptionKey = @"lastexception"; | 385 static NSString* const kLastExceptionKey = @"lastexception"; |
| 366 | 386 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 399 if (RenderViewHost* rvh = contents->render_view_host()) { | 419 if (RenderViewHost* rvh = contents->render_view_host()) { |
| 400 rvh->EnableRendererAccessibility(); | 420 rvh->EnableRendererAccessibility(); |
| 401 } | 421 } |
| 402 } | 422 } |
| 403 } | 423 } |
| 404 } | 424 } |
| 405 return [super accessibilitySetValue:value forAttribute:attribute]; | 425 return [super accessibilitySetValue:value forAttribute:attribute]; |
| 406 } | 426 } |
| 407 | 427 |
| 408 @end | 428 @end |
| OLD | NEW |