Enable Dr. Memory to run javascript, pixel, and corpus tests

- add DrMemoryWrapper in common.py to adjust Dr. Memory wrapper
- add --wrapper option to run_*_tests.py for Dr. Mempry wrapper
- update run_*_tests.py to handle Dr. Memory wrapper
- add TestPDFiumTest in pdfium_tests.py to support run_*_tests.py
- remove ValgrindTool in valgrind_tests.py

R=thestig@chromium.org
BUG=pdfium:238

Review URL: https://codereview.chromium.org/1464453003 .
diff --git a/testing/tools/common.py b/testing/tools/common.py
index d45404b..6e9de7c 100755
--- a/testing/tools/common.py
+++ b/testing/tools/common.py
@@ -3,6 +3,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import glob
 import os
 import subprocess
 import sys
@@ -27,6 +28,38 @@
   except subprocess.CalledProcessError as e:
     return e
 
+# Adjust Dr. Memory wrapper to have separate log directory for each test
+# for better error reporting.
+def DrMemoryWrapper(wrapper, pdf_name):
+  if not wrapper:
+    return []
+  # convert string to list
+  cmd_to_run = wrapper.split()
+
+  # Do nothing if using default log directory.
+  if cmd_to_run.count("-logdir") == 0:
+    return cmd_to_run
+  # Usually, we pass "-logdir" "foo\bar\spam path" args to Dr. Memory.
+  # To group reports per test, we want to put the reports for each test into a
+  # separate directory. This code can be simplified when we have
+  # https://github.com/DynamoRIO/drmemory/issues/684 fixed.
+  logdir_idx = cmd_to_run.index("-logdir")
+  old_logdir = cmd_to_run[logdir_idx + 1]
+  wrapper_pid = str(os.getpid())
+
+  # We are using the same pid of the same python process, so append the number
+  # of entries in the logdir at the end of wrapper_pid to avoid conflict.
+  wrapper_pid += "_%d" % len(glob.glob(old_logdir + "\\*"))
+
+  cmd_to_run[logdir_idx + 1] += "\\testcase.%s.logs" % wrapper_pid
+  os.makedirs(cmd_to_run[logdir_idx + 1])
+
+  f = open(old_logdir + "\\testcase.%s.name" % wrapper_pid, "w")
+  print >>f, pdf_name + ".pdf"
+  f.close()
+
+  return cmd_to_run
+
 
 class DirectoryFinder:
   '''A class for finding directories and paths under either a standalone
diff --git a/testing/tools/run_corpus_tests.py b/testing/tools/run_corpus_tests.py
index 29f23b5..e2b950c 100755
--- a/testing/tools/run_corpus_tests.py
+++ b/testing/tools/run_corpus_tests.py
@@ -26,10 +26,10 @@
 #   c_dir - "path/to/a/b/c"
 
 def test_one_file(input_filename, source_dir, working_dir,
-                  pdfium_test_path, image_differ, redirect_output=False):
+                  pdfium_test_path, image_differ, drmem_wrapper,
+                  redirect_output=False):
   input_path = os.path.join(source_dir, input_filename)
   pdf_path = os.path.join(working_dir, input_filename)
-
   # Remove any existing generated images from previous runs.
   actual_images = image_differ.GetActualFiles(
       input_filename, source_dir, working_dir)
@@ -39,8 +39,13 @@
 
   shutil.copyfile(input_path, pdf_path)
   sys.stdout.flush()
-  error = common.RunCommand([pdfium_test_path, '--png', pdf_path],
-                            redirect_output)
+  # add Dr. Memory wrapper if exist
+  # remove .pdf suffix
+  cmd_to_run = common.DrMemoryWrapper(drmem_wrapper,
+                                      os.path.splitext(input_filename)[0])
+  cmd_to_run.extend([pdfium_test_path, '--png', pdf_path])
+  # run test
+  error = common.RunCommand(cmd_to_run, redirect_output)
   if error:
     print "FAILURE: " + input_filename + "; " + str(error)
     return False
@@ -58,7 +63,7 @@
     sys.stderr = sys.stdout
     input_filename, source_dir = test_case
     result = test_one_file(input_filename, source_dir, working_dir,
-                           pdfium_test_path, image_differ, True);
+                           pdfium_test_path, image_differ, "", True);
     output = sys.stdout
     sys.stdout = old_stdout
     sys.stderr = old_stderr
@@ -84,6 +89,8 @@
   parser.add_option('-j', default=multiprocessing.cpu_count(),
                     dest='num_workers', type='int',
                     help='run NUM_WORKERS jobs in parallel')
+  parser.add_option('--wrapper', default='', dest="wrapper",
+                    help='Dr. Memory wrapper for running test under Dr. Memory')
   options, args = parser.parse_args()
   finder = common.DirectoryFinder(options.build_dir)
   pdfium_test_path = finder.ExecutablePath('pdfium_test')
@@ -143,7 +150,8 @@
     for test_case in test_cases:
       input_filename, source_dir = test_case
       result = test_one_file(input_filename, source_dir, working_dir,
-                             pdfium_test_path, image_differ)
+                             pdfium_test_path, image_differ,
+                             options.wrapper)
       handle_result(test_suppressor, input_filename, input_path, result,
                     surprises, failures)
 
diff --git a/testing/tools/run_javascript_tests.py b/testing/tools/run_javascript_tests.py
index e2fdc66..0c24017 100755
--- a/testing/tools/run_javascript_tests.py
+++ b/testing/tools/run_javascript_tests.py
@@ -18,7 +18,8 @@
 #   c_dir - "path/to/a/b/c"
 
 def generate_and_test(input_filename, source_dir, working_dir,
-                      fixup_path, pdfium_test_path, text_diff_path):
+                      fixup_path, pdfium_test_path, text_diff_path,
+                      drmem_wrapper):
   input_root, _ = os.path.splitext(input_filename)
   input_path = os.path.join(source_dir, input_root + '.in')
   pdf_path = os.path.join(working_dir, input_root + '.pdf')
@@ -29,7 +30,11 @@
     subprocess.check_call(
         [sys.executable, fixup_path, '--output-dir=' + working_dir, input_path])
     with open(txt_path, 'w') as outfile:
-      subprocess.check_call([pdfium_test_path, pdf_path], stdout=outfile)
+      # add Dr. Memory wrapper if exist
+      cmd_to_run = common.DrMemoryWrapper(drmem_wrapper, input_root)
+      cmd_to_run.extend([pdfium_test_path, pdf_path])
+      # run test
+      subprocess.check_call(cmd_to_run, stdout=outfile)
     subprocess.check_call(
         [sys.executable, text_diff_path, expected_path, txt_path])
   except subprocess.CalledProcessError as e:
@@ -41,6 +46,8 @@
   parser = optparse.OptionParser()
   parser.add_option('--build-dir', default=os.path.join('out', 'Debug'),
                     help='relative path from the base source directory')
+  parser.add_option('--wrapper', default='', dest="wrapper",
+                    help='Dr. Memory wrapper for running test under Dr. Memory')
   options, args = parser.parse_args()
 
   finder = common.DirectoryFinder(options.build_dir)
@@ -70,7 +77,8 @@
       input_path = os.path.join(source_dir, input_filename)
       if os.path.isfile(input_path):
         if not generate_and_test(input_filename, source_dir, working_dir,
-                                 fixup_path, pdfium_test_path, text_diff_path):
+                                 fixup_path, pdfium_test_path, text_diff_path,
+                                 options.wrapper):
           failures.append(input_path)
 
   if failures:
diff --git a/testing/tools/run_pixel_tests.py b/testing/tools/run_pixel_tests.py
index b167923..8d83840 100755
--- a/testing/tools/run_pixel_tests.py
+++ b/testing/tools/run_pixel_tests.py
@@ -20,7 +20,8 @@
 #   c_dir - "path/to/a/b/c"
 
 def generate_and_test(input_filename, source_dir, working_dir,
-                      fixup_path, pdfium_test_path, image_differ):
+                      fixup_path, pdfium_test_path, image_differ,
+                      drmem_wrapper):
   input_root, _ = os.path.splitext(input_filename)
   input_path = os.path.join(source_dir, input_root + '.in')
   pdf_path = os.path.join(working_dir, input_root + '.pdf')
@@ -36,7 +37,11 @@
     sys.stdout.flush()
     subprocess.check_call(
         [sys.executable, fixup_path, '--output-dir=' + working_dir, input_path])
-    subprocess.check_call([pdfium_test_path, '--png', pdf_path])
+    # add Dr. Memory wrapper if exist
+    cmd_to_run = common.DrMemoryWrapper(drmem_wrapper, input_root)
+    cmd_to_run.extend([pdfium_test_path, '--png', pdf_path])
+    # run test
+    subprocess.check_call(cmd_to_run)
   except subprocess.CalledProcessError as e:
     print "FAILURE: " + input_filename + "; " + str(e)
     return False
@@ -50,6 +55,8 @@
   parser = optparse.OptionParser()
   parser.add_option('--build-dir', default=os.path.join('out', 'Debug'),
                     help='relative path from the base source directory')
+  parser.add_option('--wrapper', default='', dest="wrapper",
+                    help='Dr. Memory wrapper for running test under Dr. Memory')
   options, args = parser.parse_args()
   finder = common.DirectoryFinder(options.build_dir)
   fixup_path = finder.ScriptPath('fixup_pdf_template.py')
@@ -82,7 +89,8 @@
         if test_suppressor.IsSuppressed(input_filename):
           continue
         if not generate_and_test(input_filename, source_dir, working_dir,
-                                 fixup_path, pdfium_test_path, image_differ):
+                                 fixup_path, pdfium_test_path, image_differ,
+                                 options.wrapper):
           failures.append(input_path)
 
   if failures:
diff --git a/tools/drmemory/scripts/pdfium_tests.py b/tools/drmemory/scripts/pdfium_tests.py
index 5486b16..c1733f5 100644
--- a/tools/drmemory/scripts/pdfium_tests.py
+++ b/tools/drmemory/scripts/pdfium_tests.py
@@ -50,10 +50,10 @@
     self._options = options
     self._args = args
 
-    script_dir = path_utils.ScriptDir()
-    # Compute the top of the tree (the "source dir") from the script dir (where
-    # this script lives).  We assume that the script dir is in tools/valgrind/
-    # relative to the top of the tree.
+    # Compute the top of the tree (the "source dir") from the script dir
+    # (where this script lives).  We assume that the script dir is in
+    # tools/drmemory/scripts relative to the top of the tree.
+    script_dir = os.path.dirname(path_utils.ScriptDir())
     self._source_dir = os.path.dirname(os.path.dirname(script_dir))
     # since this path is used for string matching, make sure it's always
     # an absolute Unix-style path
@@ -269,11 +269,53 @@
   def TestPDFiumEmbedderTests(self):
     return self.SimpleTest("pdfium_embeddertests", "pdfium_embeddertests")
 
+  def TestPDFiumTest(self, script_name):
+    # Build the command line in 'cmd'.
+    # It's going to be roughly
+    #  python valgrind_test.py ...
+    # but we'll use the --indirect_pdfium_test flag to valgrind_test.py
+    # to avoid valgrinding python.
+
+    # Start by building the valgrind_test.py commandline.
+    tool = valgrind_test.CreateTool(self._options.valgrind_tool)
+    cmd = self._DefaultCommand(tool)
+    cmd.append("--trace_children")
+    cmd.append("--indirect_pdfium_test")
+    cmd.append("--ignore_exit_code")
+    # Now build script_cmd, the run_corpus_tests commandline.
+    script = os.path.join(self._source_dir, "testing", "tools", script_name)
+    script_cmd = ["python", script]
+    if self._options.build_dir:
+      script_cmd.extend(["--build-dir", self._options.build_dir])
+    # TODO(zhaoqin): it only runs in single process mode now,
+    # need figure out why it does not work with test_one_file_parallel
+    # in run_corpus_tests.py.
+    if script_name == "run_corpus_tests.py":
+        script_cmd.extend(["-j", "1"])
+    # Now run script_cmd with the wrapper in cmd
+    cmd.append("--")
+    cmd.extend(script_cmd)
+
+    ret = tool.Run(cmd, "layout", min_runtime_in_seconds=0)
+    return ret
+
+  def TestPDFiumJavascript(self):
+    return self.TestPDFiumTest("run_javascript_tests.py")
+
+  def TestPDFiumPixel(self):
+    return self.TestPDFiumTest("run_pixel_tests.py")
+
+  def TestPDFiumCorpus(self):
+    return self.TestPDFiumTest("run_corpus_tests.py")
+
   # The known list of tests.
   _test_list = {
-    "cmdline" : RunCmdLine,
-    "pdfium_unittests": TestPDFiumUnitTests,
+    "cmdline" :             RunCmdLine,
+    "pdfium_corpus":        TestPDFiumCorpus,
     "pdfium_embeddertests": TestPDFiumEmbedderTests,
+    "pdfium_javascript":    TestPDFiumJavascript,
+    "pdfium_pixel":         TestPDFiumPixel,
+    "pdfium_unittests":     TestPDFiumUnitTests,
   }
 
 
diff --git a/tools/drmemory/scripts/valgrind_test.py b/tools/drmemory/scripts/valgrind_test.py
index bde3002..d0581f3 100644
--- a/tools/drmemory/scripts/valgrind_test.py
+++ b/tools/drmemory/scripts/valgrind_test.py
@@ -230,277 +230,6 @@
     return self.Main(args, check_sanity, min_runtime_in_seconds)
 
 
-class ValgrindTool(BaseTool):
-  """Abstract class for running Valgrind tools.
-
-  Always subclass this and implement ToolSpecificFlags() and
-  ExtendOptionParser() for tool-specific stuff.
-  """
-  def __init__(self):
-    super(ValgrindTool, self).__init__()
-    self.RegisterOptionParserHook(ValgrindTool.ExtendOptionParser)
-
-  def UseXML(self):
-    # Override if tool prefers nonxml output
-    return True
-
-  def ExtendOptionParser(self, parser):
-    parser.add_option("", "--suppressions", default=[],
-                            action="append",
-                            help="path to a valgrind suppression file")
-    parser.add_option("", "--indirect", action="store_true",
-                            default=False,
-                            help="set BROWSER_WRAPPER rather than "
-                                 "running valgrind directly")
-    parser.add_option("", "--indirect_webkit_layout", action="store_true",
-                            default=False,
-                            help="set --wrapper rather than running Dr. Memory "
-                                 "directly.")
-    parser.add_option("", "--trace_children", action="store_true",
-                            default=False,
-                            help="also trace child processes")
-    parser.add_option("", "--num-callers",
-                            dest="num_callers", default=30,
-                            help="number of callers to show in stack traces")
-    parser.add_option("", "--generate_dsym", action="store_true",
-                          default=False,
-                          help="Generate .dSYM file on Mac if needed. Slow!")
-
-  def Setup(self, args):
-    if not BaseTool.Setup(self, args):
-      return False
-    if common.IsMac():
-      self.PrepareForTestMac()
-    return True
-
-  def PrepareForTestMac(self):
-    """Runs dsymutil if needed.
-
-    Valgrind for Mac OS X requires that debugging information be in a .dSYM
-    bundle generated by dsymutil.  It is not currently able to chase DWARF
-    data into .o files like gdb does, so executables without .dSYM bundles or
-    with the Chromium-specific "fake_dsym" bundles generated by
-    build/mac/strip_save_dsym won't give source file and line number
-    information in valgrind.
-
-    This function will run dsymutil if the .dSYM bundle is missing or if
-    it looks like a fake_dsym.  A non-fake dsym that already exists is assumed
-    to be up-to-date.
-    """
-    test_command = self._args[0]
-    dsym_bundle = self._args[0] + '.dSYM'
-    dsym_file = os.path.join(dsym_bundle, 'Contents', 'Resources', 'DWARF',
-                             os.path.basename(test_command))
-    dsym_info_plist = os.path.join(dsym_bundle, 'Contents', 'Info.plist')
-
-    needs_dsymutil = True
-    saved_test_command = None
-
-    if os.path.exists(dsym_file) and os.path.exists(dsym_info_plist):
-      # Look for the special fake_dsym tag in dsym_info_plist.
-      dsym_info_plist_contents = open(dsym_info_plist).read()
-
-      if not re.search('^\s*<key>fake_dsym</key>$', dsym_info_plist_contents,
-                       re.MULTILINE):
-        # fake_dsym is not set, this is a real .dSYM bundle produced by
-        # dsymutil.  dsymutil does not need to be run again.
-        needs_dsymutil = False
-      else:
-        # fake_dsym is set.  dsym_file is a copy of the original test_command
-        # before it was stripped.  Copy it back to test_command so that
-        # dsymutil has unstripped input to work with.  Move the stripped
-        # test_command out of the way, it will be restored when this is
-        # done.
-        saved_test_command = test_command + '.stripped'
-        os.rename(test_command, saved_test_command)
-        shutil.copyfile(dsym_file, test_command)
-        shutil.copymode(saved_test_command, test_command)
-
-    if needs_dsymutil:
-      if self._options.generate_dsym:
-        # Remove the .dSYM bundle if it exists.
-        shutil.rmtree(dsym_bundle, True)
-
-        dsymutil_command = ['dsymutil', test_command]
-
-        # dsymutil is crazy slow.  Ideally we'd have a timeout here,
-        # but common.RunSubprocess' timeout is only checked
-        # after each line of output; dsymutil is silent
-        # until the end, and is then killed, which is silly.
-        common.RunSubprocess(dsymutil_command)
-
-        if saved_test_command:
-          os.rename(saved_test_command, test_command)
-      else:
-        logging.info("No real .dSYM for test_command.  Line numbers will "
-                     "not be shown.  Either tell xcode to generate .dSYM "
-                     "file, or use --generate_dsym option to this tool.")
-
-  def ToolCommand(self):
-    """Get the valgrind command to run."""
-    # Note that self._args begins with the exe to be run.
-    tool_name = self.ToolName()
-
-    # Construct the valgrind command.
-    if 'CHROME_VALGRIND' in os.environ:
-      path = os.path.join(os.environ['CHROME_VALGRIND'], "bin", "valgrind")
-    else:
-      path = "valgrind"
-    proc = [path, "--tool=%s" % tool_name]
-
-    proc += ["--num-callers=%i" % int(self._options.num_callers)]
-
-    if self._options.trace_children:
-      proc += ["--trace-children=yes"]
-      proc += ["--trace-children-skip='*dbus-daemon*'"]
-      proc += ["--trace-children-skip='*dbus-launch*'"]
-      proc += ["--trace-children-skip='*perl*'"]
-      proc += ["--trace-children-skip='*python*'"]
-      # This is really Python, but for some reason Valgrind follows it.
-      proc += ["--trace-children-skip='*lsb_release*'"]
-
-    proc += self.ToolSpecificFlags()
-    proc += self._tool_flags
-
-    suppression_count = 0
-    for suppression_file in self._options.suppressions:
-      if os.path.exists(suppression_file):
-        suppression_count += 1
-        proc += ["--suppressions=%s" % suppression_file]
-
-    if not suppression_count:
-      logging.warning("WARNING: NOT USING SUPPRESSIONS!")
-
-    logfilename = self.log_dir + ("/%s." % tool_name) + "%p"
-    if self.UseXML():
-      proc += ["--xml=yes", "--xml-file=" + logfilename]
-    else:
-      proc += ["--log-file=" + logfilename]
-
-    # The Valgrind command is constructed.
-
-    # Handle --indirect_webkit_layout separately.
-    if self._options.indirect_webkit_layout:
-      # Need to create the wrapper before modifying |proc|.
-      wrapper = self.CreateBrowserWrapper(proc, webkit=True)
-      proc = self._args
-      proc.append("--wrapper")
-      proc.append(wrapper)
-      return proc
-
-    if self._options.indirect:
-      wrapper = self.CreateBrowserWrapper(proc)
-      os.environ["BROWSER_WRAPPER"] = wrapper
-      logging.info('export BROWSER_WRAPPER=' + wrapper)
-      proc = []
-    proc += self._args
-    return proc
-
-  def ToolSpecificFlags(self):
-    raise NotImplementedError, "This method should be implemented " \
-                               "in the tool-specific subclass"
-
-  def CreateBrowserWrapper(self, proc, webkit=False):
-    """The program being run invokes Python or something else that can't stand
-    to be valgrinded, and also invokes the Chrome browser. In this case, use a
-    magic wrapper to only valgrind the Chrome browser. Build the wrapper here.
-    Returns the path to the wrapper. It's up to the caller to use the wrapper
-    appropriately.
-    """
-    command = " ".join(proc)
-    # Add the PID of the browser wrapper to the logfile names so we can
-    # separate log files for different UI tests at the analyze stage.
-    command = command.replace("%p", "$$.%p")
-
-    (fd, indirect_fname) = tempfile.mkstemp(dir=self.log_dir,
-                                            prefix="browser_wrapper.",
-                                            text=True)
-    f = os.fdopen(fd, "w")
-    f.write('#!/bin/bash\n'
-            'echo "Started Valgrind wrapper for this test, PID=$$" >&2\n')
-
-    f.write('DIR=`dirname $0`\n'
-            'TESTNAME_FILE=$DIR/testcase.$$.name\n\n')
-
-    if webkit:
-      # Webkit layout_tests pass the URL as the first line of stdin.
-      f.write('tee $TESTNAME_FILE | %s "$@"\n' % command)
-    else:
-      # Try to get the test case name by looking at the program arguments.
-      # i.e. Chromium ui_tests used --test-name arg.
-      # TODO(timurrrr): This doesn't handle "--test-name Test.Name"
-      # TODO(timurrrr): ui_tests are dead. Where do we use the non-webkit
-      # wrapper now? browser_tests? What do they do?
-      f.write('for arg in $@\ndo\n'
-              '  if [[ "$arg" =~ --test-name=(.*) ]]\n  then\n'
-              '    echo ${BASH_REMATCH[1]} >$TESTNAME_FILE\n'
-              '  fi\n'
-              'done\n\n'
-              '%s "$@"\n' % command)
-
-    f.close()
-    os.chmod(indirect_fname, stat.S_IRUSR|stat.S_IXUSR)
-    return indirect_fname
-
-  def CreateAnalyzer(self):
-    raise NotImplementedError, "This method should be implemented " \
-                               "in the tool-specific subclass"
-
-  def GetAnalyzeResults(self, check_sanity=False):
-    # Glob all the files in the log directory
-    filenames = glob.glob(self.log_dir + "/" + self.ToolName() + ".*")
-
-    # If we have browser wrapper, the logfiles are named as
-    # "toolname.wrapper_PID.valgrind_PID".
-    # Let's extract the list of wrapper_PIDs and name it ppids
-    ppids = set([int(f.split(".")[-2]) \
-                for f in filenames if re.search("\.[0-9]+\.[0-9]+$", f)])
-
-    analyzer = self.CreateAnalyzer()
-    if len(ppids) == 0:
-      # Fast path - no browser wrapper was set.
-      return analyzer.Report(filenames, None, check_sanity)
-
-    ret = 0
-    for ppid in ppids:
-      testcase_name = None
-      try:
-        f = open(self.log_dir + ("/testcase.%d.name" % ppid))
-        testcase_name = f.read().strip()
-        f.close()
-        wk_layout_prefix="third_party/WebKit/LayoutTests/"
-        wk_prefix_at = testcase_name.rfind(wk_layout_prefix)
-        if wk_prefix_at != -1:
-          testcase_name = testcase_name[wk_prefix_at + len(wk_layout_prefix):]
-      except IOError:
-        pass
-      print "====================================================="
-      print " Below is the report for valgrind wrapper PID=%d." % ppid
-      if testcase_name:
-        print " It was used while running the `%s` test." % testcase_name
-      else:
-        print " You can find the corresponding test"
-        print " by searching the above log for 'PID=%d'" % ppid
-      sys.stdout.flush()
-
-      ppid_filenames = [f for f in filenames \
-                        if re.search("\.%d\.[0-9]+$" % ppid, f)]
-      # check_sanity won't work with browser wrappers
-      assert check_sanity == False
-      ret |= analyzer.Report(ppid_filenames, testcase_name)
-      print "====================================================="
-      sys.stdout.flush()
-
-    if ret != 0:
-      print ""
-      print "The Valgrind reports are grouped by test names."
-      print "Each test has its PID printed in the log when the test was run"
-      print "and at the beginning of its Valgrind report."
-      print "Hint: you can search for the reports by Ctrl+F -> `=#`"
-      sys.stdout.flush()
-
-    return ret
-
 class DrMemory(BaseTool):
   """Dr.Memory
   Dynamic memory error detector for Windows.
@@ -527,13 +256,9 @@
                       help="Monitor python child processes.  If off, neither "
                       "python children nor any children of python children "
                       "will be monitored.")
-    parser.add_option("", "--indirect", action="store_true",
+    parser.add_option("", "--indirect_pdfium_test", action="store_true",
                       default=False,
-                      help="set BROWSER_WRAPPER rather than "
-                           "running Dr. Memory directly on the harness")
-    parser.add_option("", "--indirect_webkit_layout", action="store_true",
-                      default=False,
-                      help="set --wrapper rather than running valgrind "
+                      help="set --wrapper rather than running Dr. Memory "
                       "directly.")
     parser.add_option("", "--use_debug", action="store_true",
                       default=False, dest="use_debug",
@@ -677,20 +402,12 @@
     # Dr.Memory requires -- to separate tool flags from the executable name.
     proc += ["--"]
 
-    if self._options.indirect or self._options.indirect_webkit_layout:
-      wrapper_path = os.path.join(self._source_dir,
-                                  "tools", "valgrind", "browser_wrapper_win.py")
-      wrapper = " ".join(["python", wrapper_path] + proc)
-      self.CreateBrowserWrapper(wrapper)
-      logging.info("browser wrapper = " + " ".join(proc))
-      if self._options.indirect_webkit_layout:
-        proc = self._args
-        # Layout tests want forward slashes.
-        wrapper = wrapper.replace('\\', '/')
-        proc += ["--wrapper", wrapper]
-        return proc
-      else:
-        proc = []
+    if self._options.indirect_pdfium_test:
+      wrapper = " ".join(proc)
+      logging.info("pdfium wrapper = " + wrapper)
+      proc = self._args
+      proc += ["--wrapper", wrapper]
+      return proc
 
     # Note that self._args begins with the name of the exe to be run.
     self._args[0] = common.NormalizeWindowsPath(self._args[0])
@@ -708,7 +425,7 @@
     analyzer = drmemory_analyze.DrMemoryAnalyzer()
 
     ret = 0
-    if not self._options.indirect and not self._options.indirect_webkit_layout:
+    if not self._options.indirect_pdfium_test:
       filenames = glob.glob(self.log_dir + "/*/results.txt")
 
       ret = analyzer.Report(filenames, None, check_sanity)