Skip to content

Commit

Permalink
Add support for the new MicrosoftEdge.
Browse files Browse the repository at this point in the history
Extracting Chrome into a separate Chromium package since the new Edge
is also Chromium-based. Add the ability for EdgeDriver to launch
the new MicrosoftEdge using MSEdgeDriver without breaking any existing
Edge tests.

Signed-off-by: Jim Evans <james.h.evans.jr@gmail.com>
  • Loading branch information
loly89 authored and jimevans committed Jun 3, 2019
1 parent 7e73e8c commit 251cd38
Show file tree
Hide file tree
Showing 45 changed files with 1,465 additions and 1,028 deletions.
122 changes: 7 additions & 115 deletions dotnet/src/webdriver/Chrome/ChromeDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

using System;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium.Chromium;
using System.Collections.Generic;

namespace OpenQA.Selenium.Chrome
Expand Down Expand Up @@ -55,24 +56,14 @@ namespace OpenQA.Selenium.Chrome
/// }
/// </code>
/// </example>
public class ChromeDriver : RemoteWebDriver
public class ChromeDriver : ChromiumDriver
{

/// <summary>
/// Accept untrusted SSL Certificates
/// Initializes a new instance of the <see cref="ChromeDriver"/> class.
/// </summary>
public static readonly bool AcceptUntrustedCertificates = true;

private const string GetNetworkConditionsCommand = "getNetworkConditions";
private const string SetNetworkConditionsCommand = "setNetworkConditions";
private const string DeleteNetworkConditionsCommand = "deleteNetworkConditions";
private const string SendChromeCommand = "sendChromeCommand";
private const string SendChromeCommandWithResult = "sendChromeCommandWithResult";

/// <summary>
/// Initializes a new instance of the <see cref="ChromeDriver"/> class.
/// </summary>
public ChromeDriver()
: this(new ChromeOptions())
public ChromeDriver()
: this(new ChromeOptions())
{
}

Expand Down Expand Up @@ -145,108 +136,9 @@ public ChromeDriver(ChromeDriverService service, ChromeOptions options)
/// <param name="options">The <see cref="ChromeOptions"/> to be used with the Chrome driver.</param>
/// <param name="commandTimeout">The maximum amount of time to wait for each command.</param>
public ChromeDriver(ChromeDriverService service, ChromeOptions options, TimeSpan commandTimeout)
: base(new DriverServiceCommandExecutor(service, commandTimeout), ConvertOptionsToCapabilities(options))
{
// Add the custom commands unique to Chrome
this.AddCustomChromeCommand(GetNetworkConditionsCommand, CommandInfo.GetCommand, "/session/{sessionId}/chromium/network_conditions");
this.AddCustomChromeCommand(SetNetworkConditionsCommand, CommandInfo.PostCommand, "/session/{sessionId}/chromium/network_conditions");
this.AddCustomChromeCommand(DeleteNetworkConditionsCommand, CommandInfo.DeleteCommand, "/session/{sessionId}/chromium/network_conditions");
this.AddCustomChromeCommand(SendChromeCommand, CommandInfo.PostCommand, "/session/{sessionId}/chromium/send_command");
this.AddCustomChromeCommand(SendChromeCommandWithResult, CommandInfo.PostCommand, "/session/{sessionId}/chromium/send_command_and_get_result");
}

/// <summary>
/// Gets or sets the <see cref="IFileDetector"/> responsible for detecting
/// sequences of keystrokes representing file paths and names.
/// </summary>
/// <remarks>The Chrome driver does not allow a file detector to be set,
/// as the server component of the Chrome driver (ChromeDriver.exe) only
/// allows uploads from the local computer environment. Attempting to set
/// this property has no effect, but does not throw an exception. If you
/// are attempting to run the Chrome driver remotely, use <see cref="RemoteWebDriver"/>
/// in conjunction with a standalone WebDriver server.</remarks>
public override IFileDetector FileDetector
: base(service, options, commandTimeout)
{
get { return base.FileDetector; }
set { }
}

/// <summary>
/// Gets or sets the network condition emulation for Chrome.
/// </summary>
public ChromeNetworkConditions NetworkConditions
{
get
{
Response response = this.Execute(GetNetworkConditionsCommand, null);
return ChromeNetworkConditions.FromDictionary(response.Value as Dictionary<string, object>);
}

set
{
if (value == null)
{
throw new ArgumentNullException("value", "value must not be null");
}

Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters["network_conditions"] = value.ToDictionary();
this.Execute(SetNetworkConditionsCommand, parameters);
}
}

/// <summary>
/// Executes a custom Chrome command.
/// </summary>
/// <param name="commandName">Name of the command to execute.</param>
/// <param name="commandParameters">Parameters of the command to execute.</param>
public void ExecuteChromeCommand(string commandName, Dictionary<string, object> commandParameters)
{
if (commandName == null)
{
throw new ArgumentNullException("commandName", "commandName must not be null");
}

Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters["cmd"] = commandName;
parameters["params"] = commandParameters;
this.Execute(SendChromeCommand, parameters);
}

/// <summary>
/// Executes a custom Chrome command that returns a result.
/// </summary>
/// <param name="commandName">Name of the command to execute.</param>
/// <param name="commandParameters">Parameters of the command to execute.</param>
/// <returns>The JSON return value of the Chrome command, converted to a .NET object.</returns>
public object ExecuteChromeCommandWithResult(string commandName, Dictionary<string, object> commandParameters)
{
if (commandName == null)
{
throw new ArgumentNullException("commandName", "commandName must not be null");
}

Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters["cmd"] = commandName;
parameters["params"] = commandParameters;
Response response = this.Execute(SendChromeCommandWithResult, parameters);
return response.Value;
}

private static ICapabilities ConvertOptionsToCapabilities(ChromeOptions options)
{
if (options == null)
{
throw new ArgumentNullException("options", "options must not be null");
}

return options.ToCapabilities();
}

private void AddCustomChromeCommand(string commandName, string method, string resourcePath)
{
CommandInfo commandInfoToAdd = new CommandInfo(method, resourcePath);
this.CommandExecutor.CommandInfoRepository.TryAddCommand(commandName, commandInfoToAdd);
}
}
}
178 changes: 7 additions & 171 deletions dotnet/src/webdriver/Chrome/ChromeDriverService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,19 @@
using System.Globalization;
using System.Text;
using OpenQA.Selenium.Internal;
using OpenQA.Selenium.Chromium;

namespace OpenQA.Selenium.Chrome
{
/// <summary>
/// Exposes the service provided by the native ChromeDriver executable.
/// </summary>
public sealed class ChromeDriverService : DriverService
public sealed class ChromeDriverService : ChromiumDriverService
{
private const string DefaultChromeDriverServiceExecutableName = "chromedriver";

private static readonly Uri ChromeDriverDownloadUrl = new Uri("http://chromedriver.storage.googleapis.com/index.html");
private string logPath = string.Empty;
private string urlPathPrefix = string.Empty;
private string portServerAddress = string.Empty;
private string whitelistedIpAddresses = string.Empty;
private int adbPort = -1;
private bool enableVerboseLogging;
private bool enableAppendLog;


/// <summary>
/// Initializes a new instance of the <see cref="ChromeDriverService"/> class.
Expand All @@ -46,127 +41,8 @@ public sealed class ChromeDriverService : DriverService
/// <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, port, executableFileName, ChromeDriverDownloadUrl)
{
}

/// <summary>
/// Gets or sets the location of the log file written to by the ChromeDriver executable.
/// </summary>
public string LogPath
{
get { return this.logPath; }
set { this.logPath = value; }
}

/// <summary>
/// Gets or sets the base URL path prefix for commands (e.g., "wd/url").
/// </summary>
public string UrlPathPrefix
{
get { return this.urlPathPrefix; }
set { this.urlPathPrefix = value; }
}

/// <summary>
/// Gets or sets the address of a server to contact for reserving a port.
/// </summary>
public string PortServerAddress
{
get { return this.portServerAddress; }
set { this.portServerAddress = value; }
}

/// <summary>
/// Gets or sets the port on which the Android Debug Bridge is listening for commands.
/// </summary>
public int AndroidDebugBridgePort
: base(executablePath, executableFileName, port, ChromeDriverDownloadUrl)
{
get { return this.adbPort; }
set { this.adbPort = value; }
}

/// <summary>
/// Gets or sets a value indicating whether to enable verbose logging for the ChromeDriver executable.
/// Defaults to <see langword="false"/>.
/// </summary>
public bool EnableVerboseLogging
{
get { return this.enableVerboseLogging; }
set { this.enableVerboseLogging = value; }
}

/// <summary>
/// Gets or sets a value indicating whether to enable appending to an existing ChromeDriver log file.
/// Defaults to <see langword="false"/>.
/// </summary>
public bool EnableAppendLog
{
get { return this.enableAppendLog; }
set { this.enableAppendLog = value; }
}

/// <summary>
/// Gets or sets the comma-delimited list of IP addresses that are approved to
/// connect to this instance of the Chrome driver. Defaults to an empty string,
/// which means only the local loopback address can connect.
/// </summary>
public string WhitelistedIPAddresses
{
get { return this.whitelistedIpAddresses; }
set { this.whitelistedIpAddresses = value; }
}

/// <summary>
/// Gets the command-line arguments for the driver service.
/// </summary>
protected override string CommandLineArguments
{
get
{
StringBuilder argsBuilder = new StringBuilder(base.CommandLineArguments);
if (this.adbPort > 0)
{
argsBuilder.AppendFormat(CultureInfo.InvariantCulture, " --adb-port={0}", this.adbPort);
}

if (this.SuppressInitialDiagnosticInformation)
{
argsBuilder.Append(" --silent");
}

if (this.enableVerboseLogging)
{
argsBuilder.Append(" --verbose");
}

if (this.enableAppendLog)
{
argsBuilder.Append(" --append-log");
}

if (!string.IsNullOrEmpty(this.logPath))
{
argsBuilder.AppendFormat(CultureInfo.InvariantCulture, " --log-path=\"{0}\"", this.logPath);
}

if (!string.IsNullOrEmpty(this.urlPathPrefix))
{
argsBuilder.AppendFormat(CultureInfo.InvariantCulture, " --url-base={0}", this.urlPathPrefix);
}

if (!string.IsNullOrEmpty(this.portServerAddress))
{
argsBuilder.AppendFormat(CultureInfo.InvariantCulture, " --port-server={0}", this.portServerAddress);
}

if (!string.IsNullOrEmpty(this.whitelistedIpAddresses))
{
argsBuilder.Append(string.Format(CultureInfo.InvariantCulture, " -whitelisted-ips={0}", this.whitelistedIpAddresses));
}

return argsBuilder.ToString();
}
}

/// <summary>
Expand All @@ -175,7 +51,8 @@ protected override string CommandLineArguments
/// <returns>A ChromeDriverService that implements default settings.</returns>
public static ChromeDriverService CreateDefaultService()
{
string serviceDirectory = DriverService.FindDriverServiceExecutable(ChromeDriverServiceFileName(), ChromeDriverDownloadUrl);
string serviceDirectory = DriverService.FindDriverServiceExecutable(ChromiumDriverServiceFileName(DefaultChromeDriverServiceExecutableName),
ChromeDriverDownloadUrl);
return CreateDefaultService(serviceDirectory);
}

Expand All @@ -186,7 +63,7 @@ public static ChromeDriverService CreateDefaultService()
/// <returns>A ChromeDriverService using a random port.</returns>
public static ChromeDriverService CreateDefaultService(string driverPath)
{
return CreateDefaultService(driverPath, ChromeDriverServiceFileName());
return CreateDefaultService(driverPath, ChromiumDriverServiceFileName(DefaultChromeDriverServiceExecutableName));
}

/// <summary>
Expand All @@ -200,46 +77,5 @@ public static ChromeDriverService CreateDefaultService(string driverPath, string
return new ChromeDriverService(driverPath, driverExecutableFileName, PortUtilities.FindFreePort());
}

/// <summary>
/// Returns the Chrome driver filename for the currently running platform
/// </summary>
/// <returns>The file name of the Chrome driver service executable.</returns>
private static string ChromeDriverServiceFileName()
{
string fileName = DefaultChromeDriverServiceExecutableName;

// 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 int PlatformMonoUnixValue = 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:
break;

// Don't handle the Xbox case. Let default handle it.
// case PlatformID.Xbox:
// break;
default:
if ((int)Environment.OSVersion.Platform == PlatformMonoUnixValue)
{
break;
}

throw new WebDriverException("Unsupported platform: " + Environment.OSVersion.Platform);
}

return fileName;
}
}
}

0 comments on commit 251cd38

Please sign in to comment.