Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions dotnet/src/webdriver/BiDi/BiDi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public async ValueTask DisposeAsync()

public T AsModule<T>() where T : Module, new()
{
return (T)_modules.GetOrAdd(typeof(T), _ => Module.Create<T>(this, Broker, GetJsonOptions()));
return (T)_modules.GetOrAdd(typeof(T), _ => Module.Create<T>(this, Broker));
}

private Broker Broker { get; }
Expand All @@ -94,25 +94,25 @@ private JsonSerializerOptions GetJsonOptions()
{
return new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
//PropertyNameCaseInsensitive = true,
//PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
//DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,

// BiDi returns special numbers such as "NaN" as strings
// Additionally, -0 is returned as a string "-0"
NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals | JsonNumberHandling.AllowReadingFromString,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it safe to remove runtime options completely? As I remember we implemented it as converter?..

Converters =
{
new BrowsingContextConverter(this),
new BrowserUserContextConverter(this),
new CollectorConverter(this),
new InterceptConverter(this),
new HandleConverter(this),
new InternalIdConverter(this),
new PreloadScriptConverter(this),
new RealmConverter(this),
//new BrowsingContextConverter(),
//new BrowserUserContextConverter(),
//new CollectorConverter(),
//new InterceptConverter(),
//new HandleConverter(),
//new InternalIdConverter(),
//new PreloadScriptConverter(),
//new RealmConverter(),
new DateTimeOffsetConverter(),
new WebExtensionConverter(this),
//new WebExtensionConverter(),
}
};
}
Expand Down
5 changes: 5 additions & 0 deletions dotnet/src/webdriver/BiDi/Broker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,11 @@ private void ProcessReceivedMessage(byte[]? data)
var commandResult = JsonSerializer.Deserialize(ref resultReader, command.JsonResultTypeInfo)
?? throw new JsonException("Remote end returned null command result in the 'result' property.");

if (commandResult is IBiDiHydratable bidiHydratable)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have any types with properties that are BiDi hydratable? We might need to handle nested structures.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hydrated couple just to make tests green. If we like the approach, I will review all top-level CommndResults/EventArgs to include nested properties.

{
bidiHydratable.Hydrate(_bidi);
}

command.TaskCompletionSource.SetResult((EmptyResult)commandResult);
}
catch (Exception ex)
Expand Down
17 changes: 10 additions & 7 deletions dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
// under the License.
// </copyright>

using System.Text.Json;
using OpenQA.Selenium.BiDi.Json.Converters;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace OpenQA.Selenium.BiDi.Browser;

public sealed class BrowserModule : Module
{
private BrowserJsonSerializerContext _jsonContext = null!;
private static readonly BrowserJsonSerializerContext _jsonContext = BrowserJsonSerializerContext.Default;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we choose generated options, then rename -> s_jsonContext


public async Task<CloseResult> CloseAsync(CloseOptions? options = null)
{
Expand Down Expand Up @@ -77,11 +77,6 @@ public async Task<SetDownloadBehaviorResult> SetDownloadBehaviorDeniedAsync(SetD

return await Broker.ExecuteCommandAsync(new SetDownloadBehaviorCommand(@params), options, _jsonContext.SetDownloadBehaviorCommand, _jsonContext.SetDownloadBehaviorResult).ConfigureAwait(false);
}

protected override void Initialize(JsonSerializerOptions options)
{
_jsonContext = new BrowserJsonSerializerContext(options);
}
}

[JsonSerializable(typeof(CloseCommand))]
Expand All @@ -96,4 +91,12 @@ protected override void Initialize(JsonSerializerOptions options)
[JsonSerializable(typeof(GetClientWindowsResult))]
[JsonSerializable(typeof(SetDownloadBehaviorCommand))]
[JsonSerializable(typeof(SetDownloadBehaviorResult))]

#pragma warning disable CS3016 // Arrays as attribute arguments is not CLS-compliant
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better [ClsCompliant(false)] I think. You’ll probably run into dotnet/roslyn#68560 though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are CLS compliant:

[assembly: System.CLSCompliant(true)]

[JsonSourceGenerationOptions(
PropertyNameCaseInsensitive = true,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are duplicating shared json options. Is it good? Or do we want to return back the construction of json context in runtime rather than generated options?

DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
Converters = [typeof(DateTimeOffsetConverter)])]
#pragma warning restore CS3016 // Arrays as attribute arguments is not CLS-compliant
internal partial class BrowserJsonSerializerContext : JsonSerializerContext;
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,10 @@ public sealed class CreateUserContextOptions : CommandOptions
public Session.UserPromptHandler? UnhandledPromptBehavior { get; set; }
}

public sealed record CreateUserContextResult(UserContext UserContext) : UserContextInfo(UserContext);
public sealed record CreateUserContextResult(UserContext UserContext) : UserContextInfo(UserContext), IBiDiHydratable
{
void IBiDiHydratable.Hydrate(BiDi bidi)
{
UserContext.BiDi = bidi;
}
}
13 changes: 8 additions & 5 deletions dotnet/src/webdriver/BiDi/Browser/UserContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,29 @@
// under the License.
// </copyright>

using OpenQA.Selenium.BiDi.Json.Converters;
using System;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace OpenQA.Selenium.BiDi.Browser;

[JsonConverter(typeof(BrowserUserContextConverter))]
public sealed class UserContext : IEquatable<UserContext>, IAsyncDisposable
{
private readonly BiDi _bidi;

internal UserContext(BiDi bidi, string id)
internal UserContext(string id)
{
_bidi = bidi;
Id = id;
}

internal string Id { get; }

[JsonIgnore]
public BiDi BiDi { get; internal set; }

public Task RemoveAsync()
{
return _bidi.Browser.RemoveUserContextAsync(this);
return BiDi.Browser.RemoveUserContextAsync(this);
}

public async ValueTask DisposeAsync()
Expand Down
7 changes: 4 additions & 3 deletions dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,19 @@
// under the License.
// </copyright>

using OpenQA.Selenium.BiDi.Json.Converters;
using System;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;

namespace OpenQA.Selenium.BiDi.BrowsingContext;

[JsonConverter(typeof(BrowsingContextConverter))]
public sealed class BrowsingContext
{
internal BrowsingContext(BiDi bidi, string id)
internal BrowsingContext(string id)
{
BiDi = bidi;
Id = id;
}

Expand All @@ -41,7 +42,7 @@ internal BrowsingContext(BiDi bidi, string id)
internal string Id { get; }

[JsonIgnore]
public BiDi BiDi { get; }
public BiDi BiDi { get; internal set; }

[JsonIgnore]
public BrowsingContextLogModule Log => _logModule ?? Interlocked.CompareExchange(ref _logModule, new BrowsingContextLogModule(this, BiDi.Log), null) ?? _logModule;
Expand Down
17 changes: 10 additions & 7 deletions dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContextModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@
// under the License.
// </copyright>

using OpenQA.Selenium.BiDi.Json.Converters;
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace OpenQA.Selenium.BiDi.BrowsingContext;

public sealed class BrowsingContextModule : Module
{
private BrowsingContextJsonSerializerContext _jsonContext = null!;
private static readonly BrowsingContextJsonSerializerContext _jsonContext = BrowsingContextJsonSerializerContext.Default;

public async Task<CreateResult> CreateAsync(ContextType type, CreateOptions? options = null)
{
Expand Down Expand Up @@ -251,11 +251,6 @@ public async Task<Subscription> OnUserPromptClosedAsync(Action<UserPromptClosedE
{
return await Broker.SubscribeAsync("browsingContext.userPromptClosed", handler, options, _jsonContext.UserPromptClosedEventArgs).ConfigureAwait(false);
}

protected override void Initialize(JsonSerializerOptions options)
{
_jsonContext = new BrowsingContextJsonSerializerContext(options);
}
}

[JsonSerializable(typeof(ActivateCommand))]
Expand Down Expand Up @@ -292,4 +287,12 @@ protected override void Initialize(JsonSerializerOptions options)
[JsonSerializable(typeof(NavigationInfo))]
[JsonSerializable(typeof(UserPromptOpenedEventArgs))]
[JsonSerializable(typeof(UserPromptClosedEventArgs))]

#pragma warning disable CS3016 // Arrays as attribute arguments is not CLS-compliant
[JsonSourceGenerationOptions(
PropertyNameCaseInsensitive = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
Converters = [typeof(DateTimeOffsetConverter)])]
#pragma warning restore CS3016 // Arrays as attribute arguments is not CLS-compliant
internal partial class BrowsingContextJsonSerializerContext : JsonSerializerContext;
11 changes: 10 additions & 1 deletion dotnet/src/webdriver/BiDi/BrowsingContext/GetTreeCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,13 @@ public sealed record BrowsingContextGetTreeOptions
public long? MaxDepth { get; set; }
}

public sealed record GetTreeResult(IReadOnlyList<BrowsingContextInfo> Contexts) : EmptyResult;
public sealed record GetTreeResult(IReadOnlyList<BrowsingContextInfo> Contexts) : EmptyResult, IBiDiHydratable
{
void IBiDiHydratable.Hydrate(BiDi bidi)
{
foreach (var contextInfo in Contexts)
{
contextInfo.Context.BiDi = bidi;
}
}
}
17 changes: 10 additions & 7 deletions dotnet/src/webdriver/BiDi/Emulation/EmulationModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
// under the License.
// </copyright>

using System.Text.Json;
using OpenQA.Selenium.BiDi.Json.Converters;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace OpenQA.Selenium.BiDi.Emulation;

public sealed class EmulationModule : Module
{
private EmulationJsonSerializerContext _jsonContext = null!;
private static readonly EmulationJsonSerializerContext _jsonContext = EmulationJsonSerializerContext.Default;

public async Task<SetTimezoneOverrideResult> SetTimezoneOverrideAsync(string? timezone, SetTimezoneOverrideOptions? options = null)
{
Expand Down Expand Up @@ -91,11 +91,6 @@ public async Task<SetGeolocationOverrideResult> SetGeolocationPositionErrorOverr

return await Broker.ExecuteCommandAsync(new SetGeolocationOverrideCommand(@params), options, _jsonContext.SetGeolocationOverrideCommand, _jsonContext.SetGeolocationOverrideResult).ConfigureAwait(false);
}

protected override void Initialize(JsonSerializerOptions options)
{
_jsonContext = new EmulationJsonSerializerContext(options);
}
}

[JsonSerializable(typeof(SetTimezoneOverrideCommand))]
Expand All @@ -112,4 +107,12 @@ protected override void Initialize(JsonSerializerOptions options)
[JsonSerializable(typeof(SetScreenOrientationOverrideResult))]
[JsonSerializable(typeof(SetGeolocationOverrideCommand))]
[JsonSerializable(typeof(SetGeolocationOverrideResult))]

#pragma warning disable CS3016 // Arrays as attribute arguments is not CLS-compliant
[JsonSourceGenerationOptions(
PropertyNameCaseInsensitive = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
Converters = [typeof(DateTimeOffsetConverter)])]
#pragma warning restore CS3016 // Arrays as attribute arguments is not CLS-compliant
internal partial class EmulationJsonSerializerContext : JsonSerializerContext;
7 changes: 6 additions & 1 deletion dotnet/src/webdriver/BiDi/EventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,15 @@

namespace OpenQA.Selenium.BiDi;

public abstract record EventArgs
public abstract record EventArgs : IBiDiHydratable
{
[JsonIgnore]
public BiDi BiDi { get; internal set; }

void IBiDiHydratable.Hydrate(BiDi bidi)
{
BiDi = bidi;
}
}

public abstract record BrowsingContextEventArgs(BrowsingContext.BrowsingContext Context)
Expand Down
25 changes: 25 additions & 0 deletions dotnet/src/webdriver/BiDi/IBiDiHydratable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// <copyright file="IBiDiHydratable.cs" company="Selenium Committers">
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
// </copyright>

namespace OpenQA.Selenium.BiDi;

public interface IBiDiHydratable
{
internal void Hydrate(BiDi bidi);
}
17 changes: 10 additions & 7 deletions dotnet/src/webdriver/BiDi/Input/InputModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@
// under the License.
// </copyright>

using OpenQA.Selenium.BiDi.Json.Converters;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace OpenQA.Selenium.BiDi.Input;

public sealed class InputModule : Module
{
private InputJsonSerializerContext _jsonContext = null!;
private static readonly InputJsonSerializerContext _jsonContext = InputJsonSerializerContext.Default;

public async Task<PerformActionsResult> PerformActionsAsync(BrowsingContext.BrowsingContext context, IEnumerable<SourceActions> actions, PerformActionsOptions? options = null)
{
Expand All @@ -48,11 +48,6 @@ public async Task<SetFilesResult> SetFilesAsync(BrowsingContext.BrowsingContext

return await Broker.ExecuteCommandAsync(new SetFilesCommand(@params), options, _jsonContext.SetFilesCommand, _jsonContext.SetFilesResult).ConfigureAwait(false);
}

protected override void Initialize(JsonSerializerOptions options)
{
_jsonContext = new InputJsonSerializerContext(options);
}
}

[JsonSerializable(typeof(PerformActionsCommand))]
Expand All @@ -65,4 +60,12 @@ protected override void Initialize(JsonSerializerOptions options)
[JsonSerializable(typeof(IEnumerable<IKeySourceAction>))]
[JsonSerializable(typeof(IEnumerable<INoneSourceAction>))]
[JsonSerializable(typeof(IEnumerable<IWheelSourceAction>))]

#pragma warning disable CS3016 // Arrays as attribute arguments is not CLS-compliant
[JsonSourceGenerationOptions(
PropertyNameCaseInsensitive = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
Converters = [typeof(DateTimeOffsetConverter)])]
#pragma warning restore CS3016 // Arrays as attribute arguments is not CLS-compliant
internal partial class InputJsonSerializerContext : JsonSerializerContext;
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,11 @@ namespace OpenQA.Selenium.BiDi.Json.Converters;

internal class BrowserUserContextConverter : JsonConverter<UserContext>
{
private readonly BiDi _bidi;

public BrowserUserContextConverter(BiDi bidi)
{
_bidi = bidi;
}

public override UserContext? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var id = reader.GetString();

return new UserContext(_bidi, id!);
return new UserContext(id!);
}

public override void Write(Utf8JsonWriter writer, UserContext value, JsonSerializerOptions options)
Expand Down
Loading
Loading