Skip to content

Commit

Permalink
Adding type-safe options .NET for recently added Chrome capabilities
Browse files Browse the repository at this point in the history
Adding type-safe capabilities for `mobileEmulation`, `perfLoggingPrefs`,
and `windowTypes` to ChromeOptions class.
  • Loading branch information
jimevans committed Jan 27, 2016
1 parent b345522 commit 6db8a5f
Show file tree
Hide file tree
Showing 4 changed files with 411 additions and 1 deletion.
105 changes: 105 additions & 0 deletions dotnet/src/webdriver/Chrome/ChromeMobileEmulationDeviceSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// <copyright file="ChromeMobileEmulationDeviceSettings.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;

namespace OpenQA.Selenium.Chrome
{
/// <summary>
/// Represents the type-safe options for setting settings for emulating a
/// mobile device in the Chrome browser.
/// </summary>
public class ChromeMobileEmulationDeviceSettings
{
private string userAgent = string.Empty;
private long width;
private long height;
private double pixelRatio;
private bool enableTouchEvents = true;

/// <summary>
/// Initializes a new instance of the <see cref="ChromeMobileEmulationDeviceSettings"/> class.
/// </summary>
public ChromeMobileEmulationDeviceSettings()
{
}

/// <summary>
/// Initializes a new instance of the <see cref="ChromeMobileEmulationDeviceSettings"/> class.
/// </summary>
/// <param name="userAgent">The user agent string to be used by the browser when emulating
/// a mobile device.</param>
public ChromeMobileEmulationDeviceSettings(string userAgent)
{
this.userAgent = userAgent;
}

/// <summary>
/// Gets or sets the user agent string to be used by the browser when emulating
/// a mobile device.
/// </summary>
public string UserAgent
{
get { return this.userAgent; }
set { this.userAgent = value; }
}

/// <summary>
/// Gets or sets the width in pixels to be used by the browser when emulating
/// a mobile device.
/// </summary>
public long Width
{
get { return this.width; }
set { this.width = value; }
}

/// <summary>
/// Gets or sets the height in pixels to be used by the browser when emulating
/// a mobile device.
/// </summary>
public long Height
{
get { return this.height; }
set { this.height = value; }
}

/// <summary>
/// Gets or sets the pixel ratio to be used by the browser when emulating
/// a mobile device.
/// </summary>
public double PixelRatio
{
get { return this.pixelRatio; }
set { this.pixelRatio = value; }
}

/// <summary>
/// Gets or sets a value indicating whether touch events should be enabled by
/// the browser when emulating a mobile device. Defaults to <see langword="true"/>.
/// </summary>
public bool EnableTouchEvents
{
get { return this.enableTouchEvents; }
set { this.enableTouchEvents = value; }
}
}
}
157 changes: 156 additions & 1 deletion dotnet/src/webdriver/Chrome/ChromeOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ public class ChromeOptions
private const string DebuggerAddressChromeOption = "debuggerAddress";
private const string ExcludeSwitchesChromeOption = "excludeSwitches";
private const string MinidumpPathChromeOption = "minidumpPath";
private const string MobileEmulationChromeOption = "mobileEmulation";
private const string PerformanceLoggingPreferencesChromeOption = "perfLoggingPrefs";
private const string WindowTypesChromeOption = "windowTypes";

private bool leaveBrowserRunning;
private string binaryLocation;
Expand All @@ -78,10 +81,16 @@ public class ChromeOptions
private List<string> extensionFiles = new List<string>();
private List<string> encodedExtensions = new List<string>();
private List<string> excludedSwitches = new List<string>();
private List<string> windowTypes = new List<string>();
private Dictionary<string, object> additionalCapabilities = new Dictionary<string, object>();
private Dictionary<string, object> additionalChromeOptions = new Dictionary<string, object>();
private Dictionary<string, object> userProfilePreferences;
private Dictionary<string, object> localStatePreferences;

private string mobileEmulationDeviceName;
private ChromeMobileEmulationDeviceSettings mobileEmulationDeviceSettings;
private ChromePerformanceLoggingPreferences perfLoggingPreferences;

private Proxy proxy;

/// <summary>
Expand Down Expand Up @@ -158,6 +167,15 @@ public string MinidumpPath
set { this.minidumpPath = value; }
}

/// <summary>
/// Gets or sets the performance logging preferences for the driver.
/// </summary>
public ChromePerformanceLoggingPreferences PerformanceLoggingPreferences
{
get { return this.perfLoggingPreferences; }
set { this.perfLoggingPreferences = value; }
}

/// <summary>
/// Adds a single argument to the list of arguments to be appended to the Chrome.exe command line.
/// </summary>
Expand Down Expand Up @@ -370,6 +388,83 @@ public void AddLocalStatePreference(string preferenceName, object preferenceValu
this.localStatePreferences[preferenceName] = preferenceValue;
}

/// <summary>
/// Allows the Chrome browser to emulate a mobile device.
/// </summary>
/// <param name="deviceName">The name of the device to emulate. The device name must be a
/// valid device name from the Chrome DevTools Emulation panel.</param>
/// <remarks>Specifying an invalid device name will not throw an exeption, but
/// will generate an error in Chrome when the driver starts. To unset mobile
/// emulation, call this method with <see langword="null"/> as the argument.</remarks>
public void EnableMobileEmulation(string deviceName)
{
this.mobileEmulationDeviceSettings = null;
this.mobileEmulationDeviceName = deviceName;
}

/// <summary>
/// Allows the Chrome browser to emulate a mobile device.
/// </summary>
/// <param name="deviceSettings">The <see cref="ChromeMobileEmulationDeviceSettings"/>
/// object containing the settings of the device to emulate.</param>
/// <exception cref="ArgumentException">Thrown if the device settings option does
/// not have a user agent string set.</exception>
/// <remarks>Specifying an invalid device name will not throw an exeption, but
/// will generate an error in Chrome when the driver starts. To unset mobile
/// emulation, call this method with <see langword="null"/> as the argument.</remarks>
public void EnableMobileDeviceEmulation(ChromeMobileEmulationDeviceSettings deviceSettings)
{
this.mobileEmulationDeviceName = null;
if (deviceSettings != null && string.IsNullOrEmpty(deviceSettings.UserAgent))
{
throw new ArgumentException("Device settings must include a user agent string.", "deviceSettings");
}

this.mobileEmulationDeviceSettings = deviceSettings;
}

/// <summary>
/// Adds a type of window that will be listed in the list of window handles
/// returned by the Chrome driver.
/// </summary>
/// <param name="windowType">The name of the window type to add.</param>
/// <remarks>This method can be used to allow the driver to access {webview}
/// elements by adding "webview" as a window type.</remarks>
public void AddWindowType(string windowType)
{
if (string.IsNullOrEmpty(windowType))
{
throw new ArgumentException("windowType must not be null or empty", "windowType");
}

this.AddWindowTypes(windowType);
}

/// <summary>
/// Adds a list of window types that will be listed in the list of window handles
/// returned by the Chrome driver.
/// </summary>
/// <param name="windowTypesToAdd">An array of window types to add.</param>
public void AddWindowTypes(params string[] windowTypesToAdd)
{
this.AddWindowTypes(new List<string>(windowTypesToAdd));
}

/// <summary>
/// Adds a list of window types that will be listed in the list of window handles
/// returned by the Chrome driver.
/// </summary>
/// <param name="windowTypesToAdd">An <see cref="IEnumerable{T}"/> of window types to add.</param>
public void AddWindowTypes(IEnumerable<string> windowTypesToAdd)
{
if (windowTypesToAdd == null)
{
throw new ArgumentNullException("windowTypesToAdd", "windowTypesToAdd must not be null");
}

this.windowTypes.AddRange(windowTypesToAdd);
}

/// <summary>
/// Provides a means to add additional capabilities not yet added as type safe options
/// for the Chrome driver.
Expand Down Expand Up @@ -421,7 +516,10 @@ public void AddAdditionalCapability(string capabilityName, object capabilityValu
capabilityName == ChromeOptions.DebuggerAddressChromeOption ||
capabilityName == ChromeOptions.ExtensionsChromeOption ||
capabilityName == ChromeOptions.ExcludeSwitchesChromeOption ||
capabilityName == ChromeOptions.MinidumpPathChromeOption)
capabilityName == ChromeOptions.MinidumpPathChromeOption ||
capabilityName == ChromeOptions.MobileEmulationChromeOption ||
capabilityName == ChromeOptions.PerformanceLoggingPreferencesChromeOption ||
capabilityName == ChromeOptions.WindowTypesChromeOption)
{
string message = string.Format(CultureInfo.InvariantCulture, "There is already an option for the {0} capability. Please use that instead.", capabilityName);
throw new ArgumentException(message, "capabilityName");
Expand Down Expand Up @@ -517,12 +615,69 @@ private Dictionary<string, object> BuildChromeOptionsDictionary()
chromeOptions[MinidumpPathChromeOption] = this.minidumpPath;
}

if (!string.IsNullOrEmpty(this.mobileEmulationDeviceName) || this.mobileEmulationDeviceSettings != null)
{
chromeOptions[MobileEmulationChromeOption] = this.GenerateMobileEmulationSettingsDictionary();
}

if (this.perfLoggingPreferences != null)
{
chromeOptions[PerformanceLoggingPreferencesChromeOption] = this.GeneratePerformanceLoggingPreferencesDictionary();
}

if (this.windowTypes.Count > 0)
{
chromeOptions[WindowTypesChromeOption] = this.windowTypes;
}

foreach (KeyValuePair<string, object> pair in this.additionalChromeOptions)
{
chromeOptions.Add(pair.Key, pair.Value);
}

return chromeOptions;
}

private Dictionary<string, object> GeneratePerformanceLoggingPreferencesDictionary()
{
Dictionary<string, object> perfLoggingPrefsDictionary = new Dictionary<string, object>();
perfLoggingPrefsDictionary["enableNetwork"] = this.perfLoggingPreferences.IsCollectingNetworkEvents;
perfLoggingPrefsDictionary["enablePage"] = this.perfLoggingPreferences.IsCollectingPageEvents;
perfLoggingPrefsDictionary["enableTimeline"] = this.perfLoggingPreferences.IsCollectingTimelineEvents;

string tracingCategories = this.perfLoggingPreferences.TracingCategories;
if (!string.IsNullOrEmpty(tracingCategories))
{
perfLoggingPrefsDictionary["tracingCategories"] = tracingCategories;
}

perfLoggingPrefsDictionary["bufferUsageReportingInterval"] = Convert.ToInt64(this.perfLoggingPreferences.BufferUsageReportingInterval.TotalMilliseconds);

return perfLoggingPrefsDictionary;
}

private Dictionary<string, object> GenerateMobileEmulationSettingsDictionary()
{
Dictionary<string, object> mobileEmulationSettings = new Dictionary<string, object>();

if (!string.IsNullOrEmpty(this.mobileEmulationDeviceName))
{
mobileEmulationSettings["deviceName"] = this.mobileEmulationDeviceName;
}
else if (this.mobileEmulationDeviceSettings != null)
{
mobileEmulationSettings["userAgent"] = this.mobileEmulationDeviceSettings.UserAgent;
Dictionary<string, object> deviceMetrics = new Dictionary<string, object>();
deviceMetrics["width"] = this.mobileEmulationDeviceSettings.Width;
deviceMetrics["height"] = this.mobileEmulationDeviceSettings.Height;
deviceMetrics["pixelRatio"] = this.mobileEmulationDeviceSettings.PixelRatio;
if (!this.mobileEmulationDeviceSettings.EnableTouchEvents)
{
deviceMetrics["touch"] = this.mobileEmulationDeviceSettings.EnableTouchEvents;
}
}

return mobileEmulationSettings;
}
}
}
Loading

0 comments on commit 6db8a5f

Please sign in to comment.