Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(216)

Side by Side Diff: chrome/browser/chrome_browser_application_mac.mm

Issue 2543813003: [Mac] Modify the ObjC exception preprocessor to make some exceptions fatal. (Closed)
Patch Set: Address comments Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 #include <AvailabilityMacros.h> 7 #include "base/auto_reset.h"
8 #include <objc/objc-exception.h>
9
10 #import "base/auto_reset.h"
11 #include "base/command_line.h" 8 #include "base/command_line.h"
12 #include "base/debug/crash_logging.h" 9 #include "base/debug/crash_logging.h"
13 #include "base/debug/stack_trace.h" 10 #include "base/logging.h"
14 #import "base/logging.h"
15 #include "base/mac/call_with_eh_frame.h" 11 #include "base/mac/call_with_eh_frame.h"
16 #import "base/mac/scoped_nsobject.h"
17 #import "base/mac/scoped_objc_class_swizzler.h"
18 #include "base/macros.h"
19 #import "base/metrics/histogram_macros.h"
20 #include "base/strings/stringprintf.h" 12 #include "base/strings/stringprintf.h"
21 #import "base/strings/sys_string_conversions.h" 13 #include "base/strings/sys_string_conversions.h"
22 #import "chrome/browser/app_controller_mac.h" 14 #import "chrome/browser/app_controller_mac.h"
23 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" 15 #import "chrome/browser/mac/exception_processor.h"
24 #include "chrome/common/chrome_switches.h" 16 #include "chrome/common/chrome_switches.h"
25 #include "chrome/common/crash_keys.h" 17 #include "chrome/common/crash_keys.h"
26 #import "components/crash/core/common/objc_zombie.h" 18 #import "components/crash/core/common/objc_zombie.h"
27 #include "content/public/browser/browser_accessibility_state.h" 19 #include "content/public/browser/browser_accessibility_state.h"
28 #include "content/public/browser/render_view_host.h"
29 #include "content/public/browser/web_contents.h"
30 20
31 namespace chrome_browser_application_mac { 21 namespace chrome_browser_application_mac {
32 22
33 // Maximum number of known named exceptions we'll support. There is
34 // no central registration, but I only find about 75 possibilities in
35 // the system frameworks, and many of them are probably not
36 // interesting to track in aggregate (those relating to distributed
37 // objects, for instance).
38 const size_t kKnownNSExceptionCount = 25;
39
40 const size_t kUnknownNSException = kKnownNSExceptionCount;
41
42 size_t BinForException(NSException* exception) {
43 // A list of common known exceptions. The list position will
44 // determine where they live in the histogram, so never move them
45 // around, only add to the end.
46 static NSString* const kKnownNSExceptionNames[] = {
47 // Grab-bag exception, not very common. CFArray (or other
48 // container) mutated while being enumerated is one case seen in
49 // production.
50 NSGenericException,
51
52 // Out-of-range on NSString or NSArray. Quite common.
53 NSRangeException,
54
55 // Invalid arg to method, unrecognized selector. Quite common.
56 NSInvalidArgumentException,
57
58 // malloc() returned null in object creation, I think. Turns out
59 // to be very uncommon in production, because of the OOM killer.
60 NSMallocException,
61
62 // This contains things like windowserver errors, trying to draw
63 // views which aren't in windows, unable to read nib files. By
64 // far the most common exception seen on the crash server.
65 NSInternalInconsistencyException,
66
67 nil
68 };
69
70 // Make sure our array hasn't outgrown our abilities to track it.
71 DCHECK_LE(arraysize(kKnownNSExceptionNames), kKnownNSExceptionCount);
72
73 NSString* name = [exception name];
74 for (int i = 0; kKnownNSExceptionNames[i]; ++i) {
75 if (name == kKnownNSExceptionNames[i]) {
76 return i;
77 }
78 }
79 return kUnknownNSException;
80 }
81
82 void RecordExceptionWithUma(NSException* exception) {
83 UMA_HISTOGRAM_ENUMERATION("OSX.NSException",
84 BinForException(exception), kUnknownNSException);
85 }
86
87 namespace {
88
89 objc_exception_preprocessor g_next_preprocessor = nullptr;
90
91 id ExceptionPreprocessor(id exception) {
92 static bool seen_first_exception = false;
93
94 RecordExceptionWithUma(exception);
95
96 const char* const kExceptionKey =
97 seen_first_exception ? crash_keys::mac::kLastNSException
98 : crash_keys::mac::kFirstNSException;
99 NSString* value = [NSString stringWithFormat:@"%@ reason %@",
100 [exception name], [exception reason]];
101 base::debug::SetCrashKeyValue(kExceptionKey, [value UTF8String]);
102
103 const char* const kExceptionTraceKey =
104 seen_first_exception ? crash_keys::mac::kLastNSExceptionTrace
105 : crash_keys::mac::kFirstNSExceptionTrace;
106 // This exception preprocessor runs prior to the one in libobjc, which sets
107 // the -[NSException callStackReturnAddresses].
108 base::debug::SetCrashKeyToStackTrace(kExceptionTraceKey,
109 base::debug::StackTrace());
110
111 seen_first_exception = true;
112
113 // Forward to the original version.
114 if (g_next_preprocessor)
115 return g_next_preprocessor(exception);
116 return exception;
117 }
118
119 } // namespace
120
121 void RegisterBrowserCrApp() { 23 void RegisterBrowserCrApp() {
122 [BrowserCrApplication sharedApplication]; 24 [BrowserCrApplication sharedApplication];
123 }; 25 };
124 26
125 void Terminate() { 27 void Terminate() {
126 [NSApp terminate:nil]; 28 [NSApp terminate:nil];
127 } 29 }
128 30
129 void CancelTerminate() { 31 void CancelTerminate() {
130 [NSApp cancelTerminate:nil]; 32 [NSApp cancelTerminate:nil];
131 } 33 }
132 34
133 } // namespace chrome_browser_application_mac 35 } // namespace chrome_browser_application_mac
134 36
135 // Method exposed for the purposes of overriding. 37 // Method exposed for the purposes of overriding.
136 // Used to determine when a Panel window can become the key window. 38 // Used to determine when a Panel window can become the key window.
137 @interface NSApplication (PanelsCanBecomeKey) 39 @interface NSApplication (PanelsCanBecomeKey)
138 - (void)_cycleWindowsReversed:(BOOL)arg1; 40 - (void)_cycleWindowsReversed:(BOOL)arg1;
139 @end 41 @end
140 42
141 @implementation BrowserCrApplication 43 @implementation BrowserCrApplication
142 44
143 + (void)initialize { 45 + (void)initialize {
144 // Turn all deallocated Objective-C objects into zombies, keeping 46 // Turn all deallocated Objective-C objects into zombies, keeping
145 // the most recent 10,000 of them on the treadmill. 47 // the most recent 10,000 of them on the treadmill.
146 ObjcEvilDoers::ZombieEnable(true, 10000); 48 ObjcEvilDoers::ZombieEnable(true, 10000);
147 49
148 if (!chrome_browser_application_mac::g_next_preprocessor) { 50 chrome::InstallObjcExceptionPreprocessor();
149 chrome_browser_application_mac::g_next_preprocessor =
150 objc_setExceptionPreprocessor(
151 &chrome_browser_application_mac::ExceptionPreprocessor);
152 }
153 } 51 }
154 52
155 - (id)init { 53 - (id)init {
156 self = [super init]; 54 self = [super init];
157 55
158 // Sanity check to alert if overridden methods are not supported. 56 // Sanity check to alert if overridden methods are not supported.
159 DCHECK([NSApplication 57 DCHECK([NSApplication
160 instancesRespondToSelector:@selector(_cycleWindowsReversed:)]); 58 instancesRespondToSelector:@selector(_cycleWindowsReversed:)]);
161 DCHECK([NSApplication 59 DCHECK([NSApplication
162 instancesRespondToSelector:@selector(_removeWindow:)]); 60 instancesRespondToSelector:@selector(_removeWindow:)]);
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 } 230 }
333 231
334 NSString* actionString = NSStringFromSelector(anAction); 232 NSString* actionString = NSStringFromSelector(anAction);
335 std::string value = base::StringPrintf("%s tag %ld sending %s to %p", 233 std::string value = base::StringPrintf("%s tag %ld sending %s to %p",
336 [[sender className] UTF8String], 234 [[sender className] UTF8String],
337 static_cast<long>(tag), 235 static_cast<long>(tag),
338 [actionString UTF8String], 236 [actionString UTF8String],
339 aTarget); 237 aTarget);
340 base::debug::ScopedCrashKey key(crash_keys::mac::kSendAction, value); 238 base::debug::ScopedCrashKey key(crash_keys::mac::kSendAction, value);
341 239
342 return [super sendAction:anAction to:aTarget from:sender]; 240 __block BOOL rv;
241 base::mac::CallWithEHFrame(^{
242 rv = [super sendAction:anAction to:aTarget from:sender];
243 });
244 return rv;
343 } 245 }
344 246
345 - (BOOL)isHandlingSendEvent { 247 - (BOOL)isHandlingSendEvent {
346 return handlingSendEvent_; 248 return handlingSendEvent_;
347 } 249 }
348 250
349 - (void)setHandlingSendEvent:(BOOL)handlingSendEvent { 251 - (void)setHandlingSendEvent:(BOOL)handlingSendEvent {
350 handlingSendEvent_ = handlingSendEvent; 252 handlingSendEvent_ = handlingSendEvent;
351 } 253 }
352 254
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 - (void)_cycleWindowsReversed:(BOOL)arg1 { 294 - (void)_cycleWindowsReversed:(BOOL)arg1 {
393 base::AutoReset<BOOL> pin(&cyclingWindows_, YES); 295 base::AutoReset<BOOL> pin(&cyclingWindows_, YES);
394 [super _cycleWindowsReversed:arg1]; 296 [super _cycleWindowsReversed:arg1];
395 } 297 }
396 298
397 - (BOOL)isCyclingWindows { 299 - (BOOL)isCyclingWindows {
398 return cyclingWindows_; 300 return cyclingWindows_;
399 } 301 }
400 302
401 @end 303 @end
OLDNEW
« no previous file with comments | « chrome/browser/chrome_browser_application_mac.h ('k') | chrome/browser/chrome_browser_application_mac_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698