"Fossies" - the Fresh Open Source Software Archive

Member "selenium-selenium-4.8.1/dotnet/src/webdriver/Chromium/ChromiumOptions.cs" (17 Feb 2023, 30761 Bytes) of package /linux/www/selenium-selenium-4.8.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C# source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ChromiumOptions.cs" see the Fossies "Dox" file reference documentation.

    1 // <copyright file="ChromiumOptions.cs" company="WebDriver Committers">
    2 // Licensed to the Software Freedom Conservancy (SFC) under one
    3 // or more contributor license agreements. See the NOTICE file
    4 // distributed with this work for additional information
    5 // regarding copyright ownership. The SFC licenses this file
    6 // to you under the Apache License, Version 2.0 (the "License");
    7 // you may not use this file except in compliance with the License.
    8 // You may obtain a copy of the License at
    9 //
   10 //     http://www.apache.org/licenses/LICENSE-2.0
   11 //
   12 // Unless required by applicable law or agreed to in writing, software
   13 // distributed under the License is distributed on an "AS IS" BASIS,
   14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   15 // See the License for the specific language governing permissions and
   16 // limitations under the License.
   17 // </copyright>
   18 
   19 using System;
   20 using System.Collections.Generic;
   21 using System.Collections.ObjectModel;
   22 using System.Globalization;
   23 using System.IO;
   24 using OpenQA.Selenium.Remote;
   25 
   26 namespace OpenQA.Selenium.Chromium
   27 {
   28     /// <summary>
   29     /// Abstract class to manage options specific to Chromium-based browsers.
   30     /// </summary>
   31     public abstract class ChromiumOptions : DriverOptions
   32     {
   33         private const string ArgumentsChromeOption = "args";
   34         private const string BinaryChromeOption = "binary";
   35         private const string ExtensionsChromeOption = "extensions";
   36         private const string LocalStateChromeOption = "localState";
   37         private const string PreferencesChromeOption = "prefs";
   38         private const string DetachChromeOption = "detach";
   39         private const string DebuggerAddressChromeOption = "debuggerAddress";
   40         private const string ExcludeSwitchesChromeOption = "excludeSwitches";
   41         private const string MinidumpPathChromeOption = "minidumpPath";
   42         private const string MobileEmulationChromeOption = "mobileEmulation";
   43         private const string PerformanceLoggingPreferencesChromeOption = "perfLoggingPrefs";
   44         private const string WindowTypesChromeOption = "windowTypes";
   45         private const string UseSpecCompliantProtocolOption = "w3c";
   46 
   47         private bool leaveBrowserRunning;
   48         private bool useSpecCompliantProtocol = true;
   49         private string binaryLocation;
   50         private string debuggerAddress;
   51         private string minidumpPath;
   52         private List<string> arguments = new List<string>();
   53         private List<string> extensionFiles = new List<string>();
   54         private List<string> encodedExtensions = new List<string>();
   55         private List<string> excludedSwitches = new List<string>();
   56         private List<string> windowTypes = new List<string>();
   57         private Dictionary<string, object> additionalChromeOptions = new Dictionary<string, object>();
   58         private Dictionary<string, object> userProfilePreferences;
   59         private Dictionary<string, object> localStatePreferences;
   60 
   61         private string mobileEmulationDeviceName;
   62         private ChromiumMobileEmulationDeviceSettings mobileEmulationDeviceSettings;
   63         private ChromiumPerformanceLoggingPreferences perfLoggingPreferences;
   64         private ChromiumAndroidOptions androidOptions;
   65 
   66         /// <summary>
   67         /// Initializes a new instance of the <see cref="ChromiumOptions"/> class.
   68         /// </summary>
   69         public ChromiumOptions() : base()
   70         {
   71             this.AddKnownCapabilityName(this.CapabilityName, "current ChromiumOptions class instance");
   72             this.AddKnownCapabilityName(CapabilityType.LoggingPreferences, "SetLoggingPreference method");
   73             this.AddKnownCapabilityName(this.LoggingPreferencesChromeOption, "SetLoggingPreference method");
   74             this.AddKnownCapabilityName(ChromiumOptions.ArgumentsChromeOption, "AddArguments method");
   75             this.AddKnownCapabilityName(ChromiumOptions.BinaryChromeOption, "BinaryLocation property");
   76             this.AddKnownCapabilityName(ChromiumOptions.ExtensionsChromeOption, "AddExtensions method");
   77             this.AddKnownCapabilityName(ChromiumOptions.LocalStateChromeOption, "AddLocalStatePreference method");
   78             this.AddKnownCapabilityName(ChromiumOptions.PreferencesChromeOption, "AddUserProfilePreference method");
   79             this.AddKnownCapabilityName(ChromiumOptions.DetachChromeOption, "LeaveBrowserRunning property");
   80             this.AddKnownCapabilityName(ChromiumOptions.DebuggerAddressChromeOption, "DebuggerAddress property");
   81             this.AddKnownCapabilityName(ChromiumOptions.ExcludeSwitchesChromeOption, "AddExcludedArgument property");
   82             this.AddKnownCapabilityName(ChromiumOptions.MinidumpPathChromeOption, "MinidumpPath property");
   83             this.AddKnownCapabilityName(ChromiumOptions.MobileEmulationChromeOption, "EnableMobileEmulation method");
   84             this.AddKnownCapabilityName(ChromiumOptions.PerformanceLoggingPreferencesChromeOption, "PerformanceLoggingPreferences property");
   85             this.AddKnownCapabilityName(ChromiumOptions.WindowTypesChromeOption, "AddWindowTypes method");
   86             this.AddKnownCapabilityName(ChromiumOptions.UseSpecCompliantProtocolOption, "UseSpecCompliantProtocol property");
   87         }
   88 
   89         /// <summary>
   90         /// Gets the vendor prefix to apply to Chromium-specific capability names.
   91         /// </summary>
   92         protected abstract string VendorPrefix { get; }
   93 
   94         private string LoggingPreferencesChromeOption
   95         {
   96             get { return this.VendorPrefix + ":loggingPrefs"; }
   97         }
   98 
   99         /// <summary>
  100         /// Gets the name of the capability used to store Chromium options in
  101         /// an <see cref="ICapabilities"/> object.
  102         /// </summary>
  103         public abstract string CapabilityName { get; }
  104 
  105         /// <summary>
  106         /// Gets or sets the location of the Chromium browser's binary executable file.
  107         /// </summary>
  108         public string BinaryLocation
  109         {
  110             get { return this.binaryLocation; }
  111             set { this.binaryLocation = value; }
  112         }
  113 
  114         /// <summary>
  115         /// Gets or sets a value indicating whether Chromium should be left running after the
  116         /// ChromeDriver instance is exited. Defaults to <see langword="false"/>.
  117         /// </summary>
  118         public bool LeaveBrowserRunning
  119         {
  120             get { return this.leaveBrowserRunning; }
  121             set { this.leaveBrowserRunning = value; }
  122         }
  123 
  124         /// <summary>
  125         /// Gets the list of arguments appended to the Chromium command line as a string array.
  126         /// </summary>
  127         public ReadOnlyCollection<string> Arguments
  128         {
  129             get { return this.arguments.AsReadOnly(); }
  130         }
  131 
  132         /// <summary>
  133         /// Gets the list of extensions to be installed as an array of base64-encoded strings.
  134         /// </summary>
  135         public ReadOnlyCollection<string> Extensions
  136         {
  137             get
  138             {
  139                 List<string> allExtensions = new List<string>(this.encodedExtensions);
  140                 foreach (string extensionFile in this.extensionFiles)
  141                 {
  142                     byte[] extensionByteArray = File.ReadAllBytes(extensionFile);
  143                     string encodedExtension = Convert.ToBase64String(extensionByteArray);
  144                     allExtensions.Add(encodedExtension);
  145                 }
  146 
  147                 return allExtensions.AsReadOnly();
  148             }
  149         }
  150 
  151         /// <summary>
  152         /// Gets or sets the address of a Chromium debugger server to connect to.
  153         /// Should be of the form "{hostname|IP address}:port".
  154         /// </summary>
  155         public string DebuggerAddress
  156         {
  157             get { return this.debuggerAddress; }
  158             set { this.debuggerAddress = value; }
  159         }
  160 
  161         /// <summary>
  162         /// Gets or sets the directory in which to store minidump files.
  163         /// </summary>
  164         public string MinidumpPath
  165         {
  166             get { return this.minidumpPath; }
  167             set { this.minidumpPath = value; }
  168         }
  169 
  170         /// <summary>
  171         /// Gets or sets the performance logging preferences for the driver.
  172         /// </summary>
  173         public ChromiumPerformanceLoggingPreferences PerformanceLoggingPreferences
  174         {
  175             get { return this.perfLoggingPreferences; }
  176             set { this.perfLoggingPreferences = value; }
  177         }
  178 
  179         /// <summary>
  180         /// Gets or sets the options for automating Chromium applications on Android.
  181         /// </summary>
  182         public ChromiumAndroidOptions AndroidOptions
  183         {
  184             get { return this.androidOptions; }
  185             set { this.androidOptions = value; }
  186         }
  187 
  188         /// <summary>
  189         /// Gets or sets a value indicating whether the <see cref="ChromiumDriver"/> instance
  190         /// should use the legacy OSS protocol dialect or a dialect compliant with the W3C
  191         /// WebDriver Specification.
  192         /// </summary>
  193         [Obsolete("Spec Compliant Protocol is the only supported protocol")]
  194         public bool UseSpecCompliantProtocol
  195         {
  196             get { return this.useSpecCompliantProtocol; }
  197             set
  198             {
  199                 if (!value)
  200                 {
  201                     throw new ArgumentException("Only the spec compliant protocol is supported, " +
  202                                                 "Please update to W3C Syntax: " +
  203                                                 "https://www.selenium.dev/blog/2022/legacy-protocol-support/");
  204                 }
  205                 this.useSpecCompliantProtocol = true;
  206             }
  207         }
  208 
  209         /// <summary>
  210         /// Adds a single argument to the list of arguments to be appended to the browser executable command line.
  211         /// </summary>
  212         /// <param name="argument">The argument to add.</param>
  213         public void AddArgument(string argument)
  214         {
  215             if (string.IsNullOrEmpty(argument))
  216             {
  217                 throw new ArgumentException("argument must not be null or empty", nameof(argument));
  218             }
  219 
  220             this.AddArguments(argument);
  221         }
  222 
  223         /// <summary>
  224         /// Adds arguments to be appended to the browser executable command line.
  225         /// </summary>
  226         /// <param name="argumentsToAdd">An array of arguments to add.</param>
  227         public void AddArguments(params string[] argumentsToAdd)
  228         {
  229             this.AddArguments(new List<string>(argumentsToAdd));
  230         }
  231 
  232         /// <summary>
  233         /// Adds arguments to be appended to the browser executable command line.
  234         /// </summary>
  235         /// <param name="argumentsToAdd">An <see cref="IEnumerable{T}"/> object of arguments to add.</param>
  236         public void AddArguments(IEnumerable<string> argumentsToAdd)
  237         {
  238             if (argumentsToAdd == null)
  239             {
  240                 throw new ArgumentNullException(nameof(argumentsToAdd), "argumentsToAdd must not be null");
  241             }
  242 
  243             this.arguments.AddRange(argumentsToAdd);
  244         }
  245 
  246         /// <summary>
  247         /// Adds a single argument to be excluded from the list of arguments passed by default
  248         /// to the browser executable command line by chromedriver.exe.
  249         /// </summary>
  250         /// <param name="argument">The argument to exclude.</param>
  251         public void AddExcludedArgument(string argument)
  252         {
  253             if (string.IsNullOrEmpty(argument))
  254             {
  255                 throw new ArgumentException("argument must not be null or empty", nameof(argument));
  256             }
  257 
  258             this.AddExcludedArguments(argument);
  259         }
  260 
  261         /// <summary>
  262         /// Adds arguments to be excluded from the list of arguments passed by default
  263         /// to the browser executable command line by chromedriver.exe.
  264         /// </summary>
  265         /// <param name="argumentsToExclude">An array of arguments to exclude.</param>
  266         public void AddExcludedArguments(params string[] argumentsToExclude)
  267         {
  268             this.AddExcludedArguments(new List<string>(argumentsToExclude));
  269         }
  270 
  271         /// <summary>
  272         /// Adds arguments to be excluded from the list of arguments passed by default
  273         /// to the browser executable command line by chromedriver.exe.
  274         /// </summary>
  275         /// <param name="argumentsToExclude">An <see cref="IEnumerable{T}"/> object of arguments to exclude.</param>
  276         public void AddExcludedArguments(IEnumerable<string> argumentsToExclude)
  277         {
  278             if (argumentsToExclude == null)
  279             {
  280                 throw new ArgumentNullException(nameof(argumentsToExclude), "argumentsToExclude must not be null");
  281             }
  282 
  283             this.excludedSwitches.AddRange(argumentsToExclude);
  284         }
  285 
  286         /// <summary>
  287         /// Adds a path to a packed Chrome extension (.crx file) to the list of extensions
  288         /// to be installed in the instance of Chrome.
  289         /// </summary>
  290         /// <param name="pathToExtension">The full path to the extension to add.</param>
  291         public void AddExtension(string pathToExtension)
  292         {
  293             if (string.IsNullOrEmpty(pathToExtension))
  294             {
  295                 throw new ArgumentException("pathToExtension must not be null or empty", nameof(pathToExtension));
  296             }
  297 
  298             this.AddExtensions(pathToExtension);
  299         }
  300 
  301         /// <summary>
  302         /// Adds a list of paths to packed Chrome extensions (.crx files) to be installed
  303         /// in the instance of Chrome.
  304         /// </summary>
  305         /// <param name="extensions">An array of full paths to the extensions to add.</param>
  306         public void AddExtensions(params string[] extensions)
  307         {
  308             this.AddExtensions(new List<string>(extensions));
  309         }
  310 
  311         /// <summary>
  312         /// Adds a list of paths to packed Chrome extensions (.crx files) to be installed
  313         /// in the instance of Chrome.
  314         /// </summary>
  315         /// <param name="extensions">An <see cref="IEnumerable{T}"/> of full paths to the extensions to add.</param>
  316         public void AddExtensions(IEnumerable<string> extensions)
  317         {
  318             if (extensions == null)
  319             {
  320                 throw new ArgumentNullException(nameof(extensions), "extensions must not be null");
  321             }
  322 
  323             foreach (string extension in extensions)
  324             {
  325                 if (!File.Exists(extension))
  326                 {
  327                     throw new FileNotFoundException("No extension found at the specified path", extension);
  328                 }
  329 
  330                 this.extensionFiles.Add(extension);
  331             }
  332         }
  333 
  334         /// <summary>
  335         /// Adds a base64-encoded string representing a Chrome extension to the list of extensions
  336         /// to be installed in the instance of Chrome.
  337         /// </summary>
  338         /// <param name="extension">A base64-encoded string representing the extension to add.</param>
  339         public void AddEncodedExtension(string extension)
  340         {
  341             if (string.IsNullOrEmpty(extension))
  342             {
  343                 throw new ArgumentException("extension must not be null or empty", nameof(extension));
  344             }
  345 
  346             this.AddEncodedExtensions(extension);
  347         }
  348 
  349         /// <summary>
  350         /// Adds a list of base64-encoded strings representing Chrome extensions to the list of extensions
  351         /// to be installed in the instance of Chrome.
  352         /// </summary>
  353         /// <param name="extensions">An array of base64-encoded strings representing the extensions to add.</param>
  354         public void AddEncodedExtensions(params string[] extensions)
  355         {
  356             this.AddEncodedExtensions(new List<string>(extensions));
  357         }
  358 
  359         /// <summary>
  360         /// Adds a list of base64-encoded strings representing Chrome extensions to be installed
  361         /// in the instance of Chrome.
  362         /// </summary>
  363         /// <param name="extensions">An <see cref="IEnumerable{T}"/> of base64-encoded strings
  364         /// representing the extensions to add.</param>
  365         public void AddEncodedExtensions(IEnumerable<string> extensions)
  366         {
  367             if (extensions == null)
  368             {
  369                 throw new ArgumentNullException(nameof(extensions), "extensions must not be null");
  370             }
  371 
  372             foreach (string extension in extensions)
  373             {
  374                 // Run the extension through the base64 converter to test that the
  375                 // string is not malformed.
  376                 try
  377                 {
  378                     Convert.FromBase64String(extension);
  379                 }
  380                 catch (FormatException ex)
  381                 {
  382                     throw new WebDriverException("Could not properly decode the base64 string", ex);
  383                 }
  384 
  385                 this.encodedExtensions.Add(extension);
  386             }
  387         }
  388 
  389         /// <summary>
  390         /// Adds a preference for the user-specific profile or "user data directory."
  391         /// If the specified preference already exists, it will be overwritten.
  392         /// </summary>
  393         /// <param name="preferenceName">The name of the preference to set.</param>
  394         /// <param name="preferenceValue">The value of the preference to set.</param>
  395         public void AddUserProfilePreference(string preferenceName, object preferenceValue)
  396         {
  397             if (this.userProfilePreferences == null)
  398             {
  399                 this.userProfilePreferences = new Dictionary<string, object>();
  400             }
  401 
  402             this.userProfilePreferences[preferenceName] = preferenceValue;
  403         }
  404 
  405         /// <summary>
  406         /// Adds a preference for the local state file in the user's data directory for Chromium.
  407         /// If the specified preference already exists, it will be overwritten.
  408         /// </summary>
  409         /// <param name="preferenceName">The name of the preference to set.</param>
  410         /// <param name="preferenceValue">The value of the preference to set.</param>
  411         public void AddLocalStatePreference(string preferenceName, object preferenceValue)
  412         {
  413             if (this.localStatePreferences == null)
  414             {
  415                 this.localStatePreferences = new Dictionary<string, object>();
  416             }
  417 
  418             this.localStatePreferences[preferenceName] = preferenceValue;
  419         }
  420 
  421         /// <summary>
  422         /// Allows the Chromium browser to emulate a mobile device.
  423         /// </summary>
  424         /// <param name="deviceName">The name of the device to emulate. The device name must be a
  425         /// valid device name from the Chrome DevTools Emulation panel.</param>
  426         /// <remarks>Specifying an invalid device name will not throw an exeption, but
  427         /// will generate an error in Chrome when the driver starts. To unset mobile
  428         /// emulation, call this method with <see langword="null"/> as the argument.</remarks>
  429         public void EnableMobileEmulation(string deviceName)
  430         {
  431             this.mobileEmulationDeviceSettings = null;
  432             this.mobileEmulationDeviceName = deviceName;
  433         }
  434 
  435         /// <summary>
  436         /// Allows the Chromium browser to emulate a mobile device.
  437         /// </summary>
  438         /// <param name="deviceSettings">The <see cref="ChromiumMobileEmulationDeviceSettings"/>
  439         /// object containing the settings of the device to emulate.</param>
  440         /// <exception cref="ArgumentException">Thrown if the device settings option does
  441         /// not have a user agent string set.</exception>
  442         /// <remarks>Specifying an invalid device name will not throw an exeption, but
  443         /// will generate an error in Chrome when the driver starts. To unset mobile
  444         /// emulation, call this method with <see langword="null"/> as the argument.</remarks>
  445         public void EnableMobileEmulation(ChromiumMobileEmulationDeviceSettings deviceSettings)
  446         {
  447             this.mobileEmulationDeviceName = null;
  448             if (deviceSettings != null && string.IsNullOrEmpty(deviceSettings.UserAgent))
  449             {
  450                 throw new ArgumentException("Device settings must include a user agent string.", nameof(deviceSettings));
  451             }
  452 
  453             this.mobileEmulationDeviceSettings = deviceSettings;
  454         }
  455 
  456         /// <summary>
  457         /// Adds a type of window that will be listed in the list of window handles
  458         /// returned by the Chrome driver.
  459         /// </summary>
  460         /// <param name="windowType">The name of the window type to add.</param>
  461         /// <remarks>This method can be used to allow the driver to access {webview}
  462         /// elements by adding "webview" as a window type.</remarks>
  463         public void AddWindowType(string windowType)
  464         {
  465             if (string.IsNullOrEmpty(windowType))
  466             {
  467                 throw new ArgumentException("windowType must not be null or empty", nameof(windowType));
  468             }
  469 
  470             this.AddWindowTypes(windowType);
  471         }
  472 
  473         /// <summary>
  474         /// Adds a list of window types that will be listed in the list of window handles
  475         /// returned by the Chromium driver.
  476         /// </summary>
  477         /// <param name="windowTypesToAdd">An array of window types to add.</param>
  478         public void AddWindowTypes(params string[] windowTypesToAdd)
  479         {
  480             this.AddWindowTypes(new List<string>(windowTypesToAdd));
  481         }
  482 
  483         /// <summary>
  484         /// Adds a list of window types that will be listed in the list of window handles
  485         /// returned by the Chromium driver.
  486         /// </summary>
  487         /// <param name="windowTypesToAdd">An <see cref="IEnumerable{T}"/> of window types to add.</param>
  488         public void AddWindowTypes(IEnumerable<string> windowTypesToAdd)
  489         {
  490             if (windowTypesToAdd == null)
  491             {
  492                 throw new ArgumentNullException(nameof(windowTypesToAdd), "windowTypesToAdd must not be null");
  493             }
  494 
  495             this.windowTypes.AddRange(windowTypesToAdd);
  496         }
  497 
  498         /// <summary>
  499         /// Provides a means to add additional capabilities not yet added as type safe options
  500         /// for the Chromium driver.
  501         /// </summary>
  502         /// <param name="optionName">The name of the capability to add.</param>
  503         /// <param name="optionValue">The value of the capability to add.</param>
  504         /// <exception cref="ArgumentException">
  505         /// thrown when attempting to add a capability for which there is already a type safe option, or
  506         /// when <paramref name="optionName"/> is <see langword="null"/> or the empty string.
  507         /// </exception>
  508         /// <remarks>Calling <see cref="AddAdditionalChromiumOption(string, object)"/>
  509         /// where <paramref name="optionName"/> has already been added will overwrite the
  510         /// existing value with the new value in <paramref name="optionValue"/>.
  511         /// Calling this method adds capabilities to the Chromium-specific options object passed to
  512         /// webdriver executable (e.g. property name 'goog:chromeOptions').</remarks>
  513         protected void AddAdditionalChromiumOption(string optionName, object optionValue)
  514         {
  515             this.ValidateCapabilityName(optionName);
  516             this.additionalChromeOptions[optionName] = optionValue;
  517         }
  518 
  519         /// <summary>
  520         /// Returns DesiredCapabilities for Chromium with these options included as
  521         /// capabilities. This does not copy the options. Further changes will be
  522         /// reflected in the returned capabilities.
  523         /// </summary>
  524         /// <returns>The DesiredCapabilities for Chrome with these options.</returns>
  525         public override ICapabilities ToCapabilities()
  526         {
  527             Dictionary<string, object> chromeOptions = this.BuildChromeOptionsDictionary();
  528 
  529             IWritableCapabilities capabilities = this.GenerateDesiredCapabilities(false);
  530             capabilities.SetCapability(this.CapabilityName, chromeOptions);
  531 
  532             AddVendorSpecificChromiumCapabilities(capabilities);
  533 
  534             Dictionary<string, object> loggingPreferences = this.GenerateLoggingPreferencesDictionary();
  535             if (loggingPreferences != null)
  536             {
  537                 capabilities.SetCapability(LoggingPreferencesChromeOption, loggingPreferences);
  538             }
  539 
  540             return capabilities.AsReadOnly();
  541         }
  542 
  543         /// <summary>
  544         /// Adds vendor-specific capabilities for Chromium-based browsers.
  545         /// </summary>
  546         /// <param name="capabilities">The capabilities to add.</param>
  547         protected virtual void AddVendorSpecificChromiumCapabilities(IWritableCapabilities capabilities)
  548         {
  549         }
  550 
  551         private Dictionary<string, object> BuildChromeOptionsDictionary()
  552         {
  553             Dictionary<string, object> chromeOptions = new Dictionary<string, object>();
  554             if (this.Arguments.Count > 0)
  555             {
  556                 chromeOptions[ArgumentsChromeOption] = this.Arguments;
  557             }
  558 
  559             if (!string.IsNullOrEmpty(this.binaryLocation))
  560             {
  561                 chromeOptions[BinaryChromeOption] = this.binaryLocation;
  562             }
  563 
  564             ReadOnlyCollection<string> extensions = this.Extensions;
  565             if (extensions.Count > 0)
  566             {
  567                 chromeOptions[ExtensionsChromeOption] = extensions;
  568             }
  569 
  570             if (this.localStatePreferences != null && this.localStatePreferences.Count > 0)
  571             {
  572                 chromeOptions[LocalStateChromeOption] = this.localStatePreferences;
  573             }
  574 
  575             if (this.userProfilePreferences != null && this.userProfilePreferences.Count > 0)
  576             {
  577                 chromeOptions[PreferencesChromeOption] = this.userProfilePreferences;
  578             }
  579 
  580             if (this.leaveBrowserRunning)
  581             {
  582                 chromeOptions[DetachChromeOption] = this.leaveBrowserRunning;
  583             }
  584 
  585             if (!this.useSpecCompliantProtocol)
  586             {
  587                 chromeOptions[UseSpecCompliantProtocolOption] = this.useSpecCompliantProtocol;
  588             }
  589 
  590             if (!string.IsNullOrEmpty(this.debuggerAddress))
  591             {
  592                 chromeOptions[DebuggerAddressChromeOption] = this.debuggerAddress;
  593             }
  594 
  595             if (this.excludedSwitches.Count > 0)
  596             {
  597                 chromeOptions[ExcludeSwitchesChromeOption] = this.excludedSwitches;
  598             }
  599 
  600             if (!string.IsNullOrEmpty(this.minidumpPath))
  601             {
  602                 chromeOptions[MinidumpPathChromeOption] = this.minidumpPath;
  603             }
  604 
  605             if (!string.IsNullOrEmpty(this.mobileEmulationDeviceName) || this.mobileEmulationDeviceSettings != null)
  606             {
  607                 chromeOptions[MobileEmulationChromeOption] = this.GenerateMobileEmulationSettingsDictionary();
  608             }
  609 
  610             if (this.perfLoggingPreferences != null)
  611             {
  612                 chromeOptions[PerformanceLoggingPreferencesChromeOption] = this.GeneratePerformanceLoggingPreferencesDictionary();
  613             }
  614 
  615             if (this.androidOptions != null)
  616             {
  617                 this.AddAndroidOptions(chromeOptions);
  618             }
  619 
  620             if (this.windowTypes.Count > 0)
  621             {
  622                 chromeOptions[WindowTypesChromeOption] = this.windowTypes;
  623             }
  624 
  625             foreach (KeyValuePair<string, object> pair in this.additionalChromeOptions)
  626             {
  627                 chromeOptions.Add(pair.Key, pair.Value);
  628             }
  629 
  630             return chromeOptions;
  631         }
  632 
  633         private void AddAndroidOptions(Dictionary<string, object> chromeOptions)
  634         {
  635             chromeOptions["androidPackage"] = this.androidOptions.AndroidPackage;
  636 
  637             if (!string.IsNullOrEmpty(this.androidOptions.AndroidDeviceSerial))
  638             {
  639                 chromeOptions["androidDeviceSerial"] = this.androidOptions.AndroidDeviceSerial;
  640             }
  641 
  642             if (!string.IsNullOrEmpty(this.androidOptions.AndroidActivity))
  643             {
  644                 chromeOptions["androidActivity"] = this.androidOptions.AndroidActivity;
  645             }
  646 
  647             if (!string.IsNullOrEmpty(this.androidOptions.AndroidProcess))
  648             {
  649                 chromeOptions["androidProcess"] = this.androidOptions.AndroidProcess;
  650             }
  651 
  652             if (this.androidOptions.UseRunningApp)
  653             {
  654                 chromeOptions["androidUseRunningApp"] = this.androidOptions.UseRunningApp;
  655             }
  656         }
  657 
  658         private Dictionary<string, object> GeneratePerformanceLoggingPreferencesDictionary()
  659         {
  660             Dictionary<string, object> perfLoggingPrefsDictionary = new Dictionary<string, object>();
  661             perfLoggingPrefsDictionary["enableNetwork"] = this.perfLoggingPreferences.IsCollectingNetworkEvents;
  662             perfLoggingPrefsDictionary["enablePage"] = this.perfLoggingPreferences.IsCollectingPageEvents;
  663 
  664             string tracingCategories = this.perfLoggingPreferences.TracingCategories;
  665             if (!string.IsNullOrEmpty(tracingCategories))
  666             {
  667                 perfLoggingPrefsDictionary["traceCategories"] = tracingCategories;
  668             }
  669 
  670             perfLoggingPrefsDictionary["bufferUsageReportingInterval"] = Convert.ToInt64(this.perfLoggingPreferences.BufferUsageReportingInterval.TotalMilliseconds);
  671 
  672             return perfLoggingPrefsDictionary;
  673         }
  674 
  675         private Dictionary<string, object> GenerateMobileEmulationSettingsDictionary()
  676         {
  677             Dictionary<string, object> mobileEmulationSettings = new Dictionary<string, object>();
  678 
  679             if (!string.IsNullOrEmpty(this.mobileEmulationDeviceName))
  680             {
  681                 mobileEmulationSettings["deviceName"] = this.mobileEmulationDeviceName;
  682             }
  683             else if (this.mobileEmulationDeviceSettings != null)
  684             {
  685                 mobileEmulationSettings["userAgent"] = this.mobileEmulationDeviceSettings.UserAgent;
  686                 Dictionary<string, object> deviceMetrics = new Dictionary<string, object>();
  687                 deviceMetrics["width"] = this.mobileEmulationDeviceSettings.Width;
  688                 deviceMetrics["height"] = this.mobileEmulationDeviceSettings.Height;
  689                 deviceMetrics["pixelRatio"] = this.mobileEmulationDeviceSettings.PixelRatio;
  690                 if (!this.mobileEmulationDeviceSettings.EnableTouchEvents)
  691                 {
  692                     deviceMetrics["touch"] = this.mobileEmulationDeviceSettings.EnableTouchEvents;
  693                 }
  694 
  695                 mobileEmulationSettings["deviceMetrics"] = deviceMetrics;
  696             }
  697 
  698             return mobileEmulationSettings;
  699         }
  700     }
  701 }