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) { | |
Mark Mentovai
2011/05/17 19:07:34
If the exception is “fatal” because it matched som
Scott Hess - ex-Googler
2011/05/17 19:34:40
Crap, did I get that backwards? I had another CL
Scott Hess - ex-Googler
2011/05/17 20:00:44
Indeed, my forced exceptions were all NSGenericExc
| |
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 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
299 if (window == aTarget) { | 301 if (window == aTarget) { |
300 found = YES; | 302 found = YES; |
301 break; | 303 break; |
302 } | 304 } |
303 } | 305 } |
304 if (!found) { | 306 if (!found) { |
305 return NO; | 307 return NO; |
306 } | 308 } |
307 } | 309 } |
308 | 310 |
311 // Certain third-party code, such as print drivers, can still throw | |
312 // exceptions and Chromium cannot fix them. This provides a way to | |
313 // work around those on a spot basis. | |
314 bool enableNSExceptions = false; | |
315 | |
316 // http://crbug.com/80686 , an Epson printer driver. | |
317 if (anAction == @selector(selectPDE:)) { | |
318 enableNSExceptions = true; | |
319 } | |
320 | |
321 base::mac::ScopedNSExceptionEnabler enabler(enableNSExceptions); | |
Mark Mentovai
2011/05/17 19:07:34
I’d prefer to get this as close to [super sendActi
| |
322 | |
309 // When a Cocoa control is wired to a freed object, we get crashers | 323 // When a Cocoa control is wired to a freed object, we get crashers |
310 // in the call to |super| with no useful information in the | 324 // in the call to |super| with no useful information in the |
311 // backtrace. Attempt to add some useful information. | 325 // backtrace. Attempt to add some useful information. |
312 static NSString* const kActionKey = @"sendaction"; | 326 static NSString* const kActionKey = @"sendaction"; |
313 | 327 |
314 // If the action is something generic like -commandDispatch:, then | 328 // If the action is something generic like -commandDispatch:, then |
315 // the tag is essential. | 329 // the tag is essential. |
316 NSInteger tag = 0; | 330 NSInteger tag = 0; |
317 if ([sender isKindOfClass:[NSControl class]]) { | 331 if ([sender isKindOfClass:[NSControl class]]) { |
318 tag = [sender tag]; | 332 tag = [sender tag]; |
(...skipping 28 matching lines...) Expand all Loading... | |
347 | 361 |
348 // http://crbug.com/45928 is a bug about needing to double-close | 362 // http://crbug.com/45928 is a bug about needing to double-close |
349 // windows sometimes. One theory is that |-isHandlingSendEvent| | 363 // windows sometimes. One theory is that |-isHandlingSendEvent| |
350 // gets latched to always return |YES|. Since scopers are used to | 364 // gets latched to always return |YES|. Since scopers are used to |
351 // manipulate that value, that should not be possible. One way to | 365 // manipulate that value, that should not be possible. One way to |
352 // sidestep scopers is setjmp/longjmp (see above). The following | 366 // sidestep scopers is setjmp/longjmp (see above). The following |
353 // is to "fix" this while the more fundamental concern is | 367 // is to "fix" this while the more fundamental concern is |
354 // addressed elsewhere. | 368 // addressed elsewhere. |
355 [self clearIsHandlingSendEvent]; | 369 [self clearIsHandlingSendEvent]; |
356 | 370 |
371 // If |ScopedNSExceptionEnabler| is used to allow exceptions, and | |
372 // an uncaught exception is thrown, the flag must be reset so that | |
373 // future exceptions are not masked. | |
374 base::mac::SetNSExceptionsAllowed(false); | |
stuartmorgan
2011/05/17 18:52:14
Given that you've designed these to nest arbitrari
Mark Mentovai
2011/05/17 19:07:34
false instead of the original “was” value?
(which
Scott Hess - ex-Googler
2011/05/17 19:34:40
In the 32-bit runtime, you cannot use C++ scoped o
Scott Hess - ex-Googler
2011/05/17 19:34:40
This is effectively the outermost scope.
| |
375 | |
357 // Store some human-readable information in breakpad keys in case | 376 // Store some human-readable information in breakpad keys in case |
358 // there is a crash. Since breakpad does not provide infinite | 377 // there is a crash. Since breakpad does not provide infinite |
359 // storage, we track two exceptions. The first exception thrown | 378 // storage, we track two exceptions. The first exception thrown |
360 // is tracked because it may be the one which caused the system to | 379 // 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 | 380 // go off the rails. The last exception thrown is tracked because |
362 // it may be the one most directly associated with the crash. | 381 // it may be the one most directly associated with the crash. |
363 static NSString* const kFirstExceptionKey = @"firstexception"; | 382 static NSString* const kFirstExceptionKey = @"firstexception"; |
364 static BOOL trackedFirstException = NO; | 383 static BOOL trackedFirstException = NO; |
365 static NSString* const kLastExceptionKey = @"lastexception"; | 384 static NSString* const kLastExceptionKey = @"lastexception"; |
366 | 385 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
399 if (RenderViewHost* rvh = contents->render_view_host()) { | 418 if (RenderViewHost* rvh = contents->render_view_host()) { |
400 rvh->EnableRendererAccessibility(); | 419 rvh->EnableRendererAccessibility(); |
401 } | 420 } |
402 } | 421 } |
403 } | 422 } |
404 } | 423 } |
405 return [super accessibilitySetValue:value forAttribute:attribute]; | 424 return [super accessibilitySetValue:value forAttribute:attribute]; |
406 } | 425 } |
407 | 426 |
408 @end | 427 @end |
OLD | NEW |