Table of Contents

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

ConnectionKind

IsConnectionOpen

Gets a value indicating whether the underlying WebSocket is open.

protected override bool IsConnectionOpen { get; }

Property Value

bool

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

websocketUri Uri

The URI of the WebSocket server to connect to.

cancellationToken CancellationToken

A 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

buffer ArraySegment<byte>

The buffer to receive the data into.

cancellationToken CancellationToken

A 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

connectionString string

The 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 connectionString is 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

messageBuffer ReadOnlyMemory<byte>

The buffer containing the data to be sent to the remote end of this connection via the WebSocket.

cancellationToken CancellationToken

A 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

cancellationToken CancellationToken

A 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

cancellationToken CancellationToken

A 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 cancellationToken is canceled.

StopConnectionAsync(CancellationToken)

Asynchronously performs the WebSocket close handshake with the remote end.

protected override Task StopConnectionAsync(CancellationToken cancellationToken)

Parameters

cancellationToken CancellationToken

A 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

messageBuffer ReadOnlyMemory<byte>

The data to write to the WebSocket.

cancellationToken CancellationToken

A cancellation token used to propagate notification that the operation should be canceled.

Returns

Task

A task representing the asynchronous operation.