From f155c95e1b4df92f9031e19f07acc0a50492438b Mon Sep 17 00:00:00 2001 From: batu_hoang <55729155+longvatrong111@users.noreply.github.com> Date: Tue, 15 Jul 2025 14:51:05 +0800 Subject: [PATCH] webdriver: Element click waits for navigation complete (#37935) Step 11 in https://w3c.github.io/webdriver/#dfn-element-click > [Try](https://w3c.github.io/webdriver/#dfn-try) to [wait for navigation to complete](https://w3c.github.io/webdriver/#dfn-wait-for-navigation-to-complete) with session. This fixes issue in which element_click triggers navigation, but incoming commands still interact with old page. Testing: https://github.com/longvatrong111/servo/actions/runs/16175767947 https://github.com/longvatrong111/servo/actions/runs/16175770044 Signed-off-by: batu_hoang --- components/script/script_thread.rs | 7 ++ components/script/webdriver_handlers.rs | 21 +++- components/shared/embedder/webdriver.rs | 3 + components/webdriver_server/lib.rs | 156 ++++++++++++++---------- ports/servoshell/desktop/app.rs | 6 + ports/servoshell/desktop/app_state.rs | 7 ++ 6 files changed, 137 insertions(+), 63 deletions(-) diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 809ded115de..18bf170f1f3 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -2499,6 +2499,13 @@ impl ScriptThread { reply, can_gc, ), + WebDriverScriptCommand::IsDocumentReadyStateComplete(response_sender) => { + webdriver_handlers::handle_try_wait_for_document_navigation( + &documents, + pipeline_id, + response_sender, + ) + }, _ => (), } } diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs index 7c6677cc6b9..058b4d2245e 100644 --- a/components/script/webdriver_handlers.rs +++ b/components/script/webdriver_handlers.rs @@ -33,7 +33,9 @@ use webdriver::error::ErrorStatus; use crate::document_collection::DocumentCollection; use crate::dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods; use crate::dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods; -use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; +use crate::dom::bindings::codegen::Bindings::DocumentBinding::{ + DocumentMethods, DocumentReadyState, +}; use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods; use crate::dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementMethods; use crate::dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods; @@ -1717,3 +1719,20 @@ pub(crate) fn handle_is_selected( ) .unwrap(); } + +pub(crate) fn handle_try_wait_for_document_navigation( + documents: &DocumentCollection, + pipeline: PipelineId, + reply: IpcSender, +) { + let document = match documents.find_document(pipeline) { + Some(document) => document, + None => { + return reply.send(false).unwrap(); + }, + }; + + let wait_for_document_ready = document.ReadyState() != DocumentReadyState::Complete; + + reply.send(wait_for_document_ready).unwrap(); +} diff --git a/components/shared/embedder/webdriver.rs b/components/shared/embedder/webdriver.rs index 9ffd187706f..897289da901 100644 --- a/components/shared/embedder/webdriver.rs +++ b/components/shared/embedder/webdriver.rs @@ -127,6 +127,8 @@ pub enum WebDriverCommandMsg { IpcSender>, ), GetAlertText(WebViewId, IpcSender>), + AddLoadStatusSender(WebViewId, IpcSender), + RemoveLoadStatusSender(WebViewId), } #[derive(Debug, Deserialize, Serialize)] @@ -202,6 +204,7 @@ pub enum WebDriverScriptCommand { GetTitle(IpcSender), /// Match the element type before sending the event for webdriver `element send keys`. WillSendKeys(String, String, bool, IpcSender>), + IsDocumentReadyStateComplete(IpcSender), } #[derive(Clone, Debug, Deserialize, Serialize)] diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs index 96075e9f222..e93d19a0101 100644 --- a/components/webdriver_server/lib.rs +++ b/components/webdriver_server/lib.rs @@ -1871,9 +1871,11 @@ impl Handler { Ok(WebDriverResponse::Void) } - // https://w3c.github.io/webdriver/#element-click + /// fn handle_element_click(&mut self, element: &WebElement) -> WebDriverResult { let (sender, receiver) = ipc::channel().unwrap(); + let webview_id = self.session()?.webview_id; + let browsing_context_id = self.session()?.browsing_context_id; // Steps 1 - 7 + Step 8 for