diff --git a/dotnet/src/webdriver/Firefox/FirefoxProfile.cs b/dotnet/src/webdriver/Firefox/FirefoxProfile.cs index 0998cb436ea94..1814e35b0ca7a 100644 --- a/dotnet/src/webdriver/Firefox/FirefoxProfile.cs +++ b/dotnet/src/webdriver/Firefox/FirefoxProfile.cs @@ -20,10 +20,13 @@ using OpenQA.Selenium.Internal; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.IO.Compression; using System.Text.Json; +#nullable enable + namespace OpenQA.Selenium.Firefox { /// @@ -32,13 +35,10 @@ namespace OpenQA.Selenium.Firefox public class FirefoxProfile { private const string UserPreferencesFileName = "user.js"; - - private string profileDir; - private string sourceProfileDir; - private bool deleteSource; - private bool deleteOnClean = true; - private Preferences profilePreferences; - private Dictionary extensions = new Dictionary(); + private readonly string? sourceProfileDir; + private readonly bool deleteSource; + private readonly Preferences profilePreferences; + private readonly Dictionary extensions = new Dictionary(); /// /// Initializes a new instance of the class. @@ -53,7 +53,7 @@ public FirefoxProfile() /// specific profile directory. /// /// The directory containing the profile. - public FirefoxProfile(string profileDirectory) + public FirefoxProfile(string? profileDirectory) : this(profileDirectory, false) { } @@ -64,31 +64,24 @@ public FirefoxProfile(string profileDirectory) /// /// The directory containing the profile. /// Delete the source directory of the profile upon cleaning. - public FirefoxProfile(string profileDirectory, bool deleteSourceOnClean) + public FirefoxProfile(string? profileDirectory, bool deleteSourceOnClean) { this.sourceProfileDir = profileDirectory; this.deleteSource = deleteSourceOnClean; - this.ReadDefaultPreferences(); + this.profilePreferences = this.ReadDefaultPreferences(); this.profilePreferences.AppendPreferences(this.ReadExistingPreferences()); } /// /// Gets the directory containing the profile. /// - public string ProfileDirectory - { - get { return this.profileDir; } - } + public string? ProfileDirectory { get; private set; } /// /// Gets or sets a value indicating whether to delete this profile after use with /// the . /// - public bool DeleteAfterUse - { - get { return this.deleteOnClean; } - set { this.deleteOnClean = value; } - } + public bool DeleteAfterUse { get; set; } = true; /// /// Converts a base64-encoded string into a . @@ -130,6 +123,7 @@ public void AddExtension(string extensionToInstall) /// /// The name of the preference to add. /// A value to add to the profile. + /// If or are . public void SetPreference(string name, string value) { this.profilePreferences.SetPreference(name, value); @@ -140,6 +134,7 @@ public void SetPreference(string name, string value) /// /// The name of the preference to add. /// A value to add to the profile. + /// If is . public void SetPreference(string name, int value) { this.profilePreferences.SetPreference(name, value); @@ -150,6 +145,7 @@ public void SetPreference(string name, int value) /// /// The name of the preference to add. /// A value to add to the profile. + /// If is . public void SetPreference(string name, bool value) { this.profilePreferences.SetPreference(name, value); @@ -158,22 +154,23 @@ public void SetPreference(string name, bool value) /// /// Writes this in-memory representation of a profile to disk. /// + [MemberNotNull(nameof(ProfileDirectory))] public void WriteToDisk() { - this.profileDir = GenerateProfileDirectoryName(); + this.ProfileDirectory = GenerateProfileDirectoryName(); if (!string.IsNullOrEmpty(this.sourceProfileDir)) { - FileUtilities.CopyDirectory(this.sourceProfileDir, this.profileDir); + FileUtilities.CopyDirectory(this.sourceProfileDir, this.ProfileDirectory); } else { - Directory.CreateDirectory(this.profileDir); + Directory.CreateDirectory(this.ProfileDirectory); } - this.InstallExtensions(); - this.DeleteLockFiles(); - this.DeleteExtensionsCache(); - this.UpdateUserPreferences(); + this.InstallExtensions(this.ProfileDirectory); + this.DeleteLockFiles(this.ProfileDirectory); + this.DeleteExtensionsCache(this.ProfileDirectory); + this.UpdateUserPreferences(this.ProfileDirectory); } /// @@ -185,9 +182,9 @@ public void WriteToDisk() /// is deleted. public void Clean() { - if (this.deleteOnClean && !string.IsNullOrEmpty(this.profileDir) && Directory.Exists(this.profileDir)) + if (this.DeleteAfterUse && !string.IsNullOrEmpty(this.ProfileDirectory) && Directory.Exists(this.ProfileDirectory)) { - FileUtilities.DeleteDirectory(this.profileDir); + FileUtilities.DeleteDirectory(this.ProfileDirectory); } if (this.deleteSource && !string.IsNullOrEmpty(this.sourceProfileDir) && Directory.Exists(this.sourceProfileDir)) @@ -202,17 +199,17 @@ public void Clean() /// A base64-encoded string containing the contents of the profile. public string ToBase64String() { - string base64zip = string.Empty; + string base64zip; this.WriteToDisk(); using (MemoryStream profileMemoryStream = new MemoryStream()) { using (ZipArchive profileZipArchive = new ZipArchive(profileMemoryStream, ZipArchiveMode.Create, true)) { - string[] files = Directory.GetFiles(this.profileDir, "*.*", SearchOption.AllDirectories); + string[] files = Directory.GetFiles(this.ProfileDirectory, "*.*", SearchOption.AllDirectories); foreach (string file in files) { - string fileNameInZip = file.Substring(this.profileDir.Length + 1).Replace(Path.DirectorySeparatorChar, '/'); + string fileNameInZip = file.Substring(this.ProfileDirectory.Length + 1).Replace(Path.DirectorySeparatorChar, '/'); profileZipArchive.CreateEntryFromFile(file, fileNameInZip); } } @@ -236,20 +233,20 @@ private static string GenerateProfileDirectoryName() /// /// Deletes the lock files for a profile. /// - private void DeleteLockFiles() + private void DeleteLockFiles(string profileDirectory) { - File.Delete(Path.Combine(this.profileDir, ".parentlock")); - File.Delete(Path.Combine(this.profileDir, "parent.lock")); + File.Delete(Path.Combine(profileDirectory, ".parentlock")); + File.Delete(Path.Combine(profileDirectory, "parent.lock")); } /// /// Installs all extensions in the profile in the directory on disk. /// - private void InstallExtensions() + private void InstallExtensions(string profileDirectory) { foreach (string extensionKey in this.extensions.Keys) { - this.extensions[extensionKey].Install(this.profileDir); + this.extensions[extensionKey].Install(profileDirectory); } } @@ -259,10 +256,10 @@ private void InstallExtensions() /// If the extensions cache does not exist for this profile, the /// method performs no operations, but /// succeeds. - private void DeleteExtensionsCache() + private void DeleteExtensionsCache(string profileDirectory) { - DirectoryInfo ex = new DirectoryInfo(Path.Combine(this.profileDir, "extensions")); - string cacheFile = Path.Combine(ex.Parent.FullName, "extensions.cache"); + DirectoryInfo ex = new DirectoryInfo(Path.Combine(profileDirectory, "extensions")); + string cacheFile = Path.Combine(ex.Parent!.FullName, "extensions.cache"); if (File.Exists(cacheFile)) { File.Delete(cacheFile); @@ -272,9 +269,9 @@ private void DeleteExtensionsCache() /// /// Writes the user preferences to the profile. /// - private void UpdateUserPreferences() + private void UpdateUserPreferences(string profileDirectory) { - string userPrefs = Path.Combine(this.profileDir, UserPreferencesFileName); + string userPrefs = Path.Combine(profileDirectory, UserPreferencesFileName); if (File.Exists(userPrefs)) { try @@ -300,7 +297,7 @@ private void UpdateUserPreferences() this.profilePreferences.WriteToFile(userPrefs); } - private void ReadDefaultPreferences() + private Preferences ReadDefaultPreferences() { using (Stream defaultPrefsStream = ResourceUtilities.GetResourceStream("webdriver_prefs.json", "webdriver_prefs.json")) { @@ -309,7 +306,7 @@ private void ReadDefaultPreferences() JsonElement immutableDefaultPreferences = defaultPreferences.RootElement.GetProperty("frozen"); JsonElement editableDefaultPreferences = defaultPreferences.RootElement.GetProperty("mutable"); - this.profilePreferences = new Preferences(immutableDefaultPreferences, editableDefaultPreferences); + return new Preferences(immutableDefaultPreferences, editableDefaultPreferences); } } diff --git a/dotnet/src/webdriver/Firefox/FirefoxProfileManager.cs b/dotnet/src/webdriver/Firefox/FirefoxProfileManager.cs index f53ea800e3249..601c784e946ec 100644 --- a/dotnet/src/webdriver/Firefox/FirefoxProfileManager.cs +++ b/dotnet/src/webdriver/Firefox/FirefoxProfileManager.cs @@ -23,6 +23,8 @@ using System.Collections.ObjectModel; using System.IO; +#nullable enable + namespace OpenQA.Selenium.Firefox { /// @@ -45,14 +47,7 @@ public FirefoxProfileManager() /// Gets a containing FirefoxProfiles /// representing the existing named profiles for Firefox. /// - public ReadOnlyCollection ExistingProfiles - { - get - { - List profileList = new List(this.profiles.Keys); - return profileList.AsReadOnly(); - } - } + public ReadOnlyCollection ExistingProfiles => new List(this.profiles.Keys).AsReadOnly(); /// /// Gets a with a given name. @@ -60,37 +55,24 @@ public ReadOnlyCollection ExistingProfiles /// The name of the profile to get. /// A with a given name. /// Returns if no profile with the given name exists. - public FirefoxProfile GetProfile(string profileName) + public FirefoxProfile? GetProfile(string? profileName) { - FirefoxProfile profile = null; - if (!string.IsNullOrEmpty(profileName)) + if (profileName is not null && this.profiles.TryGetValue(profileName, out string? profile)) { - if (this.profiles.ContainsKey(profileName)) - { - profile = new FirefoxProfile(this.profiles[profileName]); - } + return new FirefoxProfile(profile); } - return profile; + return null; } private static string GetApplicationDataDirectory() { - string appDataDirectory = string.Empty; - switch (Environment.OSVersion.Platform) + string appDataDirectory = Environment.OSVersion.Platform switch { - case PlatformID.Unix: - appDataDirectory = Path.Combine(".mozilla", "firefox"); - break; - - case PlatformID.MacOSX: - appDataDirectory = Path.Combine("Library", Path.Combine("Application Support", "Firefox")); - break; - - default: - appDataDirectory = Path.Combine("Mozilla", "Firefox"); - break; - } + PlatformID.Unix => Path.Combine(".mozilla", "firefox"), + PlatformID.MacOSX => Path.Combine("Library", Path.Combine("Application Support", "Firefox")), + _ => Path.Combine("Mozilla", "Firefox"), + }; return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), appDataDirectory); } @@ -109,7 +91,7 @@ private void ReadProfiles(string appDataDirectory) string name = reader.GetValue(sectionName, "name"); bool isRelative = reader.GetValue(sectionName, "isrelative") == "1"; string profilePath = reader.GetValue(sectionName, "path"); - string fullPath = string.Empty; + string fullPath; if (isRelative) { fullPath = Path.Combine(appDataDirectory, profilePath); diff --git a/dotnet/src/webdriver/Internal/FileUtilities.cs b/dotnet/src/webdriver/Internal/FileUtilities.cs index ff23a34a1cf86..b925da2c359a3 100644 --- a/dotnet/src/webdriver/Internal/FileUtilities.cs +++ b/dotnet/src/webdriver/Internal/FileUtilities.cs @@ -76,7 +76,7 @@ public static bool CopyDirectory(string sourceDirectory, string destinationDirec /// /// The directory to delete. /// This method does not throw an exception if the delete fails. - public static void DeleteDirectory(string directoryToDelete) + public static void DeleteDirectory(string? directoryToDelete) { int numberOfRetries = 0; while (Directory.Exists(directoryToDelete) && numberOfRetries < 10) @@ -210,7 +210,11 @@ public static string GetCurrentDirectory() /// The pattern to use in creating the directory name, following standard /// .NET string replacement tokens. /// The full path to the random directory name in the temporary directory. - public static string GenerateRandomTempDirectoryName(string directoryPattern) + public static string GenerateRandomTempDirectoryName( +#if NET8_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.StringSyntax(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.CompositeFormat)] +#endif + string directoryPattern) { string directoryName = string.Format(CultureInfo.InvariantCulture, directoryPattern, Guid.NewGuid().ToString("N")); return Path.Combine(Path.GetTempPath(), directoryName);