def TestApps(options, work_dir):
    """Test a browser on a corpus of crxs.

  Args:
    options: bag of options.
    work_dir: directory to operate in.
  """
    profile_path = os.path.join(work_dir, 'profile_temp')
    app_path = os.path.join(work_dir, 'app_temp')

    list_filename = os.path.join(work_dir, 'naclapps.all')
    filenames = corpus_utils.DownloadCorpusList(list_filename)
    filenames = [f for f in filenames if f.endswith('.crx')]
    progress = corpus_utils.Progress(len(filenames))
    for filename in filenames:
        progress.Tally()
        corpus_utils.PrimeCache(options.cache_dir, filename)
        # Stop here if downloading only.
        if options.download_only:
            continue
        # Stop here if isn't a bad app but testing only bad apps.
        if options.bad_only and corpus_errors.ExpectedCrxResult(
                filename) == 'GOOD':
            continue
        # Unzip the app.
        corpus_utils.ExtractFromCache(options.cache_dir, filename, app_path)
        try:
            progress.Result(
                TestAppStartup(options, filename, app_path, profile_path))
        finally:
            pynacl.file_tools.RemoveDirectoryIfPresent(app_path)
            pynacl.file_tools.RemoveDirectoryIfPresent(profile_path)
    progress.Summary()
def TestAppStartup(options, crx_path, app_path, profile_path):
    """Run the validator on a nexe, check if the result is expected.

  Args:
    options: bag of options.
    crx_path: path to the crx.
    app_path: path to the extracted crx.
    profile_path: path to a temporary profile dir.
  """
    expected_result = corpus_errors.ExpectedCrxResult(crx_path)
    try:
        manifest = corpus_utils.LoadManifest(app_path)
        start_path = manifest.get('app').get('launch').get('local_path')
    except:
        if expected_result.Matches(corpus_errors.BAD_MANIFEST):
            return True
        else:
            print "'%s': %s," % (corpus_utils.Sha1FromFilename(crx_path),
                                 corpus_errors.BAD_MANIFEST)
            return False
    start_url = 'chrome-extension://%s/%s' % (
        corpus_utils.ChromeAppIdFromPath(app_path), start_path)
    cmd = [
        options.browser, '--disable-web-resources', '--disable-preconnect',
        '--no-first-run', '--no-default-browser-check', '--enable-logging',
        '--log-level=1', '--safebrowsing-disable-auto-update', '--enable-nacl',
        '--load-extension=' + app_path, '--user-data-dir=' + profile_path,
        start_url
    ]
    process_stdout, process_stderr, retcode = corpus_utils.RunWithTimeout(
        cmd, options.duration)
    # Check for errors we don't like.
    result = corpus_errors.GOOD
    errs = re.findall(':ERROR:[^\n]+', process_stderr)
    for err in errs:
        if 'extension_prefs.cc' in err or 'gles2_cmd_decoder.cc' in err:
            continue
        if 'Extension error: Could not load extension from' in err:
            result = result.Merge(corpus_errors.COULD_NOT_LOAD)
            continue
        if 'NaCl process exited with' in process_stderr:
            result = result.Merge(corpus_errors.MODULE_CRASHED)
            continue
        result = result.Merge(
            corpus_errors.CrxResult('custom', custom=err, precidence=20))
    if 'NaClMakePcrelThunk:' not in process_stderr:
        result = result.Merge(corpus_errors.MODULE_DIDNT_START)
    # Check if result is what we expect.
    if not expected_result.Matches(result):
        print "'%s': %s," % (corpus_utils.Sha1FromFilename(crx_path), result)
        if options.verbose:
            print '-' * 70
            print 'Return code: %s' % retcode
            print '>>> STDOUT'
            print process_stdout
            print '>>> STDERR'
            print process_stderr
            print '-' * 70
        return False
    return True