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