Skip to content

Commit 6db8a5f

Browse files
committed
Adding type-safe options .NET for recently added Chrome capabilities
Adding type-safe capabilities for `mobileEmulation`, `perfLoggingPrefs`, and `windowTypes` to ChromeOptions class.
1 parent b345522 commit 6db8a5f

File tree

4 files changed

+411
-1
lines changed

4 files changed

+411
-1
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// <copyright file="ChromeMobileEmulationDeviceSettings.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+
24+
namespace OpenQA.Selenium.Chrome
25+
{
26+
/// <summary>
27+
/// Represents the type-safe options for setting settings for emulating a
28+
/// mobile device in the Chrome browser.
29+
/// </summary>
30+
public class ChromeMobileEmulationDeviceSettings
31+
{
32+
private string userAgent = string.Empty;
33+
private long width;
34+
private long height;
35+
private double pixelRatio;
36+
private bool enableTouchEvents = true;
37+
38+
/// <summary>
39+
/// Initializes a new instance of the <see cref="ChromeMobileEmulationDeviceSettings"/> class.
40+
/// </summary>
41+
public ChromeMobileEmulationDeviceSettings()
42+
{
43+
}
44+
45+
/// <summary>
46+
/// Initializes a new instance of the <see cref="ChromeMobileEmulationDeviceSettings"/> class.
47+
/// </summary>
48+
/// <param name="userAgent">The user agent string to be used by the browser when emulating
49+
/// a mobile device.</param>
50+
public ChromeMobileEmulationDeviceSettings(string userAgent)
51+
{
52+
this.userAgent = userAgent;
53+
}
54+
55+
/// <summary>
56+
/// Gets or sets the user agent string to be used by the browser when emulating
57+
/// a mobile device.
58+
/// </summary>
59+
public string UserAgent
60+
{
61+
get { return this.userAgent; }
62+
set { this.userAgent = value; }
63+
}
64+
65+
/// <summary>
66+
/// Gets or sets the width in pixels to be used by the browser when emulating
67+
/// a mobile device.
68+
/// </summary>
69+
public long Width
70+
{
71+
get { return this.width; }
72+
set { this.width = value; }
73+
}
74+
75+
/// <summary>
76+
/// Gets or sets the height in pixels to be used by the browser when emulating
77+
/// a mobile device.
78+
/// </summary>
79+
public long Height
80+
{
81+
get { return this.height; }
82+
set { this.height = value; }
83+
}
84+
85+
/// <summary>
86+
/// Gets or sets the pixel ratio to be used by the browser when emulating
87+
/// a mobile device.
88+
/// </summary>
89+
public double PixelRatio
90+
{
91+
get { return this.pixelRatio; }
92+
set { this.pixelRatio = value; }
93+
}
94+
95+
/// <summary>
96+
/// Gets or sets a value indicating whether touch events should be enabled by
97+
/// the browser when emulating a mobile device. Defaults to <see langword="true"/>.
98+
/// </summary>
99+
public bool EnableTouchEvents
100+
{
101+
get { return this.enableTouchEvents; }
102+
set { this.enableTouchEvents = value; }
103+
}
104+
}
105+
}

dotnet/src/webdriver/Chrome/ChromeOptions.cs

Lines changed: 156 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ public class ChromeOptions
6969
private const string DebuggerAddressChromeOption = "debuggerAddress";
7070
private const string ExcludeSwitchesChromeOption = "excludeSwitches";
7171
private const string MinidumpPathChromeOption = "minidumpPath";
72+
private const string MobileEmulationChromeOption = "mobileEmulation";
73+
private const string PerformanceLoggingPreferencesChromeOption = "perfLoggingPrefs";
74+
private const string WindowTypesChromeOption = "windowTypes";
7275

7376
private bool leaveBrowserRunning;
7477
private string binaryLocation;
@@ -78,10 +81,16 @@ public class ChromeOptions
7881
private List<string> extensionFiles = new List<string>();
7982
private List<string> encodedExtensions = new List<string>();
8083
private List<string> excludedSwitches = new List<string>();
84+
private List<string> windowTypes = new List<string>();
8185
private Dictionary<string, object> additionalCapabilities = new Dictionary<string, object>();
8286
private Dictionary<string, object> additionalChromeOptions = new Dictionary<string, object>();
8387
private Dictionary<string, object> userProfilePreferences;
8488
private Dictionary<string, object> localStatePreferences;
89+
90+
private string mobileEmulationDeviceName;
91+
private ChromeMobileEmulationDeviceSettings mobileEmulationDeviceSettings;
92+
private ChromePerformanceLoggingPreferences perfLoggingPreferences;
93+
8594
private Proxy proxy;
8695

8796
/// <summary>
@@ -158,6 +167,15 @@ public string MinidumpPath
158167
set { this.minidumpPath = value; }
159168
}
160169

170+
/// <summary>
171+
/// Gets or sets the performance logging preferences for the driver.
172+
/// </summary>
173+
public ChromePerformanceLoggingPreferences PerformanceLoggingPreferences
174+
{
175+
get { return this.perfLoggingPreferences; }
176+
set { this.perfLoggingPreferences = value; }
177+
}
178+
161179
/// <summary>
162180
/// Adds a single argument to the list of arguments to be appended to the Chrome.exe command line.
163181
/// </summary>
@@ -370,6 +388,83 @@ public void AddLocalStatePreference(string preferenceName, object preferenceValu
370388
this.localStatePreferences[preferenceName] = preferenceValue;
371389
}
372390

391+
/// <summary>
392+
/// Allows the Chrome browser to emulate a mobile device.
393+
/// </summary>
394+
/// <param name="deviceName">The name of the device to emulate. The device name must be a
395+
/// valid device name from the Chrome DevTools Emulation panel.</param>
396+
/// <remarks>Specifying an invalid device name will not throw an exeption, but
397+
/// will generate an error in Chrome when the driver starts. To unset mobile
398+
/// emulation, call this method with <see langword="null"/> as the argument.</remarks>
399+
public void EnableMobileEmulation(string deviceName)
400+
{
401+
this.mobileEmulationDeviceSettings = null;
402+
this.mobileEmulationDeviceName = deviceName;
403+
}
404+
405+
/// <summary>
406+
/// Allows the Chrome browser to emulate a mobile device.
407+
/// </summary>
408+
/// <param name="deviceSettings">The <see cref="ChromeMobileEmulationDeviceSettings"/>
409+
/// object containing the settings of the device to emulate.</param>
410+
/// <exception cref="ArgumentException">Thrown if the device settings option does
411+
/// not have a user agent string set.</exception>
412+
/// <remarks>Specifying an invalid device name will not throw an exeption, but
413+
/// will generate an error in Chrome when the driver starts. To unset mobile
414+
/// emulation, call this method with <see langword="null"/> as the argument.</remarks>
415+
public void EnableMobileDeviceEmulation(ChromeMobileEmulationDeviceSettings deviceSettings)
416+
{
417+
this.mobileEmulationDeviceName = null;
418+
if (deviceSettings != null && string.IsNullOrEmpty(deviceSettings.UserAgent))
419+
{
420+
throw new ArgumentException("Device settings must include a user agent string.", "deviceSettings");
421+
}
422+
423+
this.mobileEmulationDeviceSettings = deviceSettings;
424+
}
425+
426+
/// <summary>
427+
/// Adds a type of window that will be listed in the list of window handles
428+
/// returned by the Chrome driver.
429+
/// </summary>
430+
/// <param name="windowType">The name of the window type to add.</param>
431+
/// <remarks>This method can be used to allow the driver to access {webview}
432+
/// elements by adding "webview" as a window type.</remarks>
433+
public void AddWindowType(string windowType)
434+
{
435+
if (string.IsNullOrEmpty(windowType))
436+
{
437+
throw new ArgumentException("windowType must not be null or empty", "windowType");
438+
}
439+
440+
this.AddWindowTypes(windowType);
441+
}
442+
443+
/// <summary>
444+
/// Adds a list of window types that will be listed in the list of window handles
445+
/// returned by the Chrome driver.
446+
/// </summary>
447+
/// <param name="windowTypesToAdd">An array of window types to add.</param>
448+
public void AddWindowTypes(params string[] windowTypesToAdd)
449+
{
450+
this.AddWindowTypes(new List<string>(windowTypesToAdd));
451+
}
452+
453+
/// <summary>
454+
/// Adds a list of window types that will be listed in the list of window handles
455+
/// returned by the Chrome driver.
456+
/// </summary>
457+
/// <param name="windowTypesToAdd">An <see cref="IEnumerable{T}"/> of window types to add.</param>
458+
public void AddWindowTypes(IEnumerable<string> windowTypesToAdd)
459+
{
460+
if (windowTypesToAdd == null)
461+
{
462+
throw new ArgumentNullException("windowTypesToAdd", "windowTypesToAdd must not be null");
463+
}
464+
465+
this.windowTypes.AddRange(windowTypesToAdd);
466+
}
467+
373468
/// <summary>
374469
/// Provides a means to add additional capabilities not yet added as type safe options
375470
/// for the Chrome driver.
@@ -421,7 +516,10 @@ public void AddAdditionalCapability(string capabilityName, object capabilityValu
421516
capabilityName == ChromeOptions.DebuggerAddressChromeOption ||
422517
capabilityName == ChromeOptions.ExtensionsChromeOption ||
423518
capabilityName == ChromeOptions.ExcludeSwitchesChromeOption ||
424-
capabilityName == ChromeOptions.MinidumpPathChromeOption)
519+
capabilityName == ChromeOptions.MinidumpPathChromeOption ||
520+
capabilityName == ChromeOptions.MobileEmulationChromeOption ||
521+
capabilityName == ChromeOptions.PerformanceLoggingPreferencesChromeOption ||
522+
capabilityName == ChromeOptions.WindowTypesChromeOption)
425523
{
426524
string message = string.Format(CultureInfo.InvariantCulture, "There is already an option for the {0} capability. Please use that instead.", capabilityName);
427525
throw new ArgumentException(message, "capabilityName");
@@ -517,12 +615,69 @@ private Dictionary<string, object> BuildChromeOptionsDictionary()
517615
chromeOptions[MinidumpPathChromeOption] = this.minidumpPath;
518616
}
519617

618+
if (!string.IsNullOrEmpty(this.mobileEmulationDeviceName) || this.mobileEmulationDeviceSettings != null)
619+
{
620+
chromeOptions[MobileEmulationChromeOption] = this.GenerateMobileEmulationSettingsDictionary();
621+
}
622+
623+
if (this.perfLoggingPreferences != null)
624+
{
625+
chromeOptions[PerformanceLoggingPreferencesChromeOption] = this.GeneratePerformanceLoggingPreferencesDictionary();
626+
}
627+
628+
if (this.windowTypes.Count > 0)
629+
{
630+
chromeOptions[WindowTypesChromeOption] = this.windowTypes;
631+
}
632+
520633
foreach (KeyValuePair<string, object> pair in this.additionalChromeOptions)
521634
{
522635
chromeOptions.Add(pair.Key, pair.Value);
523636
}
524637

525638
return chromeOptions;
526639
}
640+
641+
private Dictionary<string, object> GeneratePerformanceLoggingPreferencesDictionary()
642+
{
643+
Dictionary<string, object> perfLoggingPrefsDictionary = new Dictionary<string, object>();
644+
perfLoggingPrefsDictionary["enableNetwork"] = this.perfLoggingPreferences.IsCollectingNetworkEvents;
645+
perfLoggingPrefsDictionary["enablePage"] = this.perfLoggingPreferences.IsCollectingPageEvents;
646+
perfLoggingPrefsDictionary["enableTimeline"] = this.perfLoggingPreferences.IsCollectingTimelineEvents;
647+
648+
string tracingCategories = this.perfLoggingPreferences.TracingCategories;
649+
if (!string.IsNullOrEmpty(tracingCategories))
650+
{
651+
perfLoggingPrefsDictionary["tracingCategories"] = tracingCategories;
652+
}
653+
654+
perfLoggingPrefsDictionary["bufferUsageReportingInterval"] = Convert.ToInt64(this.perfLoggingPreferences.BufferUsageReportingInterval.TotalMilliseconds);
655+
656+
return perfLoggingPrefsDictionary;
657+
}
658+
659+
private Dictionary<string, object> GenerateMobileEmulationSettingsDictionary()
660+
{
661+
Dictionary<string, object> mobileEmulationSettings = new Dictionary<string, object>();
662+
663+
if (!string.IsNullOrEmpty(this.mobileEmulationDeviceName))
664+
{
665+
mobileEmulationSettings["deviceName"] = this.mobileEmulationDeviceName;
666+
}
667+
else if (this.mobileEmulationDeviceSettings != null)
668+
{
669+
mobileEmulationSettings["userAgent"] = this.mobileEmulationDeviceSettings.UserAgent;
670+
Dictionary<string, object> deviceMetrics = new Dictionary<string, object>();
671+
deviceMetrics["width"] = this.mobileEmulationDeviceSettings.Width;
672+
deviceMetrics["height"] = this.mobileEmulationDeviceSettings.Height;
673+
deviceMetrics["pixelRatio"] = this.mobileEmulationDeviceSettings.PixelRatio;
674+
if (!this.mobileEmulationDeviceSettings.EnableTouchEvents)
675+
{
676+
deviceMetrics["touch"] = this.mobileEmulationDeviceSettings.EnableTouchEvents;
677+
}
678+
}
679+
680+
return mobileEmulationSettings;
681+
}
527682
}
528683
}

0 commit comments

Comments
 (0)