aboutsummaryrefslogtreecommitdiffstats
path: root/ports
diff options
context:
space:
mode:
Diffstat (limited to 'ports')
-rw-r--r--ports/servoshell/desktop/app_state.rs45
-rw-r--r--ports/servoshell/desktop/dialog.rs79
-rw-r--r--ports/servoshell/egl/android.rs55
-rw-r--r--ports/servoshell/egl/android/simpleservo.rs2
-rw-r--r--ports/servoshell/egl/app_state.rs38
-rw-r--r--ports/servoshell/egl/host_trait.rs24
-rw-r--r--ports/servoshell/egl/ohos.rs81
7 files changed, 163 insertions, 161 deletions
diff --git a/ports/servoshell/desktop/app_state.rs b/ports/servoshell/desktop/app_state.rs
index c2d6c656e28..e4fa041d1fc 100644
--- a/ports/servoshell/desktop/app_state.rs
+++ b/ports/servoshell/desktop/app_state.rs
@@ -18,8 +18,8 @@ use servo::webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
use servo::webrender_api::ScrollLocation;
use servo::{
AllowOrDenyRequest, AuthenticationRequest, FilterPattern, GamepadHapticEffectType, LoadStatus,
- PermissionRequest, PromptDefinition, PromptOrigin, PromptResult, Servo, ServoDelegate,
- ServoError, TouchEventType, WebView, WebViewDelegate,
+ PermissionRequest, Servo, ServoDelegate, ServoError, SimpleDialog, TouchEventType, WebView,
+ WebViewDelegate,
};
use url::Url;
@@ -415,36 +415,25 @@ impl WebViewDelegate for RunningAppState {
self.inner().window.request_resize(&webview, new_size);
}
- fn show_prompt(
- &self,
- webview: servo::WebView,
- definition: PromptDefinition,
- _origin: PromptOrigin,
- ) {
+ fn show_simple_dialog(&self, webview: servo::WebView, dialog: SimpleDialog) {
if self.servoshell_preferences.headless {
- let _ = match definition {
- PromptDefinition::Alert(_message, sender) => sender.send(()),
- PromptDefinition::OkCancel(_message, sender) => sender.send(PromptResult::Primary),
- PromptDefinition::Input(_message, default, sender) => {
- sender.send(Some(default.to_owned()))
- },
+ // TODO: Avoid copying this from the default trait impl?
+ // Return the DOM-specified default value for when we **cannot show simple dialogs**.
+ let _ = match dialog {
+ SimpleDialog::Alert {
+ 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;
}
- match definition {
- PromptDefinition::Alert(message, sender) => {
- 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);
- },
- }
+ let dialog = Dialog::new_simple_dialog(dialog);
+ self.add_dialog(webview, dialog);
}
fn request_authentication(
diff --git a/ports/servoshell/desktop/dialog.rs b/ports/servoshell/desktop/dialog.rs
index 3b277b6a424..b1cd00deff4 100644
--- a/ports/servoshell/desktop/dialog.rs
+++ b/ports/servoshell/desktop/dialog.rs
@@ -9,7 +9,10 @@ use egui::Modal;
use egui_file_dialog::{DialogState, FileDialog as EguiFileDialog};
use log::warn;
use servo::ipc_channel::ipc::IpcSender;
-use servo::{AuthenticationRequest, FilterPattern, PermissionRequest, PromptResult};
+use servo::{
+ AlertResponse, AuthenticationRequest, ConfirmResponse, FilterPattern, PermissionRequest,
+ PromptResponse, SimpleDialog,
+};
pub enum Dialog {
File {
@@ -17,19 +20,8 @@ pub enum Dialog {
multiple: bool,
response_sender: IpcSender<Option<Vec<PathBuf>>>,
},
- Alert {
- message: String,
- sender: IpcSender<()>,
- },
- OkCancel {
- message: String,
- sender: IpcSender<PromptResult>,
- },
- Input {
- message: String,
- input_text: String,
- sender: IpcSender<Option<String>>,
- },
+ #[allow(clippy::enum_variant_names, reason = "spec terminology")]
+ SimpleDialog(SimpleDialog),
Authentication {
username: String,
password: String,
@@ -76,24 +68,8 @@ impl Dialog {
}
}
- pub fn new_alert_dialog(message: String, sender: IpcSender<()>) -> Self {
- Dialog::Alert { message, sender }
- }
-
- 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_simple_dialog(dialog: SimpleDialog) -> Self {
+ Self::SimpleDialog(dialog)
}
pub fn new_authentication_dialog(authentication_request: AuthenticationRequest) -> Self {
@@ -165,9 +141,12 @@ impl Dialog {
DialogState::Closed => false,
}
},
- Dialog::Alert { message, sender } => {
+ Dialog::SimpleDialog(SimpleDialog::Alert {
+ message,
+ response_sender,
+ }) => {
let mut is_open = true;
- let modal = Modal::new("alert".into());
+ let modal = Modal::new("Alert".into());
modal.show(ctx, |ui| {
make_dialog_label(message, ui, None);
egui::Sides::new().show(
@@ -176,7 +155,7 @@ impl Dialog {
|ui| {
if ui.button("Close").clicked() {
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);
}
}
@@ -185,9 +164,12 @@ impl Dialog {
});
is_open
},
- Dialog::OkCancel { message, sender } => {
+ Dialog::SimpleDialog(SimpleDialog::Confirm {
+ message,
+ response_sender,
+ }) => {
let mut is_open = true;
- let modal = Modal::new("OkCancel".into());
+ let modal = Modal::new("Confirm".into());
modal.show(ctx, |ui| {
make_dialog_label(message, ui, None);
egui::Sides::new().show(
@@ -196,13 +178,13 @@ impl Dialog {
|ui| {
if ui.button("Ok").clicked() {
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);
}
}
if ui.button("Cancel").clicked() {
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);
}
}
@@ -211,27 +193,30 @@ impl Dialog {
});
is_open
},
- Dialog::Input {
+ Dialog::SimpleDialog(SimpleDialog::Prompt {
message,
- input_text,
- sender,
- } => {
+ // The `default` field gets reused as the input buffer.
+ default: input,
+ response_sender,
+ }) => {
let mut is_open = true;
- Modal::new("input".into()).show(ctx, |ui| {
- make_dialog_label(message, ui, Some(input_text));
+ Modal::new("Prompt".into()).show(ctx, |ui| {
+ make_dialog_label(message, ui, Some(input));
egui::Sides::new().show(
ui,
|_ui| {},
|ui| {
if ui.button("Ok").clicked() {
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);
}
}
if ui.button("Cancel").clicked() {
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);
}
}
diff --git a/ports/servoshell/egl/android.rs b/ports/servoshell/egl/android.rs
index f195cc2c910..0f84dadfc14 100644
--- a/ports/servoshell/egl/android.rs
+++ b/ports/servoshell/egl/android.rs
@@ -19,10 +19,11 @@ use log::{debug, error, info, warn};
use raw_window_handle::{
AndroidDisplayHandle, AndroidNdkWindowHandle, RawDisplayHandle, RawWindowHandle,
};
-use servo::{LoadStatus, MediaSessionActionType};
+use servo::{
+ AlertResponse, LoadStatus, MediaSessionActionType, PermissionRequest, SimpleDialog, WebView,
+};
use simpleservo::{
- DeviceIntRect, EventLoopWaker, InitOptions, InputMethodType, MediaSessionPlaybackState,
- PromptResult, APP,
+ DeviceIntRect, EventLoopWaker, InitOptions, InputMethodType, MediaSessionPlaybackState, APP,
};
use super::app_state::{Coordinates, RunningAppState};
@@ -461,11 +462,8 @@ impl HostCallbacks {
let jvm = env.get_java_vm().unwrap();
HostCallbacks { callbacks, jvm }
}
-}
-impl HostTrait for HostCallbacks {
- fn prompt_alert(&self, message: String, _trusted: bool) {
- debug!("prompt_alert");
+ fn show_alert(&self, message: String) {
let mut env = self.jvm.get_env().unwrap();
let Ok(string) = new_string_as_jvalue(&mut env, &message) else {
return;
@@ -478,20 +476,41 @@ impl HostTrait for HostCallbacks {
)
.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 {
- warn!("Prompt not implemented. Cancelled. {}", message);
- PromptResult::Secondary
+impl HostTrait for HostCallbacks {
+ fn request_permission(&self, _webview: WebView, request: PermissionRequest) {
+ warn!("Permissions prompt not implemented. Denied.");
+ request.deny();
}
- fn prompt_input(&self, message: String, default: String, _trusted: bool) -> Option<String> {
- warn!("Input prompt not implemented. {}", message);
- Some(default)
+ 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)
+ },
+ 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) {
diff --git a/ports/servoshell/egl/android/simpleservo.rs b/ports/servoshell/egl/android/simpleservo.rs
index 369e583af08..1dd255402d9 100644
--- a/ports/servoshell/egl/android/simpleservo.rs
+++ b/ports/servoshell/egl/android/simpleservo.rs
@@ -14,7 +14,7 @@ pub use servo::webrender_api::units::DeviceIntRect;
/// and that perform_updates need to be called
pub use servo::EventLoopWaker;
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::app_state::{
diff --git a/ports/servoshell/egl/app_state.rs b/ports/servoshell/egl/app_state.rs
index a62ee308f7a..d7b2e0a5333 100644
--- a/ports/servoshell/egl/app_state.rs
+++ b/ports/servoshell/egl/app_state.rs
@@ -22,9 +22,9 @@ use servo::{
AllowOrDenyRequest, ContextMenuResult, EmbedderProxy, EventLoopWaker, ImeEvent, InputEvent,
InputMethodType, Key, KeyState, KeyboardEvent, LoadStatus, MediaSessionActionType,
MediaSessionEvent, MouseButton, MouseButtonAction, MouseButtonEvent, MouseMoveEvent,
- NavigationRequest, PermissionRequest, PromptDefinition, PromptOrigin, PromptResult,
- RenderingContext, Servo, ServoDelegate, ServoError, TouchEvent, TouchEventType, TouchId,
- WebView, WebViewDelegate, WindowRenderingContext,
+ NavigationRequest, PermissionRequest, RenderingContext, Servo, ServoDelegate, ServoError,
+ SimpleDialog, TouchEvent, TouchEventType, TouchId, WebView, WebViewDelegate,
+ WindowRenderingContext,
};
use url::Url;
@@ -198,15 +198,10 @@ impl WebViewDelegate for RunningAppState {
Some(new_webview)
}
- fn request_permission(&self, _webview: WebView, request: PermissionRequest) {
- let message = format!(
- "Do you want to grant permission for {:?}?",
- request.feature()
- );
- let result = match self.callbacks.host_callbacks.prompt_yes_no(message, true) {
- PromptResult::Primary => request.allow(),
- PromptResult::Secondary | PromptResult::Dismissed => request.deny(),
- };
+ fn request_permission(&self, webview: WebView, request: PermissionRequest) {
+ self.callbacks
+ .host_callbacks
+ .request_permission(webview, request);
}
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) {
- let cb = &self.callbacks.host_callbacks;
- let trusted = origin == PromptOrigin::Trusted;
- let _ = match prompt {
- 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_simple_dialog(&self, webview: WebView, dialog: SimpleDialog) {
+ self.callbacks
+ .host_callbacks
+ .show_simple_dialog(webview, dialog);
}
fn show_ime(
diff --git a/ports/servoshell/egl/host_trait.rs b/ports/servoshell/egl/host_trait.rs
index 1171cf8912a..fe4e8974af5 100644
--- a/ports/servoshell/egl/host_trait.rs
+++ b/ports/servoshell/egl/host_trait.rs
@@ -3,18 +3,22 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
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 {
- /// Show alert.
- fn prompt_alert(&self, msg: String, trusted: bool);
- /// Ask Yes/No question.
- fn prompt_yes_no(&self, msg: String, trusted: bool) -> PromptResult;
- /// Ask Ok/Cancel question.
- fn prompt_ok_cancel(&self, msg: String, trusted: bool) -> PromptResult;
- /// Ask for string
- fn prompt_input(&self, msg: String, default: String, trusted: bool) -> Option<String>;
+ /// Content in a [`WebView`] is requesting permission to access a feature requiring
+ /// permission from the user. The embedder should allow or deny the request, either by
+ /// reading a cached value or querying the user for permission via the user interface.
+ fn request_permission(&self, _webview: WebView, _: PermissionRequest);
+ /// 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.
+ fn show_simple_dialog(&self, _webview: WebView, dialog: SimpleDialog);
/// Show context menu
fn show_context_menu(&self, title: Option<String>, items: Vec<String>);
/// Notify that the load status of the page has changed.
diff --git a/ports/servoshell/egl/ohos.rs b/ports/servoshell/egl/ohos.rs
index ed95324e913..ebaab2c4d33 100644
--- a/ports/servoshell/egl/ohos.rs
+++ b/ports/servoshell/egl/ohos.rs
@@ -21,7 +21,10 @@ use napi_ohos::{Env, JsObject, JsString, NapiRaw};
use ohos_ime::{AttachOptions, Ime, ImeProxy, RawTextEditorProxy};
use ohos_ime_sys::types::InputMethod_EnterKeyType;
use servo::style::Zero;
-use servo::{InputMethodType, LoadStatus, MediaSessionPlaybackState, PromptResult};
+use servo::{
+ AlertResponse, InputMethodType, LoadStatus, MediaSessionPlaybackState, PermissionRequest,
+ SimpleDialog, WebView,
+};
use simpleservo::EventLoopWaker;
use xcomponent_sys::{
OH_NativeXComponent, OH_NativeXComponent_Callback, OH_NativeXComponent_GetKeyEvent,
@@ -671,6 +674,19 @@ impl HostCallbacks {
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 {
@@ -698,33 +714,38 @@ impl Ime for ServoIme {
#[allow(unused)]
impl HostTrait for HostCallbacks {
- fn prompt_alert(&self, msg: String, _trusted: bool) {
- debug!("prompt_alert: {msg}");
- match PROMPT_TOAST.get() {
- 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 request_permission(&self, _webview: WebView, request: PermissionRequest) {
+ warn!("Permissions prompt not implemented. Denied.");
+ request.deny();
+ }
+
+ 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}"),
- }
- }
-
- fn prompt_yes_no(&self, msg: String, trusted: bool) -> PromptResult {
- warn!("Prompt not implemented. Cancelled. {}", msg);
- PromptResult::Secondary
- }
-
- fn prompt_ok_cancel(&self, msg: String, trusted: bool) -> PromptResult {
- warn!("Prompt not implemented. Cancelled. {}", msg);
- PromptResult::Secondary
- }
-
- fn prompt_input(&self, msg: String, default: String, trusted: bool) -> Option<String> {
- warn!("Input prompt not implemented. Cancelled. {}", msg);
- Some(default)
+ 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 show_context_menu(&self, title: Option<String>, items: Vec<String>) {
@@ -740,7 +761,7 @@ impl HostTrait for HostCallbacks {
if load_status == LoadStatus::Complete {
#[cfg(feature = "tracing-hitrace")]
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 {
error!("Backtrace: {bt:?}")
}
- self.prompt_alert("Servo crashed!".to_string(), true);
- self.prompt_alert(reason, true);
+ self.show_alert("Servo crashed!".to_string());
+ self.show_alert(reason);
}
}