Skip to content

Commit

Permalink
feat(core): simplify scope definition for sidecars (#3574)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasfernog committed Mar 2, 2022
1 parent 91ec876 commit 9b3b163
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 37 deletions.
5 changes: 5 additions & 0 deletions .changes/sidecar-scope-improvement.md
@@ -0,0 +1,5 @@
---
"tauri": patch
---

The `cmd` field is no longer required on the shell scope for sidecars.
35 changes: 34 additions & 1 deletion core/tauri-utils/src/config.rs
Expand Up @@ -877,7 +877,7 @@ impl Allowlist for WindowAllowlistConfig {
}

/// A command allowed to be executed by the webview API.
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[derive(Debug, PartialEq, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
pub struct ShellAllowedCommand {
/// The name for this allowed shell command configuration.
Expand All @@ -903,6 +903,39 @@ pub struct ShellAllowedCommand {
pub sidecar: bool,
}

impl<'de> Deserialize<'de> for ShellAllowedCommand {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
struct InnerShellAllowedCommand {
name: String,
#[serde(rename = "cmd")]
command: Option<PathBuf>,
#[serde(default)]
args: ShellAllowedArgs,
#[serde(default)]
sidecar: bool,
}

let config = InnerShellAllowedCommand::deserialize(deserializer)?;

if !config.sidecar && config.command.is_none() {
return Err(DeError::custom(
"The shell scope `command` value is required.",
));
}

Ok(ShellAllowedCommand {
name: config.name,
command: config.command.unwrap_or_default(),
args: config.args,
sidecar: config.sidecar,
})
}
}

/// A set of command arguments allowed to be executed by the webview API.
///
/// A value of `true` will allow any arguments to be passed to the command. `false` will disable all
Expand Down
10 changes: 5 additions & 5 deletions core/tauri/src/endpoints/shell.rs
Expand Up @@ -97,7 +97,7 @@ impl Cmd {
let program = PathBuf::from(program);
let program_as_string = program.display().to_string();
let program_no_ext_as_string = program.with_extension("").display().to_string();
let is_configured = context
let configured_sidecar = context
.config
.tauri
.bundle
Expand All @@ -106,15 +106,15 @@ impl Cmd {
.map(|bins| {
bins
.iter()
.any(|b| b == &program_as_string || b == &program_no_ext_as_string)
.find(|b| b == &&program_as_string || b == &&program_no_ext_as_string)
})
.unwrap_or_default();
if is_configured {
if let Some(sidecar) = configured_sidecar {
context
.window
.state::<Scopes>()
.shell
.prepare(&program.to_string_lossy(), args, true)
.prepare_sidecar(&program.to_string_lossy(), sidecar, args)
.map_err(crate::error::into_anyhow)?
} else {
return Err(crate::Error::SidecarNotAllowed(program).into_anyhow());
Expand All @@ -128,7 +128,7 @@ impl Cmd {
.window
.state::<Scopes>()
.shell
.prepare(&program, args, false)
.prepare(&program, args)
{
Ok(cmd) => cmd,
Err(e) => {
Expand Down
35 changes: 31 additions & 4 deletions core/tauri/src/scope/shell.rs
Expand Up @@ -197,20 +197,37 @@ impl Scope {
Self(scope)
}

/// Validates argument inputs and creates a Tauri sidecar [`Command`].
#[cfg(shell_sidecar)]
pub fn prepare_sidecar(
&self,
command_name: &str,
command_script: &str,
args: ExecuteArgs,
) -> Result<Command, ScopeError> {
self._prepare(command_name, args, Some(command_script))
}

/// Validates argument inputs and creates a Tauri [`Command`].
#[cfg(shell_execute)]
pub fn prepare(&self, command_name: &str, args: ExecuteArgs) -> Result<Command, ScopeError> {
self._prepare(command_name, args, None)
}

/// Validates argument inputs and creates a Tauri [`Command`].
#[cfg(any(shell_execute, shell_sidecar))]
pub fn prepare(
pub fn _prepare(
&self,
command_name: &str,
args: ExecuteArgs,
sidecar: bool,
sidecar: Option<&str>,
) -> Result<Command, ScopeError> {
let command = match self.0.scopes.get(command_name) {
Some(command) => command,
None => return Err(ScopeError::NotFound(command_name.into())),
};

if command.sidecar != sidecar {
if command.sidecar != sidecar.is_some() {
return Err(ScopeError::BadSidecarFlag);
}

Expand Down Expand Up @@ -250,7 +267,17 @@ impl Scope {
(Some(_), _) => Err(ScopeError::InvalidInput(command_name.into())),
}?;

let command_s = command.command.to_string_lossy();
let command_s = sidecar
.map(|s| {
std::path::PathBuf::from(s)
.components()
.last()
.unwrap()
.as_os_str()
.to_string_lossy()
.into_owned()
})
.unwrap_or_else(|| command.command.to_string_lossy().into_owned());
let command = if command.sidecar {
Command::new_sidecar(command_s).map_err(ScopeError::Sidecar)?
} else {
Expand Down
62 changes: 45 additions & 17 deletions examples/sidecar/index.html
@@ -1,21 +1,49 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Sidecar</title>
</head>

<body>
<div></div>
<script>
const div = document.querySelector('div')
window.__TAURI__.event.listen('message', (event) => {
const p = document.createElement('p')
p.innerText = event.payload
div.appendChild(p)
})
</script>
</body>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Sidecar</title>
<style>
.container {
display: flex;
}
.container > div {
flex: 1;
}
</style>
</head>

<body>
<div class="container">
<div id="backend"></div>
<div id="frontend"></div>
</div>
<script>
function addMessage(div, message) {
const p = document.createElement('p')
p.innerText = message
div.appendChild(p)
}

const backendDiv = document.getElementById('backend')
window.__TAURI__.event.listen('message', (event) => {
addMessage(backendDiv, event.payload)
})

const frontendDiv = document.getElementById('frontend')
const { Command } = window.__TAURI__.shell
const command = Command.sidecar('binaries/app')
command.on('close', data => {
addMessage(frontendDiv, `command finished with code ${data.code} and signal ${data.signal}`)
})
command.on('error', error => addMessage(frontendDiv, `command error: "${error}"`))
command.stdout.on('data', line => addMessage(frontendDiv, `command stdout: "${line}"`))
command.stderr.on('data', line => addMessage(frontendDiv, `command stderr: "${line}"`))
command.spawn()
</script>
</body>

</html>
15 changes: 8 additions & 7 deletions examples/sidecar/src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/sidecar/src-tauri/Cargo.toml
Expand Up @@ -11,7 +11,7 @@ tauri-build = { path = "../../../core/tauri-build", features = ["codegen"] }
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = [ "derive" ] }
tauri = { path = "../../../core/tauri", features = ["shell-execute"] }
tauri = { path = "../../../core/tauri", features = ["shell-sidecar"] }

[features]
default = [ "custom-protocol" ]
Expand Down
8 changes: 7 additions & 1 deletion examples/sidecar/src-tauri/tauri.conf.json
Expand Up @@ -38,7 +38,13 @@
"allowlist": {
"all": false,
"shell": {
"execute": true
"sidecar": true,
"scope": [
{
"name": "binaries/app",
"sidecar": true
}
]
}
},
"windows": [
Expand Down
2 changes: 1 addition & 1 deletion tooling/api/src/shell.ts
Expand Up @@ -42,7 +42,7 @@
*
* - `name`: the unique identifier of the command, passed to the [[Command.constructor | Command constructor]].
* If it's a sidecar, this must be the value defined on `tauri.conf.json > tauri > bundle > externalBin`.
* - `cmd`: the program that is executed on this configuration. If it's a sidecar, it must be the same as `name`.
* - `cmd`: the program that is executed on this configuration. If it's a sidecar, this value is ignored.
* - `sidecar`: whether the object configures a sidecar or a system program.
* - `args`: the arguments that can be passed to the program. By default no arguments are allowed.
* - `true` means that any argument list is allowed.
Expand Down

0 comments on commit 9b3b163

Please sign in to comment.