LCOV - code coverage report
Current view: directory - ipc/chromium/src/chrome/common - child_process_host.cc (source / functions) Found Hit Coverage
Test: app.info Lines: 90 0 0.0 %
Date: 2012-06-02 Functions: 21 0 0.0 %

       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 "chrome/common/child_process_host.h"
       6                 : 
       7                 : #include "base/compiler_specific.h"
       8                 : #include "base/logging.h"
       9                 : #include "base/message_loop.h"
      10                 : #include "base/process_util.h"
      11                 : #include "base/singleton.h"
      12                 : #include "base/waitable_event.h"
      13                 : #include "mozilla/ipc/ProcessChild.h"
      14                 : #include "mozilla/ipc/BrowserProcessSubThread.h"
      15                 : typedef mozilla::ipc::BrowserProcessSubThread ChromeThread;
      16                 : #include "chrome/common/ipc_logging.h"
      17                 : #include "chrome/common/notification_service.h"
      18                 : #include "chrome/common/notification_type.h"
      19                 : #include "chrome/common/process_watcher.h"
      20                 : #include "chrome/common/result_codes.h"
      21                 : 
      22                 : 
      23                 : namespace {
      24                 : typedef std::list<ChildProcessHost*> ChildProcessList;
      25                 : 
      26                 : // The NotificationTask is used to notify about plugin process connection/
      27                 : // disconnection. It is needed because the notifications in the
      28                 : // NotificationService must happen in the main thread.
      29               0 : class ChildNotificationTask : public Task {
      30                 :  public:
      31               0 :   ChildNotificationTask(
      32                 :       NotificationType notification_type, ChildProcessInfo* info)
      33               0 :       : notification_type_(notification_type), info_(*info) { }
      34                 : 
      35               0 :   virtual void Run() {
      36                 :     NotificationService::current()->
      37               0 :         Notify(notification_type_, NotificationService::AllSources(),
      38               0 :                Details<ChildProcessInfo>(&info_));
      39               0 :   }
      40                 : 
      41                 :  private:
      42                 :   NotificationType notification_type_;
      43                 :   ChildProcessInfo info_;
      44                 : };
      45                 : 
      46                 : }  // namespace
      47                 : 
      48                 : 
      49                 : 
      50               0 : ChildProcessHost::ChildProcessHost(
      51                 :     ProcessType type, ResourceDispatcherHost* resource_dispatcher_host)
      52                 :     :
      53                 :       ChildProcessInfo(type),
      54                 :       ALLOW_THIS_IN_INITIALIZER_LIST(listener_(this)),
      55                 :       resource_dispatcher_host_(resource_dispatcher_host),
      56                 :       opening_channel_(false),
      57               0 :       process_event_(NULL) {
      58               0 :   Singleton<ChildProcessList>::get()->push_back(this);
      59               0 : }
      60                 : 
      61                 : 
      62               0 : ChildProcessHost::~ChildProcessHost() {
      63               0 :   Singleton<ChildProcessList>::get()->remove(this);
      64                 : 
      65               0 :   if (handle()) {
      66               0 :     watcher_.StopWatching();
      67               0 :     ProcessWatcher::EnsureProcessTerminated(handle());
      68                 : 
      69                 : #if defined(OS_WIN)
      70                 :     // Above call took ownership, so don't want WaitableEvent to assert because
      71                 :     // the handle isn't valid anymore.
      72                 :     process_event_->Release();
      73                 : #endif
      74                 :   }
      75               0 : }
      76                 : 
      77               0 : bool ChildProcessHost::CreateChannel() {
      78               0 :   channel_id_ = GenerateRandomChannelID(this);
      79                 :   channel_.reset(new IPC::Channel(
      80               0 :       channel_id_, IPC::Channel::MODE_SERVER, &listener_));
      81               0 :   if (!channel_->Connect())
      82               0 :     return false;
      83                 : 
      84               0 :   opening_channel_ = true;
      85                 : 
      86               0 :   return true;
      87                 : }
      88                 : 
      89               0 : void ChildProcessHost::SetHandle(base::ProcessHandle process) {
      90                 : #if defined(OS_WIN)
      91                 :   process_event_.reset(new base::WaitableEvent(process));
      92                 : 
      93                 :   DCHECK(!handle());
      94                 :   set_handle(process);
      95                 :   watcher_.StartWatching(process_event_.get(), this);
      96                 : #endif
      97               0 : }
      98                 : 
      99               0 : void ChildProcessHost::InstanceCreated() {
     100               0 :   Notify(NotificationType::CHILD_INSTANCE_CREATED);
     101               0 : }
     102                 : 
     103               0 : bool ChildProcessHost::Send(IPC::Message* msg) {
     104               0 :   if (!channel_.get()) {
     105               0 :     delete msg;
     106               0 :     return false;
     107                 :   }
     108               0 :   return channel_->Send(msg);
     109                 : }
     110                 : 
     111               0 : void ChildProcessHost::Notify(NotificationType type) {
     112               0 :   MessageLoop* loop = ChromeThread::GetMessageLoop(ChromeThread::IO);
     113               0 :   if (!loop)
     114               0 :       loop = mozilla::ipc::ProcessChild::message_loop();
     115               0 :   if (!loop)
     116               0 :       loop = MessageLoop::current();
     117                 :   loop->PostTask(
     118               0 :       FROM_HERE, new ChildNotificationTask(type, this));
     119               0 : }
     120                 : 
     121               0 : void ChildProcessHost::OnWaitableEventSignaled(base::WaitableEvent *event) {
     122                 : #if defined(OS_WIN)
     123                 :   HANDLE object = event->handle();
     124                 :   DCHECK(handle());
     125                 :   DCHECK_EQ(object, handle());
     126                 : 
     127                 :   bool did_crash = base::DidProcessCrash(NULL, object);
     128                 :   if (did_crash) {
     129                 :     // Report that this child process crashed.
     130                 :     Notify(NotificationType::CHILD_PROCESS_CRASHED);
     131                 :   }
     132                 :   // Notify in the main loop of the disconnection.
     133                 :   Notify(NotificationType::CHILD_PROCESS_HOST_DISCONNECTED);
     134                 : #endif
     135               0 : }
     136                 : 
     137               0 : ChildProcessHost::ListenerHook::ListenerHook(ChildProcessHost* host)
     138               0 :     : host_(host) {
     139               0 : }
     140                 : 
     141               0 : void ChildProcessHost::ListenerHook::OnMessageReceived(
     142                 :     const IPC::Message& msg) {
     143                 : #ifdef IPC_MESSAGE_LOG_ENABLED
     144               0 :   IPC::Logging* logger = IPC::Logging::current();
     145               0 :   if (msg.type() == IPC_LOGGING_ID) {
     146               0 :     logger->OnReceivedLoggingMessage(msg);
     147               0 :     return;
     148                 :   }
     149                 : 
     150               0 :   if (logger->Enabled())
     151               0 :     logger->OnPreDispatchMessage(msg);
     152                 : #endif
     153                 : 
     154               0 :   bool msg_is_ok = true;
     155               0 :   bool handled = false;
     156                 : 
     157               0 :   if (!handled) {
     158               0 :       host_->OnMessageReceived(msg);
     159                 :   }
     160                 : 
     161               0 :   if (!msg_is_ok)
     162               0 :     base::KillProcess(host_->handle(), ResultCodes::KILLED_BAD_MESSAGE, false);
     163                 : 
     164                 : #ifdef IPC_MESSAGE_LOG_ENABLED
     165               0 :   if (logger->Enabled())
     166               0 :     logger->OnPostDispatchMessage(msg, host_->channel_id_);
     167                 : #endif
     168                 : }
     169                 : 
     170               0 : void ChildProcessHost::ListenerHook::OnChannelConnected(int32 peer_pid) {
     171               0 :   host_->opening_channel_ = false;
     172               0 :   host_->OnChannelConnected(peer_pid);
     173                 : 
     174                 :   // Notify in the main loop of the connection.
     175               0 :   host_->Notify(NotificationType::CHILD_PROCESS_HOST_CONNECTED);
     176               0 : }
     177                 : 
     178               0 : void ChildProcessHost::ListenerHook::OnChannelError() {
     179               0 :   host_->opening_channel_ = false;
     180               0 :   host_->OnChannelError();
     181               0 : }
     182                 : 
     183                 : 
     184               0 : ChildProcessHost::Iterator::Iterator() : all_(true) {
     185               0 :   iterator_ = Singleton<ChildProcessList>::get()->begin();
     186               0 : }
     187                 : 
     188               0 : ChildProcessHost::Iterator::Iterator(ProcessType type)
     189               0 :     : all_(false), type_(type) {
     190               0 :   iterator_ = Singleton<ChildProcessList>::get()->begin();
     191               0 :   if (!Done() && (*iterator_)->type() != type_)
     192               0 :     ++(*this);
     193               0 : }
     194                 : 
     195               0 : ChildProcessHost* ChildProcessHost::Iterator::operator++() {
     196               0 :   do {
     197               0 :     ++iterator_;
     198               0 :     if (Done())
     199                 :       break;
     200                 : 
     201               0 :     if (!all_ && (*iterator_)->type() != type_)
     202               0 :       continue;
     203                 : 
     204               0 :     return *iterator_;
     205                 :   } while (true);
     206                 : 
     207               0 :   return NULL;
     208                 : }
     209                 : 
     210               0 : bool ChildProcessHost::Iterator::Done() {
     211               0 :   return iterator_ == Singleton<ChildProcessList>::get()->end();
     212                 : }

Generated by: LCOV version 1.7