Skip to content

Commit

Permalink
Adding commands to get and set network conditions for Chrome in .NET
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jimevans committed Jan 28, 2018
1 parent 98be3b3 commit e2bc8ea
Show file tree
Hide file tree
Showing 2 changed files with 182 additions and 4 deletions.
65 changes: 61 additions & 4 deletions dotnet/src/webdriver/Chrome/ChromeDriver.cs
Expand Up @@ -18,6 +18,7 @@

using System;
using OpenQA.Selenium.Remote;
using System.Collections.Generic;

namespace OpenQA.Selenium.Chrome
{
Expand Down Expand Up @@ -61,10 +62,15 @@ public class ChromeDriver : RemoteWebDriver
/// </summary>
public static readonly bool AcceptUntrustedCertificates = true;

/// <summary>
/// Initializes a new instance of the <see cref="ChromeDriver"/> class.
/// </summary>
public ChromeDriver()
private const string GetNetworkConditionsCommand = "getNetworkConditions";
private const string SetNetworkConditionsCommand = "setNetworkConditions";
private const string DeleteNetworkConditionsCommand = "deleteNetworkConditions";
private const string SendChromeCommand = "sendChromeCommand";

/// <summary>
/// Initializes a new instance of the <see cref="ChromeDriver"/> class.
/// </summary>
public ChromeDriver()
: this(new ChromeOptions())
{
}
Expand Down Expand Up @@ -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");
}

/// <summary>
Expand All @@ -158,6 +169,46 @@ public override IFileDetector FileDetector
set { }
}

/// <summary>
/// Gets or sets the network condition emulation for Chrome.
/// </summary>
public ChromeNetworkConditions NetworkConditions
{
get
{
Response response = this.Execute(GetNetworkConditionsCommand, null);
return ChromeNetworkConditions.FromDictionary(response.Value as Dictionary<string, object>);
}

set
{
if (value == null)
{
throw new ArgumentNullException("value", "value must not be null");
}

this.Execute(SetNetworkConditionsCommand, value.ToDictionary());
}
}

/// <summary>
/// Executes a custom Chrome command.
/// </summary>
/// <param name="commandName">Name of the command to execute.</param>
/// <param name="commandParameters">Parameters of the command to execute.</param>
public void ExecuteChromeCommand(string commandName, Dictionary<string, object> commandParameters)
{
if (commandName == null)
{
throw new ArgumentNullException("commandName", "commandName must not be null");
}

Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters["cmd"] = commandName;
parameters["params"] = commandParameters;
this.Execute(SendChromeCommand, parameters);
}

private static ICapabilities ConvertOptionsToCapabilities(ChromeOptions options)
{
if (options == null)
Expand All @@ -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);
}
}
}
121 changes: 121 additions & 0 deletions dotnet/src/webdriver/Chrome/ChromeNetworkConditions.cs
@@ -0,0 +1,121 @@
// <copyright file="ChromeNetworkConditions.cs" company="WebDriver Committers">
// 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.
// </copyright>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace OpenQA.Selenium.Chrome
{
/// <summary>
/// Provides manipulation of getting and setting network conditions from Chrome.
/// </summary>
public class ChromeNetworkConditions
{
private bool offline;
private TimeSpan latency = TimeSpan.Zero;
private long downloadThroughput = -1;
private long uploadThroughput = -1;

/// <summary>
/// Gets or sets a value indicating whether the network is offline. Defaults to <see langword="false"/>.
/// </summary>
public bool IsOffline
{
get { return this.offline; }
set { this.offline = value; }
}

/// <summary>
/// Gets or sets the simulated latency of the connection. Typically given in milliseconds.
/// </summary>
public TimeSpan Latency
{
get { return this.latency; }
set { this.latency = value; }
}

/// <summary>
/// Gets or sets the throughput of the network connection in kb/second for downloading.
/// </summary>
public long DownloadThroughput
{
get { return this.downloadThroughput; }
set { this.downloadThroughput = value; }
}

/// <summary>
/// Gets or sets the throughput of the network connection in kb/second for uploading.
/// </summary>
public long UploadThroughput
{
get { return this.uploadThroughput; }
set { this.uploadThroughput = value; }
}

static internal ChromeNetworkConditions FromDictionary(Dictionary<string, object> 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<string, object> ToDictionary()
{
Dictionary<string, object> dictionary = new Dictionary<string, object>();
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;
}
}
}

0 comments on commit e2bc8ea

Please sign in to comment.