Skip to content

Commit e2bc8ea

Browse files
committed
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.
1 parent 98be3b3 commit e2bc8ea

File tree

2 files changed

+182
-4
lines changed

2 files changed

+182
-4
lines changed

dotnet/src/webdriver/Chrome/ChromeDriver.cs

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
using System;
2020
using OpenQA.Selenium.Remote;
21+
using System.Collections.Generic;
2122

2223
namespace OpenQA.Selenium.Chrome
2324
{
@@ -61,10 +62,15 @@ public class ChromeDriver : RemoteWebDriver
6162
/// </summary>
6263
public static readonly bool AcceptUntrustedCertificates = true;
6364

64-
/// <summary>
65-
/// Initializes a new instance of the <see cref="ChromeDriver"/> class.
66-
/// </summary>
67-
public ChromeDriver()
65+
private const string GetNetworkConditionsCommand = "getNetworkConditions";
66+
private const string SetNetworkConditionsCommand = "setNetworkConditions";
67+
private const string DeleteNetworkConditionsCommand = "deleteNetworkConditions";
68+
private const string SendChromeCommand = "sendChromeCommand";
69+
70+
/// <summary>
71+
/// Initializes a new instance of the <see cref="ChromeDriver"/> class.
72+
/// </summary>
73+
public ChromeDriver()
6874
: this(new ChromeOptions())
6975
{
7076
}
@@ -140,6 +146,11 @@ public ChromeDriver(ChromeDriverService service, ChromeOptions options)
140146
public ChromeDriver(ChromeDriverService service, ChromeOptions options, TimeSpan commandTimeout)
141147
: base(new DriverServiceCommandExecutor(service, commandTimeout), ConvertOptionsToCapabilities(options))
142148
{
149+
// Add the custom commands unique to Chrome
150+
AddCustomChromeCommand(GetNetworkConditionsCommand, CommandInfo.GetCommand, "/session/{sessionId}/chromium/network_connection");
151+
AddCustomChromeCommand(SetNetworkConditionsCommand, CommandInfo.PostCommand, "/session/{sessionId}/chromium/network_connection");
152+
AddCustomChromeCommand(DeleteNetworkConditionsCommand, CommandInfo.DeleteCommand, "/session/{sessionId}/chromium/network_connection");
153+
AddCustomChromeCommand(SendChromeCommand, CommandInfo.PostCommand, "/session/{sessionId}/chromium/send_command");
143154
}
144155

145156
/// <summary>
@@ -158,6 +169,46 @@ public override IFileDetector FileDetector
158169
set { }
159170
}
160171

172+
/// <summary>
173+
/// Gets or sets the network condition emulation for Chrome.
174+
/// </summary>
175+
public ChromeNetworkConditions NetworkConditions
176+
{
177+
get
178+
{
179+
Response response = this.Execute(GetNetworkConditionsCommand, null);
180+
return ChromeNetworkConditions.FromDictionary(response.Value as Dictionary<string, object>);
181+
}
182+
183+
set
184+
{
185+
if (value == null)
186+
{
187+
throw new ArgumentNullException("value", "value must not be null");
188+
}
189+
190+
this.Execute(SetNetworkConditionsCommand, value.ToDictionary());
191+
}
192+
}
193+
194+
/// <summary>
195+
/// Executes a custom Chrome command.
196+
/// </summary>
197+
/// <param name="commandName">Name of the command to execute.</param>
198+
/// <param name="commandParameters">Parameters of the command to execute.</param>
199+
public void ExecuteChromeCommand(string commandName, Dictionary<string, object> commandParameters)
200+
{
201+
if (commandName == null)
202+
{
203+
throw new ArgumentNullException("commandName", "commandName must not be null");
204+
}
205+
206+
Dictionary<string, object> parameters = new Dictionary<string, object>();
207+
parameters["cmd"] = commandName;
208+
parameters["params"] = commandParameters;
209+
this.Execute(SendChromeCommand, parameters);
210+
}
211+
161212
private static ICapabilities ConvertOptionsToCapabilities(ChromeOptions options)
162213
{
163214
if (options == null)
@@ -167,5 +218,11 @@ private static ICapabilities ConvertOptionsToCapabilities(ChromeOptions options)
167218

168219
return options.ToCapabilities();
169220
}
221+
222+
private void AddCustomChromeCommand(string commandName, string method, string resourcePath)
223+
{
224+
CommandInfo commandInfoToAdd = new CommandInfo(method, resourcePath);
225+
this.CommandExecutor.CommandInfoRepository.TryAddCommand(commandName, commandInfoToAdd);
226+
}
170227
}
171228
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// <copyright file="ChromeNetworkConditions.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.Linq;
22+
using System.Text;
23+
using System.Threading.Tasks;
24+
25+
namespace OpenQA.Selenium.Chrome
26+
{
27+
/// <summary>
28+
/// Provides manipulation of getting and setting network conditions from Chrome.
29+
/// </summary>
30+
public class ChromeNetworkConditions
31+
{
32+
private bool offline;
33+
private TimeSpan latency = TimeSpan.Zero;
34+
private long downloadThroughput = -1;
35+
private long uploadThroughput = -1;
36+
37+
/// <summary>
38+
/// Gets or sets a value indicating whether the network is offline. Defaults to <see langword="false"/>.
39+
/// </summary>
40+
public bool IsOffline
41+
{
42+
get { return this.offline; }
43+
set { this.offline = value; }
44+
}
45+
46+
/// <summary>
47+
/// Gets or sets the simulated latency of the connection. Typically given in milliseconds.
48+
/// </summary>
49+
public TimeSpan Latency
50+
{
51+
get { return this.latency; }
52+
set { this.latency = value; }
53+
}
54+
55+
/// <summary>
56+
/// Gets or sets the throughput of the network connection in kb/second for downloading.
57+
/// </summary>
58+
public long DownloadThroughput
59+
{
60+
get { return this.downloadThroughput; }
61+
set { this.downloadThroughput = value; }
62+
}
63+
64+
/// <summary>
65+
/// Gets or sets the throughput of the network connection in kb/second for uploading.
66+
/// </summary>
67+
public long UploadThroughput
68+
{
69+
get { return this.uploadThroughput; }
70+
set { this.uploadThroughput = value; }
71+
}
72+
73+
static internal ChromeNetworkConditions FromDictionary(Dictionary<string, object> dictionary)
74+
{
75+
ChromeNetworkConditions conditions = new ChromeNetworkConditions();
76+
if (dictionary.ContainsKey("offline"))
77+
{
78+
conditions.IsOffline = (bool)dictionary["offline"];
79+
}
80+
81+
if (dictionary.ContainsKey("latency"))
82+
{
83+
conditions.Latency = TimeSpan.FromMilliseconds(Convert.ToDouble(dictionary["latency"]));
84+
}
85+
86+
if (dictionary.ContainsKey("upload_throughput"))
87+
{
88+
conditions.UploadThroughput = (long)dictionary["upload_throughput"];
89+
}
90+
91+
if (dictionary.ContainsKey("download_throughput"))
92+
{
93+
conditions.DownloadThroughput = (long)dictionary["download_throughput"];
94+
}
95+
96+
return conditions;
97+
}
98+
99+
internal Dictionary<string, object> ToDictionary()
100+
{
101+
Dictionary<string, object> dictionary = new Dictionary<string, object>();
102+
dictionary["offline"] = this.offline;
103+
if (this.latency != TimeSpan.Zero)
104+
{
105+
dictionary["latency"] = Convert.ToInt64(this.latency.TotalMilliseconds);
106+
}
107+
108+
if (this.downloadThroughput >= 0)
109+
{
110+
dictionary["download_throughput"] = this.downloadThroughput;
111+
}
112+
113+
if (this.uploadThroughput >= 0)
114+
{
115+
dictionary["upload_throughput"] = this.uploadThroughput;
116+
}
117+
118+
return dictionary;
119+
}
120+
}
121+
}

0 commit comments

Comments
 (0)