Skip to content

Commit

Permalink
[dotnet] BiDi implementation (#14318)
Browse files Browse the repository at this point in the history
* Migrate

* Use CLS compliant long instead of ulong

* Use null instead of default for optional arguments

* Use internal logging in websockettransport

* Use internal logger in broker

* Even with error log level

* Simplify AsBidirectionalContextAsync

* Fix ConfigureAwait in network module

* Hide direct network interception

* Rework public adding interception

* Simplify network interception

* Don't end session when disposing bidi driver
  • Loading branch information
nvborisenko committed Sep 9, 2024
1 parent 7b5f6d7 commit 3e8b34c
Show file tree
Hide file tree
Showing 138 changed files with 4,387 additions and 0 deletions.
4 changes: 4 additions & 0 deletions dotnet/src/webdriver/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ csharp_library(
],
deps = [
framework("nuget", "NETStandard.Library"),
framework("nuget", "Microsoft.Bcl.AsyncInterfaces"),
framework("nuget", "System.Threading.Tasks.Extensions"),
framework("nuget", "System.Memory"),
framework("nuget", "System.Text.Json"),
],
Expand Down Expand Up @@ -111,6 +113,8 @@ csharp_library(
],
deps = [
framework("nuget", "NETStandard.Library"),
framework("nuget", "Microsoft.Bcl.AsyncInterfaces"),
framework("nuget", "System.Threading.Tasks.Extensions"),
framework("nuget", "System.Memory"),
framework("nuget", "System.Text.Json"),
],
Expand Down
124 changes: 124 additions & 0 deletions dotnet/src/webdriver/BiDi/BiDi.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using OpenQA.Selenium.BiDi.Communication;
using OpenQA.Selenium.BiDi.Communication.Transport;

namespace OpenQA.Selenium.BiDi;

public class BiDi : IAsyncDisposable
{
private readonly ITransport _transport;
private readonly Broker _broker;

private readonly Lazy<Modules.Session.SessionModule> _sessionModule;
private readonly Lazy<Modules.BrowsingContext.BrowsingContextModule> _browsingContextModule;
private readonly Lazy<Modules.Browser.BrowserModule> _browserModule;
private readonly Lazy<Modules.Network.NetworkModule> _networkModule;
private readonly Lazy<Modules.Input.InputModule> _inputModule;
private readonly Lazy<Modules.Script.ScriptModule> _scriptModule;
private readonly Lazy<Modules.Log.LogModule> _logModule;
private readonly Lazy<Modules.Storage.StorageModule> _storageModule;

internal BiDi(string url)
{
var uri = new Uri(url);

_transport = new WebSocketTransport(new Uri(url));
_broker = new Broker(this, _transport);

_sessionModule = new Lazy<Modules.Session.SessionModule>(() => new Modules.Session.SessionModule(_broker));
_browsingContextModule = new Lazy<Modules.BrowsingContext.BrowsingContextModule>(() => new Modules.BrowsingContext.BrowsingContextModule(_broker));
_browserModule = new Lazy<Modules.Browser.BrowserModule>(() => new Modules.Browser.BrowserModule(_broker));
_networkModule = new Lazy<Modules.Network.NetworkModule>(() => new Modules.Network.NetworkModule(_broker));
_inputModule = new Lazy<Modules.Input.InputModule>(() => new Modules.Input.InputModule(_broker));
_scriptModule = new Lazy<Modules.Script.ScriptModule>(() => new Modules.Script.ScriptModule(_broker));
_logModule = new Lazy<Modules.Log.LogModule>(() => new Modules.Log.LogModule(_broker));
_storageModule = new Lazy<Modules.Storage.StorageModule>(() => new Modules.Storage.StorageModule(_broker));
}

internal Modules.Session.SessionModule SessionModule => _sessionModule.Value;
internal Modules.BrowsingContext.BrowsingContextModule BrowsingContextModule => _browsingContextModule.Value;
public Modules.Browser.BrowserModule Browser => _browserModule.Value;
public Modules.Network.NetworkModule Network => _networkModule.Value;
internal Modules.Input.InputModule InputModule => _inputModule.Value;
internal Modules.Script.ScriptModule ScriptModule => _scriptModule.Value;
public Modules.Log.LogModule Log => _logModule.Value;
public Modules.Storage.StorageModule Storage => _storageModule.Value;

public Task<Modules.Session.StatusResult> StatusAsync()
{
return SessionModule.StatusAsync();
}

public static async Task<BiDi> ConnectAsync(string url)
{
var bidi = new BiDi(url);

await bidi._broker.ConnectAsync(default).ConfigureAwait(false);

return bidi;
}

public Task<Modules.BrowsingContext.BrowsingContext> CreateBrowsingContextAsync(Modules.BrowsingContext.BrowsingContextType type, Modules.BrowsingContext.CreateOptions? options = null)
{
return BrowsingContextModule.CreateAsync(type, options);
}

public Task<IReadOnlyList<Modules.BrowsingContext.BrowsingContextInfo>> GetBrowsingContextTreeAsync(Modules.BrowsingContext.GetTreeOptions? options = null)
{
return BrowsingContextModule.GetTreeAsync(options);
}

public Task EndAsync(Modules.Session.EndOptions? options = null)
{
return SessionModule.EndAsync(options);
}

public async ValueTask DisposeAsync()
{
await _broker.DisposeAsync().ConfigureAwait(false);

_transport?.Dispose();
}

public Task<Subscription> OnBrowsingContextCreatedAsync(Func<Modules.BrowsingContext.BrowsingContextInfo, Task> handler, BrowsingContextsSubscriptionOptions? options = null)
{
return BrowsingContextModule.OnContextCreatedAsync(handler, options);
}

public Task<Subscription> OnBrowsingContextCreatedAsync(Action<Modules.BrowsingContext.BrowsingContextInfo> handler, BrowsingContextsSubscriptionOptions? options = null)
{
return BrowsingContextModule.OnContextCreatedAsync(handler, options);
}

public Task<Subscription> OnBrowsingContextDestroyedAsync(Func<Modules.BrowsingContext.BrowsingContextInfo, Task> handler, BrowsingContextsSubscriptionOptions? options = null)
{
return BrowsingContextModule.OnContextDestroyedAsync(handler, options);
}

public Task<Subscription> OnBrowsingContextDestroyedAsync(Action<Modules.BrowsingContext.BrowsingContextInfo> handler, BrowsingContextsSubscriptionOptions? options = null)
{
return BrowsingContextModule.OnContextDestroyedAsync(handler, options);
}

public Task<Subscription> OnUserPromptOpenedAsync(Func<Modules.BrowsingContext.UserPromptOpenedEventArgs, Task> handler, BrowsingContextsSubscriptionOptions? options = null)
{
return BrowsingContextModule.OnUserPromptOpenedAsync(handler, options);
}

public Task<Subscription> OnUserPromptOpenedAsync(Action<Modules.BrowsingContext.UserPromptOpenedEventArgs> handler, BrowsingContextsSubscriptionOptions? options = null)
{
return BrowsingContextModule.OnUserPromptOpenedAsync(handler, options);
}

public Task<Subscription> OnUserPromptClosedAsync(Func<Modules.BrowsingContext.UserPromptClosedEventArgs, Task> handler, BrowsingContextsSubscriptionOptions? options = null)
{
return BrowsingContextModule.OnUserPromptClosedAsync(handler, options);
}

public Task<Subscription> OnUserPromptClosedAsync(Action<Modules.BrowsingContext.UserPromptClosedEventArgs> handler, BrowsingContextsSubscriptionOptions? options = null)
{
return BrowsingContextModule.OnUserPromptClosedAsync(handler, options);
}
}
10 changes: 10 additions & 0 deletions dotnet/src/webdriver/BiDi/BiDiException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;

namespace OpenQA.Selenium.BiDi;

public class BiDiException : Exception
{
public BiDiException(string message) : base(message)
{
}
}
Loading

0 comments on commit 3e8b34c

Please sign in to comment.