Skip to content

Commit 83d52f8

Browse files
[dotnet] Make FirefoxProfile AOT-safe (#14742)
1 parent bee1571 commit 83d52f8

File tree

2 files changed

+68
-66
lines changed

2 files changed

+68
-66
lines changed

dotnet/src/webdriver/Firefox/FirefoxProfile.cs

+6-16
Original file line numberDiff line numberDiff line change
@@ -296,24 +296,14 @@ private void UpdateUserPreferences()
296296

297297
private void ReadDefaultPreferences()
298298
{
299-
var jsonSerializerOptions = new JsonSerializerOptions
300-
{
301-
Converters =
302-
{
303-
new ResponseValueJsonConverter()
304-
}
305-
};
306-
307299
using (Stream defaultPrefsStream = ResourceUtilities.GetResourceStream("webdriver_prefs.json", "webdriver_prefs.json"))
308300
{
309-
using (StreamReader reader = new StreamReader(defaultPrefsStream))
310-
{
311-
string defaultPreferences = reader.ReadToEnd();
312-
Dictionary<string, object> deserializedPreferences = JsonSerializer.Deserialize<Dictionary<string, object>>(defaultPreferences, jsonSerializerOptions);
313-
Dictionary<string, object> immutableDefaultPreferences = deserializedPreferences["frozen"] as Dictionary<string, object>;
314-
Dictionary<string, object> editableDefaultPreferences = deserializedPreferences["mutable"] as Dictionary<string, object>;
315-
this.profilePreferences = new Preferences(immutableDefaultPreferences, editableDefaultPreferences);
316-
}
301+
using JsonDocument defaultPreferences = JsonDocument.Parse(defaultPrefsStream);
302+
303+
JsonElement immutableDefaultPreferences = defaultPreferences.RootElement.GetProperty("frozen");
304+
JsonElement editableDefaultPreferences = defaultPreferences.RootElement.GetProperty("mutable");
305+
306+
this.profilePreferences = new Preferences(immutableDefaultPreferences, editableDefaultPreferences);
317307
}
318308
}
319309

dotnet/src/webdriver/Firefox/Preferences.cs

+62-50
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
using System.Collections.Generic;
2222
using System.Globalization;
2323
using System.IO;
24+
using System.Text.Json;
25+
26+
#nullable enable
2427

2528
namespace OpenQA.Selenium.Firefox
2629
{
@@ -29,31 +32,27 @@ namespace OpenQA.Selenium.Firefox
2932
/// </summary>
3033
internal class Preferences
3134
{
32-
private Dictionary<string, string> preferences = new Dictionary<string, string>();
33-
private Dictionary<string, string> immutablePreferences = new Dictionary<string, string>();
35+
private readonly Dictionary<string, string> preferences = new Dictionary<string, string>();
36+
private readonly HashSet<string> immutablePreferences = new HashSet<string>();
3437

3538
/// <summary>
3639
/// Initializes a new instance of the <see cref="Preferences"/> class.
3740
/// </summary>
3841
/// <param name="defaultImmutablePreferences">A set of preferences that cannot be modified once set.</param>
3942
/// <param name="defaultPreferences">A set of default preferences.</param>
40-
public Preferences(Dictionary<string, object> defaultImmutablePreferences, Dictionary<string, object> defaultPreferences)
43+
public Preferences(JsonElement defaultImmutablePreferences, JsonElement defaultPreferences)
4144
{
42-
if (defaultImmutablePreferences != null)
45+
foreach (JsonProperty pref in defaultImmutablePreferences.EnumerateObject())
4346
{
44-
foreach (KeyValuePair<string, object> pref in defaultImmutablePreferences)
45-
{
46-
this.SetPreferenceValue(pref.Key, pref.Value);
47-
this.immutablePreferences.Add(pref.Key, pref.Value.ToString());
48-
}
47+
this.ThrowIfPreferenceIsImmutable(pref.Name, pref.Value);
48+
this.preferences[pref.Name] = pref.Value.GetRawText();
49+
this.immutablePreferences.Add(pref.Name);
4950
}
5051

51-
if (defaultPreferences != null)
52+
foreach (JsonProperty pref in defaultPreferences.EnumerateObject())
5253
{
53-
foreach (KeyValuePair<string, object> pref in defaultPreferences)
54-
{
55-
this.SetPreferenceValue(pref.Key, pref.Value);
56-
}
54+
this.ThrowIfPreferenceIsImmutable(pref.Name, pref.Value);
55+
this.preferences[pref.Name] = pref.Value.GetRawText();
5756
}
5857
}
5958

@@ -64,9 +63,31 @@ public Preferences(Dictionary<string, object> defaultImmutablePreferences, Dicti
6463
/// <param name="value">A <see cref="string"/> value give the preference.</param>
6564
/// <remarks>If the preference already exists in the currently-set list of preferences,
6665
/// the value will be updated.</remarks>
66+
/// <exception cref="ArgumentNullException">If <paramref name="key"/> or <paramref name="value"/> are <see langword="null"/>.</exception>
67+
/// <exception cref="ArgumentException">
68+
/// <para>If <paramref name="value"/> is wrapped with double-quotes.</para>
69+
/// <para>-or-</para>
70+
/// <para>If the specified preference is immutable.</para>
71+
/// </exception>
6772
internal void SetPreference(string key, string value)
6873
{
69-
this.SetPreferenceValue(key, value);
74+
if (key is null)
75+
{
76+
throw new ArgumentNullException(nameof(key));
77+
}
78+
79+
if (value is null)
80+
{
81+
throw new ArgumentNullException(nameof(value));
82+
}
83+
84+
if (IsWrappedAsString(value))
85+
{
86+
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Preference values must be plain strings: {0}: {1}", key, value));
87+
}
88+
89+
this.ThrowIfPreferenceIsImmutable(key, value);
90+
this.preferences[key] = string.Format(CultureInfo.InvariantCulture, "\"{0}\"", value);
7091
}
7192

7293
/// <summary>
@@ -76,9 +97,17 @@ internal void SetPreference(string key, string value)
7697
/// <param name="value">A <see cref="int"/> value give the preference.</param>
7798
/// <remarks>If the preference already exists in the currently-set list of preferences,
7899
/// the value will be updated.</remarks>
100+
/// <exception cref="ArgumentNullException">If <paramref name="key"/> is <see langword="null"/>.</exception>
101+
/// <exception cref="ArgumentException">If the specified preference is immutable.</exception>
79102
internal void SetPreference(string key, int value)
80103
{
81-
this.SetPreferenceValue(key, value);
104+
if (key is null)
105+
{
106+
throw new ArgumentNullException(nameof(key));
107+
}
108+
109+
this.ThrowIfPreferenceIsImmutable(key, value);
110+
this.preferences[key] = value.ToString(CultureInfo.InvariantCulture);
82111
}
83112

84113
/// <summary>
@@ -88,16 +117,25 @@ internal void SetPreference(string key, int value)
88117
/// <param name="value">A <see cref="bool"/> value give the preference.</param>
89118
/// <remarks>If the preference already exists in the currently-set list of preferences,
90119
/// the value will be updated.</remarks>
120+
/// <exception cref="ArgumentNullException">If <paramref name="key"/> is <see langword="null"/>.</exception>
121+
/// <exception cref="ArgumentException">If the specified preference is immutable.</exception>
91122
internal void SetPreference(string key, bool value)
92123
{
93-
this.SetPreferenceValue(key, value);
124+
if (key is null)
125+
{
126+
throw new ArgumentNullException(nameof(key));
127+
}
128+
129+
this.ThrowIfPreferenceIsImmutable(key, value);
130+
this.preferences[key] = value ? "true" : "false";
94131
}
95132

96133
/// <summary>
97134
/// Gets a preference from the list of preferences.
98135
/// </summary>
99136
/// <param name="preferenceName">The name of the preference to retrieve.</param>
100137
/// <returns>The value of the preference, or an empty string if the preference is not set.</returns>
138+
/// <exception cref="ArgumentNullException">If <paramref name="preferenceName"/> is <see langword="null"/>.</exception>
101139
internal string GetPreference(string preferenceName)
102140
{
103141
if (this.preferences.ContainsKey(preferenceName))
@@ -151,44 +189,18 @@ private static bool IsWrappedAsString(string value)
151189
return value.StartsWith("\"", StringComparison.OrdinalIgnoreCase) && value.EndsWith("\"", StringComparison.OrdinalIgnoreCase);
152190
}
153191

154-
private bool IsSettablePreference(string preferenceName)
192+
private void ThrowIfPreferenceIsImmutable<TValue>(string preferenceName, TValue value)
155193
{
156-
return !this.immutablePreferences.ContainsKey(preferenceName);
157-
}
158-
159-
private void SetPreferenceValue(string key, object value)
160-
{
161-
if (!this.IsSettablePreference(key))
194+
if (this.immutablePreferences.Contains(preferenceName))
162195
{
163-
string message = string.Format(CultureInfo.InvariantCulture, "Preference {0} may not be overridden: frozen value={1}, requested value={2}", key, this.immutablePreferences[key], value.ToString());
196+
string message = string.Format(CultureInfo.InvariantCulture, "Preference {0} may not be overridden: frozen value={1}, requested value={2}", preferenceName, this.preferences[preferenceName], value?.ToString());
164197
throw new ArgumentException(message);
165198
}
199+
}
166200

167-
string stringValue = value as string;
168-
if (stringValue != null)
169-
{
170-
if (IsWrappedAsString(stringValue))
171-
{
172-
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Preference values must be plain strings: {0}: {1}", key, value));
173-
}
174-
175-
this.preferences[key] = string.Format(CultureInfo.InvariantCulture, "\"{0}\"", value);
176-
return;
177-
}
178-
179-
if (value is bool)
180-
{
181-
this.preferences[key] = Convert.ToBoolean(value, CultureInfo.InvariantCulture).ToString().ToLowerInvariant();
182-
return;
183-
}
184-
185-
if (value is int || value is long)
186-
{
187-
this.preferences[key] = Convert.ToInt32(value, CultureInfo.InvariantCulture).ToString(CultureInfo.InvariantCulture);
188-
return;
189-
}
190-
191-
throw new WebDriverException("Value must be string, int or boolean");
201+
private bool IsSettablePreference(string preferenceName)
202+
{
203+
return !this.immutablePreferences.Contains(preferenceName);
192204
}
193205
}
194206
}

0 commit comments

Comments
 (0)