diff --git a/components/embedder_traits/lib.rs b/components/embedder_traits/lib.rs index 71eb7876eca2..cacaf80ca50e 100644 --- a/components/embedder_traits/lib.rs +++ b/components/embedder_traits/lib.rs @@ -185,9 +185,8 @@ pub enum EmbedderMsg { GetSelectedBluetoothDevice(Vec, IpcSender>), /// Open file dialog to select files. Set boolean flag to true allows to select multiple files. SelectFiles(Vec, bool, IpcSender>>), - /// Open yes/no message for user to allow permission specified by first String. - /// With dialog title specified by second String. - PromptPermission(String, String, IpcSender), + /// Open interface to request permission specified by prompt. + PromptPermission(PermissionPrompt, IpcSender), /// 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. @@ -304,7 +303,30 @@ pub enum MediaSessionEvent { SetPositionState(MediaPositionState), } -// Status for prompting user for permission. +/// Enum with variants that match the DOM PermissionName enum +#[derive(Clone, Debug, Deserialize, Serialize)] +pub enum PermissionName { + Geolocation, + Notifications, + Push, + Midi, + Camera, + Microphone, + Speaker, + DeviceInfo, + BackgroundSync, + Bluetooth, + PersistentStorage, +} + +/// Information required to display a permission prompt +#[derive(Clone, Debug, Deserialize, Serialize)] +pub enum PermissionPrompt { + Insecure(PermissionName), + Request(PermissionName), +} + +/// Status for prompting user for permission. #[derive(Clone, Debug, Deserialize, Serialize)] pub enum PermissionRequest { Granted, diff --git a/components/script/dom/permissions.rs b/components/script/dom/permissions.rs index e456571cbc33..37887f607736 100644 --- a/components/script/dom/permissions.rs +++ b/components/script/dom/permissions.rs @@ -19,7 +19,7 @@ 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 embedder_traits::{self, EmbedderMsg, PermissionPrompt, PermissionRequest}; use ipc_channel::ipc; use js::conversions::ConversionResult; use js::jsapi::JSObject; @@ -27,11 +27,6 @@ use js::jsval::{ObjectValue, UndefinedValue}; use servo_config::pref; use std::rc::Rc; -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?"; -const REQUEST_DIALOG_MESSAGE: &'static str = "Do you want to grant permission for"; - pub trait PermissionAlgorithm { type Descriptor; type Status; @@ -256,10 +251,11 @@ impl PermissionAlgorithm for Permissions { // Step 3. PermissionState::Prompt => { let perm_name = status.get_query(); + let prompt = + PermissionPrompt::Request(embedder_traits::PermissionName::from(perm_name)); // https://w3c.github.io/permissions/#request-permission-to-use (Step 3 - 4) 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() @@ -305,8 +301,10 @@ pub fn get_descriptor_permission_state( .borrow_mut() .remove(&permission_name.to_string()); - let prompt = format!("The {} {}", permission_name, NONSECURE_DIALOG_MESSAGE); - prompt_user_from_embedder(prompt, &globalscope) + prompt_user_from_embedder( + PermissionPrompt::Insecure(embedder_traits::PermissionName::from(permission_name)), + &globalscope, + ) } }; @@ -357,13 +355,9 @@ fn allowed_in_nonsecure_contexts(permission_name: &PermissionName) -> bool { } } -fn prompt_user_from_embedder(prompt: String, gs: &GlobalScope) -> PermissionState { +fn prompt_user_from_embedder(prompt: PermissionPrompt, 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, - )); + gs.send_to_embedder(EmbedderMsg::PromptPermission(prompt, sender)); match receiver.recv() { Ok(PermissionRequest::Granted) => PermissionState::Granted, @@ -377,3 +371,23 @@ fn prompt_user_from_embedder(prompt: String, gs: &GlobalScope) -> PermissionStat }, } } + +impl From for embedder_traits::PermissionName { + fn from(permission_name: PermissionName) -> Self { + match permission_name { + PermissionName::Geolocation => embedder_traits::PermissionName::Geolocation, + PermissionName::Notifications => embedder_traits::PermissionName::Notifications, + PermissionName::Push => embedder_traits::PermissionName::Push, + PermissionName::Midi => embedder_traits::PermissionName::Midi, + PermissionName::Camera => embedder_traits::PermissionName::Camera, + PermissionName::Microphone => embedder_traits::PermissionName::Microphone, + PermissionName::Speaker => embedder_traits::PermissionName::Speaker, + PermissionName::Device_info => embedder_traits::PermissionName::DeviceInfo, + PermissionName::Background_sync => embedder_traits::PermissionName::BackgroundSync, + PermissionName::Bluetooth => embedder_traits::PermissionName::Bluetooth, + PermissionName::Persistent_storage => { + embedder_traits::PermissionName::PersistentStorage + }, + } + } +} diff --git a/ports/glutin/browser.rs b/ports/glutin/browser.rs index b250a38662ac..c46b0bd83378 100644 --- a/ports/glutin/browser.rs +++ b/ports/glutin/browser.rs @@ -9,6 +9,7 @@ use keyboard_types::{Key, KeyboardEvent, Modifiers, ShortcutMatcher}; use servo::compositing::windowing::{WebRenderDebugOption, WindowEvent}; use servo::embedder_traits::{ EmbedderMsg, FilterPattern, PermissionRequest, PromptDefinition, PromptOrigin, PromptResult, + PermissionPrompt, }; use servo::msg::constellation_msg::TopLevelBrowsingContextId as BrowserId; use servo::msg::constellation_msg::TraversalDirection; @@ -493,8 +494,8 @@ where self.event_queue.push(WindowEvent::SendError(None, reason)); }; }, - EmbedderMsg::PromptPermission(message, dialog_title, sender) => { - let permission_state = prompt_user(&message, &dialog_title); + EmbedderMsg::PromptPermission(prompt, sender) => { + let permission_state = prompt_user(prompt); let _ = sender.send(permission_state); } EmbedderMsg::ShowIME(_kind) => { @@ -520,13 +521,27 @@ where } #[cfg(target_os = "linux")] -fn prompt_user(prompt: &str, dialog_title: &str) -> PermissionRequest { +fn prompt_user(prompt: PermissionPrompt) -> PermissionRequest { if opts::get().headless { return PermissionRequest::Denied; } + + let message = match prompt { + PermissionPrompt::Request(permission_name) => { + format!("Do you want to grant permission for {:?}?", permission_name) + }, + PermissionPrompt::Insecure(permission_name) => { + format!( + "The {:?} 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?", + permission_name + ) + }, + }; + match tinyfiledialogs::message_box_yes_no( - dialog_title, - prompt, + "Permission request dialog", + &message, MessageBoxIcon::Question, YesNo::No, ) { @@ -536,7 +551,7 @@ fn prompt_user(prompt: &str, dialog_title: &str) -> PermissionRequest { } #[cfg(not(target_os = "linux"))] -fn prompt_user(_prompt: &str, _dialog_title: &str) -> PermissionRequest { +fn prompt_user(_prompt: PermissionPrompt) -> PermissionRequest { // TODO popup only supported on linux PermissionRequest::Denied }