blob: b7acb42ef2dbfea638e40148d800ed7f480a2a6c [file] [log] [blame] [edit]
// <copyright file="Command.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.Internal;
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
namespace OpenQA.Selenium;
/// <summary>
/// Provides a way to send commands to the remote server
/// </summary>
public class Command
{
private readonly static JsonSerializerOptions s_jsonSerializerOptions = new()
{
TypeInfoResolverChain =
{
CommandJsonSerializerContext.Default,
new DefaultJsonTypeInfoResolver()
},
Converters = { new ResponseValueJsonConverter() }
};
/// <summary>
/// Initializes a new instance of the <see cref="Command"/> class using a command name and a JSON-encoded string for the parameters.
/// </summary>
/// <param name="name">Name of the command</param>
/// <param name="jsonParameters">Parameters for the command as a JSON-encoded string.</param>
public Command(string name, string jsonParameters)
: this(null, name, ConvertParametersFromJson(jsonParameters))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Command"/> class for a Session
/// </summary>
/// <param name="sessionId">Session ID the driver is using</param>
/// <param name="name">Name of the command</param>
/// <param name="parameters">Parameters for that command</param>
/// <exception cref="ArgumentNullException">If <paramref name="name"/> is <see langword="null"/>.</exception>
public Command(SessionId? sessionId, string name, Dictionary<string, object?>? parameters)
{
this.SessionId = sessionId;
this.Parameters = parameters ?? new Dictionary<string, object?>();
this.Name = name ?? throw new ArgumentNullException(nameof(name));
}
/// <summary>
/// Gets the SessionID of the command
/// </summary>
[JsonPropertyName("sessionId")]
public SessionId? SessionId { get; }
/// <summary>
/// Gets the command name
/// </summary>
[JsonPropertyName("name")]
public string Name { get; }
/// <summary>
/// Gets the parameters of the command
/// </summary>
[JsonPropertyName("parameters")]
public Dictionary<string, object?> Parameters { get; }
/// <summary>
/// Gets the parameters of the command as a JSON-encoded string.
/// </summary>
public string ParametersAsJsonString
{
get
{
if (this.Parameters != null && this.Parameters.Count > 0)
{
return JsonSerializer.Serialize(this.Parameters, s_jsonSerializerOptions);
}
else
{
return "{}";
}
}
}
/// <summary>
/// Returns a string of the Command object
/// </summary>
/// <returns>A string representation of the Command Object</returns>
public override string ToString()
{
return string.Concat("[", this.SessionId, "]: ", this.Name, " ", this.ParametersAsJsonString);
}
/// <summary>
/// Gets the command parameters as a <see cref="Dictionary{K, V}"/>, with a string key, and an object value.
/// </summary>
/// <param name="value">The JSON-encoded string representing the command parameters.</param>
/// <returns>A <see cref="Dictionary{K, V}"/> with a string keys, and an object value. </returns>
/// <exception cref="JsonException">If <paramref name="value"/> is not a JSON object.</exception>
/// <exception cref="ArgumentNullException">If <paramref name="value"/> is <see langword="null"/>.</exception>
private static Dictionary<string, object?>? ConvertParametersFromJson(string value)
{
Dictionary<string, object?>? parameters = JsonSerializer.Deserialize<Dictionary<string, object?>>(value, CommandJsonSerializerContext.Default.DictionaryStringObject!);
return parameters;
}
}
// Built-in types
[JsonSerializable(typeof(bool))]
[JsonSerializable(typeof(byte))]
[JsonSerializable(typeof(sbyte))]
[JsonSerializable(typeof(char))]
[JsonSerializable(typeof(decimal))]
[JsonSerializable(typeof(double))]
[JsonSerializable(typeof(float))]
[JsonSerializable(typeof(int))]
[JsonSerializable(typeof(uint))]
[JsonSerializable(typeof(nint))]
[JsonSerializable(typeof(nuint))]
[JsonSerializable(typeof(long))]
[JsonSerializable(typeof(ulong))]
[JsonSerializable(typeof(short))]
[JsonSerializable(typeof(ushort))]
[JsonSerializable(typeof(string))]
// Selenium WebDriver types
[JsonSerializable(typeof(char[]))]
[JsonSerializable(typeof(byte[]))]
[JsonSerializable(typeof(Chromium.ChromiumNetworkConditions))]
[JsonSerializable(typeof(Cookie))]
[JsonSerializable(typeof(ReturnedCookie))]
[JsonSerializable(typeof(Proxy))]
// Selenium Dictionaries, primarily used in Capabilities
[JsonSerializable(typeof(Dictionary<string, object>))]
[JsonSerializable(typeof(Dictionary<string, bool>))]
[JsonSerializable(typeof(Dictionary<string, byte>))]
[JsonSerializable(typeof(Dictionary<string, sbyte>))]
[JsonSerializable(typeof(Dictionary<string, char>))]
[JsonSerializable(typeof(Dictionary<string, decimal>))]
[JsonSerializable(typeof(Dictionary<string, double>))]
[JsonSerializable(typeof(Dictionary<string, float>))]
[JsonSerializable(typeof(Dictionary<string, int>))]
[JsonSerializable(typeof(Dictionary<string, uint>))]
[JsonSerializable(typeof(Dictionary<string, nint>))]
[JsonSerializable(typeof(Dictionary<string, nuint>))]
[JsonSerializable(typeof(Dictionary<string, long>))]
[JsonSerializable(typeof(Dictionary<string, ulong>))]
[JsonSerializable(typeof(Dictionary<string, short>))]
[JsonSerializable(typeof(Dictionary<string, ushort>))]
[JsonSerializable(typeof(Dictionary<string, string>))]
[JsonSourceGenerationOptions(Converters = [typeof(ResponseValueJsonConverter)])]
internal partial class CommandJsonSerializerContext : JsonSerializerContext;