mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
libservo: Clean up interfaces for alert()/confirm()/prompt() (#35579)
Signed-off-by: Delan Azabani <dazabani@igalia.com>
This commit is contained in:
parent
03e953e22c
commit
276f6a3ba7
16 changed files with 278 additions and 222 deletions
|
@ -201,7 +201,7 @@ mod from_script {
|
||||||
Self::ChangePageTitle(..) => target_variant!("ChangePageTitle"),
|
Self::ChangePageTitle(..) => target_variant!("ChangePageTitle"),
|
||||||
Self::MoveTo(..) => target_variant!("MoveTo"),
|
Self::MoveTo(..) => target_variant!("MoveTo"),
|
||||||
Self::ResizeTo(..) => target_variant!("ResizeTo"),
|
Self::ResizeTo(..) => target_variant!("ResizeTo"),
|
||||||
Self::Prompt(..) => target_variant!("Prompt"),
|
Self::ShowSimpleDialog(..) => target_variant!("ShowSimpleDialog"),
|
||||||
Self::RequestAuthentication(..) => target_variant!("RequestAuthentication"),
|
Self::RequestAuthentication(..) => target_variant!("RequestAuthentication"),
|
||||||
Self::ShowContextMenu(..) => target_variant!("ShowContextMenu"),
|
Self::ShowContextMenu(..) => target_variant!("ShowContextMenu"),
|
||||||
Self::AllowNavigationRequest(..) => target_variant!("AllowNavigationRequest"),
|
Self::AllowNavigationRequest(..) => target_variant!("AllowNavigationRequest"),
|
||||||
|
|
|
@ -26,8 +26,8 @@ use cssparser::{Parser, ParserInput, SourceLocation};
|
||||||
use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType};
|
use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType};
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use embedder_traits::{
|
use embedder_traits::{
|
||||||
EmbedderMsg, PromptDefinition, PromptOrigin, PromptResult, Theme, WebDriverJSError,
|
AlertResponse, ConfirmResponse, EmbedderMsg, PromptResponse, SimpleDialog, Theme,
|
||||||
WebDriverJSResult,
|
WebDriverJSError, WebDriverJSResult,
|
||||||
};
|
};
|
||||||
use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect};
|
use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect};
|
||||||
use euclid::{Point2D, Rect, Scale, Size2D, Vector2D};
|
use euclid::{Point2D, Rect, Scale, Size2D, Vector2D};
|
||||||
|
@ -736,30 +736,43 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
|
||||||
}
|
}
|
||||||
let (sender, receiver) =
|
let (sender, receiver) =
|
||||||
ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap();
|
ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap();
|
||||||
let prompt = PromptDefinition::Alert(s.to_string(), sender);
|
let dialog = SimpleDialog::Alert {
|
||||||
let msg = EmbedderMsg::Prompt(self.webview_id(), prompt, PromptOrigin::Untrusted);
|
message: s.to_string(),
|
||||||
|
response_sender: sender,
|
||||||
|
};
|
||||||
|
let msg = EmbedderMsg::ShowSimpleDialog(self.webview_id(), dialog);
|
||||||
self.send_to_embedder(msg);
|
self.send_to_embedder(msg);
|
||||||
receiver.recv().unwrap();
|
let AlertResponse::Ok = receiver.recv().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-confirm
|
// https://html.spec.whatwg.org/multipage/#dom-confirm
|
||||||
fn Confirm(&self, s: DOMString) -> bool {
|
fn Confirm(&self, s: DOMString) -> bool {
|
||||||
let (sender, receiver) =
|
let (sender, receiver) =
|
||||||
ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap();
|
ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap();
|
||||||
let prompt = PromptDefinition::OkCancel(s.to_string(), sender);
|
let dialog = SimpleDialog::Confirm {
|
||||||
let msg = EmbedderMsg::Prompt(self.webview_id(), prompt, PromptOrigin::Untrusted);
|
message: s.to_string(),
|
||||||
|
response_sender: sender,
|
||||||
|
};
|
||||||
|
let msg = EmbedderMsg::ShowSimpleDialog(self.webview_id(), dialog);
|
||||||
self.send_to_embedder(msg);
|
self.send_to_embedder(msg);
|
||||||
receiver.recv().unwrap() == PromptResult::Primary
|
receiver.recv().unwrap() == ConfirmResponse::Ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-prompt
|
// https://html.spec.whatwg.org/multipage/#dom-prompt
|
||||||
fn Prompt(&self, message: DOMString, default: DOMString) -> Option<DOMString> {
|
fn Prompt(&self, message: DOMString, default: DOMString) -> Option<DOMString> {
|
||||||
let (sender, receiver) =
|
let (sender, receiver) =
|
||||||
ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap();
|
ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap();
|
||||||
let prompt = PromptDefinition::Input(message.to_string(), default.to_string(), sender);
|
let dialog = SimpleDialog::Prompt {
|
||||||
let msg = EmbedderMsg::Prompt(self.webview_id(), prompt, PromptOrigin::Untrusted);
|
message: message.to_string(),
|
||||||
|
default: default.to_string(),
|
||||||
|
response_sender: sender,
|
||||||
|
};
|
||||||
|
let msg = EmbedderMsg::ShowSimpleDialog(self.webview_id(), dialog);
|
||||||
self.send_to_embedder(msg);
|
self.send_to_embedder(msg);
|
||||||
receiver.recv().unwrap().map(|s| s.into())
|
match receiver.recv().unwrap() {
|
||||||
|
PromptResponse::Ok(input) => Some(input.into()),
|
||||||
|
PromptResponse::Cancel => None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-window-stop
|
// https://html.spec.whatwg.org/multipage/#dom-window-stop
|
||||||
|
|
|
@ -708,11 +708,11 @@ impl Servo {
|
||||||
webview.delegate().request_resize_to(webview, size);
|
webview.delegate().request_resize_to(webview, size);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
EmbedderMsg::Prompt(webview_id, prompt_definition, prompt_origin) => {
|
EmbedderMsg::ShowSimpleDialog(webview_id, prompt_definition) => {
|
||||||
if let Some(webview) = self.get_webview_handle(webview_id) {
|
if let Some(webview) = self.get_webview_handle(webview_id) {
|
||||||
webview
|
webview
|
||||||
.delegate()
|
.delegate()
|
||||||
.show_prompt(webview, prompt_definition, prompt_origin);
|
.show_simple_dialog(webview, prompt_definition);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
EmbedderMsg::ShowContextMenu(webview_id, ipc_sender, title, items) => {
|
EmbedderMsg::ShowContextMenu(webview_id, ipc_sender, title, items) => {
|
||||||
|
|
|
@ -9,8 +9,7 @@ use compositing_traits::ConstellationMsg;
|
||||||
use embedder_traits::{
|
use embedder_traits::{
|
||||||
AllowOrDeny, AuthenticationResponse, ContextMenuResult, Cursor, FilterPattern,
|
AllowOrDeny, AuthenticationResponse, ContextMenuResult, Cursor, FilterPattern,
|
||||||
GamepadHapticEffectType, InputMethodType, LoadStatus, MediaSessionEvent, PermissionFeature,
|
GamepadHapticEffectType, InputMethodType, LoadStatus, MediaSessionEvent, PermissionFeature,
|
||||||
PromptDefinition, PromptOrigin, WebResourceRequest, WebResourceResponse,
|
SimpleDialog, WebResourceRequest, WebResourceResponse, WebResourceResponseMsg,
|
||||||
WebResourceResponseMsg,
|
|
||||||
};
|
};
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use keyboard_types::KeyboardEvent;
|
use keyboard_types::KeyboardEvent;
|
||||||
|
@ -338,17 +337,25 @@ pub trait WebViewDelegate {
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show dialog to user
|
/// Show the user a [simple dialog](https://html.spec.whatwg.org/multipage/#simple-dialogs) (`alert()`, `confirm()`,
|
||||||
|
/// or `prompt()`). Since their messages are controlled by web content, they should be presented to the user in a
|
||||||
|
/// way that makes them impossible to mistake for browser UI.
|
||||||
/// TODO: This API needs to be reworked to match the new model of how responses are sent.
|
/// TODO: This API needs to be reworked to match the new model of how responses are sent.
|
||||||
fn show_prompt(&self, _webview: WebView, prompt: PromptDefinition, _: PromptOrigin) {
|
fn show_simple_dialog(&self, _webview: WebView, dialog: SimpleDialog) {
|
||||||
let _ = match prompt {
|
// Return the DOM-specified default value for when we **cannot show simple dialogs**.
|
||||||
PromptDefinition::Alert(_, response_sender) => response_sender.send(()),
|
let _ = match dialog {
|
||||||
PromptDefinition::OkCancel(_, response_sender) => {
|
SimpleDialog::Alert {
|
||||||
response_sender.send(embedder_traits::PromptResult::Dismissed)
|
response_sender, ..
|
||||||
},
|
} => response_sender.send(Default::default()),
|
||||||
PromptDefinition::Input(_, _, response_sender) => response_sender.send(None),
|
SimpleDialog::Confirm {
|
||||||
|
response_sender, ..
|
||||||
|
} => response_sender.send(Default::default()),
|
||||||
|
SimpleDialog::Prompt {
|
||||||
|
response_sender, ..
|
||||||
|
} => response_sender.send(Default::default()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show a context menu to the user
|
/// Show a context menu to the user
|
||||||
fn show_context_menu(
|
fn show_context_menu(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -123,14 +123,30 @@ pub enum ContextMenuResult {
|
||||||
Selected(usize),
|
Selected(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [Simple dialogs](https://html.spec.whatwg.org/multipage/#simple-dialogs) are synchronous dialogs
|
||||||
|
/// that can be opened by web content. Since their messages are controlled by web content, they
|
||||||
|
/// should be presented to the user in a way that makes them impossible to mistake for browser UI.
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub enum PromptDefinition {
|
pub enum SimpleDialog {
|
||||||
/// Show a message.
|
/// [`alert()`](https://html.spec.whatwg.org/multipage/#dom-alert).
|
||||||
Alert(String, IpcSender<()>),
|
/// TODO: Include details about the document origin.
|
||||||
/// Ask a Ok/Cancel question.
|
Alert {
|
||||||
OkCancel(String, IpcSender<PromptResult>),
|
message: String,
|
||||||
/// Ask the user to enter text.
|
response_sender: IpcSender<AlertResponse>,
|
||||||
Input(String, String, IpcSender<Option<String>>),
|
},
|
||||||
|
/// [`confirm()`](https://html.spec.whatwg.org/multipage/#dom-confirm).
|
||||||
|
/// TODO: Include details about the document origin.
|
||||||
|
Confirm {
|
||||||
|
message: String,
|
||||||
|
response_sender: IpcSender<ConfirmResponse>,
|
||||||
|
},
|
||||||
|
/// [`prompt()`](https://html.spec.whatwg.org/multipage/#dom-prompt).
|
||||||
|
/// TODO: Include details about the document origin.
|
||||||
|
Prompt {
|
||||||
|
message: String,
|
||||||
|
default: String,
|
||||||
|
response_sender: IpcSender<PromptResponse>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||||
|
@ -142,22 +158,52 @@ pub struct AuthenticationResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Serialize)]
|
#[derive(Deserialize, PartialEq, Serialize)]
|
||||||
pub enum PromptOrigin {
|
pub enum AlertResponse {
|
||||||
/// Prompt is triggered from content (window.prompt/alert/confirm/…).
|
/// The user chose Ok, or the dialog was otherwise dismissed or ignored.
|
||||||
/// Prompt message is unknown.
|
Ok,
|
||||||
Untrusted,
|
}
|
||||||
/// Prompt is triggered from Servo (ask for permission, show error,…).
|
|
||||||
Trusted,
|
impl Default for AlertResponse {
|
||||||
|
fn default() -> Self {
|
||||||
|
// Per <https://html.spec.whatwg.org/multipage/#dom-alert>,
|
||||||
|
// if we **cannot show simple dialogs**, including cases where the user or user agent decides to ignore
|
||||||
|
// all modal dialogs, we need to return (which represents Ok).
|
||||||
|
Self::Ok
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Serialize)]
|
#[derive(Deserialize, PartialEq, Serialize)]
|
||||||
pub enum PromptResult {
|
pub enum ConfirmResponse {
|
||||||
/// Prompt was closed by clicking on the primary button (ok/yes)
|
/// The user chose Ok.
|
||||||
Primary,
|
Ok,
|
||||||
/// Prompt was closed by clicking on the secondary button (cancel/no)
|
/// The user chose Cancel, or the dialog was otherwise dismissed or ignored.
|
||||||
Secondary,
|
Cancel,
|
||||||
/// Prompt was dismissed
|
}
|
||||||
Dismissed,
|
|
||||||
|
impl Default for ConfirmResponse {
|
||||||
|
fn default() -> Self {
|
||||||
|
// Per <https://html.spec.whatwg.org/multipage/#dom-confirm>,
|
||||||
|
// if we **cannot show simple dialogs**, including cases where the user or user agent decides to ignore
|
||||||
|
// all modal dialogs, we need to return false (which represents Cancel), not true (Ok).
|
||||||
|
Self::Cancel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, PartialEq, Serialize)]
|
||||||
|
pub enum PromptResponse {
|
||||||
|
/// The user chose Ok, with the given input.
|
||||||
|
Ok(String),
|
||||||
|
/// The user chose Cancel, or the dialog was otherwise dismissed or ignored.
|
||||||
|
Cancel,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for PromptResponse {
|
||||||
|
fn default() -> Self {
|
||||||
|
// Per <https://html.spec.whatwg.org/multipage/#dom-prompt>,
|
||||||
|
// if we **cannot show simple dialogs**, including cases where the user or user agent decides to ignore
|
||||||
|
// all modal dialogs, we need to return null (which represents Cancel), not the default input.
|
||||||
|
Self::Cancel
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A response to a request to allow or deny an action.
|
/// A response to a request to allow or deny an action.
|
||||||
|
@ -177,8 +223,10 @@ pub enum EmbedderMsg {
|
||||||
MoveTo(WebViewId, DeviceIntPoint),
|
MoveTo(WebViewId, DeviceIntPoint),
|
||||||
/// Resize the window to size
|
/// Resize the window to size
|
||||||
ResizeTo(WebViewId, DeviceIntSize),
|
ResizeTo(WebViewId, DeviceIntSize),
|
||||||
/// Show dialog to user
|
/// Show the user a [simple dialog](https://html.spec.whatwg.org/multipage/#simple-dialogs) (`alert()`, `confirm()`,
|
||||||
Prompt(WebViewId, PromptDefinition, PromptOrigin),
|
/// or `prompt()`). Since their messages are controlled by web content, they should be presented to the user in a
|
||||||
|
/// way that makes them impossible to mistake for browser UI.
|
||||||
|
ShowSimpleDialog(WebViewId, SimpleDialog),
|
||||||
/// Request authentication for a load or navigation from the embedder.
|
/// Request authentication for a load or navigation from the embedder.
|
||||||
RequestAuthentication(
|
RequestAuthentication(
|
||||||
WebViewId,
|
WebViewId,
|
||||||
|
@ -280,7 +328,7 @@ impl Debug for EmbedderMsg {
|
||||||
EmbedderMsg::ChangePageTitle(..) => write!(f, "ChangePageTitle"),
|
EmbedderMsg::ChangePageTitle(..) => write!(f, "ChangePageTitle"),
|
||||||
EmbedderMsg::MoveTo(..) => write!(f, "MoveTo"),
|
EmbedderMsg::MoveTo(..) => write!(f, "MoveTo"),
|
||||||
EmbedderMsg::ResizeTo(..) => write!(f, "ResizeTo"),
|
EmbedderMsg::ResizeTo(..) => write!(f, "ResizeTo"),
|
||||||
EmbedderMsg::Prompt(..) => write!(f, "Prompt"),
|
EmbedderMsg::ShowSimpleDialog(..) => write!(f, "ShowSimpleDialog"),
|
||||||
EmbedderMsg::RequestAuthentication(..) => write!(f, "RequestAuthentication"),
|
EmbedderMsg::RequestAuthentication(..) => write!(f, "RequestAuthentication"),
|
||||||
EmbedderMsg::AllowUnload(..) => write!(f, "AllowUnload"),
|
EmbedderMsg::AllowUnload(..) => write!(f, "AllowUnload"),
|
||||||
EmbedderMsg::AllowNavigationRequest(..) => write!(f, "AllowNavigationRequest"),
|
EmbedderMsg::AllowNavigationRequest(..) => write!(f, "AllowNavigationRequest"),
|
||||||
|
|
|
@ -18,8 +18,8 @@ use servo::webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
||||||
use servo::webrender_api::ScrollLocation;
|
use servo::webrender_api::ScrollLocation;
|
||||||
use servo::{
|
use servo::{
|
||||||
AllowOrDenyRequest, AuthenticationRequest, FilterPattern, GamepadHapticEffectType, LoadStatus,
|
AllowOrDenyRequest, AuthenticationRequest, FilterPattern, GamepadHapticEffectType, LoadStatus,
|
||||||
PermissionRequest, PromptDefinition, PromptOrigin, PromptResult, Servo, ServoDelegate,
|
PermissionRequest, Servo, ServoDelegate, ServoError, SimpleDialog, TouchEventType, WebView,
|
||||||
ServoError, TouchEventType, WebView, WebViewDelegate,
|
WebViewDelegate,
|
||||||
};
|
};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -415,36 +415,25 @@ impl WebViewDelegate for RunningAppState {
|
||||||
self.inner().window.request_resize(&webview, new_size);
|
self.inner().window.request_resize(&webview, new_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_prompt(
|
fn show_simple_dialog(&self, webview: servo::WebView, dialog: SimpleDialog) {
|
||||||
&self,
|
|
||||||
webview: servo::WebView,
|
|
||||||
definition: PromptDefinition,
|
|
||||||
_origin: PromptOrigin,
|
|
||||||
) {
|
|
||||||
if self.servoshell_preferences.headless {
|
if self.servoshell_preferences.headless {
|
||||||
let _ = match definition {
|
// TODO: Avoid copying this from the default trait impl?
|
||||||
PromptDefinition::Alert(_message, sender) => sender.send(()),
|
// Return the DOM-specified default value for when we **cannot show simple dialogs**.
|
||||||
PromptDefinition::OkCancel(_message, sender) => sender.send(PromptResult::Primary),
|
let _ = match dialog {
|
||||||
PromptDefinition::Input(_message, default, sender) => {
|
SimpleDialog::Alert {
|
||||||
sender.send(Some(default.to_owned()))
|
response_sender, ..
|
||||||
},
|
} => response_sender.send(Default::default()),
|
||||||
|
SimpleDialog::Confirm {
|
||||||
|
response_sender, ..
|
||||||
|
} => response_sender.send(Default::default()),
|
||||||
|
SimpleDialog::Prompt {
|
||||||
|
response_sender, ..
|
||||||
|
} => response_sender.send(Default::default()),
|
||||||
};
|
};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
match definition {
|
let dialog = Dialog::new_simple_dialog(dialog);
|
||||||
PromptDefinition::Alert(message, sender) => {
|
self.add_dialog(webview, dialog);
|
||||||
let alert_dialog = Dialog::new_alert_dialog(message, sender);
|
|
||||||
self.add_dialog(webview, alert_dialog);
|
|
||||||
},
|
|
||||||
PromptDefinition::OkCancel(message, sender) => {
|
|
||||||
let okcancel_dialog = Dialog::new_okcancel_dialog(message, sender);
|
|
||||||
self.add_dialog(webview, okcancel_dialog);
|
|
||||||
},
|
|
||||||
PromptDefinition::Input(message, default, sender) => {
|
|
||||||
let input_dialog = Dialog::new_input_dialog(message, default, sender);
|
|
||||||
self.add_dialog(webview, input_dialog);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn request_authentication(
|
fn request_authentication(
|
||||||
|
|
|
@ -9,7 +9,10 @@ use egui::Modal;
|
||||||
use egui_file_dialog::{DialogState, FileDialog as EguiFileDialog};
|
use egui_file_dialog::{DialogState, FileDialog as EguiFileDialog};
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use servo::ipc_channel::ipc::IpcSender;
|
use servo::ipc_channel::ipc::IpcSender;
|
||||||
use servo::{AuthenticationRequest, FilterPattern, PermissionRequest, PromptResult};
|
use servo::{
|
||||||
|
AlertResponse, AuthenticationRequest, ConfirmResponse, FilterPattern, PermissionRequest,
|
||||||
|
PromptResponse, SimpleDialog,
|
||||||
|
};
|
||||||
|
|
||||||
pub enum Dialog {
|
pub enum Dialog {
|
||||||
File {
|
File {
|
||||||
|
@ -17,19 +20,8 @@ pub enum Dialog {
|
||||||
multiple: bool,
|
multiple: bool,
|
||||||
response_sender: IpcSender<Option<Vec<PathBuf>>>,
|
response_sender: IpcSender<Option<Vec<PathBuf>>>,
|
||||||
},
|
},
|
||||||
Alert {
|
#[allow(clippy::enum_variant_names, reason = "spec terminology")]
|
||||||
message: String,
|
SimpleDialog(SimpleDialog),
|
||||||
sender: IpcSender<()>,
|
|
||||||
},
|
|
||||||
OkCancel {
|
|
||||||
message: String,
|
|
||||||
sender: IpcSender<PromptResult>,
|
|
||||||
},
|
|
||||||
Input {
|
|
||||||
message: String,
|
|
||||||
input_text: String,
|
|
||||||
sender: IpcSender<Option<String>>,
|
|
||||||
},
|
|
||||||
Authentication {
|
Authentication {
|
||||||
username: String,
|
username: String,
|
||||||
password: String,
|
password: String,
|
||||||
|
@ -76,24 +68,8 @@ impl Dialog {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_alert_dialog(message: String, sender: IpcSender<()>) -> Self {
|
pub fn new_simple_dialog(dialog: SimpleDialog) -> Self {
|
||||||
Dialog::Alert { message, sender }
|
Self::SimpleDialog(dialog)
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_okcancel_dialog(message: String, sender: IpcSender<PromptResult>) -> Self {
|
|
||||||
Dialog::OkCancel { message, sender }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_input_dialog(
|
|
||||||
message: String,
|
|
||||||
default: String,
|
|
||||||
sender: IpcSender<Option<String>>,
|
|
||||||
) -> Self {
|
|
||||||
Dialog::Input {
|
|
||||||
message,
|
|
||||||
input_text: default,
|
|
||||||
sender,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_authentication_dialog(authentication_request: AuthenticationRequest) -> Self {
|
pub fn new_authentication_dialog(authentication_request: AuthenticationRequest) -> Self {
|
||||||
|
@ -165,9 +141,12 @@ impl Dialog {
|
||||||
DialogState::Closed => false,
|
DialogState::Closed => false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Dialog::Alert { message, sender } => {
|
Dialog::SimpleDialog(SimpleDialog::Alert {
|
||||||
|
message,
|
||||||
|
response_sender,
|
||||||
|
}) => {
|
||||||
let mut is_open = true;
|
let mut is_open = true;
|
||||||
let modal = Modal::new("alert".into());
|
let modal = Modal::new("Alert".into());
|
||||||
modal.show(ctx, |ui| {
|
modal.show(ctx, |ui| {
|
||||||
make_dialog_label(message, ui, None);
|
make_dialog_label(message, ui, None);
|
||||||
egui::Sides::new().show(
|
egui::Sides::new().show(
|
||||||
|
@ -176,7 +155,7 @@ impl Dialog {
|
||||||
|ui| {
|
|ui| {
|
||||||
if ui.button("Close").clicked() {
|
if ui.button("Close").clicked() {
|
||||||
is_open = false;
|
is_open = false;
|
||||||
if let Err(e) = sender.send(()) {
|
if let Err(e) = response_sender.send(AlertResponse::Ok) {
|
||||||
warn!("Failed to send alert dialog response: {}", e);
|
warn!("Failed to send alert dialog response: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -185,9 +164,12 @@ impl Dialog {
|
||||||
});
|
});
|
||||||
is_open
|
is_open
|
||||||
},
|
},
|
||||||
Dialog::OkCancel { message, sender } => {
|
Dialog::SimpleDialog(SimpleDialog::Confirm {
|
||||||
|
message,
|
||||||
|
response_sender,
|
||||||
|
}) => {
|
||||||
let mut is_open = true;
|
let mut is_open = true;
|
||||||
let modal = Modal::new("OkCancel".into());
|
let modal = Modal::new("Confirm".into());
|
||||||
modal.show(ctx, |ui| {
|
modal.show(ctx, |ui| {
|
||||||
make_dialog_label(message, ui, None);
|
make_dialog_label(message, ui, None);
|
||||||
egui::Sides::new().show(
|
egui::Sides::new().show(
|
||||||
|
@ -196,13 +178,13 @@ impl Dialog {
|
||||||
|ui| {
|
|ui| {
|
||||||
if ui.button("Ok").clicked() {
|
if ui.button("Ok").clicked() {
|
||||||
is_open = false;
|
is_open = false;
|
||||||
if let Err(e) = sender.send(PromptResult::Primary) {
|
if let Err(e) = response_sender.send(ConfirmResponse::Ok) {
|
||||||
warn!("Failed to send alert dialog response: {}", e);
|
warn!("Failed to send alert dialog response: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ui.button("Cancel").clicked() {
|
if ui.button("Cancel").clicked() {
|
||||||
is_open = false;
|
is_open = false;
|
||||||
if let Err(e) = sender.send(PromptResult::Secondary) {
|
if let Err(e) = response_sender.send(ConfirmResponse::Cancel) {
|
||||||
warn!("Failed to send alert dialog response: {}", e);
|
warn!("Failed to send alert dialog response: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,27 +193,30 @@ impl Dialog {
|
||||||
});
|
});
|
||||||
is_open
|
is_open
|
||||||
},
|
},
|
||||||
Dialog::Input {
|
Dialog::SimpleDialog(SimpleDialog::Prompt {
|
||||||
message,
|
message,
|
||||||
input_text,
|
// The `default` field gets reused as the input buffer.
|
||||||
sender,
|
default: input,
|
||||||
} => {
|
response_sender,
|
||||||
|
}) => {
|
||||||
let mut is_open = true;
|
let mut is_open = true;
|
||||||
Modal::new("input".into()).show(ctx, |ui| {
|
Modal::new("Prompt".into()).show(ctx, |ui| {
|
||||||
make_dialog_label(message, ui, Some(input_text));
|
make_dialog_label(message, ui, Some(input));
|
||||||
egui::Sides::new().show(
|
egui::Sides::new().show(
|
||||||
ui,
|
ui,
|
||||||
|_ui| {},
|
|_ui| {},
|
||||||
|ui| {
|
|ui| {
|
||||||
if ui.button("Ok").clicked() {
|
if ui.button("Ok").clicked() {
|
||||||
is_open = false;
|
is_open = false;
|
||||||
if let Err(e) = sender.send(Some(input_text.clone())) {
|
if let Err(e) =
|
||||||
|
response_sender.send(PromptResponse::Ok(input.clone()))
|
||||||
|
{
|
||||||
warn!("Failed to send input dialog response: {}", e);
|
warn!("Failed to send input dialog response: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ui.button("Cancel").clicked() {
|
if ui.button("Cancel").clicked() {
|
||||||
is_open = false;
|
is_open = false;
|
||||||
if let Err(e) = sender.send(None) {
|
if let Err(e) = response_sender.send(PromptResponse::Cancel) {
|
||||||
warn!("Failed to send input dialog response: {}", e);
|
warn!("Failed to send input dialog response: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,11 @@ use log::{debug, error, info, warn};
|
||||||
use raw_window_handle::{
|
use raw_window_handle::{
|
||||||
AndroidDisplayHandle, AndroidNdkWindowHandle, RawDisplayHandle, RawWindowHandle,
|
AndroidDisplayHandle, AndroidNdkWindowHandle, RawDisplayHandle, RawWindowHandle,
|
||||||
};
|
};
|
||||||
use servo::{LoadStatus, MediaSessionActionType};
|
use servo::{
|
||||||
|
AlertResponse, LoadStatus, MediaSessionActionType, PermissionRequest, SimpleDialog, WebView,
|
||||||
|
};
|
||||||
use simpleservo::{
|
use simpleservo::{
|
||||||
DeviceIntRect, EventLoopWaker, InitOptions, InputMethodType, MediaSessionPlaybackState,
|
DeviceIntRect, EventLoopWaker, InitOptions, InputMethodType, MediaSessionPlaybackState, APP,
|
||||||
PromptResult, APP,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::app_state::{Coordinates, RunningAppState};
|
use super::app_state::{Coordinates, RunningAppState};
|
||||||
|
@ -461,11 +462,8 @@ impl HostCallbacks {
|
||||||
let jvm = env.get_java_vm().unwrap();
|
let jvm = env.get_java_vm().unwrap();
|
||||||
HostCallbacks { callbacks, jvm }
|
HostCallbacks { callbacks, jvm }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl HostTrait for HostCallbacks {
|
fn show_alert(&self, message: String) {
|
||||||
fn prompt_alert(&self, message: String, _trusted: bool) {
|
|
||||||
debug!("prompt_alert");
|
|
||||||
let mut env = self.jvm.get_env().unwrap();
|
let mut env = self.jvm.get_env().unwrap();
|
||||||
let Ok(string) = new_string_as_jvalue(&mut env, &message) else {
|
let Ok(string) = new_string_as_jvalue(&mut env, &message) else {
|
||||||
return;
|
return;
|
||||||
|
@ -478,20 +476,41 @@ impl HostTrait for HostCallbacks {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prompt_ok_cancel(&self, message: String, _trusted: bool) -> PromptResult {
|
|
||||||
warn!("Prompt not implemented. Cancelled. {}", message);
|
|
||||||
PromptResult::Secondary
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prompt_yes_no(&self, message: String, _trusted: bool) -> PromptResult {
|
impl HostTrait for HostCallbacks {
|
||||||
warn!("Prompt not implemented. Cancelled. {}", message);
|
fn request_permission(&self, _webview: WebView, request: PermissionRequest) {
|
||||||
PromptResult::Secondary
|
warn!("Permissions prompt not implemented. Denied.");
|
||||||
|
request.deny();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prompt_input(&self, message: String, default: String, _trusted: bool) -> Option<String> {
|
fn show_simple_dialog(&self, _webview: WebView, dialog: SimpleDialog) {
|
||||||
warn!("Input prompt not implemented. {}", message);
|
let _ = match dialog {
|
||||||
Some(default)
|
SimpleDialog::Alert {
|
||||||
|
message,
|
||||||
|
response_sender,
|
||||||
|
} => {
|
||||||
|
debug!("SimpleDialog::Alert");
|
||||||
|
// TODO: Indicate that this message is untrusted, and what origin it came from.
|
||||||
|
self.show_alert(message);
|
||||||
|
response_sender.send(AlertResponse::Ok)
|
||||||
|
},
|
||||||
|
SimpleDialog::Confirm {
|
||||||
|
message,
|
||||||
|
response_sender,
|
||||||
|
} => {
|
||||||
|
warn!("Confirm dialog not implemented. Cancelled. {}", message);
|
||||||
|
response_sender.send(Default::default())
|
||||||
|
},
|
||||||
|
SimpleDialog::Prompt {
|
||||||
|
message,
|
||||||
|
response_sender,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
warn!("Prompt dialog not implemented. Cancelled. {}", message);
|
||||||
|
response_sender.send(Default::default())
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn notify_load_status_changed(&self, load_status: LoadStatus) {
|
fn notify_load_status_changed(&self, load_status: LoadStatus) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub use servo::webrender_api::units::DeviceIntRect;
|
||||||
/// and that perform_updates need to be called
|
/// and that perform_updates need to be called
|
||||||
pub use servo::EventLoopWaker;
|
pub use servo::EventLoopWaker;
|
||||||
use servo::{self, resources, Servo};
|
use servo::{self, resources, Servo};
|
||||||
pub use servo::{InputMethodType, MediaSessionPlaybackState, PromptResult, WindowRenderingContext};
|
pub use servo::{InputMethodType, MediaSessionPlaybackState, WindowRenderingContext};
|
||||||
|
|
||||||
use crate::egl::android::resources::ResourceReaderInstance;
|
use crate::egl::android::resources::ResourceReaderInstance;
|
||||||
use crate::egl::app_state::{
|
use crate::egl::app_state::{
|
||||||
|
|
|
@ -22,9 +22,9 @@ use servo::{
|
||||||
AllowOrDenyRequest, ContextMenuResult, EmbedderProxy, EventLoopWaker, ImeEvent, InputEvent,
|
AllowOrDenyRequest, ContextMenuResult, EmbedderProxy, EventLoopWaker, ImeEvent, InputEvent,
|
||||||
InputMethodType, Key, KeyState, KeyboardEvent, LoadStatus, MediaSessionActionType,
|
InputMethodType, Key, KeyState, KeyboardEvent, LoadStatus, MediaSessionActionType,
|
||||||
MediaSessionEvent, MouseButton, MouseButtonAction, MouseButtonEvent, MouseMoveEvent,
|
MediaSessionEvent, MouseButton, MouseButtonAction, MouseButtonEvent, MouseMoveEvent,
|
||||||
NavigationRequest, PermissionRequest, PromptDefinition, PromptOrigin, PromptResult,
|
NavigationRequest, PermissionRequest, RenderingContext, Servo, ServoDelegate, ServoError,
|
||||||
RenderingContext, Servo, ServoDelegate, ServoError, TouchEvent, TouchEventType, TouchId,
|
SimpleDialog, TouchEvent, TouchEventType, TouchId, WebView, WebViewDelegate,
|
||||||
WebView, WebViewDelegate, WindowRenderingContext,
|
WindowRenderingContext,
|
||||||
};
|
};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -198,15 +198,10 @@ impl WebViewDelegate for RunningAppState {
|
||||||
Some(new_webview)
|
Some(new_webview)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn request_permission(&self, _webview: WebView, request: PermissionRequest) {
|
fn request_permission(&self, webview: WebView, request: PermissionRequest) {
|
||||||
let message = format!(
|
self.callbacks
|
||||||
"Do you want to grant permission for {:?}?",
|
.host_callbacks
|
||||||
request.feature()
|
.request_permission(webview, request);
|
||||||
);
|
|
||||||
let result = match self.callbacks.host_callbacks.prompt_yes_no(message, true) {
|
|
||||||
PromptResult::Primary => request.allow(),
|
|
||||||
PromptResult::Secondary | PromptResult::Dismissed => request.deny(),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn request_resize_to(&self, _webview: WebView, size: DeviceIntSize) {
|
fn request_resize_to(&self, _webview: WebView, size: DeviceIntSize) {
|
||||||
|
@ -231,21 +226,10 @@ impl WebViewDelegate for RunningAppState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_prompt(&self, _webview: WebView, prompt: PromptDefinition, origin: PromptOrigin) {
|
fn show_simple_dialog(&self, webview: WebView, dialog: SimpleDialog) {
|
||||||
let cb = &self.callbacks.host_callbacks;
|
self.callbacks
|
||||||
let trusted = origin == PromptOrigin::Trusted;
|
.host_callbacks
|
||||||
let _ = match prompt {
|
.show_simple_dialog(webview, dialog);
|
||||||
PromptDefinition::Alert(message, response_sender) => {
|
|
||||||
cb.prompt_alert(message, trusted);
|
|
||||||
response_sender.send(())
|
|
||||||
},
|
|
||||||
PromptDefinition::OkCancel(message, response_sender) => {
|
|
||||||
response_sender.send(cb.prompt_ok_cancel(message, trusted))
|
|
||||||
},
|
|
||||||
PromptDefinition::Input(message, default, response_sender) => {
|
|
||||||
response_sender.send(cb.prompt_input(message, default, trusted))
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_ime(
|
fn show_ime(
|
||||||
|
|
|
@ -3,18 +3,22 @@
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use servo::webrender_api::units::DeviceIntRect;
|
use servo::webrender_api::units::DeviceIntRect;
|
||||||
use servo::{InputMethodType, LoadStatus, MediaSessionPlaybackState, PromptResult};
|
use servo::{
|
||||||
|
InputMethodType, LoadStatus, MediaSessionPlaybackState, PermissionRequest, SimpleDialog,
|
||||||
|
WebView,
|
||||||
|
};
|
||||||
|
|
||||||
/// Callbacks. Implemented by embedder. Called by Servo.
|
/// Callbacks implemented by embedder. Called by our RunningAppState, generally on behalf of Servo.
|
||||||
pub trait HostTrait {
|
pub trait HostTrait {
|
||||||
/// Show alert.
|
/// Content in a [`WebView`] is requesting permission to access a feature requiring
|
||||||
fn prompt_alert(&self, msg: String, trusted: bool);
|
/// permission from the user. The embedder should allow or deny the request, either by
|
||||||
/// Ask Yes/No question.
|
/// reading a cached value or querying the user for permission via the user interface.
|
||||||
fn prompt_yes_no(&self, msg: String, trusted: bool) -> PromptResult;
|
fn request_permission(&self, _webview: WebView, _: PermissionRequest);
|
||||||
/// Ask Ok/Cancel question.
|
/// Show the user a [simple dialog](https://html.spec.whatwg.org/multipage/#simple-dialogs) (`alert()`, `confirm()`,
|
||||||
fn prompt_ok_cancel(&self, msg: String, trusted: bool) -> PromptResult;
|
/// or `prompt()`). Since their messages are controlled by web content, they should be presented to the user in a
|
||||||
/// Ask for string
|
/// way that makes them impossible to mistake for browser UI.
|
||||||
fn prompt_input(&self, msg: String, default: String, trusted: bool) -> Option<String>;
|
/// TODO: This API needs to be reworked to match the new model of how responses are sent.
|
||||||
|
fn show_simple_dialog(&self, _webview: WebView, dialog: SimpleDialog);
|
||||||
/// Show context menu
|
/// Show context menu
|
||||||
fn show_context_menu(&self, title: Option<String>, items: Vec<String>);
|
fn show_context_menu(&self, title: Option<String>, items: Vec<String>);
|
||||||
/// Notify that the load status of the page has changed.
|
/// Notify that the load status of the page has changed.
|
||||||
|
|
|
@ -21,7 +21,10 @@ use napi_ohos::{Env, JsObject, JsString, NapiRaw};
|
||||||
use ohos_ime::{AttachOptions, Ime, ImeProxy, RawTextEditorProxy};
|
use ohos_ime::{AttachOptions, Ime, ImeProxy, RawTextEditorProxy};
|
||||||
use ohos_ime_sys::types::InputMethod_EnterKeyType;
|
use ohos_ime_sys::types::InputMethod_EnterKeyType;
|
||||||
use servo::style::Zero;
|
use servo::style::Zero;
|
||||||
use servo::{InputMethodType, LoadStatus, MediaSessionPlaybackState, PromptResult};
|
use servo::{
|
||||||
|
AlertResponse, InputMethodType, LoadStatus, MediaSessionPlaybackState, PermissionRequest,
|
||||||
|
SimpleDialog, WebView,
|
||||||
|
};
|
||||||
use simpleservo::EventLoopWaker;
|
use simpleservo::EventLoopWaker;
|
||||||
use xcomponent_sys::{
|
use xcomponent_sys::{
|
||||||
OH_NativeXComponent, OH_NativeXComponent_Callback, OH_NativeXComponent_GetKeyEvent,
|
OH_NativeXComponent, OH_NativeXComponent_Callback, OH_NativeXComponent_GetKeyEvent,
|
||||||
|
@ -671,6 +674,19 @@ impl HostCallbacks {
|
||||||
ime_proxy: RefCell::new(None),
|
ime_proxy: RefCell::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn show_alert(&self, message: String) {
|
||||||
|
match PROMPT_TOAST.get() {
|
||||||
|
Some(prompt_fn) => {
|
||||||
|
let status = prompt_fn.call(message, ThreadsafeFunctionCallMode::NonBlocking);
|
||||||
|
if status != napi_ohos::Status::Ok {
|
||||||
|
// Queue could be full.
|
||||||
|
error!("show_alert failed with {status}");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => error!("PROMPT_TOAST not set. Dropping message {message}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ServoIme {
|
struct ServoIme {
|
||||||
|
@ -698,33 +714,38 @@ impl Ime for ServoIme {
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
impl HostTrait for HostCallbacks {
|
impl HostTrait for HostCallbacks {
|
||||||
fn prompt_alert(&self, msg: String, _trusted: bool) {
|
fn request_permission(&self, _webview: WebView, request: PermissionRequest) {
|
||||||
debug!("prompt_alert: {msg}");
|
warn!("Permissions prompt not implemented. Denied.");
|
||||||
match PROMPT_TOAST.get() {
|
request.deny();
|
||||||
Some(prompt_fn) => {
|
|
||||||
let status = prompt_fn.call(msg, ThreadsafeFunctionCallMode::NonBlocking);
|
|
||||||
if status != napi_ohos::Status::Ok {
|
|
||||||
// Queue could be full.
|
|
||||||
error!("prompt_alert failed with {status}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_simple_dialog(&self, _webview: WebView, dialog: SimpleDialog) {
|
||||||
|
let _ = match dialog {
|
||||||
|
SimpleDialog::Alert {
|
||||||
|
message,
|
||||||
|
response_sender,
|
||||||
|
} => {
|
||||||
|
debug!("SimpleDialog::Alert");
|
||||||
|
// TODO: Indicate that this message is untrusted, and what origin it came from.
|
||||||
|
self.show_alert(message);
|
||||||
|
response_sender.send(AlertResponse::Ok)
|
||||||
},
|
},
|
||||||
None => error!("PROMPT_TOAST not set. Dropping msg {msg}"),
|
SimpleDialog::Confirm {
|
||||||
}
|
message,
|
||||||
}
|
response_sender,
|
||||||
|
} => {
|
||||||
fn prompt_yes_no(&self, msg: String, trusted: bool) -> PromptResult {
|
warn!("Confirm dialog not implemented. Cancelled. {}", message);
|
||||||
warn!("Prompt not implemented. Cancelled. {}", msg);
|
response_sender.send(Default::default())
|
||||||
PromptResult::Secondary
|
},
|
||||||
}
|
SimpleDialog::Prompt {
|
||||||
|
message,
|
||||||
fn prompt_ok_cancel(&self, msg: String, trusted: bool) -> PromptResult {
|
response_sender,
|
||||||
warn!("Prompt not implemented. Cancelled. {}", msg);
|
..
|
||||||
PromptResult::Secondary
|
} => {
|
||||||
}
|
warn!("Prompt dialog not implemented. Cancelled. {}", message);
|
||||||
|
response_sender.send(Default::default())
|
||||||
fn prompt_input(&self, msg: String, default: String, trusted: bool) -> Option<String> {
|
},
|
||||||
warn!("Input prompt not implemented. Cancelled. {}", msg);
|
};
|
||||||
Some(default)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_context_menu(&self, title: Option<String>, items: Vec<String>) {
|
fn show_context_menu(&self, title: Option<String>, items: Vec<String>) {
|
||||||
|
@ -740,7 +761,7 @@ impl HostTrait for HostCallbacks {
|
||||||
if load_status == LoadStatus::Complete {
|
if load_status == LoadStatus::Complete {
|
||||||
#[cfg(feature = "tracing-hitrace")]
|
#[cfg(feature = "tracing-hitrace")]
|
||||||
let _scope = hitrace::ScopedTrace::start_trace(&c"PageLoadEndedPrompt");
|
let _scope = hitrace::ScopedTrace::start_trace(&c"PageLoadEndedPrompt");
|
||||||
self.prompt_alert("Page finished loading!".to_string(), true);
|
self.show_alert("Page finished loading!".to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -838,7 +859,7 @@ impl HostTrait for HostCallbacks {
|
||||||
if let Some(bt) = backtrace {
|
if let Some(bt) = backtrace {
|
||||||
error!("Backtrace: {bt:?}")
|
error!("Backtrace: {bt:?}")
|
||||||
}
|
}
|
||||||
self.prompt_alert("Servo crashed!".to_string(), true);
|
self.show_alert("Servo crashed!".to_string());
|
||||||
self.prompt_alert(reason, true);
|
self.show_alert(reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
[iframe_sandbox_block_modals-2.html]
|
|
||||||
[Frames without `allow-modals` should not be able to open modal dialogs]
|
|
||||||
expected: FAIL
|
|
|
@ -1,3 +0,0 @@
|
||||||
[iframe_sandbox_block_modals-3.html]
|
|
||||||
[Frames without `allow-modals` should not be able to open modal dialogs]
|
|
||||||
expected: FAIL
|
|
|
@ -1,4 +0,0 @@
|
||||||
[confirm-different-origin-frame.sub.html]
|
|
||||||
[confirm-different-origin-frame]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
[prompt-different-origin-frame.sub.html]
|
|
||||||
[prompt-different-origin-frame]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue