• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
76namespace {
77AboutIPCController* 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