LCOV - code coverage report
Current view: directory - ipc/chromium/src/chrome/common - ipc_logging.cc (source / functions) Found Hit Coverage
Test: app.info Lines: 124 10 8.1 %
Date: 2012-06-02 Functions: 24 3 12.5 %

       1                 : // Copyright (c) 2006-2008 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 "chrome/common/ipc_logging.h"
       6                 : 
       7                 : #if defined(OS_POSIX)
       8                 : #ifdef IPC_MESSAGE_LOG_ENABLED
       9                 : // This will cause render_messages.h etc to define ViewMsgLog and friends.
      10                 : #define IPC_MESSAGE_MACROS_LOG_ENABLED
      11                 : #endif
      12                 : #endif
      13                 : 
      14                 : #include "base/command_line.h"
      15                 : #include "base/logging.h"
      16                 : #include "base/message_loop.h"
      17                 : #include "base/string_util.h"
      18                 : #include "base/thread.h"
      19                 : #include "base/time.h"
      20                 : #include "base/waitable_event.h"
      21                 : #include "base/waitable_event_watcher.h"
      22                 : #include "chrome/common/chrome_switches.h"
      23                 : #include "chrome/common/ipc_sync_message.h"
      24                 : #include "chrome/common/ipc_message_utils.h"
      25                 : 
      26                 : #if defined(OS_POSIX)
      27                 : #include "base/string_util.h"
      28                 : #include <unistd.h>
      29                 : #endif
      30                 : 
      31                 : #ifdef IPC_MESSAGE_LOG_ENABLED
      32                 : 
      33                 : using base::Time;
      34                 : 
      35                 : // IPC::Logging is allocated as a singleton, so we don't need any kind of
      36                 : // special retention program.
      37                 : template <>
      38               0 : struct RunnableMethodTraits<IPC::Logging> {
      39               0 :   static void RetainCallee(IPC::Logging*) {}
      40               0 :   static void ReleaseCallee(IPC::Logging*) {}
      41                 : };
      42                 : 
      43                 : namespace IPC {
      44                 : 
      45                 : const wchar_t kLoggingEventName[] = L"ChromeIPCLog.%d";
      46                 : const int kLogSendDelayMs = 100;
      47                 : 
      48                 : // We use a pointer to the function table to avoid any linker dependencies on
      49                 : // all the traits used as IPC message parameters.
      50                 : Logging::LogFunction *Logging::log_function_mapping_;
      51                 : 
      52               1 : Logging::Logging()
      53                 :     : logging_event_on_(NULL),
      54                 :       logging_event_off_(NULL),
      55                 :       enabled_(false),
      56                 :       queue_invoke_later_pending_(false),
      57                 :       sender_(NULL),
      58               1 :       main_thread_(MessageLoop::current()),
      59               2 :       consumer_(NULL) {
      60                 :   // Create an event for this browser instance that's set when logging is
      61                 :   // enabled, so child processes can know when logging is enabled.
      62                 : 
      63                 : #if defined(OS_WIN)
      64                 :   // On Windows we have a couple of named events which switch logging on and
      65                 :   // off.
      66                 :   int browser_pid;
      67                 :   const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
      68                 :   std::wstring process_type =
      69                 :     parsed_command_line.GetSwitchValue(switches::kProcessType);
      70                 :   if (process_type.empty()) {
      71                 :     browser_pid = GetCurrentProcessId();
      72                 :   } else {
      73                 :     std::wstring channel_name =
      74                 :         parsed_command_line.GetSwitchValue(switches::kProcessChannelID);
      75                 : 
      76                 :     browser_pid = _wtoi(channel_name.c_str());
      77                 :     DCHECK(browser_pid != 0);
      78                 :   }
      79                 : 
      80                 :   std::wstring event_name = GetEventName(browser_pid, true);
      81                 :   logging_event_on_.reset(new base::WaitableEvent(
      82                 :       CreateEvent(NULL, TRUE, FALSE, event_name.c_str())));
      83                 : 
      84                 :   event_name = GetEventName(browser_pid, false);
      85                 :   logging_event_off_.reset(new base::WaitableEvent(
      86                 :       CreateEvent(NULL, TRUE, FALSE, event_name.c_str())));
      87                 : 
      88                 :   RegisterWaitForEvent(true);
      89                 : #endif
      90                 : 
      91               1 :   MessageLoop::current()->AddDestructionObserver(this);
      92               1 : }
      93                 : 
      94               0 : Logging::~Logging() {
      95               0 : }
      96                 : 
      97               1 : Logging* Logging::current() {
      98               1 :   return Singleton<Logging>::get();
      99                 : }
     100                 : 
     101               0 : void Logging::RegisterWaitForEvent(bool enabled) {
     102               0 :   watcher_.StopWatching();
     103                 :   watcher_.StartWatching(
     104               0 :       enabled ? logging_event_on_.get() : logging_event_off_.get(), this);
     105               0 : }
     106                 : 
     107               0 : void Logging::OnWaitableEventSignaled(base::WaitableEvent* event) {
     108               0 :   enabled_ = event == logging_event_on_.get();
     109               0 :   RegisterWaitForEvent(!enabled_);
     110               0 : }
     111                 : 
     112               0 : void Logging::WillDestroyCurrentMessageLoop() {
     113               0 :   watcher_.StopWatching();
     114               0 : }
     115                 : 
     116               0 : void Logging::SetLoggerFunctions(LogFunction *functions) {
     117               0 :   log_function_mapping_ = functions;
     118               0 : }
     119                 : 
     120                 : #if defined(OS_WIN)
     121                 : std::wstring Logging::GetEventName(bool enabled) {
     122                 :   return current()->GetEventName(GetCurrentProcessId(), enabled);
     123                 : }
     124                 : #endif
     125                 : 
     126               0 : std::wstring Logging::GetEventName(int browser_pid, bool enabled) {
     127               0 :   std::wstring result = StringPrintf(kLoggingEventName, browser_pid);
     128               0 :   result += enabled ? L"on" : L"off";
     129                 :   return result;
     130                 : }
     131                 : 
     132               0 : void Logging::SetConsumer(Consumer* consumer) {
     133               0 :   consumer_ = consumer;
     134               0 : }
     135                 : 
     136               0 : void Logging::Enable() {
     137               0 :   logging_event_off_->Reset();
     138               0 :   logging_event_on_->Signal();
     139               0 : }
     140                 : 
     141               0 : void Logging::Disable() {
     142               0 :   logging_event_on_->Reset();
     143               0 :   logging_event_off_->Signal();
     144               0 : }
     145                 : 
     146               0 : void Logging::OnSendLogs() {
     147               0 :   queue_invoke_later_pending_ = false;
     148               0 :   if (!sender_)
     149               0 :     return;
     150                 : 
     151                 :   Message* msg = new Message(
     152               0 :       MSG_ROUTING_CONTROL, IPC_LOGGING_ID, Message::PRIORITY_NORMAL);
     153               0 :   WriteParam(msg, queued_logs_);
     154               0 :   queued_logs_.clear();
     155               0 :   sender_->Send(msg);
     156                 : }
     157                 : 
     158               1 : void Logging::SetIPCSender(IPC::Message::Sender* sender) {
     159               1 :   sender_ = sender;
     160               1 : }
     161                 : 
     162               0 : void Logging::OnReceivedLoggingMessage(const Message& message) {
     163               0 :   std::vector<LogData> data;
     164               0 :   void* iter = NULL;
     165               0 :   if (!ReadParam(&message, &iter, &data))
     166                 :     return;
     167                 : 
     168               0 :   for (size_t i = 0; i < data.size(); ++i) {
     169               0 :     Log(data[i]);
     170                 :   }
     171                 : }
     172                 : 
     173               0 : void Logging::OnSendMessage(Message* message, const std::wstring& channel_id) {
     174               0 :   if (!Enabled())
     175               0 :     return;
     176                 : 
     177               0 :   if (message->is_reply()) {
     178               0 :     LogData* data = message->sync_log_data();
     179               0 :     if (!data)
     180               0 :       return;
     181                 : 
     182                 :     // This is actually the delayed reply to a sync message.  Create a string
     183                 :     // of the output parameters, add it to the LogData that was earlier stashed
     184                 :     // with the reply, and log the result.
     185               0 :     data->channel = channel_id;
     186               0 :     GenerateLogData(L"", *message, data);
     187               0 :     Log(*data);
     188               0 :     delete data;
     189               0 :     message->set_sync_log_data(NULL);
     190                 :   } else {
     191                 :     // If the time has already been set (i.e. by ChannelProxy), keep that time
     192                 :     // instead as it's more accurate.
     193               0 :     if (!message->sent_time())
     194               0 :       message->set_sent_time(Time::Now().ToInternalValue());
     195                 :   }
     196                 : }
     197                 : 
     198               0 : void Logging::OnPreDispatchMessage(const Message& message) {
     199               0 :   message.set_received_time(Time::Now().ToInternalValue());
     200               0 : }
     201                 : 
     202               0 : void Logging::OnPostDispatchMessage(const Message& message,
     203                 :                                     const std::wstring& channel_id) {
     204               0 :   if (!Enabled() ||
     205                 : #if defined(OS_WIN)
     206                 :       !message.sent_time() ||
     207                 : #endif
     208               0 :       message.dont_log())
     209               0 :     return;
     210                 : 
     211               0 :   LogData data;
     212               0 :   GenerateLogData(channel_id, message, &data);
     213                 : 
     214               0 :   if (MessageLoop::current() == main_thread_) {
     215               0 :     Log(data);
     216                 :   } else {
     217                 :     main_thread_->PostTask(FROM_HERE, NewRunnableMethod(
     218               0 :         this, &Logging::Log, data));
     219                 :   }
     220                 : }
     221                 : 
     222               0 : void Logging::GetMessageText(uint16 type, std::wstring* name,
     223                 :                              const Message* message,
     224                 :                              std::wstring* params) {
     225               0 :   if (!log_function_mapping_)
     226               0 :     return;
     227                 : 
     228               0 :   int message_class = type >> 12;
     229               0 :   if (log_function_mapping_[message_class] != NULL) {
     230               0 :     log_function_mapping_[message_class](type, name, message, params);
     231                 :   } else {
     232               0 :     DLOG(INFO) << "No logger function associated with message class " <<
     233               0 :         message_class;
     234                 :   }
     235                 : }
     236                 : 
     237               0 : void Logging::Log(const LogData& data) {
     238                 : #if defined(OS_WIN)
     239                 :   if (consumer_) {
     240                 :     // We're in the browser process.
     241                 :     consumer_->Log(data);
     242                 :   } else {
     243                 :     // We're in the renderer or plugin processes.
     244                 :     if (sender_) {
     245                 :       queued_logs_.push_back(data);
     246                 :       if (!queue_invoke_later_pending_) {
     247                 :         queue_invoke_later_pending_ = true;
     248                 :         MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod(
     249                 :             this, &Logging::OnSendLogs), kLogSendDelayMs);
     250                 :       }
     251                 :     }
     252                 :   }
     253                 : #elif defined(OS_POSIX)
     254                 :   // On POSIX, for now, we just dump the log to stderr
     255                 :   fprintf(stderr, "ipc %s %d %d %s %s %s\n",
     256               0 :           WideToUTF8(data.channel).c_str(),
     257                 :           data.routing_id,
     258                 :           data.type,
     259               0 :           WideToUTF8(data.flags).c_str(),
     260               0 :           WideToUTF8(data.message_name).c_str(),
     261               0 :           WideToUTF8(data.params).c_str());
     262                 : #endif
     263               0 : }
     264                 : 
     265               0 : void GenerateLogData(const std::wstring& channel, const Message& message,
     266                 :                      LogData* data) {
     267               0 :   if (message.is_reply()) {
     268                 :     // "data" should already be filled in.
     269               0 :     std::wstring params;
     270               0 :     Logging::GetMessageText(data->type, NULL, &message, &params);
     271                 : 
     272               0 :     if (!data->params.empty() && !params.empty())
     273               0 :       data->params += L", ";
     274                 : 
     275               0 :     data->flags += L" DR";
     276                 : 
     277               0 :     data->params += params;
     278                 :   } else {
     279               0 :     std::wstring flags;
     280               0 :     if (message.is_sync())
     281               0 :       flags = L"S";
     282                 : 
     283               0 :     if (message.is_reply())
     284               0 :       flags += L"R";
     285                 : 
     286               0 :     if (message.is_reply_error())
     287               0 :       flags += L"E";
     288                 : 
     289               0 :     std::wstring params, message_name;
     290               0 :     Logging::GetMessageText(message.type(), &message_name, &message, &params);
     291                 : 
     292               0 :     data->channel = channel;
     293               0 :     data->routing_id = message.routing_id();
     294               0 :     data->type = message.type();
     295               0 :     data->flags = flags;
     296               0 :     data->sent = message.sent_time();
     297               0 :     data->receive = message.received_time();
     298               0 :     data->dispatch = Time::Now().ToInternalValue();
     299               0 :     data->params = params;
     300               0 :     data->message_name = message_name;
     301                 :   }
     302               0 : }
     303                 : 
     304                 : }
     305                 : 
     306                 : #endif  // IPC_MESSAGE_LOG_ENABLED

Generated by: LCOV version 1.7