# Copyright 2013 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.
import atexit
import os
import socket
import subprocess
import time
import urllib2
class Server(object):
"""A running ChromeDriver server."""
def __init__(self, exe_path, log_path=None):
"""Starts the ChromeDriver server and waits for it to be ready.
Args:
exe_path: path to the ChromeDriver executable
log_path: path to the log file
Raises:
RuntimeError if ChromeDriver fails to start
"""
if not os.path.exists(exe_path):
raise RuntimeError('ChromeDriver exe not found at: ' + exe_path)
port = self._FindOpenPort()
chromedriver_args = [exe_path, '--port=%d' % port]
if log_path:
chromedriver_args.extend(['--verbose', '--log-path=%s' % log_path])
self._process = subprocess.Popen(chromedriver_args)
self._url = 'http://127.0.0.1:%d' % port
if self._process is None:
raise RuntimeError('ChromeDriver server cannot be started')
max_time = time.time() + 10
while not self.IsRunning():
if time.time() > max_time:
self._process.terminate()
raise RuntimeError('ChromeDriver server did not start')
time.sleep(0.1)
atexit.register(self.Kill)
def _FindOpenPort(self):
for port in range(9500, 10000):
try:
socket.create_connection(('127.0.0.1', port), 0.2).close()
except socket.error:
return port
raise RuntimeError('Cannot find open port to launch ChromeDriver')
def GetUrl(self):
return self._url
def IsRunning(self):
"""Returns whether the server is up and running."""
try:
urllib2.urlopen(self.GetUrl() + '/status')
return True
except urllib2.URLError:
return False
def Kill(self):
"""Kills the ChromeDriver server, if it is running."""
if self._process is None:
return
try:
urllib2.urlopen(self.GetUrl() + '/shutdown', timeout=10).close()
except:
self._process.terminate()
self._process.wait()
self._process = None