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.
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"
14 #if defined(IPC_MESSAGE_LOG_ENABLED)
16 @implementation CocoaLogData
18 - (id)initWithLogData:(const IPC::LogData&)data {
19 if ((self = [super init])) {
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);
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];
38 - (NSString*)channel {
39 return base::SysUTF8ToNSString(data_.channel);
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];
50 return base::SysUTF8ToNSString(data_.message_name);
55 return base::SysUTF8ToNSString(data_.flags);
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];
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];
72 - (NSString*)parameters {
73 return base::SysUTF8ToNSString(data_.params);
79 AboutIPCController* gSharedController = nil;
82 @implementation AboutIPCController
84 + (AboutIPCController*)sharedController {
85 if (gSharedController == nil)
86 gSharedController = [[AboutIPCController alloc] init];
87 return gSharedController;
91 NSString* nibpath = [base::mac::FrameworkBundle() pathForResource:@"AboutIPC"
93 if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
95 appCache_ = view_ = utilityHost_ = viewHost_ = plugin_ =
96 npObject_ = devTools_ = pluginProcessing_ = userString1_ =
97 userString2_ = userString3_ = YES;
103 if (gSharedController == self)
104 gSharedController = nil;
105 content::EnableIPCLogging(false); // just in case...
106 IPC::Logging::GetInstance()->SetConsumer(NULL);
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];
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());
120 // Delegate callback. Closing the window means there is no more need
121 // for the me, the controller.
122 - (void)windowWillClose:(NSNotification*)notification {
126 - (void)updateVisibleRunState {
127 if (IPC::Logging::GetInstance()->Enabled())
128 [startStopButton_ setTitle:@"Stop"];
130 [startStopButton_ setTitle:@"Start"];
133 - (IBAction)startStop:(id)sender {
134 content::EnableIPCLogging(!IPC::Logging::GetInstance()->Enabled());
135 [self updateVisibleRunState];
138 - (IBAction)clear:(id)sender {
139 [dataController_ setContent:[NSMutableArray array]];
140 [eventCount_ setStringValue:@"0"];
141 [filteredEventCount_ setStringValue:@"0"];
142 filteredEventCounter_ = 0;
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"])
151 if ((view_) && [name hasPrefix:@"ViewMsg"])
153 if ((utilityHost_) && [name hasPrefix:@"UtilityHost"])
155 if ((viewHost_) && [name hasPrefix:@"ViewHost"])
157 if ((plugin_) && [name hasPrefix:@"PluginMsg"])
159 if ((npObject_) && [name hasPrefix:@"NPObject"])
161 if ((devTools_) && [name hasPrefix:@"DevTools"])
163 if ((pluginProcessing_) && [name hasPrefix:@"PluginProcessing"])
165 if ((userString1_) && ([name hasPrefix:[userStringTextField1_ stringValue]]))
167 if ((userString2_) && ([name hasPrefix:[userStringTextField2_ stringValue]]))
169 if ((userString3_) && ([name hasPrefix:[userStringTextField3_ stringValue]]))
172 // Special case the unknown type.
173 if ([name hasPrefix:@"type="])
176 return YES; // filter out.
179 - (void)log:(CocoaLogData*)data {
180 if ([self filterOut:data]) {
181 [filteredEventCount_ setStringValue:[NSString stringWithFormat:@"%d",
182 ++filteredEventCounter_]];
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)]];
193 - (void)setDisplayViewMessages:(BOOL)display {
199 #endif // IPC_MESSAGE_LOG_ENABLED