diff --git a/lib/PuppeteerSharp.Tests/ChromeLauncherTests/DefaultArgsTests.cs b/lib/PuppeteerSharp.Tests/ChromeLauncherTests/DefaultArgsTests.cs new file mode 100644 index 000000000..231fb66da --- /dev/null +++ b/lib/PuppeteerSharp.Tests/ChromeLauncherTests/DefaultArgsTests.cs @@ -0,0 +1,24 @@ +using System.Linq; +using NUnit.Framework; +using PuppeteerSharp.Nunit; + +namespace PuppeteerSharp.Tests.ChromeLauncherTests +{ + public class DefaultArgsTests : PuppeteerPageBaseTest + { + [Test, PuppeteerTest("ChromeLauncher.test.ts", "ChromeLauncher", "removes disabled features if they are enabled explicitly")] + public void RemovesDisabledFeaturesIfTheyAreEnabledExplicitly() + { + var args = ChromeLauncher.GetDefaultArgs(new LaunchOptions + { + Args = new[] { "--enable-features=Translate" }, + }); + + var disableFeaturesFlag = args.FirstOrDefault(arg => arg.StartsWith("--disable-features=", System.StringComparison.Ordinal)); + Assert.That(disableFeaturesFlag, Is.Not.Null); + + var disabledFeatures = disableFeaturesFlag.Split('=')[1].Split(','); + Assert.That(disabledFeatures, Does.Not.Contain("Translate")); + } + } +} diff --git a/lib/PuppeteerSharp.Tests/ChromeLauncherTests/GetFeaturesTests.cs b/lib/PuppeteerSharp.Tests/ChromeLauncherTests/GetFeaturesTests.cs index 8ffac6aff..e93a97b8c 100644 --- a/lib/PuppeteerSharp.Tests/ChromeLauncherTests/GetFeaturesTests.cs +++ b/lib/PuppeteerSharp.Tests/ChromeLauncherTests/GetFeaturesTests.cs @@ -41,5 +41,12 @@ public void HandlesEqualsSignAroundTheFlagAndValue() var result = ChromeLauncher.GetFeatures("--foo", new[] { "--foo=bar", "--foo=baz" }); Assert.That(result, Is.EqualTo(new[] { "bar", "baz" })); } + + [Test, PuppeteerTest("ChromeLauncher.test.ts", "getFeatures", "handles comma-separated values")] + public void HandlesCommaSeparatedValues() + { + var result = ChromeLauncher.GetFeatures("--foo", new[] { "--foo=bar,baz", "--foo=qux" }); + Assert.That(result, Is.EqualTo(new[] { "bar", "baz", "qux" })); + } } } diff --git a/lib/PuppeteerSharp/ChromeLauncher.cs b/lib/PuppeteerSharp/ChromeLauncher.cs index 33ee07e5c..d75900356 100644 --- a/lib/PuppeteerSharp/ChromeLauncher.cs +++ b/lib/PuppeteerSharp/ChromeLauncher.cs @@ -49,8 +49,24 @@ public ChromeLauncher(string executable, LaunchOptions options) internal static string[] GetDefaultArgs(LaunchOptions options) { - var userDisabledFeatures = GetFeatures("--disable-features", options.Args); var args = options.Args ?? []; + + var userEnabledFeatures = GetFeatures("--enable-features", options.Args); + if (args != null && userEnabledFeatures.Length > 0) + { + args = RemoveMatchingFlags(options.Args, "--enable-features"); + } + + // Merge default enabled features with user-provided ones, if any. + var enabledFeatures = new List + { + "PdfOopif", + }; + + enabledFeatures.AddRange(userEnabledFeatures); + enabledFeatures = enabledFeatures.Where(feature => !string.IsNullOrEmpty(feature)).ToList(); + + var userDisabledFeatures = GetFeatures("--disable-features", options.Args); if (args is not null && userDisabledFeatures.Length > 0) { args = RemoveMatchingFlags(options.Args, "--disable-features"); @@ -71,20 +87,10 @@ internal static string[] GetDefaultArgs(LaunchOptions options) }; disabledFeatures.AddRange(userDisabledFeatures); - - var userEnabledFeatures = GetFeatures("--enable-features", options.Args); - if (args != null && userEnabledFeatures.Length > 0) - { - args = RemoveMatchingFlags(options.Args, "--enable-features"); - } - - // Merge default enabled features with user-provided ones, if any. - var enabledFeatures = new List - { - "PdfOopif", - }; - - enabledFeatures.AddRange(userEnabledFeatures); + disabledFeatures = disabledFeatures + .Where(feature => !string.IsNullOrEmpty(feature)) + .Where(disabledFeature => !enabledFeatures.Contains(disabledFeature)) + .ToList(); var chromiumArguments = new List( [ @@ -165,13 +171,24 @@ internal static string[] GetDefaultArgs(LaunchOptions options) } internal static string[] GetFeatures(string flag, string[] options) - => options - .Where(s => s.StartsWith($"{flag}=", StringComparison.InvariantCultureIgnoreCase)) - .Select(s => s.Substring(flag.Length + 1)) - .Where(s => !string.IsNullOrEmpty(s)).ToArray(); + { + var prefix = flag.EndsWith("=", StringComparison.Ordinal) ? flag : $"{flag}="; + return (options ?? []) + .Where(s => s.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)) + .SelectMany(s => s + .Substring(s.IndexOf('=') + 1) + .Trim() + .Split(',') + .Select(feature => feature.Trim())) + .Where(s => !string.IsNullOrEmpty(s)) + .ToArray(); + } internal static string[] RemoveMatchingFlags(string[] array, string flag) - => array.Where(arg => !arg.StartsWith(flag, StringComparison.InvariantCultureIgnoreCase)).ToArray(); + { + var prefix = flag.EndsWith("=", StringComparison.Ordinal) ? flag : $"{flag}="; + return array.Where(arg => !arg.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)).ToArray(); + } /// /// Creates the pipe transport after the process has started.