summaryrefslogtreecommitdiff
path: root/runtime/permissions/mod.rs
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2023-01-07 17:25:34 +0100
committerGitHub <noreply@github.com>2023-01-07 17:25:34 +0100
commitfac64478157ee563b185edb5734688e4523df3a1 (patch)
tree888d562982e1fc37dfb9a4459928bcec84d55dfc /runtime/permissions/mod.rs
parent82e930726ee5dbac8e6eae0962c07c72daf9843c (diff)
refactor(permissions): add PermissionsContainer struct for internal mutability (#17134)
Turns out we were cloning permissions which after prompting were discarded, so the state of permissions was never preserved. To handle that we need to store all permissions behind "Arc<Mutex<>>" (because there are situations where we need to send them to other thread). Testing and benching code still uses "Permissions" in most places - it's undesirable to share the same permission set between various test/bench files - otherwise granting or revoking permissions in one file would influence behavior of other test files.
Diffstat (limited to 'runtime/permissions/mod.rs')
-rw-r--r--runtime/permissions/mod.rs150
1 files changed, 131 insertions, 19 deletions
diff --git a/runtime/permissions/mod.rs b/runtime/permissions/mod.rs
index d2de1cc94..024aa81d9 100644
--- a/runtime/permissions/mod.rs
+++ b/runtime/permissions/mod.rs
@@ -6,6 +6,7 @@ use deno_core::error::custom_error;
use deno_core::error::type_error;
use deno_core::error::uri_error;
use deno_core::error::AnyError;
+use deno_core::parking_lot::Mutex;
use deno_core::serde::de;
use deno_core::serde::Deserialize;
use deno_core::serde::Deserializer;
@@ -22,6 +23,7 @@ use std::hash::Hash;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::string::ToString;
+use std::sync::Arc;
mod prompter;
use prompter::permission_prompt;
@@ -1614,97 +1616,207 @@ impl Permissions {
}
}
-impl deno_flash::FlashPermissions for Permissions {
+/// Wrapper struct for `Permissions` that can be shared across threads.
+///
+/// We need a way to have internal mutability for permissions as they might get
+/// passed to a future that will prompt the user for permission (and in such
+/// case might need to be mutated). Also for the Web Worker API we need a way
+/// to send permissions to a new thread.
+#[derive(Clone, Debug)]
+pub struct PermissionsContainer(pub Arc<Mutex<Permissions>>);
+
+impl PermissionsContainer {
+ pub fn new(perms: Permissions) -> Self {
+ Self(Arc::new(Mutex::new(perms)))
+ }
+
+ pub fn allow_all() -> Self {
+ Self::new(Permissions::allow_all())
+ }
+
+ #[inline(always)]
+ pub fn check_specifier(
+ &self,
+ specifier: &ModuleSpecifier,
+ ) -> Result<(), AnyError> {
+ self.0.lock().check_specifier(specifier)
+ }
+
+ #[inline(always)]
+ pub fn check_read(
+ &mut self,
+ path: &Path,
+ api_name: &str,
+ ) -> Result<(), AnyError> {
+ self.0.lock().read.check(path, Some(api_name))
+ }
+
+ #[inline(always)]
+ pub fn check_read_blind(
+ &mut self,
+ path: &Path,
+ display: &str,
+ api_name: &str,
+ ) -> Result<(), AnyError> {
+ self.0.lock().read.check_blind(path, display, api_name)
+ }
+
+ #[inline(always)]
+ pub fn check_read_all(&mut self, api_name: &str) -> Result<(), AnyError> {
+ self.0.lock().read.check_all(Some(api_name))
+ }
+
+ #[inline(always)]
+ pub fn check_write(
+ &mut self,
+ path: &Path,
+ api_name: &str,
+ ) -> Result<(), AnyError> {
+ self.0.lock().write.check(path, Some(api_name))
+ }
+
+ #[inline(always)]
+ pub fn check_write_all(&mut self, api_name: &str) -> Result<(), AnyError> {
+ self.0.lock().write.check_all(Some(api_name))
+ }
+
+ #[inline(always)]
+ pub fn check_run(
+ &mut self,
+ cmd: &str,
+ api_name: &str,
+ ) -> Result<(), AnyError> {
+ self.0.lock().run.check(cmd, Some(api_name))
+ }
+
+ #[inline(always)]
+ pub fn check_run_all(&mut self, api_name: &str) -> Result<(), AnyError> {
+ self.0.lock().run.check_all(Some(api_name))
+ }
+
+ #[inline(always)]
+ pub fn check_sys(
+ &mut self,
+ kind: &str,
+ api_name: &str,
+ ) -> Result<(), AnyError> {
+ self.0.lock().sys.check(kind, Some(api_name))
+ }
+
+ #[inline(always)]
+ pub fn check_env(&mut self, var: &str) -> Result<(), AnyError> {
+ self.0.lock().env.check(var)
+ }
+
+ #[inline(always)]
+ pub fn check_env_all(&mut self) -> Result<(), AnyError> {
+ self.0.lock().env.check_all()
+ }
+}
+
+impl deno_flash::FlashPermissions for PermissionsContainer {
+ #[inline(always)]
fn check_net<T: AsRef<str>>(
&mut self,
host: &(T, Option<u16>),
api_name: &str,
) -> Result<(), AnyError> {
- self.net.check(host, Some(api_name))
+ self.0.lock().net.check(host, Some(api_name))
}
}
-impl deno_node::NodePermissions for Permissions {
+impl deno_node::NodePermissions for PermissionsContainer {
+ #[inline(always)]
fn check_read(&mut self, path: &Path) -> Result<(), AnyError> {
- self.read.check(path, None)
+ self.0.lock().read.check(path, None)
}
}
-impl deno_net::NetPermissions for Permissions {
+impl deno_net::NetPermissions for PermissionsContainer {
+ #[inline(always)]
fn check_net<T: AsRef<str>>(
&mut self,
host: &(T, Option<u16>),
api_name: &str,
) -> Result<(), AnyError> {
- self.net.check(host, Some(api_name))
+ self.0.lock().net.check(host, Some(api_name))
}
+ #[inline(always)]
fn check_read(
&mut self,
path: &Path,
api_name: &str,
) -> Result<(), AnyError> {
- self.read.check(path, Some(api_name))
+ self.0.lock().read.check(path, Some(api_name))
}
+ #[inline(always)]
fn check_write(
&mut self,
path: &Path,
api_name: &str,
) -> Result<(), AnyError> {
- self.write.check(path, Some(api_name))
+ self.0.lock().write.check(path, Some(api_name))
}
}
-impl deno_fetch::FetchPermissions for Permissions {
+impl deno_fetch::FetchPermissions for PermissionsContainer {
+ #[inline(always)]
fn check_net_url(
&mut self,
url: &url::Url,
api_name: &str,
) -> Result<(), AnyError> {
- self.net.check_url(url, Some(api_name))
+ self.0.lock().net.check_url(url, Some(api_name))
}
+ #[inline(always)]
fn check_read(
&mut self,
path: &Path,
api_name: &str,
) -> Result<(), AnyError> {
- self.read.check(path, Some(api_name))
+ self.0.lock().read.check(path, Some(api_name))
}
}
-impl deno_web::TimersPermission for Permissions {
+impl deno_web::TimersPermission for PermissionsContainer {
+ #[inline(always)]
fn allow_hrtime(&mut self) -> bool {
- self.hrtime.check().is_ok()
+ self.0.lock().hrtime.check().is_ok()
}
+ #[inline(always)]
fn check_unstable(&self, state: &OpState, api_name: &'static str) {
crate::ops::check_unstable(state, api_name);
}
}
-impl deno_websocket::WebSocketPermissions for Permissions {
+impl deno_websocket::WebSocketPermissions for PermissionsContainer {
+ #[inline(always)]
fn check_net_url(
&mut self,
url: &url::Url,
api_name: &str,
) -> Result<(), AnyError> {
- self.net.check_url(url, Some(api_name))
+ self.0.lock().net.check_url(url, Some(api_name))
}
}
// NOTE(bartlomieju): for now, NAPI uses `--allow-ffi` flag, but that might
// change in the future.
-impl deno_napi::NapiPermissions for Permissions {
+impl deno_napi::NapiPermissions for PermissionsContainer {
+ #[inline(always)]
fn check(&mut self, path: Option<&Path>) -> Result<(), AnyError> {
- self.ffi.check(path)
+ self.0.lock().ffi.check(path)
}
}
-impl deno_ffi::FfiPermissions for Permissions {
+impl deno_ffi::FfiPermissions for PermissionsContainer {
+ #[inline(always)]
fn check(&mut self, path: Option<&Path>) -> Result<(), AnyError> {
- self.ffi.check(path)
+ self.0.lock().ffi.check(path)
}
}