Home | History | Annotate | Download | only in cocoa
      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