feat: add content protection api, closes #5132 (#5513)

Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
This commit is contained in:
Amr Bashir 2022-12-13 06:04:22 +02:00 committed by GitHub
parent 233e43b0c3
commit 4ab5545b7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 203 additions and 39 deletions

View File

@ -0,0 +1,5 @@
---
"api": "minor"
---
Added the `WindowOptions::contentProtected` option and `WebviewWindow#setContentProtected` to change it at runtime.

View File

@ -0,0 +1,5 @@
---
"tauri-utils": "patch"
---
Added the `content_protected` option to the window configuration.

View File

@ -0,0 +1,7 @@
---
"tauri": "minor"
"tauri-runtime": "minor"
"tauri-runtime-wry": "minor"
---
Added the `content_protected` option when creating a window and `Window::set_content_protected` to change it at runtime.

View File

@ -105,6 +105,7 @@
"print": false,
"requestUserAttention": false,
"setAlwaysOnTop": false,
"setContentProtected": false,
"setCursorGrab": false,
"setCursorIcon": false,
"setCursorPosition": false,
@ -378,6 +379,7 @@
"print": false,
"requestUserAttention": false,
"setAlwaysOnTop": false,
"setContentProtected": false,
"setCursorGrab": false,
"setCursorIcon": false,
"setCursorPosition": false,
@ -641,6 +643,11 @@
"default": false,
"type": "boolean"
},
"contentProtected": {
"description": "Prevents the window contents from being captured by other apps.",
"default": false,
"type": "boolean"
},
"skipTaskbar": {
"description": "If `true`, hides the window icon from the taskbar on Windows and Linux.",
"default": false,
@ -1661,6 +1668,7 @@
"print": false,
"requestUserAttention": false,
"setAlwaysOnTop": false,
"setContentProtected": false,
"setCursorGrab": false,
"setCursorIcon": false,
"setCursorPosition": false,
@ -2011,6 +2019,11 @@
"default": false,
"type": "boolean"
},
"setContentProtected": {
"description": "Allows preventing the window contents from being captured by other apps.",
"default": false,
"type": "boolean"
},
"setSize": {
"description": "Allows setting the window size.",
"default": false,

View File

@ -705,6 +705,7 @@ impl WindowBuilder for WindowBuilderWrapper {
.decorations(config.decorations)
.maximized(config.maximized)
.always_on_top(config.always_on_top)
.content_protected(config.content_protected)
.skip_taskbar(config.skip_taskbar)
.theme(config.theme);
@ -839,6 +840,11 @@ impl WindowBuilder for WindowBuilderWrapper {
self
}
fn content_protected(mut self, protected: bool) -> Self {
self.inner = self.inner.with_content_protection(protected);
self
}
#[cfg(windows)]
fn parent_window(mut self, parent: HWND) -> Self {
self.inner = self.inner.with_parent_window(parent);
@ -1059,6 +1065,7 @@ pub enum WindowMessage {
Close,
SetDecorations(bool),
SetAlwaysOnTop(bool),
SetContentProtected(bool),
SetSize(Size),
SetMinSize(Option<Size>),
SetMaxSize(Option<Size>),
@ -1436,6 +1443,16 @@ impl<T: UserEvent> Dispatch<T> for WryDispatcher<T> {
)
}
fn set_content_protected(&self, protected: bool) -> Result<()> {
send_user_message(
&self.context,
Message::Window(
self.window_id,
WindowMessage::SetContentProtected(protected),
),
)
}
fn set_size(&self, size: Size) -> Result<()> {
send_user_message(
&self.context,
@ -2399,6 +2416,9 @@ fn handle_user_message<T: UserEvent>(
}
WindowMessage::SetDecorations(decorations) => window.set_decorations(decorations),
WindowMessage::SetAlwaysOnTop(always_on_top) => window.set_always_on_top(always_on_top),
WindowMessage::SetContentProtected(protected) => {
window.set_content_protection(protected)
}
WindowMessage::SetSize(size) => {
window.set_inner_size(SizeWrapper::from(size).0);
}

View File

@ -628,6 +628,9 @@ pub trait Dispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 'static
/// Updates the window alwaysOnTop flag.
fn set_always_on_top(&self, always_on_top: bool) -> Result<()>;
/// Prevents the window contents from being captured by other apps.
fn set_content_protected(&self, protected: bool) -> Result<()>;
/// Resizes the window.
fn set_size(&self, size: Size) -> Result<()>;

View File

@ -172,6 +172,10 @@ pub trait WindowBuilder: WindowBuilderBase {
#[must_use]
fn always_on_top(self, always_on_top: bool) -> Self;
/// Prevents the window contents from being captured by other apps.
#[must_use]
fn content_protected(self, protected: bool) -> Self;
/// Sets the window icon.
fn icon(self, icon: Icon) -> crate::Result<Self>;

View File

@ -859,6 +859,9 @@ pub struct WindowConfig {
/// Whether the window should always be on top of other windows.
#[serde(default, alias = "always-on-top")]
pub always_on_top: bool,
/// Prevents the window contents from being captured by other apps.
#[serde(default, alias = "content-protected")]
pub content_protected: bool,
/// If `true`, hides the window icon from the taskbar on Windows and Linux.
#[serde(default, alias = "skip-taskbar")]
pub skip_taskbar: bool,
@ -908,6 +911,7 @@ impl Default for WindowConfig {
visible: default_visible(),
decorations: default_decorations(),
always_on_top: false,
content_protected: false,
skip_taskbar: false,
theme: None,
title_bar_style: Default::default(),
@ -1329,6 +1333,9 @@ pub struct WindowAllowlistConfig {
/// Allows setting the always_on_top flag of the window.
#[serde(default, alias = "set-always-on-top")]
pub set_always_on_top: bool,
/// Allows preventing the window contents from being captured by other apps.
#[serde(default, alias = "set-content-protected")]
pub set_content_protected: bool,
/// Allows setting the window size.
#[serde(default, alias = "set-size")]
pub set_size: bool,
@ -1394,6 +1401,7 @@ impl Allowlist for WindowAllowlistConfig {
close: true,
set_decorations: true,
set_always_on_top: true,
set_content_protected: false,
set_size: true,
set_min_size: true,
set_max_size: true,
@ -1444,6 +1452,12 @@ impl Allowlist for WindowAllowlistConfig {
set_always_on_top,
"window-set-always-on-top"
);
check_feature!(
self,
features,
set_content_protected,
"window-set-content-protected"
);
check_feature!(self, features, set_size, "window-set-size");
check_feature!(self, features, set_min_size, "window-set-min-size");
check_feature!(self, features, set_max_size, "window-set-max-size");
@ -3040,6 +3054,7 @@ mod build {
let visible = self.visible;
let decorations = self.decorations;
let always_on_top = self.always_on_top;
let content_protected = self.content_protected;
let skip_taskbar = self.skip_taskbar;
let theme = opt_lit(self.theme.as_ref());
let title_bar_style = &self.title_bar_style;
@ -3072,6 +3087,7 @@ mod build {
visible,
decorations,
always_on_top,
content_protected,
skip_taskbar,
theme,
title_bar_style,

View File

@ -240,6 +240,7 @@ window-all = [
"window-close",
"window-set-decorations",
"window-set-always-on-top",
"window-set-content-protected",
"window-set-size",
"window-set-min-size",
"window-set-max-size",
@ -270,6 +271,7 @@ window-hide = [ ]
window-close = [ ]
window-set-decorations = [ ]
window-set-always-on-top = [ ]
window-set-content-protected = [ ]
window-set-size = [ ]
window-set-min-size = [ ]
window-set-max-size = [ ]

View File

@ -81,6 +81,7 @@ fn main() {
"close",
"set-decorations",
"set-always-on-top",
"set-content-protected",
"set-size",
"set-min-size",
"set-max-size",

File diff suppressed because one or more lines are too long

View File

@ -103,6 +103,8 @@ pub enum WindowManagerCmd {
#[cfg(window_set_always_on_top)]
#[serde(rename_all = "camelCase")]
SetAlwaysOnTop(bool),
#[cfg(window_set_content_protected)]
SetContentProtected(bool),
#[cfg(window_set_size)]
SetSize(Size),
#[cfg(window_set_min_size)]
@ -164,6 +166,9 @@ pub fn into_allowlist_error(variant: &str) -> crate::Error {
"close" => crate::Error::ApiNotAllowlisted("window > close".to_string()),
"setDecorations" => crate::Error::ApiNotAllowlisted("window > setDecorations".to_string()),
"setAlwaysOnTop" => crate::Error::ApiNotAllowlisted("window > setAlwaysOnTop".to_string()),
"setContentProtected" => {
crate::Error::ApiNotAllowlisted("window > setContentProtected".to_string())
}
"setSize" => crate::Error::ApiNotAllowlisted("window > setSize".to_string()),
"setMinSize" => crate::Error::ApiNotAllowlisted("window > setMinSize".to_string()),
"setMaxSize" => crate::Error::ApiNotAllowlisted("window > setMaxSize".to_string()),
@ -299,6 +304,10 @@ impl Cmd {
WindowManagerCmd::SetDecorations(decorations) => window.set_decorations(decorations)?,
#[cfg(window_set_always_on_top)]
WindowManagerCmd::SetAlwaysOnTop(always_on_top) => window.set_always_on_top(always_on_top)?,
#[cfg(window_set_content_protected)]
WindowManagerCmd::SetContentProtected(protected) => {
window.set_content_protected(protected)?
}
#[cfg(window_set_size)]
WindowManagerCmd::SetSize(size) => window.set_size(size)?,
#[cfg(window_set_min_size)]

View File

@ -134,6 +134,7 @@
//! - **window-close**: Enables the [`close` API](https://tauri.app/en/docs/api/js/classes/window.WebviewWindow#close).
//! - **window-set-decorations**: Enables the [`setDecorations` API](https://tauri.app/en/docs/api/js/classes/window.WebviewWindow#setdecorations).
//! - **window-set-always-on-top**: Enables the [`setAlwaysOnTop` API](https://tauri.app/en/docs/api/js/classes/window.WebviewWindow#setalwaysontop).
//! - **window-set-content-protected**: Enables the [`setContentProtected` API](https://tauri.app/en/docs/api/js/classes/window.WebviewWindow#setcontentprotected).
//! - **window-set-size**: Enables the [`setSize` API](https://tauri.app/en/docs/api/js/classes/window.WebviewWindow#setsize).
//! - **window-set-min-size**: Enables the [`setMinSize` API](https://tauri.app/en/docs/api/js/classes/window.WebviewWindow#setminsize).
//! - **window-set-max-size**: Enables the [`setMaxSize` API](https://tauri.app/en/docs/api/js/classes/window.WebviewWindow#setmaxsize).

View File

@ -250,6 +250,10 @@ impl WindowBuilder for MockWindowBuilder {
self
}
fn content_protected(self, protected: bool) -> Self {
self
}
fn icon(self, icon: Icon) -> Result<Self> {
Ok(self)
}
@ -489,6 +493,10 @@ impl<T: UserEvent> Dispatch<T> for MockDispatcher {
Ok(())
}
fn set_content_protected(&self, protected: bool) -> Result<()> {
Ok(())
}
fn set_size(&self, size: Size) -> Result<()> {
Ok(())
}

View File

@ -398,6 +398,13 @@ impl<'a, R: Runtime> WindowBuilder<'a, R> {
self
}
/// Whether the window should always be on top of other windows.
#[must_use]
pub fn content_protected(mut self, protected: bool) -> Self {
self.window_builder = self.window_builder.content_protected(protected);
self
}
/// Sets the window icon.
pub fn icon(mut self, icon: Icon) -> crate::Result<Self> {
self.window_builder = self.window_builder.icon(icon.try_into()?)?;
@ -1125,6 +1132,15 @@ impl<R: Runtime> Window<R> {
.map_err(Into::into)
}
/// Prevents the window contents from being captured by other apps.
pub fn set_content_protected(&self, protected: bool) -> crate::Result<()> {
self
.window
.dispatcher
.set_content_protected(protected)
.map_err(Into::into)
}
/// Resizes this window.
pub fn set_size<S: Into<Size>>(&self, size: S) -> crate::Result<()> {
self

File diff suppressed because one or more lines are too long

View File

@ -65,7 +65,8 @@ impl AppBuilder {
.user_agent("Tauri API")
.title("Tauri API Validation")
.inner_size(1000., 800.)
.min_inner_size(600., 400.);
.min_inner_size(600., 400.)
.content_protected(true);
#[cfg(target_os = "windows")]
{

View File

@ -66,6 +66,7 @@
let maximized = false
let decorations = true
let alwaysOnTop = false
let contentProtected = true
let fullscreen = false
let width = null
let height = null
@ -182,6 +183,7 @@
: windowMap[selectedWindow]?.unmaximize()
$: windowMap[selectedWindow]?.setDecorations(decorations)
$: windowMap[selectedWindow]?.setAlwaysOnTop(alwaysOnTop)
$: windowMap[selectedWindow]?.setContentProtected(contentProtected)
$: windowMap[selectedWindow]?.setFullscreen(fullscreen)
$: width &&
@ -286,6 +288,10 @@
Always on top
<input type="checkbox" bind:checked={alwaysOnTop} />
</label>
<label>
Content protected
<input type="checkbox" bind:checked={contentProtected} />
</label>
<label>
Fullscreen
<input type="checkbox" bind:checked={fullscreen} />

View File

@ -28,6 +28,7 @@
* "close": true,
* "setDecorations": true,
* "setAlwaysOnTop": true,
* "setContentProtected": true,
* "setSize": true,
* "setMinSize": true,
* "setMaxSize": true,
@ -1142,6 +1143,34 @@ class WindowManager extends WebviewWindowHandle {
})
}
/**
* Prevents the window contents from being captured by other apps.
* @example
* ```typescript
* import { appWindow } from '@tauri-apps/api/window';
* await appWindow.setContentProtected(true);
* ```
*
* @returns A promise indicating the success or failure of the operation.
*
* @since 1.2.0
*/
async setContentProtected(protected_: boolean): Promise<void> {
return invokeTauriCommand({
__tauriModule: 'Window',
message: {
cmd: 'manage',
data: {
label: this.label,
cmd: {
type: 'setContentProtected',
payload: protected_
}
}
}
})
}
/**
* Resizes the window with a new inner size.
* @example
@ -2073,6 +2102,10 @@ interface WindowOptions {
decorations?: boolean
/** Whether the window should always be on top of other windows or not. */
alwaysOnTop?: boolean
/** Prevents the window contents from being captured by other apps. */
contentProtected?: boolean
/** Prevents the window contents from being captured by other apps. */
contentPortected?: boolean
/** Whether or not the window icon should be added to the taskbar. */
skipTaskbar?: boolean
/**

View File

@ -105,6 +105,7 @@
"print": false,
"requestUserAttention": false,
"setAlwaysOnTop": false,
"setContentProtected": false,
"setCursorGrab": false,
"setCursorIcon": false,
"setCursorPosition": false,
@ -378,6 +379,7 @@
"print": false,
"requestUserAttention": false,
"setAlwaysOnTop": false,
"setContentProtected": false,
"setCursorGrab": false,
"setCursorIcon": false,
"setCursorPosition": false,
@ -641,6 +643,11 @@
"default": false,
"type": "boolean"
},
"contentProtected": {
"description": "Prevents the window contents from being captured by other apps.",
"default": false,
"type": "boolean"
},
"skipTaskbar": {
"description": "If `true`, hides the window icon from the taskbar on Windows and Linux.",
"default": false,
@ -1661,6 +1668,7 @@
"print": false,
"requestUserAttention": false,
"setAlwaysOnTop": false,
"setContentProtected": false,
"setCursorGrab": false,
"setCursorIcon": false,
"setCursorPosition": false,
@ -2011,6 +2019,11 @@
"default": false,
"type": "boolean"
},
"setContentProtected": {
"description": "Allows preventing the window contents from being captured by other apps.",
"default": false,
"type": "boolean"
},
"setSize": {
"description": "Allows setting the window size.",
"default": false,