diff options
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | components/embedder_traits/lib.rs | 11 | ||||
-rw-r--r-- | components/script/Cargo.toml | 3 | ||||
-rw-r--r-- | components/script/dom/globalscope.rs | 9 | ||||
-rw-r--r-- | components/script/dom/permissions.rs | 72 | ||||
-rw-r--r-- | ports/glutin/browser.rs | 30 |
6 files changed, 81 insertions, 45 deletions
diff --git a/Cargo.lock b/Cargo.lock index 2c561e97ff5..8aca24486c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4762,7 +4762,6 @@ dependencies = [ "swapper", "tendril", "time", - "tinyfiledialogs", "unicode-bidi", "unicode-segmentation", "url", diff --git a/components/embedder_traits/lib.rs b/components/embedder_traits/lib.rs index c13ad617920..71eb7876eca 100644 --- a/components/embedder_traits/lib.rs +++ b/components/embedder_traits/lib.rs @@ -185,6 +185,9 @@ pub enum EmbedderMsg { GetSelectedBluetoothDevice(Vec<String>, IpcSender<Option<String>>), /// Open file dialog to select files. Set boolean flag to true allows to select multiple files. 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. ShowIME(InputMethodType), /// 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::GetSelectedBluetoothDevice(..) => write!(f, "GetSelectedBluetoothDevice"), EmbedderMsg::SelectFiles(..) => write!(f, "SelectFiles"), + EmbedderMsg::PromptPermission(..) => write!(f, "PromptPermission"), EmbedderMsg::ShowIME(..) => write!(f, "ShowIME"), EmbedderMsg::HideIME => write!(f, "HideIME"), EmbedderMsg::Shutdown => write!(f, "Shutdown"), @@ -299,3 +303,10 @@ pub enum MediaSessionEvent { /// Indicates that the position state is set. SetPositionState(MediaPositionState), } + +// Status for prompting user for permission. +#[derive(Clone, Debug, Deserialize, Serialize)] +pub enum PermissionRequest { + Granted, + Denied, +} diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index 03eac6cae65..9c5995c1c89 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -29,9 +29,6 @@ phf_codegen = "0.8" phf_shared = "0.8" serde_json = "1.0" -[target.'cfg(target_os = "linux")'.dependencies] -tinyfiledialogs = "3.0" - [dependencies] accountable-refcell = {version = "0.2.0", optional = true} app_units = "0.7" diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index e631c9bfc9c..f46a07bbcb2 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -61,6 +61,7 @@ use crate::timers::{OneshotTimers, TimerCallback}; use content_security_policy::CspList; use devtools_traits::{PageError, ScriptToDevtoolsControlMsg}; use dom_struct::dom_struct; +use embedder_traits::EmbedderMsg; use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::router::ROUTER; use js::glue::{IsWrapper, UnwrapObjectDynamic}; @@ -1917,6 +1918,14 @@ impl GlobalScope { &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> { &self.scheduler_chan } diff --git a/components/script/dom/permissions.rs b/components/script/dom/permissions.rs index e31ce563262..e456571cbc3 100644 --- a/components/script/dom/permissions.rs +++ b/components/script/dom/permissions.rs @@ -19,15 +19,14 @@ use crate::dom::promise::Promise; use crate::realms::{AlreadyInRealm, InRealm}; use crate::script_runtime::JSContext; use dom_struct::dom_struct; +use embedder_traits::{EmbedderMsg, PermissionRequest}; +use ipc_channel::ipc; use js::conversions::ConversionResult; use js::jsapi::JSObject; use js::jsval::{ObjectValue, UndefinedValue}; use servo_config::pref; 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 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?"; @@ -258,14 +257,10 @@ impl PermissionAlgorithm for Permissions { PermissionState::Prompt => { 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) - let state = prompt_user( - &format!("{} {} ?", REQUEST_DIALOG_MESSAGE, perm_name.clone()), - globalscope.is_headless(), - ); - + let globalscope = GlobalScope::current().expect("No current global object"); + let prompt = format!("{} {} ?", REQUEST_DIALOG_MESSAGE, perm_name.clone()); + let state = prompt_user_from_embedder(prompt, &globalscope); globalscope .permission_state_invocation_results() .borrow_mut() @@ -289,7 +284,7 @@ pub fn get_descriptor_permission_state( env_settings_obj: Option<&GlobalScope>, ) -> PermissionState { // Step 1. - let settings = match env_settings_obj { + let globalscope = match env_settings_obj { Some(env_settings_obj) => DomRoot::from_ref(env_settings_obj), 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) { PermissionState::Granted } else { - settings + globalscope .permission_state_invocation_results() .borrow_mut() .remove(&permission_name.to_string()); - prompt_user( - &format!("The {} {}", permission_name, NONSECURE_DIALOG_MESSAGE), - settings.is_headless(), - ) + let prompt = format!("The {} {}", permission_name, NONSECURE_DIALOG_MESSAGE); + prompt_user_from_embedder(prompt, &globalscope) } }; // Step 3. - if let Some(prev_result) = settings + if let Some(prev_result) = globalscope .permission_state_invocation_results() .borrow() .get(&permission_name.to_string()) @@ -327,7 +320,7 @@ pub fn get_descriptor_permission_state( } // Store the invocation result - settings + globalscope .permission_state_invocation_results() .borrow_mut() .insert(permission_name.to_string(), state); @@ -336,28 +329,6 @@ pub fn get_descriptor_permission_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 fn allowed_in_nonsecure_contexts(permission_name: &PermissionName) -> bool { match *permission_name { @@ -385,3 +356,24 @@ fn allowed_in_nonsecure_contexts(permission_name: &PermissionName) -> bool { 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 + }, + } +} diff --git a/ports/glutin/browser.rs b/ports/glutin/browser.rs index 1b21bfebf5f..b250a38662a 100644 --- a/ports/glutin/browser.rs +++ b/ports/glutin/browser.rs @@ -7,7 +7,9 @@ use crate::window_trait::{WindowPortsMethods, LINE_HEIGHT}; use euclid::{Point2D, Vector2D}; use keyboard_types::{Key, KeyboardEvent, Modifiers, ShortcutMatcher}; 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::TraversalDirection; use servo::net_traits::pub_domains::is_reg_domain; @@ -491,6 +493,10 @@ where 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) => { debug!("ShowIME received"); }, @@ -514,6 +520,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")] fn platform_get_selected_devices(devices: Vec<String>) -> Option<String> { let picker_name = "Choose a device"; |