Class WebSocketConnection
- Namespace
- WebDriverBiDi.Protocol
- Assembly
- WebDriverBiDi.dll
Represents a connection to a WebDriver BiDi remote end over a WebSocket.
public class WebSocketConnection : Connection, IAsyncDisposable
- Inheritance
-
WebSocketConnection
- Implements
- Inherited Members
Remarks
WebSocketConnection is the standard and recommended transport mechanism for WebDriver BiDi. It uses the ClientWebSocket class to communicate with the browser over the WebSocket protocol (ws:// or wss:// schemes).
When to use WebSocket connections:
- All standard automation scenarios (local or remote browsers)
- Containerized browser environments
- Cross-machine browser debugging
- Any browser supporting WebDriver BiDi (Chrome, Edge, Firefox)
Key characteristics:
- Universal browser support
- Network flexibility (local and remote)
- Low latency for local connections
- Automatic retry on startup (retries every 500ms within StartupTimeout; both each attempt and the pause between attempts are bounded by the remaining StartupTimeout, so neither a host that never answers nor one that refuses immediately can hold startup open past the timeout)
- Supports reconnection after calling StopAsync
- Configurable socket options (request headers, proxy, keep-alive interval, certificate validation) through an override of CreateClientWebSocket()
Most users will never create a WebSocketConnection directly. The BiDiDriver creates one automatically when constructed without a custom transport.
Constructors
WebSocketConnection()
Initializes a new instance of the WebSocketConnection class.
public WebSocketConnection()
Properties
ConnectionKind
Gets a value indicating the type of data transport used by this connection, in this case, a WebSocket connection.
public override ConnectionKind ConnectionKind { get; }
Property Value
IsConnectionOpen
Gets a value indicating whether the underlying WebSocket is open.
protected override bool IsConnectionOpen { get; }
Property Value
Remarks
A socket that is still connecting does not count as open, so IsActive stays false until the connection is established. A socket that has begun its close handshake still counts as open, because it can still receive the remote end's answer. Once the receive loop has reported that it ended, IsActive is false, whatever state the socket is left in.
Methods
ConnectWebSocketAsync(Uri, CancellationToken)
Asynchronously connects the underlying WebSocket of this connection to the remote end.
protected virtual Task ConnectWebSocketAsync(Uri websocketUri, CancellationToken cancellationToken)
Parameters
websocketUriUriThe URI of the WebSocket server to connect to.
cancellationTokenCancellationTokenA cancellation token that is canceled when the caller cancels, when the connection is stopped, or when the remaining StartupTimeout budget for this attempt elapses.
Returns
- Task
The task object representing the asynchronous operation.
Remarks
This method is protected virtual to allow test doubles to substitute the
connect operation, for example to simulate a remote end that never completes the handshake.
CreateClientWebSocket()
Creates the ClientWebSocket on which a connection attempt is made.
protected virtual ClientWebSocket CreateClientWebSocket()
Returns
- ClientWebSocket
A new ClientWebSocket that has not been connected.
Examples
public class AuthenticatedWebSocketConnection : WebSocketConnection
{
private readonly string accessToken;
public AuthenticatedWebSocketConnection(string accessToken)
{
this.accessToken = accessToken;
}
protected override ClientWebSocket CreateClientWebSocket()
{
ClientWebSocket socket = base.CreateClientWebSocket();
socket.Options.SetRequestHeader("Authorization", $"Bearer {this.accessToken}");
return socket;
}
}
Remarks
Override this method to configure the socket through Options before it
connects: for example, to add a request header that the remote end requires to authenticate the
connection, to route the connection through a proxy, to change the keep-alive interval, or to
validate the certificate of a wss endpoint that the operating system does not trust. Those
options can be set only before a socket connects, which is why they are applied here rather than
exposed as properties of the connection. Call the base implementation to obtain the socket, then
configure and return it.
StartAsync(string, CancellationToken) calls this method immediately before every session connects, including the first, and again after each connection attempt that the remote end refuses or that runs out of the StartupTimeout budget, because a socket whose connect did not succeed cannot be used again. A single start can therefore call it more than once. It is never called while the connection is being constructed, so an override may rely on state that its own constructor, or an object initializer, has assigned.
Return a new instance from every call. The connection owns each socket this method returns: it disposes a socket when it replaces it, and disposes the socket it holds when the connection itself is disposed. A socket shared between calls, or with other code, would be disposed out from under its other users.
DisposeAsyncCore()
Asynchronously releases the resources used by this Connection.
protected override ValueTask DisposeAsyncCore()
Returns
- ValueTask
A task that represents the asynchronous dispose operation.
ReadWebSocketDataAsync(ArraySegment<byte>, CancellationToken)
Asynchronously receives data from the underlying WebSocket of this connection.
protected virtual Task<WebSocketReceiveResult> ReadWebSocketDataAsync(ArraySegment<byte> buffer, CancellationToken cancellationToken)
Parameters
bufferArraySegment<byte>The buffer to receive the data into.
cancellationTokenCancellationTokenA cancellation token used to propagate notification that the operation should be canceled.
Returns
- Task<WebSocketReceiveResult>
A task representing the asynchronous operation, with a result containing the receive result.
ReceiveDataAsync()
Asynchronously receives data from the remote end of this connection.
protected override Task ReceiveDataAsync()
Returns
- Task
The task object representing the asynchronous operation.
ResolveConnectionString(string)
Resolves the connection string into the URI of the WebSocket server to connect to.
protected override void ResolveConnectionString(string connectionString)
Parameters
connectionStringstringThe connection string to interpret. It must be a valid WebSocket URL.
Remarks
Parsing the URL is what proves it is one, so this method keeps what it parsed for StartConnectionAsync(CancellationToken) rather than validating for a later parse to repeat. It is called from StartAsync(string, CancellationToken) before that method does anything that can take time, so a malformed URL is reported at once.
Exceptions
- ArgumentException
Thrown when
connectionStringis not a valid absolute URI, or does not have a WebSocket scheme.
SendConnectionDataAsync(ReadOnlyMemory<byte>, CancellationToken)
Asynchronously sends data to the underlying WebSocket of this connection.
protected override Task SendConnectionDataAsync(ReadOnlyMemory<byte> messageBuffer, CancellationToken cancellationToken = default)
Parameters
messageBufferReadOnlyMemory<byte>The buffer containing the data to be sent to the remote end of this connection via the WebSocket.
cancellationTokenCancellationTokenA cancellation token used to propagate notification that the operation should be canceled.
Returns
- Task
The task object representing the asynchronous operation.
Exceptions
- WebDriverBiDiConnectionException
Thrown when an exception is encountered sending data to the WebSocket.
SendWebSocketCloseFrameAsync(CancellationToken)
Asynchronously sends this end's Close frame to the remote WebSocket, beginning the close handshake.
protected virtual Task SendWebSocketCloseFrameAsync(CancellationToken cancellationToken)
Parameters
cancellationTokenCancellationTokenA cancellation token that is canceled when the caller of StopAsync(CancellationToken) cancels, or when ShutdownTimeout elapses.
Returns
- Task
The task object representing the asynchronous operation.
Remarks
StopConnectionAsync(CancellationToken) calls this method to send the frame when the socket is open, then waits, bounded by ShutdownTimeout, for the receive loop to observe the remote end's answer. By the time the returned task completes, the frame has been written and the socket has recorded that it was sent. The receive loop, for its part, does not end on the remote end's answer until the returned task has completed, so that it ends with the socket in the same state however quickly the answer arrives. This is the only step of the close that a derived connection can replace, and it is the only Close frame this end sends: the receive loop acknowledges a Close frame only when the remote end began the close.
This method is protected virtual to allow test doubles to observe the point at which the
frame has been sent, for example to act only once the handshake wait is certain to have begun.
StartConnectionAsync(CancellationToken)
Asynchronously opens the WebSocket to the remote end, retrying until the remote end accepts the connection or the startup budget is spent.
protected override Task StartConnectionAsync(CancellationToken cancellationToken)
Parameters
cancellationTokenCancellationTokenA cancellation token used to propagate notification that the operation should be canceled.
Returns
- Task
The task object representing the asynchronous operation.
Exceptions
- WebDriverBiDiTimeoutException
Thrown when the connection is not established within the startup timeout.
- OperationCanceledException
Thrown when
cancellationTokenis canceled.
StopConnectionAsync(CancellationToken)
Asynchronously performs the WebSocket close handshake with the remote end.
protected override Task StopConnectionAsync(CancellationToken cancellationToken)
Parameters
cancellationTokenCancellationTokenA cancellation token used to propagate notification that the operation should be canceled.
Returns
- Task
The task object representing the asynchronous operation.
Remarks
The handshake is performed here, before StopAsync(CancellationToken) cancels the connection, because cancelling the connection aborts a pending WebSocket receive rather than letting it observe the remote end's answer to the handshake.
WriteWebSocketDataAsync(ReadOnlyMemory<byte>, CancellationToken)
Asynchronously writes data to the underlying WebSocket of this connection.
protected virtual Task WriteWebSocketDataAsync(ReadOnlyMemory<byte> messageBuffer, CancellationToken cancellationToken = default)
Parameters
messageBufferReadOnlyMemory<byte>The data to write to the WebSocket.
cancellationTokenCancellationTokenA cancellation token used to propagate notification that the operation should be canceled.
Returns
- Task
A task representing the asynchronous operation.