From fc8b0d5c8c2a50a62ae52b5a66885518a3562515 Mon Sep 17 00:00:00 2001 From: Michael Render Date: Thu, 24 Oct 2024 23:48:10 -0400 Subject: [PATCH 1/2] [dotnet] Strongly-typed handling for firefox profile's default preferences --- .../src/webdriver/Firefox/FirefoxProfile.cs | 16 ++--- dotnet/src/webdriver/Firefox/Preferences.cs | 62 +++++++++++-------- 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/dotnet/src/webdriver/Firefox/FirefoxProfile.cs b/dotnet/src/webdriver/Firefox/FirefoxProfile.cs index 2c19547bde5a9..a1ade07232de8 100644 --- a/dotnet/src/webdriver/Firefox/FirefoxProfile.cs +++ b/dotnet/src/webdriver/Firefox/FirefoxProfile.cs @@ -21,7 +21,7 @@ using System.Collections.Generic; using System.IO; using System.IO.Compression; -using System.Text.Json; +using System.Text.Json.Nodes; namespace OpenQA.Selenium.Firefox { @@ -295,22 +295,14 @@ private void UpdateUserPreferences() private void ReadDefaultPreferences() { - var jsonSerializerOptions = new JsonSerializerOptions - { - Converters = - { - new ResponseValueJsonConverter() - } - }; - using (Stream defaultPrefsStream = ResourceUtilities.GetResourceStream("webdriver_prefs.json", "webdriver_prefs.json")) { using (StreamReader reader = new StreamReader(defaultPrefsStream)) { string defaultPreferences = reader.ReadToEnd(); - Dictionary deserializedPreferences = JsonSerializer.Deserialize>(defaultPreferences, jsonSerializerOptions); - Dictionary immutableDefaultPreferences = deserializedPreferences["frozen"] as Dictionary; - Dictionary editableDefaultPreferences = deserializedPreferences["mutable"] as Dictionary; + JsonObject deserializedPreferences = JsonNode.Parse(defaultPreferences)?.AsObject() ?? throw new WebDriverException("webdriver_prefs.json contents was not an object"); + JsonObject immutableDefaultPreferences = deserializedPreferences["frozen"] as JsonObject; + JsonObject editableDefaultPreferences = deserializedPreferences["mutable"] as JsonObject; this.profilePreferences = new Preferences(immutableDefaultPreferences, editableDefaultPreferences); } } diff --git a/dotnet/src/webdriver/Firefox/Preferences.cs b/dotnet/src/webdriver/Firefox/Preferences.cs index 366b96b53fa0a..8677104cd974a 100644 --- a/dotnet/src/webdriver/Firefox/Preferences.cs +++ b/dotnet/src/webdriver/Firefox/Preferences.cs @@ -18,8 +18,12 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.IO; +using System.Text.Json.Nodes; + +#nullable enable namespace OpenQA.Selenium.Firefox { @@ -28,28 +32,28 @@ namespace OpenQA.Selenium.Firefox /// internal class Preferences { - private Dictionary preferences = new Dictionary(); - private Dictionary immutablePreferences = new Dictionary(); + private readonly Dictionary preferences = new Dictionary(); + private readonly HashSet immutablePreferences = new HashSet(); /// /// Initializes a new instance of the class. /// /// A set of preferences that cannot be modified once set. /// A set of default preferences. - public Preferences(Dictionary defaultImmutablePreferences, Dictionary defaultPreferences) + public Preferences(JsonObject? defaultImmutablePreferences, JsonObject? defaultPreferences) { if (defaultImmutablePreferences != null) { - foreach (KeyValuePair pref in defaultImmutablePreferences) + foreach (KeyValuePair pref in defaultImmutablePreferences) { this.SetPreferenceValue(pref.Key, pref.Value); - this.immutablePreferences.Add(pref.Key, pref.Value.ToString()); + this.immutablePreferences.Add(pref.Key); } } if (defaultPreferences != null) { - foreach (KeyValuePair pref in defaultPreferences) + foreach (KeyValuePair pref in defaultPreferences) { this.SetPreferenceValue(pref.Key, pref.Value); } @@ -152,39 +156,47 @@ private static bool IsWrappedAsString(string value) private bool IsSettablePreference(string preferenceName) { - return !this.immutablePreferences.ContainsKey(preferenceName); + return !this.immutablePreferences.Contains(preferenceName); } - private void SetPreferenceValue(string key, object value) + private void SetPreferenceValue(string key, JsonNode? value) { if (!this.IsSettablePreference(key)) { - string message = string.Format(CultureInfo.InvariantCulture, "Preference {0} may not be overridden: frozen value={1}, requested value={2}", key, this.immutablePreferences[key], value.ToString()); + string message = string.Format(CultureInfo.InvariantCulture, "Preference {0} may not be overridden: frozen value={1}, requested value={2}", key, this.preferences[key], value?.ToString()); throw new ArgumentException(message); } - string stringValue = value as string; - if (stringValue != null) + if (value is JsonValue jValue) { - if (IsWrappedAsString(stringValue)) + if (jValue.TryGetValue(out string? stringValue)) { - throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Preference values must be plain strings: {0}: {1}", key, value)); + if (IsWrappedAsString(stringValue)) + { + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Preference values must be plain strings: {0}: {1}", key, value)); + } + + this.preferences[key] = string.Format(CultureInfo.InvariantCulture, "\"{0}\"", value); + return; } - this.preferences[key] = string.Format(CultureInfo.InvariantCulture, "\"{0}\"", value); - return; - } + if (jValue.TryGetValue(out bool boolValue)) + { + this.preferences[key] = boolValue ? "true" : "false"; + return; + } - if (value is bool) - { - this.preferences[key] = Convert.ToBoolean(value, CultureInfo.InvariantCulture).ToString().ToLowerInvariant(); - return; - } + if (jValue.TryGetValue(out int intValue)) + { + this.preferences[key] = intValue.ToString(CultureInfo.InvariantCulture); + return; + } - if (value is int || value is long) - { - this.preferences[key] = Convert.ToInt32(value, CultureInfo.InvariantCulture).ToString(CultureInfo.InvariantCulture); - return; + if (jValue.TryGetValue(out long longValue)) + { + this.preferences[key] = ((int)longValue).ToString(CultureInfo.InvariantCulture); + Debug.Fail("Above cast should fail"); + } } throw new WebDriverException("Value must be string, int or boolean"); From 781e30215cf48883c233f5abe115d8eb1646e018 Mon Sep 17 00:00:00 2001 From: Michael Render Date: Fri, 25 Oct 2024 00:12:02 -0400 Subject: [PATCH 2/2] fix cast --- dotnet/src/webdriver/Firefox/Preferences.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dotnet/src/webdriver/Firefox/Preferences.cs b/dotnet/src/webdriver/Firefox/Preferences.cs index 8677104cd974a..b3bf572d52202 100644 --- a/dotnet/src/webdriver/Firefox/Preferences.cs +++ b/dotnet/src/webdriver/Firefox/Preferences.cs @@ -194,8 +194,8 @@ private void SetPreferenceValue(string key, JsonNode? value) if (jValue.TryGetValue(out long longValue)) { - this.preferences[key] = ((int)longValue).ToString(CultureInfo.InvariantCulture); - Debug.Fail("Above cast should fail"); + this.preferences[key] = Convert.ToInt32(longValue, CultureInfo.InvariantCulture).ToString(CultureInfo.InvariantCulture); + Debug.Fail("Above conversion should fail"); } }