/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use embedder_traits::WebDriverScriptCommand; use ipc_channel::ipc; use serde_json::Value; use webdriver::command::JavascriptCommandParameters; use webdriver::error::{WebDriverError, WebDriverResult}; use crate::{Handler, VerifyBrowsingContextIsOpen, wait_for_ipc_response}; /// const ELEMENT_IDENTIFIER: &str = "element-6066-11e4-a52e-4f735466cecf"; /// const FRAME_IDENTIFIER: &str = "frame-075b-4da1-b6ba-e579c2d3230a"; /// const WINDOW_IDENTIFIER: &str = "window-fcc6-11e5-b4f8-330a88ab9d7f"; /// const SHADOW_ROOT_IDENTIFIER: &str = "shadow-6066-11e4-a52e-4f735466cecf"; impl Handler { /// pub(crate) fn extract_script_arguments( &self, parameters: JavascriptCommandParameters, ) -> WebDriverResult<(String, Vec)> { // Step 1. Let script be the result of getting a property named "script" from parameters // Step 2. (Skip) If script is not a String, return error with error code invalid argument. let script = parameters.script; // Step 3. Let args be the result of getting a property named "args" from parameters. // Step 4. (Skip) If args is not an Array return error with error code invalid argument. let args: Vec = parameters .args .as_deref() .unwrap_or(&[]) .iter() .map(|value| self.json_deserialize(value)) .collect::>>()?; Ok((script, args)) } /// pub(crate) fn deserialize_web_element(&self, element: &Value) -> WebDriverResult { // Step 2. Let reference be the result of getting the web element identifier property from object. let element_ref: String = match element { Value::String(s) => s.clone(), _ => element.to_string(), }; // Step 3. Let element be the result of trying to get a known element with session and reference. let (sender, receiver) = ipc::channel().unwrap(); self.browsing_context_script_command( WebDriverScriptCommand::GetKnownElement(element_ref.clone(), sender), VerifyBrowsingContextIsOpen::No, )?; match wait_for_ipc_response(receiver)? { // Step 4. Return success with data element. Ok(_) => Ok(format!("window.webdriverElement(\"{}\")", element_ref)), Err(err) => Err(WebDriverError::new(err, "No such element")), } } /// pub(crate) fn deserialize_shadow_root(&self, shadow_root: &Value) -> WebDriverResult { // Step 2. Let reference be the result of getting the shadow root identifier property from object. let shadow_root_ref = match shadow_root { Value::String(s) => s.clone(), _ => shadow_root.to_string(), }; // Step 3. Let element be the result of trying to get a known element with session and reference. let (sender, receiver) = ipc::channel().unwrap(); self.browsing_context_script_command( WebDriverScriptCommand::GetKnownShadowRoot(shadow_root_ref.clone(), sender), VerifyBrowsingContextIsOpen::No, )?; match wait_for_ipc_response(receiver)? { // Step 4. Return success with data element. Ok(_) => Ok(format!( "window.webdriverShadowRoot(\"{}\")", shadow_root_ref )), Err(err) => Err(WebDriverError::new(err, "No such shadowroot")), } } /// fn json_deserialize(&self, v: &Value) -> WebDriverResult { let res = match v { Value::Null => "null".to_string(), Value::String(s) => format!("\"{}\"", s), Value::Bool(b) => b.to_string(), Value::Number(n) => n.to_string(), Value::Array(list) => { let elems = list .iter() .map(|v| self.json_deserialize(v)) .collect::>>()?; format!("[{}]", elems.join(", ")) }, Value::Object(map) => { let key = map.keys().next().map(String::as_str); match (key, map.values().next()) { (Some(ELEMENT_IDENTIFIER), Some(id)) => { return self.deserialize_web_element(id); }, (Some(FRAME_IDENTIFIER), Some(id)) => { let frame_ref = match id { Value::String(s) => s.clone(), _ => id.to_string(), }; return Ok(format!("window.webdriverFrame(\"{}\")", frame_ref)); }, (Some(WINDOW_IDENTIFIER), Some(id)) => { let window_ref = match id { Value::String(s) => s.clone(), _ => id.to_string(), }; return Ok(format!("window.webdriverWindow(\"{}\")", window_ref)); }, (Some(SHADOW_ROOT_IDENTIFIER), Some(id)) => { return self.deserialize_shadow_root(id); }, _ => {}, } let elems = map .iter() .map(|(k, v)| { let arg = self.json_deserialize(v)?; Ok(format!("{}: {}", k, arg)) }) .collect::>>()?; format!("{{{}}}", elems.join(", ")) }, }; Ok(res) } }