/// <summary> /// Executes JavaScript in the context of the currently selected frame or window. /// </summary> /// <param name="script">The JavaScript code to execute.</param> /// <param name="args">The arguments to the script.</param> /// <returns>The value returned by the script.</returns> /// <remarks> /// <para> /// The <see cref="ExecuteScript"/>method executes JavaScript in the context of /// the currently selected frame or window. This means that "document" will refer /// to the current document. If the script has a return value, then the following /// steps will be taken: /// </para> /// <para> /// <list type="bullet"> /// <item><description>For an HTML element, this method returns a <see cref="IWebElement"/></description></item> /// <item><description>For a number, a <see cref="System.Int64"/> is returned</description></item> /// <item><description>For a boolean, a <see cref="System.Boolean"/> is returned</description></item> /// <item><description>For all other cases a <see cref="System.String"/> is returned.</description></item> /// <item><description>For an array,we check the first element, and attempt to return a /// <see cref="List{T}"/> of that type, following the rules above. Nested lists are not /// supported.</description></item> /// <item><description>If the value is null or there is no return value, /// <see langword="null"/> is returned.</description></item> /// </list> /// </para> /// <para> /// Arguments must be a number (which will be converted to a <see cref="System.Int64"/>), /// a <see cref="System.Boolean"/>, a <see cref="System.String"/> or a <see cref="IWebElement"/>. /// An exception will be thrown if the arguments do not meet these criteria. /// The arguments will be made available to the JavaScript via the "arguments" magic /// variable, as if the function were called via "Function.apply" /// </para> /// </remarks> public object ExecuteScript(string script, params object[] args) { object toReturn = null; SafeScriptArgsHandle scriptArgsHandle = new SafeScriptArgsHandle(); WebDriverResult result = NativeDriverLibrary.Instance.NewScriptArgs(ref scriptArgsHandle, args.Length); ResultHandler.VerifyResultCode(result, "Unable to create new script arguments array"); try { PopulateArguments(scriptArgsHandle, args); script = "(function() { return function(){" + script + "};})();"; SafeScriptResultHandle scriptResultHandle = new SafeScriptResultHandle(); result = NativeDriverLibrary.Instance.ExecuteScript(handle, script, scriptArgsHandle, ref scriptResultHandle); ResultHandler.VerifyResultCode(result, "Cannot execute script"); // Note that ExtractReturnValue frees the memory for the script result. toReturn = ExtractReturnValue(scriptResultHandle); } finally { scriptArgsHandle.Dispose(); } return(toReturn); }
internal static extern WebDriverResult wdGetNumberScriptResult(SafeScriptResultHandle scriptResult, out long resultNumber);
internal static extern WebDriverResult wdGetElementScriptResult(SafeScriptResultHandle scriptResult, SafeInternetExplorerDriverHandle driver, out SafeInternetExplorerWebElementHandle value);
internal static extern WebDriverResult wdGetDoubleScriptResult(SafeScriptResultHandle scriptResult, out double resultDouble);
internal static extern WebDriverResult wdGetBooleanScriptResult(SafeScriptResultHandle scriptResult, out int resultNumber);
internal static extern WebDriverResult wdGetArrayLengthScriptResult(SafeInternetExplorerDriverHandle driver, SafeScriptResultHandle scriptResult, out int arrayLength);
private object ExtractReturnValue(SafeScriptResultHandle scriptResult) { WebDriverResult result; int type; result = NativeDriverLibrary.Instance.GetScriptResultType(handle, scriptResult, out type); ResultHandler.VerifyResultCode(result, "Cannot determine result type"); object toReturn = null; try { switch (type) { case 1: SafeStringWrapperHandle stringHandle = new SafeStringWrapperHandle(); result = NativeDriverLibrary.Instance.GetStringScriptResult(scriptResult, ref stringHandle); ResultHandler.VerifyResultCode(result, "Cannot extract string result"); using (StringWrapper wrapper = new StringWrapper(stringHandle)) { toReturn = wrapper.Value; } break; case 2: long longVal; result = NativeDriverLibrary.Instance.GetNumberScriptResult(scriptResult, out longVal); ResultHandler.VerifyResultCode(result, "Cannot extract number result"); toReturn = longVal; break; case 3: int boolVal; result = NativeDriverLibrary.Instance.GetBooleanScriptResult(scriptResult, out boolVal); ResultHandler.VerifyResultCode(result, "Cannot extract boolean result"); toReturn = boolVal == 1 ? true : false; break; case 4: SafeInternetExplorerWebElementHandle element; result = NativeDriverLibrary.Instance.GetElementScriptResult(scriptResult, handle, out element); ResultHandler.VerifyResultCode(result, "Cannot extract element result"); toReturn = new InternetExplorerWebElement(this, element); break; case 5: toReturn = null; break; case 6: SafeStringWrapperHandle messageHandle = new SafeStringWrapperHandle(); result = NativeDriverLibrary.Instance.GetStringScriptResult(scriptResult, ref messageHandle); ResultHandler.VerifyResultCode(result, "Cannot extract string result"); string message = string.Empty; using (StringWrapper wrapper = new StringWrapper(messageHandle)) { message = wrapper.Value; } throw new WebDriverException(message); case 7: double doubleVal; result = NativeDriverLibrary.Instance.GetDoubleScriptResult(scriptResult, out doubleVal); ResultHandler.VerifyResultCode(result, "Cannot extract number result"); toReturn = doubleVal; break; case 8: bool allArrayItemsAreElements = true; int arrayLength = 0; result = NativeDriverLibrary.Instance.GetArrayLengthScriptResult(handle, scriptResult, out arrayLength); ResultHandler.VerifyResultCode(result, "Cannot extract array length."); List <object> list = new List <object>(); for (int i = 0; i < arrayLength; i++) { // Get reference to object SafeScriptResultHandle currItemHandle = new SafeScriptResultHandle(); WebDriverResult getItemResult = NativeDriverLibrary.Instance.GetArrayItemFromScriptResult(handle, scriptResult, i, out currItemHandle); if (getItemResult != WebDriverResult.Success) { // Note about memory management: Usually memory for this item // will be released during the recursive call to // ExtractReturnValue. It is freed explicitly here since a // recursive call will not happen. currItemHandle.Dispose(); throw new WebDriverException(string.Format(CultureInfo.InvariantCulture, "Cannot extract element from collection at index: {0} ({1})", i, result)); } object arrayItem = ExtractReturnValue(currItemHandle); if (allArrayItemsAreElements && !(arrayItem is IWebElement)) { allArrayItemsAreElements = false; } // Call ExtractReturnValue with the fetched item (recursive) list.Add(arrayItem); } if (allArrayItemsAreElements) { List <IWebElement> elementList = new List <IWebElement>(); foreach (object item in list) { elementList.Add((IWebElement)item); } toReturn = elementList.AsReadOnly(); } else { toReturn = list.AsReadOnly(); } break; default: throw new WebDriverException("Cannot determine result type"); } } finally { scriptResult.Dispose(); } return(toReturn); }
/// <summary> /// Executes JavaScript in the context of the currently selected frame or window. /// </summary> /// <param name="script">The JavaScript code to execute.</param> /// <param name="args">The arguments to the script.</param> /// <returns>The value returned by the script.</returns> /// <remarks> /// <para> /// The <see cref="ExecuteScript"/>method executes JavaScript in the context of /// the currently selected frame or window. This means that "document" will refer /// to the current document. If the script has a return value, then the following /// steps will be taken: /// </para> /// <para> /// <list type="bullet"> /// <item><description>For an HTML element, this method returns a <see cref="IWebElement"/></description></item> /// <item><description>For a number, a <see cref="System.Int64"/> is returned</description></item> /// <item><description>For a boolean, a <see cref="System.Boolean"/> is returned</description></item> /// <item><description>For all other cases a <see cref="System.String"/> is returned.</description></item> /// <item><description>For an array,we check the first element, and attempt to return a /// <see cref="List{T}"/> of that type, following the rules above. Nested lists are not /// supported.</description></item> /// <item><description>If the value is null or there is no return value, /// <see langword="null"/> is returned.</description></item> /// </list> /// </para> /// <para> /// Arguments must be a number (which will be converted to a <see cref="System.Int64"/>), /// a <see cref="System.Boolean"/>, a <see cref="System.String"/> or a <see cref="IWebElement"/>. /// An exception will be thrown if the arguments do not meet these criteria. /// The arguments will be made available to the JavaScript via the "arguments" magic /// variable, as if the function were called via "Function.apply" /// </para> /// </remarks> public object ExecuteScript(string script, params object[] args) { object toReturn = null; SafeScriptArgsHandle scriptArgsHandle = new SafeScriptArgsHandle(); WebDriverResult result = NativeDriverLibrary.Instance.NewScriptArgs(ref scriptArgsHandle, args.Length); ResultHandler.VerifyResultCode(result, "Unable to create new script arguments array"); try { PopulateArguments(scriptArgsHandle, args); script = "(function() { return function(){" + script + "};})();"; SafeScriptResultHandle scriptResultHandle = new SafeScriptResultHandle(); result = NativeDriverLibrary.Instance.ExecuteScript(handle, script, scriptArgsHandle, ref scriptResultHandle); ResultHandler.VerifyResultCode(result, "Cannot execute script"); // Note that ExtractReturnValue frees the memory for the script result. toReturn = ExtractReturnValue(scriptResultHandle); } finally { scriptArgsHandle.Dispose(); } return toReturn; }
/// <summary> /// Retrieves the value from the script result. /// </summary> /// <param name="scriptResultHandle">A handle to the result of the script.</param> /// <param name="driverHandle">A handle to the instance of the <see cref="InternetExplorerDriver"/> class.</param> /// <param name="scriptResultValue">A value representing the value of the returned object from the script.</param> /// <returns>A <see cref="WebDriverResult"/> value indicating success or failure.</returns> internal WebDriverResult GetElementScriptResult(SafeScriptResultHandle scriptResultHandle, SafeInternetExplorerDriverHandle driverHandle, out SafeInternetExplorerWebElementHandle scriptResultValue) { IntPtr functionPointer = NativeMethods.GetProcAddress(nativeLibraryHandle, GetElementScriptResultFunctionName); ElementReturningScriptResultFunction scriptResultFunction = Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(ElementReturningScriptResultFunction)) as ElementReturningScriptResultFunction; WebDriverResult result = scriptResultFunction(scriptResultHandle, driverHandle, out scriptResultValue); return result; }
/// <summary> /// Retrieves the value from the script result. /// </summary> /// <param name="scriptResultHandle">A handle to the result of the script.</param> /// <param name="scriptResultValue">A value representing the value of the returned object from the script.</param> /// <returns>A <see cref="WebDriverResult"/> value indicating success or failure.</returns> internal WebDriverResult GetDoubleScriptResult(SafeScriptResultHandle scriptResultHandle, out double scriptResultValue) { IntPtr functionPointer = NativeMethods.GetProcAddress(nativeLibraryHandle, GetDoubleScriptResultFunctionName); DoubleReturningScriptResultFunction scriptResultFunction = Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(DoubleReturningScriptResultFunction)) as DoubleReturningScriptResultFunction; WebDriverResult result = scriptResultFunction(scriptResultHandle, out scriptResultValue); return result; }
/// <summary> /// Gets the length of an array returned by the script. /// </summary> /// <param name="driverHandle">A handle to the instance of the <see cref="InternetExplorerDriver"/> class.</param> /// <param name="scriptResultHandle">A handle to the result of the script.</param> /// <param name="arrayLength">The number of elements in the returned array.</param> /// <returns>A <see cref="WebDriverResult"/> value indicating success or failure.</returns> internal WebDriverResult GetArrayLengthScriptResult(SafeInternetExplorerDriverHandle driverHandle, SafeScriptResultHandle scriptResultHandle, out int arrayLength) { IntPtr functionPointer = NativeMethods.GetProcAddress(nativeLibraryHandle, GetArrayLengthScriptResultFunctionName); ArrayLengthReturningScriptResultFunction getArrayLengthFunction = Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(ArrayLengthReturningScriptResultFunction)) as ArrayLengthReturningScriptResultFunction; WebDriverResult result = getArrayLengthFunction(driverHandle, scriptResultHandle, out arrayLength); return result; }
/// <summary> /// Executes arbitrary JavaScript on the page. /// </summary> /// <param name="driverHandle">A handle to the instance of the <see cref="InternetExplorerDriver"/> class.</param> /// <param name="script">The script to run.</param> /// <param name="scriptArgsHandle">A handle to the instance of the script arguments.</param> /// <param name="scriptResultHandle">A handle to the result of the script.</param> /// <returns>A <see cref="WebDriverResult"/> value indicating success or failure.</returns> internal WebDriverResult ExecuteScript(SafeInternetExplorerDriverHandle driverHandle, string script, SafeScriptArgsHandle scriptArgsHandle, ref SafeScriptResultHandle scriptResultHandle) { IntPtr functionPointer = NativeMethods.GetProcAddress(nativeLibraryHandle, ExecuteScriptFunctionName); ExecuteScriptFunction executeFunction = Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(ExecuteScriptFunction)) as ExecuteScriptFunction; WebDriverResult result = executeFunction(driverHandle, script, scriptArgsHandle, ref scriptResultHandle); return result; }
/// <summary> /// Retrieves the value from the script result. /// </summary> /// <param name="scriptResultHandle">A handle to the result of the script.</param> /// <param name="scriptResultValueWrapperHandle">A value representing the value of the returned object from the script.</param> /// <returns>A <see cref="WebDriverResult"/> value indicating success or failure.</returns> internal WebDriverResult GetStringScriptResult(SafeScriptResultHandle scriptResultHandle, ref SafeStringWrapperHandle scriptResultValueWrapperHandle) { IntPtr functionPointer = NativeMethods.GetProcAddress(nativeLibraryHandle, GetStringScriptResultFunctionName); StringReturningScriptResultFunction scriptResultFunction = Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(StringReturningScriptResultFunction)) as StringReturningScriptResultFunction; WebDriverResult result = scriptResultFunction(scriptResultHandle, ref scriptResultValueWrapperHandle); return result; }
/// <summary> /// Gets the type of object returned from the script. /// </summary> /// <param name="driverHandle">A handle to the instance of the <see cref="InternetExplorerDriver"/> class.</param> /// <param name="scriptResultHandle">A handle to the result of the script.</param> /// <param name="resultType">A value representing the return type.</param> /// <returns>A <see cref="WebDriverResult"/> value indicating success or failure.</returns> internal WebDriverResult GetScriptResultType(SafeInternetExplorerDriverHandle driverHandle, SafeScriptResultHandle scriptResultHandle, out int resultType) { IntPtr functionPointer = NativeMethods.GetProcAddress(nativeLibraryHandle, GetScriptResultTypeFunctionName); GetScriptResultTypeFunction scriptResultTypeFunction = Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(GetScriptResultTypeFunction)) as GetScriptResultTypeFunction; WebDriverResult result = scriptResultTypeFunction(driverHandle, scriptResultHandle, out resultType); return result; }
internal static extern WebDriverResult wdGetScriptResultType(SafeInternetExplorerDriverHandle driver, SafeScriptResultHandle scriptResult, out int type);
internal static extern WebDriverResult wdGetStringScriptResult(SafeScriptResultHandle scriptResult, ref SafeStringWrapperHandle resultString);
internal static extern WebDriverResult wdExecuteScript(SafeInternetExplorerDriverHandle driver, string script, SafeScriptArgsHandle scriptArgs, ref SafeScriptResultHandle scriptRes);
private object ExtractReturnValue(SafeScriptResultHandle scriptResult) { WebDriverResult result; int type; result = NativeDriverLibrary.Instance.GetScriptResultType(handle, scriptResult, out type); ResultHandler.VerifyResultCode(result, "Cannot determine result type"); object toReturn = null; try { switch (type) { case 1: SafeStringWrapperHandle stringHandle = new SafeStringWrapperHandle(); result = NativeDriverLibrary.Instance.GetStringScriptResult(scriptResult, ref stringHandle); ResultHandler.VerifyResultCode(result, "Cannot extract string result"); using (StringWrapper wrapper = new StringWrapper(stringHandle)) { toReturn = wrapper.Value; } break; case 2: long longVal; result = NativeDriverLibrary.Instance.GetNumberScriptResult(scriptResult, out longVal); ResultHandler.VerifyResultCode(result, "Cannot extract number result"); toReturn = longVal; break; case 3: int boolVal; result = NativeDriverLibrary.Instance.GetBooleanScriptResult(scriptResult, out boolVal); ResultHandler.VerifyResultCode(result, "Cannot extract boolean result"); toReturn = boolVal == 1 ? true : false; break; case 4: SafeInternetExplorerWebElementHandle element; result = NativeDriverLibrary.Instance.GetElementScriptResult(scriptResult, handle, out element); ResultHandler.VerifyResultCode(result, "Cannot extract element result"); toReturn = new InternetExplorerWebElement(this, element); break; case 5: toReturn = null; break; case 6: SafeStringWrapperHandle messageHandle = new SafeStringWrapperHandle(); result = NativeDriverLibrary.Instance.GetStringScriptResult(scriptResult, ref messageHandle); ResultHandler.VerifyResultCode(result, "Cannot extract string result"); string message = string.Empty; using (StringWrapper wrapper = new StringWrapper(messageHandle)) { message = wrapper.Value; } throw new WebDriverException(message); case 7: double doubleVal; result = NativeDriverLibrary.Instance.GetDoubleScriptResult(scriptResult, out doubleVal); ResultHandler.VerifyResultCode(result, "Cannot extract number result"); toReturn = doubleVal; break; case 8: bool allArrayItemsAreElements = true; int arrayLength = 0; result = NativeDriverLibrary.Instance.GetArrayLengthScriptResult(handle, scriptResult, out arrayLength); ResultHandler.VerifyResultCode(result, "Cannot extract array length."); List<object> list = new List<object>(); for (int i = 0; i < arrayLength; i++) { // Get reference to object SafeScriptResultHandle currItemHandle = new SafeScriptResultHandle(); WebDriverResult getItemResult = NativeDriverLibrary.Instance.GetArrayItemFromScriptResult(handle, scriptResult, i, out currItemHandle); if (getItemResult != WebDriverResult.Success) { // Note about memory management: Usually memory for this item // will be released during the recursive call to // ExtractReturnValue. It is freed explicitly here since a // recursive call will not happen. currItemHandle.Dispose(); throw new WebDriverException(string.Format(CultureInfo.InvariantCulture, "Cannot extract element from collection at index: {0} ({1})", i, result)); } object arrayItem = ExtractReturnValue(currItemHandle); if (allArrayItemsAreElements && !(arrayItem is IWebElement)) { allArrayItemsAreElements = false; } // Call ExtractReturnValue with the fetched item (recursive) list.Add(arrayItem); } if (allArrayItemsAreElements) { List<IWebElement> elementList = new List<IWebElement>(); foreach (object item in list) { elementList.Add((IWebElement)item); } toReturn = elementList.AsReadOnly(); } else { toReturn = list.AsReadOnly(); } break; default: throw new WebDriverException("Cannot determine result type"); } } finally { scriptResult.Dispose(); } return toReturn; }
internal static extern WebDriverResult wdGetArrayItemFromScriptResult(SafeInternetExplorerDriverHandle driver, SafeScriptResultHandle scriptResult, int itemIndex, out SafeScriptResultHandle item);