@@ -18,25 +18,26 @@ namespace PuppeteerSharp
1818 /// <summary>
1919 /// A connection handles the communication with a Chromium browser.
2020 /// </summary>
21- public class Connection : IDisposable , ICDPConnection
21+ public sealed class Connection : IDisposable , ICDPConnection
2222 {
23+ internal const int DefaultCommandTimeout = 180_000 ;
2324 private readonly ILogger _logger ;
2425 private readonly TaskQueue _callbackQueue = new ( ) ;
2526
2627 private readonly ConcurrentDictionary < int , MessageTask > _callbacks = new ( ) ;
2728 private readonly AsyncDictionaryHelper < string , CDPSession > _sessions = new ( "Session {0} not found" ) ;
28- private readonly List < string > _manuallyAttached = new ( ) ;
29+ private readonly List < string > _manuallyAttached = [ ] ;
2930 private int _lastId ;
3031
31- internal Connection ( string url , int delay , bool enqueueAsyncMessages , IConnectionTransport transport , ILoggerFactory loggerFactory = null )
32+ private Connection ( string url , int delay , bool enqueueAsyncMessages , IConnectionTransport transport , ILoggerFactory loggerFactory = null , int protocolTimeout = DefaultCommandTimeout )
3233 {
3334 LoggerFactory = loggerFactory ?? new LoggerFactory ( ) ;
3435 Url = url ;
3536 Delay = delay ;
3637 Transport = transport ;
3738
3839 _logger = LoggerFactory . CreateLogger < Connection > ( ) ;
39-
40+ ProtocolTimeout = protocolTimeout ;
4041 MessageQueue = new AsyncMessageQueue ( enqueueAsyncMessages , _logger ) ;
4142
4243 Transport . MessageReceived += Transport_MessageReceived ;
@@ -101,6 +102,8 @@ internal Connection(string url, int delay, bool enqueueAsyncMessages, IConnectio
101102
102103 internal ScriptInjector ScriptInjector { get ; } = new ( ) ;
103104
105+ internal int ProtocolTimeout { get ; }
106+
104107 /// <inheritdoc />
105108 public void Dispose ( )
106109 {
@@ -109,7 +112,7 @@ public void Dispose()
109112 }
110113
111114 /// <inheritdoc/>
112- public async Task < JObject > SendAsync ( string method , object args = null , bool waitForCallback = true )
115+ public async Task < JObject > SendAsync ( string method , object args = null , bool waitForCallback = true , CommandOptions options = null )
113116 {
114117 if ( IsClosed )
115118 {
@@ -131,36 +134,30 @@ public async Task<JObject> SendAsync(string method, object args = null, bool wai
131134 _callbacks [ id ] = callback ;
132135 }
133136
134- await RawSendAsync ( message ) . ConfigureAwait ( false ) ;
135- return waitForCallback ? await callback . TaskWrapper . Task . ConfigureAwait ( false ) : null ;
137+ await RawSendAsync ( message , options ) . ConfigureAwait ( false ) ;
138+ return waitForCallback ? await callback . TaskWrapper . Task . WithTimeout ( ProtocolTimeout ) . ConfigureAwait ( false ) : null ;
136139 }
137140
138141 /// <inheritdoc/>
139- public async Task < T > SendAsync < T > ( string method , object args = null )
142+ public async Task < T > SendAsync < T > ( string method , object args = null , CommandOptions options = null )
140143 {
141- var response = await SendAsync ( method , args ) . ConfigureAwait ( false ) ;
144+ var response = await SendAsync ( method , args , true , options ) . ConfigureAwait ( false ) ;
142145 return response . ToObject < T > ( true ) ;
143146 }
144147
145148 internal static async Task < Connection > Create ( string url , IConnectionOptions connectionOptions , ILoggerFactory loggerFactory = null , CancellationToken cancellationToken = default )
146149 {
147- #pragma warning disable 618
148- var transport = connectionOptions . Transport ;
149- #pragma warning restore 618
150- if ( transport == null )
151- {
152- var transportFactory = connectionOptions . TransportFactory ?? WebSocketTransport . DefaultTransportFactory ;
153- transport = await transportFactory ( new Uri ( url ) , connectionOptions , cancellationToken ) . ConfigureAwait ( false ) ;
154- }
150+ var transportFactory = connectionOptions . TransportFactory ?? WebSocketTransport . DefaultTransportFactory ;
151+ var transport = await transportFactory ( new Uri ( url ) , connectionOptions , cancellationToken ) . ConfigureAwait ( false ) ;
155152
156- return new Connection ( url , connectionOptions . SlowMo , connectionOptions . EnqueueAsyncMessages , transport , loggerFactory ) ;
153+ return new Connection ( url , connectionOptions . SlowMo , connectionOptions . EnqueueAsyncMessages , transport , loggerFactory , connectionOptions . ProtocolTimeout ) ;
157154 }
158155
159156 internal static Connection FromSession ( CDPSession session ) => session . Connection ;
160157
161158 internal int GetMessageID ( ) => Interlocked . Increment ( ref _lastId ) ;
162159
163- internal Task RawSendAsync ( string message )
160+ internal Task RawSendAsync ( string message , CommandOptions options = null )
164161 {
165162 _logger . LogTrace ( "Send ► {Message}" , message ) ;
166163 return Transport . SendAsync ( message ) ;
@@ -205,7 +202,7 @@ internal void Close(string closeReason)
205202 CloseReason = closeReason ;
206203
207204 Transport . StopReading ( ) ;
208- Disconnected ? . Invoke ( this , new EventArgs ( ) ) ;
205+ Disconnected ? . Invoke ( this , EventArgs . Empty ) ;
209206
210207 foreach ( var session in _sessions . Values . ToArray ( ) )
211208 {
@@ -237,7 +234,7 @@ internal void Close(string closeReason)
237234 /// <see cref="Connection"/> so the garbage collector can reclaim the memory that the
238235 /// <see cref="Connection"/> was occupying.</remarks>
239236 /// <param name="disposing">Indicates whether disposal was initiated by <see cref="Dispose()"/> operation.</param>
240- protected virtual void Dispose ( bool disposing )
237+ private void Dispose ( bool disposing )
241238 {
242239 Close ( "Connection disposed" ) ;
243240 Transport . MessageReceived -= Transport_MessageReceived ;
0 commit comments