Chromium Code Reviews| Index: chrome/browser/ui/cocoa/full_size_content_window.mm |
| diff --git a/chrome/browser/ui/cocoa/full_size_content_window.mm b/chrome/browser/ui/cocoa/full_size_content_window.mm |
| index 555c523fa209983c74662b42b9cfb23c12e579ca..fc8ef09ff2f3841ccfb2415c6bef606fdede4f94 100644 |
| --- a/chrome/browser/ui/cocoa/full_size_content_window.mm |
| +++ b/chrome/browser/ui/cocoa/full_size_content_window.mm |
| @@ -6,6 +6,7 @@ |
| #include "base/logging.h" |
| #include "base/mac/foundation_util.h" |
| +#include "base/mac/scoped_objc_class_swizzler.h" |
| @interface FullSizeContentWindow () |
| @@ -44,10 +45,55 @@ |
| @end |
| +static BOOL disableSymbolication = NO; |
| + |
| +@implementation NSObject (FullSizeContentWindowSwizzling) |
| + |
| +// This is the replacement method for |
| +// [_NSCallStackArray descriptionWithLocale:indent:] (see +load below). |
| +// _NSCallStackArray can't be linked against because it's a private class, |
| +// so it's not possible to add this method to the class as a category. Instead, |
| +// just add it to NSObject, which is an ancestor class to _NSCallStackArray. |
|
erikchen
2016/01/05 20:48:44
I'm not a huge fan of adding methods to NSObject,
shrike
2016/01/05 21:27:37
Yeah, that should work - I will work on that.
shrike
2016/01/05 22:03:17
Turns out that doing this makes it a little tricke
|
| +- (NSString*)chromeSwizzledDescriptionWithLocale:(id)aLocale |
| + indent:(unsigned long long)indent { |
| + return disableSymbolication ? |
| + @"" : [self chromeSwizzledDescriptionWithLocale:aLocale indent:indent]; |
| +} |
| + |
| +@end |
| + |
| @implementation FullSizeContentWindow |
| #pragma mark - Lifecycle |
| +// In initWithContentRect:styleMask:backing:defer:, the call to |
| +// [NSView addSubview:positioned:relativeTo:] causes NSWindow to complain that |
| +// an unknown view is being added to it, and to generate a stack trace. |
| +// Not only does this stack trace pollute the console, it can also take hundreds |
| +// of milliseconds to generate (because of symbolication). The AppKit uses an |
| +// _NSCallStackArray to dump the symbols to the console - by swizzling |
| +// descriptionWithLocale:indent: we can disable this output. See |
| +// crbug.com/520373 . |
| ++ (void)load { |
|
erikchen
2016/01/05 20:48:44
Instead of doing this in +load, can we do it right
shrike
2016/01/05 21:27:37
Doing it that way would be simpler, and would allo
erikchen
2016/01/05 21:33:28
Hm. Fair enough. Let's keep it in +load then.
|
| + static dispatch_once_t onceToken; |
| + dispatch_once(&onceToken, ^{ |
| + Class callStackArrayClass = NSClassFromString(@"_NSCallStackArray"); |
| + SEL originalSelector = @selector(descriptionWithLocale:indent:); |
| + SEL swizzledSelector = |
| + @selector(chromeSwizzledDescriptionWithLocale:indent:); |
| + |
| + if (callStackArrayClass && originalSelector && swizzledSelector) { |
| + CR_DEFINE_STATIC_LOCAL(base::mac::ScopedObjCClassSwizzler, |
| + callStackSupressor, (callStackArrayClass, |
| + originalSelector, swizzledSelector)); |
| + |
| + // Prevent compiler from complaining about callStackSupressor never being |
| + // used. |
| + callStackSupressor.GetOriginalImplementation(); |
|
erikchen
2016/01/05 20:48:44
better to suppress the clang diagnostic error:
ht
shrike
2016/01/05 21:27:37
Great! I wasn't sure how to deal with this.
|
| + } |
| + }); |
| +} |
| + |
| - (instancetype)init { |
| NOTREACHED(); |
| return nil; |
| @@ -87,9 +133,29 @@ |
| // it is positioned below the buttons. |
| NSView* superview = [chromeWindowView_ superview]; |
| [chromeWindowView_ removeFromSuperview]; |
| + |
| + // Prevent the AppKit from sending a complaint to the console in |
| + // response to our upcoming call to addSubview:positioned:relativeTo: by |
| + // temporarily routing stdErr to /dev/null. |
| + static int devNullFD = -1; |
| + if (devNullFD == -1) { |
| + devNullFD = open("/dev/null", O_WRONLY); |
|
erikchen
2016/01/05 20:48:44
Can you use [NSFileHandle fileHandleWithNullDevice
erikchen
2016/01/05 20:53:43
nevermind. It's probably easier to just use what y
|
| + } |
| + int stdErrorDescriptor = dup(2); |
| + dup2(devNullFD, 2); |
| + |
| + // The AppKit's complaint also contains a backtrace, which can take |
| + // significant time to symbolicate. See +load for more info. |
| + disableSymbolication = YES; |
| + |
| [superview addSubview:chromeWindowView_ |
| positioned:NSWindowBelow |
| relativeTo:nil]; |
| + |
| + // Clean up from the AppKit console message workaround. |
| + disableSymbolication = NO; |
| + dup2(stdErrorDescriptor, 2); |
| + close(stdErrorDescriptor); |
|
erikchen
2016/01/05 20:48:44
Is this call necessary? Doesn't the call to dup2 a
shrike
2016/01/05 21:27:37
The man page says, "dup2() makes newfd be the copy
erikchen
2016/01/05 21:33:28
you're right. I confused stdErrorDescriptor with d
|
| } |
| } |
| return self; |