Home | History | Annotate | Download | only in server
      1 # Copyright 2013 The Chromium Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import atexit
      6 import os
      7 import socket
      8 import subprocess
      9 import time
     10 import urllib2
     11 
     12 
     13 class Server(object):
     14   """A running ChromeDriver server."""
     15 
     16   def __init__(self, exe_path, log_path=None):
     17     """Starts the ChromeDriver server and waits for it to be ready.
     18 
     19     Args:
     20       exe_path: path to the ChromeDriver executable
     21       log_path: path to the log file
     22     Raises:
     23       RuntimeError if ChromeDriver fails to start
     24     """
     25     if not os.path.exists(exe_path):
     26       raise RuntimeError('ChromeDriver exe not found at: ' + exe_path)
     27 
     28     port = self._FindOpenPort()
     29     chromedriver_args = [exe_path, '--port=%d' % port]
     30     if log_path:
     31       chromedriver_args.extend(['--verbose', '--log-path=%s' % log_path])
     32     self._process = subprocess.Popen(chromedriver_args)
     33     self._url = 'http://127.0.0.1:%d' % port
     34     if self._process is None:
     35       raise RuntimeError('ChromeDriver server cannot be started')
     36 
     37     max_time = time.time() + 10
     38     while not self.IsRunning():
     39       if time.time() > max_time:
     40         self._process.terminate()
     41         raise RuntimeError('ChromeDriver server did not start')
     42       time.sleep(0.1)
     43 
     44     atexit.register(self.Kill)
     45 
     46   def _FindOpenPort(self):
     47     for port in range(9500, 10000):
     48       try:
     49         socket.create_connection(('127.0.0.1', port), 0.2).close()
     50       except socket.error:
     51         return port
     52     raise RuntimeError('Cannot find open port to launch ChromeDriver')
     53 
     54   def GetUrl(self):
     55     return self._url
     56 
     57   def IsRunning(self):
     58     """Returns whether the server is up and running."""
     59     try:
     60       urllib2.urlopen(self.GetUrl() + '/status')
     61       return True
     62     except urllib2.URLError:
     63       return False
     64 
     65   def Kill(self):
     66     """Kills the ChromeDriver server, if it is running."""
     67     if self._process is None:
     68       return
     69 
     70     try:
     71       urllib2.urlopen(self.GetUrl() + '/shutdown', timeout=10).close()
     72     except:
     73       self._process.terminate()
     74     self._process.wait()
     75     self._process = None
     76