Skip to content

[dotnet] Use Selenium Manager to locate drivers on PATH #12344

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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