Skip to content

Commit 90a1030

Browse files
authored
[dotnet] [bidi] Modules as extensions (#16392)
1 parent 4e5a674 commit 90a1030

File tree

13 files changed

+208
-308
lines changed

13 files changed

+208
-308
lines changed

dotnet/src/webdriver/BiDi/BiDi.cs

Lines changed: 46 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -18,164 +18,81 @@
1818
// </copyright>
1919

2020
using System;
21+
using System.Collections.Concurrent;
22+
using System.Text.Json;
23+
using System.Text.Json.Serialization;
2124
using System.Threading;
2225
using System.Threading.Tasks;
2326
using OpenQA.Selenium.BiDi.Communication;
27+
using OpenQA.Selenium.BiDi.Communication.Json;
28+
using OpenQA.Selenium.BiDi.Communication.Json.Converters;
2429

2530
namespace OpenQA.Selenium.BiDi;
2631

2732
public sealed class BiDi : IAsyncDisposable
2833
{
2934
private readonly Broker _broker;
35+
private readonly JsonSerializerOptions _jsonOptions;
36+
private readonly BiDiJsonSerializerContext _jsonContext;
3037

31-
private Session.SessionModule? _sessionModule;
32-
private BrowsingContext.BrowsingContextModule? _browsingContextModule;
33-
private Browser.BrowserModule? _browserModule;
34-
private Network.NetworkModule? _networkModule;
35-
private Input.InputModule? _inputModule;
36-
private Script.ScriptModule? _scriptModule;
37-
private Log.LogModule? _logModule;
38-
private Storage.StorageModule? _storageModule;
39-
private WebExtension.WebExtensionModule? _webExtensionModule;
40-
private Emulation.EmulationModule? _emulationModule;
41-
42-
private readonly object _moduleLock = new();
38+
private readonly ConcurrentDictionary<Type, Module> _modules = [];
4339

4440
private BiDi(string url)
4541
{
4642
var uri = new Uri(url);
4743

48-
_broker = new Broker(this, uri);
49-
}
50-
51-
internal Session.SessionModule SessionModule
52-
{
53-
get
44+
_jsonOptions = new JsonSerializerOptions
5445
{
55-
if (_sessionModule is not null) return _sessionModule;
56-
lock (_moduleLock)
46+
PropertyNameCaseInsensitive = true,
47+
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
48+
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
49+
50+
// BiDi returns special numbers such as "NaN" as strings
51+
// Additionally, -0 is returned as a string "-0"
52+
NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals | JsonNumberHandling.AllowReadingFromString,
53+
Converters =
5754
{
58-
_sessionModule ??= new Session.SessionModule(_broker);
55+
new BrowsingContextConverter(this),
56+
new BrowserUserContextConverter(this),
57+
new CollectorConverter(this),
58+
new InterceptConverter(this),
59+
new HandleConverter(this),
60+
new InternalIdConverter(this),
61+
new PreloadScriptConverter(this),
62+
new RealmConverter(this),
63+
new DateTimeOffsetConverter(),
64+
new WebExtensionConverter(this),
5965
}
60-
return _sessionModule;
61-
}
62-
}
66+
};
6367

64-
public BrowsingContext.BrowsingContextModule BrowsingContext
65-
{
66-
get
67-
{
68-
if (_browsingContextModule is not null) return _browsingContextModule;
69-
lock (_moduleLock)
70-
{
71-
_browsingContextModule ??= new BrowsingContext.BrowsingContextModule(_broker);
72-
}
73-
return _browsingContextModule;
74-
}
75-
}
68+
_jsonContext = new BiDiJsonSerializerContext(_jsonOptions);
7669

77-
public Browser.BrowserModule Browser
78-
{
79-
get
80-
{
81-
if (_browserModule is not null) return _browserModule;
82-
lock (_moduleLock)
83-
{
84-
_browserModule ??= new Browser.BrowserModule(_broker);
85-
}
86-
return _browserModule;
87-
}
70+
_broker = new Broker(this, uri, _jsonOptions);
8871
}
8972

90-
public Network.NetworkModule Network
91-
{
92-
get
93-
{
94-
if (_networkModule is not null) return _networkModule;
95-
lock (_moduleLock)
96-
{
97-
_networkModule ??= new Network.NetworkModule(_broker);
98-
}
99-
return _networkModule;
100-
}
101-
}
73+
internal Session.SessionModule SessionModule => AsModule<Session.SessionModule>();
10274

103-
internal Input.InputModule InputModule
104-
{
105-
get
106-
{
107-
if (_inputModule is not null) return _inputModule;
108-
lock (_moduleLock)
109-
{
110-
_inputModule ??= new Input.InputModule(_broker);
111-
}
112-
return _inputModule;
113-
}
114-
}
75+
public BrowsingContext.BrowsingContextModule BrowsingContext => AsModule<BrowsingContext.BrowsingContextModule>();
11576

116-
public Script.ScriptModule Script
117-
{
118-
get
119-
{
120-
if (_scriptModule is not null) return _scriptModule;
121-
lock (_moduleLock)
122-
{
123-
_scriptModule ??= new Script.ScriptModule(_broker);
124-
}
125-
return _scriptModule;
126-
}
127-
}
77+
public Browser.BrowserModule Browser => AsModule<Browser.BrowserModule>();
12878

129-
public Log.LogModule Log
130-
{
131-
get
132-
{
133-
if (_logModule is not null) return _logModule;
134-
lock (_moduleLock)
135-
{
136-
_logModule ??= new Log.LogModule(_broker);
137-
}
138-
return _logModule;
139-
}
140-
}
79+
public Network.NetworkModule Network => AsModule<Network.NetworkModule>();
14180

142-
public Storage.StorageModule Storage
143-
{
144-
get
145-
{
146-
if (_storageModule is not null) return _storageModule;
147-
lock (_moduleLock)
148-
{
149-
_storageModule ??= new Storage.StorageModule(_broker);
150-
}
151-
return _storageModule;
152-
}
153-
}
81+
internal Input.InputModule InputModule => AsModule<Input.InputModule>();
15482

155-
public WebExtension.WebExtensionModule WebExtension
156-
{
157-
get
158-
{
159-
if (_webExtensionModule is not null) return _webExtensionModule;
160-
lock (_moduleLock)
161-
{
162-
_webExtensionModule ??= new WebExtension.WebExtensionModule(_broker);
163-
}
164-
return _webExtensionModule;
165-
}
166-
}
83+
public Script.ScriptModule Script => AsModule<Script.ScriptModule>();
84+
85+
public Log.LogModule Log => AsModule<Log.LogModule>();
16786

168-
public Emulation.EmulationModule Emulation
87+
public Storage.StorageModule Storage => AsModule<Storage.StorageModule>();
88+
89+
public WebExtension.WebExtensionModule WebExtension => AsModule<WebExtension.WebExtensionModule>();
90+
91+
public Emulation.EmulationModule Emulation => AsModule<Emulation.EmulationModule>();
92+
93+
public TModule AsModule<TModule>() where TModule : Module, new()
16994
{
170-
get
171-
{
172-
if (_emulationModule is not null) return _emulationModule;
173-
lock (_moduleLock)
174-
{
175-
_emulationModule ??= new Emulation.EmulationModule(_broker);
176-
}
177-
return _emulationModule;
178-
}
95+
return (TModule)_modules.GetOrAdd(typeof(TModule), _ => Module.Create<TModule>(this, _broker, _jsonOptions, _jsonContext));
17996
}
18097

18198
public Task<Session.StatusResult> StatusAsync()

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,60 +17,60 @@
1717
// under the License.
1818
// </copyright>
1919

20-
using System.Threading.Tasks;
2120
using OpenQA.Selenium.BiDi.Communication;
21+
using System.Threading.Tasks;
2222

2323
namespace OpenQA.Selenium.BiDi.Browser;
2424

25-
public sealed class BrowserModule(Broker broker) : Module(broker)
25+
public sealed class BrowserModule : Module
2626
{
2727
public async Task<EmptyResult> CloseAsync(CloseOptions? options = null)
2828
{
29-
return await Broker.ExecuteCommandAsync<CloseCommand, EmptyResult>(new CloseCommand(), options).ConfigureAwait(false);
29+
return await Broker.ExecuteCommandAsync<CloseCommand, EmptyResult>(new CloseCommand(), options, JsonContext).ConfigureAwait(false);
3030
}
3131

3232
public async Task<UserContextInfo> CreateUserContextAsync(CreateUserContextOptions? options = null)
3333
{
3434
var @params = new CreateUserContextParameters(options?.AcceptInsecureCerts, options?.Proxy, options?.UnhandledPromptBehavior);
3535

36-
return await Broker.ExecuteCommandAsync<CreateUserContextCommand, UserContextInfo>(new CreateUserContextCommand(@params), options).ConfigureAwait(false);
36+
return await Broker.ExecuteCommandAsync<CreateUserContextCommand, UserContextInfo>(new CreateUserContextCommand(@params), options, JsonContext).ConfigureAwait(false);
3737
}
3838

3939
public async Task<GetUserContextsResult> GetUserContextsAsync(GetUserContextsOptions? options = null)
4040
{
41-
return await Broker.ExecuteCommandAsync<GetUserContextsCommand, GetUserContextsResult>(new GetUserContextsCommand(), options).ConfigureAwait(false);
41+
return await Broker.ExecuteCommandAsync<GetUserContextsCommand, GetUserContextsResult>(new GetUserContextsCommand(), options, JsonContext).ConfigureAwait(false);
4242
}
4343

4444
public async Task<EmptyResult> RemoveUserContextAsync(UserContext userContext, RemoveUserContextOptions? options = null)
4545
{
4646
var @params = new RemoveUserContextParameters(userContext);
4747

48-
return await Broker.ExecuteCommandAsync<RemoveUserContextCommand, EmptyResult>(new RemoveUserContextCommand(@params), options).ConfigureAwait(false);
48+
return await Broker.ExecuteCommandAsync<RemoveUserContextCommand, EmptyResult>(new RemoveUserContextCommand(@params), options, JsonContext).ConfigureAwait(false);
4949
}
5050

5151
public async Task<GetClientWindowsResult> GetClientWindowsAsync(GetClientWindowsOptions? options = null)
5252
{
53-
return await Broker.ExecuteCommandAsync<GetClientWindowsCommand, GetClientWindowsResult>(new(), options).ConfigureAwait(false);
53+
return await Broker.ExecuteCommandAsync<GetClientWindowsCommand, GetClientWindowsResult>(new(), options, JsonContext).ConfigureAwait(false);
5454
}
5555

5656
public async Task<EmptyResult> SetDownloadBehaviorAllowedAsync(string destinationFolder, SetDownloadBehaviorOptions? options = null)
5757
{
5858
var @params = new SetDownloadBehaviorParameters(new DownloadBehaviorAllowed(destinationFolder), options?.UserContexts);
5959

60-
return await Broker.ExecuteCommandAsync<SetDownloadBehaviorCommand, EmptyResult>(new SetDownloadBehaviorCommand(@params), options).ConfigureAwait(false);
60+
return await Broker.ExecuteCommandAsync<SetDownloadBehaviorCommand, EmptyResult>(new SetDownloadBehaviorCommand(@params), options, JsonContext).ConfigureAwait(false);
6161
}
6262

6363
public async Task<EmptyResult> SetDownloadBehaviorAllowedAsync(SetDownloadBehaviorOptions? options = null)
6464
{
6565
var @params = new SetDownloadBehaviorParameters(null, options?.UserContexts);
6666

67-
return await Broker.ExecuteCommandAsync<SetDownloadBehaviorCommand, EmptyResult>(new SetDownloadBehaviorCommand(@params), options).ConfigureAwait(false);
67+
return await Broker.ExecuteCommandAsync<SetDownloadBehaviorCommand, EmptyResult>(new SetDownloadBehaviorCommand(@params), options, JsonContext).ConfigureAwait(false);
6868
}
6969

7070
public async Task<EmptyResult> SetDownloadBehaviorDeniedAsync(SetDownloadBehaviorOptions? options = null)
7171
{
7272
var @params = new SetDownloadBehaviorParameters(new DownloadBehaviorDenied(), options?.UserContexts);
7373

74-
return await Broker.ExecuteCommandAsync<SetDownloadBehaviorCommand, EmptyResult>(new SetDownloadBehaviorCommand(@params), options).ConfigureAwait(false);
74+
return await Broker.ExecuteCommandAsync<SetDownloadBehaviorCommand, EmptyResult>(new SetDownloadBehaviorCommand(@params), options, JsonContext).ConfigureAwait(false);
7575
}
7676
}

0 commit comments

Comments
 (0)