mirror of
https://github.com/servo/servo.git
synced 2025-09-27 15:20:09 +01:00
webdriver: Implement support for simple dialogs (#37913)
Implement webdriver user prompt: accept alert, dismiss alert, get alert text. Tests: https://github.com/longvatrong111/servo/actions/runs/16175408035 https://github.com/longvatrong111/servo/actions/runs/16175409545 Signed-off-by: batu_hoang <longvatrong111@gmail.com>
This commit is contained in:
parent
84f0cd5801
commit
2e44aba753
9 changed files with 296 additions and 42 deletions
|
@ -27,7 +27,8 @@ use servo::webrender_api::ScrollLocation;
|
|||
use servo::webrender_api::units::DeviceIntSize;
|
||||
use servo::{
|
||||
EventLoopWaker, InputEvent, KeyboardEvent, MouseButtonEvent, MouseMoveEvent,
|
||||
WebDriverCommandMsg, WebDriverScriptCommand, WheelDelta, WheelEvent, WheelMode,
|
||||
WebDriverCommandMsg, WebDriverScriptCommand, WebDriverUserPromptAction, WheelDelta, WheelEvent,
|
||||
WheelMode,
|
||||
};
|
||||
use url::Url;
|
||||
use winit::application::ApplicationHandler;
|
||||
|
@ -552,6 +553,35 @@ impl App {
|
|||
webdriver_script_command,
|
||||
));
|
||||
},
|
||||
WebDriverCommandMsg::HandleUserPrompt(webview_id, action, response_sender) => {
|
||||
let response = if running_state.webview_has_active_dialog(webview_id) {
|
||||
match action {
|
||||
WebDriverUserPromptAction::Accept => {
|
||||
running_state.accept_active_dialogs(webview_id)
|
||||
},
|
||||
WebDriverUserPromptAction::Dismiss => {
|
||||
running_state.dismiss_active_dialogs(webview_id)
|
||||
},
|
||||
};
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
};
|
||||
|
||||
if let Err(error) = response_sender.send(response) {
|
||||
warn!("Failed to send response of HandleUserPrompt: {error}");
|
||||
};
|
||||
},
|
||||
WebDriverCommandMsg::GetAlertText(webview_id, response_sender) => {
|
||||
let response = match running_state.alert_text_of_newest_dialog(webview_id) {
|
||||
Some(text) => Ok(text),
|
||||
None => Err(()),
|
||||
};
|
||||
|
||||
if let Err(error) = response_sender.send(response) {
|
||||
warn!("Failed to send response of GetAlertText: {error}");
|
||||
};
|
||||
},
|
||||
WebDriverCommandMsg::TakeScreenshot(..) => {
|
||||
warn!(
|
||||
"WebDriverCommand {:?} is still not moved from constellation to embedder",
|
||||
|
|
|
@ -337,6 +337,38 @@ impl RunningAppState {
|
|||
.is_some_and(|dialogs| !dialogs.is_empty())
|
||||
}
|
||||
|
||||
pub(crate) fn webview_has_active_dialog(&self, webview_id: WebViewId) -> bool {
|
||||
let inner = self.inner();
|
||||
inner
|
||||
.dialogs
|
||||
.get(&webview_id)
|
||||
.is_some_and(|dialogs| !dialogs.is_empty())
|
||||
}
|
||||
|
||||
pub(crate) fn accept_active_dialogs(&self, webview_id: WebViewId) {
|
||||
if let Some(dialogs) = self.inner_mut().dialogs.get_mut(&webview_id) {
|
||||
dialogs.drain(..).for_each(|dialog| {
|
||||
dialog.accept();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn dismiss_active_dialogs(&self, webview_id: WebViewId) {
|
||||
if let Some(dialogs) = self.inner_mut().dialogs.get_mut(&webview_id) {
|
||||
dialogs.drain(..).for_each(|dialog| {
|
||||
dialog.dismiss();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn alert_text_of_newest_dialog(&self, webview_id: WebViewId) -> Option<String> {
|
||||
self.inner()
|
||||
.dialogs
|
||||
.get(&webview_id)
|
||||
.and_then(|dialogs| dialogs.last())
|
||||
.and_then(|dialog| dialog.message())
|
||||
}
|
||||
|
||||
pub(crate) fn get_focused_webview_index(&self) -> Option<usize> {
|
||||
let focused_id = self.inner().focused_webview_id?;
|
||||
self.webviews()
|
||||
|
@ -486,6 +518,17 @@ impl WebViewDelegate for RunningAppState {
|
|||
fn show_simple_dialog(&self, webview: servo::WebView, dialog: SimpleDialog) {
|
||||
self.interrupt_webdriver_script_evaluation();
|
||||
|
||||
// Dialogs block the page load, so need need to notify WebDriver
|
||||
let webview_id = webview.id();
|
||||
if let Some(sender) = self
|
||||
.webdriver_senders
|
||||
.borrow_mut()
|
||||
.load_status_senders
|
||||
.get(&webview_id)
|
||||
{
|
||||
let _ = sender.send(WebDriverLoadStatus::Blocked);
|
||||
};
|
||||
|
||||
if self.servoshell_preferences.headless &&
|
||||
self.servoshell_preferences.webdriver_port.is_none()
|
||||
{
|
||||
|
|
|
@ -140,6 +140,34 @@ impl Dialog {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn accept(&self) {
|
||||
#[allow(clippy::single_match)]
|
||||
match self {
|
||||
Dialog::SimpleDialog(dialog) => {
|
||||
dialog.accept();
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dismiss(&self) {
|
||||
#[allow(clippy::single_match)]
|
||||
match self {
|
||||
Dialog::SimpleDialog(dialog) => {
|
||||
dialog.dismiss();
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn message(&self) -> Option<String> {
|
||||
#[allow(clippy::single_match)]
|
||||
match self {
|
||||
Dialog::SimpleDialog(dialog) => Some(dialog.message().to_string()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, ctx: &egui::Context) -> bool {
|
||||
match self {
|
||||
Dialog::File {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue