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/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 
     78 namespace {
     79 AboutIPCController* 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