#!/usr/bin/python2
# Copyright (c) 2012 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.

# Virtual Me2Me implementation.  This script runs and manages the processes
# required for a Virtual Me2Me desktop, which are: X server, X desktop
# session, and Host process.
# This script is intended to run continuously as a background daemon
# process, running under an ordinary (non-root) user account.

from __future__ import print_function

import sys
if sys.version_info[0] != 2 or sys.version_info[1] < 7:
  print("This script requires Python version 2.7")
  sys.exit(1)

import argparse
import atexit
import errno
import fcntl
import getpass
import grp
import hashlib
import json
import logging
import os
import pipes
import platform
import psutil
import platform
import pwd
import re
import signal
import socket
import subprocess
import tempfile
import threading
import time
import uuid

# If this env var is defined, extra host params will be loaded from this env var
# as a list of strings separated by space (\s+). Note that param that contains
# space is currently NOT supported and will be broken down into two params at
# the space character.
HOST_EXTRA_PARAMS_ENV_VAR = "CHROME_REMOTE_DESKTOP_HOST_EXTRA_PARAMS"

# This script has a sensible default for the initial and maximum desktop size,
# which can be overridden either on the command-line, or via a comma-separated
# list of sizes in this environment variable.
DEFAULT_SIZES_ENV_VAR = "CHROME_REMOTE_DESKTOP_DEFAULT_DESKTOP_SIZES"

# By default, this script launches Xvfb as the virtual X display. When this
# environment variable is set, the script will instead launch an instance of
# Xorg using the dummy display driver and void input device. In order for this
# to work, both the dummy display driver and void input device need to be
# installed:
#
#     sudo apt-get install xserver-xorg-video-dummy
#     sudo apt-get install xserver-xorg-input-void
#
# TODO(rkjnsn): Add xserver-xorg-video-dummy and xserver-xorg-input-void as
# package dependencies at the same time we switch the default to Xorg
USE_XORG_ENV_VAR = "CHROME_REMOTE_DESKTOP_USE_XORG"

# The amount of video RAM the dummy driver should claim to have, which limits
# the maximum possible resolution.
# 1048576 KiB = 1 GiB, which is the amount of video RAM needed to have a
# 16384x16384 pixel frame buffer (the maximum size supported by VP8) with 32
# bits per pixel.
XORG_DUMMY_VIDEO_RAM = 1048576 # KiB

# By default, provide a maximum size that is large enough to support clients
# with large or multiple monitors. This is a comma-separated list of
# resolutions that will be made available if the X server supports RANDR. These
# defaults can be overridden in ~/.profile.
DEFAULT_SIZES = "1600x1200,3840x2560"

# If RANDR is not available, use a smaller default size. Only a single
# resolution is supported in this case.
DEFAULT_SIZE_NO_RANDR = "1600x1200"

SCRIPT_PATH = os.path.abspath(sys.argv[0])
SCRIPT_DIR = os.path.dirname(SCRIPT_PATH)

if (os.path.basename(sys.argv[0]) == 'linux_me2me_host.py'):
  # Needed for swarming/isolate tests.
  HOST_BINARY_PATH = os.path.join(SCRIPT_DIR,
                                  "../../../out/Release/remoting_me2me_host")
else:
  HOST_BINARY_PATH = os.path.join(SCRIPT_DIR, "chrome-remote-desktop-host")

USER_SESSION_PATH = os.path.join(SCRIPT_DIR, "user-session")

CHROME_REMOTING_GROUP_NAME = "chrome-remote-desktop"

HOME_DIR = os.environ["HOME"]
CONFIG_DIR = os.path.join(HOME_DIR, ".config/chrome-remote-desktop")
SESSION_FILE_PATH = os.path.join(HOME_DIR, ".chrome-remote-desktop-session")
SYSTEM_SESSION_FILE_PATH = "/etc/chrome-remote-desktop-session"

X_LOCK_FILE_TEMPLATE = "/tmp/.X%d-lock"
FIRST_X_DISPLAY_NUMBER = 20

# Amount of time to wait between relaunching processes.
SHORT_BACKOFF_TIME = 5
LONG_BACKOFF_TIME = 60

# How long a process must run in order not to be counted against the restart
# thresholds.
MINIMUM_PROCESS_LIFETIME = 60

# Thresholds for switching from fast- to slow-restart and for giving up
# trying to restart entirely.
SHORT_BACKOFF_THRESHOLD = 5
MAX_LAUNCH_FAILURES = SHORT_BACKOFF_THRESHOLD + 10

# Number of seconds to save session output to the log.
SESSION_OUTPUT_TIME_LIMIT_SECONDS = 300

# Host offline reason if the X server retry count is exceeded.
HOST_OFFLINE_REASON_X_SERVER_RETRIES_EXCEEDED = "X_SERVER_RETRIES_EXCEEDED"

# Host offline reason if the X session retry count is exceeded.
HOST_OFFLINE_REASON_SESSION_RETRIES_EXCEEDED = "SESSION_RETRIES_EXCEEDED"

# Host offline reason if the host retry count is exceeded. (Note: It may or may
# not be possible to send this, depending on why the host is failing.)
HOST_OFFLINE_REASON_HOST_RETRIES_EXCEEDED = "HOST_RETRIES_EXCEEDED"

# This is the file descriptor used to pass messages to the user_session binary
# during startup. It must be kept in sync with kMessageFd in
# remoting_user_session.cc.
USER_SESSION_MESSAGE_FD = 202

# This is the exit code used to signal to wrapper that it should restart instead
# of exiting. It must be kept in sync with kRelaunchExitCode in
# remoting_user_session.cc.
RELAUNCH_EXIT_CODE = 41

# This exit code is returned when a needed binary such as user-session or sg
# cannot be found.
COMMAND_NOT_FOUND_EXIT_CODE = 127

# This exit code is returned when a needed binary exists but cannot be executed.
COMMAND_NOT_EXECUTABLE_EXIT_CODE = 126

# Globals needed by the atexit cleanup() handler.
g_desktop = None
g_host_hash = hashlib.md5(socket.gethostname()).hexdigest()

def gen_xorg_config(sizes):
  return (
      # This causes X to load the default GLX module, even if a proprietary one
      # is installed in a different directory.
      'Section "Files"\n'
      '  ModulePath "/usr/lib/xorg/modules"\n'
      'EndSection\n'
      '\n'
      # Suppress device probing, which happens by default.
      'Section "ServerFlags"\n'
      '  Option "AutoAddDevices" "false"\n'
      '  Option "AutoEnableDevices" "false"\n'
      '  Option "DontVTSwitch" "true"\n'
      '  Option "PciForceNone" "true"\n'
      'EndSection\n'
      '\n'
      'Section "InputDevice"\n'
      # The host looks for this name to check whether it's running in a virtual
      # session
      '  Identifier "Chrome Remote Desktop Input"\n'
      # While the xorg.conf man page specifies that both of these options are
      # deprecated synonyms for `Option "Floating" "false"`, it turns out that
      # if both aren't specified, the Xorg server will automatically attempt to
      # add additional devices.
      '  Option "CoreKeyboard" "true"\n'
      '  Option "CorePointer" "true"\n'
      '  Driver "void"\n'
      'EndSection\n'
      '\n'
      'Section "Device"\n'
      '  Identifier "Chrome Remote Desktop Videocard"\n'
      '  Driver "dummy"\n'
      '  VideoRam {video_ram}\n'
      'EndSection\n'
      '\n'
      'Section "Monitor"\n'
      '  Identifier "Chrome Remote Desktop Monitor"\n'
      # The horizontal sync rate was calculated from the vertical refresh rate
      # and the modline template:
      # (33000 (vert total) * 0.1 Hz = 3.3 kHz)
      '  HorizSync   3.3\n' # kHz
      # The vertical refresh rate was chosen both to be low enough to have an
      # acceptable dot clock at high resolutions, and then bumped down a little
      # more so that in the unlikely event that a low refresh rate would break
      # something, it would break obviously.
      '  VertRefresh 0.1\n' # Hz
      '{modelines}'
      'EndSection\n'
      '\n'
      'Section "Screen"\n'
      '  Identifier "Chrome Remote Desktop Screen"\n'
      '  Device "Chrome Remote Desktop Videocard"\n'
      '  Monitor "Chrome Remote Desktop Monitor"\n'
      '  DefaultDepth 24\n'
      '  SubSection "Display"\n'
      '    Viewport 0 0\n'
      '    Depth 24\n'
      '    Modes {modes}\n'
      '  EndSubSection\n'
      'EndSection\n'
      '\n'
      'Section "ServerLayout"\n'
      '  Identifier   "Chrome Remote Desktop Layout"\n'
      '  Screen       "Chrome Remote Desktop Screen"\n'
      '  InputDevice  "Chrome Remote Desktop Input"\n'
      'EndSection\n'.format(
          # This Modeline template allows resolutions up to the dummy driver's
          # max supported resolution of 32767x32767 without additional
          # calculation while meeting the driver's dot clock requirements. Note
          # that VP8 (and thus the amount of video RAM chosen) only support a
          # maximum resolution of 16384x16384.
          # 32767x32767 should be possible if we switch fully to VP9 and
          # increase the video RAM to 4GiB.
          # The dot clock was calculated to match the VirtRefresh chosen above.
          # (33000 * 33000 * 0.1 Hz = 108.9 MHz)
          # Changes this line require matching changes to HorizSync and
          # VertRefresh.
          modelines="".join(
              '  Modeline "{0}x{1}" 108.9 {0} 32998 32999 33000 '
              '{1} 32998 32999 33000\n'.format(w, h) for w, h in sizes),
          modes=" ".join('"{0}x{1}"'.format(w, h) for w, h in sizes),
          video_ram=XORG_DUMMY_VIDEO_RAM))


def is_supported_platform():
  # Always assume that the system is supported if the config directory or
  # session file exist.
  if (os.path.isdir(CONFIG_DIR) or os.path.isfile(SESSION_FILE_PATH) or
      os.path.isfile(SYSTEM_SESSION_FILE_PATH)):
    return True

  # The host has been tested only on Ubuntu.
  distribution = platform.linux_distribution()
  return (distribution[0]).lower() == 'ubuntu'


def locate_xvfb_randr():
  """Returns a path to our RANDR-supporting Xvfb server, if it is found on the
  system. Otherwise returns None."""

  xvfb = "/usr/bin/Xvfb-randr"
  if os.path.exists(xvfb):
    return xvfb

  xvfb = os.path.join(SCRIPT_DIR, "Xvfb-randr")
  if os.path.exists(xvfb):
    return xvfb

  return None


class Config:
  def __init__(self, path):
    self.path = path
    self.data = {}
    self.changed = False

  def load(self):
    """Loads the config from file.

    Raises:
      IOError: Error reading data
      ValueError: Error parsing JSON
    """
    settings_file = open(self.path, 'r')
    self.data = json.load(settings_file)
    self.changed = False
    settings_file.close()

  def save(self):
    """Saves the config to file.

    Raises:
      IOError: Error writing data
      TypeError: Error serialising JSON
    """
    if not self.changed:
      return
    old_umask = os.umask(0o066)
    try:
      settings_file = open(self.path, 'w')
      settings_file.write(json.dumps(self.data, indent=2))
      settings_file.close()
      self.changed = False
    finally:
      os.umask(old_umask)

  def save_and_log_errors(self):
    """Calls self.save(), trapping and logging any errors."""
    try:
      self.save()
    except (IOError, TypeError) as e:
      logging.error("Failed to save config: " + str(e))

  def get(self, key):
    return self.data.get(key)

  def __getitem__(self, key):
    return self.data[key]

  def __setitem__(self, key, value):
    self.data[key] = value
    self.changed = True

  def clear(self):
    self.data = {}
    self.changed = True


class Authentication:
  """Manage authentication tokens for Chromoting/xmpp"""

  def __init__(self):
    # Note: Initial values are never used.
    self.login = None
    self.oauth_refresh_token = None

  def copy_from(self, config):
    """Loads the config and returns false if the config is invalid."""
    try:
      self.login = config["xmpp_login"]
      self.oauth_refresh_token = config["oauth_refresh_token"]
    except KeyError:
      return False
    return True

  def copy_to(self, config):
    config["xmpp_login"] = self.login
    config["oauth_refresh_token"] = self.oauth_refresh_token


class Host:
  """This manages the configuration for a host."""

  def __init__(self):
    # Note: Initial values are never used.
    self.host_id = None
    self.gcd_device_id = None
    self.host_name = None
    self.host_secret_hash = None
    self.private_key = None

  def copy_from(self, config):
    try:
      self.host_id = config.get("host_id")
      self.gcd_device_id = config.get("gcd_device_id")
      self.host_name = config["host_name"]
      self.host_secret_hash = config.get("host_secret_hash")
      self.private_key = config["private_key"]
    except KeyError:
      return False
    return bool(self.host_id or self.gcd_device_id)

  def copy_to(self, config):
    if self.host_id:
      config["host_id"] = self.host_id
    if self.gcd_device_id:
      config["gcd_device_id"] = self.gcd_device_id
    config["host_name"] = self.host_name
    config["host_secret_hash"] = self.host_secret_hash
    config["private_key"] = self.private_key


class SessionOutputFilterThread(threading.Thread):
  """Reads session log from a pipe and logs the output for amount of time
  defined by SESSION_OUTPUT_TIME_LIMIT_SECONDS."""

  def __init__(self, stream):
    threading.Thread.__init__(self)
    self.stream = stream
    self.daemon = True

  def run(self):
    started_time = time.time()
    is_logging = True
    while True:
      try:
        line = self.stream.readline();
      except IOError as e:
        print("IOError when reading session output: ", e)
        return

      if line == "":
        # EOF reached. Just stop the thread.
        return

      if not is_logging:
        continue

      if time.time() - started_time >= SESSION_OUTPUT_TIME_LIMIT_SECONDS:
        is_logging = False
        print("Suppressing rest of the session output.")
        sys.stdout.flush()
      else:
        print("Session output: %s" % line.strip("\n"))
        sys.stdout.flush()


class Desktop:
  """Manage a single virtual desktop"""

  def __init__(self, sizes):
    self.x_proc = None
    self.session_proc = None
    self.host_proc = None
    self.child_env = None
    self.sizes = sizes
    self.xorg_conf = None
    self.pulseaudio_pipe = None
    self.server_supports_exact_resize = False
    self.server_supports_randr = False
    self.randr_add_sizes = False
    self.host_ready = False
    self.ssh_auth_sockname = None
    global g_desktop
    assert(g_desktop is None)
    g_desktop = self

  @staticmethod
  def get_unused_display_number():
    """Return a candidate display number for which there is currently no
    X Server lock file"""
    display = FIRST_X_DISPLAY_NUMBER
    while os.path.exists(X_LOCK_FILE_TEMPLATE % display):
      display += 1
    return display

  def _init_child_env(self):
    self.child_env = dict(os.environ)

    # Ensure that the software-rendering GL drivers are loaded by the desktop
    # session, instead of any hardware GL drivers installed on the system.
    library_path = (
        "/usr/lib/mesa-diverted/%(arch)s-linux-gnu:"
        "/usr/lib/%(arch)s-linux-gnu/mesa:"
        "/usr/lib/%(arch)s-linux-gnu/dri:"
        "/usr/lib/%(arch)s-linux-gnu/gallium-pipe" %
        { "arch": platform.machine() })

    if "LD_LIBRARY_PATH" in self.child_env:
      library_path += ":" + self.child_env["LD_LIBRARY_PATH"]

    self.child_env["LD_LIBRARY_PATH"] = library_path

  def _setup_pulseaudio(self):
    self.pulseaudio_pipe = None

    # pulseaudio uses UNIX sockets for communication. Length of UNIX socket
    # name is limited to 108 characters, so audio will not work properly if
    # the path is too long. To workaround this problem we use only first 10
    # symbols of the host hash.
    pulse_path = os.path.join(CONFIG_DIR,
                              "pulseaudio#%s" % g_host_hash[0:10])
    if len(pulse_path) + len("/native") >= 108:
      logging.error("Audio will not be enabled because pulseaudio UNIX " +
                    "socket path is too long.")
      return False

    sink_name = "chrome_remote_desktop_session"
    pipe_name = os.path.join(pulse_path, "fifo_output")

    try:
      if not os.path.exists(pulse_path):
        os.mkdir(pulse_path)
    except IOError as e:
      logging.error("Failed to create pulseaudio pipe: " + str(e))
      return False

    try:
      pulse_config = open(os.path.join(pulse_path, "daemon.conf"), "w")
      pulse_config.write("default-sample-format = s16le\n")
      pulse_config.write("default-sample-rate = 48000\n")
      pulse_config.write("default-sample-channels = 2\n")
      pulse_config.close()

      pulse_script = open(os.path.join(pulse_path, "default.pa"), "w")
      pulse_script.write("load-module module-native-protocol-unix\n")
      pulse_script.write(
          ("load-module module-pipe-sink sink_name=%s file=\"%s\" " +
           "rate=48000 channels=2 format=s16le\n") %
          (sink_name, pipe_name))
      pulse_script.close()
    except IOError as e:
      logging.error("Failed to write pulseaudio config: " + str(e))
      return False

    self.child_env["PULSE_CONFIG_PATH"] = pulse_path
    self.child_env["PULSE_RUNTIME_PATH"] = pulse_path
    self.child_env["PULSE_STATE_PATH"] = pulse_path
    self.child_env["PULSE_SINK"] = sink_name
    self.pulseaudio_pipe = pipe_name

    return True

  def _setup_gnubby(self):
    self.ssh_auth_sockname = ("/tmp/chromoting.%s.ssh_auth_sock" %
                              os.environ["USER"])

  # Returns child environment not containing TMPDIR.
  # Certain values of TMPDIR can break the X server (crbug.com/672684), so we
  # want to make sure it isn't set in the envirionment we use to start the
  # server.
  def _x_env(self):
    if "TMPDIR" not in self.child_env:
      return self.child_env
    else:
      env_copy = dict(self.child_env)
      del env_copy["TMPDIR"]
      return env_copy

  def check_x_responding(self):
    """Checks if the X server is responding to connections."""
    with open(os.devnull, "r+") as devnull:
      exit_code = subprocess.call("xdpyinfo", env=self.child_env,
                                  stdout=devnull)
    return exit_code == 0

  def _wait_for_x(self):
    # Wait for X to be active.
    for _test in range(20):
      if self.check_x_responding():
        logging.info("X server is active.")
        return
      time.sleep(0.5)

    raise Exception("Could not connect to X server.")

  def _launch_xvfb(self, display, x_auth_file, extra_x_args):
    max_width = max([width for width, height in self.sizes])
    max_height = max([height for width, height in self.sizes])

    xvfb = locate_xvfb_randr()
    if not xvfb:
      xvfb = "Xvfb"

    logging.info("Starting %s on display :%d" % (xvfb, display))
    screen_option = "%dx%dx24" % (max_width, max_height)
    self.x_proc = subprocess.Popen(
        [xvfb, ":%d" % display,
         "-auth", x_auth_file,
         "-nolisten", "tcp",
         "-noreset",
         "-screen", "0", screen_option
        ] + extra_x_args, env=self._x_env())
    if not self.x_proc.pid:
      raise Exception("Could not start Xvfb.")

    self._wait_for_x()

    with open(os.devnull, "r+") as devnull:
      exit_code = subprocess.call("xrandr", env=self.child_env,
                                  stdout=devnull, stderr=devnull)
    if exit_code == 0:
      # RandR is supported
      self.server_supports_exact_resize = True
      self.server_supports_randr = True
      self.randr_add_sizes = True

  def _launch_xorg(self, display, x_auth_file, extra_x_args):
    with tempfile.NamedTemporaryFile(
        prefix="chrome_remote_desktop_",
        suffix=".conf", delete=False) as config_file:
      config_file.write(gen_xorg_config(self.sizes))

    # We can't support exact resize with the current Xorg dummy driver.
    self.server_supports_exact_resize = False
    # But dummy does support RandR 1.0.
    self.server_supports_randr = True
    self.xorg_conf = config_file.name

    logging.info("Starting Xorg on display :%d" % display)
    # We use the child environment so the Xorg server picks up the Mesa libGL
    # instead of any proprietary versions that may be installed, thanks to
    # LD_LIBRARY_PATH.
    # Note: This prevents any environment variable the user has set from
    # affecting the Xorg server.
    self.x_proc = subprocess.Popen(
        ["Xorg", ":%d" % display,
         "-auth", x_auth_file,
         "-nolisten", "tcp",
         "-noreset",
         # Disable logging to a file and instead bump up the stderr verbosity
         # so the equivalent information gets logged in our main log file.
         "-logfile", "/dev/null",
         "-verbose", "3",
         "-config", config_file.name
        ] + extra_x_args, env=self._x_env())
    if not self.x_proc.pid:
      raise Exception("Could not start Xorg.")
    self._wait_for_x()

  def _launch_x_server(self, extra_x_args):
    x_auth_file = os.path.expanduser("~/.Xauthority")
    self.child_env["XAUTHORITY"] = x_auth_file
    display = self.get_unused_display_number()

    # Run "xauth add" with |child_env| so that it modifies the same XAUTHORITY
    # file which will be used for the X session.
    exit_code = subprocess.call("xauth add :%d . `mcookie`" % display,
                                env=self.child_env, shell=True)
    if exit_code != 0:
      raise Exception("xauth failed with code %d" % exit_code)

    # Disable the Composite extension iff the X session is the default
    # Unity-2D, since it uses Metacity which fails to generate DAMAGE
    # notifications correctly. See crbug.com/166468.
    x_session = choose_x_session()
    if (len(x_session) == 2 and
        x_session[1] == "/usr/bin/gnome-session --session=ubuntu-2d"):
      extra_x_args.extend(["-extension", "Composite"])

    self.child_env["DISPLAY"] = ":%d" % display
    self.child_env["CHROME_REMOTE_DESKTOP_SESSION"] = "1"

    # Use a separate profile for any instances of Chrome that are started in
    # the virtual session. Chrome doesn't support sharing a profile between
    # multiple DISPLAYs, but Chrome Sync allows for a reasonable compromise.
    chrome_profile = os.path.join(CONFIG_DIR, "chrome-profile")
    self.child_env["CHROME_USER_DATA_DIR"] = chrome_profile

    # Set SSH_AUTH_SOCK to the file name to listen on.
    if self.ssh_auth_sockname:
      self.child_env["SSH_AUTH_SOCK"] = self.ssh_auth_sockname

    if USE_XORG_ENV_VAR in os.environ:
      self._launch_xorg(display, x_auth_file, extra_x_args)
    else:
      self._launch_xvfb(display, x_auth_file, extra_x_args)

    # The remoting host expects the server to use "evdev" keycodes, but Xvfb
    # starts configured to use the "base" ruleset, resulting in XKB configuring
    # for "xfree86" keycodes, and screwing up some keys. See crbug.com/119013.
    # Reconfigure the X server to use "evdev" keymap rules.  The X server must
    # be started with -noreset otherwise it'll reset as soon as the command
    # completes, since there are no other X clients running yet.
    exit_code = subprocess.call(["setxkbmap", "-rules", "evdev"],
                                env=self.child_env)
    if exit_code != 0:
      logging.error("Failed to set XKB to 'evdev'")

    if not self.server_supports_randr:
      return

    with open(os.devnull, "r+") as devnull:
      # Register the screen sizes with RandR, if needed.  Errors here are
      # non-fatal; the X server will continue to run with the dimensions from
      # the "-screen" option.
      if self.randr_add_sizes:
        for width, height in self.sizes:
          label = "%dx%d" % (width, height)
          args = ["xrandr", "--newmode", label, "0", str(width), "0", "0", "0",
                  str(height), "0", "0", "0"]
          subprocess.call(args, env=self.child_env, stdout=devnull,
                          stderr=devnull)
          args = ["xrandr", "--addmode", "screen", label]
          subprocess.call(args, env=self.child_env, stdout=devnull,
                          stderr=devnull)

      # Set the initial mode to the first size specified, otherwise the X server
      # would default to (max_width, max_height), which might not even be in the
      # list.
      initial_size = self.sizes[0]
      label = "%dx%d" % initial_size
      args = ["xrandr", "-s", label]
      subprocess.call(args, env=self.child_env, stdout=devnull, stderr=devnull)

      # Set the physical size of the display so that the initial mode is running
      # at approximately 96 DPI, since some desktops require the DPI to be set
      # to something realistic.
      args = ["xrandr", "--dpi", "96"]
      subprocess.call(args, env=self.child_env, stdout=devnull, stderr=devnull)

      # Monitor for any automatic resolution changes from the desktop
      # environment.
      args = [SCRIPT_PATH, "--watch-resolution", str(initial_size[0]),
              str(initial_size[1])]

      # It is not necessary to wait() on the process here, as this script's main
      # loop will reap the exit-codes of all child processes.
      subprocess.Popen(args, env=self.child_env, stdout=devnull, stderr=devnull)

  def _launch_x_session(self):
    # Start desktop session.
    # The /dev/null input redirection is necessary to prevent the X session
    # reading from stdin.  If this code runs as a shell background job in a
    # terminal, any reading from stdin causes the job to be suspended.
    # Daemonization would solve this problem by separating the process from the
    # controlling terminal.
    xsession_command = choose_x_session()
    if xsession_command is None:
      raise Exception("Unable to choose suitable X session command.")

    logging.info("Launching X session: %s" % xsession_command)
    self.session_proc = subprocess.Popen(xsession_command,
                                         stdin=open(os.devnull, "r"),
                                         stdout=subprocess.PIPE,
                                         stderr=subprocess.STDOUT,
                                         cwd=HOME_DIR,
                                         env=self.child_env)

    output_filter_thread = SessionOutputFilterThread(self.session_proc.stdout)
    output_filter_thread.start()

    if not self.session_proc.pid:
      raise Exception("Could not start X session")

  def launch_session(self, x_args):
    self._init_child_env()
    self._setup_pulseaudio()
    self._setup_gnubby()
    self._launch_x_server(x_args)
    self._launch_x_session()

  def launch_host(self, host_config, extra_start_host_args):
    # Start remoting host
    args = [HOST_BINARY_PATH, "--host-config=-"]
    if self.pulseaudio_pipe:
      args.append("--audio-pipe-name=%s" % self.pulseaudio_pipe)
    if self.server_supports_exact_resize:
      args.append("--server-supports-exact-resize")
    if self.ssh_auth_sockname:
      args.append("--ssh-auth-sockname=%s" % self.ssh_auth_sockname)

    args.extend(extra_start_host_args)

    # Have the host process use SIGUSR1 to signal a successful start.
    def sigusr1_handler(signum, frame):
      _ = signum, frame
      logging.info("Host ready to receive connections.")
      self.host_ready = True
      ParentProcessLogger.release_parent_if_connected(True)

    signal.signal(signal.SIGUSR1, sigusr1_handler)
    args.append("--signal-parent")

    logging.info(args)
    self.host_proc = subprocess.Popen(args, env=self.child_env,
                                      stdin=subprocess.PIPE)
    if not self.host_proc.pid:
      raise Exception("Could not start Chrome Remote Desktop host")

    try:
      self.host_proc.stdin.write(json.dumps(host_config.data).encode('UTF-8'))
      self.host_proc.stdin.flush()
    except IOError as e:
      # This can occur in rare situations, for example, if the machine is
      # heavily loaded and the host process dies quickly (maybe if the X
      # connection failed), the host process might be gone before this code
      # writes to the host's stdin. Catch and log the exception, allowing
      # the process to be retried instead of exiting the script completely.
      logging.error("Failed writing to host's stdin: " + str(e))
    finally:
      self.host_proc.stdin.close()

  def shutdown_all_procs(self):
    """Send SIGTERM to all procs and wait for them to exit. Will fallback to
    SIGKILL if a process doesn't exit within 10 seconds.
    """
    for proc, name in [(self.x_proc, "X server"),
                       (self.session_proc, "session"),
                       (self.host_proc, "host")]:
      if proc is not None:
        logging.info("Terminating " + name)
        try:
          psutil_proc = psutil.Process(proc.pid)
          psutil_proc.terminate()

          # Use a short timeout, to avoid delaying service shutdown if the
          # process refuses to die for some reason.
          psutil_proc.wait(timeout=10)
        except psutil.TimeoutExpired:
          logging.error("Timed out - sending SIGKILL")
          psutil_proc.kill()
        except psutil.Error:
          logging.error("Error terminating process")
    self.x_proc = None
    self.session_proc = None
    self.host_proc = None

  def report_offline_reason(self, host_config, reason):
    """Attempt to report the specified offline reason to the registry. This
    is best effort, and requires a valid host config.
    """
    logging.info("Attempting to report offline reason: " + reason)
    args = [HOST_BINARY_PATH, "--host-config=-",
            "--report-offline-reason=" + reason]
    proc = subprocess.Popen(args, env=self.child_env, stdin=subprocess.PIPE)
    proc.communicate(json.dumps(host_config.data).encode('UTF-8'))


def parse_config_arg(args):
  """Parses only the --config option from a given command-line.

  Returns:
    A two-tuple. The first element is the value of the --config option (or None
    if it is not specified), and the second is a list containing the remaining
    arguments
  """

  # By default, argparse will exit the program on error. We would like it not to
  # do that.
  class ArgumentParserError(Exception):
    pass
  class ThrowingArgumentParser(argparse.ArgumentParser):
    def error(self, message):
      raise ArgumentParserError(message)

  parser = ThrowingArgumentParser()
  parser.add_argument("--config", nargs='?', action="store")

  try:
    result = parser.parse_known_args(args)
    return (result[0].config, result[1])
  except ArgumentParserError:
    return (None, list(args))


def get_daemon_proc(config_file, require_child_process=False):
  """Checks if there is already an instance of this script running against
  |config_file|, and returns a psutil.Process instance for it. If
  |require_child_process| is true, only check for an instance with the
  --child-process flag specified.

  If a process is found without --config in the command line, get_daemon_proc
  will fall back to the old behavior of checking whether the script path matches
  the current script. This is to facilitate upgrades from previous versions.

  Returns:
    A Process instance for the existing daemon process, or None if the daemon
    is not running.
  """

  # Note: When making changes to how instances are detected, it is imperative
  # that this function retains the ability to find older versions. Otherwise,
  # upgrades can leave the user with two running sessions, with confusing
  # results.

  uid = os.getuid()
  this_pid = os.getpid()

  # This function should return the process with the --child-process flag if it
  # exists. If there's only a process without, it might be a legacy process.
  non_child_process = None

  # Support new & old psutil API. This is the right way to check, according to
  # http://grodola.blogspot.com/2014/01/psutil-20-porting.html
  if psutil.version_info >= (2, 0):
    psget = lambda x: x()
  else:
    psget = lambda x: x

  for process in psutil.process_iter():
    # Skip any processes that raise an exception, as processes may terminate
    # during iteration over the list.
    try:
      # Skip other users' processes.
      if psget(process.uids).real != uid:
        continue

      # Skip the process for this instance.
      if process.pid == this_pid:
        continue

      # |cmdline| will be [python-interpreter, script-file, other arguments...]
      cmdline = psget(process.cmdline)
      if len(cmdline) < 2:
        continue
      if (os.path.basename(cmdline[0]).startswith('python') and
          os.path.basename(cmdline[1]) == os.path.basename(sys.argv[0]) and
          "--start" in cmdline):
        process_config = parse_config_arg(cmdline[2:])[0]

        # Fall back to old behavior if there is no --config argument
        # TODO(rkjnsn): Consider removing this fallback once sufficient time
        # has passed.
        if process_config == config_file or (process_config is None and
                                             cmdline[1] == sys.argv[0]):
          if "--child-process" in cmdline:
            return process
          else:
            non_child_process = process

    except (psutil.NoSuchProcess, psutil.AccessDenied):
      continue

  return non_child_process if not require_child_process else None


def choose_x_session():
  """Chooses the most appropriate X session command for this system.

  Returns:
    A string containing the command to run, or a list of strings containing
    the executable program and its arguments, which is suitable for passing as
    the first parameter of subprocess.Popen().  If a suitable session cannot
    be found, returns None.
  """
  XSESSION_FILES = [
    SESSION_FILE_PATH,
    SYSTEM_SESSION_FILE_PATH ]
  for startup_file in XSESSION_FILES:
    startup_file = os.path.expanduser(startup_file)
    if os.path.exists(startup_file):
      if os.access(startup_file, os.X_OK):
        # "/bin/sh -c" is smart about how to execute the session script and
        # works in cases where plain exec() fails (for example, if the file is
        # marked executable, but is a plain script with no shebang line).
        return ["/bin/sh", "-c", pipes.quote(startup_file)]
      else:
        # If this is a system-wide session script, it should be run using the
        # system shell, ignoring any login shell that might be set for the
        # current user.
        return ["/bin/sh", startup_file]

  # Choose a session wrapper script to run the session. On some systems,
  # /etc/X11/Xsession fails to load the user's .profile, so look for an
  # alternative wrapper that is more likely to match the script that the
  # system actually uses for console desktop sessions.
  SESSION_WRAPPERS = [
    "/usr/sbin/lightdm-session",
    "/etc/gdm/Xsession",
    "/etc/X11/Xsession" ]
  for session_wrapper in SESSION_WRAPPERS:
    if os.path.exists(session_wrapper):
      if os.path.exists("/usr/bin/unity-2d-panel"):
        # On Ubuntu 12.04, the default session relies on 3D-accelerated
        # hardware. Trying to run this with a virtual X display produces
        # weird results on some systems (for example, upside-down and
        # corrupt displays).  So if the ubuntu-2d session is available,
        # choose it explicitly.
        return [session_wrapper, "/usr/bin/gnome-session --session=ubuntu-2d"]
      else:
        # Use the session wrapper by itself, and let the system choose a
        # session.
        return [session_wrapper]
  return None


class ParentProcessLogger(object):
  """Redirects logs to the parent process, until the host is ready or quits.

  This class creates a pipe to allow logging from the daemon process to be
  copied to the parent process. The daemon process adds a log-handler that
  directs logging output to the pipe. The parent process reads from this pipe
  and writes the content to stderr. When the pipe is no longer needed (for
  example, the host signals successful launch or permanent failure), the daemon
  removes the log-handler and closes the pipe, causing the the parent process
  to reach end-of-file while reading the pipe and exit.

  The file descriptor for the pipe to the parent process should be passed to
  the constructor. The (grand-)child process should call start_logging() when
  it starts, and then use logging.* to issue log statements, as usual. When the
  child has either succesfully started the host or terminated, it must call
  release_parent() to allow the parent to exit.
  """

  __instance = None

  def __init__(self, write_fd):
    """Constructor.

    Constructs the singleton instance of ParentProcessLogger. This should be
    called at most once.

    write_fd: The write end of the pipe created by the parent process. If
              write_fd is not a valid file descriptor, the constructor will
              throw either IOError or OSError.
    """
    # Ensure write_pipe is closed on exec, otherwise it will be kept open by
    # child processes (X, host), preventing the read pipe from EOF'ing.
    old_flags = fcntl.fcntl(write_fd, fcntl.F_GETFD)
    fcntl.fcntl(write_fd, fcntl.F_SETFD, old_flags | fcntl.FD_CLOEXEC)
    self._write_file = os.fdopen(write_fd, 'w')
    self._logging_handler = None
    ParentProcessLogger.__instance = self

  def _start_logging(self):
    """Installs a logging handler that sends log entries to a pipe, prefixed
    with the string 'MSG:'. This allows them to be distinguished by the parent
    process from commands sent over the same pipe.

    Must be called by the child process.
    """
    self._logging_handler = logging.StreamHandler(self._write_file)
    self._logging_handler.setFormatter(logging.Formatter(fmt='MSG:%(message)s'))
    logging.getLogger().addHandler(self._logging_handler)

  def _release_parent(self, success):
    """Uninstalls logging handler and closes the pipe, releasing the parent.

    Must be called by the child process.

    success: If true, write a "host ready" message to the parent process before
             closing the pipe.
    """
    if self._logging_handler:
      logging.getLogger().removeHandler(self._logging_handler)
      self._logging_handler = None
    if not self._write_file.closed:
      if success:
        try:
          self._write_file.write("READY\n")
          self._write_file.flush()
        except IOError:
          # A "broken pipe" IOError can happen if the receiving process
          # (remoting_user_session) has exited (probably due to timeout waiting
          # for the host to start).
          # Trapping the error here means the host can continue running.
          logging.info("Caught IOError writing READY message.")
      self._write_file.close()

  @staticmethod
  def try_start_logging(write_fd):
    """Attempt to initialize ParentProcessLogger and start forwarding log
    messages.

    Returns False if the file descriptor was invalid (safe to ignore).
    """
    try:
      ParentProcessLogger(USER_SESSION_MESSAGE_FD)._start_logging()
      return True
    except (IOError, OSError):
      # One of these will be thrown if the file descriptor is invalid, such as
      # if the the fd got closed by the login shell. In that case, just continue
      # without sending log messages.
      return False

  @staticmethod
  def release_parent_if_connected(success):
    """If ParentProcessLogger is active, stop logging and release the parent.

    success: If true, signal to the parent that the script was successful.
    """
    instance = ParentProcessLogger.__instance
    if instance is not None:
      instance._release_parent(success)


def run_command_with_group(command, group):
  """Run a command with a different primary group."""

  # This is implemented using sg, which is an odd character and will try to
  # prompt for a password if it can't verify the user is a member of the given
  # group, along with in a few other corner cases. (It will prompt in the
  # non-member case even if the group doesn't have a password set.)
  #
  # To prevent sg from prompting the user for a password that doesn't exist,
  # redirect stdin and detach sg from the TTY. It will still print something
  # like "Password: crypt: Invalid argument", so redirect stdout and stderr, as
  # well. Finally, have the shell unredirect them when executing user-session.
  #
  # It is also desirable to have some way to tell whether any errors are
  # from sg or the command, which is done using a pipe.

  def pre_exec(read_fd, write_fd):
    os.close(read_fd)

    # /bin/sh may be dash, which only allows redirecting file descriptors 0-9,
    # the minimum required by POSIX. Since there may be files open elsewhere,
    # move the relevant file descriptors to specific numbers under that limit.
    # Because this runs in the child process, it doesn't matter if existing file
    # descriptors are closed in the process. After, stdio will be redirected to
    # /dev/null, write_fd will be moved to 6, and the old stdio will be moved
    # to 7, 8, and 9.
    if (write_fd != 6):
      os.dup2(write_fd, 6)
      os.close(write_fd)
    os.dup2(0, 7)
    os.dup2(1, 8)
    os.dup2(2, 9)
    devnull = os.open(os.devnull, os.O_RDWR)
    os.dup2(devnull, 0)
    os.dup2(devnull, 1)
    os.dup2(devnull, 2)
    os.close(devnull)

    # os.setsid will detach subprocess from the TTY
    os.setsid()

  # Pipe to check whether sg successfully ran our command.
  read_fd, write_fd = os.pipe()
  try:
    # sg invokes the provided argument using /bin/sh. In that shell, first write
    # "success\n" to the pipe, which is checked later to determine whether sg
    # itself succeeded, and then restore stdio, close the extra file
    # descriptors, and exec the provided command.
    process = subprocess.Popen(
        ["sg", group,
         "echo success >&6; exec {command} "
           # Restore original stdio
           "0<&7 1>&8 2>&9 "
           # Close no-longer-needed file descriptors
           "6>&- 7<&- 8>&- 9>&-"
           .format(command=" ".join(map(pipes.quote, command)))],
        preexec_fn=lambda: pre_exec(read_fd, write_fd))
    result = process.wait()
  except OSError as e:
    logging.error("Failed to execute sg: {}".format(e.strerror))
    if e.errno == errno.ENOENT:
      result = COMMAND_NOT_FOUND_EXIT_CODE
    else:
      result = COMMAND_NOT_EXECUTABLE_EXIT_CODE
    # Skip pipe check, since sg was never executed.
    os.close(read_fd)
    return result
  except KeyboardInterrupt:
    # Because sg is in its own session, it won't have gotten the interrupt.
    try:
      os.killpg(os.getpgid(process.pid), signal.SIGINT)
      result = process.wait()
    except OSError:
      logging.warning("Command may still be running")
      result = 1
  finally:
    os.close(write_fd)

  with os.fdopen(read_fd) as read_file:
    contents = read_file.read()
  if contents != "success\n":
    # No success message means sg didn't execute the command. (Maybe the user
    # is not a member of the group?)
    logging.error("Failed to access {} group. Is the user a member?"
                  .format(group))
    result = COMMAND_NOT_EXECUTABLE_EXIT_CODE

  return result


def start_via_user_session(foreground):
  # We need to invoke user-session
  command = [USER_SESSION_PATH, "start"]
  if foreground:
    command += ["--foreground"]
  command += ["--"] + sys.argv[1:]
  try:
    process = subprocess.Popen(command)
    result = process.wait()
  except OSError as e:
    if e.errno == errno.EACCES:
      # User may have just been added to the CRD group, in which case they
      # won't be able to execute user-session directly until they log out and
      # back in. In the mean time, we can try to switch to the CRD group and
      # execute user-session.
      result = run_command_with_group(command, CHROME_REMOTING_GROUP_NAME)
    else:
      logging.error("Could not execute {}: {}"
                    .format(USER_SESSION_PATH, e.strerror))
      if e.errno == errno.ENOENT:
        result = COMMAND_NOT_FOUND_EXIT_CODE
      else:
        result = COMMAND_NOT_EXECUTABLE_EXIT_CODE
  except KeyboardInterrupt:
    # Child will have also gotten the interrupt. Wait for it to exit.
    result = process.wait()

  return result


def cleanup():
  logging.info("Cleanup.")

  global g_desktop
  if g_desktop is not None:
    g_desktop.shutdown_all_procs()
    if g_desktop.xorg_conf is not None:
      os.remove(g_desktop.xorg_conf)

  g_desktop = None
  ParentProcessLogger.release_parent_if_connected(False)

class SignalHandler:
  """Reload the config file on SIGHUP. Since we pass the configuration to the
  host processes via stdin, they can't reload it, so terminate them. They will
  be relaunched automatically with the new config."""

  def __init__(self, host_config):
    self.host_config = host_config

  def __call__(self, signum, _stackframe):
    if signum == signal.SIGHUP:
      logging.info("SIGHUP caught, restarting host.")
      try:
        self.host_config.load()
      except (IOError, ValueError) as e:
        logging.error("Failed to load config: " + str(e))
      if g_desktop is not None and g_desktop.host_proc:
        g_desktop.host_proc.send_signal(signal.SIGTERM)
    else:
      # Exit cleanly so the atexit handler, cleanup(), gets called.
      raise SystemExit


class RelaunchInhibitor:
  """Helper class for inhibiting launch of a child process before a timeout has
  elapsed.

  A managed process can be in one of these states:
    running, not inhibited (running == True)
    stopped and inhibited (running == False and is_inhibited() == True)
    stopped but not inhibited (running == False and is_inhibited() == False)

  Attributes:
    label: Name of the tracked process. Only used for logging.
    running: Whether the process is currently running.
    earliest_relaunch_time: Time before which the process should not be
      relaunched, or 0 if there is no limit.
    failures: The number of times that the process ran for less than a
      specified timeout, and had to be inhibited.  This count is reset to 0
      whenever the process has run for longer than the timeout.
  """

  def __init__(self, label):
    self.label = label
    self.running = False
    self.earliest_relaunch_time = 0
    self.earliest_successful_termination = 0
    self.failures = 0

  def is_inhibited(self):
    return (not self.running) and (time.time() < self.earliest_relaunch_time)

  def record_started(self, minimum_lifetime, relaunch_delay):
    """Record that the process was launched, and set the inhibit time to
    |timeout| seconds in the future."""
    self.earliest_relaunch_time = time.time() + relaunch_delay
    self.earliest_successful_termination = time.time() + minimum_lifetime
    self.running = True

  def record_stopped(self, expected):
    """Record that the process was stopped, and adjust the failure count
    depending on whether the process ran long enough. If the process was
    intentionally stopped (expected is True), the failure count will not be
    incremented."""
    self.running = False
    if time.time() >= self.earliest_successful_termination:
      self.failures = 0
    elif not expected:
      self.failures += 1
    logging.info("Failure count for '%s' is now %d", self.label, self.failures)


def relaunch_self():
  """Relaunches the session to pick up any changes to the session logic in case
  Chrome Remote Desktop has been upgraded. We return a special exit code to
  inform user-session that it should relaunch.
  """

  # cleanup run via atexit
  sys.exit(RELAUNCH_EXIT_CODE)


def waitpid_with_timeout(pid, deadline):
  """Wrapper around os.waitpid() which waits until either a child process dies
  or the deadline elapses.

  Args:
    pid: Process ID to wait for, or -1 to wait for any child process.
    deadline: Waiting stops when time.time() exceeds this value.

  Returns:
    (pid, status): Same as for os.waitpid(), except that |pid| is 0 if no child
    changed state within the timeout.

  Raises:
    Same as for os.waitpid().
  """
  while time.time() < deadline:
    pid, status = os.waitpid(pid, os.WNOHANG)
    if pid != 0:
      return (pid, status)
    time.sleep(1)
  return (0, 0)


def waitpid_handle_exceptions(pid, deadline):
  """Wrapper around os.waitpid()/waitpid_with_timeout(), which waits until
  either a child process exits or the deadline elapses, and retries if certain
  exceptions occur.

  Args:
    pid: Process ID to wait for, or -1 to wait for any child process.
    deadline: If non-zero, waiting stops when time.time() exceeds this value.
      If zero, waiting stops when a child process exits.

  Returns:
    (pid, status): Same as for waitpid_with_timeout(). |pid| is non-zero if and
    only if a child exited during the wait.

  Raises:
    Same as for os.waitpid(), except:
      OSError with errno==EINTR causes the wait to be retried (this can happen,
      for example, if this parent process receives SIGHUP).
      OSError with errno==ECHILD means there are no child processes, and so
      this function sleeps until |deadline|. If |deadline| is zero, this is an
      error and the OSError exception is raised in this case.
  """
  while True:
    try:
      if deadline == 0:
        pid_result, status = os.waitpid(pid, 0)
      else:
        pid_result, status = waitpid_with_timeout(pid, deadline)
      return (pid_result, status)
    except OSError as e:
      if e.errno == errno.EINTR:
        continue
      elif e.errno == errno.ECHILD:
        now = time.time()
        if deadline == 0:
          # No time-limit and no child processes. This is treated as an error
          # (see docstring).
          raise
        elif deadline > now:
          time.sleep(deadline - now)
        return (0, 0)
      else:
        # Anything else is an unexpected error.
        raise


def watch_for_resolution_changes(initial_size):
  """Watches for any resolution-changes which set the maximum screen resolution,
  and resets the initial size if this happens.

  The Ubuntu desktop has a component (the 'xrandr' plugin of
  unity-settings-daemon) which often changes the screen resolution to the
  first listed mode. This is the built-in mode for the maximum screen size,
  which can trigger excessive CPU usage in some situations. So this is a hack
  which waits for any such events, and undoes the change if it occurs.

  Sometimes, the user might legitimately want to use the maximum available
  resolution, so this monitoring is limited to a short time-period.
  """
  for _ in range(30):
    time.sleep(1)

    xrandr_output = subprocess.Popen(["xrandr"],
                                     stdout=subprocess.PIPE).communicate()[0]
    matches = re.search(r'current (\d+) x (\d+), maximum (\d+) x (\d+)',
                        xrandr_output)

    # No need to handle ValueError. If xrandr fails to give valid output,
    # there's no point in continuing to monitor.
    current_size = (int(matches.group(1)), int(matches.group(2)))
    maximum_size = (int(matches.group(3)), int(matches.group(4)))

    if current_size != initial_size:
      # Resolution change detected.
      if current_size == maximum_size:
        # This was probably an automated change from unity-settings-daemon, so
        # undo it.
        label = "%dx%d" % initial_size
        args = ["xrandr", "-s", label]
        subprocess.call(args)
        args = ["xrandr", "--dpi", "96"]
        subprocess.call(args)

      # Stop monitoring after any change was detected.
      break


def main():
  EPILOG = """This script is not intended for use by end-users.  To configure
Chrome Remote Desktop, please install the app from the Chrome
Web Store: https://chrome.google.com/remotedesktop"""
  parser = argparse.ArgumentParser(
      usage="Usage: %(prog)s [options] [ -- [ X server options ] ]",
      epilog=EPILOG)
  parser.add_argument("-s", "--size", dest="size", action="append",
                      help="Dimensions of virtual desktop. This can be "
                      "specified multiple times to make multiple screen "
                      "resolutions available (if the X server supports this).")
  parser.add_argument("-f", "--foreground", dest="foreground", default=False,
                      action="store_true",
                      help="Don't run as a background daemon.")
  parser.add_argument("--start", dest="start", default=False,
                      action="store_true",
                      help="Start the host.")
  parser.add_argument("-k", "--stop", dest="stop", default=False,
                      action="store_true",
                      help="Stop the daemon currently running.")
  parser.add_argument("--get-status", dest="get_status", default=False,
                      action="store_true",
                      help="Prints host status")
  parser.add_argument("--check-running", dest="check_running",
                      default=False, action="store_true",
                      help="Return 0 if the daemon is running, or 1 otherwise.")
  parser.add_argument("--config", dest="config", action="store",
                      help="Use the specified configuration file.")
  parser.add_argument("--reload", dest="reload", default=False,
                      action="store_true",
                      help="Signal currently running host to reload the "
                      "config.")
  parser.add_argument("--add-user", dest="add_user", default=False,
                      action="store_true",
                      help="Add current user to the chrome-remote-desktop "
                      "group.")
  parser.add_argument("--add-user-as-root", dest="add_user_as_root",
                      action="store", metavar="USER",
                      help="Adds the specified user to the "
                      "chrome-remote-desktop group (must be run as root).")
  # The script is being run as a child process under the user-session binary.
  # Don't daemonize and use the inherited environment.
  parser.add_argument("--child-process", dest="child_process", default=False,
                      action="store_true",
                      help=argparse.SUPPRESS)
  parser.add_argument("--watch-resolution", dest="watch_resolution",
                      type=int, nargs=2, default=False, action="store",
                      help=argparse.SUPPRESS)
  parser.add_argument(dest="args", nargs="*", help=argparse.SUPPRESS)
  options = parser.parse_args()

  # Determine the filename of the host configuration.
  if options.config:
    config_file = options.config
  else:
    config_file = os.path.join(CONFIG_DIR, "host#%s.json" % g_host_hash)
  config_file = os.path.realpath(config_file)

  # Check for a modal command-line option (start, stop, etc.)
  if options.get_status:
    proc = get_daemon_proc(config_file)
    if proc is not None:
      print("STARTED")
    elif is_supported_platform():
      print("STOPPED")
    else:
      print("NOT_IMPLEMENTED")
    return 0

  # TODO(sergeyu): Remove --check-running once NPAPI plugin and NM host are
  # updated to always use get-status flag instead.
  if options.check_running:
    proc = get_daemon_proc(config_file)
    return 1 if proc is None else 0

  if options.stop:
    proc = get_daemon_proc(config_file)
    if proc is None:
      print("The daemon is not currently running")
    else:
      print("Killing process %s" % proc.pid)
      proc.terminate()
      try:
        proc.wait(timeout=30)
      except psutil.TimeoutExpired:
        print("Timed out trying to kill daemon process")
        return 1
    return 0

  if options.reload:
    proc = get_daemon_proc(config_file)
    if proc is None:
      return 1
    proc.send_signal(signal.SIGHUP)
    return 0

  if options.add_user:
    user = getpass.getuser()

    try:
      if user in grp.getgrnam(CHROME_REMOTING_GROUP_NAME).gr_mem:
        logging.info("User '%s' is already a member of '%s'." %
                     (user, CHROME_REMOTING_GROUP_NAME))
        return 0
    except KeyError:
      logging.info("Group '%s' not found." % CHROME_REMOTING_GROUP_NAME)

    command = [SCRIPT_PATH, '--add-user-as-root', user]
    if os.getenv("DISPLAY"):
      # TODO(rickyz): Add a Polkit policy that includes a more friendly message
      # about what this command does.
      command = ["/usr/bin/pkexec"] + command
    else:
      command = ["/usr/bin/sudo", "-k", "--"] + command

    # Run with an empty environment out of paranoia, though if an attacker
    # controls the environment this script is run under, we're already screwed
    # anyway.
    os.execve(command[0], command, {})
    return 1

  if options.add_user_as_root is not None:
    if os.getuid() != 0:
      logging.error("--add-user-as-root can only be specified as root.")
      return 1;

    user = options.add_user_as_root
    try:
      pwd.getpwnam(user)
    except KeyError:
      logging.error("user '%s' does not exist." % user)
      return 1

    try:
      subprocess.check_call(["/usr/sbin/groupadd", "-f",
                             CHROME_REMOTING_GROUP_NAME])
      subprocess.check_call(["/usr/bin/gpasswd", "--add", user,
                             CHROME_REMOTING_GROUP_NAME])
    except (ValueError, OSError, subprocess.CalledProcessError) as e:
      logging.error("Command failed: " + str(e))
      return 1

    return 0

  if options.watch_resolution:
    watch_for_resolution_changes(options.watch_resolution)
    return 0

  if not options.start:
    # If no modal command-line options specified, print an error and exit.
    print(EPILOG, file=sys.stderr)
    return 1

  # Determine whether a desktop is already active for the specified host
  # configuration.
  if get_daemon_proc(config_file, options.child_process) is not None:
    # Debian policy requires that services should "start" cleanly and return 0
    # if they are already running.
    if options.child_process:
      # If the script is running under user-session, try to relay the message.
      ParentProcessLogger.try_start_logging(USER_SESSION_MESSAGE_FD)
    logging.info("Service already running.")
    ParentProcessLogger.release_parent_if_connected(True)
    return 0

  if config_file != options.config:
    # --config was either not specified or isn't a canonical absolute path.
    # Replace it with the canonical path so get_daemon_proc can find us.
    sys.argv = ([sys.argv[0], "--config=" + config_file] +
                parse_config_arg(sys.argv[1:])[1])
    if options.child_process:
      os.execvp(sys.argv[0], sys.argv)

  if not options.child_process:
    return start_via_user_session(options.foreground)

  # Start logging to user-session messaging pipe if it exists.
  ParentProcessLogger.try_start_logging(USER_SESSION_MESSAGE_FD)

  # If a RANDR-supporting Xvfb is not available, limit the default size to
  # something more sensible.
  if USE_XORG_ENV_VAR not in os.environ and locate_xvfb_randr():
    default_sizes = DEFAULT_SIZES
  else:
    default_sizes = DEFAULT_SIZE_NO_RANDR

  # Collate the list of sizes that XRANDR should support.
  if not options.size:
    if DEFAULT_SIZES_ENV_VAR in os.environ:
      default_sizes = os.environ[DEFAULT_SIZES_ENV_VAR]
    options.size = default_sizes.split(",")

  sizes = []
  for size in options.size:
    size_components = size.split("x")
    if len(size_components) != 2:
      parser.error("Incorrect size format '%s', should be WIDTHxHEIGHT" % size)

    try:
      width = int(size_components[0])
      height = int(size_components[1])

      # Enforce minimum desktop size, as a sanity-check.  The limit of 100 will
      # detect typos of 2 instead of 3 digits.
      if width < 100 or height < 100:
        raise ValueError
    except ValueError:
      parser.error("Width and height should be 100 pixels or greater")

    sizes.append((width, height))

  # Register an exit handler to clean up session process and the PID file.
  atexit.register(cleanup)

  # Load the initial host configuration.
  host_config = Config(config_file)
  try:
    host_config.load()
  except (IOError, ValueError) as e:
    print("Failed to load config: " + str(e), file=sys.stderr)
    return 1

  # Register handler to re-load the configuration in response to signals.
  for s in [signal.SIGHUP, signal.SIGINT, signal.SIGTERM]:
    signal.signal(s, SignalHandler(host_config))

  # Verify that the initial host configuration has the necessary fields.
  auth = Authentication()
  auth_config_valid = auth.copy_from(host_config)
  host = Host()
  host_config_valid = host.copy_from(host_config)
  if not host_config_valid or not auth_config_valid:
    logging.error("Failed to load host configuration.")
    return 1

  if host.host_id:
    logging.info("Using host_id: " + host.host_id)
  if host.gcd_device_id:
    logging.info("Using gcd_device_id: " + host.gcd_device_id)

  desktop = Desktop(sizes)

  # Keep track of the number of consecutive failures of any child process to
  # run for longer than a set period of time. The script will exit after a
  # threshold is exceeded.
  # There is no point in tracking the X session process separately, since it is
  # launched at (roughly) the same time as the X server, and the termination of
  # one of these triggers the termination of the other.
  x_server_inhibitor = RelaunchInhibitor("X server")
  session_inhibitor = RelaunchInhibitor("session")
  host_inhibitor = RelaunchInhibitor("host")
  all_inhibitors = [
      (x_server_inhibitor, HOST_OFFLINE_REASON_X_SERVER_RETRIES_EXCEEDED),
      (session_inhibitor, HOST_OFFLINE_REASON_SESSION_RETRIES_EXCEEDED),
      (host_inhibitor, HOST_OFFLINE_REASON_HOST_RETRIES_EXCEEDED)
  ]

  # Whether we are tearing down because the X server and/or session exited.
  # This keeps us from counting processes exiting because we've terminated them
  # as errors.
  tear_down = False

  while True:
    # If the session process or X server stops running (e.g. because the user
    # logged out), terminate all processes. The session will be restarted once
    # everything has exited.
    if tear_down:
      desktop.shutdown_all_procs()

      failure_count = 0
      for inhibitor, _ in all_inhibitors:
        if inhibitor.running:
          inhibitor.record_stopped(True)
        failure_count += inhibitor.failures

      tear_down = False

      if (failure_count == 0):
        # Since the user's desktop is already gone at this point, there's no
        # state to lose and now is a good time to pick up any updates to this
        # script that might have been installed.
        logging.info("Relaunching self")
        relaunch_self()
      else:
        # If there is a non-zero |failures| count, restarting the whole script
        # would lose this information, so just launch the session as normal,
        # below.
        pass

    relaunch_times = []

    # Set the backoff interval and exit if a process failed too many times.
    backoff_time = SHORT_BACKOFF_TIME
    for inhibitor, offline_reason in all_inhibitors:
      if inhibitor.failures >= MAX_LAUNCH_FAILURES:
        logging.error("Too many launch failures of '%s', exiting."
                      % inhibitor.label)
        desktop.report_offline_reason(host_config, offline_reason)
        return 1
      elif inhibitor.failures >= SHORT_BACKOFF_THRESHOLD:
        backoff_time = LONG_BACKOFF_TIME

      if inhibitor.is_inhibited():
        relaunch_times.append(inhibitor.earliest_relaunch_time)

    if relaunch_times:
      # We want to wait until everything is ready to start so we don't end up
      # launching things in the wrong order due to differing relaunch times.
      logging.info("Waiting before relaunching")
    else:
      if desktop.x_proc is None and desktop.session_proc is None:
        logging.info("Launching X server and X session.")
        desktop.launch_session(options.args)
        x_server_inhibitor.record_started(MINIMUM_PROCESS_LIFETIME,
                                          backoff_time)
        session_inhibitor.record_started(MINIMUM_PROCESS_LIFETIME,
                                         backoff_time)
      if desktop.host_proc is None:
        logging.info("Launching host process")

        extra_start_host_args = []
        if HOST_EXTRA_PARAMS_ENV_VAR in os.environ:
            extra_start_host_args = \
                re.split('\s+', os.environ[HOST_EXTRA_PARAMS_ENV_VAR].strip())
        desktop.launch_host(host_config, extra_start_host_args)

        host_inhibitor.record_started(MINIMUM_PROCESS_LIFETIME, backoff_time)

    deadline = max(relaunch_times) if relaunch_times else 0
    pid, status = waitpid_handle_exceptions(-1, deadline)
    if pid == 0:
      continue

    logging.info("wait() returned (%s,%s)" % (pid, status))

    # When a process has terminated, and we've reaped its exit-code, any Popen
    # instance for that process is no longer valid. Reset any affected instance
    # to None.
    if desktop.x_proc is not None and pid == desktop.x_proc.pid:
      logging.info("X server process terminated")
      desktop.x_proc = None
      x_server_inhibitor.record_stopped(False)
      tear_down = True

    if desktop.session_proc is not None and pid == desktop.session_proc.pid:
      logging.info("Session process terminated")
      desktop.session_proc = None
      # The session may have exited on its own or been brought down by the X
      # server dying. Check if the X server is still running so we know whom
      # to penalize.
      if desktop.check_x_responding():
        session_inhibitor.record_stopped(False)
      else:
        x_server_inhibitor.record_stopped(False)
      # Either way, we want to tear down the session.
      tear_down = True

    if desktop.host_proc is not None and pid == desktop.host_proc.pid:
      logging.info("Host process terminated")
      desktop.host_proc = None
      desktop.host_ready = False

      # These exit-codes must match the ones used by the host.
      # See remoting/host/host_error_codes.h.
      # Delete the host or auth configuration depending on the returned error
      # code, so the next time this script is run, a new configuration
      # will be created and registered.
      if os.WIFEXITED(status):
        if os.WEXITSTATUS(status) == 100:
          logging.info("Host configuration is invalid - exiting.")
          return 0
        elif os.WEXITSTATUS(status) == 101:
          logging.info("Host ID has been deleted - exiting.")
          host_config.clear()
          host_config.save_and_log_errors()
          return 0
        elif os.WEXITSTATUS(status) == 102:
          logging.info("OAuth credentials are invalid - exiting.")
          return 0
        elif os.WEXITSTATUS(status) == 103:
          logging.info("Host domain is blocked by policy - exiting.")
          return 0
        # Nothing to do for Mac-only status 104 (login screen unsupported)
        elif os.WEXITSTATUS(status) == 105:
          logging.info("Username is blocked by policy - exiting.")
          return 0
        else:
          logging.info("Host exited with status %s." % os.WEXITSTATUS(status))
      elif os.WIFSIGNALED(status):
        logging.info("Host terminated by signal %s." % os.WTERMSIG(status))

      # The host may have exited on it's own or been brought down by the X
      # server dying. Check if the X server is still running so we know whom to
      # penalize.
      if desktop.check_x_responding():
        host_inhibitor.record_stopped(False)
      else:
        x_server_inhibitor.record_stopped(False)
        # Only tear down if the X server isn't responding.
        tear_down = True


if __name__ == "__main__":
  logging.basicConfig(level=logging.DEBUG,
                      format="%(asctime)s:%(levelname)s:%(message)s")
  sys.exit(main())
