20
20
using OpenQA . Selenium . Internal ;
21
21
using System ;
22
22
using System . Collections . Generic ;
23
+ using System . Diagnostics . CodeAnalysis ;
23
24
using System . IO ;
24
25
using System . IO . Compression ;
25
26
using System . Text . Json ;
26
27
28
+ #nullable enable
29
+
27
30
namespace OpenQA . Selenium . Firefox
28
31
{
29
32
/// <summary>
@@ -32,13 +35,10 @@ namespace OpenQA.Selenium.Firefox
32
35
public class FirefoxProfile
33
36
{
34
37
private const string UserPreferencesFileName = "user.js" ;
35
-
36
- private string profileDir ;
37
- private string sourceProfileDir ;
38
- private bool deleteSource ;
39
- private bool deleteOnClean = true ;
40
- private Preferences profilePreferences ;
41
- private Dictionary < string , FirefoxExtension > extensions = new Dictionary < string , FirefoxExtension > ( ) ;
38
+ private readonly string ? sourceProfileDir ;
39
+ private readonly bool deleteSource ;
40
+ private readonly Preferences profilePreferences ;
41
+ private readonly Dictionary < string , FirefoxExtension > extensions = new Dictionary < string , FirefoxExtension > ( ) ;
42
42
43
43
/// <summary>
44
44
/// Initializes a new instance of the <see cref="FirefoxProfile"/> class.
@@ -53,7 +53,7 @@ public FirefoxProfile()
53
53
/// specific profile directory.
54
54
/// </summary>
55
55
/// <param name="profileDirectory">The directory containing the profile.</param>
56
- public FirefoxProfile ( string profileDirectory )
56
+ public FirefoxProfile ( string ? profileDirectory )
57
57
: this ( profileDirectory , false )
58
58
{
59
59
}
@@ -64,31 +64,24 @@ public FirefoxProfile(string profileDirectory)
64
64
/// </summary>
65
65
/// <param name="profileDirectory">The directory containing the profile.</param>
66
66
/// <param name="deleteSourceOnClean">Delete the source directory of the profile upon cleaning.</param>
67
- public FirefoxProfile ( string profileDirectory , bool deleteSourceOnClean )
67
+ public FirefoxProfile ( string ? profileDirectory , bool deleteSourceOnClean )
68
68
{
69
69
this . sourceProfileDir = profileDirectory ;
70
70
this . deleteSource = deleteSourceOnClean ;
71
- this . ReadDefaultPreferences ( ) ;
71
+ this . profilePreferences = this . ReadDefaultPreferences ( ) ;
72
72
this . profilePreferences . AppendPreferences ( this . ReadExistingPreferences ( ) ) ;
73
73
}
74
74
75
75
/// <summary>
76
76
/// Gets the directory containing the profile.
77
77
/// </summary>
78
- public string ProfileDirectory
79
- {
80
- get { return this . profileDir ; }
81
- }
78
+ public string ? ProfileDirectory { get ; private set ; }
82
79
83
80
/// <summary>
84
81
/// Gets or sets a value indicating whether to delete this profile after use with
85
82
/// the <see cref="FirefoxDriver"/>.
86
83
/// </summary>
87
- public bool DeleteAfterUse
88
- {
89
- get { return this . deleteOnClean ; }
90
- set { this . deleteOnClean = value ; }
91
- }
84
+ public bool DeleteAfterUse { get ; set ; } = true ;
92
85
93
86
/// <summary>
94
87
/// Converts a base64-encoded string into a <see cref="FirefoxProfile"/>.
@@ -130,6 +123,7 @@ public void AddExtension(string extensionToInstall)
130
123
/// </summary>
131
124
/// <param name="name">The name of the preference to add.</param>
132
125
/// <param name="value">A <see cref="string"/> value to add to the profile.</param>
126
+ /// <exception cref="ArgumentNullException">If <paramref name="name"/> or <paramref name="value"/> are <see langword="null"/>.</exception>
133
127
public void SetPreference ( string name , string value )
134
128
{
135
129
this . profilePreferences . SetPreference ( name , value ) ;
@@ -140,6 +134,7 @@ public void SetPreference(string name, string value)
140
134
/// </summary>
141
135
/// <param name="name">The name of the preference to add.</param>
142
136
/// <param name="value">A <see cref="int"/> value to add to the profile.</param>
137
+ /// <exception cref="ArgumentNullException">If <paramref name="name"/> is <see langword="null"/>.</exception>
143
138
public void SetPreference ( string name , int value )
144
139
{
145
140
this . profilePreferences . SetPreference ( name , value ) ;
@@ -150,6 +145,7 @@ public void SetPreference(string name, int value)
150
145
/// </summary>
151
146
/// <param name="name">The name of the preference to add.</param>
152
147
/// <param name="value">A <see cref="bool"/> value to add to the profile.</param>
148
+ /// <exception cref="ArgumentNullException">If <paramref name="name"/> is <see langword="null"/>.</exception>
153
149
public void SetPreference ( string name , bool value )
154
150
{
155
151
this . profilePreferences . SetPreference ( name , value ) ;
@@ -158,22 +154,23 @@ public void SetPreference(string name, bool value)
158
154
/// <summary>
159
155
/// Writes this in-memory representation of a profile to disk.
160
156
/// </summary>
157
+ [ MemberNotNull ( nameof ( ProfileDirectory ) ) ]
161
158
public void WriteToDisk ( )
162
159
{
163
- this . profileDir = GenerateProfileDirectoryName ( ) ;
160
+ this . ProfileDirectory = GenerateProfileDirectoryName ( ) ;
164
161
if ( ! string . IsNullOrEmpty ( this . sourceProfileDir ) )
165
162
{
166
- FileUtilities . CopyDirectory ( this . sourceProfileDir , this . profileDir ) ;
163
+ FileUtilities . CopyDirectory ( this . sourceProfileDir , this . ProfileDirectory ) ;
167
164
}
168
165
else
169
166
{
170
- Directory . CreateDirectory ( this . profileDir ) ;
167
+ Directory . CreateDirectory ( this . ProfileDirectory ) ;
171
168
}
172
169
173
- this . InstallExtensions ( ) ;
174
- this . DeleteLockFiles ( ) ;
175
- this . DeleteExtensionsCache ( ) ;
176
- this . UpdateUserPreferences ( ) ;
170
+ this . InstallExtensions ( this . ProfileDirectory ) ;
171
+ this . DeleteLockFiles ( this . ProfileDirectory ) ;
172
+ this . DeleteExtensionsCache ( this . ProfileDirectory ) ;
173
+ this . UpdateUserPreferences ( this . ProfileDirectory ) ;
177
174
}
178
175
179
176
/// <summary>
@@ -185,9 +182,9 @@ public void WriteToDisk()
185
182
/// is deleted.</remarks>
186
183
public void Clean ( )
187
184
{
188
- if ( this . deleteOnClean && ! string . IsNullOrEmpty ( this . profileDir ) && Directory . Exists ( this . profileDir ) )
185
+ if ( this . DeleteAfterUse && ! string . IsNullOrEmpty ( this . ProfileDirectory ) && Directory . Exists ( this . ProfileDirectory ) )
189
186
{
190
- FileUtilities . DeleteDirectory ( this . profileDir ) ;
187
+ FileUtilities . DeleteDirectory ( this . ProfileDirectory ) ;
191
188
}
192
189
193
190
if ( this . deleteSource && ! string . IsNullOrEmpty ( this . sourceProfileDir ) && Directory . Exists ( this . sourceProfileDir ) )
@@ -202,17 +199,17 @@ public void Clean()
202
199
/// <returns>A base64-encoded string containing the contents of the profile.</returns>
203
200
public string ToBase64String ( )
204
201
{
205
- string base64zip = string . Empty ;
202
+ string base64zip ;
206
203
this . WriteToDisk ( ) ;
207
204
208
205
using ( MemoryStream profileMemoryStream = new MemoryStream ( ) )
209
206
{
210
207
using ( ZipArchive profileZipArchive = new ZipArchive ( profileMemoryStream , ZipArchiveMode . Create , true ) )
211
208
{
212
- string [ ] files = Directory . GetFiles ( this . profileDir , "*.*" , SearchOption . AllDirectories ) ;
209
+ string [ ] files = Directory . GetFiles ( this . ProfileDirectory , "*.*" , SearchOption . AllDirectories ) ;
213
210
foreach ( string file in files )
214
211
{
215
- string fileNameInZip = file . Substring ( this . profileDir . Length + 1 ) . Replace ( Path . DirectorySeparatorChar , '/' ) ;
212
+ string fileNameInZip = file . Substring ( this . ProfileDirectory . Length + 1 ) . Replace ( Path . DirectorySeparatorChar , '/' ) ;
216
213
profileZipArchive . CreateEntryFromFile ( file , fileNameInZip ) ;
217
214
}
218
215
}
@@ -236,20 +233,20 @@ private static string GenerateProfileDirectoryName()
236
233
/// <summary>
237
234
/// Deletes the lock files for a profile.
238
235
/// </summary>
239
- private void DeleteLockFiles ( )
236
+ private void DeleteLockFiles ( string profileDirectory )
240
237
{
241
- File . Delete ( Path . Combine ( this . profileDir , ".parentlock" ) ) ;
242
- File . Delete ( Path . Combine ( this . profileDir , "parent.lock" ) ) ;
238
+ File . Delete ( Path . Combine ( profileDirectory , ".parentlock" ) ) ;
239
+ File . Delete ( Path . Combine ( profileDirectory , "parent.lock" ) ) ;
243
240
}
244
241
245
242
/// <summary>
246
243
/// Installs all extensions in the profile in the directory on disk.
247
244
/// </summary>
248
- private void InstallExtensions ( )
245
+ private void InstallExtensions ( string profileDirectory )
249
246
{
250
247
foreach ( string extensionKey in this . extensions . Keys )
251
248
{
252
- this . extensions [ extensionKey ] . Install ( this . profileDir ) ;
249
+ this . extensions [ extensionKey ] . Install ( profileDirectory ) ;
253
250
}
254
251
}
255
252
@@ -259,10 +256,10 @@ private void InstallExtensions()
259
256
/// <remarks>If the extensions cache does not exist for this profile, the
260
257
/// <see cref="DeleteExtensionsCache"/> method performs no operations, but
261
258
/// succeeds.</remarks>
262
- private void DeleteExtensionsCache ( )
259
+ private void DeleteExtensionsCache ( string profileDirectory )
263
260
{
264
- DirectoryInfo ex = new DirectoryInfo ( Path . Combine ( this . profileDir , "extensions" ) ) ;
265
- string cacheFile = Path . Combine ( ex . Parent . FullName , "extensions.cache" ) ;
261
+ DirectoryInfo ex = new DirectoryInfo ( Path . Combine ( profileDirectory , "extensions" ) ) ;
262
+ string cacheFile = Path . Combine ( ex . Parent ! . FullName , "extensions.cache" ) ;
266
263
if ( File . Exists ( cacheFile ) )
267
264
{
268
265
File . Delete ( cacheFile ) ;
@@ -272,9 +269,9 @@ private void DeleteExtensionsCache()
272
269
/// <summary>
273
270
/// Writes the user preferences to the profile.
274
271
/// </summary>
275
- private void UpdateUserPreferences ( )
272
+ private void UpdateUserPreferences ( string profileDirectory )
276
273
{
277
- string userPrefs = Path . Combine ( this . profileDir , UserPreferencesFileName ) ;
274
+ string userPrefs = Path . Combine ( profileDirectory , UserPreferencesFileName ) ;
278
275
if ( File . Exists ( userPrefs ) )
279
276
{
280
277
try
@@ -300,7 +297,7 @@ private void UpdateUserPreferences()
300
297
this . profilePreferences . WriteToFile ( userPrefs ) ;
301
298
}
302
299
303
- private void ReadDefaultPreferences ( )
300
+ private Preferences ReadDefaultPreferences ( )
304
301
{
305
302
using ( Stream defaultPrefsStream = ResourceUtilities . GetResourceStream ( "webdriver_prefs.json" , "webdriver_prefs.json" ) )
306
303
{
@@ -309,7 +306,7 @@ private void ReadDefaultPreferences()
309
306
JsonElement immutableDefaultPreferences = defaultPreferences . RootElement . GetProperty ( "frozen" ) ;
310
307
JsonElement editableDefaultPreferences = defaultPreferences . RootElement . GetProperty ( "mutable" ) ;
311
308
312
- this . profilePreferences = new Preferences ( immutableDefaultPreferences , editableDefaultPreferences ) ;
309
+ return new Preferences ( immutableDefaultPreferences , editableDefaultPreferences ) ;
313
310
}
314
311
}
315
312
0 commit comments