diff --git a/dotnet/src/webdriver/DevTools/DevToolsCommandData.cs b/dotnet/src/webdriver/DevTools/DevToolsCommandData.cs
index 95e665fb634a3..cbc30ed42cc87 100644
--- a/dotnet/src/webdriver/DevTools/DevToolsCommandData.cs
+++ b/dotnet/src/webdriver/DevTools/DevToolsCommandData.cs
@@ -35,7 +35,7 @@ public class DevToolsCommandData
///
/// Initializes a new instance of the DevToolsCommandData class.
///
- /// The ID of the commmand execution.
+ /// The ID of the command execution.
/// The method name of the DevTools command.
/// The parameters of the DevTools command.
/// If is .
@@ -47,7 +47,7 @@ public DevToolsCommandData(long commandId, string commandName, JsonNode commandP
///
/// Initializes a new instance of the DevToolsCommandData class.
///
- /// The ID of the commmand execution.
+ /// The ID of the command execution.
/// The session ID of the current command execution.
/// The method name of the DevTools command.
/// The parameters of the DevTools command.
diff --git a/dotnet/src/webdriver/DevTools/DevToolsSession.cs b/dotnet/src/webdriver/DevTools/DevToolsSession.cs
index a11f4757776a3..aebbc46d9467f 100644
--- a/dotnet/src/webdriver/DevTools/DevToolsSession.cs
+++ b/dotnet/src/webdriver/DevTools/DevToolsSession.cs
@@ -27,11 +27,13 @@
using System.Threading;
using System.Threading.Tasks;
+#nullable enable
+
namespace OpenQA.Selenium.DevTools
{
///
/// Represents a WebSocket connection to a running DevTools instance that can be used to send
- /// commands and recieve events.
+ /// commands and receive events.
///
public class DevToolsSession : IDevToolsSession
{
@@ -42,20 +44,17 @@ public class DevToolsSession : IDevToolsSession
public const int AutoDetectDevToolsProtocolVersion = 0;
private readonly string debuggerEndpoint;
- private string websocketAddress;
private readonly TimeSpan openConnectionWaitTimeSpan = TimeSpan.FromSeconds(30);
private readonly TimeSpan closeConnectionWaitTimeSpan = TimeSpan.FromSeconds(2);
private bool isDisposed = false;
- private string attachedTargetId;
+ private string? attachedTargetId;
- private WebSocketConnection connection;
+ private WebSocketConnection? connection;
private ConcurrentDictionary pendingCommands = new ConcurrentDictionary();
private readonly BlockingCollection messageQueue = new BlockingCollection();
private readonly Task messageQueueMonitorTask;
private long currentCommandId = 0;
-
- private DevToolsDomains domains;
private readonly DevToolsOptions options;
private readonly static ILogger logger = Internal.Logging.Log.GetLogger();
@@ -72,7 +71,7 @@ public class DevToolsSession : IDevToolsSession
///
///
///
- ///
+ /// If is , or is or .
public DevToolsSession(string endpointAddress, DevToolsOptions options)
{
if (string.IsNullOrWhiteSpace(endpointAddress))
@@ -85,7 +84,7 @@ public DevToolsSession(string endpointAddress, DevToolsOptions options)
this.debuggerEndpoint = endpointAddress;
if (endpointAddress.StartsWith("ws", StringComparison.InvariantCultureIgnoreCase))
{
- this.websocketAddress = endpointAddress;
+ this.EndpointAddress = endpointAddress;
}
this.messageQueueMonitorTask = Task.Run(() => this.MonitorMessageQueue());
}
@@ -93,12 +92,12 @@ public DevToolsSession(string endpointAddress, DevToolsOptions options)
///
/// Event raised when the DevToolsSession logs informational messages.
///
- public event EventHandler LogMessage;
+ public event EventHandler? LogMessage;
///
/// Event raised an event notification is received from the DevTools session.
///
- public event EventHandler DevToolsEventReceived;
+ public event EventHandler? DevToolsEventReceived;
///
/// Gets or sets the time to wait for a command to complete. Default is 30 seconds.
@@ -108,17 +107,17 @@ public DevToolsSession(string endpointAddress, DevToolsOptions options)
///
/// Gets or sets the active session ID of the connection.
///
- public string ActiveSessionId { get; private set; }
+ public string? ActiveSessionId { get; private set; }
///
/// Gets the endpoint address of the session.
///
- public string EndpointAddress => this.websocketAddress;
+ public string? EndpointAddress { get; private set; }
///
/// Gets the version-independent domain implementation for this Developer Tools connection
///
- public DevToolsDomains Domains => this.domains;
+ public DevToolsDomains Domains { get; private set; } = null!; // TODO handle nullability for this
///
/// Gets the version-specific implementation of domains for this DevTools session.
@@ -128,11 +127,10 @@ public DevToolsSession(string endpointAddress, DevToolsOptions options)
/// The version-specific DevTools Protocol domain implementation.
public T GetVersionSpecificDomains() where T : DevToolsSessionDomains
{
- T versionSpecificDomains = this.domains.VersionSpecificDomains as T;
- if (versionSpecificDomains == null)
+ if (this.Domains.VersionSpecificDomains is not T versionSpecificDomains)
{
string errorTemplate = "The type is invalid for conversion. You requested domains of type '{0}', but the version-specific domains for this session are '{1}'";
- string exceptionMessage = string.Format(CultureInfo.InvariantCulture, errorTemplate, typeof(T).ToString(), this.domains.GetType().ToString());
+ string exceptionMessage = string.Format(CultureInfo.InvariantCulture, errorTemplate, typeof(T).ToString(), this.Domains.GetType().ToString());
throw new InvalidOperationException(exceptionMessage);
}
@@ -148,7 +146,7 @@ public T GetVersionSpecificDomains() where T : DevToolsSessionDomains
/// The execution timeout of the command in milliseconds.
/// to throw an exception if a response is not received; otherwise, .
/// The command response object implementing the interface.
- public async Task> SendCommand(TCommand command, CancellationToken cancellationToken = default(CancellationToken), int? millisecondsTimeout = null, bool throwExceptionIfResponseNotReceived = true)
+ public async Task?> SendCommand(TCommand command, CancellationToken cancellationToken = default, int? millisecondsTimeout = null, bool throwExceptionIfResponseNotReceived = true)
where TCommand : ICommand
{
if (command == null)
@@ -156,14 +154,15 @@ public T GetVersionSpecificDomains() where T : DevToolsSessionDomains
throw new ArgumentNullException(nameof(command));
}
- var result = await SendCommand(command.CommandName, JsonSerializer.SerializeToNode(command), cancellationToken, millisecondsTimeout, throwExceptionIfResponseNotReceived).ConfigureAwait(false);
+ JsonNode commandParameters = JsonSerializer.SerializeToNode(command) ?? throw new InvalidOperationException("Command serialized to \"null\".");
+ var result = await SendCommand(command.CommandName, commandParameters, cancellationToken, millisecondsTimeout, throwExceptionIfResponseNotReceived).ConfigureAwait(false);
if (result == null)
{
return null;
}
- if (!this.domains.VersionSpecificDomains.ResponseTypeMap.TryGetCommandResponseType(out Type commandResponseType))
+ if (!this.Domains.VersionSpecificDomains.ResponseTypeMap.TryGetCommandResponseType(out Type? commandResponseType))
{
throw new InvalidOperationException($"Type {command.GetType()} does not correspond to a known command response type.");
}
@@ -181,7 +180,7 @@ public T GetVersionSpecificDomains() where T : DevToolsSessionDomains
/// The execution timeout of the command in milliseconds.
/// to throw an exception if a response is not received; otherwise, .
/// The command response object implementing the interface.
- public async Task> SendCommand(TCommand command, string sessionId, CancellationToken cancellationToken = default(CancellationToken), int? millisecondsTimeout = null, bool throwExceptionIfResponseNotReceived = true)
+ public async Task?> SendCommand(TCommand command, string sessionId, CancellationToken cancellationToken = default, int? millisecondsTimeout = null, bool throwExceptionIfResponseNotReceived = true)
where TCommand : ICommand
{
if (command == null)
@@ -189,14 +188,15 @@ public T GetVersionSpecificDomains() where T : DevToolsSessionDomains
throw new ArgumentNullException(nameof(command));
}
- var result = await SendCommand(command.CommandName, sessionId, JsonSerializer.SerializeToNode(command), cancellationToken, millisecondsTimeout, throwExceptionIfResponseNotReceived).ConfigureAwait(false);
+ JsonNode commandParameters = JsonSerializer.SerializeToNode(command) ?? throw new InvalidOperationException("Command serialized to \"null\".");
+ var result = await SendCommand(command.CommandName, sessionId, commandParameters, cancellationToken, millisecondsTimeout, throwExceptionIfResponseNotReceived).ConfigureAwait(false);
if (result == null)
{
return null;
}
- if (!this.domains.VersionSpecificDomains.ResponseTypeMap.TryGetCommandResponseType(command, out Type commandResponseType))
+ if (!this.Domains.VersionSpecificDomains.ResponseTypeMap.TryGetCommandResponseType(command, out Type? commandResponseType))
{
throw new InvalidOperationException($"Type {typeof(TCommand)} does not correspond to a known command response type.");
}
@@ -214,7 +214,7 @@ public T GetVersionSpecificDomains() where T : DevToolsSessionDomains
/// The execution timeout of the command in milliseconds.
/// to throw an exception if a response is not received; otherwise, .
/// The command response object implementing the interface.
- public async Task SendCommand(TCommand command, CancellationToken cancellationToken = default(CancellationToken), int? millisecondsTimeout = null, bool throwExceptionIfResponseNotReceived = true)
+ public async Task SendCommand(TCommand command, CancellationToken cancellationToken = default, int? millisecondsTimeout = null, bool throwExceptionIfResponseNotReceived = true)
where TCommand : ICommand
where TCommandResponse : ICommandResponse
{
@@ -223,11 +223,12 @@ public T GetVersionSpecificDomains() where T : DevToolsSessionDomains
throw new ArgumentNullException(nameof(command));
}
- var result = await SendCommand(command.CommandName, JsonSerializer.SerializeToNode(command), cancellationToken, millisecondsTimeout, throwExceptionIfResponseNotReceived).ConfigureAwait(false);
+ JsonNode commandParameters = JsonSerializer.SerializeToNode(command) ?? throw new InvalidOperationException("Command serialized to \"null\".");
+ var result = await SendCommand(command.CommandName, commandParameters, cancellationToken, millisecondsTimeout, throwExceptionIfResponseNotReceived).ConfigureAwait(false);
if (result == null)
{
- return default(TCommandResponse);
+ return default;
}
return result.Value.Deserialize();
@@ -242,8 +243,7 @@ public T GetVersionSpecificDomains() where T : DevToolsSessionDomains
/// The execution timeout of the command in milliseconds.
/// to throw an exception if a response is not received; otherwise, .
/// The command response object implementing the interface.
- //[DebuggerStepThrough]
- public async Task SendCommand(string commandName, JsonNode commandParameters, CancellationToken cancellationToken = default(CancellationToken), int? millisecondsTimeout = null, bool throwExceptionIfResponseNotReceived = true)
+ public async Task SendCommand(string commandName, JsonNode commandParameters, CancellationToken cancellationToken = default, int? millisecondsTimeout = null, bool throwExceptionIfResponseNotReceived = true)
{
if (this.attachedTargetId == null)
{
@@ -264,13 +264,9 @@ public T GetVersionSpecificDomains() where T : DevToolsSessionDomains
/// The execution timeout of the command in milliseconds.
/// to throw an exception if a response is not received; otherwise, .
/// The command response object implementing the interface.
- //[DebuggerStepThrough]
- public async Task SendCommand(string commandName, string sessionId, JsonNode commandParameters, CancellationToken cancellationToken = default(CancellationToken), int? millisecondsTimeout = null, bool throwExceptionIfResponseNotReceived = true)
+ public async Task SendCommand(string commandName, string? sessionId, JsonNode commandParameters, CancellationToken cancellationToken = default, int? millisecondsTimeout = null, bool throwExceptionIfResponseNotReceived = true)
{
- if (millisecondsTimeout.HasValue == false)
- {
- millisecondsTimeout = Convert.ToInt32(CommandTimeout.TotalMilliseconds);
- }
+ millisecondsTimeout ??= Convert.ToInt32(CommandTimeout.TotalMilliseconds);
var message = new DevToolsCommandData(Interlocked.Increment(ref this.currentCommandId), sessionId, commandName, commandParameters);
@@ -294,7 +290,7 @@ public T GetVersionSpecificDomains() where T : DevToolsSessionDomains
throw new InvalidOperationException($"A command response was not received: {commandName}, timeout: {millisecondsTimeout.Value}ms");
}
- if (this.pendingCommands.TryRemove(message.CommandId, out DevToolsCommandData modified))
+ if (this.pendingCommands.TryRemove(message.CommandId, out DevToolsCommandData? modified))
{
if (modified.IsError)
{
@@ -307,7 +303,7 @@ public T GetVersionSpecificDomains() where T : DevToolsSessionDomains
exceptionMessage = $"{exceptionMessage} - {errorData}";
}
- LogTrace("Recieved Error Response {0}: {1} {2}", modified.CommandId, message, errorData);
+ LogTrace("Received Error Response {0}: {1} {2}", modified.CommandId, message, errorData);
throw new CommandResponseException(exceptionMessage)
{
Code = modified.Result.TryGetProperty("code", out var code) ? code.GetInt64() : -1
@@ -331,6 +327,7 @@ public T GetVersionSpecificDomains() where T : DevToolsSessionDomains
public void Dispose()
{
this.Dispose(true);
+ GC.SuppressFinalize(this);
}
///
@@ -339,16 +336,17 @@ public void Dispose()
/// A task that represents the asynchronous operation.
internal async Task StartSession()
{
- var requestedProtocolVersion = options.ProtocolVersion.HasValue ? options.ProtocolVersion.Value : AutoDetectDevToolsProtocolVersion;
+ int requestedProtocolVersion = options.ProtocolVersion ?? AutoDetectDevToolsProtocolVersion;
int protocolVersion = await InitializeProtocol(requestedProtocolVersion).ConfigureAwait(false);
- this.domains = DevToolsDomains.InitializeDomains(protocolVersion, this);
+ this.Domains = DevToolsDomains.InitializeDomains(protocolVersion, this);
+
await this.InitializeSocketConnection().ConfigureAwait(false);
await this.InitializeSession().ConfigureAwait(false);
try
{
// Wrap this in a try-catch, because it's not the end of the
// world if clearing the log doesn't work.
- await this.domains.Log.Clear().ConfigureAwait(false);
+ await this.Domains.Log.Clear().ConfigureAwait(false);
LogTrace("Log cleared.", this.attachedTargetId);
}
catch (WebDriverException)
@@ -360,14 +358,14 @@ internal async Task StartSession()
/// Asynchronously stops the session.
///
/// to manually detach the session
- /// from its attached target; otherswise .
+ /// from its attached target; otherwise .
/// A task that represents the asynchronous operation.
internal async Task StopSession(bool manualDetach)
{
if (this.attachedTargetId != null)
{
this.Domains.Target.TargetDetached -= this.OnTargetDetached;
- string sessionId = this.ActiveSessionId;
+ string? sessionId = this.ActiveSessionId;
this.ActiveSessionId = null;
if (manualDetach)
{
@@ -400,23 +398,22 @@ protected void Dispose(bool disposing)
private async Task InitializeProtocol(int requestedProtocolVersion)
{
int protocolVersion = requestedProtocolVersion;
- if (this.websocketAddress == null)
+ if (this.EndpointAddress == null)
{
string debuggerUrl = string.Format(CultureInfo.InvariantCulture, "http://{0}", this.debuggerEndpoint);
- string rawVersionInfo = string.Empty;
+ string rawVersionInfo;
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(debuggerUrl);
rawVersionInfo = await client.GetStringAsync("/json/version").ConfigureAwait(false);
}
- var versionInfo = JsonSerializer.Deserialize(rawVersionInfo);
- this.websocketAddress = versionInfo.WebSocketDebuggerUrl;
+ var versionInfo = JsonSerializer.Deserialize(rawVersionInfo) ?? throw new JsonException("/json/version endpoint returned null response");
+ this.EndpointAddress = versionInfo.WebSocketDebuggerUrl;
if (requestedProtocolVersion == AutoDetectDevToolsProtocolVersion)
{
- bool versionParsed = int.TryParse(versionInfo.BrowserMajorVersion, out protocolVersion);
- if (!versionParsed)
+ if (!int.TryParse(versionInfo.BrowserMajorVersion, out protocolVersion))
{
throw new WebDriverException(string.Format(CultureInfo.InvariantCulture, "Unable to parse version number received from browser. Reported browser version string is '{0}'", versionInfo.Browser));
}
@@ -443,7 +440,7 @@ private async Task InitializeSession()
// that when getting the available targets, we won't
// recursively try to call InitializeSession.
this.attachedTargetId = "";
- var targets = await this.domains.Target.GetTargets().ConfigureAwait(false);
+ var targets = await this.Domains.Target.GetTargets().ConfigureAwait(false);
foreach (var target in targets)
{
if (target.Type == "page")
@@ -458,30 +455,30 @@ private async Task InitializeSession()
if (this.attachedTargetId == "")
{
this.attachedTargetId = null;
- throw new WebDriverException("Unable to find target to attach to, no taargets of type 'page' available");
+ throw new WebDriverException("Unable to find target to attach to, no targets of type 'page' available");
}
- string sessionId = await this.domains.Target.AttachToTarget(this.attachedTargetId).ConfigureAwait(false);
+ string sessionId = await this.Domains.Target.AttachToTarget(this.attachedTargetId).ConfigureAwait(false);
LogTrace("Target ID {0} attached. Active session ID: {1}", this.attachedTargetId, sessionId);
this.ActiveSessionId = sessionId;
- await this.domains.Target.SetAutoAttach().ConfigureAwait(false);
+ await this.Domains.Target.SetAutoAttach().ConfigureAwait(false);
LogTrace("AutoAttach is set.", this.attachedTargetId);
- // The Target domain needs to send Sessionless commands! Else the waitForDebugger setting in setAutoAttach wont work!
+ // The Target domain needs to send Session-less commands! Else the waitForDebugger setting in setAutoAttach wont work!
if (options.WaitForDebuggerOnStart)
{
- var setAutoAttachCommand = domains.Target.CreateSetAutoAttachCommand(true);
- var setDiscoverTargetsCommand = domains.Target.CreateDiscoverTargetsCommand();
+ var setAutoAttachCommand = Domains.Target.CreateSetAutoAttachCommand(true);
+ var setDiscoverTargetsCommand = Domains.Target.CreateDiscoverTargetsCommand();
- await SendCommand(setAutoAttachCommand, string.Empty, default(CancellationToken), null, true).ConfigureAwait(false);
- await SendCommand(setDiscoverTargetsCommand, string.Empty, default(CancellationToken), null, true).ConfigureAwait(false);
+ await SendCommand(setAutoAttachCommand, string.Empty, default, null, true).ConfigureAwait(false);
+ await SendCommand(setDiscoverTargetsCommand, string.Empty, default, null, true).ConfigureAwait(false);
}
- this.domains.Target.TargetDetached += this.OnTargetDetached;
+ this.Domains.Target.TargetDetached += this.OnTargetDetached;
}
- private void OnTargetDetached(object sender, TargetDetachedEventArgs e)
+ private void OnTargetDetached(object? sender, TargetDetachedEventArgs e)
{
if (e.SessionId == this.ActiveSessionId && e.TargetId == this.attachedTargetId)
{
@@ -494,7 +491,7 @@ private async Task InitializeSocketConnection()
LogTrace("Creating WebSocket");
this.connection = new WebSocketConnection(this.openConnectionWaitTimeSpan, this.closeConnectionWaitTimeSpan);
connection.DataReceived += OnConnectionDataReceived;
- await connection.Start(this.websocketAddress).ConfigureAwait(false);
+ await connection.Start(this.EndpointAddress).ConfigureAwait(false);
LogTrace("WebSocket created");
}
@@ -504,18 +501,18 @@ private async Task TerminateSocketConnection()
if (this.connection != null && this.connection.IsActive)
{
await this.connection.Stop().ConfigureAwait(false);
- await this.ShutdownMessageQueue().ConfigureAwait(false);
+ await this.ShutdownMessageQueue(this.connection).ConfigureAwait(false);
}
LogTrace("WebSocket closed");
}
- private async Task ShutdownMessageQueue()
+ private async Task ShutdownMessageQueue(WebSocketConnection connection)
{
- // THe WebSockect connection is always closed before this method
+ // THe WebSocket connection is always closed before this method
// is called, so there will eventually be no more data written
// into the message queue, meaning this loop should be guaranteed
// to complete.
- while (this.connection.IsActive)
+ while (connection.IsActive)
{
await Task.Delay(TimeSpan.FromMilliseconds(10));
}
@@ -534,7 +531,7 @@ private void MonitorMessageQueue()
// in the IEnumerable, meaning the foreach loop will terminate gracefully.
foreach (string message in this.messageQueue.GetConsumingEnumerable())
{
- // Don't breake entire thread in case of unsuccessful message,
+ // Don't break entire thread in case of unsuccessful message,
// and give a chance for the next message in queue to be processed
try
{
@@ -544,10 +541,10 @@ private void MonitorMessageQueue()
{
if (logger.IsEnabled(LogEventLevel.Error))
{
- logger.Error($"Unexpected error occured while processing message: {ex}");
+ logger.Error($"Unexpected error occurred while processing message: {ex}");
}
- LogError("Unexpected error occured while processing message: {0}", ex);
+ LogError("Unexpected error occurred while processing message: {0}", ex);
}
}
}
@@ -569,8 +566,7 @@ private void ProcessMessage(string message)
{
long commandId = idProperty.GetInt64();
- DevToolsCommandData commandInfo;
- if (this.pendingCommands.TryGetValue(commandId, out commandInfo))
+ if (this.pendingCommands.TryGetValue(commandId, out DevToolsCommandData? commandInfo))
{
if (messageObject.TryGetProperty("error", out var errorProperty))
{
@@ -580,7 +576,7 @@ private void ProcessMessage(string message)
else
{
commandInfo.Result = messageObject.GetProperty("result");
- LogTrace("Recieved Response {0}: {1}", commandId, commandInfo.Result.ToString());
+ LogTrace("Received Response {0}: {1}", commandId, commandInfo.Result.ToString());
}
commandInfo.SyncEvent.Set();
@@ -589,10 +585,10 @@ private void ProcessMessage(string message)
{
if (logger.IsEnabled(LogEventLevel.Error))
{
- logger.Error($"Recieved Unknown Response {commandId}: {message}");
+ logger.Error($"Received Unknown Response {commandId}: {message}");
}
- LogError("Recieved Unknown Response {0}: {1}", commandId, message);
+ LogError("Received Unknown Response {0}: {1}", commandId, message);
}
return;
@@ -600,11 +596,11 @@ private void ProcessMessage(string message)
if (messageObject.TryGetProperty("method", out var methodProperty))
{
- var method = methodProperty.GetString();
+ var method = methodProperty.GetString() ?? throw new InvalidOperationException("CDP message contained \"method\" property with a value of \"null\".");
var methodParts = method.Split(new char[] { '.' }, 2);
var eventData = messageObject.GetProperty("params");
- LogTrace("Recieved Event {0}: {1}", method, eventData.ToString());
+ LogTrace("Received Event {0}: {1}", method, eventData.ToString());
// Dispatch the event on a new thread so that any event handlers
// responding to the event will not block this thread from processing
@@ -621,7 +617,7 @@ private void ProcessMessage(string message)
{
if (logger.IsEnabled(LogEventLevel.Warn))
{
- logger.Warn($"CDP VNT ^^ Unhandled error occured in event handler of '{method}' method. {ex}");
+ logger.Warn($"CDP VNT ^^ Unhandled error occurred in event handler of '{method}' method. {ex}");
}
throw;
@@ -631,7 +627,7 @@ private void ProcessMessage(string message)
return;
}
- LogTrace("Recieved Other: {0}", message);
+ LogTrace("Received Other: {0}", message);
}
private void OnDevToolsEventReceived(DevToolsEventReceivedEventArgs e)
@@ -642,12 +638,12 @@ private void OnDevToolsEventReceived(DevToolsEventReceivedEventArgs e)
}
}
- private void OnConnectionDataReceived(object sender, WebSocketConnectionDataReceivedEventArgs e)
+ private void OnConnectionDataReceived(object? sender, WebSocketConnectionDataReceivedEventArgs e)
{
this.messageQueue.Add(e.Data);
}
- private void LogTrace(string message, params object[] args)
+ private void LogTrace(string message, params object?[] args)
{
if (LogMessage != null)
{
@@ -655,7 +651,7 @@ private void LogTrace(string message, params object[] args)
}
}
- private void LogError(string message, params object[] args)
+ private void LogError(string message, params object?[] args)
{
if (LogMessage != null)
{
diff --git a/dotnet/src/webdriver/DevTools/DevToolsSessionLogMessageEventArgs.cs b/dotnet/src/webdriver/DevTools/DevToolsSessionLogMessageEventArgs.cs
index c2e233a695e2a..f11553a7eabdb 100644
--- a/dotnet/src/webdriver/DevTools/DevToolsSessionLogMessageEventArgs.cs
+++ b/dotnet/src/webdriver/DevTools/DevToolsSessionLogMessageEventArgs.cs
@@ -50,7 +50,7 @@ public class DevToolsSessionLogMessageEventArgs : EventArgs
/// The level of the log message.
/// The content of the log message.
/// Arguments to be substituted when the message is formatted.
- public DevToolsSessionLogMessageEventArgs(DevToolsSessionLogLevel level, string message, params object[] args)
+ public DevToolsSessionLogMessageEventArgs(DevToolsSessionLogLevel level, string message, params object?[] args)
{
Level = level;
Message = string.Format(message, args);
diff --git a/dotnet/src/webdriver/DevTools/DevToolsVersionInfo.cs b/dotnet/src/webdriver/DevTools/DevToolsVersionInfo.cs
index 9b0314577c8e7..347ded9d45b1b 100644
--- a/dotnet/src/webdriver/DevTools/DevToolsVersionInfo.cs
+++ b/dotnet/src/webdriver/DevTools/DevToolsVersionInfo.cs
@@ -88,8 +88,7 @@ public string V8VersionNumber
get
{
//Get the v8 version
- var v8VersionRegex = new Regex(@"^(\d+)\.(\d+)\.(\d+)(\.\d+.*)?");
- var v8VersionMatch = v8VersionRegex.Match(V8Version);
+ var v8VersionMatch = Regex.Match(V8Version, @"^(\d+)\.(\d+)\.(\d+)(\.\d+.*)?");
if (v8VersionMatch.Success == false || v8VersionMatch.Groups.Count < 4)
{
throw new InvalidOperationException($"Unable to determine v8 version number from v8 version string ({V8Version})");
@@ -115,8 +114,7 @@ public string WebKitVersionHash
get
{
//Get the webkit version hash.
- var webkitVersionRegex = new Regex(@"\s\(@(\b[0-9a-f]{5,40}\b)");
- var webkitVersionMatch = webkitVersionRegex.Match(WebKitVersion);
+ var webkitVersionMatch = Regex.Match(WebKitVersion, @"\s\(@(\b[0-9a-f]{5,40}\b)");
if (webkitVersionMatch.Success == false || webkitVersionMatch.Groups.Count != 2)
{
throw new InvalidOperationException($"Unable to determine webkit version hash from webkit version string ({WebKitVersion})");
diff --git a/dotnet/src/webdriver/DevTools/IDevToolsSession.cs b/dotnet/src/webdriver/DevTools/IDevToolsSession.cs
index 3837d38485523..9671da3d39780 100644
--- a/dotnet/src/webdriver/DevTools/IDevToolsSession.cs
+++ b/dotnet/src/webdriver/DevTools/IDevToolsSession.cs
@@ -23,6 +23,8 @@
using System.Threading;
using System.Threading.Tasks;
+#nullable enable
+
namespace OpenQA.Selenium.DevTools
{
///
@@ -34,18 +36,18 @@ public interface IDevToolsSession : IDisposable
///
/// Event raised when the DevToolsSession logs informational messages.
///
- event EventHandler LogMessage;
+ event EventHandler? LogMessage;
///
/// Event raised an event notification is received from the DevTools session.
///
- event EventHandler DevToolsEventReceived;
+ event EventHandler? DevToolsEventReceived;
///
- /// Gets the domains that are valid for the specfied version of Developer Tools connection.
+ /// Gets the domains that are valid for the specified version of Developer Tools connection.
///
///
- /// A type specific to the version of Develoepr Tools with which to communicate.
+ /// A type specific to the version of Developer Tools with which to communicate.
///
/// The version-specific domains for this Developer Tools connection.
T GetVersionSpecificDomains() where T : DevToolsSessionDomains;
@@ -59,7 +61,7 @@ public interface IDevToolsSession : IDisposable
/// The execution timeout of the command in milliseconds.
/// to throw an exception if a response is not received; otherwise, .
/// The command response object implementing the interface.
- Task> SendCommand(TCommand command, CancellationToken cancellationToken, int? millisecondsTimeout, bool throwExceptionIfResponseNotReceived)
+ Task?> SendCommand(TCommand command, CancellationToken cancellationToken, int? millisecondsTimeout, bool throwExceptionIfResponseNotReceived)
where TCommand : ICommand;
///
@@ -72,7 +74,7 @@ Task> SendCommand(TCommand command, Cancell
/// The execution timeout of the command in milliseconds.
/// to throw an exception if a response is not received; otherwise, .
/// The command response object implementing the interface.
- Task SendCommand(TCommand command, CancellationToken cancellationToken, int? millisecondsTimeout, bool throwExceptionIfResponseNotReceived)
+ Task SendCommand(TCommand command, CancellationToken cancellationToken, int? millisecondsTimeout, bool throwExceptionIfResponseNotReceived)
where TCommand : ICommand
where TCommandResponse : ICommandResponse;