Skip to content

Commit

Permalink
[dotnet] [bidi] Support getting of client windows in browser module (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
nvborisenko authored Feb 6, 2025
1 parent 0721800 commit e19d069
Show file tree
Hide file tree
Showing 14 changed files with 228 additions and 5 deletions.
2 changes: 2 additions & 0 deletions dotnet/src/webdriver/BiDi/Communication/Broker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ internal Broker(BiDi bidi, ITransport transport)
{
new BrowsingContextConverter(_bidi),
new BrowserUserContextConverter(bidi),
new BrowserClientWindowConverter(),
new NavigationConverter(),
new InterceptConverter(_bidi),
new RequestConverter(_bidi),
Expand Down Expand Up @@ -97,6 +98,7 @@ internal Broker(BiDi bidi, ITransport transport)
new Json.Converters.Enumerable.LocateNodesResultConverter(),
new Json.Converters.Enumerable.InputSourceActionsConverter(),
new Json.Converters.Enumerable.GetUserContextsResultConverter(),
new Json.Converters.Enumerable.GetClientWindowsResultConverter(),
new Json.Converters.Enumerable.GetRealmsResultConverter(),
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,11 @@ namespace OpenQA.Selenium.BiDi.Communication.Json;
[JsonSerializable(typeof(Modules.Browser.GetUserContextsCommand))]
[JsonSerializable(typeof(Modules.Browser.GetUserContextsResult))]
[JsonSerializable(typeof(Modules.Browser.RemoveUserContextCommand))]
[JsonSerializable(typeof(Modules.Browser.GetClientWindowsCommand))]
[JsonSerializable(typeof(Modules.Browser.GetClientWindowsResult))]
[JsonSerializable(typeof(Modules.Browser.UserContextInfo))]
[JsonSerializable(typeof(IReadOnlyList<Modules.Browser.UserContextInfo>))]
[JsonSerializable(typeof(IReadOnlyList<Modules.Browser.ClientWindowInfo>))]


[JsonSerializable(typeof(Modules.BrowsingContext.ActivateCommand))]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// <copyright file="BrowserClientWindowConverter.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>

using OpenQA.Selenium.BiDi.Modules.Browser;
using System;
using System.Text.Json;
using System.Text.Json.Serialization;

#nullable enable

namespace OpenQA.Selenium.BiDi.Communication.Json.Converters;

internal class BrowserClientWindowConverter : JsonConverter<ClientWindow>
{
public override ClientWindow? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var id = reader.GetString();

return new ClientWindow(id!);
}

public override void Write(Utf8JsonWriter writer, ClientWindow value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.Id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// <copyright file="GetClientWindowsResultConverter.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>

using OpenQA.Selenium.BiDi.Modules.Browser;
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;

#nullable enable

namespace OpenQA.Selenium.BiDi.Communication.Json.Converters.Enumerable;

internal class GetClientWindowsResultConverter : JsonConverter<GetClientWindowsResult>
{
public override GetClientWindowsResult Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using var doc = JsonDocument.ParseValue(ref reader);
var clientWindows = doc.RootElement.GetProperty("clientWindows").Deserialize<IReadOnlyList<ClientWindowInfo>>(options);

return new GetClientWindowsResult(clientWindows!);
}

public override void Write(Utf8JsonWriter writer, GetClientWindowsResult value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ internal class GetCookiesResultConverter : JsonConverter<GetCookiesResult>
{
public override GetCookiesResult Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var doc = JsonDocument.ParseValue(ref reader);
using var doc = JsonDocument.ParseValue(ref reader);
var cookies = doc.RootElement.GetProperty("cookies").Deserialize<IReadOnlyList<Modules.Network.Cookie>>(options);
var partitionKey = doc.RootElement.GetProperty("partitionKey").Deserialize<PartitionKey>(options);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ internal class GetRealmsResultConverter : JsonConverter<GetRealmsResult>
{
public override GetRealmsResult Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var doc = JsonDocument.ParseValue(ref reader);
using var doc = JsonDocument.ParseValue(ref reader);
var realms = doc.RootElement.GetProperty("realms").Deserialize<IReadOnlyList<RealmInfo>>(options);

return new GetRealmsResult(realms!);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ internal class GetUserContextsResultConverter : JsonConverter<GetUserContextsRes
{
public override GetUserContextsResult Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var doc = JsonDocument.ParseValue(ref reader);
using var doc = JsonDocument.ParseValue(ref reader);
var userContexts = doc.RootElement.GetProperty("userContexts").Deserialize<IReadOnlyList<UserContextInfo>>(options);

return new GetUserContextsResult(userContexts!);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ internal class LocateNodesResultConverter : JsonConverter<LocateNodesResult>
{
public override LocateNodesResult Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var doc = JsonDocument.ParseValue(ref reader);
using var doc = JsonDocument.ParseValue(ref reader);
var nodes = doc.RootElement.GetProperty("nodes").Deserialize<IReadOnlyList<RemoteValue.Node>>(options);

return new LocateNodesResult(nodes!);
Expand Down
5 changes: 5 additions & 0 deletions dotnet/src/webdriver/BiDi/Modules/Browser/BrowserModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,9 @@ public async Task RemoveUserContextAsync(UserContext userContext, RemoveUserCont

await Broker.ExecuteCommandAsync(new RemoveUserContextCommand(@params), options).ConfigureAwait(false);
}

public async Task<GetClientWindowsResult> GetClientWindowsAsync(GetClientWindowsOptions? options = null)
{
return await Broker.ExecuteCommandAsync<GetClientWindowsCommand, GetClientWindowsResult>(new(), options).ConfigureAwait(false);
}
}
32 changes: 32 additions & 0 deletions dotnet/src/webdriver/BiDi/Modules/Browser/ClientWindow.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// <copyright file="ClientWindow.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>

#nullable enable

namespace OpenQA.Selenium.BiDi.Modules.Browser;

public record ClientWindow
{
internal ClientWindow(string id)
{
Id = id;
}

internal string Id { get; }
}
34 changes: 34 additions & 0 deletions dotnet/src/webdriver/BiDi/Modules/Browser/ClientWindowInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// <copyright file="ClientWindowInfo.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>

#nullable enable

using System.Text.Json.Serialization;

namespace OpenQA.Selenium.BiDi.Modules.Browser;

public record ClientWindowInfo([property: JsonPropertyName("active")] bool IsActive, ClientWindow ClientWindow, ClientWindowState State, int Height, int Width, int X, int Y);

public enum ClientWindowState
{
Fullscreen,
Maximized,
Minimized,
Normal
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// <copyright file="GetClientWindowsCommand.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>

using OpenQA.Selenium.BiDi.Communication;
using System.Collections;
using System.Collections.Generic;

#nullable enable

namespace OpenQA.Selenium.BiDi.Modules.Browser;

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

public record GetClientWindowsOptions : CommandOptions;

public record GetClientWindowsResult : IReadOnlyList<ClientWindowInfo>
{
private readonly IReadOnlyList<ClientWindowInfo> _clientWindows;

internal GetClientWindowsResult(IReadOnlyList<ClientWindowInfo> clientWindows)
{
_clientWindows = clientWindows;
}

public ClientWindowInfo this[int index] => _clientWindows[index];

public int Count => _clientWindows.Count;

public IEnumerator<ClientWindowInfo> GetEnumerator() => _clientWindows.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => (_clientWindows as IEnumerable).GetEnumerator();
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
namespace OpenQA.Selenium.BiDi.Modules.BrowsingContext;

// TODO: Split it to separate class with just info and event args
public record BrowsingContextInfo(BiDi BiDi, IReadOnlyList<BrowsingContextInfo> Children, BrowsingContext Context, BrowsingContext OriginalOpener, string Url, Browser.UserContext UserContext)
public record BrowsingContextInfo(BiDi BiDi, IReadOnlyList<BrowsingContextInfo> Children, Browser.ClientWindow ClientWindow, BrowsingContext Context, BrowsingContext OriginalOpener, string Url, Browser.UserContext UserContext)
: BrowsingContextEventArgs(BiDi, Context)
{
[JsonInclude]
Expand Down
12 changes: 12 additions & 0 deletions dotnet/test/common/BiDi/Browser/BrowserTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,16 @@ public async Task CanRemoveUserContext()
Assert.That(userContexts, Does.Contain(userContext1));
Assert.That(userContexts, Does.Not.Contain(userContext2));
}

[Test]
[IgnoreBrowser(Selenium.Browser.Chrome, "BiDi GetClientWindows command not yet supported by Chrome 133")]
[IgnoreBrowser(Selenium.Browser.Edge, "BiDi GetClientWindows command not yet supported by Edge 133")]
public async Task CanGetClientWindows()
{
var clientWindows = await bidi.Browser.GetClientWindowsAsync();

Assert.That(clientWindows, Is.Not.Null);
Assert.That(clientWindows, Has.Count.GreaterThanOrEqualTo(1));
Assert.That(clientWindows[0].ClientWindow, Is.Not.Null);
}
}

0 comments on commit e19d069

Please sign in to comment.