POSIX: add command line option to launch renderers in a wrapper

For example, ./Hammer/chrome --renderer-cmd-prefix="gdb --args"

Review URL: http://codereview.chromium.org/21190


git-svn-id: svn://svn.chromium.org/chrome/trunk/src@9438 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/base/command_line.cc b/base/command_line.cc
index cf3e36f4..d9a2052 100644
--- a/base/command_line.cc
+++ b/base/command_line.cc
@@ -334,5 +334,15 @@
   for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
     switches_[i->first] = i->second;
 }
+
+void CommandLine::PrependWrapper(const std::wstring& wrapper_wide) {
+  // The wrapper may have embedded arguments (like "gdb --args"). In this case,
+  // we don't pretend to do anything fancy, we just split on spaces.
+  const std::string wrapper = WideToASCII(wrapper_wide);
+  std::vector<std::string> wrapper_and_args;
+  SplitString(wrapper, ' ', &wrapper_and_args);
+  argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end());
+}
+
 #endif
 
diff --git a/base/command_line.h b/base/command_line.h
index 9a02546..94992b8 100644
--- a/base/command_line.h
+++ b/base/command_line.h
@@ -114,6 +114,10 @@
   void AppendArguments(const CommandLine& other,
                        bool include_program);
 
+  // On POSIX systems it's common to run processes via a wrapper (like
+  // "valgrind" or "gdb --args"). *Note, only availible on POSIX*
+  void PrependWrapper(const std::wstring& wrapper);
+
  private:
   friend class InProcessBrowserTest;
 
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc
index 33ef770..3e3081a 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -284,6 +284,13 @@
       DebugFlags::ProcessDebugFlags(&cmd_line,
                                     DebugFlags::RENDERER,
                                     in_sandbox);
+#elif defined(OS_POSIX)
+  if (browser_command_line.HasSwitch(switches::kRendererCmdPrefix)) {
+    // launch the renderer child with some prefix (usually "gdb --args")
+    const std::wstring prefix =
+        browser_command_line.GetSwitchValue(switches::kRendererCmdPrefix);
+    cmd_line.PrependWrapper(prefix);
+  }
 #endif
 
   cmd_line.AppendSwitchWithValue(switches::kProcessType,
@@ -644,7 +651,15 @@
   } else {
     // Need to verify that the peer_pid is actually the process we know, if
     // it is not, we need to panic now. See bug 1002150.
-    CHECK(peer_pid == process_.pid());
+    if (peer_pid != process_.pid()) {
+      // In the case that we are running the renderer in a wrapper, this check
+      // is invalid as it's the wrapper PID that we'll have, not the actual
+      // renderer
+      const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
+      if (cmd_line.HasSwitch(switches::kRendererCmdPrefix))
+        return;
+      CHECK(peer_pid == process_.pid());
+    }
   }
 }
 
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 1e5a622..78ad8d3 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -371,4 +371,8 @@
 // Pass the name of the current running automated test to Chrome.
 const wchar_t kTestName[]                      = L"test-name";
 
+// On POSIX only: the contents of this flag are prepended to the renderer
+// command line. (Useful values might be "valgrind" or "gdb --args")
+const wchar_t kRendererCmdPrefix[]             = L"renderer-cmd-prefix";
+
 }  // namespace switches
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index a64f632..6f9946b 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -144,6 +144,8 @@
 
 extern const wchar_t kTestName[];
 
+extern const wchar_t kRendererCmdPrefix[];
+
 }  // namespace switches
 
 #endif  // CHROME_COMMON_CHROME_SWITCHES_H__