diff --git a/dotnet/src/webdriver/DriverService.cs b/dotnet/src/webdriver/DriverService.cs index 2770fc245f9b9..2da6a6aef7904 100644 --- a/dotnet/src/webdriver/DriverService.cs +++ b/dotnet/src/webdriver/DriverService.cs @@ -65,7 +65,23 @@ protected DriverService(string servicePath, int port, string driverServiceExecut string executablePath = Path.Combine(servicePath, driverServiceExecutableName); if (!File.Exists(executablePath)) { - throw new DriverServiceNotFoundException(string.Format(CultureInfo.InvariantCulture, "The file {0} does not exist. The driver can be downloaded at {1}", executablePath, driverServiceDownloadUrl)); + try + { + executablePath = SeleniumManager.DriverPath(driverServiceExecutableName); + } + catch (Exception e) + { + // No-op; entirely a fall-back feature + } + + if (File.Exists(executablePath)) + { + servicePath = Path.GetDirectoryName(executablePath); + } + else + { + throw new DriverServiceNotFoundException(string.Format(CultureInfo.InvariantCulture, "The file {0} does not exist. The driver can be downloaded at {1}", executablePath, driverServiceDownloadUrl)); + } } this.driverServicePath = servicePath; @@ -74,12 +90,12 @@ protected DriverService(string servicePath, int port, string driverServiceExecut } /// - /// Occurs when the driver process is starting. + /// Occurs when the driver process is starting. /// public event EventHandler DriverProcessStarting; /// - /// Occurs when the driver process has completely started. + /// Occurs when the driver process has completely started. /// public event EventHandler DriverProcessStarted; diff --git a/dotnet/src/webdriver/SeleniumManager.cs b/dotnet/src/webdriver/SeleniumManager.cs new file mode 100644 index 0000000000000..18ccbb820ef3c --- /dev/null +++ b/dotnet/src/webdriver/SeleniumManager.cs @@ -0,0 +1,146 @@ +// +// 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. +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Text; +using System.Threading; +using OpenQA.Selenium.Internal; + +namespace OpenQA.Selenium +{ + /// + /// Wrapper for the Selenium Manager binary. + /// + public static class SeleniumManager + { + private static string binary; + private static readonly List KnownDrivers = new List() { + "geckodriver.exe", + "chromedriver.exe" + }; + + /// + /// Determines the location of the correct driver. + /// + /// Which driver the service needs. + /// + /// The location of the driver. + /// + public static string DriverPath(string driverName) + { + if (!KnownDrivers.Contains(driverName)) + { + throw new WebDriverException("Unable to locate driver with name: " + driverName); + } + var binaryFile = Binary; + if (binaryFile == null) return null; + + var arguments = "--driver " + driverName.Replace(".exe", ""); + var output = RunCommand(binaryFile, arguments); + return output.Replace("INFO\t", "").TrimEnd(); + } + + /// + /// Gets the location of the correct Selenium Manager binary. + /// + private static string Binary + { + get + { + if (string.IsNullOrEmpty(binary)) + { + string folder = "windows"; + string extension = ".exe"; + + if (!Environment.OSVersion.Platform.ToString().StartsWith("Win")) + { + throw new WebDriverException("Selenium Manager only supports Windows in .NET at this time"); + } + + try + { + string name = "selenium-manager-" + folder; + using (Stream fileStream = ResourceUtilities.GetResourceStream(name, name)) + { + using (BinaryReader binReader = new BinaryReader(fileStream, Encoding.ASCII)) + { + byte[] fileBytes = binReader.ReadBytes((int)fileStream.Length); + string directoryName = string.Format(CultureInfo.InvariantCulture, "webdriver.{0}", + Guid.NewGuid().ToString("N")); + var path = Path.Combine(Path.GetTempPath(), directoryName + "/" + folder); + Directory.CreateDirectory(path); + var filePath = Path.Combine(path, "selenium-manager" + extension); + + using (BinaryWriter binWriter = new BinaryWriter(File.Open(filePath, FileMode.Create))) + { + binWriter.Flush(); + binWriter.Write(fileBytes); + } + binary = filePath; + } + } + } + catch (Exception ex) + { + throw new WebDriverException("Unable to obtain Selenium Manager", ex); + } + } + + return binary; + } + } + + /// + /// Executes a process with the given arguments. + /// + /// The path to the Selenium Manager. + /// The switches to be used by Selenium Manager. + /// + /// the standard output of the execution. + /// + private static string RunCommand(string fileName, string arguments) + { + Process process = new Process(); + process.StartInfo.FileName = fileName; + process.StartInfo.Arguments = arguments; + process.StartInfo.UseShellExecute = false; + process.StartInfo.RedirectStandardOutput = true; + + try + { + process.Start(); + } + catch (Exception ex) + { + throw new WebDriverException("Error starting process: " + process, ex); + } + + String output = process.StandardOutput.ReadToEnd(); + + if (!output.StartsWith("INFO")) { + throw new WebDriverException("Invalid response from process: " + process); + } + + return output; + } + } +} diff --git a/dotnet/src/webdriver/WebDriver.csproj b/dotnet/src/webdriver/WebDriver.csproj index f2c128b22c308..ab7a074a9da3e 100644 --- a/dotnet/src/webdriver/WebDriver.csproj +++ b/dotnet/src/webdriver/WebDriver.csproj @@ -117,6 +117,10 @@ False webdriver_prefs.json + + False + selenium-manager-windows + False get-attribute.js @@ -140,6 +144,10 @@ False webdriver_prefs.json + + False + selenium-manager-windows + False get-attribute.js