blob: 1aebf06e2ebd15b9377ddbd7573fe4e23b230c7b [file] [log] [blame]
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/logging.h"
#include "base/mac/bundle_locations.h"
#include "base/mac/mac_util.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/time/time.h"
#import "chrome/browser/ui/cocoa/about_ipc_controller.h"
#include "content/public/browser/browser_ipc_logging.h"
#if defined(IPC_MESSAGE_LOG_ENABLED)
@implementation CocoaLogData
- (id)initWithLogData:(const IPC::LogData&)data {
if ((self = [super init])) {
data_ = data;
// data_.message_name may not have been filled in if it originated
// somewhere other than the browser process.
if (data_.message_name == "")
IPC::Logging::GetMessageText(data_.type, &data_.message_name, NULL, NULL);
}
return self;
}
- (NSString*)time {
base::Time t = base::Time::FromInternalValue(data_.sent);
base::Time::Exploded exploded;
t.LocalExplode(&exploded);
return [NSString stringWithFormat:@"%02d:%02d:%02d.%03d",
exploded.hour, exploded.minute,
exploded.second, exploded.millisecond];
}
- (NSString*)channel {
return base::SysUTF8ToNSString(data_.channel);
}
- (NSString*)message {
if (data_.message_name == "") {
int high = data_.type >> 12;
int low = data_.type - (high<<12);
return [NSString stringWithFormat:@"type=(%d,%d) 0x%x,0x%x",
high, low, high, low];
}
else {
return base::SysUTF8ToNSString(data_.message_name);
}
}
- (NSString*)flags {
return base::SysUTF8ToNSString(data_.flags);
}
- (NSString*)dispatch {
base::Time sent = base::Time::FromInternalValue(data_.sent);
int64 delta = (base::Time::FromInternalValue(data_.receive) -
sent).InMilliseconds();
return [NSString stringWithFormat:@"%d", delta ? (int)delta : 0];
}
- (NSString*)process {
base::TimeDelta delta = (base::Time::FromInternalValue(data_.dispatch) -
base::Time::FromInternalValue(data_.receive));
int64 t = delta.InMilliseconds();
return [NSString stringWithFormat:@"%d", t ? (int)t : 0];
}
- (NSString*)parameters {
return base::SysUTF8ToNSString(data_.params);
}
@end
namespace {
AboutIPCController* gSharedController = nil;
}
@implementation AboutIPCController
+ (AboutIPCController*)sharedController {
if (gSharedController == nil)
gSharedController = [[AboutIPCController alloc] init];
return gSharedController;
}
- (id)init {
NSString* nibpath = [base::mac::FrameworkBundle() pathForResource:@"AboutIPC"
ofType:@"nib"];
if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
// Default to all on
appCache_ = view_ = utilityHost_ = viewHost_ = plugin_ =
npObject_ = devTools_ = pluginProcessing_ = userString1_ =
userString2_ = userString3_ = YES;
}
return self;
}
- (void)dealloc {
if (gSharedController == self)
gSharedController = nil;
content::EnableIPCLogging(false); // just in case...
IPC::Logging::GetInstance()->SetConsumer(NULL);
[super dealloc];
}
- (void)awakeFromNib {
// Running Chrome with the --ipc-logging switch might cause it to
// be enabled before the about:ipc window comes up; accomodate.
[self updateVisibleRunState];
// We are now able to display information, so let'er rip.
bridge_.reset(new AboutIPCBridge(self));
IPC::Logging::GetInstance()->SetConsumer(bridge_.get());
}
// Delegate callback. Closing the window means there is no more need
// for the me, the controller.
- (void)windowWillClose:(NSNotification*)notification {
[self autorelease];
}
- (void)updateVisibleRunState {
if (IPC::Logging::GetInstance()->Enabled())
[startStopButton_ setTitle:@"Stop"];
else
[startStopButton_ setTitle:@"Start"];
}
- (IBAction)startStop:(id)sender {
content::EnableIPCLogging(!IPC::Logging::GetInstance()->Enabled());
[self updateVisibleRunState];
}
- (IBAction)clear:(id)sender {
[dataController_ setContent:[NSMutableArray array]];
[eventCount_ setStringValue:@"0"];
[filteredEventCount_ setStringValue:@"0"];
filteredEventCounter_ = 0;
}
// Return YES if we should filter this out; else NO.
// Just to be clear, [@"any string" hasPrefix:@""] returns NO.
- (BOOL)filterOut:(CocoaLogData*)data {
NSString* name = [data message];
if ((appCache_) && [name hasPrefix:@"AppCache"])
return NO;
if ((view_) && [name hasPrefix:@"ViewMsg"])
return NO;
if ((utilityHost_) && [name hasPrefix:@"UtilityHost"])
return NO;
if ((viewHost_) && [name hasPrefix:@"ViewHost"])
return NO;
if ((plugin_) && [name hasPrefix:@"PluginMsg"])
return NO;
if ((npObject_) && [name hasPrefix:@"NPObject"])
return NO;
if ((devTools_) && [name hasPrefix:@"DevTools"])
return NO;
if ((pluginProcessing_) && [name hasPrefix:@"PluginProcessing"])
return NO;
if ((userString1_) && ([name hasPrefix:[userStringTextField1_ stringValue]]))
return NO;
if ((userString2_) && ([name hasPrefix:[userStringTextField2_ stringValue]]))
return NO;
if ((userString3_) && ([name hasPrefix:[userStringTextField3_ stringValue]]))
return NO;
// Special case the unknown type.
if ([name hasPrefix:@"type="])
return NO;
return YES; // filter out.
}
- (void)log:(CocoaLogData*)data {
if ([self filterOut:data]) {
[filteredEventCount_ setStringValue:[NSString stringWithFormat:@"%d",
++filteredEventCounter_]];
return;
}
[dataController_ addObject:data];
NSUInteger count = [[dataController_ arrangedObjects] count];
// Uncomment if you want scroll-to-end behavior... but seems expensive.
// [tableView_ scrollRowToVisible:count-1];
[eventCount_ setStringValue:[NSString stringWithFormat:@"%ld",
static_cast<long>(count)]];
}
- (void)setDisplayViewMessages:(BOOL)display {
view_ = display;
}
@end
#endif // IPC_MESSAGE_LOG_ENABLED