"Fossies" - the Fresh Open Source Software Archive

Member "selenium-selenium-4.8.1/dotnet/src/webdriver/Remote/RemoteSessionSettings.cs" (17 Feb 2023, 14662 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 "RemoteSessionSettings.cs" see the Fossies "Dox" file reference documentation.

A hint: This file contains one or more very long lines, so maybe it is better readable using the pure text view mode that shows the contents as wrapped lines within the browser window.


    1 // <copyright file="RemoteSessionSettings.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;
   21 using System.Collections.Generic;
   22 using System.Globalization;
   23 using Newtonsoft.Json;
   24 using OpenQA.Selenium.Remote;
   25 
   26 namespace OpenQA.Selenium
   27 {
   28     /// <summary>
   29     /// Base class for managing options specific to a browser driver.
   30     /// </summary>
   31     public class RemoteSessionSettings : ICapabilities
   32     {
   33         private const string FirstMatchCapabilityName = "firstMatch";
   34         private const string AlwaysMatchCapabilityName = "alwaysMatch";
   35 
   36         private readonly List<string> reservedSettingNames = new List<string>() { FirstMatchCapabilityName, AlwaysMatchCapabilityName };
   37         private DriverOptions mustMatchDriverOptions;
   38         private List<DriverOptions> firstMatchOptions = new List<DriverOptions>();
   39         private Dictionary<string, object> remoteMetadataSettings = new Dictionary<string, object>();
   40 
   41         /// <summary>
   42         /// Creates a new instance of the <see cref="RemoteSessionSettings"/> class.
   43         /// </summary>
   44         public RemoteSessionSettings()
   45         {
   46         }
   47 
   48         /// <summary>
   49         /// Creates a new instance of the <see cref="RemoteSessionSettings"/> class,
   50         /// containing the specified <see cref="DriverOptions"/> to use in the remote
   51         /// session.
   52         /// </summary>
   53         /// <param name="mustMatchDriverOptions">
   54         /// A <see cref="DriverOptions"/> object that contains values that must be matched
   55         /// by the remote end to create the remote session.
   56         /// </param>
   57         /// <param name="firstMatchDriverOptions">
   58         /// A list of <see cref="DriverOptions"/> objects that contain values that may be matched
   59         /// by the remote end to create the remote session.
   60         /// </param>
   61         public RemoteSessionSettings(DriverOptions mustMatchDriverOptions, params DriverOptions[] firstMatchDriverOptions)
   62         {
   63             this.mustMatchDriverOptions = mustMatchDriverOptions;
   64             foreach (DriverOptions firstMatchOption in firstMatchDriverOptions)
   65             {
   66                 this.AddFirstMatchDriverOption(firstMatchOption);
   67             }
   68         }
   69 
   70         /// <summary>
   71         /// Gets a value indicating the options that must be matched by the remote end to create a session.
   72         /// </summary>
   73         internal DriverOptions MustMatchDriverOptions
   74         {
   75             get { return this.mustMatchDriverOptions; }
   76         }
   77 
   78         /// <summary>
   79         /// Gets a value indicating the number of options that may be matched by the remote end to create a session.
   80         /// </summary>
   81         internal int FirstMatchOptionsCount
   82         {
   83             get { return this.firstMatchOptions.Count; }
   84         }
   85 
   86         /// <summary>
   87         /// Gets the capability value with the specified name.
   88         /// </summary>
   89         /// <param name="capabilityName">The name of the capability to get.</param>
   90         /// <returns>The value of the capability.</returns>
   91         /// <exception cref="ArgumentException">
   92         /// The specified capability name is not in the set of capabilities.
   93         /// </exception>
   94         public object this[string capabilityName]
   95         {
   96             get
   97             {
   98                 if (capabilityName == AlwaysMatchCapabilityName)
   99                 {
  100                     return this.GetAlwaysMatchOptionsAsSerializableDictionary();
  101                 }
  102 
  103                 if (capabilityName == FirstMatchCapabilityName)
  104                 {
  105                     return this.GetFirstMatchOptionsAsSerializableList();
  106                 }
  107 
  108                 if (!this.remoteMetadataSettings.ContainsKey(capabilityName))
  109                 {
  110                     throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "The capability {0} is not present in this set of capabilities", capabilityName));
  111                 }
  112 
  113                 return this.remoteMetadataSettings[capabilityName];
  114             }
  115 
  116         }
  117 
  118         /// <summary>
  119         /// Add a metadata setting to this set of remote session settings.
  120         /// </summary>
  121         /// <param name="settingName">The name of the setting to set.</param>
  122         /// <param name="settingValue">The value of the setting.</param>
  123         /// <remarks>
  124         /// The value to be set must be serializable to JSON for transmission
  125         /// across the wire to the remote end. To be JSON-serializable, the value
  126         /// must be a string, a numeric value, a boolean value, an object that
  127         /// implmeents <see cref="IEnumerable"/> that contains JSON-serializable
  128         /// objects, or a <see cref="Dictionary{TKey, TValue}"/> where the keys
  129         /// are strings and the values are JSON-serializable.
  130         /// </remarks>
  131         /// <exception cref="ArgumentException">
  132         /// Thrown if the setting name is null, the empty string, or one of the
  133         /// reserved names of metadata settings; or if the setting value is not
  134         /// JSON serializable.
  135         /// </exception>
  136         public void AddMetadataSetting(string settingName, object settingValue)
  137         {
  138             if (string.IsNullOrEmpty(settingName))
  139             {
  140                 throw new ArgumentException("Metadata setting name cannot be null or empty", nameof(settingName));
  141             }
  142 
  143             if (this.reservedSettingNames.Contains(settingName))
  144             {
  145                 throw new ArgumentException(string.Format("'{0}' is a reserved name for a metadata setting, and cannot be used as a name.", settingName), nameof(settingName));
  146             }
  147 
  148             if (!this.IsJsonSerializable(settingValue))
  149             {
  150                 throw new ArgumentException("Metadata setting value must be JSON serializable.", nameof(settingValue));
  151             }
  152 
  153             this.remoteMetadataSettings[settingName] = settingValue;
  154         }
  155 
  156         /// <summary>
  157         /// Adds a <see cref="DriverOptions"/> object to the list of options containing values to be
  158         /// "first matched" by the remote end.
  159         /// </summary>
  160         /// <param name="options">The <see cref="DriverOptions"/> to add to the list of "first matched" options.</param>
  161         public void AddFirstMatchDriverOption(DriverOptions options)
  162         {
  163             if (mustMatchDriverOptions != null)
  164             {
  165                 DriverOptionsMergeResult mergeResult = mustMatchDriverOptions.GetMergeResult(options);
  166                 if (mergeResult.IsMergeConflict)
  167                 {
  168                     string msg = string.Format(CultureInfo.InvariantCulture, "You cannot request the same capability in both must-match and first-match capabilities. You are attempting to add a first-match driver options object that defines a capability, '{0}', that is already defined in the must-match driver options.", mergeResult.MergeConflictOptionName);
  169                     throw new ArgumentException(msg, nameof(options));
  170                 }
  171             }
  172 
  173             firstMatchOptions.Add(options);
  174         }
  175 
  176         /// <summary>
  177         /// Adds a <see cref="DriverOptions"/> object containing values that must be matched
  178         /// by the remote end to successfully create a session.
  179         /// </summary>
  180         /// <param name="options">The <see cref="DriverOptions"/> that must be matched by
  181         /// the remote end to successfully create a session.</param>
  182         public void SetMustMatchDriverOptions(DriverOptions options)
  183         {
  184             if (this.firstMatchOptions.Count > 0)
  185             {
  186                 int driverOptionIndex = 0;
  187                 foreach (DriverOptions firstMatchOption in this.firstMatchOptions)
  188                 {
  189                     DriverOptionsMergeResult mergeResult = firstMatchOption.GetMergeResult(options);
  190                     if (mergeResult.IsMergeConflict)
  191                     {
  192                         string msg = string.Format(CultureInfo.InvariantCulture, "You cannot request the same capability in both must-match and first-match capabilities. You are attempting to add a must-match driver options object that defines a capability, '{0}', that is already defined in the first-match driver options with index {1}.", mergeResult.MergeConflictOptionName, driverOptionIndex);
  193                         throw new ArgumentException(msg, nameof(options));
  194                     }
  195 
  196                     driverOptionIndex++;
  197                 }
  198             }
  199 
  200             this.mustMatchDriverOptions = options;
  201         }
  202 
  203         /// <summary>
  204         /// Gets a value indicating whether the browser has a given capability.
  205         /// </summary>
  206         /// <param name="capability">The capability to get.</param>
  207         /// <returns>Returns <see langword="true"/> if this set of capabilities has the capability;
  208         /// otherwise, <see langword="false"/>.</returns>
  209         public bool HasCapability(string capability)
  210         {
  211             if (capability == AlwaysMatchCapabilityName || capability == FirstMatchCapabilityName)
  212             {
  213                 return true;
  214             }
  215 
  216             return this.remoteMetadataSettings.ContainsKey(capability);
  217         }
  218 
  219         /// <summary>
  220         /// Gets a capability of the browser.
  221         /// </summary>
  222         /// <param name="capability">The capability to get.</param>
  223         /// <returns>An object associated with the capability, or <see langword="null"/>
  224         /// if the capability is not set in this set of capabilities.</returns>
  225         public object GetCapability(string capability)
  226         {
  227             if (capability == AlwaysMatchCapabilityName)
  228             {
  229                 return this.GetAlwaysMatchOptionsAsSerializableDictionary();
  230             }
  231 
  232             if (capability == FirstMatchCapabilityName)
  233             {
  234                 return this.GetFirstMatchOptionsAsSerializableList();
  235             }
  236 
  237             if (this.remoteMetadataSettings.ContainsKey(capability))
  238             {
  239                 return this.remoteMetadataSettings[capability];
  240             }
  241 
  242             return null;
  243         }
  244 
  245         /// <summary>
  246         /// Return a dictionary representation of this <see cref="RemoteSessionSettings"/>.
  247         /// </summary>
  248         /// <returns>A <see cref="Dictionary{TKey, TValue}"/> representation of this <see cref="RemoteSessionSettings"/>.</returns>
  249         public Dictionary<string, object> ToDictionary()
  250         {
  251             Dictionary<string, object> capabilitiesDictionary = new Dictionary<string, object>();
  252 
  253             foreach (KeyValuePair<string, object> remoteMetadataSetting in this.remoteMetadataSettings)
  254             {
  255                 capabilitiesDictionary[remoteMetadataSetting.Key] = remoteMetadataSetting.Value;
  256             }
  257 
  258             if (this.mustMatchDriverOptions != null)
  259             {
  260                 capabilitiesDictionary["alwaysMatch"] = GetAlwaysMatchOptionsAsSerializableDictionary();
  261             }
  262 
  263             if (this.firstMatchOptions.Count > 0)
  264             {
  265                 List<object> optionsMatches = GetFirstMatchOptionsAsSerializableList();
  266 
  267                 capabilitiesDictionary["firstMatch"] = optionsMatches;
  268             }
  269 
  270             return capabilitiesDictionary;
  271         }
  272 
  273         /// <summary>
  274         /// Return a string representation of the remote session settings to be sent.
  275         /// </summary>
  276         /// <returns>String representation of the remote session settings to be sent.</returns>
  277         public override string ToString()
  278         {
  279             return JsonConvert.SerializeObject(this.ToDictionary(), Formatting.Indented);
  280         }
  281 
  282         internal DriverOptions GetFirstMatchDriverOptions(int firstMatchIndex)
  283         {
  284             if (firstMatchIndex < 0 || firstMatchIndex >= this.firstMatchOptions.Count)
  285             {
  286                 throw new ArgumentException("Requested index must be greater than zero and less than the count of firstMatch options added.");
  287             }
  288 
  289             return this.firstMatchOptions[firstMatchIndex];
  290         }
  291 
  292         private IDictionary<string, object> GetAlwaysMatchOptionsAsSerializableDictionary()
  293         {
  294             return this.mustMatchDriverOptions.ToDictionary();
  295         }
  296 
  297         private List<object> GetFirstMatchOptionsAsSerializableList()
  298         {
  299             List<object> optionsMatches = new List<object>();
  300             foreach (DriverOptions options in this.firstMatchOptions)
  301             {
  302                 optionsMatches.Add(options.ToDictionary());
  303             }
  304 
  305             return optionsMatches;
  306         }
  307 
  308         private bool IsJsonSerializable(object arg)
  309         {
  310             IEnumerable argAsEnumerable = arg as IEnumerable;
  311             IDictionary argAsDictionary = arg as IDictionary;
  312 
  313             if (arg is string || arg is float || arg is double || arg is int || arg is long || arg is bool || arg == null)
  314             {
  315                 return true;
  316             }
  317             else if (argAsDictionary != null)
  318             {
  319                 foreach (object key in argAsDictionary.Keys)
  320                 {
  321                     if (!(key is string))
  322                     {
  323                         return false;
  324                     }
  325                 }
  326 
  327                 foreach (object value in argAsDictionary.Values)
  328                 {
  329                     if (!IsJsonSerializable(value))
  330                     {
  331                         return false;
  332                     }
  333                 }
  334             }
  335             else if (argAsEnumerable != null)
  336             {
  337                 foreach (object item in argAsEnumerable)
  338                 {
  339                     if (!IsJsonSerializable(item))
  340                     {
  341                         return false;
  342                     }
  343                 }
  344             }
  345             else
  346             {
  347                 return false;
  348             }
  349 
  350             return true;
  351         }
  352     }
  353 }