@@ -38,6 +38,7 @@ public class BidiPage : Page
3838{
3939 private readonly CdpEmulationManager _cdpEmulationManager ;
4040 private InternalNetworkConditions _emulatedNetworkConditions ;
41+ private TaskCompletionSource < bool > _closedTcs ;
4142
4243 internal BidiPage ( BidiBrowserContext browserContext , BrowsingContext browsingContext ) : base ( browserContext . ScreenshotTaskQueue )
4344 {
@@ -92,6 +93,26 @@ public override IFrame[] Frames
9293 /// <inheritdoc />
9394 protected override Browser Browser { get ; }
9495
96+ private Task ClosedTask
97+ {
98+ get
99+ {
100+ if ( _closedTcs == null )
101+ {
102+ _closedTcs = new TaskCompletionSource < bool > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
103+ BidiMainFrame . BrowsingContext . Closed += ContextClosed ;
104+
105+ void ContextClosed ( object sender , ClosedEventArgs e )
106+ {
107+ _closedTcs . TrySetException ( new TargetClosedException ( "Target closed" , "Browsing context closed" ) ) ;
108+ BidiMainFrame . BrowsingContext . Closed -= ContextClosed ;
109+ }
110+ }
111+
112+ return _closedTcs . Task ;
113+ }
114+ }
115+
95116 /// <inheritdoc />
96117 public override Task SetExtraHttpHeadersAsync ( Dictionary < string , string > headers ) => throw new NotImplementedException ( ) ;
97118
@@ -118,7 +139,10 @@ public override Task EmulateIdleStateAsync(EmulateIdleOverrides idleOverrides =
118139 /// <inheritdoc />
119140 public override async Task < IResponse > ReloadAsync ( NavigationOptions options )
120141 {
121- var waitForNavigationTask = WaitForNavigationAsync ( options ) ;
142+ var navOptions = options == null
143+ ? new NavigationOptions { IgnoreSameDocumentNavigation = true }
144+ : options with { IgnoreSameDocumentNavigation = true } ;
145+ var waitForNavigationTask = WaitForNavigationAsync ( navOptions ) ;
122146 var navigationTask = BidiMainFrame . BrowsingContext . ReloadAsync ( ) ;
123147
124148 try
@@ -142,10 +166,41 @@ public override async Task<IResponse> ReloadAsync(NavigationOptions options)
142166 public override Task WaitForNetworkIdleAsync ( WaitForNetworkIdleOptions options = null ) => throw new NotImplementedException ( ) ;
143167
144168 /// <inheritdoc />
145- public override Task < IRequest > WaitForRequestAsync ( Func < IRequest , bool > predicate , WaitForOptions options = null ) => throw new NotImplementedException ( ) ;
169+ public override async Task < IRequest > WaitForRequestAsync ( Func < IRequest , bool > predicate , WaitForOptions options = null )
170+ {
171+ // TODO: Implement full network request monitoring for BiDi
172+ // For now, this creates a task that will be faulted when the page closes
173+ var timeout = options ? . Timeout ?? DefaultTimeout ;
174+ var requestTcs = new TaskCompletionSource < IRequest > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
175+
176+ await Task . WhenAny ( requestTcs . Task , ClosedTask ) . WithTimeout ( timeout , t =>
177+ new TimeoutException ( $ "Timeout of { t . TotalMilliseconds } ms exceeded") ) . ConfigureAwait ( false ) ;
178+
179+ if ( ClosedTask . IsFaulted )
180+ {
181+ await ClosedTask . ConfigureAwait ( false ) ;
182+ }
183+
184+ return await requestTcs . Task . ConfigureAwait ( false ) ;
185+ }
146186
147187 /// <inheritdoc />
148- public override Task < IResponse > WaitForResponseAsync ( Func < IResponse , Task < bool > > predicate , WaitForOptions options = null ) => throw new NotImplementedException ( ) ;
188+ public override async Task < IResponse > WaitForResponseAsync ( Func < IResponse , Task < bool > > predicate , WaitForOptions options = null )
189+ {
190+ // TODO: Implement full network response monitoring for BiDi
191+ // For now, this creates a task that will be faulted when the page closes
192+ var timeout = options ? . Timeout ?? DefaultTimeout ;
193+ var responseTcs = new TaskCompletionSource < IResponse > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
194+
195+ await Task . WhenAny ( responseTcs . Task , ClosedTask ) . WithTimeout ( timeout ) . ConfigureAwait ( false ) ;
196+
197+ if ( ClosedTask . IsFaulted )
198+ {
199+ await ClosedTask . ConfigureAwait ( false ) ;
200+ }
201+
202+ return await responseTcs . Task . ConfigureAwait ( false ) ;
203+ }
149204
150205 /// <inheritdoc />
151206 public override Task < FileChooser > WaitForFileChooserAsync ( WaitForOptions options = null ) => throw new NotImplementedException ( ) ;
@@ -612,6 +667,7 @@ private void Initialize()
612667 BidiMainFrame . BrowsingContext . Closed += ( _ , _ ) =>
613668 {
614669 OnClose ( ) ;
670+ IsClosed = true ;
615671 } ;
616672 }
617673}
0 commit comments