mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
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:
parent
8b3e7b1c6a
commit
37ac4ffeb4
9 changed files with 188 additions and 125 deletions
|
@ -133,7 +133,7 @@ use embedder_traits::{
|
|||
FocusSequenceNumber, InputEvent, JSValue, JavaScriptEvaluationError, JavaScriptEvaluationId,
|
||||
KeyboardEvent, MediaSessionActionType, MediaSessionEvent, MediaSessionPlaybackState,
|
||||
MouseButton, MouseButtonAction, MouseButtonEvent, Theme, ViewportDetails, WebDriverCommandMsg,
|
||||
WebDriverCommandResponse,
|
||||
WebDriverCommandResponse, WebDriverLoadStatus, WebDriverScriptCommand,
|
||||
};
|
||||
use euclid::Size2D;
|
||||
use euclid::default::Size2D as UntypedSize2D;
|
||||
|
@ -396,6 +396,9 @@ pub struct Constellation<STF, SWF> {
|
|||
/// and the namespaces are allocated by the constellation.
|
||||
next_pipeline_namespace_id: PipelineNamespaceId,
|
||||
|
||||
/// An [`IpcSender`] to notify navigation events to webdriver.
|
||||
webdriver_load_status_sender: Option<(IpcSender<WebDriverLoadStatus>, PipelineId)>,
|
||||
|
||||
/// An [`IpcSender`] to forward responses from the `ScriptThread` to the WebDriver server.
|
||||
webdriver_input_command_reponse_sender: Option<IpcSender<WebDriverCommandResponse>>,
|
||||
|
||||
|
@ -666,6 +669,7 @@ where
|
|||
time_profiler_chan: state.time_profiler_chan,
|
||||
mem_profiler_chan: state.mem_profiler_chan.clone(),
|
||||
phantom: PhantomData,
|
||||
webdriver_load_status_sender: None,
|
||||
webdriver_input_command_reponse_sender: None,
|
||||
document_states: HashMap::new(),
|
||||
#[cfg(feature = "webgpu")]
|
||||
|
@ -1254,6 +1258,12 @@ where
|
|||
if allowed {
|
||||
self.load_url(webview_id, pipeline_id, load_data, history_handling);
|
||||
} else {
|
||||
if let Some((sender, id)) = &self.webdriver_load_status_sender {
|
||||
if pipeline_id == *id {
|
||||
let _ = sender.send(WebDriverLoadStatus::NavigationStop);
|
||||
}
|
||||
}
|
||||
|
||||
let pipeline_is_top_level_pipeline = self
|
||||
.browsing_contexts
|
||||
.get(&BrowsingContextId::from(webview_id))
|
||||
|
@ -3518,7 +3528,12 @@ where
|
|||
};
|
||||
if let Err(e) = result {
|
||||
self.handle_send_error(parent_pipeline_id, e);
|
||||
} else if let Some((sender, id)) = &self.webdriver_load_status_sender {
|
||||
if source_id == *id {
|
||||
let _ = sender.send(WebDriverLoadStatus::NavigationStop);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
},
|
||||
None => {
|
||||
|
@ -4414,6 +4429,17 @@ where
|
|||
.get(&browsing_context_id)
|
||||
.expect("ScriptCommand: Browsing context must exist at this point")
|
||||
.pipeline_id;
|
||||
|
||||
match &cmd {
|
||||
WebDriverScriptCommand::AddLoadStatusSender(_, sender) => {
|
||||
self.webdriver_load_status_sender = Some((sender.clone(), pipeline_id));
|
||||
},
|
||||
WebDriverScriptCommand::RemoveLoadStatusSender(_) => {
|
||||
self.webdriver_load_status_sender = None;
|
||||
},
|
||||
_ => {},
|
||||
};
|
||||
|
||||
let control_msg = ScriptThreadMessage::WebDriverScriptCommand(pipeline_id, cmd);
|
||||
let result = match self.pipelines.get(&pipeline_id) {
|
||||
Some(pipeline) => pipeline.event_loop.send(control_msg),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue