From f4edf7aecf758672843413e299e0b43c45a4ab46 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Mon, 6 Oct 2025 22:39:48 +0300 Subject: [PATCH 1/3] Dummy --- dotnet/src/webdriver/BiDi/BiDi.cs | 20 ++++++------- .../webdriver/BiDi/Browser/BrowserModule.cs | 24 +++++++++++++-- .../BrowsingContext/BrowsingContextModule.cs | 7 ++++- .../webdriver/BiDi/Communication/Broker.cs | 30 +++++++++---------- .../BiDi/Emulation/EmulationModule.cs | 7 ++++- .../src/webdriver/BiDi/Input/InputModule.cs | 7 ++++- dotnet/src/webdriver/BiDi/Log/LogModule.cs | 7 ++++- dotnet/src/webdriver/BiDi/Module.cs | 14 +++++++-- .../webdriver/BiDi/Network/NetworkModule.cs | 7 ++++- .../src/webdriver/BiDi/Script/ScriptModule.cs | 7 ++++- .../webdriver/BiDi/Session/SessionModule.cs | 7 ++++- .../webdriver/BiDi/Storage/StorageModule.cs | 7 ++++- .../BiDi/WebExtension/WebExtensionModule.cs | 7 ++++- 13 files changed, 113 insertions(+), 38 deletions(-) diff --git a/dotnet/src/webdriver/BiDi/BiDi.cs b/dotnet/src/webdriver/BiDi/BiDi.cs index 3edb8edac2401..35e01a1048670 100644 --- a/dotnet/src/webdriver/BiDi/BiDi.cs +++ b/dotnet/src/webdriver/BiDi/BiDi.cs @@ -55,7 +55,7 @@ internal Session.SessionModule SessionModule if (_sessionModule is not null) return _sessionModule; lock (_moduleLock) { - _sessionModule ??= new Session.SessionModule(_broker); + _sessionModule ??= Module.Create(_broker); } return _sessionModule; } @@ -68,7 +68,7 @@ public BrowsingContext.BrowsingContextModule BrowsingContext if (_browsingContextModule is not null) return _browsingContextModule; lock (_moduleLock) { - _browsingContextModule ??= new BrowsingContext.BrowsingContextModule(_broker); + _browsingContextModule ??= Module.Create(_broker); } return _browsingContextModule; } @@ -81,7 +81,7 @@ public Browser.BrowserModule Browser if (_browserModule is not null) return _browserModule; lock (_moduleLock) { - _browserModule ??= new Browser.BrowserModule(_broker); + _browserModule ??= Module.Create(_broker); } return _browserModule; } @@ -94,7 +94,7 @@ public Network.NetworkModule Network if (_networkModule is not null) return _networkModule; lock (_moduleLock) { - _networkModule ??= new Network.NetworkModule(_broker); + _networkModule ??= Module.Create(_broker); } return _networkModule; } @@ -107,7 +107,7 @@ internal Input.InputModule InputModule if (_inputModule is not null) return _inputModule; lock (_moduleLock) { - _inputModule ??= new Input.InputModule(_broker); + _inputModule ??= Module.Create(_broker); } return _inputModule; } @@ -120,7 +120,7 @@ public Script.ScriptModule Script if (_scriptModule is not null) return _scriptModule; lock (_moduleLock) { - _scriptModule ??= new Script.ScriptModule(_broker); + _scriptModule ??= Module.Create(_broker); } return _scriptModule; } @@ -133,7 +133,7 @@ public Log.LogModule Log if (_logModule is not null) return _logModule; lock (_moduleLock) { - _logModule ??= new Log.LogModule(_broker); + _logModule ??= Module.Create(_broker); } return _logModule; } @@ -146,7 +146,7 @@ public Storage.StorageModule Storage if (_storageModule is not null) return _storageModule; lock (_moduleLock) { - _storageModule ??= new Storage.StorageModule(_broker); + _storageModule ??= Module.Create(_broker); } return _storageModule; } @@ -159,7 +159,7 @@ public WebExtension.WebExtensionModule WebExtension if (_webExtensionModule is not null) return _webExtensionModule; lock (_moduleLock) { - _webExtensionModule ??= new WebExtension.WebExtensionModule(_broker); + _webExtensionModule ??= Module.Create(_broker); } return _webExtensionModule; } @@ -172,7 +172,7 @@ public Emulation.EmulationModule Emulation if (_emulationModule is not null) return _emulationModule; lock (_moduleLock) { - _emulationModule ??= new Emulation.EmulationModule(_broker); + _emulationModule ??= Module.Create(_broker); } return _emulationModule; } diff --git a/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs b/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs index cb23e20ad06e8..66e68b3664dc6 100644 --- a/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs +++ b/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs @@ -17,12 +17,14 @@ // under the License. // -using System.Threading.Tasks; using OpenQA.Selenium.BiDi.Communication; +using System.Collections.Generic; +using System.Text.Json.Serialization; +using System.Threading.Tasks; namespace OpenQA.Selenium.BiDi.Browser; -public sealed class BrowserModule(Broker broker) : Module(broker) +public sealed class BrowserModule : Module { public async Task CloseAsync(CloseOptions? options = null) { @@ -73,4 +75,22 @@ public async Task SetDownloadBehaviorDeniedAsync(SetDownloadBehavio return await Broker.ExecuteCommandAsync(new SetDownloadBehaviorCommand(@params), options).ConfigureAwait(false); } + + protected internal override void Initialize(Broker broker) + { + broker.ConfigureJsonContext(opts => opts.TypeInfoResolverChain.Add(BrowserModuleJsonSerializerContext.Default)); + } } + +[JsonSerializable(typeof(CloseCommand))] +[JsonSerializable(typeof(CreateUserContextCommand))] +[JsonSerializable(typeof(GetUserContextsCommand))] +[JsonSerializable(typeof(GetUserContextsResult))] +[JsonSerializable(typeof(RemoveUserContextCommand))] +[JsonSerializable(typeof(GetClientWindowsCommand))] +[JsonSerializable(typeof(GetClientWindowsResult))] +[JsonSerializable(typeof(SetDownloadBehaviorCommand))] +[JsonSerializable(typeof(UserContextInfo))] +[JsonSerializable(typeof(IReadOnlyList))] +[JsonSerializable(typeof(IReadOnlyList))] +internal partial class BrowserModuleJsonSerializerContext : JsonSerializerContext; diff --git a/dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContextModule.cs b/dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContextModule.cs index 9e42a9178dcf0..4e7062af98cce 100644 --- a/dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContextModule.cs +++ b/dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContextModule.cs @@ -23,7 +23,7 @@ namespace OpenQA.Selenium.BiDi.BrowsingContext; -public sealed class BrowsingContextModule(Broker broker) : Module(broker) +public sealed class BrowsingContextModule : Module { public async Task CreateAsync(ContextType type, CreateOptions? options = null) { @@ -250,4 +250,9 @@ public async Task OnUserPromptClosedAsync(Action action) + { + // Keep options mutable; do not create a context bound to them (avoids InvalidOperationException) + action(_jsonSerializerOptions); } public async Task ConnectAsync(CancellationToken cancellationToken) @@ -205,21 +212,14 @@ private async Task ExecuteCommandCoreAsync(TCommand comma where TCommand : Command { command.Id = Interlocked.Increment(ref _currentCommandId); - var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - var timeout = options?.Timeout ?? TimeSpan.FromSeconds(30); - using var cts = new CancellationTokenSource(timeout); - cts.Token.Register(() => tcs.TrySetCanceled(cts.Token)); - _pendingCommands[command.Id] = new(command.Id, command.ResultType, tcs); - var data = JsonSerializer.SerializeToUtf8Bytes(command, typeof(TCommand), _jsonSerializerContext); - + var data = JsonSerializer.SerializeToUtf8Bytes(command, typeof(TCommand), _jsonSerializerOptions); await _transport.SendAsync(data, cts.Token).ConfigureAwait(false); - return await tcs.Task.ConfigureAwait(false); } @@ -341,11 +341,11 @@ private void ProcessReceivedMessage(byte[]? data) break; case "result": - resultReader = reader; // cloning reader with current position + resultReader = reader; // snapshot break; case "params": - paramsReader = reader; // cloning reader with current position + paramsReader = reader; // snapshot break; case "error": @@ -368,7 +368,7 @@ private void ProcessReceivedMessage(byte[]? data) if (_pendingCommands.TryGetValue(id.Value, out var successCommand)) { - var messageSuccess = JsonSerializer.Deserialize(ref resultReader, successCommand.ResultType, _jsonSerializerContext)!; + var messageSuccess = JsonSerializer.Deserialize(ref resultReader, successCommand.ResultType, _jsonSerializerOptions)!; successCommand.TaskCompletionSource.SetResult((EmptyResult)messageSuccess); _pendingCommands.TryRemove(id.Value, out _); } @@ -384,7 +384,7 @@ private void ProcessReceivedMessage(byte[]? data) if (_eventTypesMap.TryGetValue(method, out var eventType)) { - var eventArgs = (EventArgs)JsonSerializer.Deserialize(ref paramsReader, eventType, _jsonSerializerContext)!; + var eventArgs = (EventArgs)JsonSerializer.Deserialize(ref paramsReader, eventType, _jsonSerializerOptions)!; var messageEvent = new MessageEvent(method, eventArgs); _pendingEvents.Add(messageEvent); diff --git a/dotnet/src/webdriver/BiDi/Emulation/EmulationModule.cs b/dotnet/src/webdriver/BiDi/Emulation/EmulationModule.cs index 69e48d464085d..ddc0e57a5e8a4 100644 --- a/dotnet/src/webdriver/BiDi/Emulation/EmulationModule.cs +++ b/dotnet/src/webdriver/BiDi/Emulation/EmulationModule.cs @@ -23,7 +23,7 @@ namespace OpenQA.Selenium.BiDi.Emulation; -public sealed class EmulationModule(Broker broker) : Module(broker) +public sealed class EmulationModule : Module { public async Task SetTimezoneOverrideAsync(string? timezone, SetTimezoneOverrideOptions? options = null) { @@ -89,4 +89,9 @@ public async Task SetGeolocationPositionErrorOverrideAsync(SetGeolo return await Broker.ExecuteCommandAsync(new SetGeolocationOverrideCommand(@params), options).ConfigureAwait(false); } + + protected internal override void Initialize(Broker broker) + { + throw new NotImplementedException(); + } } diff --git a/dotnet/src/webdriver/BiDi/Input/InputModule.cs b/dotnet/src/webdriver/BiDi/Input/InputModule.cs index c394ffc0556cb..37e726195984d 100644 --- a/dotnet/src/webdriver/BiDi/Input/InputModule.cs +++ b/dotnet/src/webdriver/BiDi/Input/InputModule.cs @@ -23,7 +23,7 @@ namespace OpenQA.Selenium.BiDi.Input; -public sealed class InputModule(Broker broker) : Module(broker) +public sealed class InputModule : Module { public async Task PerformActionsAsync(BrowsingContext.BrowsingContext context, IEnumerable actions, PerformActionsOptions? options = null) { @@ -45,4 +45,9 @@ public async Task SetFilesAsync(BrowsingContext.BrowsingContext con return await Broker.ExecuteCommandAsync(new SetFilesCommand(@params), options).ConfigureAwait(false); } + + protected internal override void Initialize(Broker broker) + { + throw new System.NotImplementedException(); + } } diff --git a/dotnet/src/webdriver/BiDi/Log/LogModule.cs b/dotnet/src/webdriver/BiDi/Log/LogModule.cs index 2f3d7f22d1738..b47abac8db90d 100644 --- a/dotnet/src/webdriver/BiDi/Log/LogModule.cs +++ b/dotnet/src/webdriver/BiDi/Log/LogModule.cs @@ -23,7 +23,7 @@ namespace OpenQA.Selenium.BiDi.Log; -public sealed class LogModule(Broker broker) : Module(broker) +public sealed class LogModule : Module { public async Task OnEntryAddedAsync(Func handler, SubscriptionOptions? options = null) { @@ -34,4 +34,9 @@ public async Task OnEntryAddedAsync(Action handler, Subs { return await Broker.SubscribeAsync("log.entryAdded", handler, options).ConfigureAwait(false); } + + protected internal override void Initialize(Broker broker) + { + throw new NotImplementedException(); + } } diff --git a/dotnet/src/webdriver/BiDi/Module.cs b/dotnet/src/webdriver/BiDi/Module.cs index 6ab1dc0e9bfaf..4a1b819944ba4 100644 --- a/dotnet/src/webdriver/BiDi/Module.cs +++ b/dotnet/src/webdriver/BiDi/Module.cs @@ -21,7 +21,17 @@ namespace OpenQA.Selenium.BiDi; -public abstract class Module(Broker broker) +public abstract class Module { - protected Broker Broker { get; } = broker; + protected Broker Broker { get; private set; } + + protected internal abstract void Initialize(Broker broker); + + public static TModule Create(Broker broker) where TModule : Module, new() + { + TModule module = new(); + module.Broker = broker; + module.Initialize(broker); + return module; + } } diff --git a/dotnet/src/webdriver/BiDi/Network/NetworkModule.cs b/dotnet/src/webdriver/BiDi/Network/NetworkModule.cs index 74136bfc03bb0..f46c26061439b 100644 --- a/dotnet/src/webdriver/BiDi/Network/NetworkModule.cs +++ b/dotnet/src/webdriver/BiDi/Network/NetworkModule.cs @@ -24,7 +24,7 @@ namespace OpenQA.Selenium.BiDi.Network; -public sealed partial class NetworkModule(Broker broker) : Module(broker) +public sealed partial class NetworkModule : Module { public async Task AddDataCollectorAsync(IEnumerable DataTypes, int MaxEncodedDataSize, AddDataCollectorOptions? options = null) { @@ -173,4 +173,9 @@ public async Task OnAuthRequiredAsync(Action EvaluateAsync(string expression, bool awaitPromise, Target target, EvaluateOptions? options = null) { @@ -105,4 +105,9 @@ public async Task OnRealmDestroyedAsync(Action StatusAsync(StatusOptions? options = null) { @@ -55,4 +55,9 @@ public async Task EndAsync(EndOptions? options = null) { return await Broker.ExecuteCommandAsync(new EndCommand(), options).ConfigureAwait(false); } + + protected internal override void Initialize(Broker broker) + { + throw new System.NotImplementedException(); + } } diff --git a/dotnet/src/webdriver/BiDi/Storage/StorageModule.cs b/dotnet/src/webdriver/BiDi/Storage/StorageModule.cs index 7b51658794519..e66af426deb27 100644 --- a/dotnet/src/webdriver/BiDi/Storage/StorageModule.cs +++ b/dotnet/src/webdriver/BiDi/Storage/StorageModule.cs @@ -22,7 +22,7 @@ namespace OpenQA.Selenium.BiDi.Storage; -public sealed class StorageModule(Broker broker) : Module(broker) +public sealed class StorageModule : Module { public async Task GetCookiesAsync(GetCookiesOptions? options = null) { @@ -44,4 +44,9 @@ public async Task SetCookieAsync(PartialCookie cookie, SetCooki return await Broker.ExecuteCommandAsync(new SetCookieCommand(@params), options).ConfigureAwait(false); } + + protected internal override void Initialize(Broker broker) + { + throw new System.NotImplementedException(); + } } diff --git a/dotnet/src/webdriver/BiDi/WebExtension/WebExtensionModule.cs b/dotnet/src/webdriver/BiDi/WebExtension/WebExtensionModule.cs index 009e01f1e7012..69866d3592214 100644 --- a/dotnet/src/webdriver/BiDi/WebExtension/WebExtensionModule.cs +++ b/dotnet/src/webdriver/BiDi/WebExtension/WebExtensionModule.cs @@ -22,7 +22,7 @@ namespace OpenQA.Selenium.BiDi.WebExtension; -public sealed class WebExtensionModule(Broker broker) : Module(broker) +public sealed class WebExtensionModule : Module { public async Task InstallAsync(ExtensionData extensionData, InstallOptions? options = null) { @@ -37,4 +37,9 @@ public async Task UninstallAsync(Extension extension, UninstallOpti return await Broker.ExecuteCommandAsync(new UninstallCommand(@params), options).ConfigureAwait(false); } + + protected internal override void Initialize(Broker broker) + { + throw new System.NotImplementedException(); + } } From 8e5006882618f2ddd0140ec4e36d94e3ef86c9b1 Mon Sep 17 00:00:00 2001 From: Michael Render Date: Mon, 6 Oct 2025 18:26:26 -0400 Subject: [PATCH 2/3] Refactor so each module controls its own JSON serialization --- .../webdriver/BiDi/Browser/BrowserModule.cs | 25 +++--- .../BrowsingContext/BrowsingContextModule.cs | 87 ++++++++++--------- .../webdriver/BiDi/Communication/Broker.cs | 58 ++++++------- .../BiDi/Emulation/EmulationModule.cs | 25 +++--- .../src/webdriver/BiDi/Input/InputModule.cs | 14 +-- dotnet/src/webdriver/BiDi/Log/LogModule.cs | 11 ++- dotnet/src/webdriver/BiDi/Module.cs | 5 +- .../webdriver/BiDi/Network/NetworkModule.cs | 56 ++++++------ .../src/webdriver/BiDi/Script/ScriptModule.cs | 30 ++++--- .../webdriver/BiDi/Session/SessionModule.cs | 18 ++-- .../webdriver/BiDi/Storage/StorageModule.cs | 14 +-- .../BiDi/WebExtension/WebExtensionModule.cs | 12 ++- 12 files changed, 196 insertions(+), 159 deletions(-) diff --git a/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs b/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs index 66e68b3664dc6..bccf20c3b04cb 100644 --- a/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs +++ b/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs @@ -19,6 +19,7 @@ using OpenQA.Selenium.BiDi.Communication; using System.Collections.Generic; +using System.Text.Json; using System.Text.Json.Serialization; using System.Threading.Tasks; @@ -26,62 +27,66 @@ namespace OpenQA.Selenium.BiDi.Browser; public sealed class BrowserModule : Module { + private BrowserModuleJsonSerializerContext _context = null!; public async Task CloseAsync(CloseOptions? options = null) { - return await Broker.ExecuteCommandAsync(new CloseCommand(), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new CloseCommand(), options, _context).ConfigureAwait(false); } public async Task CreateUserContextAsync(CreateUserContextOptions? options = null) { var @params = new CreateUserContextParameters(options?.AcceptInsecureCerts, options?.Proxy, options?.UnhandledPromptBehavior); - return await Broker.ExecuteCommandAsync(new CreateUserContextCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new CreateUserContextCommand(@params), options, _context).ConfigureAwait(false); } public async Task GetUserContextsAsync(GetUserContextsOptions? options = null) { - return await Broker.ExecuteCommandAsync(new GetUserContextsCommand(), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new GetUserContextsCommand(), options, _context).ConfigureAwait(false); } public async Task RemoveUserContextAsync(UserContext userContext, RemoveUserContextOptions? options = null) { var @params = new RemoveUserContextParameters(userContext); - return await Broker.ExecuteCommandAsync(new RemoveUserContextCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new RemoveUserContextCommand(@params), options, _context).ConfigureAwait(false); } public async Task GetClientWindowsAsync(GetClientWindowsOptions? options = null) { - return await Broker.ExecuteCommandAsync(new(), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new(), options, _context).ConfigureAwait(false); } public async Task SetDownloadBehaviorAllowedAsync(string destinationFolder, SetDownloadBehaviorOptions? options = null) { var @params = new SetDownloadBehaviorParameters(new DownloadBehaviorAllowed(destinationFolder), options?.UserContexts); - return await Broker.ExecuteCommandAsync(new SetDownloadBehaviorCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new SetDownloadBehaviorCommand(@params), options, _context).ConfigureAwait(false); } public async Task SetDownloadBehaviorAllowedAsync(SetDownloadBehaviorOptions? options = null) { var @params = new SetDownloadBehaviorParameters(null, options?.UserContexts); - return await Broker.ExecuteCommandAsync(new SetDownloadBehaviorCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new SetDownloadBehaviorCommand(@params), options, _context).ConfigureAwait(false); } public async Task SetDownloadBehaviorDeniedAsync(SetDownloadBehaviorOptions? options = null) { var @params = new SetDownloadBehaviorParameters(new DownloadBehaviorDenied(), options?.UserContexts); - return await Broker.ExecuteCommandAsync(new SetDownloadBehaviorCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new SetDownloadBehaviorCommand(@params), options, _context).ConfigureAwait(false); } - protected internal override void Initialize(Broker broker) + protected internal override void Initialize(JsonSerializerOptions options) { - broker.ConfigureJsonContext(opts => opts.TypeInfoResolverChain.Add(BrowserModuleJsonSerializerContext.Default)); + _context = new BrowserModuleJsonSerializerContext(options); } } +[JsonSerializable(typeof(Command))] +[JsonSerializable(typeof(EmptyResult))] + [JsonSerializable(typeof(CloseCommand))] [JsonSerializable(typeof(CreateUserContextCommand))] [JsonSerializable(typeof(GetUserContextsCommand))] diff --git a/dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContextModule.cs b/dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContextModule.cs index 4e7062af98cce..b851cb681997e 100644 --- a/dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContextModule.cs +++ b/dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContextModule.cs @@ -18,18 +18,21 @@ // using System; +using System.Text.Json; using System.Threading.Tasks; using OpenQA.Selenium.BiDi.Communication; +using OpenQA.Selenium.BiDi.Communication.Json; namespace OpenQA.Selenium.BiDi.BrowsingContext; public sealed class BrowsingContextModule : Module { + private BiDiJsonSerializerContext _context; public async Task CreateAsync(ContextType type, CreateOptions? options = null) { var @params = new CreateParameters(type, options?.ReferenceContext, options?.Background, options?.UserContext); - var createResult = await Broker.ExecuteCommandAsync(new CreateCommand(@params), options).ConfigureAwait(false); + var createResult = await Broker.ExecuteCommandAsync(new CreateCommand(@params), options, _context).ConfigureAwait(false); return createResult.Context; } @@ -38,221 +41,221 @@ public async Task NavigateAsync(BrowsingContext context, string { var @params = new NavigateParameters(context, url, options?.Wait); - return await Broker.ExecuteCommandAsync(new NavigateCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new NavigateCommand(@params), options, _context).ConfigureAwait(false); } public async Task ActivateAsync(BrowsingContext context, ActivateOptions? options = null) { var @params = new ActivateParameters(context); - return await Broker.ExecuteCommandAsync(new ActivateCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new ActivateCommand(@params), options, _context).ConfigureAwait(false); } public async Task LocateNodesAsync(BrowsingContext context, Locator locator, LocateNodesOptions? options = null) { var @params = new LocateNodesParameters(context, locator, options?.MaxNodeCount, options?.SerializationOptions, options?.StartNodes); - return await Broker.ExecuteCommandAsync(new LocateNodesCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new LocateNodesCommand(@params), options, _context).ConfigureAwait(false); } public async Task CaptureScreenshotAsync(BrowsingContext context, CaptureScreenshotOptions? options = null) { var @params = new CaptureScreenshotParameters(context, options?.Origin, options?.Format, options?.Clip); - return await Broker.ExecuteCommandAsync(new CaptureScreenshotCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new CaptureScreenshotCommand(@params), options, _context).ConfigureAwait(false); } public async Task CloseAsync(BrowsingContext context, CloseOptions? options = null) { var @params = new CloseParameters(context, options?.PromptUnload); - return await Broker.ExecuteCommandAsync(new CloseCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new CloseCommand(@params), options, _context).ConfigureAwait(false); } public async Task TraverseHistoryAsync(BrowsingContext context, int delta, TraverseHistoryOptions? options = null) { var @params = new TraverseHistoryParameters(context, delta); - return await Broker.ExecuteCommandAsync(new TraverseHistoryCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new TraverseHistoryCommand(@params), options, _context).ConfigureAwait(false); } public async Task ReloadAsync(BrowsingContext context, ReloadOptions? options = null) { var @params = new ReloadParameters(context, options?.IgnoreCache, options?.Wait); - return await Broker.ExecuteCommandAsync(new ReloadCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new ReloadCommand(@params), options, _context).ConfigureAwait(false); } public async Task SetViewportAsync(BrowsingContext context, SetViewportOptions? options = null) { var @params = new SetViewportParameters(context, options?.Viewport, options?.DevicePixelRatio); - return await Broker.ExecuteCommandAsync(new SetViewportCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new SetViewportCommand(@params), options, _context).ConfigureAwait(false); } public async Task GetTreeAsync(GetTreeOptions? options = null) { var @params = new GetTreeParameters(options?.MaxDepth, options?.Root); - return await Broker.ExecuteCommandAsync(new GetTreeCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new GetTreeCommand(@params), options, _context).ConfigureAwait(false); } public async Task PrintAsync(BrowsingContext context, PrintOptions? options = null) { var @params = new PrintParameters(context, options?.Background, options?.Margin, options?.Orientation, options?.Page, options?.PageRanges, options?.Scale, options?.ShrinkToFit); - return await Broker.ExecuteCommandAsync(new PrintCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new PrintCommand(@params), options, _context).ConfigureAwait(false); } public async Task HandleUserPromptAsync(BrowsingContext context, HandleUserPromptOptions? options = null) { var @params = new HandleUserPromptParameters(context, options?.Accept, options?.UserText); - return await Broker.ExecuteCommandAsync(new HandleUserPromptCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new HandleUserPromptCommand(@params), options, _context).ConfigureAwait(false); } public async Task OnNavigationStartedAsync(Func handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.navigationStarted", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.navigationStarted", handler, options, _context).ConfigureAwait(false); } public async Task OnNavigationStartedAsync(Action handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.navigationStarted", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.navigationStarted", handler, options, _context).ConfigureAwait(false); } public async Task OnFragmentNavigatedAsync(Func handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.fragmentNavigated", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.fragmentNavigated", handler, options, _context).ConfigureAwait(false); } public async Task OnFragmentNavigatedAsync(Action handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.fragmentNavigated", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.fragmentNavigated", handler, options, _context).ConfigureAwait(false); } public async Task OnHistoryUpdatedAsync(Func handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.historyUpdated", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.historyUpdated", handler, options, _context).ConfigureAwait(false); } public async Task OnHistoryUpdatedAsync(Action handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.historyUpdated", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.historyUpdated", handler, options, _context).ConfigureAwait(false); } public async Task OnDomContentLoadedAsync(Func handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.domContentLoaded", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.domContentLoaded", handler, options, _context).ConfigureAwait(false); } public async Task OnDomContentLoadedAsync(Action handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.domContentLoaded", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.domContentLoaded", handler, options, _context).ConfigureAwait(false); } public async Task OnLoadAsync(Func handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.load", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.load", handler, options, _context).ConfigureAwait(false); } public async Task OnLoadAsync(Action handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.load", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.load", handler, options, _context).ConfigureAwait(false); } public async Task OnDownloadWillBeginAsync(Func handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.downloadWillBegin", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.downloadWillBegin", handler, options, _context).ConfigureAwait(false); } public async Task OnDownloadWillBeginAsync(Action handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.downloadWillBegin", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.downloadWillBegin", handler, options, _context).ConfigureAwait(false); } public async Task OnDownloadEndAsync(Func handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.downloadEnd", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.downloadEnd", handler, options, _context).ConfigureAwait(false); } public async Task OnDownloadEndAsync(Action handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.downloadEnd", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.downloadEnd", handler, options, _context).ConfigureAwait(false); } public async Task OnNavigationAbortedAsync(Func handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.navigationAborted", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.navigationAborted", handler, options, _context).ConfigureAwait(false); } public async Task OnNavigationAbortedAsync(Action handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.navigationAborted", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.navigationAborted", handler, options, _context).ConfigureAwait(false); } public async Task OnNavigationFailedAsync(Func handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.navigationFailed", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.navigationFailed", handler, options, _context).ConfigureAwait(false); } public async Task OnNavigationFailedAsync(Action handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.navigationFailed", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.navigationFailed", handler, options, _context).ConfigureAwait(false); } public async Task OnNavigationCommittedAsync(Func handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.navigationCommitted", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.navigationCommitted", handler, options, _context).ConfigureAwait(false); } public async Task OnNavigationCommittedAsync(Action handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.navigationCommitted", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.navigationCommitted", handler, options, _context).ConfigureAwait(false); } public async Task OnContextCreatedAsync(Func handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.contextCreated", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.contextCreated", handler, options, _context).ConfigureAwait(false); } public async Task OnContextCreatedAsync(Action handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.contextCreated", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.contextCreated", handler, options, _context).ConfigureAwait(false); } public async Task OnContextDestroyedAsync(Func handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.contextDestroyed", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.contextDestroyed", handler, options, _context).ConfigureAwait(false); } public async Task OnContextDestroyedAsync(Action handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.contextDestroyed", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.contextDestroyed", handler, options, _context).ConfigureAwait(false); } public async Task OnUserPromptOpenedAsync(Func handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.userPromptOpened", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.userPromptOpened", handler, options, _context).ConfigureAwait(false); } public async Task OnUserPromptOpenedAsync(Action handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.userPromptOpened", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.userPromptOpened", handler, options, _context).ConfigureAwait(false); } public async Task OnUserPromptClosedAsync(Func handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.userPromptClosed", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.userPromptClosed", handler, options, _context).ConfigureAwait(false); } public async Task OnUserPromptClosedAsync(Action handler, BrowsingContextsSubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("browsingContext.userPromptClosed", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("browsingContext.userPromptClosed", handler, options, _context).ConfigureAwait(false); } - protected internal override void Initialize(Broker broker) + protected internal override void Initialize(JsonSerializerOptions options) { - + _context = new BiDiJsonSerializerContext(options); } } diff --git a/dotnet/src/webdriver/BiDi/Communication/Broker.cs b/dotnet/src/webdriver/BiDi/Communication/Broker.cs index 58c1de5d6cc55..29e6f0f55cc69 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Broker.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Broker.cs @@ -41,7 +41,7 @@ public sealed class Broker : IAsyncDisposable private readonly ConcurrentDictionary _pendingCommands = new(); private readonly BlockingCollection _pendingEvents = []; - private readonly Dictionary _eventTypesMap = []; + private readonly Dictionary _eventTypesMap = []; private readonly ConcurrentDictionary> _eventHandlers = new(); @@ -53,14 +53,20 @@ public sealed class Broker : IAsyncDisposable private Task? _eventEmitterTask; private CancellationTokenSource? _receiveMessagesCancellationTokenSource; - private readonly JsonSerializerOptions _jsonSerializerOptions; - internal Broker(BiDi bidi, Uri url) { _bidi = bidi; _transport = new WebSocketTransport(url); - _jsonSerializerOptions = new JsonSerializerOptions + //_jsonSerializerOptions = CreateOptions(); + + //// Add base BiDi generated context resolver; keep options mutable for module contexts + //_jsonSerializerOptions.TypeInfoResolverChain.Add(BiDiJsonSerializerContext.Default); + } + + public JsonSerializerOptions CreateOptions() + { + return new JsonSerializerOptions { PropertyNameCaseInsensitive = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase, @@ -83,15 +89,6 @@ internal Broker(BiDi bidi, Uri url) new WebExtensionConverter(_bidi), } }; - - // Add base BiDi generated context resolver; keep options mutable for module contexts - _jsonSerializerOptions.TypeInfoResolverChain.Add(BiDiJsonSerializerContext.Default); - } - - public void ConfigureJsonContext(Action action) - { - // Keep options mutable; do not create a context bound to them (avoids InvalidOperationException) - action(_jsonSerializerOptions); } public async Task ConnectAsync(CancellationToken cancellationToken) @@ -175,34 +172,36 @@ private async Task ProcessEventsAwaiterAsync() } } - public async Task ExecuteCommandAsync(TCommand command, CommandOptions? options) + public async Task ExecuteCommandAsync(TCommand command, CommandOptions? options, JsonSerializerContext jsonContext) where TCommand : Command where TResult : EmptyResult { - var result = await ExecuteCommandCoreAsync(command, options).ConfigureAwait(false); + var result = await ExecuteCommandCoreAsync(command, options, jsonContext).ConfigureAwait(false); return (TResult)result; } - private async Task ExecuteCommandCoreAsync(TCommand command, CommandOptions? options) + private async Task ExecuteCommandCoreAsync(TCommand command, CommandOptions? options, JsonSerializerContext jsonContext) where TCommand : Command { command.Id = Interlocked.Increment(ref _currentCommandId); - var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var timeout = options?.Timeout ?? TimeSpan.FromSeconds(30); using var cts = new CancellationTokenSource(timeout); cts.Token.Register(() => tcs.TrySetCanceled(cts.Token)); - _pendingCommands[command.Id] = new(command.Id, command.ResultType, tcs); + var commandInfo = new CommandInfo(command.Id, command.ResultType, tcs); + _pendingCommands[command.Id] = commandInfo; + var data = JsonSerializer.SerializeToUtf8Bytes(command, typeof(TCommand), jsonContext); - var data = JsonSerializer.SerializeToUtf8Bytes(command, typeof(TCommand), _jsonSerializerOptions); await _transport.SendAsync(data, cts.Token).ConfigureAwait(false); - return await tcs.Task.ConfigureAwait(false); + var resultJson = await tcs.Task.ConfigureAwait(false); + return (EmptyResult)JsonSerializer.Deserialize(resultJson, commandInfo.ResultType, jsonContext)!; } - public async Task SubscribeAsync(string eventName, Action action, SubscriptionOptions? options = null) + public async Task SubscribeAsync(string eventName, Action action, SubscriptionOptions? options, JsonSerializerContext jsonContext) where TEventArgs : EventArgs { - _eventTypesMap[eventName] = typeof(TEventArgs); + _eventTypesMap[eventName] = (typeof(TEventArgs), jsonContext); var handlers = _eventHandlers.GetOrAdd(eventName, (a) => []); @@ -228,10 +227,10 @@ public async Task SubscribeAsync(string eventName, Act } } - public async Task SubscribeAsync(string eventName, Func func, SubscriptionOptions? options = null) + public async Task SubscribeAsync(string eventName, Func func, SubscriptionOptions? options, JsonSerializerContext jsonContext) where TEventArgs : EventArgs { - _eventTypesMap[eventName] = typeof(TEventArgs); + _eventTypesMap[eventName] = (typeof(TEventArgs), jsonContext); var handlers = _eventHandlers.GetOrAdd(eventName, (a) => []); @@ -344,8 +343,7 @@ private void ProcessReceivedMessage(byte[]? data) if (_pendingCommands.TryGetValue(id.Value, out var successCommand)) { - var messageSuccess = JsonSerializer.Deserialize(ref resultReader, successCommand.ResultType, _jsonSerializerOptions)!; - successCommand.TaskCompletionSource.SetResult((EmptyResult)messageSuccess); + successCommand.TaskCompletionSource.SetResult(JsonElement.ParseValue(ref resultReader)); _pendingCommands.TryRemove(id.Value, out _); } else @@ -358,9 +356,9 @@ private void ProcessReceivedMessage(byte[]? data) case "event": if (method is null) throw new JsonException("The remote end responded with 'event' message type, but missed required 'method' property."); - if (_eventTypesMap.TryGetValue(method, out var eventType)) + if (_eventTypesMap.TryGetValue(method, out var eventInfo)) { - var eventArgs = (EventArgs)JsonSerializer.Deserialize(ref paramsReader, eventType, _jsonSerializerOptions)!; + var eventArgs = (EventArgs)JsonSerializer.Deserialize(ref paramsReader, eventInfo.EventType, eventInfo.JsonContext)!; var messageEvent = new MessageEvent(method, eventArgs); _pendingEvents.Add(messageEvent); @@ -389,12 +387,12 @@ private void ProcessReceivedMessage(byte[]? data) } } - class CommandInfo(long id, Type resultType, TaskCompletionSource taskCompletionSource) + class CommandInfo(long id, Type resultType, TaskCompletionSource taskCompletionSource) { public long Id { get; } = id; public Type ResultType { get; } = resultType; - public TaskCompletionSource TaskCompletionSource { get; } = taskCompletionSource; + public TaskCompletionSource TaskCompletionSource { get; } = taskCompletionSource; }; } diff --git a/dotnet/src/webdriver/BiDi/Emulation/EmulationModule.cs b/dotnet/src/webdriver/BiDi/Emulation/EmulationModule.cs index ddc0e57a5e8a4..5102828b7b74f 100644 --- a/dotnet/src/webdriver/BiDi/Emulation/EmulationModule.cs +++ b/dotnet/src/webdriver/BiDi/Emulation/EmulationModule.cs @@ -18,53 +18,56 @@ // using System; +using System.Text.Json; using System.Threading.Tasks; using OpenQA.Selenium.BiDi.Communication; +using OpenQA.Selenium.BiDi.Communication.Json; namespace OpenQA.Selenium.BiDi.Emulation; public sealed class EmulationModule : Module { + private BiDiJsonSerializerContext _context = null!; public async Task SetTimezoneOverrideAsync(string? timezone, SetTimezoneOverrideOptions? options = null) { var @params = new SetTimezoneOverrideParameters(timezone, options?.Contexts, options?.UserContexts); - return await Broker.ExecuteCommandAsync(new SetTimezoneOverrideCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new SetTimezoneOverrideCommand(@params), options, _context).ConfigureAwait(false); } public async Task SetUserAgentOverrideAsync(string? userAgent, SetUserAgentOverrideOptions? options = null) { var @params = new SetUserAgentOverrideParameters(userAgent, options?.Contexts, options?.UserContexts); - return await Broker.ExecuteCommandAsync(new SetUserAgentOverrideCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new SetUserAgentOverrideCommand(@params), options, _context).ConfigureAwait(false); } public async Task SetLocaleOverrideAsync(string? locale, SetLocaleOverrideOptions? options = null) { var @params = new SetLocaleOverrideParameters(locale, options?.Contexts, options?.UserContexts); - return await Broker.ExecuteCommandAsync(new SetLocaleOverrideCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new SetLocaleOverrideCommand(@params), options, _context).ConfigureAwait(false); } public async Task SetForcedColorsModeThemeOverrideAsync(ForcedColorsModeTheme? theme, SetForcedColorsModeThemeOverrideOptions? options = null) { var @params = new SetForcedColorsModeThemeOverrideParameters(theme, options?.Contexts, options?.UserContexts); - return await Broker.ExecuteCommandAsync(new SetForcedColorsModeThemeOverrideCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new SetForcedColorsModeThemeOverrideCommand(@params), options, _context).ConfigureAwait(false); } public async Task SetScriptingEnabledAsync(bool? enabled, SetScriptingEnabledOptions? options = null) { var @params = new SetScriptingEnabledParameters(enabled, options?.Contexts, options?.UserContexts); - return await Broker.ExecuteCommandAsync(new SetScriptingEnabledCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new SetScriptingEnabledCommand(@params), options, _context).ConfigureAwait(false); } public async Task SetScreenOrientationOverrideAsync(ScreenOrientation? screenOrientation, SetScreenOrientationOverrideOptions? options = null) { var @params = new SetScreenOrientationOverrideParameters(screenOrientation, options?.Contexts, options?.UserContexts); - return await Broker.ExecuteCommandAsync(new SetScreenOrientationOverrideCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new SetScreenOrientationOverrideCommand(@params), options, _context).ConfigureAwait(false); } public async Task SetGeolocationCoordinatesOverrideAsync(double latitude, double longitude, SetGeolocationCoordinatesOverrideOptions? options = null) @@ -73,25 +76,25 @@ public async Task SetGeolocationCoordinatesOverrideAsync(double lat var @params = new SetGeolocationOverrideCoordinatesParameters(coordinates, options?.Contexts, options?.UserContexts); - return await Broker.ExecuteCommandAsync(new SetGeolocationOverrideCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new SetGeolocationOverrideCommand(@params), options, _context).ConfigureAwait(false); } public async Task SetGeolocationCoordinatesOverrideAsync(SetGeolocationOverrideOptions? options = null) { var @params = new SetGeolocationOverrideCoordinatesParameters(null, options?.Contexts, options?.UserContexts); - return await Broker.ExecuteCommandAsync(new SetGeolocationOverrideCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new SetGeolocationOverrideCommand(@params), options, _context).ConfigureAwait(false); } public async Task SetGeolocationPositionErrorOverrideAsync(SetGeolocationPositionErrorOverrideOptions? options = null) { var @params = new SetGeolocationOverridePositionErrorParameters(new GeolocationPositionError(), options?.Contexts, options?.UserContexts); - return await Broker.ExecuteCommandAsync(new SetGeolocationOverrideCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new SetGeolocationOverrideCommand(@params), options, _context).ConfigureAwait(false); } - protected internal override void Initialize(Broker broker) + protected internal override void Initialize(JsonSerializerOptions options) { - throw new NotImplementedException(); + _context = new BiDiJsonSerializerContext(options); } } diff --git a/dotnet/src/webdriver/BiDi/Input/InputModule.cs b/dotnet/src/webdriver/BiDi/Input/InputModule.cs index 37e726195984d..159d577e83930 100644 --- a/dotnet/src/webdriver/BiDi/Input/InputModule.cs +++ b/dotnet/src/webdriver/BiDi/Input/InputModule.cs @@ -18,36 +18,40 @@ // using OpenQA.Selenium.BiDi.Communication; +using OpenQA.Selenium.BiDi.Communication.Json; using System.Collections.Generic; +using System.Text.Json; using System.Threading.Tasks; namespace OpenQA.Selenium.BiDi.Input; public sealed class InputModule : Module { + private BiDiJsonSerializerContext _context = null!; + public async Task PerformActionsAsync(BrowsingContext.BrowsingContext context, IEnumerable actions, PerformActionsOptions? options = null) { var @params = new PerformActionsParameters(context, actions); - return await Broker.ExecuteCommandAsync(new PerformActionsCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new PerformActionsCommand(@params), options, _context).ConfigureAwait(false); } public async Task ReleaseActionsAsync(BrowsingContext.BrowsingContext context, ReleaseActionsOptions? options = null) { var @params = new ReleaseActionsParameters(context); - return await Broker.ExecuteCommandAsync(new ReleaseActionsCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new ReleaseActionsCommand(@params), options, _context).ConfigureAwait(false); } public async Task SetFilesAsync(BrowsingContext.BrowsingContext context, Script.ISharedReference element, IEnumerable files, SetFilesOptions? options = null) { var @params = new SetFilesParameters(context, element, files); - return await Broker.ExecuteCommandAsync(new SetFilesCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new SetFilesCommand(@params), options, _context).ConfigureAwait(false); } - protected internal override void Initialize(Broker broker) + protected internal override void Initialize(JsonSerializerOptions options) { - throw new System.NotImplementedException(); + _context = new BiDiJsonSerializerContext(options); } } diff --git a/dotnet/src/webdriver/BiDi/Log/LogModule.cs b/dotnet/src/webdriver/BiDi/Log/LogModule.cs index b47abac8db90d..9e349e0e3271b 100644 --- a/dotnet/src/webdriver/BiDi/Log/LogModule.cs +++ b/dotnet/src/webdriver/BiDi/Log/LogModule.cs @@ -20,23 +20,26 @@ using System.Threading.Tasks; using System; using OpenQA.Selenium.BiDi.Communication; +using System.Text.Json; +using OpenQA.Selenium.BiDi.Communication.Json; namespace OpenQA.Selenium.BiDi.Log; public sealed class LogModule : Module { + private BiDiJsonSerializerContext _context = null!; public async Task OnEntryAddedAsync(Func handler, SubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("log.entryAdded", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("log.entryAdded", handler, options, _context).ConfigureAwait(false); } public async Task OnEntryAddedAsync(Action handler, SubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("log.entryAdded", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("log.entryAdded", handler, options, _context).ConfigureAwait(false); } - protected internal override void Initialize(Broker broker) + protected internal override void Initialize(JsonSerializerOptions options) { - throw new NotImplementedException(); + _context = new BiDiJsonSerializerContext(options); } } diff --git a/dotnet/src/webdriver/BiDi/Module.cs b/dotnet/src/webdriver/BiDi/Module.cs index 4a1b819944ba4..407324282ed83 100644 --- a/dotnet/src/webdriver/BiDi/Module.cs +++ b/dotnet/src/webdriver/BiDi/Module.cs @@ -18,6 +18,7 @@ // using OpenQA.Selenium.BiDi.Communication; +using System.Text.Json; namespace OpenQA.Selenium.BiDi; @@ -25,13 +26,13 @@ public abstract class Module { protected Broker Broker { get; private set; } - protected internal abstract void Initialize(Broker broker); + protected internal abstract void Initialize(JsonSerializerOptions options); public static TModule Create(Broker broker) where TModule : Module, new() { TModule module = new(); module.Broker = broker; - module.Initialize(broker); + module.Initialize(broker.CreateOptions()); return module; } } diff --git a/dotnet/src/webdriver/BiDi/Network/NetworkModule.cs b/dotnet/src/webdriver/BiDi/Network/NetworkModule.cs index f46c26061439b..6a37e07916bcf 100644 --- a/dotnet/src/webdriver/BiDi/Network/NetworkModule.cs +++ b/dotnet/src/webdriver/BiDi/Network/NetworkModule.cs @@ -19,18 +19,22 @@ using System; using System.Collections.Generic; +using System.Text.Json; using System.Threading.Tasks; using OpenQA.Selenium.BiDi.Communication; +using OpenQA.Selenium.BiDi.Communication.Json; namespace OpenQA.Selenium.BiDi.Network; public sealed partial class NetworkModule : Module { + private BiDiJsonSerializerContext _context = null!; + public async Task AddDataCollectorAsync(IEnumerable DataTypes, int MaxEncodedDataSize, AddDataCollectorOptions? options = null) { var @params = new AddDataCollectorParameters(DataTypes, MaxEncodedDataSize, options?.CollectorType, options?.Contexts, options?.UserContexts); - var result = await Broker.ExecuteCommandAsync(new AddDataCollectorCommand(@params), options).ConfigureAwait(false); + var result = await Broker.ExecuteCommandAsync(new AddDataCollectorCommand(@params), options, _context).ConfigureAwait(false); return result.Collector; } @@ -39,7 +43,7 @@ public async Task AddInterceptAsync(IEnumerable phase { var @params = new AddInterceptParameters(phases, options?.Contexts, options?.UrlPatterns); - var result = await Broker.ExecuteCommandAsync(new AddInterceptCommand(@params), options).ConfigureAwait(false); + var result = await Broker.ExecuteCommandAsync(new AddInterceptCommand(@params), options, _context).ConfigureAwait(false); return result.Intercept; } @@ -48,56 +52,56 @@ public async Task RemoveDataCollectorAsync(Collector collector, Rem { var @params = new RemoveDataCollectorParameters(collector); - return await Broker.ExecuteCommandAsync(new RemoveDataCollectorCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new RemoveDataCollectorCommand(@params), options, _context).ConfigureAwait(false); } public async Task RemoveInterceptAsync(Intercept intercept, RemoveInterceptOptions? options = null) { var @params = new RemoveInterceptParameters(intercept); - return await Broker.ExecuteCommandAsync(new RemoveInterceptCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new RemoveInterceptCommand(@params), options, _context).ConfigureAwait(false); } public async Task SetCacheBehaviorAsync(CacheBehavior behavior, SetCacheBehaviorOptions? options = null) { var @params = new SetCacheBehaviorParameters(behavior, options?.Contexts); - return await Broker.ExecuteCommandAsync(new SetCacheBehaviorCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new SetCacheBehaviorCommand(@params), options, _context).ConfigureAwait(false); } public async Task SetExtraHeadersAsync(IEnumerable
headers, SetExtraHeadersOptions? options = null) { var @params = new SetExtraHeadersParameters(headers, options?.Contexts, options?.UserContexts); - return await Broker.ExecuteCommandAsync(new SetExtraHeadersCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new SetExtraHeadersCommand(@params), options, _context).ConfigureAwait(false); } public async Task ContinueRequestAsync(Request request, ContinueRequestOptions? options = null) { var @params = new ContinueRequestParameters(request, options?.Body, options?.Cookies, options?.Headers, options?.Method, options?.Url); - return await Broker.ExecuteCommandAsync(new ContinueRequestCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new ContinueRequestCommand(@params), options, _context).ConfigureAwait(false); } public async Task ContinueResponseAsync(Request request, ContinueResponseOptions? options = null) { var @params = new ContinueResponseParameters(request, options?.Cookies, options?.Credentials, options?.Headers, options?.ReasonPhrase, options?.StatusCode); - return await Broker.ExecuteCommandAsync(new ContinueResponseCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new ContinueResponseCommand(@params), options, _context).ConfigureAwait(false); } public async Task FailRequestAsync(Request request, FailRequestOptions? options = null) { var @params = new FailRequestParameters(request); - return await Broker.ExecuteCommandAsync(new FailRequestCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new FailRequestCommand(@params), options, _context).ConfigureAwait(false); } public async Task GetDataAsync(DataType dataType, Request request, GetDataOptions? options = null) { var @params = new GetDataParameters(dataType, request, options?.Collector, options?.Disown); - var result = await Broker.ExecuteCommandAsync(new GetDataCommand(@params), options).ConfigureAwait(false); + var result = await Broker.ExecuteCommandAsync(new GetDataCommand(@params), options, _context).ConfigureAwait(false); return result.Bytes; } @@ -106,76 +110,76 @@ public async Task ProvideResponseAsync(Request request, ProvideResp { var @params = new ProvideResponseParameters(request, options?.Body, options?.Cookies, options?.Headers, options?.ReasonPhrase, options?.StatusCode); - return await Broker.ExecuteCommandAsync(new ProvideResponseCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new ProvideResponseCommand(@params), options, _context).ConfigureAwait(false); } public async Task ContinueWithAuthAsync(Request request, AuthCredentials credentials, ContinueWithAuthCredentialsOptions? options = null) { - return await Broker.ExecuteCommandAsync(new ContinueWithAuthCommand(new ContinueWithAuthCredentials(request, credentials)), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new ContinueWithAuthCommand(new ContinueWithAuthCredentials(request, credentials)), options, _context).ConfigureAwait(false); } public async Task ContinueWithAuthAsync(Request request, ContinueWithAuthDefaultCredentialsOptions? options = null) { - return await Broker.ExecuteCommandAsync(new ContinueWithAuthCommand(new ContinueWithAuthDefaultCredentials(request)), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new ContinueWithAuthCommand(new ContinueWithAuthDefaultCredentials(request)), options, _context).ConfigureAwait(false); } public async Task ContinueWithAuthAsync(Request request, ContinueWithAuthCancelCredentialsOptions? options = null) { - return await Broker.ExecuteCommandAsync(new ContinueWithAuthCommand(new ContinueWithAuthCancelCredentials(request)), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new ContinueWithAuthCommand(new ContinueWithAuthCancelCredentials(request)), options, _context).ConfigureAwait(false); } public async Task OnBeforeRequestSentAsync(Func handler, SubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("network.beforeRequestSent", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("network.beforeRequestSent", handler, options, _context).ConfigureAwait(false); } public async Task OnBeforeRequestSentAsync(Action handler, SubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("network.beforeRequestSent", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("network.beforeRequestSent", handler, options, _context).ConfigureAwait(false); } public async Task OnResponseStartedAsync(Func handler, SubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("network.responseStarted", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("network.responseStarted", handler, options, _context).ConfigureAwait(false); } public async Task OnResponseStartedAsync(Action handler, SubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("network.responseStarted", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("network.responseStarted", handler, options, _context).ConfigureAwait(false); } public async Task OnResponseCompletedAsync(Func handler, SubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("network.responseCompleted", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("network.responseCompleted", handler, options, _context).ConfigureAwait(false); } public async Task OnResponseCompletedAsync(Action handler, SubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("network.responseCompleted", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("network.responseCompleted", handler, options, _context).ConfigureAwait(false); } public async Task OnFetchErrorAsync(Func handler, SubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("network.fetchError", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("network.fetchError", handler, options, _context).ConfigureAwait(false); } public async Task OnFetchErrorAsync(Action handler, SubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("network.fetchError", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("network.fetchError", handler, options, _context).ConfigureAwait(false); } public async Task OnAuthRequiredAsync(Func handler, SubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("network.authRequired", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("network.authRequired", handler, options, _context).ConfigureAwait(false); } public async Task OnAuthRequiredAsync(Action handler, SubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("network.authRequired", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("network.authRequired", handler, options, _context).ConfigureAwait(false); } - protected internal override void Initialize(Broker broker) + protected internal override void Initialize(JsonSerializerOptions options) { - throw new System.NotImplementedException(); + _context = new BiDiJsonSerializerContext(options); } } diff --git a/dotnet/src/webdriver/BiDi/Script/ScriptModule.cs b/dotnet/src/webdriver/BiDi/Script/ScriptModule.cs index 5dfa4532a4de2..dae59ac1903db 100644 --- a/dotnet/src/webdriver/BiDi/Script/ScriptModule.cs +++ b/dotnet/src/webdriver/BiDi/Script/ScriptModule.cs @@ -18,18 +18,22 @@ // using OpenQA.Selenium.BiDi.Communication; +using OpenQA.Selenium.BiDi.Communication.Json; using System; +using System.Text.Json; using System.Threading.Tasks; namespace OpenQA.Selenium.BiDi.Script; public sealed class ScriptModule : Module { + private BiDiJsonSerializerContext _context = null!; + public async Task EvaluateAsync(string expression, bool awaitPromise, Target target, EvaluateOptions? options = null) { var @params = new EvaluateParameters(expression, target, awaitPromise, options?.ResultOwnership, options?.SerializationOptions, options?.UserActivation); - return await Broker.ExecuteCommandAsync(new EvaluateCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new EvaluateCommand(@params), options, _context).ConfigureAwait(false); } public async Task EvaluateAsync(string expression, bool awaitPromise, Target target, EvaluateOptions? options = null) @@ -43,7 +47,7 @@ public async Task CallFunctionAsync(string functionDeclaration, { var @params = new CallFunctionParameters(functionDeclaration, awaitPromise, target, options?.Arguments, options?.ResultOwnership, options?.SerializationOptions, options?.This, options?.UserActivation); - return await Broker.ExecuteCommandAsync(new CallFunctionCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new CallFunctionCommand(@params), options, _context).ConfigureAwait(false); } public async Task CallFunctionAsync(string functionDeclaration, bool awaitPromise, Target target, CallFunctionOptions? options = null) @@ -57,14 +61,14 @@ public async Task GetRealmsAsync(GetRealmsOptions? options = nu { var @params = new GetRealmsParameters(options?.Context, options?.Type); - return await Broker.ExecuteCommandAsync(new GetRealmsCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new GetRealmsCommand(@params), options, _context).ConfigureAwait(false); } public async Task AddPreloadScriptAsync(string functionDeclaration, AddPreloadScriptOptions? options = null) { var @params = new AddPreloadScriptParameters(functionDeclaration, options?.Arguments, options?.Contexts, options?.Sandbox); - var result = await Broker.ExecuteCommandAsync(new AddPreloadScriptCommand(@params), options).ConfigureAwait(false); + var result = await Broker.ExecuteCommandAsync(new AddPreloadScriptCommand(@params), options, _context).ConfigureAwait(false); return result.Script; } @@ -73,41 +77,41 @@ public async Task RemovePreloadScriptAsync(PreloadScript script, Re { var @params = new RemovePreloadScriptParameters(script); - return await Broker.ExecuteCommandAsync(new RemovePreloadScriptCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new RemovePreloadScriptCommand(@params), options, _context).ConfigureAwait(false); } public async Task OnMessageAsync(Func handler, SubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("script.message", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("script.message", handler, options, _context).ConfigureAwait(false); } public async Task OnMessageAsync(Action handler, SubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("script.message", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("script.message", handler, options, _context).ConfigureAwait(false); } public async Task OnRealmCreatedAsync(Func handler, SubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("script.realmCreated", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("script.realmCreated", handler, options, _context).ConfigureAwait(false); } public async Task OnRealmCreatedAsync(Action handler, SubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("script.realmCreated", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("script.realmCreated", handler, options, _context).ConfigureAwait(false); } public async Task OnRealmDestroyedAsync(Func handler, SubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("script.realmDestroyed", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("script.realmDestroyed", handler, options, _context).ConfigureAwait(false); } public async Task OnRealmDestroyedAsync(Action handler, SubscriptionOptions? options = null) { - return await Broker.SubscribeAsync("script.realmDestroyed", handler, options).ConfigureAwait(false); + return await Broker.SubscribeAsync("script.realmDestroyed", handler, options, _context).ConfigureAwait(false); } - protected internal override void Initialize(Broker broker) + protected internal override void Initialize(JsonSerializerOptions options) { - throw new NotImplementedException(); + _context = new BiDiJsonSerializerContext(options); } } diff --git a/dotnet/src/webdriver/BiDi/Session/SessionModule.cs b/dotnet/src/webdriver/BiDi/Session/SessionModule.cs index 5b2ecf912b615..2d9f5319753ba 100644 --- a/dotnet/src/webdriver/BiDi/Session/SessionModule.cs +++ b/dotnet/src/webdriver/BiDi/Session/SessionModule.cs @@ -18,46 +18,50 @@ // using OpenQA.Selenium.BiDi.Communication; +using OpenQA.Selenium.BiDi.Communication.Json; using System.Collections.Generic; +using System.Text.Json; using System.Threading.Tasks; namespace OpenQA.Selenium.BiDi.Session; internal sealed class SessionModule : Module { + private BiDiJsonSerializerContext _context = null!; + public async Task StatusAsync(StatusOptions? options = null) { - return await Broker.ExecuteCommandAsync(new StatusCommand(), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new StatusCommand(), options, _context).ConfigureAwait(false); } public async Task SubscribeAsync(IEnumerable events, SubscribeOptions? options = null) { var @params = new SubscribeParameters(events, options?.Contexts); - return await Broker.ExecuteCommandAsync(new(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new(@params), options, _context).ConfigureAwait(false); } public async Task UnsubscribeAsync(IEnumerable subscriptions, UnsubscribeByIdOptions? options = null) { var @params = new UnsubscribeByIdParameters(subscriptions); - return await Broker.ExecuteCommandAsync(new UnsubscribeByIdCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new UnsubscribeByIdCommand(@params), options, _context).ConfigureAwait(false); } public async Task NewAsync(CapabilitiesRequest capabilitiesRequest, NewOptions? options = null) { var @params = new NewParameters(capabilitiesRequest); - return await Broker.ExecuteCommandAsync(new NewCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new NewCommand(@params), options, _context).ConfigureAwait(false); } public async Task EndAsync(EndOptions? options = null) { - return await Broker.ExecuteCommandAsync(new EndCommand(), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new EndCommand(), options, _context).ConfigureAwait(false); } - protected internal override void Initialize(Broker broker) + protected internal override void Initialize(JsonSerializerOptions options) { - throw new System.NotImplementedException(); + _context = new BiDiJsonSerializerContext(options); } } diff --git a/dotnet/src/webdriver/BiDi/Storage/StorageModule.cs b/dotnet/src/webdriver/BiDi/Storage/StorageModule.cs index e66af426deb27..43bf9c2afbfac 100644 --- a/dotnet/src/webdriver/BiDi/Storage/StorageModule.cs +++ b/dotnet/src/webdriver/BiDi/Storage/StorageModule.cs @@ -18,35 +18,39 @@ // using OpenQA.Selenium.BiDi.Communication; +using OpenQA.Selenium.BiDi.Communication.Json; +using System.Text.Json; using System.Threading.Tasks; namespace OpenQA.Selenium.BiDi.Storage; public sealed class StorageModule : Module { + private BiDiJsonSerializerContext _context = null!; + public async Task GetCookiesAsync(GetCookiesOptions? options = null) { var @params = new GetCookiesParameters(options?.Filter, options?.Partition); - return await Broker.ExecuteCommandAsync(new GetCookiesCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new GetCookiesCommand(@params), options, _context).ConfigureAwait(false); } public async Task DeleteCookiesAsync(DeleteCookiesOptions? options = null) { var @params = new DeleteCookiesParameters(options?.Filter, options?.Partition); - return await Broker.ExecuteCommandAsync(new DeleteCookiesCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new DeleteCookiesCommand(@params), options, _context).ConfigureAwait(false); } public async Task SetCookieAsync(PartialCookie cookie, SetCookieOptions? options = null) { var @params = new SetCookieParameters(cookie, options?.Partition); - return await Broker.ExecuteCommandAsync(new SetCookieCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new SetCookieCommand(@params), options, _context).ConfigureAwait(false); } - protected internal override void Initialize(Broker broker) + protected internal override void Initialize(JsonSerializerOptions options) { - throw new System.NotImplementedException(); + _context = new BiDiJsonSerializerContext(options); } } diff --git a/dotnet/src/webdriver/BiDi/WebExtension/WebExtensionModule.cs b/dotnet/src/webdriver/BiDi/WebExtension/WebExtensionModule.cs index 69866d3592214..c57fe2b67c72e 100644 --- a/dotnet/src/webdriver/BiDi/WebExtension/WebExtensionModule.cs +++ b/dotnet/src/webdriver/BiDi/WebExtension/WebExtensionModule.cs @@ -18,28 +18,32 @@ // using OpenQA.Selenium.BiDi.Communication; +using OpenQA.Selenium.BiDi.Communication.Json; +using System.Text.Json; using System.Threading.Tasks; namespace OpenQA.Selenium.BiDi.WebExtension; public sealed class WebExtensionModule : Module { + private BiDiJsonSerializerContext _context = null!; + public async Task InstallAsync(ExtensionData extensionData, InstallOptions? options = null) { var @params = new InstallParameters(extensionData); - return await Broker.ExecuteCommandAsync(new InstallCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new InstallCommand(@params), options, _context).ConfigureAwait(false); } public async Task UninstallAsync(Extension extension, UninstallOptions? options = null) { var @params = new UninstallParameters(extension); - return await Broker.ExecuteCommandAsync(new UninstallCommand(@params), options).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new UninstallCommand(@params), options, _context).ConfigureAwait(false); } - protected internal override void Initialize(Broker broker) + protected internal override void Initialize(JsonSerializerOptions options) { - throw new System.NotImplementedException(); + _context = new BiDiJsonSerializerContext(options); } } From 283376ecf12c1e7dc8abe8a4b4e6dedfabb56793 Mon Sep 17 00:00:00 2001 From: Michael Render Date: Mon, 6 Oct 2025 18:31:54 -0400 Subject: [PATCH 3/3] Remove commented code --- dotnet/src/webdriver/BiDi/Communication/Broker.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dotnet/src/webdriver/BiDi/Communication/Broker.cs b/dotnet/src/webdriver/BiDi/Communication/Broker.cs index 29e6f0f55cc69..0b2ec9a1d3ed7 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Broker.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Broker.cs @@ -57,11 +57,6 @@ internal Broker(BiDi bidi, Uri url) { _bidi = bidi; _transport = new WebSocketTransport(url); - - //_jsonSerializerOptions = CreateOptions(); - - //// Add base BiDi generated context resolver; keep options mutable for module contexts - //_jsonSerializerOptions.TypeInfoResolverChain.Add(BiDiJsonSerializerContext.Default); } public JsonSerializerOptions CreateOptions()