mirror of
https://github.com/servo/servo.git
synced 2025-08-23 22:35:33 +01:00
webdriver: Evaluate script commands via the WebView
API in servoshell (#37663)
Let `WebDriverCommandMsg::ScriptCommand` goes through embedder first. Give `embedder` the ability to release `webdriver` from waiting for a response of `ExecuteScript`. Tests: https://github.com/longvatrong111/servo/actions/runs/16071375821 No regression compared to CI run on main branch. Fixes: https://github.com/servo/servo/issues/37370 cc: @xiaochengh --------- Signed-off-by: batu_hoang <longvatrong111@gmail.com> Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
562d9e4a21
commit
4499fdeb2b
14 changed files with 75 additions and 150 deletions
|
@ -19,7 +19,8 @@ use servo::webrender_api::units::{DeviceIntPoint, DeviceIntSize};
|
|||
use servo::{
|
||||
AllowOrDenyRequest, AuthenticationRequest, FilterPattern, FormControl, GamepadHapticEffectType,
|
||||
KeyboardEvent, LoadStatus, PermissionRequest, Servo, ServoDelegate, ServoError, SimpleDialog,
|
||||
WebDriverCommandMsg, WebDriverLoadStatus, WebView, WebViewBuilder, WebViewDelegate,
|
||||
WebDriverCommandMsg, WebDriverJSResult, WebDriverJSValue, WebDriverLoadStatus, WebView,
|
||||
WebViewBuilder, WebViewDelegate,
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
|
@ -42,6 +43,7 @@ pub(crate) enum AppState {
|
|||
#[derive(Clone, Default)]
|
||||
struct WebDriverSenders {
|
||||
pub load_status_senders: HashMap<WebViewId, IpcSender<WebDriverLoadStatus>>,
|
||||
pub script_evaluation_interrupt_sender: Option<IpcSender<WebDriverJSResult>>,
|
||||
}
|
||||
|
||||
pub(crate) struct RunningAppState {
|
||||
|
@ -406,6 +408,36 @@ impl RunningAppState {
|
|||
.load_status_senders
|
||||
.insert(webview_id, sender);
|
||||
}
|
||||
|
||||
pub(crate) fn set_script_command_interrupt_sender(
|
||||
&self,
|
||||
sender: Option<IpcSender<WebDriverJSResult>>,
|
||||
) {
|
||||
self.webdriver_senders
|
||||
.borrow_mut()
|
||||
.script_evaluation_interrupt_sender = sender;
|
||||
}
|
||||
|
||||
/// Interrupt any ongoing WebDriver-based script evaluation.
|
||||
///
|
||||
/// From <https://w3c.github.io/webdriver/#dfn-execute-a-function-body>:
|
||||
/// > The rules to execute a function body are as follows. The algorithm returns
|
||||
/// > an ECMAScript completion record.
|
||||
/// >
|
||||
/// > If at any point during the algorithm a user prompt appears, immediately return
|
||||
/// > Completion { Type: normal, Value: null, Target: empty }, but continue to run the
|
||||
/// > other steps of this algorithm in parallel.
|
||||
fn interrupt_webdriver_script_evaluation(&self) {
|
||||
if let Some(sender) = &self
|
||||
.webdriver_senders
|
||||
.borrow()
|
||||
.script_evaluation_interrupt_sender
|
||||
{
|
||||
sender.send(Ok(WebDriverJSValue::Null)).unwrap_or_else(|err| {
|
||||
info!("Notify dialog appear failed. Maybe the channel to webdriver is closed: {err}");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ServoShellServoDelegate;
|
||||
|
@ -452,6 +484,8 @@ impl WebViewDelegate for RunningAppState {
|
|||
}
|
||||
|
||||
fn show_simple_dialog(&self, webview: servo::WebView, dialog: SimpleDialog) {
|
||||
self.interrupt_webdriver_script_evaluation();
|
||||
|
||||
if self.servoshell_preferences.headless &&
|
||||
self.servoshell_preferences.webdriver_port.is_none()
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue