mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Move tinyfiledialog out of script into embedder.
This commit is contained in:
parent
24c14ac94e
commit
675b36dde5
6 changed files with 81 additions and 45 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -4762,7 +4762,6 @@ dependencies = [
|
||||||
"swapper",
|
"swapper",
|
||||||
"tendril",
|
"tendril",
|
||||||
"time",
|
"time",
|
||||||
"tinyfiledialogs",
|
|
||||||
"unicode-bidi",
|
"unicode-bidi",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
"url",
|
"url",
|
||||||
|
|
|
@ -185,6 +185,9 @@ pub enum EmbedderMsg {
|
||||||
GetSelectedBluetoothDevice(Vec<String>, IpcSender<Option<String>>),
|
GetSelectedBluetoothDevice(Vec<String>, IpcSender<Option<String>>),
|
||||||
/// Open file dialog to select files. Set boolean flag to true allows to select multiple files.
|
/// Open file dialog to select files. Set boolean flag to true allows to select multiple files.
|
||||||
SelectFiles(Vec<FilterPattern>, bool, IpcSender<Option<Vec<String>>>),
|
SelectFiles(Vec<FilterPattern>, bool, IpcSender<Option<Vec<String>>>),
|
||||||
|
/// Open yes/no message for user to allow permission specified by first String.
|
||||||
|
/// With dialog title specified by second String.
|
||||||
|
PromptPermission(String, String, IpcSender<PermissionRequest>),
|
||||||
/// Request to present an IME to the user when an editable element is focused.
|
/// Request to present an IME to the user when an editable element is focused.
|
||||||
ShowIME(InputMethodType),
|
ShowIME(InputMethodType),
|
||||||
/// Request to hide the IME when the editable element is blurred.
|
/// Request to hide the IME when the editable element is blurred.
|
||||||
|
@ -222,6 +225,7 @@ impl Debug for EmbedderMsg {
|
||||||
EmbedderMsg::Panic(..) => write!(f, "Panic"),
|
EmbedderMsg::Panic(..) => write!(f, "Panic"),
|
||||||
EmbedderMsg::GetSelectedBluetoothDevice(..) => write!(f, "GetSelectedBluetoothDevice"),
|
EmbedderMsg::GetSelectedBluetoothDevice(..) => write!(f, "GetSelectedBluetoothDevice"),
|
||||||
EmbedderMsg::SelectFiles(..) => write!(f, "SelectFiles"),
|
EmbedderMsg::SelectFiles(..) => write!(f, "SelectFiles"),
|
||||||
|
EmbedderMsg::PromptPermission(..) => write!(f, "PromptPermission"),
|
||||||
EmbedderMsg::ShowIME(..) => write!(f, "ShowIME"),
|
EmbedderMsg::ShowIME(..) => write!(f, "ShowIME"),
|
||||||
EmbedderMsg::HideIME => write!(f, "HideIME"),
|
EmbedderMsg::HideIME => write!(f, "HideIME"),
|
||||||
EmbedderMsg::Shutdown => write!(f, "Shutdown"),
|
EmbedderMsg::Shutdown => write!(f, "Shutdown"),
|
||||||
|
@ -299,3 +303,10 @@ pub enum MediaSessionEvent {
|
||||||
/// Indicates that the position state is set.
|
/// Indicates that the position state is set.
|
||||||
SetPositionState(MediaPositionState),
|
SetPositionState(MediaPositionState),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Status for prompting user for permission.
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub enum PermissionRequest {
|
||||||
|
Granted,
|
||||||
|
Denied,
|
||||||
|
}
|
||||||
|
|
|
@ -29,9 +29,6 @@ phf_codegen = "0.8"
|
||||||
phf_shared = "0.8"
|
phf_shared = "0.8"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
|
||||||
tinyfiledialogs = "3.0"
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
accountable-refcell = {version = "0.2.0", optional = true}
|
accountable-refcell = {version = "0.2.0", optional = true}
|
||||||
app_units = "0.7"
|
app_units = "0.7"
|
||||||
|
|
|
@ -61,6 +61,7 @@ use crate::timers::{OneshotTimers, TimerCallback};
|
||||||
use content_security_policy::CspList;
|
use content_security_policy::CspList;
|
||||||
use devtools_traits::{PageError, ScriptToDevtoolsControlMsg};
|
use devtools_traits::{PageError, ScriptToDevtoolsControlMsg};
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
|
use embedder_traits::EmbedderMsg;
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use js::glue::{IsWrapper, UnwrapObjectDynamic};
|
use js::glue::{IsWrapper, UnwrapObjectDynamic};
|
||||||
|
@ -1917,6 +1918,14 @@ impl GlobalScope {
|
||||||
&self.script_to_constellation_chan
|
&self.script_to_constellation_chan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn send_to_embedder(&self, msg: EmbedderMsg) {
|
||||||
|
self.send_to_constellation(ScriptMsg::ForwardToEmbedder(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_to_constellation(&self, msg: ScriptMsg) {
|
||||||
|
self.script_to_constellation_chan().send(msg).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn scheduler_chan(&self) -> &IpcSender<TimerSchedulerMsg> {
|
pub fn scheduler_chan(&self) -> &IpcSender<TimerSchedulerMsg> {
|
||||||
&self.scheduler_chan
|
&self.scheduler_chan
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,15 +19,14 @@ use crate::dom::promise::Promise;
|
||||||
use crate::realms::{AlreadyInRealm, InRealm};
|
use crate::realms::{AlreadyInRealm, InRealm};
|
||||||
use crate::script_runtime::JSContext;
|
use crate::script_runtime::JSContext;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
|
use embedder_traits::{EmbedderMsg, PermissionRequest};
|
||||||
|
use ipc_channel::ipc;
|
||||||
use js::conversions::ConversionResult;
|
use js::conversions::ConversionResult;
|
||||||
use js::jsapi::JSObject;
|
use js::jsapi::JSObject;
|
||||||
use js::jsval::{ObjectValue, UndefinedValue};
|
use js::jsval::{ObjectValue, UndefinedValue};
|
||||||
use servo_config::pref;
|
use servo_config::pref;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
use tinyfiledialogs::{self, MessageBoxIcon, YesNo};
|
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
const DIALOG_TITLE: &'static str = "Permission request dialog";
|
const DIALOG_TITLE: &'static str = "Permission request dialog";
|
||||||
const NONSECURE_DIALOG_MESSAGE: &'static str = "feature is only safe to use in secure context,\
|
const NONSECURE_DIALOG_MESSAGE: &'static str = "feature is only safe to use in secure context,\
|
||||||
but servo can't guarantee\n that the current context is secure. Do you want to proceed and grant permission?";
|
but servo can't guarantee\n that the current context is secure. Do you want to proceed and grant permission?";
|
||||||
|
@ -258,14 +257,10 @@ impl PermissionAlgorithm for Permissions {
|
||||||
PermissionState::Prompt => {
|
PermissionState::Prompt => {
|
||||||
let perm_name = status.get_query();
|
let perm_name = status.get_query();
|
||||||
|
|
||||||
let globalscope = GlobalScope::current().expect("No current global object");
|
|
||||||
|
|
||||||
// https://w3c.github.io/permissions/#request-permission-to-use (Step 3 - 4)
|
// https://w3c.github.io/permissions/#request-permission-to-use (Step 3 - 4)
|
||||||
let state = prompt_user(
|
let globalscope = GlobalScope::current().expect("No current global object");
|
||||||
&format!("{} {} ?", REQUEST_DIALOG_MESSAGE, perm_name.clone()),
|
let prompt = format!("{} {} ?", REQUEST_DIALOG_MESSAGE, perm_name.clone());
|
||||||
globalscope.is_headless(),
|
let state = prompt_user_from_embedder(prompt, &globalscope);
|
||||||
);
|
|
||||||
|
|
||||||
globalscope
|
globalscope
|
||||||
.permission_state_invocation_results()
|
.permission_state_invocation_results()
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
|
@ -289,7 +284,7 @@ pub fn get_descriptor_permission_state(
|
||||||
env_settings_obj: Option<&GlobalScope>,
|
env_settings_obj: Option<&GlobalScope>,
|
||||||
) -> PermissionState {
|
) -> PermissionState {
|
||||||
// Step 1.
|
// Step 1.
|
||||||
let settings = match env_settings_obj {
|
let globalscope = match env_settings_obj {
|
||||||
Some(env_settings_obj) => DomRoot::from_ref(env_settings_obj),
|
Some(env_settings_obj) => DomRoot::from_ref(env_settings_obj),
|
||||||
None => GlobalScope::current().expect("No current global object"),
|
None => GlobalScope::current().expect("No current global object"),
|
||||||
};
|
};
|
||||||
|
@ -305,20 +300,18 @@ pub fn get_descriptor_permission_state(
|
||||||
if pref!(dom.permissions.testing.allowed_in_nonsecure_contexts) {
|
if pref!(dom.permissions.testing.allowed_in_nonsecure_contexts) {
|
||||||
PermissionState::Granted
|
PermissionState::Granted
|
||||||
} else {
|
} else {
|
||||||
settings
|
globalscope
|
||||||
.permission_state_invocation_results()
|
.permission_state_invocation_results()
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.remove(&permission_name.to_string());
|
.remove(&permission_name.to_string());
|
||||||
|
|
||||||
prompt_user(
|
let prompt = format!("The {} {}", permission_name, NONSECURE_DIALOG_MESSAGE);
|
||||||
&format!("The {} {}", permission_name, NONSECURE_DIALOG_MESSAGE),
|
prompt_user_from_embedder(prompt, &globalscope)
|
||||||
settings.is_headless(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 3.
|
// Step 3.
|
||||||
if let Some(prev_result) = settings
|
if let Some(prev_result) = globalscope
|
||||||
.permission_state_invocation_results()
|
.permission_state_invocation_results()
|
||||||
.borrow()
|
.borrow()
|
||||||
.get(&permission_name.to_string())
|
.get(&permission_name.to_string())
|
||||||
|
@ -327,7 +320,7 @@ pub fn get_descriptor_permission_state(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the invocation result
|
// Store the invocation result
|
||||||
settings
|
globalscope
|
||||||
.permission_state_invocation_results()
|
.permission_state_invocation_results()
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.insert(permission_name.to_string(), state);
|
.insert(permission_name.to_string(), state);
|
||||||
|
@ -336,28 +329,6 @@ pub fn get_descriptor_permission_state(
|
||||||
state
|
state
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
fn prompt_user(message: &str, headless: bool) -> PermissionState {
|
|
||||||
if headless {
|
|
||||||
return PermissionState::Denied;
|
|
||||||
}
|
|
||||||
match tinyfiledialogs::message_box_yes_no(
|
|
||||||
DIALOG_TITLE,
|
|
||||||
message,
|
|
||||||
MessageBoxIcon::Question,
|
|
||||||
YesNo::No,
|
|
||||||
) {
|
|
||||||
YesNo::Yes => PermissionState::Granted,
|
|
||||||
YesNo::No => PermissionState::Denied,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "linux"))]
|
|
||||||
fn prompt_user(_message: &str, _headless: bool) -> PermissionState {
|
|
||||||
// TODO popup only supported on linux
|
|
||||||
PermissionState::Denied
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://w3c.github.io/permissions/#allowed-in-non-secure-contexts
|
// https://w3c.github.io/permissions/#allowed-in-non-secure-contexts
|
||||||
fn allowed_in_nonsecure_contexts(permission_name: &PermissionName) -> bool {
|
fn allowed_in_nonsecure_contexts(permission_name: &PermissionName) -> bool {
|
||||||
match *permission_name {
|
match *permission_name {
|
||||||
|
@ -385,3 +356,24 @@ fn allowed_in_nonsecure_contexts(permission_name: &PermissionName) -> bool {
|
||||||
PermissionName::Persistent_storage => false,
|
PermissionName::Persistent_storage => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prompt_user_from_embedder(prompt: String, gs: &GlobalScope) -> PermissionState {
|
||||||
|
let (sender, receiver) = ipc::channel().expect("Failed to create IPC channel!");
|
||||||
|
gs.send_to_embedder(EmbedderMsg::PromptPermission(
|
||||||
|
prompt,
|
||||||
|
DIALOG_TITLE.to_string(),
|
||||||
|
sender,
|
||||||
|
));
|
||||||
|
|
||||||
|
match receiver.recv() {
|
||||||
|
Ok(PermissionRequest::Granted) => PermissionState::Granted,
|
||||||
|
Ok(PermissionRequest::Denied) => PermissionState::Denied,
|
||||||
|
Err(e) => {
|
||||||
|
warn!(
|
||||||
|
"Failed to receive permission state from embedder ({:?}).",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
PermissionState::Denied
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,7 +7,9 @@ use crate::window_trait::{WindowPortsMethods, LINE_HEIGHT};
|
||||||
use euclid::{Point2D, Vector2D};
|
use euclid::{Point2D, Vector2D};
|
||||||
use keyboard_types::{Key, KeyboardEvent, Modifiers, ShortcutMatcher};
|
use keyboard_types::{Key, KeyboardEvent, Modifiers, ShortcutMatcher};
|
||||||
use servo::compositing::windowing::{WebRenderDebugOption, WindowEvent};
|
use servo::compositing::windowing::{WebRenderDebugOption, WindowEvent};
|
||||||
use servo::embedder_traits::{EmbedderMsg, FilterPattern, PromptDefinition, PromptOrigin, PromptResult};
|
use servo::embedder_traits::{
|
||||||
|
EmbedderMsg, FilterPattern, PermissionRequest, PromptDefinition, PromptOrigin, PromptResult,
|
||||||
|
};
|
||||||
use servo::msg::constellation_msg::TopLevelBrowsingContextId as BrowserId;
|
use servo::msg::constellation_msg::TopLevelBrowsingContextId as BrowserId;
|
||||||
use servo::msg::constellation_msg::TraversalDirection;
|
use servo::msg::constellation_msg::TraversalDirection;
|
||||||
use servo::net_traits::pub_domains::is_reg_domain;
|
use servo::net_traits::pub_domains::is_reg_domain;
|
||||||
|
@ -491,6 +493,10 @@ where
|
||||||
self.event_queue.push(WindowEvent::SendError(None, reason));
|
self.event_queue.push(WindowEvent::SendError(None, reason));
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
EmbedderMsg::PromptPermission(message, dialog_title, sender) => {
|
||||||
|
let permission_state = prompt_user(&message, &dialog_title);
|
||||||
|
let _ = sender.send(permission_state);
|
||||||
|
}
|
||||||
EmbedderMsg::ShowIME(_kind) => {
|
EmbedderMsg::ShowIME(_kind) => {
|
||||||
debug!("ShowIME received");
|
debug!("ShowIME received");
|
||||||
},
|
},
|
||||||
|
@ -513,6 +519,28 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
fn prompt_user(prompt: &str, dialog_title: &str) -> PermissionRequest {
|
||||||
|
if opts::get().headless {
|
||||||
|
return PermissionRequest::Denied;
|
||||||
|
}
|
||||||
|
match tinyfiledialogs::message_box_yes_no(
|
||||||
|
dialog_title,
|
||||||
|
prompt,
|
||||||
|
MessageBoxIcon::Question,
|
||||||
|
YesNo::No,
|
||||||
|
) {
|
||||||
|
YesNo::Yes => PermissionRequest::Granted,
|
||||||
|
YesNo::No => PermissionRequest::Denied,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "linux"))]
|
||||||
|
fn prompt_user(_prompt: &str, _dialog_title: &str) -> PermissionRequest {
|
||||||
|
// TODO popup only supported on linux
|
||||||
|
PermissionRequest::Denied
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
fn platform_get_selected_devices(devices: Vec<String>) -> Option<String> {
|
fn platform_get_selected_devices(devices: Vec<String>) -> Option<String> {
|
||||||
let picker_name = "Choose a device";
|
let picker_name = "Choose a device";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue