10BC0 webdriver: Evaluate script commands via the `WebView` API in servoshe… · servo/servo@4499fde · GitHub
[go: up one dir, main page]

Skip to content

Commit 4499fde

Browse files
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: #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>
1 parent 562d9e4 commit 4499fde

File tree

14 files changed

+75
-150
lines changed

14 files changed

+75
-150
lines changed

components/webdriver_server/lib.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -726,10 +726,10 @@ impl Handler {
726726
if let VerifyBrowsingContextIsOpen::Yes = verify {
727727
self.verify_browsing_context_is_open(browsing_context_id)?;
728728
}
729-
let msg = EmbedderToConstellationMessage::WebDriverCommand(
730-
WebDriverCommandMsg::ScriptCommand(browsing_context_id, cmd_msg),
731-
);
732-
self.constellation_chan.send(msg).unwrap();
729+
self.send_message_to_embedder(WebDriverCommandMsg::ScriptCommand(
730+
browsing_context_id,
731+
cmd_msg,
732+
))?;
733733
Ok(())
734734
}
735735

@@ -746,10 +746,10 @@ impl Handler {
746746
self.verify_top_level_browsing_context_is_open(webview_id)?;
747747
}
748748
let browsing_context_id = BrowsingContextId::from(webview_id);
749-
let msg = EmbedderToConstellationMessage::WebDriverCommand(
750-
WebDriverCommandMsg::ScriptCommand(browsing_context_id, cmd_msg),
751-
);
752-
self.constellation_chan.send(msg).unwrap();
749+
self.send_message_to_embedder(WebDriverCommandMsg::ScriptCommand(
750+
browsing_context_id,
751+
cmd_msg,
752+
))?;
753753
Ok(())
754754
}
755755

ports/servoshell/desktop/app.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use servo::webrender_api::ScrollLocation;
2727
use servo::webrender_api::units::DeviceIntSize;
2828
use servo::{
2929
EventLoopWaker, InputEvent, KeyboardEvent, MouseButtonEvent, MouseMoveEvent,
30-
WebDriverCommandMsg, WheelDelta, WheelEvent, WheelMode,
30+
WebDriverCommandMsg, WebDriverScriptCommand, WheelDelta, WheelEvent, WheelMode,
3131
};
3232
use url::Url;
3333
use winit::application::ApplicationHandler;
@@ -542,7 +542,16 @@ impl App {
542542
webview.notify_scroll_event(scroll_location, point.to_i32());
543543
}
544544
},
545-
WebDriverCommandMsg::ScriptCommand(..) |
545+
WebDriverCommandMsg::ScriptCommand(
546+
browsing_context_id,
547+
webdriver_script_command,
548+
) => {
549+
self.handle_webdriver_script_commnd(&webdriver_script_command, running_state);
550+
running_state.forward_webdriver_command(WebDriverCommandMsg::ScriptCommand(
551+
browsing_context_id,
552+
webdriver_script_command,
553+
));
554+
},
546555
WebDriverCommandMsg::TakeScreenshot(..) => {
547556
warn!(
548557
"WebDriverCommand {:?} is still not moved from constellation to embedder",
@@ -552,6 +561,24 @@ impl App {
552561
};
553562
}
554563
}
564+
565+
fn handle_webdriver_script_commnd(
566+
&self,
567+
msg: &WebDriverScriptCommand,
568+
running_state: &RunningAppState,
569+
) {
570+
match msg {
571+
WebDriverScriptCommand::ExecuteScript(_webview_id, response_sender) => {
572+
// Give embedder a chance to interrupt the script command.
573+
// Webdriver only handles 1 script command at a time, so we can
574+
// safely set a new interrupt sender and remove the previous one here.
575+
running_state.set_script_command_interrupt_sender(Some(response_sender.clone()));
576+
},
577+
_ => {
578+
running_state.set_script_command_interrupt_sender(None);
579+
},
580+
}
581+
}
555582
}
556583

557584
impl ApplicationHandler<AppEvent> for App {

ports/servoshell/desktop/app_state.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ use servo::webrender_api::units::{DeviceIntPoint, DeviceIntSize};
1919
use servo::{
2020
AllowOrDenyRequest, AuthenticationRequest, FilterPattern, FormControl, GamepadHapticEffectType,
2121
KeyboardEvent, LoadStatus, PermissionRequest, Servo, ServoDelegate, ServoError, SimpleDialog,
22-
WebDriverCommandMsg, WebDriverLoadStatus, WebView, WebViewBuilder, WebViewDelegate,
22+
WebDriverCommandMsg, WebDriverJSResult, WebDriverJSValue, WebDriverLoadStatus, WebView,
23+
WebViewBuilder, WebViewDelegate,
2324
};
2425
use url::Url;
2526

@@ -42,6 +43,7 @@ pub(crate) enum AppState {
4243
#[derive(Clone, Default)]
4344
struct WebDriverSenders {
4445
pub load_status_senders: HashMap<WebViewId, IpcSender<WebDriverLoadStatus>>,
46+
pub script_evaluation_interrupt_sender: Option<IpcSender<WebDriverJSResult>>,
4547
}
4648

4749
pub(crate) struct RunningAppState {
@@ -406,6 +408,36 @@ impl RunningAppState {
406408
.load_status_senders
407409
.insert(webview_id, sender);
408410
}
411+
412+
pub(crate) fn set_script_command_interrupt_sender(
413+
&self,
414+
sender: Option<IpcSender<WebDriverJSResult>>,
415+
) {
416+
self.webdriver_senders
417+
.borrow_mut()
418+
.script_evaluation_interrupt_sender = sender;
419+
}
420+
421+
/// Interrupt any ongoing WebDriver-based script evaluation.
422+
///
423+
/// From <https://w3c.github.io/webdriver/#dfn-execute-a-function-body>:
424+
/// > The rules to execute a function body are as follows. The algorithm returns
425+
/// > an ECMAScript completion record.
426+
/// >
427+
/// > If at any point during the algorithm a user prompt appears, immediately return
428+
/// > Completion { Type: normal, Value: null, Target: empty }, but continue to run the
429+
/// > other steps of this algorithm in parallel.
430+
fn interrupt_webdriver_script_evaluation(&self) {
431+
if let Some(sender) = &self
432+
.webdriver_senders
433+
.borrow()
434+
.script_evaluation_interrupt_sender
435+
{
436+
sender.send(Ok(WebDriverJSValue::Null)).unwrap_or_else(|err| {
437+
info!("Notify dialog appear failed. Maybe the channel to webdriver is closed: {err}");
438+
});
439+
}
440+
}
409441
}
410442

411443
struct ServoShellServoDelegate;
@@ -452,6 +484,8 @@ impl WebViewDelegate for RunningAppState {
452484
}
453485

454486
fn show_simple_dialog(&self, webview: servo::WebView, dialog: SimpleDialog) {
487+
self.interrupt_webdriver_script_evaluation();
488+
455489
if self.servoshell_preferences.headless &&
456490
self.servoshell_preferences.webdriver_port.is_none()
457491
{

tests/wpt/meta/webdriver/tests/classic/element_send_keys/events.py.ini

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,3 @@
44

55
[test_form_control_send_text[textarea\]]
66
expected: FAIL
7-
8-
[test_file_upload]
9-
expected: FAIL
10-
11-
[test_not_blurred[input\]]
12-
expected: FAIL
13-
14-
[test_not_blurred[textarea\]]
15-
expected: FAIL

tests/wpt/meta/webdriver/tests/classic/element_send_keys/file_upload.py.ini

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,33 +22,3 @@
2222

2323
[test_strict_display_none]
2424
expected: ERROR
25-
26-
[test_multiple_files]
27-
expected: FAIL
28-
29-
[test_multiple_files_without_multiple_attribute]
30-
expected: FAIL
31-
32-
[test_single_file]
33-
expected: FAIL
34-
35-
[test_single_file_replaces_without_multiple_attribute]
36-
expected: FAIL
37-
38-
[test_transparent]
39-
expected: FAIL
40-
41-
[test_obscured]
42-
expected: FAIL
43-
44-
[test_outside_viewport]
45-
expected: FAIL
46-
47-
[test_hidden]
48-
expected: FAIL
49-
50-
[test_display_none]
51-
expected: FAIL
52-
53-
[test_not_focused]
54-
expected: FAIL

tests/wpt/meta/webdriver/tests/classic/element_send_keys/form_controls.py.ini

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,3 @@
44

55
[test_textarea_append]
66
expected: FAIL
7-
8-
[test_input]
9-
expected: FAIL
10-
11-
[test_textarea]
12-
expected: FAIL
13-
14-
[test_input_insert_when_focused]
15-
expected: FAIL
16-
17-
[test_textarea_insert_when_focused]
18-
expected: FAIL
19-
20-
[test_date]
21-
expected: FAIL

tests/wpt/meta/webdriver/tests/classic/element_send_keys/interactability.py.ini

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,3 @@
2222

2323
[test_readonly_element]
2424
expected: FAIL
25-
26-
[test_body_is_interactable]
27-
expected: FAIL
28-
29-
[test_transparent_element]
30-
expected: FAIL
31-
32-
[test_obscured_element]
33-
expected: FAIL

tests/wpt/meta/webdriver/tests/classic/element_send_keys/scroll_into_view.py.ini

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,3 @@
2222

2323
[test_element_just_outside_viewport[Just below viewport\]]
2424
expected: FAIL
25-
26-
[test_element_outside_of_not_scrollable_viewport]
27-
expected: FAIL
Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,3 @@
11
[send_keys.py]
2-
[test_null_response_value]
3-
expected: FAIL
4-
5-
[test_no_top_browsing_context]
6-
expected: FAIL
7-
8-
[test_no_such_element_with_invalid_value]
9-
expected: FAIL
10-
11-
[test_no_such_element_with_shadow_root]
12-
expected: FAIL
13-
14-
[test_no_such_element_from_other_window_handle[open\]]
15-
expected: FAIL
16-
17-
[test_no_such_element_from_other_window_handle[closed\]]
18-
expected: FAIL
19-
20-
[test_no_such_element_from_other_frame[open\]]
21-
expected: FAIL
22-
23-
[test_no_such_element_from_other_frame[closed\]]
24-
expected: FAIL
25-
26-
[test_stale_element_reference[top_context\]]
27-
expected: FAIL
28-
29-
[test_stale_element_reference[child_context\]]
30-
expected: FAIL
31-
32-
[test_surrogates]
2+
[test_no_browsing_context]
333
expected: FAIL
Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,6 @@
11
[key_events.py]
2-
[test_modifier_key_sends_correct_events[\\ue008-SHIFT\]]
3-
expected: FAIL
4-
5-
[test_non_printable_key_sends_events[\\ue00c-ESCAPE\]]
6-
expected: FAIL
7-
82
[test_special_key_sends_keydown[EQUALS-expected12\]]
93
expected: FAIL
104

115
[test_special_key_sends_keydown[PAUSE-expected45\]]
126
expected: FAIL
13-
14-
[test_modifier_key_sends_correct_events[\\ue00a-ALT\]]
15-
expected: FAIL
16-
17-
[test_modifier_key_sends_correct_events[\\ue009-CONTROL\]]
18-
expected: FAIL
19-
20-
[test_modifier_key_sends_correct_events[\\ue03d-META\]]
21-
expected: FAIL
22-
23-
[test_modifier_key_sends_correct_events[\\ue052-R_ALT\]]
24-
expected: FAIL

0 commit comments

Comments
 (0)
0