1// Copyright (c) 2009 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/logging.h" 6#include "base/mac/bundle_locations.h" 7#include "base/mac/mac_util.h" 8#include "base/strings/string_util.h" 9#include "base/strings/sys_string_conversions.h" 10#include "base/time/time.h" 11#import "chrome/browser/ui/cocoa/about_ipc_controller.h" 12#include "content/public/browser/browser_ipc_logging.h" 13 14#if defined(IPC_MESSAGE_LOG_ENABLED) 15 16@implementation CocoaLogData 17 18- (id)initWithLogData:(const IPC::LogData&)data { 19 if ((self = [super init])) { 20 data_ = data; 21 // data_.message_name may not have been filled in if it originated 22 // somewhere other than the browser process. 23 if (data_.message_name == "") 24 IPC::Logging::GetMessageText(data_.type, &data_.message_name, NULL, NULL); 25 } 26 return self; 27} 28 29- (NSString*)time { 30 base::Time t = base::Time::FromInternalValue(data_.sent); 31 base::Time::Exploded exploded; 32 t.LocalExplode(&exploded); 33 return [NSString stringWithFormat:@"%02d:%02d:%02d.%03d", 34 exploded.hour, exploded.minute, 35 exploded.second, exploded.millisecond]; 36} 37 38- (NSString*)channel { 39 return base::SysUTF8ToNSString(data_.channel); 40} 41 42- (NSString*)message { 43 if (data_.message_name == "") { 44 int high = data_.type >> 12; 45 int low = data_.type - (high<<12); 46 return [NSString stringWithFormat:@"type=(%d,%d) 0x%x,0x%x", 47 high, low, high, low]; 48 } 49 else { 50 return base::SysUTF8ToNSString(data_.message_name); 51 } 52} 53 54- (NSString*)flags { 55 return base::SysUTF8ToNSString(data_.flags); 56} 57 58- (NSString*)dispatch { 59 base::Time sent = base::Time::FromInternalValue(data_.sent); 60 int64 delta = (base::Time::FromInternalValue(data_.receive) - 61 sent).InMilliseconds(); 62 return [NSString stringWithFormat:@"%d", delta ? (int)delta : 0]; 63} 64 65- (NSString*)process { 66 base::TimeDelta delta = (base::Time::FromInternalValue(data_.dispatch) - 67 base::Time::FromInternalValue(data_.receive)); 68 int64 t = delta.InMilliseconds(); 69 return [NSString stringWithFormat:@"%d", t ? (int)t : 0]; 70} 71 72- (NSString*)parameters { 73 return base::SysUTF8ToNSString(data_.params); 74} 75 76@end 77 78namespace { 79AboutIPCController* gSharedController = nil; 80} 81 82@implementation AboutIPCController 83 84+ (AboutIPCController*)sharedController { 85 if (gSharedController == nil) 86 gSharedController = [[AboutIPCController alloc] init]; 87 return gSharedController; 88} 89 90- (id)init { 91 NSString* nibpath = [base::mac::FrameworkBundle() pathForResource:@"AboutIPC" 92 ofType:@"nib"]; 93 if ((self = [super initWithWindowNibPath:nibpath owner:self])) { 94 // Default to all on 95 appCache_ = view_ = utilityHost_ = viewHost_ = plugin_ = 96 npObject_ = devTools_ = pluginProcessing_ = userString1_ = 97 userString2_ = userString3_ = YES; 98 } 99 return self; 100} 101 102- (void)dealloc { 103 if (gSharedController == self) 104 gSharedController = nil; 105 content::EnableIPCLogging(false); // just in case... 106 IPC::Logging::GetInstance()->SetConsumer(NULL); 107 [super dealloc]; 108} 109 110- (void)awakeFromNib { 111 // Running Chrome with the --ipc-logging switch might cause it to 112 // be enabled before the about:ipc window comes up; accomodate. 113 [self updateVisibleRunState]; 114 115 // We are now able to display information, so let'er rip. 116 bridge_.reset(new AboutIPCBridge(self)); 117 IPC::Logging::GetInstance()->SetConsumer(bridge_.get()); 118} 119 120// Delegate callback. Closing the window means there is no more need 121// for the me, the controller. 122- (void)windowWillClose:(NSNotification*)notification { 123 [self autorelease]; 124} 125 126- (void)updateVisibleRunState { 127 if (IPC::Logging::GetInstance()->Enabled()) 128 [startStopButton_ setTitle:@"Stop"]; 129 else 130 [startStopButton_ setTitle:@"Start"]; 131} 132 133- (IBAction)startStop:(id)sender { 134 content::EnableIPCLogging(!IPC::Logging::GetInstance()->Enabled()); 135 [self updateVisibleRunState]; 136} 137 138- (IBAction)clear:(id)sender { 139 [dataController_ setContent:[NSMutableArray array]]; 140 [eventCount_ setStringValue:@"0"]; 141 [filteredEventCount_ setStringValue:@"0"]; 142 filteredEventCounter_ = 0; 143} 144 145// Return YES if we should filter this out; else NO. 146// Just to be clear, [@"any string" hasPrefix:@""] returns NO. 147- (BOOL)filterOut:(CocoaLogData*)data { 148 NSString* name = [data message]; 149 if ((appCache_) && [name hasPrefix:@"AppCache"]) 150 return NO; 151 if ((view_) && [name hasPrefix:@"ViewMsg"]) 152 return NO; 153 if ((utilityHost_) && [name hasPrefix:@"UtilityHost"]) 154 return NO; 155 if ((viewHost_) && [name hasPrefix:@"ViewHost"]) 156 return NO; 157 if ((plugin_) && [name hasPrefix:@"PluginMsg"]) 158 return NO; 159 if ((npObject_) && [name hasPrefix:@"NPObject"]) 160 return NO; 161 if ((devTools_) && [name hasPrefix:@"DevTools"]) 162 return NO; 163 if ((pluginProcessing_) && [name hasPrefix:@"PluginProcessing"]) 164 return NO; 165 if ((userString1_) && ([name hasPrefix:[userStringTextField1_ stringValue]])) 166 return NO; 167 if ((userString2_) && ([name hasPrefix:[userStringTextField2_ stringValue]])) 168 return NO; 169 if ((userString3_) && ([name hasPrefix:[userStringTextField3_ stringValue]])) 170 return NO; 171 172 // Special case the unknown type. 173 if ([name hasPrefix:@"type="]) 174 return NO; 175 176 return YES; // filter out. 177} 178 179- (void)log:(CocoaLogData*)data { 180 if ([self filterOut:data]) { 181 [filteredEventCount_ setStringValue:[NSString stringWithFormat:@"%d", 182 ++filteredEventCounter_]]; 183 return; 184 } 185 [dataController_ addObject:data]; 186 NSUInteger count = [[dataController_ arrangedObjects] count]; 187 // Uncomment if you want scroll-to-end behavior... but seems expensive. 188 // [tableView_ scrollRowToVisible:count-1]; 189 [eventCount_ setStringValue:[NSString stringWithFormat:@"%ld", 190 static_cast<long>(count)]]; 191} 192 193- (void)setDisplayViewMessages:(BOOL)display { 194 view_ = display; 195} 196 197@end 198 199#endif // IPC_MESSAGE_LOG_ENABLED 200 201