1 | #!/usr/bin/python
|
---|
2 | #
|
---|
3 | # Copyright 2011 Webdriver_name committers
|
---|
4 | # Copyright 2011 Google Inc.
|
---|
5 | #
|
---|
6 | # Licensed under the Apache License, Version 2.0 (the "License");
|
---|
7 | # you may not use this file except in compliance with the License.
|
---|
8 | # You may obtain a copy of the License at
|
---|
9 | #
|
---|
10 | # http://www.apache.org/licenses/LICENSE-2.0
|
---|
11 | #
|
---|
12 | # Unless required by applicable law or agreed to in writing, software
|
---|
13 | # distributed under the License is distributed on an "AS IS" BASIS,
|
---|
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
---|
15 | # See the License for the specific language governing permissions and
|
---|
16 | # limitations under the License.
|
---|
17 | import os
|
---|
18 | import subprocess
|
---|
19 | from subprocess import PIPE
|
---|
20 | import time
|
---|
21 |
|
---|
22 | from selenium.common.exceptions import WebDriverException
|
---|
23 | from selenium.webdriver.common import utils
|
---|
24 |
|
---|
25 | class Service(object):
|
---|
26 | """
|
---|
27 | Object that manages the starting and stopping of the ChromeDriver
|
---|
28 | """
|
---|
29 |
|
---|
30 | def __init__(self, executable_path, port=0, service_args=None,
|
---|
31 | log_path=None, env=None):
|
---|
32 | """
|
---|
33 | Creates a new instance of the Service
|
---|
34 |
|
---|
35 | :Args:
|
---|
36 | - executable_path : Path to the ChromeDriver
|
---|
37 | - port : Port the service is running on
|
---|
38 | - service_args : List of args to pass to the chromedriver service
|
---|
39 | - log_path : Path for the chromedriver service to log to"""
|
---|
40 |
|
---|
41 | self.port = port
|
---|
42 | self.path = executable_path
|
---|
43 | self.service_args = service_args or []
|
---|
44 | if log_path:
|
---|
45 | self.service_args.append('--log-path=%s' % log_path)
|
---|
46 | if self.port == 0:
|
---|
47 | self.port = utils.free_port()
|
---|
48 | self.env = env
|
---|
49 |
|
---|
50 | def start(self):
|
---|
51 | """
|
---|
52 | Starts the ChromeDriver Service.
|
---|
53 |
|
---|
54 | :Exceptions:
|
---|
55 | - WebDriverException : Raised either when it can't start the service
|
---|
56 | or when it can't connect to the service
|
---|
57 | """
|
---|
58 | env = self.env or os.environ
|
---|
59 | try:
|
---|
60 | startupInfo = subprocess.STARTUPINFO()
|
---|
61 | startupInfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
---|
62 | self.process = subprocess.Popen([
|
---|
63 | self.path,
|
---|
64 | "--port=%d" % self.port] +
|
---|
65 | self.service_args, env=env, stdout=PIPE, stderr=PIPE,
|
---|
66 | startupinfo = startupInfo)
|
---|
67 | except:
|
---|
68 | raise WebDriverException(
|
---|
69 | "'" + os.path.basename(self.path) + "' executable needs to be \
|
---|
70 | available in the path. Please look at \
|
---|
71 | http://docs.seleniumhq.org/download/#thirdPartyDrivers \
|
---|
72 | and read up at \
|
---|
73 | http://code.google.com/p/selenium/wiki/ChromeDriver")
|
---|
74 | count = 0
|
---|
75 | while not utils.is_connectable(self.port):
|
---|
76 | count += 1
|
---|
77 | time.sleep(1)
|
---|
78 | if count == 30:
|
---|
79 | raise WebDriverException("Can not connect to the '" +
|
---|
80 | os.path.basename(self.path) + "'")
|
---|
81 |
|
---|
82 | @property
|
---|
83 | def service_url(self):
|
---|
84 | """
|
---|
85 | Gets the url of the ChromeDriver Service
|
---|
86 | """
|
---|
87 | return "http://localhost:%d" % self.port
|
---|
88 |
|
---|
89 | def stop(self):
|
---|
90 | """
|
---|
91 | Tells the ChromeDriver to stop and cleans up the process
|
---|
92 | """
|
---|
93 | #If its dead dont worry
|
---|
94 | if self.process is None:
|
---|
95 | return
|
---|
96 |
|
---|
97 | #Tell the Server to die!
|
---|
98 | try:
|
---|
99 | from urllib import request as url_request
|
---|
100 | except ImportError:
|
---|
101 | import urllib2 as url_request
|
---|
102 |
|
---|
103 | url_request.urlopen("http://127.0.0.1:%d/shutdown" % self.port)
|
---|
104 | count = 0
|
---|
105 | while utils.is_connectable(self.port):
|
---|
106 | if count == 30:
|
---|
107 | break
|
---|
108 | count += 1
|
---|
109 | time.sleep(1)
|
---|
110 |
|
---|
111 | #Tell the Server to properly die in case
|
---|
112 | try:
|
---|
113 | if self.process:
|
---|
114 | self.process.kill()
|
---|
115 | self.process.wait()
|
---|
116 | except OSError:
|
---|
117 | # kill may not be available under windows environment
|
---|
118 | pass
|
---|