Skip to content

Commit e6bbf24

Browse files
authored
Merge branch 'trunk' into annotate-relative-by
2 parents 050feb0 + 4aee006 commit e6bbf24

33 files changed

+303
-375
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// <copyright file="DevToolsJsonOptions.cs" company="Selenium Committers">
2+
// Licensed to the Software Freedom Conservancy (SFC) under one
3+
// or more contributor license agreements. See the NOTICE file
4+
// distributed with this work for additional information
5+
// regarding copyright ownership. The SFC licenses this file
6+
// to you under the Apache License, Version 2.0 (the
7+
// "License"); you may not use this file except in compliance
8+
// with the License. You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing,
13+
// software distributed under the License is distributed on an
14+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
// KIND, either express or implied. See the License for the
16+
// specific language governing permissions and limitations
17+
// under the License.
18+
// </copyright>
19+
20+
using System.Text.Json;
21+
22+
#nullable enable
23+
24+
namespace OpenQA.Selenium.DevTools.Json;
25+
26+
internal static class DevToolsJsonOptions
27+
{
28+
public static JsonSerializerOptions Default { get; } = new JsonSerializerOptions()
29+
{
30+
Converters =
31+
{
32+
new StringConverter(),
33+
}
34+
};
35+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// <copyright file="StringConverter.cs" company="Selenium Committers">
2+
// Licensed to the Software Freedom Conservancy (SFC) under one
3+
// or more contributor license agreements. See the NOTICE file
4+
// distributed with this work for additional information
5+
// regarding copyright ownership. The SFC licenses this file
6+
// to you under the Apache License, Version 2.0 (the
7+
// "License"); you may not use this file except in compliance
8+
// with the License. You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing,
13+
// software distributed under the License is distributed on an
14+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
// KIND, either express or implied. See the License for the
16+
// specific language governing permissions and limitations
17+
// under the License.
18+
// </copyright>
19+
20+
using System;
21+
using System.Text;
22+
using System.Text.Json;
23+
using System.Text.Json.Serialization;
24+
25+
#nullable enable
26+
27+
namespace OpenQA.Selenium.DevTools.Json;
28+
29+
internal sealed class StringConverter : JsonConverter<string>
30+
{
31+
public override bool HandleNull => true;
32+
33+
public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
34+
{
35+
try
36+
{
37+
return reader.GetString();
38+
}
39+
catch (InvalidOperationException)
40+
{
41+
// Fallback to read the value as bytes instead of string.
42+
// System.Text.Json library throws exception when CDP remote end sends non-encoded string as binary data.
43+
// Using JavaScriptEncoder.UnsafeRelaxedJsonEscaping doesn't help because the string actually is byte[].
44+
// https://chromedevtools.github.io/devtools-protocol/tot/Network/#type-Request - here "postData" property
45+
// is a string, which we cannot deserialize properly. This property is marked as deprecated, and new "postDataEntries"
46+
// is suggested for using, where most likely it is base64 encoded.
47+
48+
var bytes = reader.ValueSpan;
49+
var sb = new StringBuilder(bytes.Length);
50+
foreach (byte b in bytes)
51+
{
52+
sb.Append(Convert.ToChar(b));
53+
}
54+
55+
return sb.ToString();
56+
}
57+
}
58+
59+
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) =>
60+
writer.WriteStringValue(value);
61+
}

dotnet/src/webdriver/Internal/Logging/LogContext.cs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
using System;
2121
using System.Collections.Concurrent;
2222
using System.Collections.Generic;
23+
using System.Diagnostics.CodeAnalysis;
2324
using System.Linq;
2425

2526
#nullable enable
@@ -30,7 +31,7 @@ namespace OpenQA.Selenium.Internal.Logging
3031
/// Represents a logging context that provides methods for creating sub-contexts, retrieving loggers, emitting log messages, and configuring minimum log levels.
3132
/// </summary>
3233
/// <inheritdoc cref="ILogContext"/>
33-
internal class LogContext : ILogContext
34+
internal sealed class LogContext : ILogContext
3435
{
3536
private ConcurrentDictionary<Type, ILogger>? _loggers;
3637

@@ -46,7 +47,7 @@ public LogContext(LogEventLevel level, ILogContext? parentLogContext, Concurrent
4647

4748
_parentLogContext = parentLogContext;
4849

49-
_loggers = loggers;
50+
_loggers = CloneLoggers(loggers, level);
5051

5152
if (handlers is not null)
5253
{
@@ -65,12 +66,7 @@ public ILogContext CreateContext()
6566

6667
public ILogContext CreateContext(LogEventLevel minimumLevel)
6768
{
68-
ConcurrentDictionary<Type, ILogger>? loggers = null;
69-
70-
if (_loggers != null)
71-
{
72-
loggers = new ConcurrentDictionary<Type, ILogger>(_loggers.Select(l => new KeyValuePair<Type, ILogger>(l.Key, new Logger(l.Value.Issuer, minimumLevel))));
73-
}
69+
ConcurrentDictionary<Type, ILogger>? loggers = CloneLoggers(_loggers, minimumLevel);
7470

7571
var context = new LogContext(minimumLevel, this, loggers, Handlers);
7672

@@ -98,7 +94,7 @@ public ILogger GetLogger(Type type)
9894

9995
public bool IsEnabled(ILogger logger, LogEventLevel level)
10096
{
101-
return Handlers != null && level >= _level && level >= logger.Level;
97+
return Handlers != null && level >= _level && (_loggers?.TryGetValue(logger.Issuer, out var loggerEntry) != true || level >= loggerEntry?.Level);
10298
}
10399

104100
public void EmitMessage(ILogger logger, LogEventLevel level, string message)
@@ -155,5 +151,24 @@ public void Dispose()
155151

156152
Log.CurrentContext = _parentLogContext;
157153
}
154+
155+
[return: NotNullIfNotNull(nameof(loggers))]
156+
private static ConcurrentDictionary<Type, ILogger>? CloneLoggers(ConcurrentDictionary<Type, ILogger>? loggers, LogEventLevel minimumLevel)
157+
{
158+
if (loggers is null)
159+
{
160+
return null;
161+
}
162+
163+
var cloned = new Dictionary<Type, ILogger>(loggers.Count);
164+
165+
foreach (KeyValuePair<Type, ILogger> logger in loggers)
166+
{
167+
var clonedLogger = new Logger(logger.Value.Issuer, minimumLevel);
168+
cloned.Add(logger.Key, clonedLogger);
169+
}
170+
171+
return new ConcurrentDictionary<Type, ILogger>(cloned);
172+
}
158173
}
159174
}

dotnet/src/webdriver/cdp/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ add an entry for version `<N>` to the `SupportedDevToolsVersions` dictionary ini
1717
6. In [`//dotnet/src/webdriver:WebDriver.csproj.prebuild.cmd`](https://github.com/SeleniumHQ/selenium/blob/trunk/dotnet/src/webdriver/WebDriver.csproj.prebuild.cmd),
1818
add the following block (substituting the proper value for `<N>`):
1919

20-
```
20+
```bash
2121
if not exist "%1..\..\..\bazel-bin\dotnet\src\webdriver\cdp\v<N>\DevToolsSessionDomains.cs" (
2222
echo Generating CDP code for version <N>
2323
pushd "%1..\..\.."
@@ -29,7 +29,7 @@ if not exist "%1..\..\..\bazel-bin\dotnet\src\webdriver\cdp\v<N>\DevToolsSessio
2929
7. In [`//dotnet/src/webdriver:WebDriver.csproj.prebuild.sh`](https://github.com/SeleniumHQ/selenium/blob/trunk/dotnet/src/webdriver/WebDriver.csproj.prebuild.sh),
3030
add the following block (substituting the proper value for `<N>`):
3131
32-
```
32+
```bash
3333
if [[ ! -f "$1../../../bazel-bin/dotnet/src/webdriver/cdp/v<N>/DevToolsSessionDomains.cs" ]]
3434
then
3535
echo "Generating CDP code for version <N>"

dotnet/test/common/Internal/Logging/LogTest.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,27 @@ public class LogTest
2828
private TestLogHandler testLogHandler;
2929
private ILogger logger;
3030

31+
private void ResetGlobalLog()
32+
{
33+
Log.SetLevel(LogEventLevel.Info);
34+
Log.Handlers.Clear().Handlers.Add(new ConsoleLogHandler());
35+
}
36+
3137
[SetUp]
3238
public void SetUp()
3339
{
40+
ResetGlobalLog();
41+
3442
testLogHandler = new TestLogHandler();
3543
logger = Log.GetLogger<LogTest>();
3644
}
3745

46+
[TearDown]
47+
public void TearDown()
48+
{
49+
ResetGlobalLog();
50+
}
51+
3852
[Test]
3953
public void LoggerShouldEmitEvent()
4054
{
@@ -160,6 +174,16 @@ public void ContextShouldChangeLevel()
160174
Assert.That(logger.Level, Is.EqualTo(LogEventLevel.Warn));
161175
}
162176

177+
[Test]
178+
public void ContextShouldEmitMessages()
179+
{
180+
using var context = Log.CreateContext(LogEventLevel.Trace).Handlers.Add(testLogHandler);
181+
182+
logger.Trace("test message");
183+
184+
Assert.That(testLogHandler.Events.Count, Is.EqualTo(1));
185+
}
186+
163187
[Test]
164188
public void ShouldCreateContextWithCustomHandler()
165189
{

java/src/org/openqa/selenium/devtools/DevTools.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public class DevTools implements Closeable {
4242
private static final Logger LOG = Logger.getLogger(DevTools.class.getName());
4343

4444
private final Domains protocol;
45-
private final Duration timeout = Duration.ofSeconds(10);
45+
private final Duration timeout = Duration.ofSeconds(30);
4646
private final Connection connection;
4747
private SessionID cdpSession = null;
4848

third_party/dotnet/devtools/src/generator/CodeGen/CodeGenerationDefinitionTemplateSettings.cs

Lines changed: 8 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ public CodeGenerationDefinitionTemplateSettings()
1616
OutputPath = "{{domainName}}\\{{className}}Adapter.cs",
1717
};
1818

19-
CommandTemplate = new CodeGenerationTemplateSettings {
19+
CommandTemplate = new CodeGenerationTemplateSettings
20+
{
2021
TemplatePath = "command.hbs",
2122
OutputPath = "{{domainName}}\\{{className}}Command.cs",
2223
};
@@ -47,46 +48,21 @@ public CodeGenerationDefinitionTemplateSettings()
4748
}
4849

4950
[JsonProperty("domainTemplate")]
50-
public CodeGenerationTemplateSettings DomainTemplate
51-
{
52-
get;
53-
set;
54-
}
51+
public CodeGenerationTemplateSettings DomainTemplate { get; set; }
5552

5653
[JsonProperty("commandTemplate")]
57-
public CodeGenerationTemplateSettings CommandTemplate
58-
{
59-
get;
60-
set;
61-
}
54+
public CodeGenerationTemplateSettings CommandTemplate { get; set; }
6255

6356
[JsonProperty("eventTemplate")]
64-
public CodeGenerationTemplateSettings EventTemplate
65-
{
66-
get;
67-
set;
68-
}
57+
public CodeGenerationTemplateSettings EventTemplate { get; set; }
6958

7059
[JsonProperty("typeObjectTemplate")]
71-
public CodeGenerationTemplateSettings TypeObjectTemplate
72-
{
73-
get;
74-
set;
75-
}
60+
public CodeGenerationTemplateSettings TypeObjectTemplate { get; set; }
7661

7762
[JsonProperty("typeHashTemplate")]
78-
public CodeGenerationTemplateSettings TypeHashTemplate
79-
{
80-
get;
81-
set;
82-
}
63+
public CodeGenerationTemplateSettings TypeHashTemplate { get; set; }
8364

8465
[JsonProperty("typeEnumTemplate")]
85-
public CodeGenerationTemplateSettings TypeEnumTemplate
86-
{
87-
get;
88-
set;
89-
}
90-
66+
public CodeGenerationTemplateSettings TypeEnumTemplate { get; set; }
9167
}
9268
}
Lines changed: 9 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace OpenQA.Selenium.DevToolsGenerator.CodeGen
1+
namespace OpenQA.Selenium.DevToolsGenerator.CodeGen
22
{
33
using Newtonsoft.Json;
44
using System.Collections.Generic;
@@ -27,74 +27,42 @@ public CodeGenerationSettings()
2727
/// Collection of templates that will be parsed and output in the target folder.
2828
/// </summary>
2929
[JsonProperty("include")]
30-
public ICollection<CodeGenerationTemplateSettings> Include
31-
{
32-
get;
33-
set;
34-
}
30+
public ICollection<CodeGenerationTemplateSettings> Include { get; set; }
3531

3632
/// <summary>
3733
/// Indicates whether or not domains marked as depreciated will be generated. (Default: true)
3834
/// </summary>
3935
[JsonProperty("includeDeprecatedDomains")]
40-
public bool IncludeDeprecatedDomains
41-
{
42-
get;
43-
set;
44-
}
36+
public bool IncludeDeprecatedDomains { get; set; }
4537

4638
/// <summary>
4739
/// Indicates whether or not domains marked as depreciated will be generated. (Default: true)
4840
/// </summary>
4941
[JsonProperty("includeExperimentalDomains")]
50-
public bool IncludeExperimentalDomains
51-
{
52-
get;
53-
set;
54-
}
42+
public bool IncludeExperimentalDomains { get; set; }
5543

5644
/// <summary>
5745
/// Gets or sets the root namespace of generated classes.
5846
/// </summary>
5947
[JsonProperty("rootNamespace")]
60-
public string RootNamespace
61-
{
62-
get;
63-
set;
64-
}
48+
public string RootNamespace { get; set; }
6549

6650
/// <summary>
6751
/// Gets the version number of the runtime.
6852
/// </summary>
6953
[JsonProperty("runtimeVersion")]
70-
public string RuntimeVersion
71-
{
72-
get;
73-
set;
74-
}
54+
public string RuntimeVersion { get; set; }
7555

7656
[JsonProperty("definitionTemplates")]
77-
public CodeGenerationDefinitionTemplateSettings DefinitionTemplates
78-
{
79-
get;
80-
set;
81-
}
57+
public CodeGenerationDefinitionTemplateSettings DefinitionTemplates { get; set; }
8258

8359
[JsonProperty("templatesPath")]
84-
public string TemplatesPath
85-
{
86-
get;
87-
set;
88-
}
60+
public string TemplatesPath { get; set; }
8961

9062
/// <summary>
9163
/// The using statements that will be included on each generated file.
9264
/// </summary>
9365
[JsonProperty("usingStatements")]
94-
public ICollection<string> UsingStatements
95-
{
96-
get;
97-
set;
98-
}
66+
public ICollection<string> UsingStatements { get; set; }
9967
}
10068
}

0 commit comments

Comments
 (0)