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 |