Rework on webdriver wait for navigation complete (#38234)

For current implementation, when a command may trigger a navigation,
webdriver only waits for document readiness state.
However, not all navigations make change in document.
This PR handles more cases for waiting for a navigation, and apply to
`element_click`.

- Before sending a command which may trigger a navigation, `webdriver`
sets `load status send` to `embedder`, `constelltation` and `script
thread` to listen to `navigation events`.
- Webdriver check if there is a navigation with `script thread`.
- If the navigation is loading a new url, webdriver checks if the
request is approved with `constellation`, then waits for document
readiness state.
- If the navigation is a hashchange, webdriver waits untill all new
generated dom events have been processed.

Testing: 
`tests/wpt/tests/webdriver/tests/classic/element_click/navigate.py`
`tests/wpt/tests/webdriver/tests/classic/element_click/user_prompts.py`
https://github.com/longvatrong111/servo/actions/runs/16488690749

cc: @xiaochengh

---------

Signed-off-by: batu_hoang <hoang.binh.trong@huawei.com>
This commit is contained in:
batu_hoang 2025-07-30 15:24:07 +08:00 committed by GitHub
parent 8b3e7b1c6a
commit 37ac4ffeb4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 188 additions and 125 deletions

View file

@ -455,12 +455,6 @@ impl App {
warn!("Failed to send response of GetFocusedWebView: {error}");
};
},
WebDriverCommandMsg::AddLoadStatusSender(webview_id, load_status_sender) => {
running_state.set_load_status_sender(webview_id, load_status_sender);
},
WebDriverCommandMsg::RemoveLoadStatusSender(webview_id) => {
running_state.remove_load_status_sender(webview_id);
},
WebDriverCommandMsg::LoadUrl(webview_id, url, load_status_sender) => {
if let Some(webview) = running_state.webview_by_id(webview_id) {
running_state.set_load_status_sender(webview_id, load_status_sender);
@ -571,7 +565,7 @@ impl App {
}
},
WebDriverCommandMsg::ScriptCommand(_, ref webdriver_script_command) => {
self.handle_webdriver_script_commnd(webdriver_script_command, running_state);
self.handle_webdriver_script_command(webdriver_script_command, running_state);
running_state.servo().execute_webdriver_command(msg);
},
WebDriverCommandMsg::CurrentUserPrompt(webview_id, response_sender) => {
@ -627,7 +621,7 @@ impl App {
}
}
fn handle_webdriver_script_commnd(
fn handle_webdriver_script_command(
&self,
msg: &WebDriverScriptCommand,
running_state: &RunningAppState,
@ -640,6 +634,12 @@ impl App {
// safely set a new interrupt sender and remove the previous one here.
running_state.set_script_command_interrupt_sender(Some(response_sender.clone()));
},
WebDriverScriptCommand::AddLoadStatusSender(webview_id, load_status_sender) => {
running_state.set_load_status_sender(*webview_id, load_status_sender.clone());
},
WebDriverScriptCommand::RemoveLoadStatusSender(webview_id) => {
running_state.remove_load_status_sender(*webview_id);
},
_ => {
running_state.set_script_command_interrupt_sender(None);
},