# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
This script runs Chrome and automatically navigates through the given list of
URLs the specified number of times.

Usage: vpython3 auto-nav.py <chrome dir> <number of navigations> <url> <url> ...

Optional flags:
* --interval <seconds>, -i <seconds>: specify a number of seconds to wait
                                      between navigations, e.g., -i=5
* --start_prompt, -s: start Chrome, then wait for the user to press Enter before
                      starting auto-navigation
* --exit-prompt, -e: after auto-navigation, wait for the user to press Enter
                     before shutting down chrome.exe
* --idlewakeups_dir: Windows only; specify the directory containing
                     idlewakeups.exe to print measurements taken by IdleWakeups,
                     e.g., --idlewakeups_dir=tools/win/IdleWakeups/x64/Debug

Optional flags to chrome.exe, example:
-- --user-data-dir=temp --disable-features=SomeFeature
Note: must be at end of command, following options terminator "--". The options
terminator stops command-line options from being interpreted as options for this
script, which would cause an unrecognized-argument error.
"""

# [VPYTHON:BEGIN]
# python_version: "3.8"
# wheel: <
#   name: "infra/python/wheels/selenium-py2_py3"
#   version: "version:3.14.0"
# >
# wheel: <
#   name: "infra/python/wheels/urllib3-py2_py3"
#   version: "version:1.24.3"
# >
# wheel: <
#   name: "infra/python/wheels/psutil/${vpython_platform}"
#   version: "version:5.7.2"
# >
# [VPYTHON:END]

import argparse
import os
import subprocess
import sys
import time
import urllib

try:
  import psutil
  from selenium import webdriver
except ImportError:
  print('Error importing required modules. Run with vpython3 instead of python.')
  sys.exit(1)

DEFAULT_INTERVAL = 1
EXIT_CODE_ERROR = 1

# Splits list |positional_args| into two lists: |urls| and |chrome_args|, where
# arguments starting with '-' are treated as chrome args, and the rest as URLs.
def ParsePositionalArgs(positional_args):
  urls, chrome_args = [], []
  for arg in positional_args:
    if arg.startswith('-'):
      chrome_args.append(arg)
    else:
      urls.append(arg)
  return [urls, chrome_args]


# Returns an object containing the arguments parsed from this script's command
# line.
def ParseArgs():
  # Customize usage and help to include options to be passed to chrome.exe.
  usage_text = '''%(prog)s [-h] [--interval INTERVAL] [--wait]
                   [--idlewakeups_dir IDLEWAKEUPS_DIR]
                   chrome_dir num_navigations url [url ...]
                   [-- --chrome_option ...]'''
  additional_help_text = '''optional arguments to chrome.exe, example:
  -- --enable-features=MyFeature --browser-startup-dialog
                        Must be at end of command, following the options
                        terminator "--"'''
  parser = argparse.ArgumentParser(
      epilog=additional_help_text,
      usage=usage_text,
      formatter_class=argparse.RawDescriptionHelpFormatter)
  parser.add_argument(
      'chrome_dir', help='Directory containing chrome.exe and chromedriver.exe')
  parser.add_argument('num_navigations',
                      type=int,
                      help='Number of times to navigate through list of URLs')
  parser.add_argument('--interval',
                      '-i',
                      type=int,
                      help='Seconds to wait between navigations; default is 1')
  parser.add_argument('--start_prompt',
                      '-s',
                      action='store_true',
                      help='Wait for confirmation before starting navigation')
  parser.add_argument('--exit_prompt',
                      '-e',
                      action='store_true',
                      help='Wait for confirmation before exiting chrome.exe')
  parser.add_argument(
      '--idlewakeups_dir',
      help='Windows only; directory containing idlewakeups.exe, if using')
  parser.add_argument(
      'url',
      nargs='+',
      help='URL(s) to navigate, separated by spaces; must include scheme, '
      'e.g., "https://"')
  args = parser.parse_args()
  args.url, chrome_args = ParsePositionalArgs(args.url)
  if not args.url:
    parser.print_usage()
    print(os.path.basename(__file__) + ': error: missing URL argument')
    exit(EXIT_CODE_ERROR)
  for url in args.url:
    if not urllib.parse.urlparse(url).scheme:
      print(os.path.basename(__file__) +
            ': error: URL is missing required scheme (e.g., "https://"): ' + url)
      exit(EXIT_CODE_ERROR)
  return [args, chrome_args]


# If |path| does not exist, prints a generic error plus optional |error_message|
# and exits.
def ExitIfNotFound(path, error_message=None):
  if not os.path.exists(path):
    print('File not found: {}.'.format(path))
    if error_message:
      print(error_message)
    exit(EXIT_CODE_ERROR)


def main():
  # Parse arguments and check that file paths received are valid.
  args, chrome_args = ParseArgs()
  ExitIfNotFound(os.path.join(args.chrome_dir, 'chrome.exe'),
                 'Build target "chrome" to generate it first.')
  chromedriver_exe = os.path.join(args.chrome_dir, 'chromedriver.exe')
  ExitIfNotFound(chromedriver_exe,
                 'Build target "chromedriver" to generate it first.')
  if args.idlewakeups_dir:
    idlewakeups_exe = os.path.join(args.idlewakeups_dir, 'idlewakeups.exe')
    ExitIfNotFound(idlewakeups_exe)

  # Start chrome.exe. Disable chrome.exe's extensive logging to make reading
  # this script's output easier.
  chrome_options = webdriver.ChromeOptions()
  chrome_options.add_experimental_option('excludeSwitches', ['enable-logging'])
  for arg in chrome_args:
    chrome_options.add_argument(arg)
  driver = webdriver.Chrome(os.path.abspath(chromedriver_exe),
                            options=chrome_options)

  if args.start_prompt:
    driver.get(args.url[0])
    input('Press Enter to begin navigation...')

  # Start IdleWakeups, if using, passing the browser process's ID as its target.
  # IdleWakeups will monitor the browser process and its children. Other running
  # chrome.exe processes (i.e., those not launched by this script) are excluded.
  if args.idlewakeups_dir:
    launched_processes = psutil.Process(
        driver.service.process.pid).children(recursive=False)
    if not launched_processes:
      print('Error getting browser process ID for IdleWakeups.')
      exit()
    # Assume the first child process created by |driver| is the browser process.
    idlewakeups = subprocess.Popen([
        idlewakeups_exe,
        str(launched_processes[0].pid), '--stop-on-exit', '--tabbed'
    ],
                                   stdout=subprocess.PIPE)

  # Navigate through |args.url| list |args.num_navigations| times, then close
  # chrome.exe.
  interval = args.interval if args.interval else DEFAULT_INTERVAL
  for _ in range(args.num_navigations):
    for url in args.url:
      driver.get(url)
      time.sleep(interval)

  if args.exit_prompt:
    input('Press Enter to exit...')
  driver.quit()

  # Print IdleWakeups' output, if using.
  if args.idlewakeups_dir:
    print(idlewakeups.communicate()[0])


if __name__ == '__main__':
  sys.exit(main())
