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/mac_util.h" 7 #include "base/string_util.h" 8 #include "base/sys_string_conversions.h" 9 #include "base/time.h" 10 #include "chrome/browser/browser_process.h" 11 #import "chrome/browser/ui/cocoa/about_ipc_controller.h" 12 13 #if defined(IPC_MESSAGE_LOG_ENABLED) 14 15 @implementation CocoaLogData 16 17 - (id)initWithLogData:(const IPC::LogData&)data { 18 if ((self = [super init])) { 19 data_ = data; 20 // data_.message_name may not have been filled in if it originated 21 // somewhere other than the browser process. 22 IPC::Logging::GetMessageText(data_.type, &data_.message_name, NULL, NULL); 23 } 24 return self; 25 } 26 27 - (NSString*)time { 28 base::Time t = base::Time::FromInternalValue(data_.sent); 29 base::Time::Exploded exploded; 30 t.LocalExplode(&exploded); 31 return [NSString stringWithFormat:@"%02d:%02d:%02d.%03d", 32 exploded.hour, exploded.minute, 33 exploded.second, exploded.millisecond]; 34 } 35 36 - (NSString*)channel { 37 return base::SysUTF8ToNSString(data_.channel); 38 } 39 40 - (NSString*)message { 41 if (data_.message_name == "") { 42 int high = data_.type >> 12; 43 int low = data_.type - (high<<12); 44 return [NSString stringWithFormat:@"type=(%d,%d) 0x%x,0x%x", 45 high, low, high, low]; 46 } 47 else { 48 return base::SysUTF8ToNSString(data_.message_name); 49 } 50 } 51 52 - (NSString*)flags { 53 return base::SysUTF8ToNSString(data_.flags); 54 } 55 56 - (NSString*)dispatch { 57 base::Time sent = base::Time::FromInternalValue(data_.sent); 58 int64 delta = (base::Time::FromInternalValue(data_.receive) - 59 sent).InMilliseconds(); 60 return [NSString stringWithFormat:@"%d", delta ? (int)delta : 0]; 61 } 62 63 - (NSString*)process { 64 base::TimeDelta delta = (base::Time::FromInternalValue(data_.dispatch) - 65 base::Time::FromInternalValue(data_.receive)); 66 int64 t = delta.InMilliseconds(); 67 return [NSString stringWithFormat:@"%d", t ? (int)t : 0]; 68 } 69 70 - (NSString*)parameters { 71 return base::SysUTF8ToNSString(data_.params); 72 } 73 74 @end 75 76 namespace { 77 AboutIPCController* gSharedController = nil; 78 } 79 80 @implementation AboutIPCController 81 82 + (AboutIPCController*)sharedController { 83 if (gSharedController == nil) 84 gSharedController = [[AboutIPCController alloc] init]; 85 return gSharedController; 86 } 87 88 - (id)init { 89 NSString* nibpath = [base::mac::MainAppBundle() pathForResource:@"AboutIPC" 90 ofType:@"nib"]; 91 if ((self = [super initWithWindowNibPath:nibpath owner:self])) { 92 // Default to all on 93 appCache_ = view_ = utilityHost_ = viewHost_ = plugin_ = 94 npObject_ = devTools_ = pluginProcessing_ = userString1_ = 95 userString2_ = userString3_ = YES; 96 } 97 return self; 98 } 99 100 - (void)dealloc { 101 if (gSharedController == self) 102 gSharedController = nil; 103 if (g_browser_process) 104 g_browser_process->SetIPCLoggingEnabled(false); // just in case... 105 IPC::Logging::GetInstance()->SetConsumer(NULL); 106 [super dealloc]; 107 } 108 109 - (void)awakeFromNib { 110 // Running Chrome with the --ipc-logging switch might cause it to 111 // be enabled before the about:ipc window comes up; accomodate. 112 [self updateVisibleRunState]; 113 114 // We are now able to display information, so let'er rip. 115 bridge_.reset(new AboutIPCBridge(self)); 116 IPC::Logging::GetInstance()->SetConsumer(bridge_.get()); 117 } 118 119 // Delegate callback. Closing the window means there is no more need 120 // for the me, the controller. 121 - (void)windowWillClose:(NSNotification*)notification { 122 [self autorelease]; 123 } 124 125 - (void)updateVisibleRunState { 126 if (IPC::Logging::GetInstance()->Enabled()) 127 [startStopButton_ setTitle:@"Stop"]; 128 else 129 [startStopButton_ setTitle:@"Start"]; 130 } 131 132 - (IBAction)startStop:(id)sender { 133 g_browser_process->SetIPCLoggingEnabled( 134 !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:@"%d", count]]; 190 } 191 192 - (void)setDisplayViewMessages:(BOOL)display { 193 view_ = display; 194 } 195 196 @end 197 198 #endif // IPC_MESSAGE_LOG_ENABLED 199 200