diff options
author | George Roman <george.roman.99@gmail.com> | 2019-08-28 00:00:23 +0300 |
---|---|---|
committer | George Roman <george.roman.99@gmail.com> | 2019-08-31 10:14:40 +0300 |
commit | 32f7254883d573f0704fc885243f998e5f62c0b4 (patch) | |
tree | 200d6ebd35bbc3a93e06d9f3b2c5d57680af1bd6 /components/webdriver_server | |
parent | b2a7fc9046b8488525adea93d8869b264280bfc8 (diff) | |
download | servo-32f7254883d573f0704fc885243f998e5f62c0b4.tar.gz servo-32f7254883d573f0704fc885243f998e5f62c0b4.zip |
Implement ElementClick wd command
Diffstat (limited to 'components/webdriver_server')
-rw-r--r-- | components/webdriver_server/actions.rs | 185 | ||||
-rw-r--r-- | components/webdriver_server/lib.rs | 67 |
2 files changed, 150 insertions, 102 deletions
diff --git a/components/webdriver_server/actions.rs b/components/webdriver_server/actions.rs index 28255e44cd9..e04c40d54c8 100644 --- a/components/webdriver_server/actions.rs +++ b/components/webdriver_server/actions.rs @@ -3,14 +3,12 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::Handler; -use crossbeam_channel::Sender; use ipc_channel::ipc; use keyboard_types::webdriver::KeyInputState; use script_traits::webdriver_msg::WebDriverScriptCommand; use script_traits::{ConstellationMsg, MouseButton, MouseEventType, WebDriverCommandMsg}; use std::cmp; use std::collections::HashSet; -use std::sync::{Arc, Mutex}; use std::thread; use std::time::{Duration, Instant}; use webdriver::actions::{ActionSequence, ActionsType, GeneralAction, NullActionItem}; @@ -28,7 +26,7 @@ static POINTERMOVE_INTERVAL: u64 = 17; pub(crate) enum InputSourceState { Null, Key(KeyInputState), - Pointer(Arc<Mutex<PointerInputState>>), + Pointer(PointerInputState), } // https://w3c.github.io/webdriver/#dfn-pointer-input-source @@ -82,73 +80,6 @@ fn compute_tick_duration(tick_actions: &ActionSequence) -> u64 { duration } -// https://w3c.github.io/webdriver/#dfn-perform-a-pointer-move -fn perform_pointer_move( - constellation_chan: Sender<ConstellationMsg>, - pointer_input_state: Arc<Mutex<PointerInputState>>, - duration: u64, - start_x: i64, - start_y: i64, - target_x: i64, - target_y: i64, - tick_start: Instant, -) { - let mut pointer_input_state = pointer_input_state.lock().unwrap(); - - loop { - // Step 1 - let time_delta = tick_start.elapsed().as_millis(); - - // Step 2 - let duration_ratio = if duration > 0 { - time_delta as f64 / duration as f64 - } else { - 1.0 - }; - - // Step 3 - let last = if 1.0 - duration_ratio < 0.001 { - true - } else { - false - }; - - // Step 4 - let (x, y) = if last { - (target_x, target_y) - } else { - ( - (duration_ratio * (target_x - start_x) as f64) as i64 + start_x, - (duration_ratio * (target_y - start_y) as f64) as i64 + start_y, - ) - }; - - // Steps 5 - 6 - let current_x = pointer_input_state.x; - let current_y = pointer_input_state.y; - - // Step 7 - if x != current_x || y != current_y { - // Step 7.2 - let cmd_msg = WebDriverCommandMsg::MouseMoveAction(x as f32, y as f32); - constellation_chan - .send(ConstellationMsg::WebDriverCommand(cmd_msg)) - .unwrap(); - // Step 7.3 - pointer_input_state.x = x; - pointer_input_state.y = y; - } - - // Step 8 - if last { - return; - } - - // Step 9 - thread::sleep(Duration::from_millis(POINTERMOVE_INTERVAL)); - } -} - fn u64_to_mouse_button(button: u64) -> Option<MouseButton> { if MouseButton::Left as u64 == button { Some(MouseButton::Left) @@ -235,9 +166,9 @@ impl Handler { .unwrap() .input_state_table .entry(source_id.to_string()) - .or_insert(InputSourceState::Pointer(Arc::new(Mutex::new( - PointerInputState::new(¶meters.pointer_type), - )))); + .or_insert(InputSourceState::Pointer(PointerInputState::new( + ¶meters.pointer_type, + ))); match action { PointerAction::Cancel => (), PointerAction::Down(action) => { @@ -319,13 +250,17 @@ impl Handler { } // https://w3c.github.io/webdriver/#dfn-dispatch-a-pointerdown-action - fn dispatch_pointerdown_action(&mut self, source_id: &str, action: &PointerDownAction) { + pub(crate) fn dispatch_pointerdown_action( + &mut self, + source_id: &str, + action: &PointerDownAction, + ) { let session = self.session.as_mut().unwrap(); - let mut pointer_input_state = match session.input_state_table.get(source_id).unwrap() { + let pointer_input_state = match session.input_state_table.get_mut(source_id).unwrap() { InputSourceState::Null => unreachable!(), InputSourceState::Key(_) => unreachable!(), - InputSourceState::Pointer(pointer_input_state) => pointer_input_state.lock().unwrap(), + InputSourceState::Pointer(pointer_input_state) => pointer_input_state, }; if pointer_input_state.pressed.contains(&action.button) { @@ -365,13 +300,13 @@ impl Handler { } // https://w3c.github.io/webdriver/#dfn-dispatch-a-pointerup-action - fn dispatch_pointerup_action(&mut self, source_id: &str, action: &PointerUpAction) { + pub(crate) fn dispatch_pointerup_action(&mut self, source_id: &str, action: &PointerUpAction) { let session = self.session.as_mut().unwrap(); - let mut pointer_input_state = match session.input_state_table.get(source_id).unwrap() { + let pointer_input_state = match session.input_state_table.get_mut(source_id).unwrap() { InputSourceState::Null => unreachable!(), InputSourceState::Key(_) => unreachable!(), - InputSourceState::Pointer(pointer_input_state) => pointer_input_state.lock().unwrap(), + InputSourceState::Pointer(pointer_input_state) => pointer_input_state, }; if !pointer_input_state.pressed.contains(&action.button) { @@ -411,7 +346,7 @@ impl Handler { } // https://w3c.github.io/webdriver/#dfn-dispatch-a-pointermove-action - fn dispatch_pointermove_action( + pub(crate) fn dispatch_pointermove_action( &mut self, source_id: &str, action: &PointerMoveAction, @@ -435,7 +370,6 @@ impl Handler { InputSourceState::Null => unreachable!(), InputSourceState::Key(_) => unreachable!(), InputSourceState::Pointer(pointer_input_state) => { - let pointer_input_state = pointer_input_state.lock().unwrap(); (pointer_input_state.x, pointer_input_state.y) }, }; @@ -488,12 +422,30 @@ impl Handler { thread::sleep(Duration::from_millis(POINTERMOVE_INTERVAL)); } + // Step 11 + self.perform_pointer_move(source_id, duration, start_x, start_y, x, y, tick_start); + + // Step 12 + Ok(()) + } + + // https://w3c.github.io/webdriver/#dfn-perform-a-pointer-move + fn perform_pointer_move( + &mut self, + source_id: &str, + duration: u64, + start_x: i64, + start_y: i64, + target_x: i64, + target_y: i64, + tick_start: Instant, + ) { let pointer_input_state = match self .session - .as_ref() + .as_mut() .unwrap() .input_state_table - .get(source_id) + .get_mut(source_id) .unwrap() { InputSourceState::Null => unreachable!(), @@ -501,24 +453,57 @@ impl Handler { InputSourceState::Pointer(pointer_input_state) => pointer_input_state, }; - let constellation_chan = self.constellation_chan.clone(); - let pointer_input_state = pointer_input_state.clone(); + loop { + // Step 1 + let time_delta = tick_start.elapsed().as_millis(); + + // Step 2 + let duration_ratio = if duration > 0 { + time_delta as f64 / duration as f64 + } else { + 1.0 + }; + + // Step 3 + let last = if 1.0 - duration_ratio < 0.001 { + true + } else { + false + }; + + // Step 4 + let (x, y) = if last { + (target_x, target_y) + } else { + ( + (duration_ratio * (target_x - start_x) as f64) as i64 + start_x, + (duration_ratio * (target_y - start_y) as f64) as i64 + start_y, + ) + }; + + // Steps 5 - 6 + let current_x = pointer_input_state.x; + let current_y = pointer_input_state.y; + + // Step 7 + if x != current_x || y != current_y { + // Step 7.2 + let cmd_msg = WebDriverCommandMsg::MouseMoveAction(x as f32, y as f32); + self.constellation_chan + .send(ConstellationMsg::WebDriverCommand(cmd_msg)) + .unwrap(); + // Step 7.3 + pointer_input_state.x = x; + pointer_input_state.y = y; + } - // Step 11 - thread::spawn(move || { - perform_pointer_move( - constellation_chan, - pointer_input_state, - duration, - start_x, - start_y, - x, - y, - tick_start, - ); - }); + // Step 8 + if last { + return; + } - // Step 12 - Ok(()) + // Step 9 + thread::sleep(Duration::from_millis(POINTERMOVE_INTERVAL)); + } } } diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs index 431ac5eee9e..c6813488df7 100644 --- a/components/webdriver_server/lib.rs +++ b/components/webdriver_server/lib.rs @@ -18,7 +18,7 @@ extern crate serde_json; mod actions; mod capabilities; -use crate::actions::InputSourceState; +use crate::actions::{InputSourceState, PointerInputState}; use base64; use capabilities::ServoCapabilities; use crossbeam_channel::{after, unbounded, Receiver, Sender}; @@ -49,7 +49,10 @@ use std::thread; use std::time::Duration; use style_traits::CSSPixel; use uuid::Uuid; -use webdriver::actions::ActionSequence; +use webdriver::actions::{ + ActionSequence, PointerDownAction, PointerMoveAction, PointerOrigin, PointerType, + PointerUpAction, +}; use webdriver::capabilities::{Capabilities, CapabilitiesMatching}; use webdriver::command::{ActionsParameters, SwitchToWindowParameters}; use webdriver::command::{ @@ -1474,6 +1477,65 @@ impl Handler { Ok(WebDriverResponse::Void) } + // https://w3c.github.io/webdriver/#element-click + fn handle_element_click(&mut self, element: &WebElement) -> WebDriverResult<WebDriverResponse> { + let (sender, receiver) = ipc::channel().unwrap(); + + // Steps 1 - 7 + let command = WebDriverScriptCommand::ElementClick(element.to_string(), sender); + self.browsing_context_script_command(command)?; + + match receiver.recv().unwrap() { + Ok(element_id) => match element_id { + Some(element_id) => { + let id = Uuid::new_v4().to_string(); + + // Step 8.1 + self.session_mut()?.input_state_table.insert( + id.clone(), + InputSourceState::Pointer(PointerInputState::new(&PointerType::Mouse)), + ); + + // Steps 8.3 - 8.6 + let pointer_move_action = PointerMoveAction { + duration: None, + origin: PointerOrigin::Element(WebElement(element_id)), + x: Some(0), + y: Some(0), + }; + + // Steps 8.7 - 8.8 + let pointer_down_action = PointerDownAction { button: 1 }; + + // Steps 8.9 - 8.10 + let pointer_up_action = PointerUpAction { button: 1 }; + + // Step 8.11 + if let Err(error) = + self.dispatch_pointermove_action(&id, &pointer_move_action, 0) + { + return Err(WebDriverError::new(error, "")); + } + + // Steps 8.12 + self.dispatch_pointerdown_action(&id, &pointer_down_action); + + // Steps 8.13 + self.dispatch_pointerup_action(&id, &pointer_up_action); + + // Step 8.14 + self.session_mut()?.input_state_table.remove(&id); + + // Step 13 + Ok(WebDriverResponse::Void) + }, + // Step 13 + None => Ok(WebDriverResponse::Void), + }, + Err(error) => Err(WebDriverError::new(error, "")), + } + } + fn take_screenshot(&self, rect: Option<Rect<f32, CSSPixel>>) -> WebDriverResult<String> { let mut img = None; @@ -1694,6 +1756,7 @@ impl WebDriverHandler<ServoExtensionRoute> for Handler { WebDriverCommand::ElementSendKeys(ref element, ref keys) => { self.handle_element_send_keys(element, keys) }, + WebDriverCommand::ElementClick(ref element) => self.handle_element_click(element), WebDriverCommand::DismissAlert => self.handle_dismiss_alert(), WebDriverCommand::DeleteCookies => self.handle_delete_cookies(), WebDriverCommand::GetTimeouts => self.handle_get_timeouts(), |