Home | History | Annotate | Download | only in replay
      1 // Copyright 2013 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 "tools/ipc_fuzzer/replay/replay_process.h"
      6 
      7 #include <limits.h>
      8 #include <string>
      9 #include "base/bind.h"
     10 #include "base/command_line.h"
     11 #include "base/files/file_path.h"
     12 #include "base/logging.h"
     13 #include "base/posix/global_descriptors.h"
     14 #include "chrome/common/chrome_switches.h"
     15 #include "ipc/ipc_descriptors.h"
     16 #include "ipc/ipc_switches.h"
     17 
     18 namespace ipc_fuzzer {
     19 
     20 ReplayProcess::ReplayProcess()
     21     : main_loop_(base::MessageLoop::TYPE_DEFAULT),
     22       io_thread_("Chrome_ChildIOThread"),
     23       shutdown_event_(true, false),
     24       message_index_(0) {
     25 }
     26 
     27 ReplayProcess::~ReplayProcess() {
     28   channel_.reset();
     29 }
     30 
     31 bool ReplayProcess::Initialize(int argc, const char** argv) {
     32   CommandLine::Init(argc, argv);
     33 
     34   if (!CommandLine::ForCurrentProcess()->HasSwitch(
     35       switches::kIpcFuzzerTestcase)) {
     36     LOG(ERROR) << "This binary shouldn't be executed directly, "
     37                << "please use tools/ipc_fuzzer/play_testcase.py";
     38     return false;
     39   }
     40 
     41   // Log to default destination.
     42   logging::SetMinLogLevel(logging::LOG_ERROR);
     43   logging::InitLogging(logging::LoggingSettings());
     44 
     45   io_thread_.StartWithOptions(
     46       base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
     47 
     48   base::GlobalDescriptors* g_fds = base::GlobalDescriptors::GetInstance();
     49   g_fds->Set(kPrimaryIPCChannel,
     50              kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor);
     51   return true;
     52 }
     53 
     54 void ReplayProcess::OpenChannel() {
     55   std::string channel_name =
     56       CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
     57           switches::kProcessChannelID);
     58 
     59   channel_.reset(
     60       new IPC::ChannelProxy(channel_name,
     61                             IPC::Channel::MODE_CLIENT,
     62                             this,
     63                             io_thread_.message_loop_proxy()));
     64 }
     65 
     66 bool ReplayProcess::OpenTestcase() {
     67   base::FilePath path = CommandLine::ForCurrentProcess()->GetSwitchValuePath(
     68       switches::kIpcFuzzerTestcase);
     69   return MessageFile::Read(path, &messages_);
     70 }
     71 
     72 void ReplayProcess::SendNextMessage() {
     73   if (message_index_ >= messages_.size()) {
     74     base::MessageLoop::current()->Quit();
     75     return;
     76   }
     77 
     78   // Take next message and release it from vector.
     79   IPC::Message* message = messages_[message_index_];
     80   messages_[message_index_++] = NULL;
     81 
     82   if (!channel_->Send(message)) {
     83     LOG(ERROR) << "ChannelProxy::Send() failed";
     84     base::MessageLoop::current()->Quit();
     85   }
     86 }
     87 
     88 void ReplayProcess::Run() {
     89   timer_.reset(new base::Timer(false, true));
     90   timer_->Start(FROM_HERE,
     91                 base::TimeDelta::FromMilliseconds(1),
     92                 base::Bind(&ReplayProcess::SendNextMessage,
     93                            base::Unretained(this)));
     94   base::MessageLoop::current()->Run();
     95 }
     96 
     97 bool ReplayProcess::OnMessageReceived(const IPC::Message& msg) {
     98   return true;
     99 }
    100 
    101 void ReplayProcess::OnChannelError() {
    102   LOG(ERROR) << "Channel error, quitting";
    103   base::MessageLoop::current()->Quit();
    104 }
    105 
    106 }  // namespace ipc_fuzzer
    107