From 36e141d149f1a00757f54a83e56df0b0001d084d Mon Sep 17 00:00:00 2001 From: Jim Evans Date: Wed, 11 Nov 2020 09:40:28 -0500 Subject: [PATCH] Allow user to specify DevTools Protocol verison in .NET This change introduces an overload to the `CreateDevToolsSession` method that will allow a user to request a specific version of the protocol to use instead of automatically detecting the version used by the browser being automated. While using this overload can in theory help a user avoid code changes with every browser update when their code relies on the concrete, browser-specific protocol domains, using this overload is still fraught with peril, and should be avoided in favor of the version-independent API the Selenium library provides. This change also cleans up some API details, removing, among other things, the `Start` method of the DevToolsSession object from the public-facing API. When the `CreateDevToolsSession` method is called, there is no need to start the session, as it is already started. --- .../src/webdriver/Chromium/ChromiumDriver.cs | 13 ++++++++++- .../src/webdriver/DevTools/DevToolsDomains.cs | 23 ++++++++----------- .../src/webdriver/DevTools/DevToolsSession.cs | 17 ++++++++++++-- .../webdriver/DevTools/IDevToolsSession.cs | 6 ----- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/dotnet/src/webdriver/Chromium/ChromiumDriver.cs b/dotnet/src/webdriver/Chromium/ChromiumDriver.cs index eb5f7b5812521..c7bc187102aaa 100644 --- a/dotnet/src/webdriver/Chromium/ChromiumDriver.cs +++ b/dotnet/src/webdriver/Chromium/ChromiumDriver.cs @@ -167,8 +167,19 @@ public object ExecuteChromeCommandWithResult(string commandName, Dictionary /// Creates a session to communicate with a browser using the Chromium Developer Tools debugging protocol. /// + /// The version of the Chromium Developer Tools protocol to use. Defaults to autodetect the protocol version. /// The active session to use to communicate with the Chromium Developer Tools debugging protocol. public DevToolsSession CreateDevToolsSession() + { + return CreateDevToolsSession(DevToolsSession.AutoDetectDevToolsProtocolVersion); + } + + /// + /// Creates a session to communicate with a browser using the Chromium Developer Tools debugging protocol. + /// + /// The version of the Chromium Developer Tools protocol to use. Defaults to autodetect the protocol version. + /// The active session to use to communicate with the Chromium Developer Tools debugging protocol. + public DevToolsSession CreateDevToolsSession(int devToolsProtocolVersion) { if (!this.Capabilities.HasCapability(this.optionsCapabilityName)) { @@ -190,7 +201,7 @@ public DevToolsSession CreateDevToolsSession() try { DevToolsSession session = new DevToolsSession(debuggerAddress); - session.Start().ConfigureAwait(false).GetAwaiter().GetResult(); + session.Start(devToolsProtocolVersion).ConfigureAwait(false).GetAwaiter().GetResult(); return session; } catch (Exception e) diff --git a/dotnet/src/webdriver/DevTools/DevToolsDomains.cs b/dotnet/src/webdriver/DevTools/DevToolsDomains.cs index a726b5d9481c9..fed33b3210d32 100644 --- a/dotnet/src/webdriver/DevTools/DevToolsDomains.cs +++ b/dotnet/src/webdriver/DevTools/DevToolsDomains.cs @@ -71,22 +71,22 @@ public abstract class DevToolsDomains /// /// Initializes the supplied DevTools session's domains for the specified browser version. /// - /// The object containing the browser version information. + /// The version of the DevTools Protocol to use. /// The for which to initialiize the domains. /// The object containing the version-specific domains. - public static DevToolsDomains InitializeDomains(DevToolsVersionInfo versionInfo, DevToolsSession session) + public static DevToolsDomains InitializeDomains(int protocolVersion, DevToolsSession session) { - return InitializeDomains(versionInfo, session, DefaultVersionRange); + return InitializeDomains(protocolVersion, session, DefaultVersionRange); } /// /// Initializes the supplied DevTools session's domains for the specified browser version within the specified number of versions. /// - /// The object containing the browser version information. + /// The version of the DevTools Protocol to use. /// The for which to initialiize the domains. /// The range of versions within which to match the provided version number. Defaults to 5 versions. /// The object containing the version-specific domains. - public static DevToolsDomains InitializeDomains(DevToolsVersionInfo versionInfo, DevToolsSession session, int versionRange) + public static DevToolsDomains InitializeDomains(int protocolVersion, DevToolsSession session, int versionRange) { if (versionRange < 0) { @@ -94,16 +94,11 @@ public static DevToolsDomains InitializeDomains(DevToolsVersionInfo versionInfo, } DevToolsDomains domains = null; - int browserMajorVersion = 0; - bool versionParsed = int.TryParse(versionInfo.BrowserMajorVersion, out browserMajorVersion); - if (versionParsed) + Type domainType = MatchDomainsVersion(protocolVersion, versionRange); + ConstructorInfo constructor = domainType.GetConstructor(new Type[] { typeof(DevToolsSession) }); + if (constructor != null) { - Type domainType = MatchDomainsVersion(browserMajorVersion, versionRange); - ConstructorInfo constructor = domainType.GetConstructor(new Type[] { typeof(DevToolsSession) }); - if (constructor != null) - { - domains = constructor.Invoke(new object[] { session }) as DevToolsDomains; - } + domains = constructor.Invoke(new object[] { session }) as DevToolsDomains; } return domains; diff --git a/dotnet/src/webdriver/DevTools/DevToolsSession.cs b/dotnet/src/webdriver/DevTools/DevToolsSession.cs index 62fa08af9e36b..edb18731c422b 100644 --- a/dotnet/src/webdriver/DevTools/DevToolsSession.cs +++ b/dotnet/src/webdriver/DevTools/DevToolsSession.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Concurrent; +using System.ComponentModel; using System.Globalization; using System.IO; using System.Net.Http; @@ -36,6 +37,8 @@ namespace OpenQA.Selenium.DevTools /// public class DevToolsSession : IDevToolsSession { + public const int AutoDetectDevToolsProtocolVersion = 0; + private readonly string debuggerEndpoint; private string websocketAddress; private readonly TimeSpan closeConnectionWaitTimeSpan = TimeSpan.FromSeconds(2); @@ -242,8 +245,9 @@ public T GetVersionSpecificDomains() where T: DevToolsSessionDomains /// /// Asynchronously starts the session. /// + /// The version of the protocol to use in communicating with the browswer. /// A task that represents the asynchronous operation. - public async Task Start() + internal async Task Start(int protocolVersion) { string debuggerUrl = string.Format(CultureInfo.InvariantCulture, "http://{0}", this.debuggerEndpoint); string rawVersionInfo = string.Empty; @@ -256,7 +260,16 @@ public async Task Start() var versionInfo = JsonConvert.DeserializeObject(rawVersionInfo); websocketAddress = versionInfo.WebSocketDebuggerUrl; - this.domains = DevToolsDomains.InitializeDomains(versionInfo, this); + if (protocolVersion == AutoDetectDevToolsProtocolVersion) + { + bool versionParsed = int.TryParse(versionInfo.BrowserMajorVersion, out protocolVersion); + if (!versionParsed) + { + throw new WebDriverException(string.Format(CultureInfo.InvariantCulture, "Unable to parse version number received from browser. Reported browser version string is '{0}'", versionInfo.Browser)); + } + } + + this.domains = DevToolsDomains.InitializeDomains(protocolVersion, this); string targetId = null; var targets = await this.domains.Target.GetTargets(); diff --git a/dotnet/src/webdriver/DevTools/IDevToolsSession.cs b/dotnet/src/webdriver/DevTools/IDevToolsSession.cs index e52a949753b99..682bbf6316911 100644 --- a/dotnet/src/webdriver/DevTools/IDevToolsSession.cs +++ b/dotnet/src/webdriver/DevTools/IDevToolsSession.cs @@ -85,11 +85,5 @@ Task SendCommand(TCommand command, /// to throw an exception if a response is not received; otherwise, . /// The command response object implementing the interface. Task SendCommand(string commandName, JToken @params, CancellationToken cancellationToken, int? millisecondsTimeout, bool throwExceptionIfResponseNotReceived); - - /// - /// Asynchronously starts the session. - /// - /// A task that represents the asynchronous operation. - Task Start(); } }