Skip to content
21 changes: 13 additions & 8 deletions dotnet/src/webdriver/BiDi/Broker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,16 @@ public async ValueTask UnsubscribeAsync(Subscription subscription, CancellationT
_eventDispatcher.RemoveHandler(subscription.EventName, subscription.Handler);
}

public async Task<TResult> ExecuteCommandAsync<TCommand, TResult>(TCommand command, CommandOptions? options, JsonTypeInfo<TCommand> jsonCommandTypeInfo, JsonTypeInfo<TResult> jsonResultTypeInfo, CancellationToken cancellationToken)
where TCommand : Command
public async Task<TResult> ExecuteAsync<TParameters, TResult>(CommandDescriptor<TParameters, TResult> descriptor, TParameters @params, CommandOptions? options, CancellationToken cancellationToken)
where TParameters : Parameters
where TResult : EmptyResult
{
if (_terminalReceiveException is { } terminalException)
{
throw new BiDiException("The broker is no longer processing messages due to a transport error.", terminalException);
}

command.Id = Interlocked.Increment(ref _currentCommandId);
var id = Interlocked.Increment(ref _currentCommandId);

var tcs = new TaskCompletionSource<EmptyResult>(TaskCreationOptions.RunContinuationsAsynchronously);

Expand All @@ -141,7 +141,12 @@ public async Task<TResult> ExecuteCommandAsync<TCommand, TResult>(TCommand comma
using (BiDiContext.Use(_bidi))
using (var writer = new Utf8JsonWriter(sendBuffer))
{
JsonSerializer.Serialize(writer, command, jsonCommandTypeInfo);
writer.WriteStartObject();
writer.WriteNumber("id"u8, id);
writer.WriteString("method"u8, descriptor.Method);
writer.WritePropertyName("params"u8);
JsonSerializer.Serialize(writer, @params, descriptor.ParamsTypeInfo);
writer.WriteEndObject();
}
}
catch
Expand All @@ -150,13 +155,13 @@ public async Task<TResult> ExecuteCommandAsync<TCommand, TResult>(TCommand comma
throw;
}

var commandInfo = new CommandInfo(tcs, jsonResultTypeInfo);
_pendingCommands[command.Id] = commandInfo;
var commandInfo = new CommandInfo(tcs, descriptor.ResultTypeInfo);
_pendingCommands[id] = commandInfo;

using var ctsRegistration = cts.Token.Register(() =>
{
tcs.TrySetCanceled(cts.Token);
_pendingCommands.TryRemove(command.Id, out _);
_pendingCommands.TryRemove(id, out _);
});

try
Expand All @@ -174,7 +179,7 @@ public async Task<TResult> ExecuteCommandAsync<TCommand, TResult>(TCommand comma
}
catch
{
_pendingCommands.TryRemove(command.Id, out _);
_pendingCommands.TryRemove(id, out _);
throw;
}
finally
Expand Down
47 changes: 31 additions & 16 deletions dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,75 +18,90 @@
// </copyright>

using System.Text.Json.Serialization;
using static OpenQA.Selenium.BiDi.Browser.BrowserJsonSerializerContext;

namespace OpenQA.Selenium.BiDi.Browser;

public sealed class BrowserModule : Module, IBrowserModule
internal sealed class BrowserModule : Module, IBrowserModule
Comment thread
nvborisenko marked this conversation as resolved.
{
private static readonly BrowserJsonSerializerContext JsonContext = BrowserJsonSerializerContext.Default;
private static readonly CommandDescriptor<Parameters, CloseResult> CloseCommand = new(
"browser.close", Default.Parameters, Default.CloseResult);

private static readonly CommandDescriptor<CreateUserContextParameters, CreateUserContextResult> CreateUserContextCommand = new(
"browser.createUserContext", Default.CreateUserContextParameters, Default.CreateUserContextResult);

private static readonly CommandDescriptor<Parameters, GetUserContextsResult> GetUserContextsCommand = new(
"browser.getUserContexts", Default.Parameters, Default.GetUserContextsResult);

private static readonly CommandDescriptor<RemoveUserContextParameters, RemoveUserContextResult> RemoveUserContextCommand = new(
"browser.removeUserContext", Default.RemoveUserContextParameters, Default.RemoveUserContextResult);

private static readonly CommandDescriptor<Parameters, GetClientWindowsResult> GetClientWindowsCommand = new(
"browser.getClientWindows", Default.Parameters, Default.GetClientWindowsResult);

private static readonly CommandDescriptor<SetDownloadBehaviorParameters, SetDownloadBehaviorResult> SetDownloadBehaviorCommand = new(
"browser.setDownloadBehavior", Default.SetDownloadBehaviorParameters, Default.SetDownloadBehaviorResult);

public async Task<CloseResult> CloseAsync(CloseOptions? options = null, CancellationToken cancellationToken = default)
{
return await ExecuteCommandAsync(new CloseCommand(), options, JsonContext.CloseCommand, JsonContext.CloseResult, cancellationToken).ConfigureAwait(false);
return await ExecuteAsync(CloseCommand, Parameters.Empty, options, cancellationToken).ConfigureAwait(false);
}

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

return await ExecuteCommandAsync(new CreateUserContextCommand(@params), options, JsonContext.CreateUserContextCommand, JsonContext.CreateUserContextResult, cancellationToken).ConfigureAwait(false);
return await ExecuteAsync(CreateUserContextCommand, @params, options, cancellationToken).ConfigureAwait(false);
}

public async Task<GetUserContextsResult> GetUserContextsAsync(GetUserContextsOptions? options = null, CancellationToken cancellationToken = default)
{
return await ExecuteCommandAsync(new GetUserContextsCommand(), options, JsonContext.GetUserContextsCommand, JsonContext.GetUserContextsResult, cancellationToken).ConfigureAwait(false);
return await ExecuteAsync(GetUserContextsCommand, Parameters.Empty, options, cancellationToken).ConfigureAwait(false);
}

public async Task<RemoveUserContextResult> RemoveUserContextAsync(UserContext userContext, RemoveUserContextOptions? options = null, CancellationToken cancellationToken = default)
{
var @params = new RemoveUserContextParameters(userContext);

return await ExecuteCommandAsync(new RemoveUserContextCommand(@params), options, JsonContext.RemoveUserContextCommand, JsonContext.RemoveUserContextResult, cancellationToken).ConfigureAwait(false);
return await ExecuteAsync(RemoveUserContextCommand, @params, options, cancellationToken).ConfigureAwait(false);
}

public async Task<GetClientWindowsResult> GetClientWindowsAsync(GetClientWindowsOptions? options = null, CancellationToken cancellationToken = default)
{
return await ExecuteCommandAsync(new(), options, JsonContext.GetClientWindowsCommand, JsonContext.GetClientWindowsResult, cancellationToken).ConfigureAwait(false);
return await ExecuteAsync(GetClientWindowsCommand, Parameters.Empty, options, cancellationToken).ConfigureAwait(false);
}

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

return await ExecuteCommandAsync(new SetDownloadBehaviorCommand(@params), options, JsonContext.SetDownloadBehaviorCommand, JsonContext.SetDownloadBehaviorResult, cancellationToken).ConfigureAwait(false);
return await ExecuteAsync(SetDownloadBehaviorCommand, @params, options, cancellationToken).ConfigureAwait(false);
}

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

return await ExecuteCommandAsync(new SetDownloadBehaviorCommand(@params), options, JsonContext.SetDownloadBehaviorCommand, JsonContext.SetDownloadBehaviorResult, cancellationToken).ConfigureAwait(false);
return await ExecuteAsync(SetDownloadBehaviorCommand, @params, options, cancellationToken).ConfigureAwait(false);
}

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

return await ExecuteCommandAsync(new SetDownloadBehaviorCommand(@params), options, JsonContext.SetDownloadBehaviorCommand, JsonContext.SetDownloadBehaviorResult, cancellationToken).ConfigureAwait(false);
return await ExecuteAsync(SetDownloadBehaviorCommand, @params, options, cancellationToken).ConfigureAwait(false);
}
}

[JsonSerializable(typeof(CloseCommand))]
[JsonSerializable(typeof(Parameters))]
[JsonSerializable(typeof(CloseResult))]
[JsonSerializable(typeof(CreateUserContextCommand))]
[JsonSerializable(typeof(CreateUserContextParameters))]
[JsonSerializable(typeof(CreateUserContextResult))]
[JsonSerializable(typeof(GetUserContextsCommand))]
[JsonSerializable(typeof(GetUserContextsResult))]
[JsonSerializable(typeof(RemoveUserContextCommand))]
[JsonSerializable(typeof(RemoveUserContextParameters))]
[JsonSerializable(typeof(RemoveUserContextResult))]
[JsonSerializable(typeof(GetClientWindowsCommand))]
[JsonSerializable(typeof(GetClientWindowsResult))]
[JsonSerializable(typeof(SetDownloadBehaviorCommand))]
[JsonSerializable(typeof(SetDownloadBehaviorParameters))]
[JsonSerializable(typeof(SetDownloadBehaviorResult))]

[JsonSourceGenerationOptions(
Expand Down
Comment thread
nvborisenko marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@

namespace OpenQA.Selenium.BiDi.Browser;

internal sealed class CloseCommand()
: Command<Parameters, CloseResult>(Parameters.Empty, "browser.close");

public sealed record CloseOptions : CommandOptions;

public sealed record CloseResult : EmptyResult;
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@

namespace OpenQA.Selenium.BiDi.Browser;

internal sealed class CreateUserContextCommand(CreateUserContextParameters @params)
: Command<CreateUserContextParameters, CreateUserContextResult>(@params, "browser.createUserContext");

internal sealed record CreateUserContextParameters(bool? AcceptInsecureCerts, Session.ProxyConfiguration? Proxy, Session.UserPromptHandler? UnhandledPromptBehavior) : Parameters;

public sealed record CreateUserContextOptions : CommandOptions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@

namespace OpenQA.Selenium.BiDi.Browser;

internal sealed class GetClientWindowsCommand()
: Command<Parameters, GetClientWindowsResult>(Parameters.Empty, "browser.getClientWindows");

public sealed record GetClientWindowsOptions : CommandOptions;

public sealed record GetClientWindowsResult(IReadOnlyList<ClientWindowInfo> ClientWindows) : EmptyResult;
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@

namespace OpenQA.Selenium.BiDi.Browser;

internal sealed class GetUserContextsCommand()
: Command<Parameters, GetUserContextsResult>(Parameters.Empty, "browser.getUserContexts");

public record GetUserContextsOptions : CommandOptions;

public sealed record GetUserContextsResult(IReadOnlyList<UserContextInfo> UserContexts) : EmptyResult;
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@

namespace OpenQA.Selenium.BiDi.Browser;

internal sealed class RemoveUserContextCommand(RemoveUserContextParameters @params)
: Command<RemoveUserContextParameters, RemoveUserContextResult>(@params, "browser.removeUserContext");

internal sealed record RemoveUserContextParameters(UserContext UserContext) : Parameters;

public sealed record RemoveUserContextOptions : CommandOptions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@

namespace OpenQA.Selenium.BiDi.Browser;

internal sealed class SetDownloadBehaviorCommand(SetDownloadBehaviorParameters @params)
: Command<SetDownloadBehaviorParameters, SetDownloadBehaviorResult>(@params, "browser.setDownloadBehavior");

internal sealed record SetDownloadBehaviorParameters([property: JsonIgnore(Condition = JsonIgnoreCondition.Never)] DownloadBehavior? DownloadBehavior, IEnumerable<UserContext>? UserContexts) : Parameters;

[JsonPolymorphic(TypeDiscriminatorPropertyName = "type")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@

namespace OpenQA.Selenium.BiDi.BrowsingContext;

internal sealed class ActivateCommand(ActivateParameters @params)
: Command<ActivateParameters, ActivateResult>(@params, "browsingContext.activate");

internal sealed record ActivateParameters(BrowsingContext Context) : Parameters;

public sealed record ActivateOptions : CommandOptions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

namespace OpenQA.Selenium.BiDi.BrowsingContext;

public sealed class BrowsingContextInputModule(BrowsingContext context, IInputModule inputModule) : IBrowsingContextInputModule
internal sealed class BrowsingContextInputModule(BrowsingContext context, IInputModule inputModule) : IBrowsingContextInputModule
{
public Task<PerformActionsResult> PerformActionsAsync(IEnumerable<SourceActions> actions, PerformActionsOptions? options = null, CancellationToken cancellationToken = default)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

namespace OpenQA.Selenium.BiDi.BrowsingContext;

public sealed class BrowsingContextLogModule(BrowsingContext context, ILogModule logModule) : IBrowsingContextLogModule
internal sealed class BrowsingContextLogModule(BrowsingContext context, ILogModule logModule) : IBrowsingContextLogModule
{
public Task<Subscription> OnEntryAddedAsync(Func<EntryAddedEventArgs, Task> handler, ContextSubscriptionOptions? options = null, CancellationToken cancellationToken = default)
{
Expand Down
Loading
Loading