webdriver: Refactor webdriver session and improve window handles (#38745)

This PR contains 2 parts:

1. Refactor webdriver session.
2. Improve webdriver window handles:
- Webdriver always get window handles from script thread by default.
- If script thread is blocked by user prompt, embedder stores the window
handle before user prompt appears, then webdriver can get window handle
from embedder.

Testing: Clear timeout cause by user prompt blocking script thread:
https://github.com/longvatrong111/servo/actions/runs/17033900026

---------

Signed-off-by: batu_hoang <hoang.binh.trong@huawei.com>
Signed-off-by: batu_hoang <longvatrong111@gmail.com>
Co-authored-by: Euclid Ye <euclid.ye@huawei.com>
This commit is contained in:
batu_hoang 2025-08-22 06:46:13 +08:00 committed by GitHub
parent b18a65ed70
commit bce9f06cf8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 372 additions and 369 deletions

View file

@ -2436,9 +2436,6 @@ impl ScriptThread {
WebDriverScriptCommand::RemoveLoadStatusSender(_) => { WebDriverScriptCommand::RemoveLoadStatusSender(_) => {
webdriver_handlers::handle_remove_load_status_sender(&documents, pipeline_id) webdriver_handlers::handle_remove_load_status_sender(&documents, pipeline_id)
}, },
WebDriverScriptCommand::GetWindowHandle(reply) => {
webdriver_handlers::handle_get_window_handle(pipeline_id, reply)
},
_ => (), _ => (),
} }
} }

View file

@ -460,9 +460,7 @@ unsafe fn jsval_to_webdriver_inner(
} else { } else {
let pipeline = window.pipeline_id(); let pipeline = window.pipeline_id();
if window_proxy.browsing_context_id() == window_proxy.webview_id() { if window_proxy.browsing_context_id() == window_proxy.webview_id() {
Ok(JSValue::Window( Ok(JSValue::Window(window.webview_id().to_string()))
window.Document().upcast::<Node>().unique_id(pipeline),
))
} else { } else {
Ok(JSValue::Frame( Ok(JSValue::Frame(
window.Document().upcast::<Node>().unique_id(pipeline), window.Document().upcast::<Node>().unique_id(pipeline),
@ -2076,16 +2074,3 @@ pub(crate) fn handle_remove_load_status_sender(
window.set_webdriver_load_status_sender(None); window.set_webdriver_load_status_sender(None);
} }
} }
pub(crate) fn handle_get_window_handle(
pipeline_id: PipelineId,
reply: IpcSender<Result<String, ErrorStatus>>,
) {
if let Some(res) = ScriptThread::find_document(pipeline_id)
.map(|document| document.upcast::<Node>().unique_id(pipeline_id))
{
reply.send(Ok(res)).ok();
} else {
reply.send(Err(ErrorStatus::NoSuchWindow)).ok();
}
}

View file

@ -156,8 +156,8 @@ pub enum WebDriverCommandMsg {
FocusWebView(WebViewId, IpcSender<bool>), FocusWebView(WebViewId, IpcSender<bool>),
/// Get focused webview. For now, this is only used when start new session. /// Get focused webview. For now, this is only used when start new session.
GetFocusedWebView(IpcSender<Option<WebViewId>>), GetFocusedWebView(IpcSender<Option<WebViewId>>),
/// Get all webviews /// Get webviews state
GetAllWebViews(IpcSender<Result<Vec<WebViewId>, ErrorStatus>>), GetAllWebViews(IpcSender<Vec<WebViewId>>),
/// Check whether top-level browsing context is open. /// Check whether top-level browsing context is open.
IsWebViewOpen(WebViewId, IpcSender<bool>), IsWebViewOpen(WebViewId, IpcSender<bool>),
/// Check whether browsing context is open. /// Check whether browsing context is open.
@ -246,7 +246,6 @@ pub enum WebDriverScriptCommand {
WillSendKeys(String, String, bool, IpcSender<Result<bool, ErrorStatus>>), WillSendKeys(String, String, bool, IpcSender<Result<bool, ErrorStatus>>),
AddLoadStatusSender(WebViewId, IpcSender<WebDriverLoadStatus>), AddLoadStatusSender(WebViewId, IpcSender<WebDriverLoadStatus>),
RemoveLoadStatusSender(WebViewId), RemoveLoadStatusSender(WebViewId),
GetWindowHandle(IpcSender<Result<String, ErrorStatus>>),
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]

View file

@ -216,6 +216,8 @@ impl Handler {
tick_actions: &TickActions, tick_actions: &TickActions,
tick_duration: u64, tick_duration: u64,
) -> Result<(), ErrorStatus> { ) -> Result<(), ErrorStatus> {
let session = self.session().unwrap();
// Step 1. For each action object in tick actions: // Step 1. For each action object in tick actions:
// Step 1.1. Let input_id be the value of the id property of action object. // Step 1.1. Let input_id be the value of the id property of action object.
for (input_id, action) in tick_actions.iter() { for (input_id, action) in tick_actions.iter() {
@ -233,16 +235,12 @@ impl Handler {
// Step 9. If subtype is "keyDown", append a copy of action // Step 9. If subtype is "keyDown", append a copy of action
// object with the subtype property changed to "keyUp" to // object with the subtype property changed to "keyUp" to
// input state's input cancel list. // input state's input cancel list.
self.session() session.input_cancel_list_mut().push((
.unwrap() input_id.clone(),
.input_cancel_list ActionItem::Key(KeyActionItem::Key(KeyAction::Up(KeyUpAction {
.borrow_mut() value: keydown_action.value.clone(),
.push(( }))),
input_id.clone(), ));
ActionItem::Key(KeyActionItem::Key(KeyAction::Up(KeyUpAction {
value: keydown_action.value.clone(),
}))),
));
}, },
ActionItem::Key(KeyActionItem::Key(KeyAction::Up(keyup_action))) => { ActionItem::Key(KeyActionItem::Key(KeyAction::Up(keyup_action))) => {
self.dispatch_keyup_action(input_id, keyup_action); self.dispatch_keyup_action(input_id, keyup_action);
@ -257,19 +255,15 @@ impl Handler {
// Step 10. If subtype is "pointerDown", append a copy of action // Step 10. If subtype is "pointerDown", append a copy of action
// object with the subtype property changed to "pointerUp" to // object with the subtype property changed to "pointerUp" to
// input state's input cancel list. // input state's input cancel list.
self.session() session.input_cancel_list_mut().push((
.unwrap() input_id.clone(),
.input_cancel_list ActionItem::Pointer(PointerActionItem::Pointer(PointerAction::Up(
.borrow_mut() PointerUpAction {
.push(( button: pointer_down_action.button,
input_id.clone(), ..Default::default()
ActionItem::Pointer(PointerActionItem::Pointer(PointerAction::Up( },
PointerUpAction { ))),
button: pointer_down_action.button, ));
..Default::default()
},
))),
));
}, },
ActionItem::Pointer(PointerActionItem::Pointer(PointerAction::Move( ActionItem::Pointer(PointerActionItem::Pointer(PointerAction::Move(
pointer_move_action, pointer_move_action,
@ -298,8 +292,7 @@ impl Handler {
fn dispatch_general_action(&self, source_id: &str) { fn dispatch_general_action(&self, source_id: &str) {
self.session() self.session()
.unwrap() .unwrap()
.input_state_table .input_state_table_mut()
.borrow_mut()
.entry(source_id.to_string()) .entry(source_id.to_string())
.or_insert(InputSourceState::Null); .or_insert(InputSourceState::Null);
} }
@ -307,9 +300,9 @@ impl Handler {
/// <https://w3c.github.io/webdriver/#dfn-dispatch-a-keydown-action> /// <https://w3c.github.io/webdriver/#dfn-dispatch-a-keydown-action>
fn dispatch_keydown_action(&self, source_id: &str, action: &KeyDownAction) { fn dispatch_keydown_action(&self, source_id: &str, action: &KeyDownAction) {
let session = self.session().unwrap(); let session = self.session().unwrap();
let mut input_state_table = session.input_state_table_mut();
let raw_key = action.value.chars().next().unwrap(); let raw_key = action.value.chars().next().unwrap();
let mut input_state_table = session.input_state_table.borrow_mut();
let key_input_state = match input_state_table.get_mut(source_id).unwrap() { let key_input_state = match input_state_table.get_mut(source_id).unwrap() {
InputSourceState::Key(key_input_state) => key_input_state, InputSourceState::Key(key_input_state) => key_input_state,
_ => unreachable!(), _ => unreachable!(),
@ -321,7 +314,7 @@ impl Handler {
self.increment_num_pending_actions(); self.increment_num_pending_actions();
let msg_id = self.current_action_id.get(); let msg_id = self.current_action_id.get();
let cmd_msg = let cmd_msg =
WebDriverCommandMsg::KeyboardAction(session.webview_id, keyboard_event, msg_id); WebDriverCommandMsg::KeyboardAction(self.verified_webview_id(), keyboard_event, msg_id);
let _ = self.send_message_to_embedder(cmd_msg); let _ = self.send_message_to_embedder(cmd_msg);
} }
@ -333,7 +326,7 @@ impl Handler {
// See https://github.com/w3c/webdriver/issues/1905 && // See https://github.com/w3c/webdriver/issues/1905 &&
// https://github.com/servo/servo/issues/37579#issuecomment-2990762713 // https://github.com/servo/servo/issues/37579#issuecomment-2990762713
{ {
let mut input_cancel_list = session.input_cancel_list.borrow_mut(); let mut input_cancel_list = session.input_cancel_list_mut();
if let Some(pos) = input_cancel_list.iter().rposition(|(id, item)| { if let Some(pos) = input_cancel_list.iter().rposition(|(id, item)| {
id == source_id && id == source_id &&
matches!(item, matches!(item,
@ -346,7 +339,7 @@ impl Handler {
} }
let raw_key = action.value.chars().next().unwrap(); let raw_key = action.value.chars().next().unwrap();
let mut input_state_table = session.input_state_table.borrow_mut(); let mut input_state_table = session.input_state_table_mut();
let key_input_state = match input_state_table.get_mut(source_id).unwrap() { let key_input_state = match input_state_table.get_mut(source_id).unwrap() {
InputSourceState::Key(key_input_state) => key_input_state, InputSourceState::Key(key_input_state) => key_input_state,
_ => unreachable!(), _ => unreachable!(),
@ -356,8 +349,11 @@ impl Handler {
// Step 12 // Step 12
self.increment_num_pending_actions(); self.increment_num_pending_actions();
let msg_id = self.current_action_id.get(); let msg_id = self.current_action_id.get();
let cmd_msg = let cmd_msg = WebDriverCommandMsg::KeyboardAction(
WebDriverCommandMsg::KeyboardAction(session.webview_id, keyboard_event, msg_id); self.verified_webview_id(),
keyboard_event,
msg_id,
);
let _ = self.send_message_to_embedder(cmd_msg); let _ = self.send_message_to_embedder(cmd_msg);
} }
} }
@ -366,7 +362,7 @@ impl Handler {
pub(crate) fn dispatch_pointerdown_action(&self, source_id: &str, action: &PointerDownAction) { pub(crate) fn dispatch_pointerdown_action(&self, source_id: &str, action: &PointerDownAction) {
let session = self.session().unwrap(); let session = self.session().unwrap();
let mut input_state_table = session.input_state_table.borrow_mut(); let mut input_state_table = session.input_state_table_mut();
let pointer_input_state = match input_state_table.get_mut(source_id).unwrap() { let pointer_input_state = match input_state_table.get_mut(source_id).unwrap() {
InputSourceState::Pointer(pointer_input_state) => pointer_input_state, InputSourceState::Pointer(pointer_input_state) => pointer_input_state,
_ => unreachable!(), _ => unreachable!(),
@ -380,7 +376,7 @@ impl Handler {
self.increment_num_pending_actions(); self.increment_num_pending_actions();
let msg_id = self.current_action_id.get(); let msg_id = self.current_action_id.get();
let cmd_msg = WebDriverCommandMsg::MouseButtonAction( let cmd_msg = WebDriverCommandMsg::MouseButtonAction(
session.webview_id, self.verified_webview_id(),
MouseButtonAction::Down, MouseButtonAction::Down,
action.button.into(), action.button.into(),
pointer_input_state.x as f32, pointer_input_state.x as f32,
@ -394,7 +390,7 @@ impl Handler {
pub(crate) fn dispatch_pointerup_action(&self, source_id: &str, action: &PointerUpAction) { pub(crate) fn dispatch_pointerup_action(&self, source_id: &str, action: &PointerUpAction) {
let session = self.session().unwrap(); let session = self.session().unwrap();
let mut input_state_table = session.input_state_table.borrow_mut(); let mut input_state_table = session.input_state_table_mut();
let pointer_input_state = match input_state_table.get_mut(source_id).unwrap() { let pointer_input_state = match input_state_table.get_mut(source_id).unwrap() {
InputSourceState::Pointer(pointer_input_state) => pointer_input_state, InputSourceState::Pointer(pointer_input_state) => pointer_input_state,
_ => unreachable!(), _ => unreachable!(),
@ -409,7 +405,7 @@ impl Handler {
// See https://github.com/w3c/webdriver/issues/1905 && // See https://github.com/w3c/webdriver/issues/1905 &&
// https://github.com/servo/servo/issues/37579#issuecomment-2990762713 // https://github.com/servo/servo/issues/37579#issuecomment-2990762713
{ {
let mut input_cancel_list = session.input_cancel_list.borrow_mut(); let mut input_cancel_list = session.input_cancel_list_mut();
if let Some(pos) = input_cancel_list.iter().position(|(id, item)| { if let Some(pos) = input_cancel_list.iter().position(|(id, item)| {
id == source_id && id == source_id &&
matches!(item, ActionItem::Pointer(PointerActionItem::Pointer(PointerAction::Up( matches!(item, ActionItem::Pointer(PointerActionItem::Pointer(PointerAction::Up(
@ -426,7 +422,7 @@ impl Handler {
self.increment_num_pending_actions(); self.increment_num_pending_actions();
let msg_id = self.current_action_id.get(); let msg_id = self.current_action_id.get();
let cmd_msg = WebDriverCommandMsg::MouseButtonAction( let cmd_msg = WebDriverCommandMsg::MouseButtonAction(
session.webview_id, self.verified_webview_id(),
MouseButtonAction::Up, MouseButtonAction::Up,
action.button.into(), action.button.into(),
pointer_input_state.x as f32, pointer_input_state.x as f32,
@ -452,8 +448,7 @@ impl Handler {
let (start_x, start_y) = match self let (start_x, start_y) = match self
.session() .session()
.unwrap() .unwrap()
.input_state_table .input_state_table()
.borrow()
.get(source_id) .get(source_id)
.unwrap() .unwrap()
{ {
@ -517,8 +512,7 @@ impl Handler {
let (start_x, start_y) = match self let (start_x, start_y) = match self
.session() .session()
.unwrap() .unwrap()
.input_state_table .input_state_table()
.borrow()
.get(source_id) .get(source_id)
.unwrap() .unwrap()
{ {
@ -548,7 +542,7 @@ impl Handler {
tick_start: Instant, tick_start: Instant,
) { ) {
let session = self.session().unwrap(); let session = self.session().unwrap();
let mut input_state_table = session.input_state_table.borrow_mut(); let mut input_state_table = session.input_state_table_mut();
let pointer_input_state = match input_state_table.get_mut(source_id).unwrap() { let pointer_input_state = match input_state_table.get_mut(source_id).unwrap() {
InputSourceState::Pointer(pointer_input_state) => pointer_input_state, InputSourceState::Pointer(pointer_input_state) => pointer_input_state,
_ => unreachable!(), _ => unreachable!(),
@ -594,7 +588,7 @@ impl Handler {
None None
}; };
let cmd_msg = WebDriverCommandMsg::MouseMoveAction( let cmd_msg = WebDriverCommandMsg::MouseMoveAction(
session.webview_id, self.verified_webview_id(),
x as f32, x as f32,
y as f32, y as f32,
msg_id, msg_id,
@ -710,8 +704,6 @@ impl Handler {
mut curr_delta_y: f64, mut curr_delta_y: f64,
tick_start: Instant, tick_start: Instant,
) { ) {
let session = self.session().unwrap();
// Step 1. Let time delta be the time since the beginning of the current tick, // Step 1. Let time delta be the time since the beginning of the current tick,
// measured in milliseconds on a monotonic clock. // measured in milliseconds on a monotonic clock.
let time_delta = tick_start.elapsed().as_millis(); let time_delta = tick_start.elapsed().as_millis();
@ -751,7 +743,7 @@ impl Handler {
None None
}; };
let cmd_msg = WebDriverCommandMsg::WheelScrollAction( let cmd_msg = WebDriverCommandMsg::WheelScrollAction(
session.webview_id, self.verified_webview_id(),
x, x,
y, y,
delta_x, delta_x,
@ -795,8 +787,7 @@ impl Handler {
return Err(ErrorStatus::MoveTargetOutOfBounds); return Err(ErrorStatus::MoveTargetOutOfBounds);
} }
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let cmd_msg = let cmd_msg = WebDriverCommandMsg::GetViewportSize(self.verified_webview_id(), sender);
WebDriverCommandMsg::GetViewportSize(self.session.as_ref().unwrap().webview_id, sender);
self.send_message_to_embedder(cmd_msg) self.send_message_to_embedder(cmd_msg)
.map_err(|_| ErrorStatus::UnknownError)?; .map_err(|_| ErrorStatus::UnknownError)?;
@ -878,7 +869,7 @@ impl Handler {
// Step 2. Let id be the value of the id property of action sequence. // Step 2. Let id be the value of the id property of action sequence.
let id = action_sequence.id.clone(); let id = action_sequence.id.clone();
let mut input_state_table = self.session().unwrap().input_state_table.borrow_mut(); let mut input_state_table = self.session().unwrap().input_state_table_mut();
match action_sequence.actions { match action_sequence.actions {
ActionsType::Null { ActionsType::Null {

File diff suppressed because it is too large Load diff

View file

@ -2,19 +2,25 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::cell::{Ref, RefCell, RefMut};
use std::collections::HashMap;
use base::id::{BrowsingContextId, WebViewId}; use base::id::{BrowsingContextId, WebViewId};
use serde_json::{Map, Value, json}; use serde_json::{Map, Value, json};
use uuid::Uuid; use uuid::Uuid;
use webdriver::error::WebDriverResult; use webdriver::error::WebDriverResult;
use crate::Handler;
use crate::actions::{ActionItem, InputSourceState};
use crate::capabilities::ServoCapabilities; use crate::capabilities::ServoCapabilities;
use crate::timeout::{deserialize_as_timeouts_configuration, serialize_timeouts_configuration}; use crate::timeout::{
use crate::user_prompt::{ TimeoutsConfiguration, deserialize_as_timeouts_configuration, serialize_timeouts_configuration,
default_unhandled_prompt_behavior, deserialize_unhandled_prompt_behaviour, };
use crate::user_prompt::{
UserPromptHandler, default_unhandled_prompt_behavior, deserialize_unhandled_prompt_behaviour,
}; };
use crate::{Handler, WebDriverSession};
#[derive(Debug, PartialEq, serde::Serialize)] #[derive(Debug, Clone, PartialEq, serde::Serialize)]
pub enum PageLoadStrategy { pub enum PageLoadStrategy {
None, None,
Eager, Eager,
@ -33,17 +39,109 @@ impl ToString for PageLoadStrategy {
} }
} }
/// Represents the current WebDriver session and holds relevant session state.
/// Currently, only 1 webview is supported per session.
/// So only there is only 1 InputState.
pub struct WebDriverSession {
/// <https://www.w3.org/TR/webdriver2/#dfn-session-id>
id: Uuid,
/// <https://www.w3.org/TR/webdriver2/#dfn-current-top-level-browsing-context>
/// The id of the current top-level browsing context
webview_id: Option<WebViewId>,
/// <https://www.w3.org/TR/webdriver2/#dfn-current-browsing-context>
/// The id of the current browsing context
browsing_context_id: Option<BrowsingContextId>,
timeouts: TimeoutsConfiguration,
page_loading_strategy: PageLoadStrategy,
strict_file_interactability: bool,
user_prompt_handler: UserPromptHandler,
/// <https://w3c.github.io/webdriver/#dfn-input-state-map>
input_state_table: RefCell<HashMap<String, InputSourceState>>,
/// <https://w3c.github.io/webdriver/#dfn-input-cancel-list>
input_cancel_list: RefCell<Vec<(String, ActionItem)>>,
}
impl WebDriverSession {
pub fn new() -> WebDriverSession {
WebDriverSession {
id: Uuid::new_v4(),
webview_id: None,
browsing_context_id: None,
timeouts: TimeoutsConfiguration::default(),
page_loading_strategy: PageLoadStrategy::Normal,
strict_file_interactability: false,
user_prompt_handler: UserPromptHandler::new(),
input_state_table: RefCell::new(HashMap::new()),
input_cancel_list: RefCell::new(Vec::new()),
}
}
pub fn set_webview_id(&mut self, webview_id: Option<WebViewId>) {
self.webview_id = webview_id;
}
pub fn set_browsing_context_id(&mut self, browsing_context_id: Option<BrowsingContextId>) {
self.browsing_context_id = browsing_context_id;
}
pub fn current_webview_id(&self) -> Option<WebViewId> {
self.webview_id
}
pub fn current_browsing_context_id(&self) -> Option<BrowsingContextId> {
self.browsing_context_id
}
pub fn session_timeouts(&self) -> &TimeoutsConfiguration {
&self.timeouts
}
pub fn session_timeouts_mut(&mut self) -> &mut TimeoutsConfiguration {
&mut self.timeouts
}
pub fn page_loading_strategy(&self) -> PageLoadStrategy {
self.page_loading_strategy.clone()
}
pub fn strict_file_interactability(&self) -> bool {
self.strict_file_interactability
}
pub fn user_prompt_handler(&self) -> &UserPromptHandler {
&self.user_prompt_handler
}
pub fn input_state_table(&self) -> Ref<'_, HashMap<String, InputSourceState>> {
self.input_state_table.borrow()
}
pub fn input_state_table_mut(&self) -> RefMut<'_, HashMap<String, InputSourceState>> {
self.input_state_table.borrow_mut()
}
pub fn input_cancel_list_mut(&self) -> RefMut<'_, Vec<(String, ActionItem)>> {
self.input_cancel_list.borrow_mut()
}
}
impl Handler { impl Handler {
/// <https://w3c.github.io/webdriver/#dfn-create-a-session> /// <https://w3c.github.io/webdriver/#dfn-create-a-session>
pub(crate) fn create_session( pub(crate) fn create_session(
&mut self, &mut self,
capabilities: &mut Map<String, Value>, capabilities: &mut Map<String, Value>,
servo_capabilities: &ServoCapabilities, servo_capabilities: &ServoCapabilities,
webview_id: WebViewId,
browsing_context_id: BrowsingContextId,
) -> WebDriverResult<Uuid> { ) -> WebDriverResult<Uuid> {
// Step 2. Let session be a new session // Step 2. Let session be a new session
let mut session = WebDriverSession::new(browsing_context_id, webview_id); let mut session = WebDriverSession::new();
// Step 3. Let proxy be the result of getting property "proxy" from capabilities // Step 3. Let proxy be the result of getting property "proxy" from capabilities
match capabilities.get("proxy") { match capabilities.get("proxy") {

View file

@ -178,7 +178,7 @@ impl Handler {
pub(crate) fn handle_dismiss_alert(&self) -> WebDriverResult<WebDriverResponse> { pub(crate) fn handle_dismiss_alert(&self) -> WebDriverResult<WebDriverResponse> {
// Step 1. If session's current top-level browsing context is no longer open, // Step 1. If session's current top-level browsing context is no longer open,
// return error with error code no such window. // return error with error code no such window.
self.verify_top_level_browsing_context_is_open(self.session()?.webview_id)?; self.verify_top_level_browsing_context_is_open(self.webview_id()?)?;
// Step 3. Dismiss the current user prompt. // Step 3. Dismiss the current user prompt.
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
@ -203,7 +203,7 @@ impl Handler {
pub(crate) fn handle_accept_alert(&self) -> WebDriverResult<WebDriverResponse> { pub(crate) fn handle_accept_alert(&self) -> WebDriverResult<WebDriverResponse> {
// Step 1. If session's current top-level browsing context is no longer open, // Step 1. If session's current top-level browsing context is no longer open,
// return error with error code no such window. // return error with error code no such window.
self.verify_top_level_browsing_context_is_open(self.session()?.webview_id)?; self.verify_top_level_browsing_context_is_open(self.webview_id()?)?;
// Step 3. Accept the current user prompt. // Step 3. Accept the current user prompt.
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
@ -228,7 +228,7 @@ impl Handler {
pub(crate) fn handle_get_alert_text(&self) -> WebDriverResult<WebDriverResponse> { pub(crate) fn handle_get_alert_text(&self) -> WebDriverResult<WebDriverResponse> {
// Step 1. If session's current top-level browsing context is no longer open, // Step 1. If session's current top-level browsing context is no longer open,
// return error with error code no such window. // return error with error code no such window.
self.verify_top_level_browsing_context_is_open(self.session()?.webview_id)?; self.verify_top_level_browsing_context_is_open(self.webview_id()?)?;
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
self.send_message_to_embedder(WebDriverCommandMsg::GetAlertText( self.send_message_to_embedder(WebDriverCommandMsg::GetAlertText(
@ -261,7 +261,7 @@ impl Handler {
&self, &self,
text: String, text: String,
) -> WebDriverResult<WebDriverResponse> { ) -> WebDriverResult<WebDriverResponse> {
let webview_id = self.session()?.webview_id; let webview_id = self.webview_id()?;
// Step 3. If session's current top-level browsing context is no longer open, // Step 3. If session's current top-level browsing context is no longer open,
// return error with error code no such window. // return error with error code no such window.
@ -321,7 +321,7 @@ impl Handler {
Some(prompt_type) => { Some(prompt_type) => {
// Step 2 - 4. Get user prompt handler for the prompt type. // Step 2 - 4. Get user prompt handler for the prompt type.
let handler = let handler =
get_user_prompt_handler(&self.session()?.user_prompt_handler, prompt_type); get_user_prompt_handler(self.session()?.user_prompt_handler(), prompt_type);
// Step 5. Perform the substeps based on handler's handler // Step 5. Perform the substeps based on handler's handler
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();

View file

@ -382,13 +382,9 @@ impl App {
} }
}, },
WebDriverCommandMsg::GetAllWebViews(response_sender) => { WebDriverCommandMsg::GetAllWebViews(response_sender) => {
let webviews = running_state let webviews = running_state.webviews().iter().map(|(id, _)| *id).collect();
.webviews()
.iter()
.map(|(id, _)| *id)
.collect::<Vec<_>>();
if let Err(error) = response_sender.send(Ok(webviews)) { if let Err(error) = response_sender.send(webviews) {
warn!("Failed to send response of GetAllWebViews: {error}"); warn!("Failed to send response of GetAllWebViews: {error}");
} }
}, },

View file

@ -1,3 +0,0 @@
[accept.py]
[test_accept_in_popup_window]
expected: FAIL

View file

@ -7,3 +7,6 @@
[test_seen_nodes[https coop\]] [test_seen_nodes[https coop\]]
expected: FAIL expected: FAIL
[test_history_pushstate]
expected: FAIL

View file

@ -1,3 +0,0 @@
[dismiss.py]
[test_dismiss_in_popup_window]
expected: FAIL

View file

@ -37,3 +37,6 @@
[test_element_reference[shadow-root\]] [test_element_reference[shadow-root\]]
expected: FAIL expected: FAIL
[test_element_reference[window\]]
expected: FAIL

View file

@ -37,3 +37,6 @@
[test_element_reference[shadow-root\]] [test_element_reference[shadow-root\]]
expected: FAIL expected: FAIL
[test_element_reference[window\]]
expected: FAIL

View file

@ -1,3 +0,0 @@
[window.py]
[test_same_id_after_cross_origin_navigation]
expected: FAIL

View file

@ -13,3 +13,6 @@
[test_removed_iframe] [test_removed_iframe]
expected: FAIL expected: FAIL
[test_history_pushstate]
expected: FAIL

View file

@ -1,6 +0,0 @@
[get.py]
[test_get_confirm_text]
expected: FAIL
[test_get_prompt_text]
expected: FAIL

View file

@ -1,4 +0,0 @@
[navigation.py]
expected: TIMEOUT
[test_pointer]
expected: FAIL

View file

@ -13,3 +13,6 @@
[test_send_alert_text[Fed\\terer\]] [test_send_alert_text[Fed\\terer\]]
expected: FAIL expected: FAIL
[test_chained_alert_element_not_interactable[confirm\]]
expected: FAIL