1#!/usr/bin/env python
2# Copyright 2013 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Wrapper around chrome.
7
8Replaces all the child processes (renderer, GPU, plugins and utility) with the
9IPC fuzzer. The fuzzer will then play back a specified testcase.
10
11Depends on ipc_fuzzer being available on the same directory as chrome.
12"""
13
14import argparse
15import os
16import platform
17import subprocess
18import sys
19
20def main():
21  desc = 'Wrapper to run chrome with child processes replaced by IPC fuzzers'
22  parser = argparse.ArgumentParser(description=desc)
23  parser.add_argument('--out-dir', dest='out_dir', default='out',
24                      help='output directory under src/ directory')
25  parser.add_argument('--build-type', dest='build_type', default='Release',
26                      help='Debug vs. Release build')
27  parser.add_argument('--gdb-browser', dest='gdb_browser', default=False,
28                      action='store_true',
29                      help='run browser process inside gdb')
30  parser.add_argument('testcase',
31                      help='IPC file to be replayed')
32  parser.add_argument('chrome_args',
33                      nargs=argparse.REMAINDER,
34                      help='any additional arguments are passed to chrome')
35  args = parser.parse_args()
36
37  chrome_binary = 'chrome'
38  fuzzer_binary = 'ipc_fuzzer_replay'
39
40  script_path = os.path.realpath(__file__)
41  ipc_fuzzer_dir = os.path.dirname(script_path)
42  src_dir = os.path.abspath(os.path.join(ipc_fuzzer_dir, os.pardir, os.pardir))
43  out_dir =  os.path.join(src_dir, args.out_dir)
44  build_dir = os.path.join(out_dir, args.build_type)
45
46  chrome_path = os.path.join(build_dir, chrome_binary)
47  if not os.path.exists(chrome_path):
48    print 'chrome executable not found at ', chrome_path
49    return 1
50
51  fuzzer_path = os.path.join(build_dir, fuzzer_binary)
52  if not os.path.exists(fuzzer_path):
53    print 'fuzzer executable not found at ', fuzzer_path
54    print ('ensure GYP_DEFINES="enable_ipc_fuzzer=1" and build target ' +
55           fuzzer_binary + '.')
56    return 1
57
58  prefixes = {
59    '--renderer-cmd-prefix',
60    '--gpu-launcher',
61    '--plugin-launcher',
62    '--ppapi-plugin-launcher',
63    '--utility-cmd-prefix',
64  }
65
66  chrome_command = [
67    chrome_path,
68    '--ipc-fuzzer-testcase=' + args.testcase,
69    '--no-sandbox',
70    '--disable-kill-after-bad-ipc',
71  ]
72
73  if args.gdb_browser:
74    chrome_command = ['gdb', '--args'] + chrome_command
75
76  launchers = {}
77  for prefix in prefixes:
78    launchers[prefix] = fuzzer_path
79
80  for arg in args.chrome_args:
81    if arg.find('=') != -1:
82      switch, value = arg.split('=', 1)
83      if switch in prefixes:
84        launchers[switch] = value + ' ' + launchers[switch]
85        continue
86    chrome_command.append(arg)
87
88  for switch, value in launchers.items():
89    chrome_command.append(switch + '=' + value)
90
91  command_line = ' '.join(['\'' + arg + '\'' for arg in chrome_command])
92  print 'Executing: ' + command_line
93
94  return subprocess.call(chrome_command)
95
96
97if __name__ == "__main__":
98  sys.exit(main())
99