From 6db8a5fd2bf8a1fc89d41467d1f21d073ffadfe0 Mon Sep 17 00:00:00 2001 From: Jim Evans Date: Wed, 27 Jan 2016 14:42:47 -0800 Subject: [PATCH] Adding type-safe options .NET for recently added Chrome capabilities Adding type-safe capabilities for `mobileEmulation`, `perfLoggingPrefs`, and `windowTypes` to ChromeOptions class. --- .../ChromeMobileEmulationDeviceSettings.cs | 105 ++++++++++++ dotnet/src/webdriver/Chrome/ChromeOptions.cs | 157 +++++++++++++++++- .../ChromePerformanceLoggingPreferences.cs | 148 +++++++++++++++++ dotnet/src/webdriver/WebDriver.csproj | 2 + 4 files changed, 411 insertions(+), 1 deletion(-) create mode 100644 dotnet/src/webdriver/Chrome/ChromeMobileEmulationDeviceSettings.cs create mode 100644 dotnet/src/webdriver/Chrome/ChromePerformanceLoggingPreferences.cs diff --git a/dotnet/src/webdriver/Chrome/ChromeMobileEmulationDeviceSettings.cs b/dotnet/src/webdriver/Chrome/ChromeMobileEmulationDeviceSettings.cs new file mode 100644 index 0000000000000..2e2a1ec9c34ef --- /dev/null +++ b/dotnet/src/webdriver/Chrome/ChromeMobileEmulationDeviceSettings.cs @@ -0,0 +1,105 @@ +// +// 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; + +namespace OpenQA.Selenium.Chrome +{ + /// + /// Represents the type-safe options for setting settings for emulating a + /// mobile device in the Chrome browser. + /// + public class ChromeMobileEmulationDeviceSettings + { + private string userAgent = string.Empty; + private long width; + private long height; + private double pixelRatio; + private bool enableTouchEvents = true; + + /// + /// Initializes a new instance of the class. + /// + public ChromeMobileEmulationDeviceSettings() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The user agent string to be used by the browser when emulating + /// a mobile device. + public ChromeMobileEmulationDeviceSettings(string userAgent) + { + this.userAgent = userAgent; + } + + /// + /// Gets or sets the user agent string to be used by the browser when emulating + /// a mobile device. + /// + public string UserAgent + { + get { return this.userAgent; } + set { this.userAgent = value; } + } + + /// + /// Gets or sets the width in pixels to be used by the browser when emulating + /// a mobile device. + /// + public long Width + { + get { return this.width; } + set { this.width = value; } + } + + /// + /// Gets or sets the height in pixels to be used by the browser when emulating + /// a mobile device. + /// + public long Height + { + get { return this.height; } + set { this.height = value; } + } + + /// + /// Gets or sets the pixel ratio to be used by the browser when emulating + /// a mobile device. + /// + public double PixelRatio + { + get { return this.pixelRatio; } + set { this.pixelRatio = value; } + } + + /// + /// Gets or sets a value indicating whether touch events should be enabled by + /// the browser when emulating a mobile device. Defaults to . + /// + public bool EnableTouchEvents + { + get { return this.enableTouchEvents; } + set { this.enableTouchEvents = value; } + } + } +} diff --git a/dotnet/src/webdriver/Chrome/ChromeOptions.cs b/dotnet/src/webdriver/Chrome/ChromeOptions.cs index 032e5a3d6711f..c69a4f882b772 100644 --- a/dotnet/src/webdriver/Chrome/ChromeOptions.cs +++ b/dotnet/src/webdriver/Chrome/ChromeOptions.cs @@ -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; @@ -78,10 +81,16 @@ public class ChromeOptions private List extensionFiles = new List(); private List encodedExtensions = new List(); private List excludedSwitches = new List(); + private List windowTypes = new List(); private Dictionary additionalCapabilities = new Dictionary(); private Dictionary additionalChromeOptions = new Dictionary(); private Dictionary userProfilePreferences; private Dictionary localStatePreferences; + + private string mobileEmulationDeviceName; + private ChromeMobileEmulationDeviceSettings mobileEmulationDeviceSettings; + private ChromePerformanceLoggingPreferences perfLoggingPreferences; + private Proxy proxy; /// @@ -158,6 +167,15 @@ public string MinidumpPath set { this.minidumpPath = value; } } + /// + /// Gets or sets the performance logging preferences for the driver. + /// + public ChromePerformanceLoggingPreferences PerformanceLoggingPreferences + { + get { return this.perfLoggingPreferences; } + set { this.perfLoggingPreferences = value; } + } + /// /// Adds a single argument to the list of arguments to be appended to the Chrome.exe command line. /// @@ -370,6 +388,83 @@ public void AddLocalStatePreference(string preferenceName, object preferenceValu this.localStatePreferences[preferenceName] = preferenceValue; } + /// + /// Allows the Chrome browser to emulate a mobile device. + /// + /// The name of the device to emulate. The device name must be a + /// valid device name from the Chrome DevTools Emulation panel. + /// 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 as the argument. + public void EnableMobileEmulation(string deviceName) + { + this.mobileEmulationDeviceSettings = null; + this.mobileEmulationDeviceName = deviceName; + } + + /// + /// Allows the Chrome browser to emulate a mobile device. + /// + /// The + /// object containing the settings of the device to emulate. + /// Thrown if the device settings option does + /// not have a user agent string set. + /// 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 as the argument. + 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; + } + + /// + /// Adds a type of window that will be listed in the list of window handles + /// returned by the Chrome driver. + /// + /// The name of the window type to add. + /// This method can be used to allow the driver to access {webview} + /// elements by adding "webview" as a window type. + public void AddWindowType(string windowType) + { + if (string.IsNullOrEmpty(windowType)) + { + throw new ArgumentException("windowType must not be null or empty", "windowType"); + } + + this.AddWindowTypes(windowType); + } + + /// + /// Adds a list of window types that will be listed in the list of window handles + /// returned by the Chrome driver. + /// + /// An array of window types to add. + public void AddWindowTypes(params string[] windowTypesToAdd) + { + this.AddWindowTypes(new List(windowTypesToAdd)); + } + + /// + /// Adds a list of window types that will be listed in the list of window handles + /// returned by the Chrome driver. + /// + /// An of window types to add. + public void AddWindowTypes(IEnumerable windowTypesToAdd) + { + if (windowTypesToAdd == null) + { + throw new ArgumentNullException("windowTypesToAdd", "windowTypesToAdd must not be null"); + } + + this.windowTypes.AddRange(windowTypesToAdd); + } + /// /// Provides a means to add additional capabilities not yet added as type safe options /// for the Chrome driver. @@ -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"); @@ -517,6 +615,21 @@ private Dictionary 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 pair in this.additionalChromeOptions) { chromeOptions.Add(pair.Key, pair.Value); @@ -524,5 +637,47 @@ private Dictionary BuildChromeOptionsDictionary() return chromeOptions; } + + private Dictionary GeneratePerformanceLoggingPreferencesDictionary() + { + Dictionary perfLoggingPrefsDictionary = new Dictionary(); + 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 GenerateMobileEmulationSettingsDictionary() + { + Dictionary mobileEmulationSettings = new Dictionary(); + + if (!string.IsNullOrEmpty(this.mobileEmulationDeviceName)) + { + mobileEmulationSettings["deviceName"] = this.mobileEmulationDeviceName; + } + else if (this.mobileEmulationDeviceSettings != null) + { + mobileEmulationSettings["userAgent"] = this.mobileEmulationDeviceSettings.UserAgent; + Dictionary deviceMetrics = new Dictionary(); + 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; + } } } diff --git a/dotnet/src/webdriver/Chrome/ChromePerformanceLoggingPreferences.cs b/dotnet/src/webdriver/Chrome/ChromePerformanceLoggingPreferences.cs new file mode 100644 index 0000000000000..afee75150e831 --- /dev/null +++ b/dotnet/src/webdriver/Chrome/ChromePerformanceLoggingPreferences.cs @@ -0,0 +1,148 @@ +// +// 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; + +namespace OpenQA.Selenium.Chrome +{ + /// + /// Represents the type-safe options for setting preferences for performance + /// logging in the Chrome browser. + /// + public class ChromePerformanceLoggingPreferences + { + private bool isCollectingNetworkEvents = true; + private bool isCollectingPageEvents = true; + private bool isCollectingTimelineEvents = true; + private TimeSpan bufferUsageReportingInterval = TimeSpan.FromMilliseconds(1000); + private List tracingCategories = new List(); + + /// + /// Gets or sets a value indicating whether Chrome will collect events from the Network domain. + /// Defaults to . + /// + public bool IsCollectingNetworkEvents + { + get { return this.isCollectingNetworkEvents; } + set { this.isCollectingNetworkEvents = value; } + } + + /// + /// Gets or sets a value indicating whether Chrome will collect events from the Page domain. + /// Defaults to . + /// + public bool IsCollectingPageEvents + { + get { return this.isCollectingPageEvents; } + set { this.isCollectingPageEvents = value; } + } + + /// + /// Gets or sets a value indicating whether Chrome will collect events from the Timeline domain. + /// Defaults to , but is set to when tracing + /// is enabled by adding one or more tracing categories. + /// + public bool IsCollectingTimelineEvents + { + get { return this.isCollectingTimelineEvents; } + set { this.isCollectingTimelineEvents = value; } + } + + /// + /// Gets or sets the interval between Chrome DevTools trace buffer usage events. + /// Defaults to 1000 milliseconds. + /// + /// Thrown when an attempt is made to set + /// the value to a time span of less tnan or equal to zero milliseconds. + public TimeSpan BufferUsageReportingInterval + { + get + { + return this.bufferUsageReportingInterval; + } + + set + { + if (value.TotalMilliseconds <= 0) + { + throw new ArgumentException("Interval must be greater than zero."); + } + + this.bufferUsageReportingInterval = value; + } + } + + /// + /// Gets a comma-separated list of the categories for which tracing is enabled. + /// + public string TracingCategories + { + get + { + if (this.tracingCategories.Count == 0) + { + return string.Empty; + } + + return string.Join(",", this.tracingCategories.ToArray()); + } + } + + /// + /// Adds a single category to the list of Chrome tracing categories for which events should be collected. + /// + /// The category to add. + public void AddTracingCategory(string category) + { + if (string.IsNullOrEmpty(category)) + { + throw new ArgumentException("category must not be null or empty", "category"); + } + + this.AddTracingCategories(category); + } + + /// + /// Adds categories to the list of Chrome tracing categories for which events should be collected. + /// + /// An array of categories to add. + public void AddTracingCategories(params string[] categoriesToAdd) + { + this.AddTracingCategories(new List(categoriesToAdd)); + } + + /// + /// Adds categories to the list of Chrome tracing categories for which events should be collected. + /// + /// An object of categories to add. + public void AddTracingCategories(IEnumerable categoriesToAdd) + { + if (categoriesToAdd == null) + { + throw new ArgumentNullException("categoriesToAdd", "categoriesToAdd must not be null"); + } + + // Adding a tracing category automatically turns timeline events off. + this.isCollectingTimelineEvents = false; + this.tracingCategories.AddRange(categoriesToAdd); + } + } +} diff --git a/dotnet/src/webdriver/WebDriver.csproj b/dotnet/src/webdriver/WebDriver.csproj index 11137907326f0..e6f971da2c509 100644 --- a/dotnet/src/webdriver/WebDriver.csproj +++ b/dotnet/src/webdriver/WebDriver.csproj @@ -81,6 +81,8 @@ + +