Skip to content

Commit

Permalink
[dotnet] Use Selenium Manager to locate drivers on PATH (#12344)
Browse files Browse the repository at this point in the history
* [dotnet] use Selenium Manager to locate drivers on PATH

* [dotnet] allow user to pass in full path to driver in Service class

---------

Co-authored-by: Diego Molina <[email protected]>
  • Loading branch information
titusfortner and diemol authored Jul 13, 2023
1 parent 6176d7e commit 6a48692
Show file tree
Hide file tree
Showing 11 changed files with 75 additions and 77 deletions.
19 changes: 10 additions & 9 deletions dotnet/src/webdriver/Chrome/ChromeDriverService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
// limitations under the License.
// </copyright>

using System;
using OpenQA.Selenium.Internal;
using System.IO;
using OpenQA.Selenium.Chromium;
using OpenQA.Selenium.Internal;

namespace OpenQA.Selenium.Chrome
{
Expand All @@ -29,16 +29,14 @@ public sealed class ChromeDriverService : ChromiumDriverService
{
private const string DefaultChromeDriverServiceExecutableName = "chromedriver";

private static readonly Uri ChromeDriverDownloadUrl = new Uri("http://chromedriver.storage.googleapis.com/index.html");

/// <summary>
/// Initializes a new instance of the <see cref="ChromeDriverService"/> class.
/// </summary>
/// <param name="executablePath">The full path to the ChromeDriver executable.</param>
/// <param name="executableFileName">The file name of the ChromeDriver executable.</param>
/// <param name="port">The port on which the ChromeDriver executable should listen.</param>
private ChromeDriverService(string executablePath, string executableFileName, int port)
: base(executablePath, executableFileName, port, ChromeDriverDownloadUrl)
: base(executablePath, executableFileName, port)
{
}

Expand All @@ -58,10 +56,8 @@ public static ChromeDriverService CreateDefaultService()
/// <returns>A ChromeDriverService that implements default settings.</returns>
public static ChromeDriverService CreateDefaultService(ChromeOptions options)
{
string serviceDirectory = DriverService.FindDriverServiceExecutable(ChromiumDriverServiceFileName(DefaultChromeDriverServiceExecutableName),
ChromeDriverDownloadUrl);
ChromeDriverService service = CreateDefaultService(serviceDirectory);
return DriverFinder.VerifyDriverServicePath(service, options) as ChromeDriverService;;
string fullServicePath = DriverFinder.FullPath(options);
return CreateDefaultService(Path.GetDirectoryName(fullServicePath), Path.GetFileName(fullServicePath));
}

/// <summary>
Expand All @@ -71,6 +67,11 @@ public static ChromeDriverService CreateDefaultService(ChromeOptions options)
/// <returns>A ChromeDriverService using a random port.</returns>
public static ChromeDriverService CreateDefaultService(string driverPath)
{
if (Path.GetFileName(driverPath).Contains(DefaultChromeDriverServiceExecutableName))
{
driverPath = Path.GetDirectoryName(driverPath);
}

return CreateDefaultService(driverPath, ChromiumDriverServiceFileName(DefaultChromeDriverServiceExecutableName));
}

Expand Down
2 changes: 1 addition & 1 deletion dotnet/src/webdriver/Chromium/ChromiumDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public class ChromiumDriver : WebDriver, ISupportsLogs, IDevTools
/// <param name="options">The <see cref="ChromiumOptions"/> to be used with the ChromiumDriver.</param>
/// <param name="commandTimeout">The maximum amount of time to wait for each command.</param>
protected ChromiumDriver(ChromiumDriverService service, ChromiumOptions options, TimeSpan commandTimeout)
: base(new DriverServiceCommandExecutor(DriverFinder.VerifyDriverServicePath(service, options), commandTimeout), ConvertOptionsToCapabilities(options))
: base(new DriverServiceCommandExecutor(service, commandTimeout), ConvertOptionsToCapabilities(options))
{
this.optionsCapabilityName = options.CapabilityName;
}
Expand Down
5 changes: 2 additions & 3 deletions dotnet/src/webdriver/Chromium/ChromiumDriverService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,8 @@ public abstract class ChromiumDriverService : DriverService
/// <param name="executablePath">The full path to the ChromeDriver executable.</param>
/// <param name="executableFileName">The file name of the ChromeDriver executable.</param>
/// <param name="port">The port on which the ChromeDriver executable should listen.</param>
/// <param name="downloadUrl">The url that ChromiumDriver should be downloaded from.</param>
protected ChromiumDriverService(string executablePath, string executableFileName, int port, Uri downloadUrl)
: base(executablePath, port, executableFileName, downloadUrl)
protected ChromiumDriverService(string executablePath, string executableFileName, int port, Uri downloadUrl = null)
: base(executablePath, port, executableFileName)
{
}

Expand Down
30 changes: 19 additions & 11 deletions dotnet/src/webdriver/DriverFinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,31 +28,39 @@ namespace OpenQA.Selenium
public static class DriverFinder
{
/// <summary>
/// Checks if the driver path exists, else uses Selenium Manager to return it.
/// Use Selenium Manager to locate the driver
/// </summary>
/// <param name="service">DriverService with the current path.</param>
/// <param name="options">DriverOptions with the current browser options.</param>
/// <returns>
/// The service with a verified driver executable path.
/// The full path and name of the driver
/// </returns>
public static DriverService VerifyDriverServicePath(DriverService service, DriverOptions options)
/// <exception cref="NoSuchDriverException"></exception>
public static string FullPath(DriverOptions options)
{
string executablePath = Path.Combine(service.DriverServicePath, service.DriverServiceExecutableName);
if (File.Exists(executablePath)) return service;
string executablePath;
try
{
executablePath = SeleniumManager.DriverPath(options);
service.DriverServicePath = Path.GetDirectoryName(executablePath);
service.DriverServiceExecutableName = Path.GetFileName(executablePath);
}
catch (Exception e)
{
throw new NoSuchDriverException($"Unable to obtain {service.DriverServiceExecutableName} using Selenium Manager", e);
throw new NoSuchDriverException($"Unable to obtain {options.BrowserName} using Selenium Manager", e);
}

if (File.Exists(executablePath)) return service;
string message;
if (executablePath == null)
{
message = $"Unable to locate or obtain {options.BrowserName} driver";
} else if (!File.Exists(executablePath))
{
message = $"{options.BrowserName} driver located at {executablePath}, but invalid";
}
else
{
return executablePath;
}

throw new NoSuchDriverException($"Unable to locate or obtain {service.DriverServiceExecutableName}");
throw new NoSuchDriverException(message);
}
}
}
18 changes: 2 additions & 16 deletions dotnet/src/webdriver/DriverService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ public abstract class DriverService : ICommandServer
/// <param name="servicePath">The full path to the directory containing the executable providing the service to drive the browser.</param>
/// <param name="port">The port on which the driver executable should listen.</param>
/// <param name="driverServiceExecutableName">The file name of the driver service executable.</param>
/// <param name="driverServiceDownloadUrl">A URL at which the driver service executable may be downloaded.</param>
/// <param name="driverServiceDownloadUrl">This parameter is no longer used; kept for backwards compatibility.</param>
/// <exception cref="ArgumentException">
/// If the path specified is <see langword="null"/> or an empty string.
/// </exception>
/// <exception cref="DriverServiceNotFoundException">
/// If the specified driver service executable does not exist in the specified directory.
/// </exception>
protected DriverService(string servicePath, int port, string driverServiceExecutableName, Uri driverServiceDownloadUrl)
protected DriverService(string servicePath, int port, string driverServiceExecutableName, Uri driverServiceDownloadUrl = null)
{
this.driverServicePath = servicePath;
this.driverServiceExecutableName = driverServiceExecutableName;
Expand Down Expand Up @@ -284,20 +284,6 @@ public void Start()
}
}

/// <summary>
/// Finds the specified driver service executable.
/// </summary>
/// <param name="executableName">The file name of the executable to find.</param>
/// <param name="downloadUrl">A URL at which the driver service executable may be downloaded.</param>
/// <returns>The directory containing the driver service executable.</returns>
/// <exception cref="DriverServiceNotFoundException">
/// If the specified driver service executable does not exist in the current directory or in a directory on the system path.
/// </exception>
protected static string FindDriverServiceExecutable(string executableName, Uri downloadUrl)
{
return FileUtilities.FindFile(executableName);
}

/// <summary>
/// Releases all resources associated with this <see cref="DriverService"/>.
/// </summary>
Expand Down
21 changes: 10 additions & 11 deletions dotnet/src/webdriver/Edge/EdgeDriverService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@
// limitations under the License.
// </copyright>

using System;
using System.Globalization;
using System.Text;
using OpenQA.Selenium.Internal;
using System.IO;
using OpenQA.Selenium.Chromium;
using OpenQA.Selenium.Internal;

namespace OpenQA.Selenium.Edge
{
Expand All @@ -31,16 +29,14 @@ public sealed class EdgeDriverService : ChromiumDriverService
{
private const string MSEdgeDriverServiceFileName = "msedgedriver";

private static readonly Uri MicrosoftWebDriverDownloadUrl = new Uri("https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/");

/// <summary>
/// Initializes a new instance of the <see cref="EdgeDriverService"/> class.
/// </summary>
/// <param name="executablePath">The full path to the EdgeDriver executable.</param>
/// <param name="executableFileName">The file name of the EdgeDriver executable.</param>
/// <param name="port">The port on which the EdgeDriver executable should listen.</param>
private EdgeDriverService(string executablePath, string executableFileName, int port)
: base(executablePath, executableFileName, port, MicrosoftWebDriverDownloadUrl)
: base(executablePath, executableFileName, port)
{
}

Expand Down Expand Up @@ -69,10 +65,8 @@ public static EdgeDriverService CreateDefaultService()
/// <returns>A EdgeDriverService that implements default settings.</returns>
public static EdgeDriverService CreateDefaultService(EdgeOptions options)
{
string serviceDirectory = DriverService.FindDriverServiceExecutable(ChromiumDriverServiceFileName(MSEdgeDriverServiceFileName),
MicrosoftWebDriverDownloadUrl);
EdgeDriverService service = CreateDefaultService(serviceDirectory);
return DriverFinder.VerifyDriverServicePath(service, options) as EdgeDriverService;
string fullServicePath = DriverFinder.FullPath(options);
return CreateDefaultService(Path.GetDirectoryName(fullServicePath), Path.GetFileName(fullServicePath));
}

/// <summary>
Expand All @@ -82,6 +76,11 @@ public static EdgeDriverService CreateDefaultService(EdgeOptions options)
/// <returns>An EdgeDriverService using a random port.</returns>
public static EdgeDriverService CreateDefaultService(string driverPath)
{
if (Path.GetFileName(driverPath).Contains(MSEdgeDriverServiceFileName))
{
driverPath = Path.GetDirectoryName(driverPath);
}

return CreateDefaultService(driverPath, ChromiumDriverServiceFileName(MSEdgeDriverServiceFileName));
}

Expand Down
2 changes: 1 addition & 1 deletion dotnet/src/webdriver/Firefox/FirefoxDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ public FirefoxDriver(FirefoxDriverService service, FirefoxOptions options)
/// <param name="options">The <see cref="FirefoxOptions"/> to be used with the Firefox driver.</param>
/// <param name="commandTimeout">The maximum amount of time to wait for each command.</param>
public FirefoxDriver(FirefoxDriverService service, FirefoxOptions options, TimeSpan commandTimeout)
: base(new DriverServiceCommandExecutor(DriverFinder.VerifyDriverServicePath(service, options), commandTimeout), ConvertOptionsToCapabilities(options))
: base(new DriverServiceCommandExecutor(service, commandTimeout), ConvertOptionsToCapabilities(options))
{
// Add the custom commands unique to Firefox
this.AddCustomFirefoxCommands();
Expand Down
15 changes: 9 additions & 6 deletions dotnet/src/webdriver/Firefox/FirefoxDriverService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

using System;
using System.Globalization;
using System.Net;
using System.IO;
using System.Text;
using OpenQA.Selenium.Internal;

Expand All @@ -30,7 +30,6 @@ namespace OpenQA.Selenium.Firefox
public sealed class FirefoxDriverService : DriverService
{
private const string DefaultFirefoxDriverServiceFileName = "geckodriver";
private static readonly Uri FirefoxDriverDownloadUrl = new Uri("https://github.com/mozilla/geckodriver/releases");

private bool connectToRunningBrowser;
private bool openBrowserToolbox;
Expand All @@ -47,7 +46,7 @@ public sealed class FirefoxDriverService : DriverService
/// <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, FirefoxDriverDownloadUrl)
: base(executablePath, port, executableFileName)
{
}

Expand Down Expand Up @@ -220,9 +219,8 @@ public static FirefoxDriverService CreateDefaultService()
/// <returns>A FirefoxDriverService that implements default settings.</returns>
public static FirefoxDriverService CreateDefaultService(FirefoxOptions options)
{
string serviceDirectory = DriverService.FindDriverServiceExecutable(FirefoxDriverServiceFileName(), FirefoxDriverDownloadUrl);
FirefoxDriverService service = CreateDefaultService(serviceDirectory);
return DriverFinder.VerifyDriverServicePath(service, options) as FirefoxDriverService;
string fullServicePath = DriverFinder.FullPath(options);
return CreateDefaultService(Path.GetDirectoryName(fullServicePath), Path.GetFileName(fullServicePath));
}

/// <summary>
Expand All @@ -232,6 +230,11 @@ public static FirefoxDriverService CreateDefaultService(FirefoxOptions options)
/// <returns>A FirefoxDriverService using a random port.</returns>
public static FirefoxDriverService CreateDefaultService(string driverPath)
{
if (Path.GetFileName(driverPath) == FirefoxDriverServiceFileName())
{
driverPath = Path.GetDirectoryName(driverPath);
}

return CreateDefaultService(driverPath, FirefoxDriverServiceFileName());
}

Expand Down
2 changes: 1 addition & 1 deletion dotnet/src/webdriver/IE/InternetExplorerDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ public InternetExplorerDriver(InternetExplorerDriverService service, InternetExp
/// <param name="options">The <see cref="InternetExplorerOptions"/> used to initialize the driver.</param>
/// <param name="commandTimeout">The maximum amount of time to wait for each command.</param>
public InternetExplorerDriver(InternetExplorerDriverService service, InternetExplorerOptions options, TimeSpan commandTimeout)
: base(new DriverServiceCommandExecutor(DriverFinder.VerifyDriverServicePath(service, options), commandTimeout), ConvertOptionsToCapabilities(options))
: base(new DriverServiceCommandExecutor(service, commandTimeout), ConvertOptionsToCapabilities(options))
{
}

Expand Down
15 changes: 9 additions & 6 deletions dotnet/src/webdriver/IE/InternetExplorerDriverService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
// limitations under the License.
// </copyright>

using System;
using System.Globalization;
using System.IO;
using System.Text;
using OpenQA.Selenium.Internal;

Expand All @@ -29,7 +29,6 @@ namespace OpenQA.Selenium.IE
public sealed class InternetExplorerDriverService : DriverService
{
private const string InternetExplorerDriverServiceFileName = "IEDriverServer.exe";
private static readonly Uri InternetExplorerDriverDownloadUrl = new Uri("https://www.selenium.dev/downloads/");

private InternetExplorerDriverLogLevel loggingLevel = InternetExplorerDriverLogLevel.Fatal;
private string host = string.Empty;
Expand All @@ -44,7 +43,7 @@ public sealed class InternetExplorerDriverService : DriverService
/// <param name="executableFileName">The file name of the IEDriverServer executable.</param>
/// <param name="port">The port on which the IEDriverServer executable should listen.</param>
private InternetExplorerDriverService(string executablePath, string executableFileName, int port)
: base(executablePath, port, executableFileName, InternetExplorerDriverDownloadUrl)
: base(executablePath, port, executableFileName)
{
}

Expand Down Expand Up @@ -159,9 +158,8 @@ public static InternetExplorerDriverService CreateDefaultService()
/// <returns>A InternetExplorerDriverService that implements default settings.</returns>
public static InternetExplorerDriverService CreateDefaultService(InternetExplorerOptions options)
{
string serviceDirectory = DriverService.FindDriverServiceExecutable(InternetExplorerDriverServiceFileName, InternetExplorerDriverDownloadUrl);
InternetExplorerDriverService service = CreateDefaultService(serviceDirectory);
return DriverFinder.VerifyDriverServicePath(service, options) as InternetExplorerDriverService;
string fullServicePath = DriverFinder.FullPath(options);
return CreateDefaultService(Path.GetDirectoryName(fullServicePath), Path.GetFileName(fullServicePath));
}

/// <summary>
Expand All @@ -171,6 +169,11 @@ public static InternetExplorerDriverService CreateDefaultService(InternetExplore
/// <returns>A InternetExplorerDriverService using a random port.</returns>
public static InternetExplorerDriverService CreateDefaultService(string driverPath)
{
if (Path.GetFileName(driverPath) == InternetExplorerDriverServiceFileName)
{
driverPath = Path.GetDirectoryName(driverPath);
}

return CreateDefaultService(driverPath, InternetExplorerDriverServiceFileName);
}

Expand Down
Loading

0 comments on commit 6a48692

Please sign in to comment.