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