From e2bc8ea0e90c3fb4b18c1efa284251edee9f7ed9 Mon Sep 17 00:00:00 2001 From: Jim Evans Date: Sat, 27 Jan 2018 16:13:20 -0800 Subject: [PATCH] Adding commands to get and set network conditions for Chrome in .NET To get or set the network conditions, use the `NetworkConditions` property of the ChromeDriver object. This property gets or sets a ChromeNetworkConditions object which contains the proper values. Fixes issue #5338. --- dotnet/src/webdriver/Chrome/ChromeDriver.cs | 65 +++++++++- .../Chrome/ChromeNetworkConditions.cs | 121 ++++++++++++++++++ 2 files changed, 182 insertions(+), 4 deletions(-) create mode 100644 dotnet/src/webdriver/Chrome/ChromeNetworkConditions.cs diff --git a/dotnet/src/webdriver/Chrome/ChromeDriver.cs b/dotnet/src/webdriver/Chrome/ChromeDriver.cs index 3c0ebb7cd1d8a..660bacb252cc7 100644 --- a/dotnet/src/webdriver/Chrome/ChromeDriver.cs +++ b/dotnet/src/webdriver/Chrome/ChromeDriver.cs @@ -18,6 +18,7 @@ using System; using OpenQA.Selenium.Remote; +using System.Collections.Generic; namespace OpenQA.Selenium.Chrome { @@ -61,10 +62,15 @@ public class ChromeDriver : RemoteWebDriver /// public static readonly bool AcceptUntrustedCertificates = true; - /// - /// Initializes a new instance of the class. - /// - public ChromeDriver() + private const string GetNetworkConditionsCommand = "getNetworkConditions"; + private const string SetNetworkConditionsCommand = "setNetworkConditions"; + private const string DeleteNetworkConditionsCommand = "deleteNetworkConditions"; + private const string SendChromeCommand = "sendChromeCommand"; + + /// + /// Initializes a new instance of the class. + /// + public ChromeDriver() : this(new ChromeOptions()) { } @@ -140,6 +146,11 @@ public ChromeDriver(ChromeDriverService service, ChromeOptions options) public ChromeDriver(ChromeDriverService service, ChromeOptions options, TimeSpan commandTimeout) : base(new DriverServiceCommandExecutor(service, commandTimeout), ConvertOptionsToCapabilities(options)) { + // Add the custom commands unique to Chrome + AddCustomChromeCommand(GetNetworkConditionsCommand, CommandInfo.GetCommand, "/session/{sessionId}/chromium/network_connection"); + AddCustomChromeCommand(SetNetworkConditionsCommand, CommandInfo.PostCommand, "/session/{sessionId}/chromium/network_connection"); + AddCustomChromeCommand(DeleteNetworkConditionsCommand, CommandInfo.DeleteCommand, "/session/{sessionId}/chromium/network_connection"); + AddCustomChromeCommand(SendChromeCommand, CommandInfo.PostCommand, "/session/{sessionId}/chromium/send_command"); } /// @@ -158,6 +169,46 @@ public override IFileDetector FileDetector set { } } + /// + /// Gets or sets the network condition emulation for Chrome. + /// + public ChromeNetworkConditions NetworkConditions + { + get + { + Response response = this.Execute(GetNetworkConditionsCommand, null); + return ChromeNetworkConditions.FromDictionary(response.Value as Dictionary); + } + + set + { + if (value == null) + { + throw new ArgumentNullException("value", "value must not be null"); + } + + this.Execute(SetNetworkConditionsCommand, value.ToDictionary()); + } + } + + /// + /// Executes a custom Chrome command. + /// + /// Name of the command to execute. + /// Parameters of the command to execute. + public void ExecuteChromeCommand(string commandName, Dictionary commandParameters) + { + if (commandName == null) + { + throw new ArgumentNullException("commandName", "commandName must not be null"); + } + + Dictionary parameters = new Dictionary(); + parameters["cmd"] = commandName; + parameters["params"] = commandParameters; + this.Execute(SendChromeCommand, parameters); + } + private static ICapabilities ConvertOptionsToCapabilities(ChromeOptions options) { if (options == null) @@ -167,5 +218,11 @@ private static ICapabilities ConvertOptionsToCapabilities(ChromeOptions options) return options.ToCapabilities(); } + + private void AddCustomChromeCommand(string commandName, string method, string resourcePath) + { + CommandInfo commandInfoToAdd = new CommandInfo(method, resourcePath); + this.CommandExecutor.CommandInfoRepository.TryAddCommand(commandName, commandInfoToAdd); + } } } diff --git a/dotnet/src/webdriver/Chrome/ChromeNetworkConditions.cs b/dotnet/src/webdriver/Chrome/ChromeNetworkConditions.cs new file mode 100644 index 0000000000000..80809279cae97 --- /dev/null +++ b/dotnet/src/webdriver/Chrome/ChromeNetworkConditions.cs @@ -0,0 +1,121 @@ +// +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OpenQA.Selenium.Chrome +{ + /// + /// Provides manipulation of getting and setting network conditions from Chrome. + /// + public class ChromeNetworkConditions + { + private bool offline; + private TimeSpan latency = TimeSpan.Zero; + private long downloadThroughput = -1; + private long uploadThroughput = -1; + + /// + /// Gets or sets a value indicating whether the network is offline. Defaults to . + /// + public bool IsOffline + { + get { return this.offline; } + set { this.offline = value; } + } + + /// + /// Gets or sets the simulated latency of the connection. Typically given in milliseconds. + /// + public TimeSpan Latency + { + get { return this.latency; } + set { this.latency = value; } + } + + /// + /// Gets or sets the throughput of the network connection in kb/second for downloading. + /// + public long DownloadThroughput + { + get { return this.downloadThroughput; } + set { this.downloadThroughput = value; } + } + + /// + /// Gets or sets the throughput of the network connection in kb/second for uploading. + /// + public long UploadThroughput + { + get { return this.uploadThroughput; } + set { this.uploadThroughput = value; } + } + + static internal ChromeNetworkConditions FromDictionary(Dictionary dictionary) + { + ChromeNetworkConditions conditions = new ChromeNetworkConditions(); + if (dictionary.ContainsKey("offline")) + { + conditions.IsOffline = (bool)dictionary["offline"]; + } + + if (dictionary.ContainsKey("latency")) + { + conditions.Latency = TimeSpan.FromMilliseconds(Convert.ToDouble(dictionary["latency"])); + } + + if (dictionary.ContainsKey("upload_throughput")) + { + conditions.UploadThroughput = (long)dictionary["upload_throughput"]; + } + + if (dictionary.ContainsKey("download_throughput")) + { + conditions.DownloadThroughput = (long)dictionary["download_throughput"]; + } + + return conditions; + } + + internal Dictionary ToDictionary() + { + Dictionary dictionary = new Dictionary(); + dictionary["offline"] = this.offline; + if (this.latency != TimeSpan.Zero) + { + dictionary["latency"] = Convert.ToInt64(this.latency.TotalMilliseconds); + } + + if (this.downloadThroughput >= 0) + { + dictionary["download_throughput"] = this.downloadThroughput; + } + + if (this.uploadThroughput >= 0) + { + dictionary["upload_throughput"] = this.uploadThroughput; + } + + return dictionary; + } + } +}