forked from SeleniumHQ/selenium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFirefoxDriverService.cs
292 lines (258 loc) · 11.5 KB
/
FirefoxDriverService.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
// <copyright file="FirefoxDriverService.cs" company="Selenium Committers">
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
// </copyright>
using OpenQA.Selenium.Internal;
using System;
using System.Globalization;
using System.IO;
using System.Text;
namespace OpenQA.Selenium.Firefox
{
/// <summary>
/// Exposes the service provided by the native FirefoxDriver executable.
/// </summary>
public sealed class FirefoxDriverService : DriverService
{
private const string DefaultFirefoxDriverServiceFileName = "geckodriver";
private bool connectToRunningBrowser;
private bool openBrowserToolbox;
private int browserCommunicationPort = -1;
private string browserBinaryPath = string.Empty;
private string host = string.Empty;
private string browserCommunicationHost = string.Empty;
private FirefoxDriverLogLevel loggingLevel = FirefoxDriverLogLevel.Default;
/// <summary>
/// Initializes a new instance of the <see cref="FirefoxDriverService"/> class.
/// </summary>
/// <param name="executablePath">The full path to the Firefox driver executable.</param>
/// <param name="executableFileName">The file name of the Firefox driver executable.</param>
/// <param name="port">The port on which the Firefox driver executable should listen.</param>
private FirefoxDriverService(string executablePath, string executableFileName, int port)
: base(executablePath, port, executableFileName)
{
}
/// <inheritdoc />
protected override DriverOptions GetDefaultDriverOptions()
{
return new FirefoxOptions();
}
/// <summary>
/// Gets or sets the location of the Firefox binary executable.
/// </summary>
public string FirefoxBinaryPath
{
get { return this.browserBinaryPath; }
set { this.browserBinaryPath = value; }
}
/// <summary>
/// Gets or sets the port used by the driver executable to communicate with the browser.
/// </summary>
public int BrowserCommunicationPort
{
get { return this.browserCommunicationPort; }
set { this.browserCommunicationPort = value; }
}
/// <summary>
/// Gets or sets the value of the IP address of the host adapter used by the driver
/// executable to communicate with the browser.
/// </summary>
public string BrowserCommunicationHost
{
get { return this.browserCommunicationHost; }
set { this.browserCommunicationHost = value; }
}
/// <summary>
/// Gets or sets the value of the IP address of the host adapter on which the
/// service should listen for connections.
/// </summary>
public string Host
{
get { return this.host; }
set { this.host = value; }
}
/// <summary>
/// Gets or sets a value indicating whether to connect to an already-running
/// instance of Firefox.
/// </summary>
public bool ConnectToRunningBrowser
{
get { return this.connectToRunningBrowser; }
set { this.connectToRunningBrowser = value; }
}
/// <summary>
/// Gets or sets a value indicating whether to open the Firefox Browser Toolbox
/// when Firefox is launched.
/// </summary>
public bool OpenBrowserToolbox
{
get { return this.openBrowserToolbox; }
set { this.openBrowserToolbox = value; }
}
/// <summary>
/// Gets or sets the level at which log output is displayed.
/// </summary>
/// <remarks>
/// This is largely equivalent to setting the <see cref="FirefoxOptions.LogLevel"/>
/// property, except the log level is set when the driver launches, instead of
/// when the browser is launched, meaning that initial driver logging before
/// initiation of a session can be controlled.
/// </remarks>
public FirefoxDriverLogLevel LogLevel
{
get { return this.loggingLevel; }
set { this.loggingLevel = value; }
}
/// <summary>
/// Gets a value indicating the time to wait for the service to terminate before forcing it to terminate.
/// </summary>
protected override TimeSpan TerminationTimeout
{
// Use a very small timeout for terminating the Firefox driver,
// because the executable does not have a clean shutdown command,
// which means we have to kill the process. Using a short timeout
// gets us to the termination point much faster.
get { return TimeSpan.FromMilliseconds(100); }
}
/// <summary>
/// Gets a value indicating whether the service has a shutdown API that can be called to terminate
/// it gracefully before forcing a termination.
/// </summary>
protected override bool HasShutdown
{
// The Firefox driver executable does not have a clean shutdown command,
// which means we have to kill the process.
get { return false; }
}
/// <summary>
/// Gets the command-line arguments for the driver service.
/// </summary>
protected override string CommandLineArguments
{
get
{
StringBuilder argsBuilder = new StringBuilder();
if (this.connectToRunningBrowser)
{
argsBuilder.Append(" --connect-existing");
}
else
{
argsBuilder.Append(string.Format(CultureInfo.InvariantCulture, " --websocket-port {0}", PortUtilities.FindFreePort()));
}
if (this.browserCommunicationPort > 0)
{
argsBuilder.AppendFormat(CultureInfo.InvariantCulture, " --marionette-port {0}", this.browserCommunicationPort);
}
if (!string.IsNullOrEmpty(this.browserCommunicationHost))
{
argsBuilder.AppendFormat(CultureInfo.InvariantCulture, " --marionette-host \"{0}\"", this.browserCommunicationHost);
}
if (this.Port > 0)
{
argsBuilder.AppendFormat(CultureInfo.InvariantCulture, " --port {0}", this.Port);
}
if (!string.IsNullOrEmpty(this.browserBinaryPath))
{
argsBuilder.AppendFormat(CultureInfo.InvariantCulture, " --binary \"{0}\"", this.browserBinaryPath);
}
if (!string.IsNullOrEmpty(this.host))
{
argsBuilder.AppendFormat(CultureInfo.InvariantCulture, " --host \"{0}\"", this.host);
}
if (this.loggingLevel != FirefoxDriverLogLevel.Default)
{
argsBuilder.Append(string.Format(CultureInfo.InvariantCulture, " --log {0}", this.loggingLevel.ToString().ToLowerInvariant()));
}
if (this.openBrowserToolbox)
{
argsBuilder.Append(" --jsdebugger");
}
return argsBuilder.ToString().Trim();
}
}
/// <summary>
/// Creates a default instance of the FirefoxDriverService.
/// </summary>
/// <returns>A FirefoxDriverService that implements default settings.</returns>
public static FirefoxDriverService CreateDefaultService()
{
return new FirefoxDriverService(null, null, PortUtilities.FindFreePort());
}
/// <summary>
/// Creates a default instance of the FirefoxDriverService using a specified path to the Firefox driver executable.
/// </summary>
/// <param name="driverPath">The path to the executable or the directory containing the Firefox driver executable.</param>
/// <returns>A FirefoxDriverService using a random port.</returns>
public static FirefoxDriverService CreateDefaultService(string driverPath)
{
string fileName;
if (File.Exists(driverPath))
{
fileName = Path.GetFileName(driverPath);
driverPath = Path.GetDirectoryName(driverPath);
}
else
{
fileName = FirefoxDriverServiceFileName();
}
return CreateDefaultService(driverPath, fileName);
}
/// <summary>
/// Creates a default instance of the FirefoxDriverService using a specified path to the Firefox driver executable with the given name.
/// </summary>
/// <param name="driverPath">The directory containing the Firefox driver executable.</param>
/// <param name="driverExecutableFileName">The name of the Firefox driver executable file.</param>
/// <returns>A FirefoxDriverService using a random port.</returns>
public static FirefoxDriverService CreateDefaultService(string driverPath, string driverExecutableFileName)
{
return new FirefoxDriverService(driverPath, driverExecutableFileName, PortUtilities.FindFreePort());
}
/// <summary>
/// Returns the Firefox driver filename for the currently running platform
/// </summary>
/// <returns>The file name of the Firefox driver service executable.</returns>
private static string FirefoxDriverServiceFileName()
{
string fileName = DefaultFirefoxDriverServiceFileName;
// Unfortunately, detecting the currently running platform isn't as
// straightforward as you might hope.
// See: http://mono.wikia.com/wiki/Detecting_the_execution_platform
// and https://msdn.microsoft.com/en-us/library/3a8hyw88(v=vs.110).aspx
const PlatformID PlatformIDMonoUnix = (PlatformID)128;
switch (Environment.OSVersion.Platform)
{
case PlatformID.Win32NT:
case PlatformID.Win32S:
case PlatformID.Win32Windows:
case PlatformID.WinCE:
fileName += ".exe";
break;
case PlatformID.MacOSX:
case PlatformID.Unix:
case PlatformIDMonoUnix:
break;
// Don't handle the Xbox case. Let default handle it.
// case PlatformID.Xbox:
// break;
default:
throw new WebDriverException("Unsupported platform: " + Environment.OSVersion.Platform);
}
return fileName;
}
}
}