Skip to content

Commit 150c432

Browse files
authored
[dotnet] [bidi] Introduce CancellationToken for async commands (#16990)
1 parent 722e65c commit 150c432

File tree

19 files changed

+242
-201
lines changed

19 files changed

+242
-201
lines changed

dotnet/src/webdriver/BiDi/BiDi.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,28 +60,28 @@ private BiDi(string url)
6060

6161
public Emulation.EmulationModule Emulation => AsModule<Emulation.EmulationModule>();
6262

63-
public static async Task<BiDi> ConnectAsync(string url, BiDiOptions? options = null)
63+
public static async Task<BiDi> ConnectAsync(string url, BiDiOptions? options = null, CancellationToken cancellationToken = default)
6464
{
6565
var bidi = new BiDi(url);
6666

67-
await bidi.Broker.ConnectAsync(CancellationToken.None).ConfigureAwait(false);
67+
await bidi.Broker.ConnectAsync(cancellationToken).ConfigureAwait(false);
6868

6969
return bidi;
7070
}
7171

72-
public Task<Session.StatusResult> StatusAsync(Session.StatusOptions? options = null)
72+
public Task<Session.StatusResult> StatusAsync(Session.StatusOptions? options = null, CancellationToken cancellationToken = default)
7373
{
74-
return SessionModule.StatusAsync(options);
74+
return SessionModule.StatusAsync(options, cancellationToken);
7575
}
7676

77-
public Task<Session.NewResult> NewAsync(Session.CapabilitiesRequest capabilities, Session.NewOptions? options = null)
77+
public Task<Session.NewResult> NewAsync(Session.CapabilitiesRequest capabilities, Session.NewOptions? options = null, CancellationToken cancellationToken = default)
7878
{
79-
return SessionModule.NewAsync(capabilities, options);
79+
return SessionModule.NewAsync(capabilities, options, cancellationToken);
8080
}
8181

82-
public Task EndAsync(Session.EndOptions? options = null)
82+
public Task EndAsync(Session.EndOptions? options = null, CancellationToken cancellationToken = default)
8383
{
84-
return SessionModule.EndAsync(options);
84+
return SessionModule.EndAsync(options, cancellationToken);
8585
}
8686

8787
public async ValueTask DisposeAsync()

dotnet/src/webdriver/BiDi/Broker.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,14 +127,21 @@ private async Task ProcessEventsAwaiterAsync()
127127
}
128128
}
129129

130-
public async Task<TResult> ExecuteCommandAsync<TCommand, TResult>(TCommand command, CommandOptions? options, JsonTypeInfo<TCommand> jsonCommandTypeInfo, JsonTypeInfo<TResult> jsonResultTypeInfo)
130+
public async Task<TResult> ExecuteCommandAsync<TCommand, TResult>(TCommand command, CommandOptions? options, JsonTypeInfo<TCommand> jsonCommandTypeInfo, JsonTypeInfo<TResult> jsonResultTypeInfo, CancellationToken cancellationToken)
131131
where TCommand : Command
132132
where TResult : EmptyResult
133133
{
134134
command.Id = Interlocked.Increment(ref _currentCommandId);
135+
135136
var tcs = new TaskCompletionSource<EmptyResult>(TaskCreationOptions.RunContinuationsAsynchronously);
137+
138+
using var cts = cancellationToken.CanBeCanceled
139+
? CancellationTokenSource.CreateLinkedTokenSource(cancellationToken)
140+
: new CancellationTokenSource();
141+
136142
var timeout = options?.Timeout ?? TimeSpan.FromSeconds(30);
137-
using var cts = new CancellationTokenSource(timeout);
143+
cts.CancelAfter(timeout);
144+
138145
cts.Token.Register(() => tcs.TrySetCanceled(cts.Token));
139146
var commandInfo = new CommandInfo(command.Id, tcs, jsonResultTypeInfo);
140147
_pendingCommands[command.Id] = commandInfo;

dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
using OpenQA.Selenium.BiDi.Json.Converters;
2121
using System.Text.Json;
2222
using System.Text.Json.Serialization;
23+
using System.Threading;
2324
using System.Threading.Tasks;
2425

2526
namespace OpenQA.Selenium.BiDi.Browser;
@@ -28,55 +29,54 @@ public sealed class BrowserModule : Module
2829
{
2930
private BrowserJsonSerializerContext _jsonContext = null!;
3031

31-
public async Task<CloseResult> CloseAsync(CloseOptions? options = null)
32+
public async Task<CloseResult> CloseAsync(CloseOptions? options = null, CancellationToken cancellationToken = default)
3233
{
33-
return await ExecuteCommandAsync(new CloseCommand(), options, _jsonContext.CloseCommand, _jsonContext.CloseResult).ConfigureAwait(false);
34+
return await ExecuteCommandAsync(new CloseCommand(), options, _jsonContext.CloseCommand, _jsonContext.CloseResult, cancellationToken).ConfigureAwait(false);
3435
}
3536

36-
public async Task<CreateUserContextResult> CreateUserContextAsync(CreateUserContextOptions? options = null)
37+
public async Task<CreateUserContextResult> CreateUserContextAsync(CreateUserContextOptions? options = null, CancellationToken cancellationToken = default)
3738
{
3839
var @params = new CreateUserContextParameters(options?.AcceptInsecureCerts, options?.Proxy, options?.UnhandledPromptBehavior);
3940

40-
return await ExecuteCommandAsync(new CreateUserContextCommand(@params), options, _jsonContext.CreateUserContextCommand, _jsonContext.CreateUserContextResult).ConfigureAwait(false);
41+
return await ExecuteCommandAsync(new CreateUserContextCommand(@params), options, _jsonContext.CreateUserContextCommand, _jsonContext.CreateUserContextResult, cancellationToken).ConfigureAwait(false);
4142
}
4243

43-
public async Task<GetUserContextsResult> GetUserContextsAsync(GetUserContextsOptions? options = null)
44+
public async Task<GetUserContextsResult> GetUserContextsAsync(GetUserContextsOptions? options = null, CancellationToken cancellationToken = default)
4445
{
45-
return await ExecuteCommandAsync(new GetUserContextsCommand(), options, _jsonContext.GetUserContextsCommand, _jsonContext.GetUserContextsResult).ConfigureAwait(false);
46+
return await ExecuteCommandAsync(new GetUserContextsCommand(), options, _jsonContext.GetUserContextsCommand, _jsonContext.GetUserContextsResult, cancellationToken).ConfigureAwait(false);
4647
}
4748

48-
public async Task<RemoveUserContextResult> RemoveUserContextAsync(UserContext userContext, RemoveUserContextOptions? options = null)
49+
public async Task<RemoveUserContextResult> RemoveUserContextAsync(UserContext userContext, RemoveUserContextOptions? options = null, CancellationToken cancellationToken = default)
4950
{
5051
var @params = new RemoveUserContextParameters(userContext);
5152

52-
return await ExecuteCommandAsync(new RemoveUserContextCommand(@params), options, _jsonContext.RemoveUserContextCommand, _jsonContext.RemoveUserContextResult).ConfigureAwait(false);
53+
return await ExecuteCommandAsync(new RemoveUserContextCommand(@params), options, _jsonContext.RemoveUserContextCommand, _jsonContext.RemoveUserContextResult, cancellationToken).ConfigureAwait(false);
5354
}
5455

55-
public async Task<GetClientWindowsResult> GetClientWindowsAsync(GetClientWindowsOptions? options = null)
56+
public async Task<GetClientWindowsResult> GetClientWindowsAsync(GetClientWindowsOptions? options = null, CancellationToken cancellationToken = default)
5657
{
57-
return await ExecuteCommandAsync(new(), options, _jsonContext.GetClientWindowsCommand, _jsonContext.GetClientWindowsResult
58-
).ConfigureAwait(false);
58+
return await ExecuteCommandAsync(new(), options, _jsonContext.GetClientWindowsCommand, _jsonContext.GetClientWindowsResult, cancellationToken).ConfigureAwait(false);
5959
}
6060

61-
public async Task<SetDownloadBehaviorResult> SetDownloadBehaviorAllowedAsync(string destinationFolder, SetDownloadBehaviorOptions? options = null)
61+
public async Task<SetDownloadBehaviorResult> SetDownloadBehaviorAllowedAsync(string destinationFolder, SetDownloadBehaviorOptions? options = null, CancellationToken cancellationToken = default)
6262
{
6363
var @params = new SetDownloadBehaviorParameters(new DownloadBehaviorAllowed(destinationFolder), options?.UserContexts);
6464

65-
return await ExecuteCommandAsync(new SetDownloadBehaviorCommand(@params), options, _jsonContext.SetDownloadBehaviorCommand, _jsonContext.SetDownloadBehaviorResult).ConfigureAwait(false);
65+
return await ExecuteCommandAsync(new SetDownloadBehaviorCommand(@params), options, _jsonContext.SetDownloadBehaviorCommand, _jsonContext.SetDownloadBehaviorResult, cancellationToken).ConfigureAwait(false);
6666
}
6767

68-
public async Task<SetDownloadBehaviorResult> SetDownloadBehaviorAllowedAsync(SetDownloadBehaviorOptions? options = null)
68+
public async Task<SetDownloadBehaviorResult> SetDownloadBehaviorAllowedAsync(SetDownloadBehaviorOptions? options = null, CancellationToken cancellationToken = default)
6969
{
7070
var @params = new SetDownloadBehaviorParameters(null, options?.UserContexts);
7171

72-
return await ExecuteCommandAsync(new SetDownloadBehaviorCommand(@params), options, _jsonContext.SetDownloadBehaviorCommand, _jsonContext.SetDownloadBehaviorResult).ConfigureAwait(false);
72+
return await ExecuteCommandAsync(new SetDownloadBehaviorCommand(@params), options, _jsonContext.SetDownloadBehaviorCommand, _jsonContext.SetDownloadBehaviorResult, cancellationToken).ConfigureAwait(false);
7373
}
7474

75-
public async Task<SetDownloadBehaviorResult> SetDownloadBehaviorDeniedAsync(SetDownloadBehaviorOptions? options = null)
75+
public async Task<SetDownloadBehaviorResult> SetDownloadBehaviorDeniedAsync(SetDownloadBehaviorOptions? options = null, CancellationToken cancellationToken = default)
7676
{
7777
var @params = new SetDownloadBehaviorParameters(new DownloadBehaviorDenied(), options?.UserContexts);
7878

79-
return await ExecuteCommandAsync(new SetDownloadBehaviorCommand(@params), options, _jsonContext.SetDownloadBehaviorCommand, _jsonContext.SetDownloadBehaviorResult).ConfigureAwait(false);
79+
return await ExecuteCommandAsync(new SetDownloadBehaviorCommand(@params), options, _jsonContext.SetDownloadBehaviorCommand, _jsonContext.SetDownloadBehaviorResult, cancellationToken).ConfigureAwait(false);
8080
}
8181

8282
protected override void Initialize(BiDi bidi, JsonSerializerOptions jsonSerializerOptions)

dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContext.cs

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -71,59 +71,59 @@ public BiDi BiDi
7171
[JsonIgnore]
7272
public BrowsingContextInputModule Input => _inputModule ?? Interlocked.CompareExchange(ref _inputModule, new BrowsingContextInputModule(this, BiDi.Input), null) ?? _inputModule;
7373

74-
public Task<NavigateResult> NavigateAsync(string url, NavigateOptions? options = null)
74+
public Task<NavigateResult> NavigateAsync(string url, NavigateOptions? options = null, CancellationToken cancellationToken = default)
7575
{
76-
return BiDi.BrowsingContext.NavigateAsync(this, url, options);
76+
return BiDi.BrowsingContext.NavigateAsync(this, url, options, cancellationToken);
7777
}
7878

79-
public Task<ReloadResult> ReloadAsync(ReloadOptions? options = null)
79+
public Task<ReloadResult> ReloadAsync(ReloadOptions? options = null, CancellationToken cancellationToken = default)
8080
{
81-
return BiDi.BrowsingContext.ReloadAsync(this, options);
81+
return BiDi.BrowsingContext.ReloadAsync(this, options, cancellationToken);
8282
}
8383

84-
public Task<ActivateResult> ActivateAsync(ActivateOptions? options = null)
84+
public Task<ActivateResult> ActivateAsync(ActivateOptions? options = null, CancellationToken cancellationToken = default)
8585
{
86-
return BiDi.BrowsingContext.ActivateAsync(this, options);
86+
return BiDi.BrowsingContext.ActivateAsync(this, options, cancellationToken);
8787
}
8888

89-
public Task<LocateNodesResult> LocateNodesAsync(Locator locator, LocateNodesOptions? options = null)
89+
public Task<LocateNodesResult> LocateNodesAsync(Locator locator, LocateNodesOptions? options = null, CancellationToken cancellationToken = default)
9090
{
91-
return BiDi.BrowsingContext.LocateNodesAsync(this, locator, options);
91+
return BiDi.BrowsingContext.LocateNodesAsync(this, locator, options, cancellationToken);
9292
}
9393

94-
public Task<CaptureScreenshotResult> CaptureScreenshotAsync(CaptureScreenshotOptions? options = null)
94+
public Task<CaptureScreenshotResult> CaptureScreenshotAsync(CaptureScreenshotOptions? options = null, CancellationToken cancellationToken = default)
9595
{
96-
return BiDi.BrowsingContext.CaptureScreenshotAsync(this, options);
96+
return BiDi.BrowsingContext.CaptureScreenshotAsync(this, options, cancellationToken);
9797
}
9898

99-
public Task<CloseResult> CloseAsync(CloseOptions? options = null)
99+
public Task<CloseResult> CloseAsync(CloseOptions? options = null, CancellationToken cancellationToken = default)
100100
{
101-
return BiDi.BrowsingContext.CloseAsync(this, options);
101+
return BiDi.BrowsingContext.CloseAsync(this, options, cancellationToken);
102102
}
103103

104-
public Task<TraverseHistoryResult> TraverseHistoryAsync(int delta, TraverseHistoryOptions? options = null)
104+
public Task<TraverseHistoryResult> TraverseHistoryAsync(int delta, TraverseHistoryOptions? options = null, CancellationToken cancellationToken = default)
105105
{
106-
return BiDi.BrowsingContext.TraverseHistoryAsync(this, delta, options);
106+
return BiDi.BrowsingContext.TraverseHistoryAsync(this, delta, options, cancellationToken);
107107
}
108108

109-
public Task<SetViewportResult> SetViewportAsync(SetViewportOptions? options = null)
109+
public Task<SetViewportResult> SetViewportAsync(SetViewportOptions? options = null, CancellationToken cancellationToken = default)
110110
{
111-
return BiDi.BrowsingContext.SetViewportAsync(this, options);
111+
return BiDi.BrowsingContext.SetViewportAsync(this, options, cancellationToken);
112112
}
113113

114-
public Task<PrintResult> PrintAsync(PrintOptions? options = null)
114+
public Task<PrintResult> PrintAsync(PrintOptions? options = null, CancellationToken cancellationToken = default)
115115
{
116-
return BiDi.BrowsingContext.PrintAsync(this, options);
116+
return BiDi.BrowsingContext.PrintAsync(this, options, cancellationToken);
117117
}
118118

119-
public Task<HandleUserPromptResult> HandleUserPromptAsync(HandleUserPromptOptions? options = null)
119+
public Task<HandleUserPromptResult> HandleUserPromptAsync(HandleUserPromptOptions? options = null, CancellationToken cancellationToken = default)
120120
{
121-
return BiDi.BrowsingContext.HandleUserPromptAsync(this, options);
121+
return BiDi.BrowsingContext.HandleUserPromptAsync(this, options, cancellationToken);
122122
}
123123

124-
public Task<GetTreeResult> GetTreeAsync(ContextGetTreeOptions? options = null)
124+
public Task<GetTreeResult> GetTreeAsync(ContextGetTreeOptions? options = null, CancellationToken cancellationToken = default)
125125
{
126-
return BiDi.BrowsingContext.GetTreeAsync(ContextGetTreeOptions.WithContext(options, this));
126+
return BiDi.BrowsingContext.GetTreeAsync(ContextGetTreeOptions.WithContext(options, this), cancellationToken);
127127
}
128128

129129
public Task<Subscription> OnNavigationStartedAsync(Func<NavigationInfo, Task> handler, ContextSubscriptionOptions? options = null)

dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContextInputModule.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
// </copyright>
1919

2020
using System;
21+
using System.Threading;
2122
using System.Threading.Tasks;
2223
using OpenQA.Selenium.BiDi.Input;
2324
using System.Collections.Generic;
@@ -26,19 +27,19 @@ namespace OpenQA.Selenium.BiDi.BrowsingContext;
2627

2728
public sealed class BrowsingContextInputModule(BrowsingContext context, InputModule inputModule)
2829
{
29-
public Task<PerformActionsResult> PerformActionsAsync(IEnumerable<SourceActions> actions, PerformActionsOptions? options = null)
30+
public Task<PerformActionsResult> PerformActionsAsync(IEnumerable<SourceActions> actions, PerformActionsOptions? options = null, CancellationToken cancellationToken = default)
3031
{
31-
return inputModule.PerformActionsAsync(context, actions, options);
32+
return inputModule.PerformActionsAsync(context, actions, options, cancellationToken);
3233
}
3334

34-
public Task<ReleaseActionsResult> ReleaseActionsAsync(ReleaseActionsOptions? options = null)
35+
public Task<ReleaseActionsResult> ReleaseActionsAsync(ReleaseActionsOptions? options = null, CancellationToken cancellationToken = default)
3536
{
36-
return inputModule.ReleaseActionsAsync(context, options);
37+
return inputModule.ReleaseActionsAsync(context, options, cancellationToken);
3738
}
3839

39-
public Task<SetFilesResult> SetFilesAsync(Script.ISharedReference element, IEnumerable<string> files, SetFilesOptions? options = null)
40+
public Task<SetFilesResult> SetFilesAsync(Script.ISharedReference element, IEnumerable<string> files, SetFilesOptions? options = null, CancellationToken cancellationToken = default)
4041
{
41-
return inputModule.SetFilesAsync(context, element, files, options);
42+
return inputModule.SetFilesAsync(context, element, files, options, cancellationToken);
4243
}
4344

4445
public Task<Subscription> OnFileDialogOpenedAsync(Func<FileDialogInfo, Task> handler, ContextSubscriptionOptions? options = null)

0 commit comments

Comments
 (0)