mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-08-15 19:00:35 +03:00
Isolation Pattern (#43)
Co-authored-by: Ngo Iok Ui (Wu Yu Wei) <wusyong9104@gmail.com> Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.studio>
This commit is contained in:
parent
c077f44927
commit
d5d6d2abc1
7
.changes/isolation-pattern.md
Normal file
7
.changes/isolation-pattern.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
"tauri": patch
|
||||
"tauri-utils": patch
|
||||
"tauri-codegen": patch
|
||||
---
|
||||
|
||||
Added the `isolation` pattern.
|
5
.changes/rust-1.57.md
Normal file
5
.changes/rust-1.57.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri": patch
|
||||
---
|
||||
|
||||
The minimum Rust version is now 1.57.
|
@ -14,7 +14,8 @@ exclude = [
|
||||
"examples/api/src-tauri",
|
||||
"examples/updater/src-tauri",
|
||||
"examples/resources/src-tauri",
|
||||
"examples/sidecar/src-tauri"
|
||||
"examples/sidecar/src-tauri",
|
||||
"examples/isolation/src-tauri"
|
||||
]
|
||||
|
||||
# default to small, optimized workspace release binaries
|
||||
|
@ -8,7 +8,7 @@ homepage = "https://tauri.studio"
|
||||
repository = "https://github.com/tauri-apps/tauri/tree/dev/core/tauri-build"
|
||||
description = "build time code to pair with https://crates.io/crates/tauri"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
exclude = [ ".license_template", "CHANGELOG.md", "/target" ]
|
||||
readme = "README.md"
|
||||
|
||||
@ -29,3 +29,4 @@ winres = "0.1"
|
||||
|
||||
[features]
|
||||
codegen = [ "tauri-codegen", "quote" ]
|
||||
isolation = ["tauri-codegen/isolation", "tauri-utils/isolation"]
|
||||
|
@ -42,6 +42,7 @@ impl CodegenContext {
|
||||
/// This defaults to a file called `tauri.conf.json` inside of the current working directory of
|
||||
/// the package compiling; does not need to be set manually if that config file is in the same
|
||||
/// directory as your `Cargo.toml`.
|
||||
#[must_use]
|
||||
pub fn config_path(mut self, config_path: impl Into<PathBuf>) -> Self {
|
||||
self.config_path = config_path.into();
|
||||
self
|
||||
@ -58,6 +59,7 @@ impl CodegenContext {
|
||||
/// Defaults to `tauri-build-context.rs`.
|
||||
///
|
||||
/// [`tauri::include_codegen_context!`]: https://docs.rs/tauri/0.12/tauri/macro.include_codegen_context.html
|
||||
#[must_use]
|
||||
pub fn out_file(mut self, filename: PathBuf) -> Self {
|
||||
self.out_file = filename;
|
||||
self
|
||||
@ -65,6 +67,7 @@ impl CodegenContext {
|
||||
|
||||
/// Run the codegen in a `dev` context, meaning that Tauri is using a dev server or local file for development purposes,
|
||||
/// usually with the `tauri dev` CLI command.
|
||||
#[must_use]
|
||||
pub fn dev(mut self) -> Self {
|
||||
self.dev = true;
|
||||
self
|
||||
|
@ -43,6 +43,7 @@ impl WindowsAttributes {
|
||||
|
||||
/// Sets the icon to use on the window. Currently only used on Windows.
|
||||
/// It must be in `ico` format. Defaults to `icons/icon.ico`.
|
||||
#[must_use]
|
||||
pub fn window_icon_path<P: AsRef<Path>>(mut self, window_icon_path: P) -> Self {
|
||||
self.window_icon_path = window_icon_path.as_ref().into();
|
||||
self
|
||||
@ -50,6 +51,7 @@ impl WindowsAttributes {
|
||||
|
||||
/// Sets the sdk dir for windows. Currently only used on Windows. This must be a vaild UTF-8
|
||||
/// path. Defaults to whatever the `winres` crate determines is best.
|
||||
#[must_use]
|
||||
pub fn sdk_dir<P: AsRef<Path>>(mut self, sdk_dir: P) -> Self {
|
||||
self.sdk_dir = Some(sdk_dir.as_ref().into());
|
||||
self
|
||||
@ -70,6 +72,7 @@ impl Attributes {
|
||||
}
|
||||
|
||||
/// Sets the icon to use on the window. Currently only used on Windows.
|
||||
#[must_use]
|
||||
pub fn windows_attributes(mut self, windows_attributes: WindowsAttributes) -> Self {
|
||||
self.windows_attributes = windows_attributes;
|
||||
self
|
||||
|
@ -8,7 +8,7 @@ homepage = "https://tauri.studio"
|
||||
repository = "https://github.com/tauri-apps/tauri/tree/dev/core/tauri-codegen"
|
||||
description = "code generation meant to be consumed inside of `tauri` through `tauri-build` or `tauri-macros`"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
exclude = [ ".license_template", "CHANGELOG.md", "/target" ]
|
||||
readme = "README.md"
|
||||
|
||||
@ -25,7 +25,9 @@ thiserror = "1"
|
||||
walkdir = "2"
|
||||
zstd = { version = "0.9", optional = true }
|
||||
regex = "1"
|
||||
uuid = { version = "0.8", features = [ "v4" ] }
|
||||
|
||||
[features]
|
||||
default = [ "compression" ]
|
||||
compression = [ "zstd", "tauri-utils/compression" ]
|
||||
isolation = ["tauri-utils/isolation"]
|
||||
|
@ -2,11 +2,18 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use crate::embedded_assets::{AssetOptions, EmbeddedAssets, EmbeddedAssetsError};
|
||||
use std::ffi::OsStr;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use std::path::{Path, PathBuf};
|
||||
use tauri_utils::config::{AppUrl, Config, WindowUrl};
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
use tauri_utils::assets::AssetKey;
|
||||
use tauri_utils::config::{AppUrl, Config, PatternKind, WindowUrl};
|
||||
use tauri_utils::html::{inject_nonce_token, parse as parse_html, NodeRef, PatternObject};
|
||||
|
||||
use crate::embedded_assets::{AssetOptions, CspHashes, EmbeddedAssets, EmbeddedAssetsError};
|
||||
|
||||
/// Necessary data needed by [`context_codegen`] to generate code for a Tauri application context.
|
||||
pub struct ContextData {
|
||||
@ -16,6 +23,81 @@ pub struct ContextData {
|
||||
pub root: TokenStream,
|
||||
}
|
||||
|
||||
fn load_csp(document: &mut NodeRef, key: &AssetKey, csp_hashes: &mut CspHashes) {
|
||||
#[cfg(target_os = "linux")]
|
||||
::tauri_utils::html::inject_csp_token(document);
|
||||
inject_nonce_token(document);
|
||||
if let Ok(inline_script_elements) = document.select("script:not(empty)") {
|
||||
let mut scripts = Vec::new();
|
||||
for inline_script_el in inline_script_elements {
|
||||
let script = inline_script_el.as_node().text_contents();
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(&script);
|
||||
let hash = hasher.finalize();
|
||||
scripts.push(format!("'sha256-{}'", base64::encode(&hash)));
|
||||
}
|
||||
csp_hashes
|
||||
.inline_scripts
|
||||
.entry(key.clone().into())
|
||||
.or_default()
|
||||
.append(&mut scripts);
|
||||
}
|
||||
}
|
||||
|
||||
fn map_core_assets(
|
||||
options: &AssetOptions,
|
||||
) -> impl Fn(&AssetKey, &Path, &mut Vec<u8>, &mut CspHashes) -> Result<(), EmbeddedAssetsError> {
|
||||
#[allow(unused_variables)]
|
||||
let pattern = PatternObject::from(&options.pattern);
|
||||
let csp = options.csp;
|
||||
move |key, path, input, csp_hashes| {
|
||||
if path.extension() == Some(OsStr::new("html")) {
|
||||
let mut document = parse_html(String::from_utf8_lossy(input).into_owned());
|
||||
|
||||
if csp {
|
||||
load_csp(&mut document, key, csp_hashes);
|
||||
|
||||
#[cfg(feature = "isolation")]
|
||||
if let PatternObject::Isolation { .. } = &pattern {
|
||||
// create the csp for the isolation iframe styling now, to make the runtime less complex
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(tauri_utils::pattern::isolation::IFRAME_STYLE);
|
||||
let hash = hasher.finalize();
|
||||
csp_hashes
|
||||
.styles
|
||||
.push(format!("'sha256-{}'", base64::encode(&hash)));
|
||||
}
|
||||
}
|
||||
|
||||
*input = document.to_string().as_bytes().to_vec();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "isolation")]
|
||||
fn map_isolation(
|
||||
_options: &AssetOptions,
|
||||
dir: PathBuf,
|
||||
) -> impl Fn(&AssetKey, &Path, &mut Vec<u8>, &mut CspHashes) -> Result<(), EmbeddedAssetsError> {
|
||||
move |_key, path, input, _csp_hashes| {
|
||||
if path.extension() == Some(OsStr::new("html")) {
|
||||
let mut isolation_html =
|
||||
tauri_utils::html::parse(String::from_utf8_lossy(input).into_owned());
|
||||
|
||||
// this is appended, so no need to reverse order it
|
||||
tauri_utils::html::inject_codegen_isolation_script(&mut isolation_html);
|
||||
|
||||
// temporary workaround for windows not loading assets
|
||||
tauri_utils::html::inline_isolation(&mut isolation_html, &dir);
|
||||
|
||||
*input = isolation_html.to_string().as_bytes().to_vec()
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Build a `tauri::Context` for including in application code.
|
||||
pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsError> {
|
||||
let ContextData {
|
||||
@ -25,7 +107,8 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
|
||||
root,
|
||||
} = data;
|
||||
|
||||
let mut options = AssetOptions::new();
|
||||
let mut options = AssetOptions::new(config.tauri.pattern.clone())
|
||||
.freeze_prototype(config.tauri.security.freeze_prototype);
|
||||
let csp = if dev {
|
||||
config
|
||||
.tauri
|
||||
@ -64,7 +147,7 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
|
||||
path
|
||||
)
|
||||
}
|
||||
EmbeddedAssets::new(assets_path, options)?
|
||||
EmbeddedAssets::new(assets_path, map_core_assets(&options))?
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
@ -73,7 +156,7 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
|
||||
.iter()
|
||||
.map(|p| config_parent.join(p))
|
||||
.collect::<Vec<_>>(),
|
||||
options,
|
||||
map_core_assets(&options),
|
||||
)?,
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
@ -180,7 +263,31 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let info_plist = quote!(());
|
||||
|
||||
// double braces are purposeful to force the code into a block expression
|
||||
let pattern = match &options.pattern {
|
||||
PatternKind::Brownfield => quote!(#root::Pattern::Brownfield(std::marker::PhantomData)),
|
||||
#[cfg(feature = "isolation")]
|
||||
PatternKind::Isolation { dir } => {
|
||||
let dir = config_parent.join(dir);
|
||||
if !dir.exists() {
|
||||
panic!(
|
||||
"The isolation dir configuration is set to `{:?}` but this path doesn't exist",
|
||||
dir
|
||||
)
|
||||
}
|
||||
|
||||
let key = uuid::Uuid::new_v4().to_string();
|
||||
let assets = EmbeddedAssets::new(dir.clone(), map_isolation(&options, dir))?;
|
||||
let schema = options.isolation_schema;
|
||||
|
||||
quote!(#root::Pattern::Isolation {
|
||||
assets: ::std::sync::Arc::new(#assets),
|
||||
schema: #schema.into(),
|
||||
key: #key.into(),
|
||||
crypto_keys: std::boxed::Box::new(::tauri::utils::pattern::isolation::Keys::new().expect("unable to generate cryptographically secure keys for Tauri \"Isolation\" Pattern")),
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
Ok(quote!(#root::Context::new(
|
||||
#config,
|
||||
::std::sync::Arc::new(#assets),
|
||||
@ -188,6 +295,7 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
|
||||
#system_tray_icon,
|
||||
#package_info,
|
||||
#info_plist,
|
||||
#pattern
|
||||
)))
|
||||
}
|
||||
|
||||
|
@ -4,18 +4,14 @@
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{quote, ToTokens, TokenStreamExt};
|
||||
use regex::RegexSet;
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
ffi::OsStr,
|
||||
fs::File,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use tauri_utils::{
|
||||
assets::AssetKey,
|
||||
html::{inject_invoke_key_token, inject_nonce_token, parse as parse_html},
|
||||
};
|
||||
use tauri_utils::assets::AssetKey;
|
||||
use tauri_utils::config::PatternKind;
|
||||
use thiserror::Error;
|
||||
use walkdir::{DirEntry, WalkDir};
|
||||
|
||||
@ -143,12 +139,14 @@ impl RawEmbeddedAssets {
|
||||
}
|
||||
|
||||
/// Holds all hashes that we will apply on the CSP tag/header.
|
||||
#[derive(Default)]
|
||||
struct CspHashes {
|
||||
#[derive(Debug, Default)]
|
||||
pub struct CspHashes {
|
||||
/// Scripts that are part of the asset collection (JS or MJS files).
|
||||
scripts: Vec<String>,
|
||||
pub(crate) scripts: Vec<String>,
|
||||
/// Inline scripts (`<script>code</script>`). Maps a HTML path to a list of hashes.
|
||||
inline_scripts: HashMap<String, Vec<String>>,
|
||||
pub(crate) inline_scripts: HashMap<String, Vec<String>>,
|
||||
/// A list of hashes of the contents of all `style` elements.
|
||||
pub(crate) styles: Vec<String>,
|
||||
}
|
||||
|
||||
impl CspHashes {
|
||||
@ -181,20 +179,38 @@ impl CspHashes {
|
||||
/// Options used to embed assets.
|
||||
#[derive(Default)]
|
||||
pub struct AssetOptions {
|
||||
csp: bool,
|
||||
pub(crate) csp: bool,
|
||||
pub(crate) pattern: PatternKind,
|
||||
pub(crate) freeze_prototype: bool,
|
||||
#[cfg(feature = "isolation")]
|
||||
pub(crate) isolation_schema: String,
|
||||
}
|
||||
|
||||
impl AssetOptions {
|
||||
/// Creates the default asset options.
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
pub fn new(pattern: PatternKind) -> Self {
|
||||
Self {
|
||||
csp: false,
|
||||
pattern,
|
||||
freeze_prototype: true,
|
||||
#[cfg(feature = "isolation")]
|
||||
isolation_schema: format!("isolation-{}", uuid::Uuid::new_v4()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Instruct the asset handler to inject the CSP token to HTML files.
|
||||
#[must_use]
|
||||
pub fn with_csp(mut self) -> Self {
|
||||
self.csp = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Instruct the asset handler to include a script to freeze the `Object.prototype` on all HTML files.
|
||||
#[must_use]
|
||||
pub fn freeze_prototype(mut self, freeze: bool) -> Self {
|
||||
self.freeze_prototype = freeze;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl EmbeddedAssets {
|
||||
@ -203,18 +219,27 @@ impl EmbeddedAssets {
|
||||
/// [`Assets`]: tauri_utils::assets::Assets
|
||||
pub fn new(
|
||||
input: impl Into<EmbeddedAssetsInput>,
|
||||
options: AssetOptions,
|
||||
map: impl Fn(&AssetKey, &Path, &mut Vec<u8>, &mut CspHashes) -> Result<(), EmbeddedAssetsError>,
|
||||
) -> Result<Self, EmbeddedAssetsError> {
|
||||
// we need to pre-compute all files now, so that we can inject data from all files into a few
|
||||
let RawEmbeddedAssets {
|
||||
paths,
|
||||
mut csp_hashes,
|
||||
} = RawEmbeddedAssets::new(input.into())?;
|
||||
let RawEmbeddedAssets { paths, csp_hashes } = RawEmbeddedAssets::new(input.into())?;
|
||||
|
||||
let assets = paths
|
||||
.into_iter()
|
||||
.map(|(prefix, entry)| Self::compress_file(&prefix, entry.path(), &options, &mut csp_hashes))
|
||||
.collect::<Result<_, _>>()?;
|
||||
struct CompressState {
|
||||
csp_hashes: CspHashes,
|
||||
assets: HashMap<AssetKey, (PathBuf, PathBuf)>,
|
||||
}
|
||||
|
||||
let CompressState { assets, csp_hashes } = paths.into_iter().try_fold(
|
||||
CompressState {
|
||||
csp_hashes,
|
||||
assets: HashMap::new(),
|
||||
},
|
||||
move |mut state, (prefix, entry)| {
|
||||
let (key, asset) = Self::compress_file(&prefix, entry.path(), &map, &mut state.csp_hashes)?;
|
||||
state.assets.insert(key, asset);
|
||||
Ok(state)
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(Self { assets, csp_hashes })
|
||||
}
|
||||
@ -234,7 +259,7 @@ impl EmbeddedAssets {
|
||||
fn compress_file(
|
||||
prefix: &Path,
|
||||
path: &Path,
|
||||
options: &AssetOptions,
|
||||
map: &impl Fn(&AssetKey, &Path, &mut Vec<u8>, &mut CspHashes) -> Result<(), EmbeddedAssetsError>,
|
||||
csp_hashes: &mut CspHashes,
|
||||
) -> Result<Asset, EmbeddedAssetsError> {
|
||||
let mut input = std::fs::read(path).map_err(|error| EmbeddedAssetsError::AssetRead {
|
||||
@ -251,75 +276,8 @@ impl EmbeddedAssets {
|
||||
path: path.to_owned(),
|
||||
})?;
|
||||
|
||||
if path.extension() == Some(OsStr::new("html")) {
|
||||
let mut document = parse_html(String::from_utf8_lossy(&input).into_owned());
|
||||
if options.csp {
|
||||
#[cfg(target_os = "linux")]
|
||||
::tauri_utils::html::inject_csp_token(&mut document);
|
||||
inject_nonce_token(&mut document);
|
||||
if let Ok(inline_script_elements) = document.select("script:not(empty)") {
|
||||
let mut scripts = Vec::new();
|
||||
for inline_script_el in inline_script_elements {
|
||||
let script = inline_script_el.as_node().text_contents();
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(&script);
|
||||
let hash = hasher.finalize();
|
||||
scripts.push(format!("'sha256-{}'", base64::encode(&hash)));
|
||||
}
|
||||
csp_hashes
|
||||
.inline_scripts
|
||||
.insert(key.clone().into(), scripts);
|
||||
}
|
||||
}
|
||||
inject_invoke_key_token(&mut document);
|
||||
input = document.to_string().as_bytes().to_vec();
|
||||
} else {
|
||||
let is_javascript = ["js", "cjs", "mjs"]
|
||||
.iter()
|
||||
.any(|e| path.extension() == Some(OsStr::new(e)));
|
||||
if is_javascript {
|
||||
let js = String::from_utf8_lossy(&input).into_owned();
|
||||
input = if RegexSet::new(&[
|
||||
// import keywords
|
||||
"import\\{",
|
||||
"import \\{",
|
||||
"import\\*",
|
||||
"import \\*",
|
||||
"import (\"|');?$",
|
||||
"import\\(",
|
||||
"import (.|\n)+ from (\"|')([A-Za-z/\\.@-]+)(\"|')",
|
||||
// export keywords
|
||||
"export\\{",
|
||||
"export \\{",
|
||||
"export\\*",
|
||||
"export \\*",
|
||||
"export (default|class|let|const|function|async)",
|
||||
])
|
||||
.unwrap()
|
||||
.is_match(&js)
|
||||
{
|
||||
format!(
|
||||
r#"
|
||||
const __TAURI_INVOKE_KEY__ = __TAURI__INVOKE_KEY_TOKEN__;
|
||||
{}
|
||||
"#,
|
||||
js
|
||||
)
|
||||
.as_bytes()
|
||||
.to_vec()
|
||||
} else {
|
||||
format!(
|
||||
r#"(function () {{
|
||||
const __TAURI_INVOKE_KEY__ = __TAURI__INVOKE_KEY_TOKEN__;
|
||||
{}
|
||||
}})()"#,
|
||||
js
|
||||
)
|
||||
.as_bytes()
|
||||
.to_vec()
|
||||
};
|
||||
}
|
||||
}
|
||||
// perform any caller-requested input manipulation
|
||||
map(&key, path, &mut input, csp_hashes)?;
|
||||
|
||||
// we must canonicalize the base of our paths to allow long paths on windows
|
||||
let out_dir = std::env::var("OUT_DIR")
|
||||
@ -404,6 +362,11 @@ impl ToTokens for EmbeddedAssets {
|
||||
global_hashes.append_all(quote!(CspHash::Script(#hash),));
|
||||
}
|
||||
|
||||
for style_hash in &self.csp_hashes.styles {
|
||||
let hash = style_hash.as_str();
|
||||
global_hashes.append_all(quote!(CspHash::Style(#hash),));
|
||||
}
|
||||
|
||||
let mut html_hashes = TokenStream::new();
|
||||
for (path, hashes) in &self.csp_hashes.inline_scripts {
|
||||
let key = path.as_str();
|
||||
|
@ -8,7 +8,7 @@ homepage = "https://tauri.studio"
|
||||
repository = "https://github.com/tauri-apps/tauri"
|
||||
description = "Macros for the tauri crate."
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
exclude = [ ".license_template", "CHANGELOG.md", "/target" ]
|
||||
readme = "README.md"
|
||||
|
||||
@ -25,3 +25,4 @@ tauri-codegen = { version = "1.0.0-beta.4", default-features = false, path = "..
|
||||
[features]
|
||||
custom-protocol = [ ]
|
||||
compression = [ "tauri-codegen/compression" ]
|
||||
isolation = ["tauri-codegen/isolation"]
|
||||
|
@ -8,7 +8,7 @@ homepage = "https://tauri.studio"
|
||||
repository = "https://github.com/tauri-apps/tauri"
|
||||
description = "Wry bindings to the Tauri runtime"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
exclude = [ ".license_template", "CHANGELOG.md", "/target" ]
|
||||
readme = "README.md"
|
||||
|
||||
|
@ -8,7 +8,7 @@ homepage = "https://tauri.studio"
|
||||
repository = "https://github.com/tauri-apps/tauri"
|
||||
description = "Runtime for Tauri applications"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
exclude = [ ".license_template", "CHANGELOG.md", "/target" ]
|
||||
readme = "README.md"
|
||||
|
||||
|
@ -168,7 +168,8 @@ impl Builder {
|
||||
}
|
||||
|
||||
/// Set the HTTP mimetype for this response.
|
||||
pub fn mimetype(self, mimetype: &str) -> Builder {
|
||||
#[must_use]
|
||||
pub fn mimetype(self, mimetype: &str) -> Self {
|
||||
self.and_then(move |mut head| {
|
||||
head.mimetype = Some(mimetype.to_string());
|
||||
Ok(head)
|
||||
@ -176,7 +177,8 @@ impl Builder {
|
||||
}
|
||||
|
||||
/// Set the HTTP status for this response.
|
||||
pub fn status<T>(self, status: T) -> Builder
|
||||
#[must_use]
|
||||
pub fn status<T>(self, status: T) -> Self
|
||||
where
|
||||
StatusCode: TryFrom<T>,
|
||||
<StatusCode as TryFrom<T>>::Error: Into<crate::Error>,
|
||||
@ -193,7 +195,8 @@ impl Builder {
|
||||
/// will be returned from `Builder::build`.
|
||||
///
|
||||
/// By default this is HTTP/1.1
|
||||
pub fn version(self, version: Version) -> Builder {
|
||||
#[must_use]
|
||||
pub fn version(self, version: Version) -> Self {
|
||||
self.and_then(move |mut head| {
|
||||
head.version = version;
|
||||
Ok(head)
|
||||
@ -205,7 +208,8 @@ impl Builder {
|
||||
/// This function will append the provided key/value as a header to the
|
||||
/// internal `HeaderMap` being constructed. Essentially this is equivalent
|
||||
/// to calling `HeaderMap::append`.
|
||||
pub fn header<K, V>(self, key: K, value: V) -> Builder
|
||||
#[must_use]
|
||||
pub fn header<K, V>(self, key: K, value: V) -> Self
|
||||
where
|
||||
HeaderName: TryFrom<K>,
|
||||
<HeaderName as TryFrom<K>>::Error: Into<crate::Error>,
|
||||
|
@ -57,6 +57,7 @@ impl SystemTray {
|
||||
}
|
||||
|
||||
/// Sets the tray icon. Must be a [`Icon::File`] on Linux and a [`Icon::Raw`] on Windows and macOS.
|
||||
#[must_use]
|
||||
pub fn with_icon(mut self, icon: Icon) -> Self {
|
||||
self.icon.replace(icon);
|
||||
self
|
||||
@ -64,12 +65,14 @@ impl SystemTray {
|
||||
|
||||
/// Sets the tray icon as template.
|
||||
#[cfg(target_os = "macos")]
|
||||
#[must_use]
|
||||
pub fn with_icon_as_template(mut self, is_template: bool) -> Self {
|
||||
self.icon_as_template = is_template;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the menu to show when the system tray is right clicked.
|
||||
#[must_use]
|
||||
pub fn with_menu(mut self, menu: menu::SystemTrayMenu) -> Self {
|
||||
self.menu.replace(menu);
|
||||
self
|
||||
|
@ -206,18 +206,21 @@ impl Menu {
|
||||
}
|
||||
|
||||
/// Adds the custom menu item to the menu.
|
||||
#[must_use]
|
||||
pub fn add_item(mut self, item: CustomMenuItem) -> Self {
|
||||
self.items.push(MenuEntry::CustomItem(item));
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a native item to the menu.
|
||||
#[must_use]
|
||||
pub fn add_native_item(mut self, item: MenuItem) -> Self {
|
||||
self.items.push(MenuEntry::NativeItem(item));
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds an entry with submenu.
|
||||
#[must_use]
|
||||
pub fn add_submenu(mut self, submenu: Submenu) -> Self {
|
||||
self.items.push(MenuEntry::Submenu(submenu));
|
||||
self
|
||||
@ -255,6 +258,7 @@ impl CustomMenuItem {
|
||||
}
|
||||
|
||||
/// Assign a keyboard shortcut to the menu action.
|
||||
#[must_use]
|
||||
pub fn accelerator<T: Into<String>>(mut self, accelerator: T) -> Self {
|
||||
self.keyboard_accelerator.replace(accelerator.into());
|
||||
self
|
||||
@ -262,6 +266,7 @@ impl CustomMenuItem {
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
|
||||
#[must_use]
|
||||
/// A native image do render on the menu item.
|
||||
pub fn native_image(mut self, image: NativeImage) -> Self {
|
||||
self.native_image.replace(image);
|
||||
@ -269,12 +274,14 @@ impl CustomMenuItem {
|
||||
}
|
||||
|
||||
/// Mark the item as disabled.
|
||||
#[must_use]
|
||||
pub fn disabled(mut self) -> Self {
|
||||
self.enabled = false;
|
||||
self
|
||||
}
|
||||
|
||||
/// Mark the item as selected.
|
||||
#[must_use]
|
||||
pub fn selected(mut self) -> Self {
|
||||
self.selected = true;
|
||||
self
|
||||
@ -320,18 +327,21 @@ impl SystemTrayMenu {
|
||||
}
|
||||
|
||||
/// Adds the custom menu item to the system tray menu.
|
||||
#[must_use]
|
||||
pub fn add_item(mut self, item: CustomMenuItem) -> Self {
|
||||
self.items.push(SystemTrayMenuEntry::CustomItem(item));
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a native item to the system tray menu.
|
||||
#[must_use]
|
||||
pub fn add_native_item(mut self, item: SystemTrayMenuItem) -> Self {
|
||||
self.items.push(SystemTrayMenuEntry::NativeItem(item));
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds an entry with submenu.
|
||||
#[must_use]
|
||||
pub fn add_submenu(mut self, submenu: SystemTraySubmenu) -> Self {
|
||||
self.items.push(SystemTrayMenuEntry::Submenu(submenu));
|
||||
self
|
||||
|
@ -36,18 +36,21 @@ impl WebviewAttributes {
|
||||
}
|
||||
|
||||
/// Sets the init script.
|
||||
#[must_use]
|
||||
pub fn initialization_script(mut self, script: &str) -> Self {
|
||||
self.initialization_scripts.push(script.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// Data directory for the webview.
|
||||
#[must_use]
|
||||
pub fn data_directory(mut self, data_directory: PathBuf) -> Self {
|
||||
self.data_directory.replace(data_directory);
|
||||
self
|
||||
}
|
||||
|
||||
/// Disables the file drop handler. This is required to use drag and drop APIs on the front end on Windows.
|
||||
#[must_use]
|
||||
pub fn disable_file_drop_handler(mut self) -> Self {
|
||||
self.file_drop_handler_enabled = false;
|
||||
self
|
||||
@ -57,6 +60,7 @@ impl WebviewAttributes {
|
||||
///
|
||||
/// **macOS** doesn't provide such method and is always enabled by default,
|
||||
/// but you still need to add menu item accelerators to use shortcuts.
|
||||
#[must_use]
|
||||
pub fn enable_clipboard_access(mut self) -> Self {
|
||||
self.clipboard = true;
|
||||
self
|
||||
@ -80,39 +84,51 @@ pub trait WindowBuilder: WindowBuilderBase {
|
||||
fn with_config(config: WindowConfig) -> Self;
|
||||
|
||||
/// Sets the menu for the window.
|
||||
#[must_use]
|
||||
fn menu(self, menu: Menu) -> Self;
|
||||
|
||||
/// Show window in the center of the screen.
|
||||
#[must_use]
|
||||
fn center(self) -> Self;
|
||||
|
||||
/// The initial position of the window's.
|
||||
#[must_use]
|
||||
fn position(self, x: f64, y: f64) -> Self;
|
||||
|
||||
/// Window size.
|
||||
#[must_use]
|
||||
fn inner_size(self, min_width: f64, min_height: f64) -> Self;
|
||||
|
||||
/// Window min inner size.
|
||||
#[must_use]
|
||||
fn min_inner_size(self, min_width: f64, min_height: f64) -> Self;
|
||||
|
||||
/// Window max inner size.
|
||||
#[must_use]
|
||||
fn max_inner_size(self, max_width: f64, max_height: f64) -> Self;
|
||||
|
||||
/// Whether the window is resizable or not.
|
||||
#[must_use]
|
||||
fn resizable(self, resizable: bool) -> Self;
|
||||
|
||||
/// The title of the window in the title bar.
|
||||
#[must_use]
|
||||
fn title<S: Into<String>>(self, title: S) -> Self;
|
||||
|
||||
/// Whether to start the window in fullscreen or not.
|
||||
#[must_use]
|
||||
fn fullscreen(self, fullscreen: bool) -> Self;
|
||||
|
||||
/// Whether the window will be initially hidden or focused.
|
||||
#[must_use]
|
||||
fn focus(self) -> Self;
|
||||
|
||||
/// Whether the window should be maximized upon creation.
|
||||
#[must_use]
|
||||
fn maximized(self, maximized: bool) -> Self;
|
||||
|
||||
/// Whether the window should be immediately visible upon creation.
|
||||
#[must_use]
|
||||
fn visible(self, visible: bool) -> Self;
|
||||
|
||||
/// Whether the the window should be transparent. If this is true, writing colors
|
||||
@ -122,18 +138,22 @@ pub trait WindowBuilder: WindowBuilderBase {
|
||||
doc_cfg,
|
||||
doc(cfg(any(not(target_os = "macos"), feature = "macos-private-api")))
|
||||
)]
|
||||
#[must_use]
|
||||
fn transparent(self, transparent: bool) -> Self;
|
||||
|
||||
/// Whether the window should have borders and bars.
|
||||
#[must_use]
|
||||
fn decorations(self, decorations: bool) -> Self;
|
||||
|
||||
/// Whether the window should always be on top of other windows.
|
||||
#[must_use]
|
||||
fn always_on_top(self, always_on_top: bool) -> Self;
|
||||
|
||||
/// Sets the window icon.
|
||||
fn icon(self, icon: Icon) -> crate::Result<Self>;
|
||||
|
||||
/// Sets whether or not the window icon should be added to the taskbar.
|
||||
#[must_use]
|
||||
fn skip_taskbar(self, skip: bool) -> Self;
|
||||
|
||||
/// Sets a parent to the window to be created.
|
||||
@ -142,6 +162,7 @@ pub trait WindowBuilder: WindowBuilderBase {
|
||||
///
|
||||
/// For more information, see <https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#child-windows>
|
||||
#[cfg(windows)]
|
||||
#[must_use]
|
||||
fn parent_window(self, parent: HWND) -> Self;
|
||||
|
||||
/// Set an owner to the window to be created.
|
||||
@ -153,6 +174,7 @@ pub trait WindowBuilder: WindowBuilderBase {
|
||||
///
|
||||
/// For more information, see <https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#owned-windows>
|
||||
#[cfg(windows)]
|
||||
#[must_use]
|
||||
fn owner_window(self, owner: HWND) -> Self;
|
||||
|
||||
/// Whether the icon was set or not.
|
||||
|
@ -168,6 +168,7 @@ impl<R: Runtime> PendingWindow<R> {
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn set_menu(mut self, menu: Menu) -> Self {
|
||||
let mut menu_ids = HashMap::new();
|
||||
get_menu_ids(&mut menu_ids, &menu);
|
||||
|
@ -7,7 +7,7 @@ homepage = "https://tauri.studio"
|
||||
repository = "https://github.com/tauri-apps/tauri"
|
||||
description = "Utilities for Tauri"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
exclude = [ ".license_template", "CHANGELOG.md", "/target" ]
|
||||
readme = "README.md"
|
||||
|
||||
@ -24,6 +24,13 @@ proc-macro2 = { version = "1.0", optional = true }
|
||||
quote = { version = "1.0", optional = true }
|
||||
schemars = { version = "0.8", features = ["url"], optional = true }
|
||||
serde_with = "1.10"
|
||||
sha2 = "0.9"
|
||||
base64 = "0.13"
|
||||
aes-gcm = { version = "0.9", optional = true }
|
||||
ring = { version = "0.16", optional = true, features = ["std"] }
|
||||
once_cell = { version = "1.8", optional = true }
|
||||
serialize-to-javascript = { git = "https://github.com/chippers/serialize-to-javascript" }
|
||||
|
||||
|
||||
[target."cfg(target_os = \"linux\")".dependencies]
|
||||
heck = "0.4"
|
||||
@ -32,3 +39,4 @@ heck = "0.4"
|
||||
build = [ "proc-macro2", "quote" ]
|
||||
compression = [ "zstd" ]
|
||||
schema = ["schemars"]
|
||||
isolation = [ "aes-gcm", "ring", "once_cell" ]
|
||||
|
@ -81,6 +81,9 @@ impl<P: AsRef<Path>> From<P> for AssetKey {
|
||||
pub enum CspHash<'a> {
|
||||
/// The `script-src` directive.
|
||||
Script(&'a str),
|
||||
|
||||
/// The `style-src` directive.
|
||||
Style(&'a str),
|
||||
}
|
||||
|
||||
impl CspHash<'_> {
|
||||
@ -88,6 +91,7 @@ impl CspHash<'_> {
|
||||
pub fn directive(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Script(_) => "script-src",
|
||||
Self::Style(_) => "style-src",
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,6 +99,7 @@ impl CspHash<'_> {
|
||||
pub fn hash(&self) -> &str {
|
||||
match self {
|
||||
Self::Script(hash) => hash,
|
||||
Self::Style(hash) => hash,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,8 +36,8 @@ pub enum WindowUrl {
|
||||
App(PathBuf),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for WindowUrl {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
impl fmt::Display for WindowUrl {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::External(url) => write!(f, "{}", url),
|
||||
Self::App(path) => write!(f, "{}", path.display()),
|
||||
@ -542,7 +542,7 @@ fn default_file_drop_enabled() -> bool {
|
||||
|
||||
/// Security configuration.
|
||||
#[skip_serializing_none]
|
||||
#[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
|
||||
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
|
||||
#[cfg_attr(feature = "schema", derive(JsonSchema))]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
pub struct SecurityConfig {
|
||||
@ -557,6 +557,23 @@ pub struct SecurityConfig {
|
||||
/// This is a really important part of the configuration since it helps you ensure your WebView is secured.
|
||||
/// See <https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP>.
|
||||
pub dev_csp: Option<String>,
|
||||
/// Freeze the `Object.prototype` when using the custom protocol.
|
||||
#[serde(default = "default_freeze_prototype")]
|
||||
pub freeze_prototype: bool,
|
||||
}
|
||||
|
||||
impl Default for SecurityConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
csp: None,
|
||||
dev_csp: None,
|
||||
freeze_prototype: default_freeze_prototype(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn default_freeze_prototype() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// Defines an allowlist type.
|
||||
@ -1292,12 +1309,37 @@ fn default_window_config() -> Vec<WindowConfig> {
|
||||
vec![Default::default()]
|
||||
}
|
||||
|
||||
/// The application pattern.
|
||||
#[skip_serializing_none]
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "lowercase", tag = "use", content = "options")]
|
||||
#[cfg_attr(feature = "schema", derive(JsonSchema))]
|
||||
pub enum PatternKind {
|
||||
/// Brownfield pattern.
|
||||
Brownfield,
|
||||
/// Isolation pattern. Recommended for security purposes.
|
||||
#[cfg(feature = "isolation")]
|
||||
Isolation {
|
||||
/// The dir containing the index.html file that contains the secure isolation application.
|
||||
dir: PathBuf,
|
||||
},
|
||||
}
|
||||
|
||||
impl Default for PatternKind {
|
||||
fn default() -> Self {
|
||||
Self::Brownfield
|
||||
}
|
||||
}
|
||||
|
||||
/// The Tauri configuration object.
|
||||
#[skip_serializing_none]
|
||||
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
|
||||
#[cfg_attr(feature = "schema", derive(JsonSchema))]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
pub struct TauriConfig {
|
||||
/// The pattern to use.
|
||||
#[serde(default)]
|
||||
pub pattern: PatternKind,
|
||||
/// The windows configuration.
|
||||
#[serde(default = "default_window_config")]
|
||||
pub windows: Vec<WindowConfig>,
|
||||
@ -1325,6 +1367,7 @@ pub struct TauriConfig {
|
||||
impl Default for TauriConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
pattern: Default::default(),
|
||||
windows: default_window_config(),
|
||||
cli: None,
|
||||
bundle: BundleConfig::default(),
|
||||
@ -1338,6 +1381,20 @@ impl Default for TauriConfig {
|
||||
}
|
||||
|
||||
impl TauriConfig {
|
||||
/// Returns all Cargo features.
|
||||
#[allow(dead_code)]
|
||||
pub fn all_features() -> Vec<&'static str> {
|
||||
let mut features = AllowlistConfig::all_features();
|
||||
features.extend(vec![
|
||||
"cli",
|
||||
"updater",
|
||||
"system-tray",
|
||||
"macos-private-api",
|
||||
"isolation",
|
||||
]);
|
||||
features
|
||||
}
|
||||
|
||||
/// Returns the enabled Cargo features.
|
||||
#[allow(dead_code)]
|
||||
pub fn features(&self) -> Vec<&str> {
|
||||
@ -1354,6 +1411,10 @@ impl TauriConfig {
|
||||
if self.macos_private_api {
|
||||
features.push("macos-private-api");
|
||||
}
|
||||
#[cfg(feature = "isolation")]
|
||||
if let PatternKind::Isolation { .. } = self.pattern {
|
||||
features.push("isolation");
|
||||
}
|
||||
features.sort_unstable();
|
||||
features
|
||||
}
|
||||
@ -1964,6 +2025,21 @@ mod build {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for PatternKind {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let prefix = quote! { ::tauri::utils::config::PatternKind };
|
||||
|
||||
tokens.append_all(match self {
|
||||
Self::Brownfield => quote! { #prefix::Brownfield },
|
||||
#[cfg(feature = "isolation")]
|
||||
Self::Isolation { dir } => {
|
||||
let dir = path_buf_lit(dir);
|
||||
quote! { #prefix::Isolation { dir: #dir } }
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for WindowsConfig {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let webview_fixed_runtime_path = opt_lit(
|
||||
@ -2082,8 +2158,9 @@ mod build {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let csp = opt_str_lit(self.csp.as_ref());
|
||||
let dev_csp = opt_str_lit(self.dev_csp.as_ref());
|
||||
let freeze_prototype = self.freeze_prototype;
|
||||
|
||||
literal_struct!(tokens, SecurityConfig, csp, dev_csp);
|
||||
literal_struct!(tokens, SecurityConfig, csp, dev_csp, freeze_prototype);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2151,6 +2228,7 @@ mod build {
|
||||
|
||||
impl ToTokens for TauriConfig {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let pattern = &self.pattern;
|
||||
let windows = vec_lit(&self.windows, identity);
|
||||
let cli = opt_lit(self.cli.as_ref());
|
||||
let bundle = &self.bundle;
|
||||
@ -2163,6 +2241,7 @@ mod build {
|
||||
literal_struct!(
|
||||
tokens,
|
||||
TauriConfig,
|
||||
pattern,
|
||||
windows,
|
||||
cli,
|
||||
bundle,
|
||||
@ -2234,6 +2313,7 @@ mod test {
|
||||
|
||||
// create a tauri config.
|
||||
let tauri = TauriConfig {
|
||||
pattern: Default::default(),
|
||||
windows: vec![WindowConfig {
|
||||
label: "main".to_string(),
|
||||
url: WindowUrl::default(),
|
||||
@ -2283,6 +2363,7 @@ mod test {
|
||||
security: SecurityConfig {
|
||||
csp: None,
|
||||
dev_csp: None,
|
||||
freeze_prototype: true,
|
||||
},
|
||||
allowlist: AllowlistConfig::default(),
|
||||
system_tray: None,
|
||||
|
@ -4,8 +4,18 @@
|
||||
|
||||
//! The module to process HTML in Tauri.
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use html5ever::{interface::QualName, namespace_url, ns, tendril::TendrilSink, LocalName};
|
||||
use kuchiki::{Attribute, ExpandedName, NodeRef};
|
||||
pub use kuchiki::NodeRef;
|
||||
use kuchiki::{Attribute, ExpandedName};
|
||||
use serde::Serialize;
|
||||
#[cfg(feature = "isolation")]
|
||||
use serialize_to_javascript::DefaultTemplate;
|
||||
|
||||
use crate::config::PatternKind;
|
||||
#[cfg(feature = "isolation")]
|
||||
use crate::pattern::isolation::IsolationJavascriptCodegen;
|
||||
|
||||
/// The token used on the CSP tag content.
|
||||
pub const CSP_TOKEN: &str = "__TAURI_CSP__";
|
||||
@ -13,14 +23,25 @@ pub const CSP_TOKEN: &str = "__TAURI_CSP__";
|
||||
pub const SCRIPT_NONCE_TOKEN: &str = "__TAURI_SCRIPT_NONCE__";
|
||||
/// The token used for style nonces.
|
||||
pub const STYLE_NONCE_TOKEN: &str = "__TAURI_STYLE_NONCE__";
|
||||
/// The token used for the invoke key.
|
||||
pub const INVOKE_KEY_TOKEN: &str = "__TAURI__INVOKE_KEY_TOKEN__";
|
||||
|
||||
/// Parses the given HTML string.
|
||||
pub fn parse(html: String) -> NodeRef {
|
||||
kuchiki::parse_html().one(html)
|
||||
}
|
||||
|
||||
fn with_head<F: FnOnce(&NodeRef)>(document: &mut NodeRef, f: F) {
|
||||
if let Ok(ref node) = document.select_first("head") {
|
||||
f(node.as_node())
|
||||
} else {
|
||||
let node = NodeRef::new_element(
|
||||
QualName::new(None, ns!(html), LocalName::from("head")),
|
||||
None,
|
||||
);
|
||||
f(&node);
|
||||
document.prepend(node)
|
||||
}
|
||||
}
|
||||
|
||||
fn inject_nonce(document: &mut NodeRef, selector: &str, token: &str) {
|
||||
if let Ok(scripts) = document.select(selector) {
|
||||
for target in scripts {
|
||||
@ -43,88 +64,11 @@ pub fn inject_nonce_token(document: &mut NodeRef) {
|
||||
inject_nonce(document, "style", STYLE_NONCE_TOKEN);
|
||||
}
|
||||
|
||||
/// Injects the invoke key token to each script on the document.
|
||||
///
|
||||
/// The invoke key token is replaced at runtime with the actual invoke key value.
|
||||
pub fn inject_invoke_key_token(document: &mut NodeRef) {
|
||||
let mut targets = vec![];
|
||||
if let Ok(scripts) = document.select("script") {
|
||||
for target in scripts {
|
||||
targets.push(target);
|
||||
}
|
||||
for target in targets {
|
||||
let node = target.as_node();
|
||||
let element = node.as_element().unwrap();
|
||||
|
||||
let attrs = element.attributes.borrow();
|
||||
// if the script is external (has `src`), we won't inject the token
|
||||
if attrs.get("src").is_some() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let replacement_node = match attrs.get("type") {
|
||||
Some("module") | Some("application/ecmascript") => {
|
||||
let replacement_node = NodeRef::new_element(
|
||||
QualName::new(None, ns!(html), "script".into()),
|
||||
element
|
||||
.attributes
|
||||
.borrow()
|
||||
.clone()
|
||||
.map
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
let script = node.text_contents();
|
||||
replacement_node.append(NodeRef::new_text(format!(
|
||||
r#"
|
||||
const __TAURI_INVOKE_KEY__ = {token};
|
||||
{script}
|
||||
"#,
|
||||
token = INVOKE_KEY_TOKEN,
|
||||
script = script
|
||||
)));
|
||||
replacement_node
|
||||
}
|
||||
Some("application/javascript") | None => {
|
||||
let replacement_node = NodeRef::new_element(
|
||||
QualName::new(None, ns!(html), "script".into()),
|
||||
element
|
||||
.attributes
|
||||
.borrow()
|
||||
.clone()
|
||||
.map
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
let script = node.text_contents();
|
||||
replacement_node.append(NodeRef::new_text(
|
||||
script.replace("__TAURI_INVOKE_KEY__", INVOKE_KEY_TOKEN),
|
||||
));
|
||||
replacement_node
|
||||
}
|
||||
_ => {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
node.insert_after(replacement_node);
|
||||
node.detach();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Injects a content security policy to the HTML.
|
||||
pub fn inject_csp(document: &mut NodeRef, csp: &str) {
|
||||
if let Ok(ref head) = document.select_first("head") {
|
||||
head.as_node().append(create_csp_meta_tag(csp));
|
||||
} else {
|
||||
let head = NodeRef::new_element(
|
||||
QualName::new(None, ns!(html), LocalName::from("head")),
|
||||
None,
|
||||
);
|
||||
with_head(document, |head| {
|
||||
head.append(create_csp_meta_tag(csp));
|
||||
document.prepend(head);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Injects a content security policy token to the HTML.
|
||||
@ -154,9 +98,101 @@ fn create_csp_meta_tag(csp: &str) -> NodeRef {
|
||||
)
|
||||
}
|
||||
|
||||
/// The shape of the JavaScript Pattern config
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "lowercase", tag = "pattern")]
|
||||
pub enum PatternObject {
|
||||
/// Brownfield pattern.
|
||||
Brownfield,
|
||||
/// Isolation pattern. Recommended for security purposes.
|
||||
Isolation {
|
||||
/// Which `IsolationSide` this `PatternObject` is getting injected into
|
||||
side: IsolationSide,
|
||||
},
|
||||
}
|
||||
|
||||
impl From<&PatternKind> for PatternObject {
|
||||
fn from(pattern_kind: &PatternKind) -> Self {
|
||||
match pattern_kind {
|
||||
PatternKind::Brownfield => Self::Brownfield,
|
||||
#[cfg(feature = "isolation")]
|
||||
PatternKind::Isolation { .. } => Self::Isolation {
|
||||
side: IsolationSide::default(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Where the JavaScript is injected to
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum IsolationSide {
|
||||
/// Original frame, the Brownfield application
|
||||
Original,
|
||||
/// Secure frame, the isolation security application
|
||||
Secure,
|
||||
}
|
||||
|
||||
impl Default for IsolationSide {
|
||||
fn default() -> Self {
|
||||
Self::Original
|
||||
}
|
||||
}
|
||||
|
||||
/// Injects the Isolation JavaScript to a codegen time document.
|
||||
///
|
||||
/// Note: This function is not considered part of the stable API.
|
||||
#[cfg(feature = "isolation")]
|
||||
pub fn inject_codegen_isolation_script(document: &mut NodeRef) {
|
||||
with_head(document, |head| {
|
||||
let script = NodeRef::new_element(QualName::new(None, ns!(html), "script".into()), None);
|
||||
script.append(NodeRef::new_text(
|
||||
IsolationJavascriptCodegen {}
|
||||
.render_default(&Default::default())
|
||||
.expect("unable to render codegen isolation script template"),
|
||||
));
|
||||
|
||||
head.prepend(script);
|
||||
});
|
||||
}
|
||||
|
||||
/// Temporary workaround for Windows not allowing requests
|
||||
///
|
||||
/// Note: this does not prevent path traversal due to the isolation application expectation that it
|
||||
/// is secure.
|
||||
pub fn inline_isolation(document: &mut NodeRef, dir: &Path) {
|
||||
for script in document
|
||||
.select("script[src]")
|
||||
.expect("unable to parse document for scripts")
|
||||
{
|
||||
let src = {
|
||||
let attributes = script.attributes.borrow();
|
||||
attributes
|
||||
.get(LocalName::from("src"))
|
||||
.expect("script with src attribute has no src value")
|
||||
.to_string()
|
||||
};
|
||||
|
||||
let mut path = PathBuf::from(src);
|
||||
if path.has_root() {
|
||||
path = path
|
||||
.strip_prefix("/")
|
||||
.expect("Tauri \"Isolation\" Pattern only supports relative or absolute (`/`) paths.")
|
||||
.into();
|
||||
}
|
||||
|
||||
let file = std::fs::read_to_string(dir.join(path)).expect("unable to find isolation file");
|
||||
script.as_node().append(NodeRef::new_text(file));
|
||||
|
||||
let mut attributes = script.attributes.borrow_mut();
|
||||
attributes.remove(LocalName::from("src"));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use kuchiki::traits::*;
|
||||
|
||||
#[test]
|
||||
fn csp() {
|
||||
let htmls = vec![
|
||||
|
@ -10,6 +10,9 @@ pub mod config;
|
||||
pub mod html;
|
||||
pub mod platform;
|
||||
|
||||
/// Application pattern.
|
||||
pub mod pattern;
|
||||
|
||||
/// `tauri::App` package information.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PackageInfo {
|
||||
@ -112,4 +115,7 @@ pub enum Error {
|
||||
/// IO error
|
||||
#[error("{0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
/// Invalid pattern.
|
||||
#[error("invalid pattern `{0}`. Expected either `brownfield` or `isolation`.")]
|
||||
InvalidPattern(String),
|
||||
}
|
||||
|
115
core/tauri-utils/src/pattern/isolation.js
Normal file
115
core/tauri-utils/src/pattern/isolation.js
Normal file
@ -0,0 +1,115 @@
|
||||
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* IMPORTANT: See ipc.js for the main frame implementation.
|
||||
* main frame -> isolation frame = isolation payload
|
||||
* isolation frame -> main frame = isolation message
|
||||
*/
|
||||
|
||||
;(async function () {
|
||||
/**
|
||||
* Sends the message to the isolation frame.
|
||||
* @param {any} message
|
||||
*/
|
||||
function sendMessage(message) {
|
||||
window.parent.postMessage(message, '*')
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {Uint8Array} - Injected by Tauri during runtime
|
||||
*/
|
||||
const aesGcmKeyRaw = new Uint8Array(__TEMPLATE_runtime_aes_gcm_key__)
|
||||
|
||||
/**
|
||||
* @type {CryptoKey}
|
||||
*/
|
||||
const aesGcmKey = await window.crypto.subtle.importKey(
|
||||
'raw',
|
||||
aesGcmKeyRaw,
|
||||
'AES-GCM',
|
||||
true,
|
||||
['encrypt']
|
||||
)
|
||||
|
||||
/**
|
||||
* @param {object} data
|
||||
* @return {Promise<{nonce: number[], payload: number[]}>}
|
||||
*/
|
||||
async function encrypt(data) {
|
||||
let algorithm = Object.create(null)
|
||||
algorithm.name = 'AES-GCM'
|
||||
algorithm.iv = window.crypto.getRandomValues(new Uint8Array(12))
|
||||
|
||||
let encoder = new TextEncoder()
|
||||
let payloadRaw = encoder.encode(JSON.stringify(data))
|
||||
|
||||
return window.crypto.subtle
|
||||
.encrypt(algorithm, aesGcmKey, payloadRaw)
|
||||
.then((payload) => {
|
||||
let result = Object.create(null)
|
||||
result.nonce = Array.from(new Uint8Array(algorithm.iv))
|
||||
result.payload = Array.from(new Uint8Array(payload))
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect if a message event is a valid isolation payload.
|
||||
*
|
||||
* @param {MessageEvent<object>} event - a message event that is expected to be an isolation payload
|
||||
* @return boolean
|
||||
*/
|
||||
function isIsolationPayload(event) {
|
||||
return (
|
||||
typeof event.data === 'object' &&
|
||||
'callback' in event.data &&
|
||||
'error' in event.data
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle incoming payload events.
|
||||
* @param {MessageEvent<any>} event
|
||||
*/
|
||||
async function payloadHandler(event) {
|
||||
if (!isIsolationPayload(event)) {
|
||||
return
|
||||
}
|
||||
|
||||
let data = event.data
|
||||
|
||||
if (typeof window.__TAURI_ISOLATION_HOOK__ === 'function') {
|
||||
// await even if it's not async so that we can support async ones
|
||||
data = await window.__TAURI_ISOLATION_HOOK__(data)
|
||||
}
|
||||
|
||||
const encrypted = await encrypt(data)
|
||||
sendMessage(encrypted)
|
||||
}
|
||||
|
||||
window.addEventListener('message', payloadHandler, false)
|
||||
|
||||
/**
|
||||
* @type {number} - How many milliseconds to wait between ready checks
|
||||
*/
|
||||
const readyIntervalMs = 50
|
||||
|
||||
/**
|
||||
* Wait until this Isolation context is ready to receive messages, and let the main frame know.
|
||||
*/
|
||||
function waitUntilReady() {
|
||||
// consider either a function or an explicitly set null value as the ready signal
|
||||
if (
|
||||
typeof window.__TAURI_ISOLATION_HOOK__ === 'function' ||
|
||||
window.__TAURI_ISOLATION_HOOK__ === null
|
||||
) {
|
||||
sendMessage('__TAURI_ISOLATION_READY__')
|
||||
} else {
|
||||
setTimeout(waitUntilReady, readyIntervalMs)
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(waitUntilReady, readyIntervalMs)
|
||||
})()
|
164
core/tauri-utils/src/pattern/isolation.rs
Normal file
164
core/tauri-utils/src/pattern/isolation.rs
Normal file
@ -0,0 +1,164 @@
|
||||
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::array::TryFromSliceError;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::string::FromUtf8Error;
|
||||
|
||||
use aes_gcm::aead::Aead;
|
||||
use aes_gcm::{aead::NewAead, Aes256Gcm, Nonce};
|
||||
use once_cell::sync::OnceCell;
|
||||
use ring::error::Unspecified;
|
||||
use ring::rand::SystemRandom;
|
||||
use serialize_to_javascript::{default_template, Template};
|
||||
|
||||
/// Cryptographically secure pseudo-random number generator.
|
||||
static RNG: OnceCell<SystemRandom> = OnceCell::new();
|
||||
|
||||
/// The style for the isolation iframe.
|
||||
pub const IFRAME_STYLE: &str = "#__tauri_isolation__ { display: none !important }";
|
||||
|
||||
/// Errors that can occur during Isolation keys generation.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[non_exhaustive]
|
||||
pub enum Error {
|
||||
/// Something went wrong with the CSPRNG.
|
||||
#[error("Unspecified CSPRNG error")]
|
||||
Csprng,
|
||||
|
||||
/// Something went wrong with decryping an AES-GCM payload
|
||||
#[error("AES-GCM")]
|
||||
Aes,
|
||||
|
||||
/// Nonce was not 96 bits
|
||||
#[error("Nonce: {0}")]
|
||||
NonceSize(#[from] TryFromSliceError),
|
||||
|
||||
/// Payload was not valid utf8
|
||||
#[error("{0}")]
|
||||
Utf8(#[from] FromUtf8Error),
|
||||
|
||||
/// Invalid json format
|
||||
#[error("{0}")]
|
||||
Json(#[from] serde_json::Error),
|
||||
}
|
||||
|
||||
impl From<Unspecified> for Error {
|
||||
fn from(_: Unspecified) -> Self {
|
||||
Self::Csprng
|
||||
}
|
||||
}
|
||||
|
||||
/// A formatted AES-GCM cipher instance along with the key used to initialize it.
|
||||
#[derive(Clone)]
|
||||
pub struct AesGcmPair {
|
||||
raw: [u8; 32],
|
||||
key: Aes256Gcm,
|
||||
}
|
||||
|
||||
impl Debug for AesGcmPair {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "AesGcmPair(...)")
|
||||
}
|
||||
}
|
||||
|
||||
impl AesGcmPair {
|
||||
fn new() -> Result<Self, Error> {
|
||||
let rng = RNG.get_or_init(SystemRandom::new);
|
||||
let raw: [u8; 32] = ring::rand::generate(rng)?.expose();
|
||||
let key = aes_gcm::Key::from_slice(&raw);
|
||||
Ok(Self {
|
||||
raw,
|
||||
key: Aes256Gcm::new(key),
|
||||
})
|
||||
}
|
||||
|
||||
/// The raw value used to create the AES-GCM key
|
||||
pub fn raw(&self) -> &[u8; 32] {
|
||||
&self.raw
|
||||
}
|
||||
|
||||
/// The formatted AES-GCM key
|
||||
pub fn key(&self) -> &Aes256Gcm {
|
||||
&self.key
|
||||
}
|
||||
}
|
||||
|
||||
/// All cryptographic keys required for Isolation encryption
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Keys {
|
||||
/// AES-GCM key
|
||||
aes_gcm: AesGcmPair,
|
||||
}
|
||||
|
||||
impl Keys {
|
||||
/// Securely generate required keys for Isolation encryption.
|
||||
pub fn new() -> Result<Self, Error> {
|
||||
AesGcmPair::new()
|
||||
.map(|aes_gcm| Self { aes_gcm })
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// The AES-GCM data (and raw data).
|
||||
pub fn aes_gcm(&self) -> &AesGcmPair {
|
||||
&self.aes_gcm
|
||||
}
|
||||
|
||||
/// Decrypts a message using the generated keys.
|
||||
pub fn decrypt(&self, raw: RawIsolationPayload<'_>) -> Result<String, Error> {
|
||||
let RawIsolationPayload { nonce, payload } = raw;
|
||||
let nonce: [u8; 12] = nonce.as_ref().try_into()?;
|
||||
let bytes = self
|
||||
.aes_gcm
|
||||
.key
|
||||
.decrypt(Nonce::from_slice(&nonce), payload.as_ref())
|
||||
.map_err(|_| self::Error::Aes)?;
|
||||
|
||||
String::from_utf8(bytes).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
/// Raw representation of
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
pub struct RawIsolationPayload<'a> {
|
||||
nonce: Cow<'a, [u8]>,
|
||||
payload: Cow<'a, [u8]>,
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<&'a str> for RawIsolationPayload<'a> {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(value: &'a str) -> Result<Self, Self::Error> {
|
||||
serde_json::from_str(value).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
/// The Isolation JavaScript template meant to be injected during codegen.
|
||||
///
|
||||
/// Note: This struct is not considered part of the stable API
|
||||
#[derive(Template)]
|
||||
#[default_template("isolation.js")]
|
||||
pub struct IsolationJavascriptCodegen {
|
||||
// this template intentionally does not include the runtime field
|
||||
}
|
||||
|
||||
/// The Isolation JavaScript template meant to be injected during runtime.
|
||||
///
|
||||
/// Note: This struct is not considered part of the stable API
|
||||
#[derive(Template)]
|
||||
#[default_template("isolation.js")]
|
||||
pub struct IsolationJavascriptRuntime<'a> {
|
||||
/// The key used on the Rust backend and the Isolation Javascript
|
||||
pub runtime_aes_gcm_key: &'a [u8; 32],
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#[test]
|
||||
fn create_keys() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let _ = super::Keys::new()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
7
core/tauri-utils/src/pattern/mod.rs
Normal file
7
core/tauri-utils/src/pattern/mod.rs
Normal file
@ -0,0 +1,7 @@
|
||||
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/// Handling the Tauri "Isolation" Pattern.
|
||||
#[cfg(feature = "isolation")]
|
||||
pub mod isolation;
|
@ -3,7 +3,7 @@ authors = ["Tauri Programme within The Commons Conservancy"]
|
||||
categories = ["gui", "web-programming"]
|
||||
description = "Make tiny, secure apps for all desktop platforms with Tauri"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
exclude = [
|
||||
"/test",
|
||||
"/.scripts",
|
||||
@ -77,6 +77,7 @@ epi = { git = "https://github.com/wusyong/egui", branch = "tao", optional = true
|
||||
regex = "1.5"
|
||||
glob = "0.3"
|
||||
data-url = "0.1"
|
||||
serialize-to-javascript = { git = "https://github.com/chippers/serialize-to-javascript" }
|
||||
|
||||
[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
|
||||
glib = "0.14"
|
||||
@ -99,10 +100,14 @@ tauri = {path = "."}
|
||||
tokio-test = "0.4.2"
|
||||
tokio = { version = "1.15", features = [ "full" ] }
|
||||
|
||||
[target."cfg(windows)".dev-dependencies]
|
||||
webview2-com = "0.7.0"
|
||||
|
||||
[features]
|
||||
default = [ "wry", "compression" ]
|
||||
compression = [ "tauri-macros/compression", "tauri-utils/compression" ]
|
||||
wry = ["tauri-runtime-wry"]
|
||||
isolation = ["tauri-utils/isolation", "tauri-macros/isolation"]
|
||||
custom-protocol = ["tauri-macros/custom-protocol"]
|
||||
updater = ["minisign-verify", "base64", "dialog-ask"]
|
||||
http-api = ["attohttpc"]
|
||||
@ -233,10 +238,12 @@ path = "../../examples/helloworld/src-tauri/src/main.rs"
|
||||
[[example]]
|
||||
name = "multiwindow"
|
||||
path = "../../examples/multiwindow/src-tauri/src/main.rs"
|
||||
required-features = [ "window-create" ]
|
||||
|
||||
[[example]]
|
||||
name = "navigation"
|
||||
path = "../../examples/navigation/src-tauri/src/main.rs"
|
||||
required-features = [ "window-create" ]
|
||||
|
||||
[[example]]
|
||||
name = "splashscreen"
|
||||
@ -249,3 +256,8 @@ path = "../../examples/state/src-tauri/src/main.rs"
|
||||
[[example]]
|
||||
name = "streaming"
|
||||
path = "../../examples/streaming/src-tauri/src/main.rs"
|
||||
|
||||
[[example]]
|
||||
name = "isolation"
|
||||
path = "../../examples/isolation/src-tauri/src/main.rs"
|
||||
required-features = [ "isolation" ]
|
||||
|
File diff suppressed because one or more lines are too long
@ -8,7 +8,9 @@
|
||||
}
|
||||
|
||||
if (!window.__TAURI__) {
|
||||
window.__TAURI__ = {}
|
||||
Object.defineProperty(window, '__TAURI__', {
|
||||
value: {}
|
||||
})
|
||||
}
|
||||
|
||||
window.__TAURI__.transformCallback = function transformCallback(
|
||||
@ -33,7 +35,20 @@
|
||||
return identifier
|
||||
}
|
||||
|
||||
window.__TAURI_INVOKE__ = function invoke(cmd, args = {}, key = null) {
|
||||
const ipcQueue = []
|
||||
let isWaitingForIpc = false
|
||||
|
||||
function waitForIpc() {
|
||||
if ('__TAURI_IPC__' in window) {
|
||||
for (const action of ipcQueue) {
|
||||
action()
|
||||
}
|
||||
} else {
|
||||
setTimeout(waitForIpc, 50)
|
||||
}
|
||||
}
|
||||
|
||||
window.__TAURI_INVOKE__ = function invoke(cmd, args = {}) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var callback = window.__TAURI__.transformCallback(function (r) {
|
||||
resolve(r)
|
||||
@ -52,25 +67,21 @@
|
||||
return reject(new Error('Invalid argument type.'))
|
||||
}
|
||||
|
||||
if (
|
||||
document.readyState === 'complete' ||
|
||||
document.readyState === 'interactive'
|
||||
) {
|
||||
window.__TAURI_POST_MESSAGE__(cmd, {
|
||||
const action = () => {
|
||||
window.__TAURI_IPC__({
|
||||
...args,
|
||||
callback: callback,
|
||||
error: error,
|
||||
__invokeKey: key || __TAURI_INVOKE_KEY__
|
||||
callback,
|
||||
error: error
|
||||
})
|
||||
}
|
||||
if (window.__TAURI_IPC__) {
|
||||
action()
|
||||
} else {
|
||||
window.addEventListener('DOMContentLoaded', function () {
|
||||
window.__TAURI_POST_MESSAGE__(cmd, {
|
||||
...args,
|
||||
callback: callback,
|
||||
error: error,
|
||||
__invokeKey: key || __TAURI_INVOKE_KEY__
|
||||
})
|
||||
})
|
||||
ipcQueue.push(action)
|
||||
if (!isWaitingForIpc) {
|
||||
waitForIpc()
|
||||
isWaitingForIpc = true
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -88,17 +99,13 @@
|
||||
target.href.startsWith('http') &&
|
||||
target.target === '_blank'
|
||||
) {
|
||||
window.__TAURI_INVOKE__(
|
||||
'tauri',
|
||||
{
|
||||
__tauriModule: 'Shell',
|
||||
message: {
|
||||
cmd: 'open',
|
||||
path: target.href
|
||||
}
|
||||
},
|
||||
_KEY_VALUE_
|
||||
)
|
||||
window.__TAURI_INVOKE__('tauri', {
|
||||
__tauriModule: 'Shell',
|
||||
message: {
|
||||
cmd: 'open',
|
||||
path: target.href
|
||||
}
|
||||
})
|
||||
e.preventDefault()
|
||||
}
|
||||
break
|
||||
@ -129,43 +136,35 @@
|
||||
document.addEventListener('mousedown', (e) => {
|
||||
if (e.target.hasAttribute('data-tauri-drag-region') && e.buttons === 1) {
|
||||
// start dragging if the element has a `tauri-drag-region` data attribute and maximize on double-clicking it
|
||||
window.__TAURI_INVOKE__(
|
||||
'tauri',
|
||||
{
|
||||
__tauriModule: 'Window',
|
||||
message: {
|
||||
cmd: 'manage',
|
||||
data: {
|
||||
cmd: {
|
||||
type: e.detail === 2 ? '__toggleMaximize' : 'startDragging'
|
||||
}
|
||||
window.__TAURI_INVOKE__('tauri', {
|
||||
__tauriModule: 'Window',
|
||||
message: {
|
||||
cmd: 'manage',
|
||||
data: {
|
||||
cmd: {
|
||||
type: e.detail === 2 ? '__toggleMaximize' : 'startDragging'
|
||||
}
|
||||
}
|
||||
},
|
||||
_KEY_VALUE_
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
window.__TAURI_INVOKE__(
|
||||
'tauri',
|
||||
{
|
||||
__tauriModule: 'Event',
|
||||
message: {
|
||||
cmd: 'listen',
|
||||
event: 'tauri://window-created',
|
||||
handler: window.__TAURI__.transformCallback(function (event) {
|
||||
if (event.payload) {
|
||||
var windowLabel = event.payload.label
|
||||
window.__TAURI__.__windows.push({
|
||||
label: windowLabel
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
_KEY_VALUE_
|
||||
)
|
||||
window.__TAURI_INVOKE__('tauri', {
|
||||
__tauriModule: 'Event',
|
||||
message: {
|
||||
cmd: 'listen',
|
||||
event: 'tauri://window-created',
|
||||
handler: window.__TAURI__.transformCallback(function (event) {
|
||||
if (event.payload) {
|
||||
var windowLabel = event.payload.label
|
||||
window.__TAURI__.__windows.push({
|
||||
label: windowLabel
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
let permissionSettable = false
|
||||
let permissionValue = 'default'
|
||||
@ -174,16 +173,12 @@
|
||||
if (window.Notification.permission !== 'default') {
|
||||
return Promise.resolve(window.Notification.permission === 'granted')
|
||||
}
|
||||
return window.__TAURI_INVOKE__(
|
||||
'tauri',
|
||||
{
|
||||
__tauriModule: 'Notification',
|
||||
message: {
|
||||
cmd: 'isNotificationPermissionGranted'
|
||||
}
|
||||
},
|
||||
_KEY_VALUE_
|
||||
)
|
||||
return window.__TAURI_INVOKE__('tauri', {
|
||||
__tauriModule: 'Notification',
|
||||
message: {
|
||||
cmd: 'isNotificationPermissionGranted'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function setNotificationPermission(value) {
|
||||
@ -194,16 +189,12 @@
|
||||
|
||||
function requestPermission() {
|
||||
return window
|
||||
.__TAURI_INVOKE__(
|
||||
'tauri',
|
||||
{
|
||||
__tauriModule: 'Notification',
|
||||
message: {
|
||||
cmd: 'requestNotificationPermission'
|
||||
}
|
||||
},
|
||||
_KEY_VALUE_
|
||||
)
|
||||
.__TAURI_INVOKE__('tauri', {
|
||||
__tauriModule: 'Notification',
|
||||
message: {
|
||||
cmd: 'requestNotificationPermission'
|
||||
}
|
||||
})
|
||||
.then(function (permission) {
|
||||
setNotificationPermission(permission)
|
||||
return permission
|
||||
@ -215,20 +206,18 @@
|
||||
Object.freeze(options)
|
||||
}
|
||||
|
||||
return window.__TAURI_INVOKE__(
|
||||
'tauri', {
|
||||
__tauriModule: 'Notification',
|
||||
message: {
|
||||
cmd: 'notification',
|
||||
options: typeof options === 'string' ?
|
||||
{
|
||||
title: options
|
||||
} :
|
||||
options
|
||||
}
|
||||
},
|
||||
_KEY_VALUE_
|
||||
)
|
||||
return window.__TAURI_INVOKE__('tauri', {
|
||||
__tauriModule: 'Notification',
|
||||
message: {
|
||||
cmd: 'notification',
|
||||
options:
|
||||
typeof options === 'string'
|
||||
? {
|
||||
title: options
|
||||
}
|
||||
: options
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
window.Notification = function (title, options) {
|
||||
@ -264,51 +253,39 @@
|
||||
})
|
||||
|
||||
window.alert = function (message) {
|
||||
window.__TAURI_INVOKE__(
|
||||
'tauri',
|
||||
{
|
||||
__tauriModule: 'Dialog',
|
||||
message: {
|
||||
cmd: 'messageDialog',
|
||||
message: message
|
||||
}
|
||||
},
|
||||
_KEY_VALUE_
|
||||
)
|
||||
window.__TAURI_INVOKE__('tauri', {
|
||||
__tauriModule: 'Dialog',
|
||||
message: {
|
||||
cmd: 'messageDialog',
|
||||
message: message
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
window.confirm = function (message) {
|
||||
return window.__TAURI_INVOKE__(
|
||||
'tauri',
|
||||
{
|
||||
__tauriModule: 'Dialog',
|
||||
message: {
|
||||
cmd: 'confirmDialog',
|
||||
message: message
|
||||
}
|
||||
},
|
||||
_KEY_VALUE_
|
||||
)
|
||||
return window.__TAURI_INVOKE__('tauri', {
|
||||
__tauriModule: 'Dialog',
|
||||
message: {
|
||||
cmd: 'confirmDialog',
|
||||
message: message
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// window.print works on Linux/Windows; need to use the API on macOS
|
||||
if (navigator.userAgent.includes('Mac')) {
|
||||
window.print = function () {
|
||||
return window.__TAURI_INVOKE__(
|
||||
'tauri',
|
||||
{
|
||||
__tauriModule: 'Window',
|
||||
message: {
|
||||
cmd: 'manage',
|
||||
data: {
|
||||
cmd: {
|
||||
type: 'print'
|
||||
}
|
||||
return window.__TAURI_INVOKE__('tauri', {
|
||||
__tauriModule: 'Window',
|
||||
message: {
|
||||
cmd: 'manage',
|
||||
data: {
|
||||
cmd: {
|
||||
type: 'print'
|
||||
}
|
||||
}
|
||||
},
|
||||
_KEY_VALUE_
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})()
|
||||
|
5
core/tauri/scripts/freeze_prototype.js
Normal file
5
core/tauri/scripts/freeze_prototype.js
Normal file
@ -0,0 +1,5 @@
|
||||
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
Object.freeze(Object.prototype)
|
26
core/tauri/scripts/init.js
Normal file
26
core/tauri/scripts/init.js
Normal file
@ -0,0 +1,26 @@
|
||||
;(function () {
|
||||
if (window.location.origin.startsWith(__TEMPLATE_origin__)) {
|
||||
__RAW_freeze_prototype__
|
||||
|
||||
__RAW_pattern_script__
|
||||
|
||||
__RAW_ipc_script__
|
||||
;(function () {
|
||||
__RAW_bundle_script__
|
||||
})()
|
||||
|
||||
__RAW_core_script__
|
||||
|
||||
__RAW_event_initialization_script__
|
||||
|
||||
if (window.ipc) {
|
||||
window.__TAURI_INVOKE__('__initialized', { url: window.location.href })
|
||||
} else {
|
||||
window.addEventListener('DOMContentLoaded', function () {
|
||||
window.__TAURI_INVOKE__('__initialized', { url: window.location.href })
|
||||
})
|
||||
}
|
||||
|
||||
__RAW_plugin_initialization_script__
|
||||
}
|
||||
})()
|
153
core/tauri/scripts/ipc.js
Normal file
153
core/tauri/scripts/ipc.js
Normal file
@ -0,0 +1,153 @@
|
||||
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @typedef {{callback: string, error: string, data: *}} IsolationPayload - a valid isolation payload
|
||||
*/
|
||||
|
||||
;
|
||||
(function () {
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
const pattern = window.__TAURI_PATTERN__.pattern
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
const isolationOrigin = __TEMPLATE_isolation_origin__
|
||||
|
||||
/**
|
||||
* @type {{queue: object[], ready: boolean, frame: HTMLElement | null}}
|
||||
*/
|
||||
const isolation = Object.create(null)
|
||||
isolation.queue = []
|
||||
isolation.ready = false
|
||||
isolation.frame = null
|
||||
|
||||
/**
|
||||
* Detects if a message event is a valid isolation message.
|
||||
*
|
||||
* @param {MessageEvent<object>} event - a message event that is expected to be an isolation message
|
||||
* @return {boolean} - if the event was a valid isolation message
|
||||
*/
|
||||
function isIsolationMessage(event) {
|
||||
return (
|
||||
typeof event.data === 'object' &&
|
||||
'nonce' in event.data &&
|
||||
'payload' in event.data
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects if data is able to transform into an isolation payload.
|
||||
*
|
||||
* @param {object} data - object that is expected to contain at least a callback and error identifier
|
||||
* @return {boolean} - if the data is able to transform into an isolation payload
|
||||
*/
|
||||
function isIsolationPayload(data) {
|
||||
return typeof data === 'object' && 'callback' in data && 'error' in data
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a properly formatted message to the isolation frame.
|
||||
*
|
||||
* @param {IsolationPayload} data - data that has been validated to be an isolation payload
|
||||
*/
|
||||
function sendIsolationMessage(data) {
|
||||
// set the frame dom element if it's not been set before
|
||||
if (!isolation.frame) {
|
||||
const frame = document.querySelector('iframe#__tauri_isolation__')
|
||||
if (frame.src.startsWith(isolationOrigin)) {
|
||||
isolation.frame = frame
|
||||
} else {
|
||||
console.error(
|
||||
'Tauri IPC found an isolation iframe, but it had the wrong origin'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// ensure we have the target to send the message to
|
||||
if (!isolation.frame || !isolation.frame.contentWindow) {
|
||||
console.error(
|
||||
'Tauri "Isolation" Pattern could not find the Isolation iframe window'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
isolation.frame.contentWindow.postMessage(
|
||||
data,
|
||||
'*' /* todo: set this to the secure origin */
|
||||
)
|
||||
}
|
||||
|
||||
Object.defineProperty(window, '__TAURI_IPC__', {
|
||||
// todo: JSDoc this function
|
||||
value: Object.freeze((message) => {
|
||||
switch (pattern) {
|
||||
case 'brownfield':
|
||||
window.__TAURI_POST_MESSAGE__(message)
|
||||
break
|
||||
|
||||
case 'isolation':
|
||||
if (!isIsolationPayload(message)) {
|
||||
console.error(
|
||||
'Tauri "Isolation" Pattern found an invalid isolation message payload',
|
||||
message
|
||||
)
|
||||
break
|
||||
}
|
||||
|
||||
if (isolation.ready) {
|
||||
sendIsolationMessage(message)
|
||||
} else {
|
||||
isolation.queue.push(message)
|
||||
}
|
||||
|
||||
break
|
||||
|
||||
case 'error':
|
||||
console.error(
|
||||
'Tauri IPC found a Tauri Pattern, but it was an error. Check for other log messages to find the cause.'
|
||||
)
|
||||
break
|
||||
|
||||
default:
|
||||
console.error(
|
||||
'Tauri IPC did not find a Tauri Pattern that it understood.'
|
||||
)
|
||||
break
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* IMPORTANT: See isolation_secure.js for the isolation frame implementation.
|
||||
* main frame -> isolation frame = isolation payload
|
||||
* isolation frame -> main frame = isolation message
|
||||
*/
|
||||
if (pattern === 'isolation') {
|
||||
window.addEventListener(
|
||||
'message',
|
||||
(event) => {
|
||||
// watch for the isolation frame being ready and flush any queued messages
|
||||
if (event.data === '__TAURI_ISOLATION_READY__') {
|
||||
isolation.ready = true
|
||||
|
||||
for (const message of isolation.queue) {
|
||||
sendIsolationMessage(message)
|
||||
}
|
||||
|
||||
isolation.queue = []
|
||||
return
|
||||
}
|
||||
|
||||
if (isIsolationMessage(event)) {
|
||||
window.__TAURI_POST_MESSAGE__(event.data)
|
||||
}
|
||||
},
|
||||
false
|
||||
)
|
||||
}
|
||||
})()
|
15
core/tauri/scripts/isolation.js
Normal file
15
core/tauri/scripts/isolation.js
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
let style = document.createElement('style')
|
||||
style.textContent = __TEMPLATE_style__
|
||||
document.head.append(style)
|
||||
|
||||
let iframe = document.createElement('iframe')
|
||||
iframe.id = '__tauri_isolation__'
|
||||
iframe.sandbox.add('allow-scripts')
|
||||
iframe.src = __TEMPLATE_isolation_src__
|
||||
document.body.append(iframe)
|
||||
})
|
21
core/tauri/scripts/pattern.js
Normal file
21
core/tauri/scripts/pattern.js
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
;(function () {
|
||||
function __tauriDeepFreeze(object) {
|
||||
const props = Object.getOwnPropertyNames(object)
|
||||
|
||||
for (const prop of props) {
|
||||
if (typeof object[name] === 'object') {
|
||||
__tauriDeepFreeze(object[name])
|
||||
}
|
||||
}
|
||||
|
||||
return Object.freeze(object)
|
||||
}
|
||||
|
||||
Object.defineProperty(window, '__TAURI_PATTERN__', {
|
||||
value: __tauriDeepFreeze(__TEMPLATE_pattern__)
|
||||
})
|
||||
})()
|
@ -47,24 +47,28 @@ impl FileDialogBuilder {
|
||||
}
|
||||
|
||||
/// Add file extension filter. Takes in the name of the filter, and list of extensions
|
||||
#[must_use]
|
||||
pub fn add_filter(mut self, name: impl AsRef<str>, extensions: &[&str]) -> Self {
|
||||
self.0 = self.0.add_filter(name.as_ref(), extensions);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set starting directory of the dialog.
|
||||
#[must_use]
|
||||
pub fn set_directory<P: AsRef<Path>>(mut self, directory: P) -> Self {
|
||||
self.0 = self.0.set_directory(directory);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set starting file name of the dialog.
|
||||
#[must_use]
|
||||
pub fn set_file_name(mut self, file_name: &str) -> Self {
|
||||
self.0 = self.0.set_file_name(file_name);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the parent window of the dialog.
|
||||
#[must_use]
|
||||
pub fn set_parent<W: raw_window_handle::HasRawWindowHandle>(mut self, parent: &W) -> Self {
|
||||
self.0 = self.0.set_parent(parent);
|
||||
self
|
||||
|
@ -29,12 +29,14 @@ impl ClientBuilder {
|
||||
}
|
||||
|
||||
/// Sets the maximum number of redirections.
|
||||
#[must_use]
|
||||
pub fn max_redirections(mut self, max_redirections: usize) -> Self {
|
||||
self.max_redirections = Some(max_redirections);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the connection timeout.
|
||||
#[must_use]
|
||||
pub fn connect_timeout(mut self, connect_timeout: u64) -> Self {
|
||||
self.connect_timeout = Some(connect_timeout);
|
||||
self
|
||||
@ -294,30 +296,35 @@ impl HttpRequestBuilder {
|
||||
}
|
||||
|
||||
/// Sets the request parameters.
|
||||
#[must_use]
|
||||
pub fn query(mut self, query: HashMap<String, String>) -> Self {
|
||||
self.query = Some(query);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the request headers.
|
||||
#[must_use]
|
||||
pub fn headers(mut self, headers: HashMap<String, String>) -> Self {
|
||||
self.headers = Some(headers);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the request body.
|
||||
#[must_use]
|
||||
pub fn body(mut self, body: Body) -> Self {
|
||||
self.body = Some(body);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the general request timeout.
|
||||
#[must_use]
|
||||
pub fn timeout(mut self, timeout: u64) -> Self {
|
||||
self.timeout = Some(timeout);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the type of the response. Interferes with the way we read the response.
|
||||
#[must_use]
|
||||
pub fn response_type(mut self, response_type: ResponseType) -> Self {
|
||||
self.response_type = Some(response_type);
|
||||
self
|
||||
|
@ -43,18 +43,21 @@ impl Notification {
|
||||
}
|
||||
|
||||
/// Sets the notification body.
|
||||
#[must_use]
|
||||
pub fn body(mut self, body: impl Into<String>) -> Self {
|
||||
self.body = Some(body.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the notification title.
|
||||
#[must_use]
|
||||
pub fn title(mut self, title: impl Into<String>) -> Self {
|
||||
self.title = Some(title.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the notification icon.
|
||||
#[must_use]
|
||||
pub fn icon(mut self, icon: impl Into<String>) -> Self {
|
||||
self.icon = Some(icon.into());
|
||||
self
|
||||
|
@ -134,8 +134,7 @@ pub fn parse<P: AsRef<Path>>(
|
||||
let mut p = PathBuf::new();
|
||||
let mut components = path.as_ref().components();
|
||||
if let Some(Component::Normal(str)) = components.next() {
|
||||
if let Some(base_directory) = BaseDirectory::from_variable(&str.to_string_lossy().into_owned())
|
||||
{
|
||||
if let Some(base_directory) = BaseDirectory::from_variable(&str.to_string_lossy()) {
|
||||
p.push(resolve_path(
|
||||
config,
|
||||
package_info,
|
||||
|
@ -192,6 +192,7 @@ impl Command {
|
||||
}
|
||||
|
||||
/// Appends arguments to the command.
|
||||
#[must_use]
|
||||
pub fn args<I, S>(mut self, args: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
@ -204,18 +205,21 @@ impl Command {
|
||||
}
|
||||
|
||||
/// Clears the entire environment map for the child process.
|
||||
#[must_use]
|
||||
pub fn env_clear(mut self) -> Self {
|
||||
self.env_clear = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds or updates multiple environment variable mappings.
|
||||
#[must_use]
|
||||
pub fn envs(mut self, env: HashMap<String, String>) -> Self {
|
||||
self.env = env;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the working directory for the child process.
|
||||
#[must_use]
|
||||
pub fn current_dir(mut self, current_dir: PathBuf) -> Self {
|
||||
self.current_dir.replace(current_dir);
|
||||
self
|
||||
|
@ -36,7 +36,6 @@ impl FromStr for Program {
|
||||
type Err = super::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
#[allow(clippy::match_str_case_mismatch)]
|
||||
let p = match s.to_lowercase().as_str() {
|
||||
"open" => Self::Open,
|
||||
"start" => Self::Start,
|
||||
|
@ -676,7 +676,7 @@ impl<R: Runtime> Builder<R> {
|
||||
invoke_handler: Box::new(|_| ()),
|
||||
invoke_responder: Arc::new(window_invoke_responder),
|
||||
invoke_initialization_script:
|
||||
"Object.defineProperty(window, '__TAURI_POST_MESSAGE__', { value: (command, args) => window.ipc.notify(JSON.stringify({{ ...args, command }})) })".into(),
|
||||
"Object.defineProperty(window, '__TAURI_POST_MESSAGE__', { value: (message) => window.ipc.postMessage(JSON.stringify(message)) })".into(),
|
||||
on_page_load: Box::new(|_, _| ()),
|
||||
pending_windows: Default::default(),
|
||||
plugins: PluginStore::default(),
|
||||
@ -693,6 +693,7 @@ impl<R: Runtime> Builder<R> {
|
||||
}
|
||||
|
||||
/// Defines the JS message handler callback.
|
||||
#[must_use]
|
||||
pub fn invoke_handler<F>(mut self, invoke_handler: F) -> Self
|
||||
where
|
||||
F: Fn(Invoke<R>) + Send + Sync + 'static,
|
||||
@ -706,7 +707,7 @@ impl<R: Runtime> Builder<R> {
|
||||
/// The `responder` is a function that will be called when a command has been executed and must send a response to the JS layer.
|
||||
///
|
||||
/// The `initialization_script` is a script that initializes `window.__TAURI_POST_MESSAGE__`.
|
||||
/// That function must take the `command: string` and `args: object` types and send a message to the backend.
|
||||
/// That function must take the `message: object` argument and send it to the backend.
|
||||
pub fn invoke_system<F>(mut self, initialization_script: String, responder: F) -> Self
|
||||
where
|
||||
F: Fn(Window<R>, InvokeResponse, CallbackFn, CallbackFn) + Send + Sync + 'static,
|
||||
@ -717,6 +718,7 @@ impl<R: Runtime> Builder<R> {
|
||||
}
|
||||
|
||||
/// Defines the setup hook.
|
||||
#[must_use]
|
||||
pub fn setup<F>(mut self, setup: F) -> Self
|
||||
where
|
||||
F: FnOnce(&mut App<R>) -> Result<(), Box<dyn std::error::Error + Send>> + Send + 'static,
|
||||
@ -726,6 +728,7 @@ impl<R: Runtime> Builder<R> {
|
||||
}
|
||||
|
||||
/// Defines the page load hook.
|
||||
#[must_use]
|
||||
pub fn on_page_load<F>(mut self, on_page_load: F) -> Self
|
||||
where
|
||||
F: Fn(Window<R>, PageLoadPayload) + Send + Sync + 'static,
|
||||
@ -735,6 +738,7 @@ impl<R: Runtime> Builder<R> {
|
||||
}
|
||||
|
||||
/// Adds a plugin to the runtime.
|
||||
#[must_use]
|
||||
pub fn plugin<P: Plugin<R> + 'static>(mut self, plugin: P) -> Self {
|
||||
self.plugins.register(plugin);
|
||||
self
|
||||
@ -815,6 +819,7 @@ impl<R: Runtime> Builder<R> {
|
||||
/// .expect("error while running tauri application");
|
||||
/// }
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub fn manage<T>(self, state: T) -> Self
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@ -829,6 +834,7 @@ impl<R: Runtime> Builder<R> {
|
||||
}
|
||||
|
||||
/// Creates a new webview window.
|
||||
#[must_use]
|
||||
pub fn create_window<F>(mut self, label: impl Into<String>, url: WindowUrl, setup: F) -> Self
|
||||
where
|
||||
F: FnOnce(
|
||||
@ -854,18 +860,21 @@ impl<R: Runtime> Builder<R> {
|
||||
/// Adds the icon configured on `tauri.conf.json` to the system tray with the specified menu items.
|
||||
#[cfg(feature = "system-tray")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "system-tray")))]
|
||||
#[must_use]
|
||||
pub fn system_tray(mut self, system_tray: tray::SystemTray) -> Self {
|
||||
self.system_tray.replace(system_tray);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the menu to use on all windows.
|
||||
#[must_use]
|
||||
pub fn menu(mut self, menu: Menu) -> Self {
|
||||
self.menu.replace(menu);
|
||||
self
|
||||
}
|
||||
|
||||
/// Registers a menu event handler for all windows.
|
||||
#[must_use]
|
||||
pub fn on_menu_event<F: Fn(WindowMenuEvent<R>) + Send + Sync + 'static>(
|
||||
mut self,
|
||||
handler: F,
|
||||
@ -875,6 +884,7 @@ impl<R: Runtime> Builder<R> {
|
||||
}
|
||||
|
||||
/// Registers a window event handler for all windows.
|
||||
#[must_use]
|
||||
pub fn on_window_event<F: Fn(GlobalWindowEvent<R>) + Send + Sync + 'static>(
|
||||
mut self,
|
||||
handler: F,
|
||||
@ -886,6 +896,7 @@ impl<R: Runtime> Builder<R> {
|
||||
/// Registers a system tray event handler.
|
||||
#[cfg(feature = "system-tray")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "system-tray")))]
|
||||
#[must_use]
|
||||
pub fn on_system_tray_event<
|
||||
F: Fn(&AppHandle<R>, tray::SystemTrayEvent) + Send + Sync + 'static,
|
||||
>(
|
||||
@ -905,6 +916,7 @@ impl<R: Runtime> Builder<R> {
|
||||
///
|
||||
/// * `uri_scheme` The URI scheme to register, such as `example`.
|
||||
/// * `protocol` the protocol associated with the given URI scheme. It's a function that takes an URL such as `example://localhost/asset.css`.
|
||||
#[must_use]
|
||||
pub fn register_uri_scheme_protocol<
|
||||
N: Into<String>,
|
||||
H: Fn(&AppHandle<R>, &HttpRequest) -> Result<HttpResponse, Box<dyn std::error::Error>>
|
||||
@ -1245,16 +1257,16 @@ impl Default for Builder<crate::Wry> {
|
||||
mod tests {
|
||||
#[test]
|
||||
fn is_send_sync() {
|
||||
crate::test::assert_send::<super::AppHandle>();
|
||||
crate::test::assert_sync::<super::AppHandle>();
|
||||
crate::test_utils::assert_send::<super::AppHandle>();
|
||||
crate::test_utils::assert_sync::<super::AppHandle>();
|
||||
|
||||
#[cfg(feature = "wry")]
|
||||
{
|
||||
crate::test::assert_send::<super::AssetResolver<crate::Wry>>();
|
||||
crate::test::assert_sync::<super::AssetResolver<crate::Wry>>();
|
||||
crate::test_utils::assert_send::<super::AssetResolver<crate::Wry>>();
|
||||
crate::test_utils::assert_sync::<super::AssetResolver<crate::Wry>>();
|
||||
}
|
||||
|
||||
crate::test::assert_send::<super::PathResolver>();
|
||||
crate::test::assert_sync::<super::PathResolver>();
|
||||
crate::test_utils::assert_send::<super::PathResolver>();
|
||||
crate::test_utils::assert_sync::<super::PathResolver>();
|
||||
}
|
||||
}
|
||||
|
@ -279,6 +279,7 @@ where
|
||||
runtime.spawn_blocking(func)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn safe_block_on<F>(task: F) -> F::Output
|
||||
where
|
||||
F: Future + Send + 'static,
|
||||
|
@ -19,7 +19,7 @@ impl Cmd {
|
||||
#[module_command_handler(cli, "CLI definition not set under tauri.conf.json > tauri > cli (https://tauri.studio/docs/api/config#tauri.cli)")]
|
||||
fn cli_matches<R: Runtime>(context: InvokeContext<R>) -> crate::Result<InvokeResponse> {
|
||||
if let Some(cli) = &context.config.tauri.cli {
|
||||
crate::api::cli::get_matches(cli, context.package_info)
|
||||
crate::api::cli::get_matches(cli, &context.package_info)
|
||||
.map(Into::into)
|
||||
.map_err(Into::into)
|
||||
} else {
|
||||
|
@ -15,6 +15,7 @@ use serde::{
|
||||
};
|
||||
use tauri_macros::{module_command_handler, CommandModule};
|
||||
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::{
|
||||
fs,
|
||||
fs::File,
|
||||
@ -334,8 +335,21 @@ fn resolve_path<R: Runtime>(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{BaseDirectory, DirOperationOptions, FileOperationOptions, SafePathBuf};
|
||||
|
||||
use quickcheck::{Arbitrary, Gen};
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
impl Arbitrary for super::SafePathBuf {
|
||||
fn arbitrary(g: &mut Gen) -> Self {
|
||||
Self(PathBuf::arbitrary(g))
|
||||
}
|
||||
|
||||
fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
|
||||
Box::new(self.0.shrink().map(SafePathBuf))
|
||||
}
|
||||
}
|
||||
|
||||
impl Arbitrary for BaseDirectory {
|
||||
fn arbitrary(g: &mut Gen) -> Self {
|
||||
if bool::arbitrary(g) {
|
||||
@ -363,12 +377,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
impl Arbitrary for SafePathBuf {
|
||||
fn arbitrary(g: &mut Gen) -> Self {
|
||||
SafePathBuf(std::path::PathBuf::arbitrary(g))
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri_macros::module_command_test(fs_read_file, "fs > readFile")]
|
||||
#[quickcheck_macros::quickcheck]
|
||||
fn read_file(path: SafePathBuf, options: Option<FileOperationOptions>) {
|
||||
|
@ -96,6 +96,10 @@ pub enum Error {
|
||||
/// Program not allowed by the scope.
|
||||
#[error("program not allowed on the configured shell scope: {0}")]
|
||||
ProgramNotAllowed(PathBuf),
|
||||
/// An error happened inside the isolation pattern.
|
||||
#[cfg(feature = "isolation")]
|
||||
#[error("isolation pattern error: {0}")]
|
||||
IsolationPattern(#[from] tauri_utils::pattern::isolation::Error),
|
||||
}
|
||||
|
||||
impl From<serde_json::Error> for Error {
|
||||
|
@ -10,6 +10,7 @@ use crate::{
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
use serialize_to_javascript::{default_template, Template};
|
||||
use std::{future::Future, sync::Arc};
|
||||
|
||||
use tauri_macros::default_runtime;
|
||||
@ -28,6 +29,21 @@ pub type InvokeResponder<R> =
|
||||
/// A closure that is run once every time a window is created and loaded.
|
||||
pub type OnPageLoad<R> = dyn Fn(Window<R>, PageLoadPayload) + Send + Sync + 'static;
|
||||
|
||||
// todo: why is this derive broken but the output works manually?
|
||||
#[derive(Template)]
|
||||
#[default_template("../scripts/ipc.js")]
|
||||
pub(crate) struct IpcJavascript<'a> {
|
||||
pub(crate) isolation_origin: &'a str,
|
||||
}
|
||||
|
||||
#[cfg(feature = "isolation")]
|
||||
#[derive(Template)]
|
||||
#[default_template("../scripts/isolation.js")]
|
||||
pub(crate) struct IsolationJavascript<'a> {
|
||||
pub(crate) isolation_src: &'a str,
|
||||
pub(crate) style: &'a str,
|
||||
}
|
||||
|
||||
/// The payload for the [`OnPageLoad`] hook.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct PageLoadPayload {
|
||||
@ -45,7 +61,7 @@ impl PageLoadPayload {
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct InvokePayload {
|
||||
/// The invoke command.
|
||||
pub command: String,
|
||||
pub cmd: String,
|
||||
#[serde(rename = "__tauriModule")]
|
||||
#[doc(hidden)]
|
||||
pub tauri_module: Option<String>,
|
||||
@ -53,9 +69,6 @@ pub struct InvokePayload {
|
||||
pub callback: CallbackFn,
|
||||
/// The error callback.
|
||||
pub error: CallbackFn,
|
||||
/// The invoke key.
|
||||
#[serde(rename = "__invokeKey")]
|
||||
pub key: u32,
|
||||
/// The payload of the message.
|
||||
#[serde(flatten)]
|
||||
pub inner: JsonValue,
|
||||
|
@ -11,6 +11,7 @@
|
||||
//! The following are a list of [Cargo features](https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section) that can be enabled or disabled:
|
||||
//!
|
||||
//! - **wry** *(enabled by default)*: Enables the [wry](https://github.com/tauri-apps/wry) runtime. Only disable it if you want a custom runtime.
|
||||
//! - **isolation**: Enables the isolation pattern. Enabled by default if the `tauri > pattern > use` config option is set to `isolation` on the `tauri.conf.json` file.
|
||||
//! - **custom-protocol**: Feature managed by the Tauri CLI. When enabled, Tauri assumes a production environment instead of a development one.
|
||||
//! - **updater**: Enables the application auto updater. Enabled by default if the `updater` config is defined on the `tauri.conf.json` file.
|
||||
//! - **http-api**: Enables the [`api::http`] module.
|
||||
@ -144,6 +145,7 @@ mod error;
|
||||
mod event;
|
||||
mod hooks;
|
||||
mod manager;
|
||||
mod pattern;
|
||||
pub mod plugin;
|
||||
pub mod window;
|
||||
pub use tauri_runtime as runtime;
|
||||
@ -255,6 +257,8 @@ macro_rules! tauri_build_context {
|
||||
};
|
||||
}
|
||||
|
||||
pub use pattern::Pattern;
|
||||
|
||||
/// User supplied data required inside of a Tauri application.
|
||||
///
|
||||
/// # Stability
|
||||
@ -267,6 +271,7 @@ pub struct Context<A: Assets> {
|
||||
pub(crate) system_tray_icon: Option<Icon>,
|
||||
pub(crate) package_info: PackageInfo,
|
||||
pub(crate) _info_plist: (),
|
||||
pub(crate) pattern: Pattern,
|
||||
}
|
||||
|
||||
impl<A: Assets> fmt::Debug for Context<A> {
|
||||
@ -276,6 +281,7 @@ impl<A: Assets> fmt::Debug for Context<A> {
|
||||
.field("default_window_icon", &self.default_window_icon)
|
||||
.field("system_tray_icon", &self.system_tray_icon)
|
||||
.field("package_info", &self.package_info)
|
||||
.field("pattern", &self.pattern)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
@ -341,6 +347,12 @@ impl<A: Assets> Context<A> {
|
||||
&mut self.package_info
|
||||
}
|
||||
|
||||
/// The application pattern.
|
||||
#[inline(always)]
|
||||
pub fn pattern(&self) -> &Pattern {
|
||||
&self.pattern
|
||||
}
|
||||
|
||||
/// Create a new [`Context`] from the minimal required items.
|
||||
#[inline(always)]
|
||||
pub fn new(
|
||||
@ -350,6 +362,7 @@ impl<A: Assets> Context<A> {
|
||||
system_tray_icon: Option<Icon>,
|
||||
package_info: PackageInfo,
|
||||
info_plist: (),
|
||||
pattern: Pattern,
|
||||
) -> Self {
|
||||
Self {
|
||||
config,
|
||||
@ -358,6 +371,7 @@ impl<A: Assets> Context<A> {
|
||||
system_tray_icon,
|
||||
package_info,
|
||||
_info_plist: info_plist,
|
||||
pattern,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -503,7 +517,7 @@ pub(crate) mod sealed {
|
||||
pub mod test;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
mod test_utils {
|
||||
use proptest::prelude::*;
|
||||
|
||||
pub fn assert_send<T: Send>() {}
|
||||
|
@ -2,6 +2,35 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::{HashMap, HashSet},
|
||||
fmt,
|
||||
fs::create_dir_all,
|
||||
sync::{Arc, Mutex, MutexGuard},
|
||||
};
|
||||
|
||||
use regex::{Captures, Regex};
|
||||
use serde::Serialize;
|
||||
use serde_json::Value as JsonValue;
|
||||
use serialize_to_javascript::{default_template, DefaultTemplate, Template};
|
||||
use url::Url;
|
||||
|
||||
use tauri_macros::default_runtime;
|
||||
#[cfg(feature = "isolation")]
|
||||
use tauri_utils::pattern::isolation::RawIsolationPayload;
|
||||
use tauri_utils::{
|
||||
assets::{AssetKey, CspHash},
|
||||
html::{inject_csp, parse as parse_html, SCRIPT_NONCE_TOKEN, STYLE_NONCE_TOKEN},
|
||||
};
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
use crate::api::path::{resolve_path, BaseDirectory};
|
||||
use crate::app::{GlobalMenuEventListener, WindowMenuEvent};
|
||||
use crate::hooks::IpcJavascript;
|
||||
#[cfg(feature = "isolation")]
|
||||
use crate::hooks::IsolationJavascript;
|
||||
use crate::pattern::{format_real_schema, PatternJavascript};
|
||||
use crate::{
|
||||
app::{AppHandle, GlobalWindowEvent, GlobalWindowEventListener},
|
||||
event::{is_event_name_valid, Event, EventHandler, Listeners},
|
||||
@ -21,36 +50,14 @@ use crate::{
|
||||
config::{AppUrl, Config, WindowUrl},
|
||||
PackageInfo,
|
||||
},
|
||||
Context, Invoke, StateManager, Window,
|
||||
Context, Invoke, Pattern, StateManager, Window,
|
||||
};
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
use crate::api::path::{resolve_path, BaseDirectory};
|
||||
|
||||
use crate::app::{GlobalMenuEventListener, WindowMenuEvent};
|
||||
|
||||
use crate::{runtime::menu::Menu, MenuEvent};
|
||||
|
||||
use regex::{Captures, Regex};
|
||||
use serde::Serialize;
|
||||
use serde_json::Value as JsonValue;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::{HashMap, HashSet},
|
||||
fmt,
|
||||
fs::create_dir_all,
|
||||
sync::{Arc, Mutex, MutexGuard},
|
||||
};
|
||||
use tauri_macros::default_runtime;
|
||||
use tauri_utils::{
|
||||
assets::{AssetKey, CspHash},
|
||||
html::{
|
||||
inject_csp, parse as parse_html, CSP_TOKEN, INVOKE_KEY_TOKEN, SCRIPT_NONCE_TOKEN,
|
||||
STYLE_NONCE_TOKEN,
|
||||
},
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
const WINDOW_RESIZED_EVENT: &str = "tauri://resize";
|
||||
const WINDOW_MOVED_EVENT: &str = "tauri://move";
|
||||
const WINDOW_CLOSE_REQUESTED_EVENT: &str = "tauri://close-requested";
|
||||
@ -67,6 +74,71 @@ struct CspHashStrings {
|
||||
style: String,
|
||||
}
|
||||
|
||||
/// Sets the CSP value to the asset HTML if needed (on Linux).
|
||||
/// Returns the CSP string for access on the response header (on Windows and macOS).
|
||||
fn set_csp<R: Runtime>(
|
||||
asset: &mut String,
|
||||
assets: Arc<dyn Assets>,
|
||||
asset_path: &AssetKey,
|
||||
#[allow(unused_variables)] manager: &WindowManager<R>,
|
||||
mut csp: String,
|
||||
) -> String {
|
||||
let hash_strings =
|
||||
assets
|
||||
.csp_hashes(asset_path)
|
||||
.fold(CspHashStrings::default(), |mut acc, hash| {
|
||||
match hash {
|
||||
CspHash::Script(hash) => {
|
||||
acc.script.push(' ');
|
||||
acc.script.push_str(hash);
|
||||
}
|
||||
CspHash::Style(hash) => {
|
||||
acc.style.push(' ');
|
||||
acc.style.push_str(hash);
|
||||
}
|
||||
_csp_hash => {
|
||||
#[cfg(debug_assertions)]
|
||||
eprintln!("Unknown CspHash variant encountered: {:?}", _csp_hash)
|
||||
}
|
||||
}
|
||||
|
||||
acc
|
||||
});
|
||||
|
||||
replace_csp_nonce(
|
||||
asset,
|
||||
SCRIPT_NONCE_TOKEN,
|
||||
&mut csp,
|
||||
"script-src",
|
||||
hash_strings.script,
|
||||
);
|
||||
|
||||
replace_csp_nonce(
|
||||
asset,
|
||||
STYLE_NONCE_TOKEN,
|
||||
&mut csp,
|
||||
"style-src",
|
||||
hash_strings.style,
|
||||
);
|
||||
|
||||
#[cfg(feature = "isolation")]
|
||||
if let Pattern::Isolation { schema, .. } = &manager.inner.pattern {
|
||||
let default_src = format!("default-src {}", format_real_schema(schema));
|
||||
if csp.contains("default-src") {
|
||||
csp = csp.replace("default-src", &default_src);
|
||||
} else {
|
||||
csp.push_str("; ");
|
||||
csp.push_str(&default_src);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
*asset = asset.replacen(tauri_utils::html::CSP_TOKEN, &csp, 1);
|
||||
}
|
||||
csp
|
||||
}
|
||||
|
||||
fn replace_csp_nonce(
|
||||
asset: &mut String,
|
||||
token: &str,
|
||||
@ -141,6 +213,8 @@ pub struct InnerWindowManager<R: Runtime> {
|
||||
invoke_responder: Arc<InvokeResponder<R>>,
|
||||
/// The script that initializes the invoke system.
|
||||
invoke_initialization_script: String,
|
||||
/// Application pattern.
|
||||
pattern: Pattern,
|
||||
}
|
||||
|
||||
impl<R: Runtime> fmt::Debug for InnerWindowManager<R> {
|
||||
@ -152,6 +226,7 @@ impl<R: Runtime> fmt::Debug for InnerWindowManager<R> {
|
||||
.field("default_window_icon", &self.default_window_icon)
|
||||
.field("package_info", &self.package_info)
|
||||
.field("menu", &self.menu)
|
||||
.field("pattern", &self.pattern)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
@ -181,14 +256,12 @@ pub struct CustomProtocol<R: Runtime> {
|
||||
#[derive(Debug)]
|
||||
pub struct WindowManager<R: Runtime> {
|
||||
pub inner: Arc<InnerWindowManager<R>>,
|
||||
invoke_keys: Arc<Mutex<Vec<u32>>>,
|
||||
}
|
||||
|
||||
impl<R: Runtime> Clone for WindowManager<R> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
inner: self.inner.clone(),
|
||||
invoke_keys: self.invoke_keys.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -196,7 +269,7 @@ impl<R: Runtime> Clone for WindowManager<R> {
|
||||
impl<R: Runtime> WindowManager<R> {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn with_handlers(
|
||||
context: Context<impl Assets>,
|
||||
#[allow(unused_mut)] mut context: Context<impl Assets>,
|
||||
plugins: PluginStore<R>,
|
||||
invoke_handler: Box<InvokeHandler<R>>,
|
||||
on_page_load: Box<OnPageLoad<R>>,
|
||||
@ -206,6 +279,12 @@ impl<R: Runtime> WindowManager<R> {
|
||||
(menu, menu_event_listeners): (Option<Menu>, Vec<GlobalMenuEventListener<R>>),
|
||||
(invoke_responder, invoke_initialization_script): (Arc<InvokeResponder<R>>, String),
|
||||
) -> Self {
|
||||
// generate a random isolation key at runtime
|
||||
#[cfg(feature = "isolation")]
|
||||
if let Pattern::Isolation { ref mut key, .. } = &mut context.pattern {
|
||||
*key = uuid::Uuid::new_v4().to_string();
|
||||
}
|
||||
|
||||
Self {
|
||||
inner: Arc::new(InnerWindowManager {
|
||||
windows: Mutex::default(),
|
||||
@ -218,6 +297,7 @@ impl<R: Runtime> WindowManager<R> {
|
||||
assets: context.assets,
|
||||
default_window_icon: context.default_window_icon,
|
||||
package_info: context.package_info,
|
||||
pattern: context.pattern,
|
||||
uri_scheme_protocols,
|
||||
menu,
|
||||
menu_event_listeners: Arc::new(menu_event_listeners),
|
||||
@ -225,10 +305,13 @@ impl<R: Runtime> WindowManager<R> {
|
||||
invoke_responder,
|
||||
invoke_initialization_script,
|
||||
}),
|
||||
invoke_keys: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn pattern(&self) -> &Pattern {
|
||||
&self.inner.pattern
|
||||
}
|
||||
|
||||
/// Get a locked handle to the windows.
|
||||
pub(crate) fn windows_lock(&self) -> MutexGuard<'_, HashMap<String, Window<R>>> {
|
||||
self.inner.windows.lock().expect("poisoned window manager")
|
||||
@ -268,10 +351,18 @@ impl<R: Runtime> WindowManager<R> {
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_invoke_key(&self) -> u32 {
|
||||
let key = rand::random();
|
||||
self.invoke_keys.lock().unwrap().push(key);
|
||||
key
|
||||
/// Get the origin as it will be seen in the webview.
|
||||
fn get_browser_origin(&self) -> Cow<'_, str> {
|
||||
match self.base_path() {
|
||||
AppUrl::Url(WindowUrl::External(url)) => {
|
||||
let mut url = url.to_string();
|
||||
if url.ends_with('/') {
|
||||
url.pop();
|
||||
}
|
||||
Cow::Owned(url)
|
||||
}
|
||||
_ => Cow::Owned(format_real_schema("tauri")),
|
||||
}
|
||||
}
|
||||
|
||||
fn csp(&self) -> Option<String> {
|
||||
@ -289,13 +380,6 @@ impl<R: Runtime> WindowManager<R> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks whether the invoke key is valid or not.
|
||||
///
|
||||
/// An invoke key is valid if it was generated by this manager instance.
|
||||
pub(crate) fn verify_invoke_key(&self, key: u32) -> bool {
|
||||
self.invoke_keys.lock().unwrap().contains(&key)
|
||||
}
|
||||
|
||||
fn prepare_pending_window(
|
||||
&self,
|
||||
mut pending: PendingWindow<R>,
|
||||
@ -311,39 +395,48 @@ impl<R: Runtime> WindowManager<R> {
|
||||
.expect("poisoned plugin store")
|
||||
.initialization_script();
|
||||
|
||||
let mut webview_attributes = pending.webview_attributes;
|
||||
webview_attributes =
|
||||
webview_attributes.initialization_script(&self.inner.invoke_initialization_script);
|
||||
if is_init_global {
|
||||
webview_attributes = webview_attributes.initialization_script(&format!(
|
||||
"(function () {{
|
||||
const __TAURI_INVOKE_KEY__ = {key};
|
||||
{bundle_script}
|
||||
}})()",
|
||||
key = self.generate_invoke_key(),
|
||||
bundle_script = include_str!("../scripts/bundle.js"),
|
||||
));
|
||||
let pattern_init = PatternJavascript {
|
||||
pattern: self.pattern().into(),
|
||||
}
|
||||
.render_default(&Default::default())?;
|
||||
|
||||
let ipc_init = IpcJavascript {
|
||||
isolation_origin: &match self.pattern() {
|
||||
#[cfg(feature = "isolation")]
|
||||
Pattern::Isolation { schema, .. } => crate::pattern::format_real_schema(schema),
|
||||
_ => "".to_string(),
|
||||
},
|
||||
}
|
||||
.render_default(&Default::default())?;
|
||||
|
||||
let mut webview_attributes = pending.webview_attributes;
|
||||
|
||||
webview_attributes = webview_attributes
|
||||
.initialization_script(&self.inner.invoke_initialization_script)
|
||||
.initialization_script(&self.initialization_script(&ipc_init,&pattern_init,&plugin_init, is_init_global)?)
|
||||
.initialization_script(&format!(
|
||||
r#"
|
||||
if (!window.__TAURI__) {{
|
||||
window.__TAURI__ = {{}}
|
||||
Object.defineProperty(window, '__TAURI__', {{
|
||||
value: {{}}
|
||||
}})
|
||||
}}
|
||||
window.__TAURI__.__windows = {window_labels_array}.map(function (label) {{ return {{ label: label }} }});
|
||||
window.__TAURI__.__currentWindow = {{ label: {current_window_label} }}
|
||||
"#,
|
||||
window_labels_array = serde_json::to_string(pending_labels)?,
|
||||
current_window_label = serde_json::to_string(&label)?,
|
||||
))
|
||||
.initialization_script(&self.initialization_script(&plugin_init));
|
||||
|
||||
#[cfg(dev)]
|
||||
{
|
||||
webview_attributes = webview_attributes.initialization_script(&format!(
|
||||
"window.__TAURI_INVOKE_KEY__ = {}",
|
||||
self.generate_invoke_key()
|
||||
));
|
||||
|
||||
#[cfg(feature = "isolation")]
|
||||
if let Pattern::Isolation { schema, .. } = self.pattern() {
|
||||
webview_attributes = webview_attributes.initialization_script(
|
||||
&IsolationJavascript {
|
||||
isolation_src: &crate::pattern::format_real_schema(schema),
|
||||
style: tauri_utils::pattern::isolation::IFRAME_STYLE,
|
||||
}
|
||||
.render_default(&Default::default())?,
|
||||
);
|
||||
}
|
||||
|
||||
pending.webview_attributes = webview_attributes;
|
||||
@ -492,14 +585,76 @@ impl<R: Runtime> WindowManager<R> {
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(feature = "isolation")]
|
||||
if let Pattern::Isolation {
|
||||
assets,
|
||||
schema,
|
||||
key: _,
|
||||
crypto_keys,
|
||||
} = &self.inner.pattern
|
||||
{
|
||||
let assets = assets.clone();
|
||||
let schema_ = schema.clone();
|
||||
let url_base = format!("{}://localhost", schema_);
|
||||
let aes_gcm_key = *crypto_keys.aes_gcm().raw();
|
||||
|
||||
pending.register_uri_scheme_protocol(schema, move |request| {
|
||||
match request_to_path(request, &url_base).as_str() {
|
||||
"index.html" => match assets.get(&"index.html".into()) {
|
||||
Some(asset) => {
|
||||
let asset = String::from_utf8_lossy(asset.as_ref());
|
||||
let template = tauri_utils::pattern::isolation::IsolationJavascriptRuntime {
|
||||
runtime_aes_gcm_key: &aes_gcm_key,
|
||||
};
|
||||
match template.render(asset.as_ref(), &Default::default()) {
|
||||
Ok(asset) => HttpResponseBuilder::new()
|
||||
.mimetype("text/html")
|
||||
.body(asset.as_bytes().to_vec()),
|
||||
Err(_) => HttpResponseBuilder::new()
|
||||
.status(500)
|
||||
.mimetype("text/plain")
|
||||
.body(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
None => HttpResponseBuilder::new()
|
||||
.status(404)
|
||||
.mimetype("text/plain")
|
||||
.body(Vec::new()),
|
||||
},
|
||||
_ => HttpResponseBuilder::new()
|
||||
.status(404)
|
||||
.mimetype("text/plain")
|
||||
.body(Vec::new()),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Ok(pending)
|
||||
}
|
||||
|
||||
fn prepare_ipc_handler(&self, app_handle: AppHandle<R>) -> WebviewIpcHandler<R> {
|
||||
let manager = self.clone();
|
||||
Box::new(move |window, request| {
|
||||
Box::new(move |window, #[allow(unused_mut)] mut request| {
|
||||
let window = Window::new(manager.clone(), window, app_handle.clone());
|
||||
|
||||
#[cfg(feature = "isolation")]
|
||||
if let Pattern::Isolation { crypto_keys, .. } = manager.pattern() {
|
||||
match RawIsolationPayload::try_from(request.as_str())
|
||||
.and_then(|raw| crypto_keys.decrypt(raw))
|
||||
{
|
||||
Ok(json) => request = json,
|
||||
Err(e) => {
|
||||
let error: crate::Error = e.into();
|
||||
let _ = window.eval(&format!(
|
||||
r#"console.error({})"#,
|
||||
JsonValue::String(error.to_string())
|
||||
));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match serde_json::from_str::<InvokePayload>(&request) {
|
||||
Ok(message) => {
|
||||
let _ = window.on_message(message);
|
||||
@ -530,7 +685,6 @@ impl<R: Runtime> WindowManager<R> {
|
||||
// skip leading `/`
|
||||
path.chars().skip(1).collect::<String>()
|
||||
};
|
||||
let is_javascript = path.ends_with(".js") || path.ends_with(".cjs") || path.ends_with(".mjs");
|
||||
let is_html = path.ends_with(".html");
|
||||
|
||||
let mut asset_path = AssetKey::from(path.as_str());
|
||||
@ -558,48 +712,16 @@ impl<R: Runtime> WindowManager<R> {
|
||||
|
||||
match asset_response {
|
||||
Ok(asset) => {
|
||||
let final_data = if is_javascript || is_html {
|
||||
let final_data = if is_html {
|
||||
let mut asset = String::from_utf8_lossy(&asset).into_owned();
|
||||
asset = asset.replacen(INVOKE_KEY_TOKEN, &self.generate_invoke_key().to_string(), 1);
|
||||
|
||||
if is_html {
|
||||
if let Some(mut csp) = self.csp() {
|
||||
let hash_strings = self.inner.assets.csp_hashes(&asset_path).fold(
|
||||
CspHashStrings::default(),
|
||||
|mut acc, hash| {
|
||||
match hash {
|
||||
CspHash::Script(hash) => {
|
||||
acc.script.push(' ');
|
||||
acc.script.push_str(hash);
|
||||
}
|
||||
csp_hash => {
|
||||
#[cfg(debug_assertions)]
|
||||
eprintln!("Unknown CspHash variant encountered: {:?}", csp_hash)
|
||||
}
|
||||
}
|
||||
|
||||
acc
|
||||
},
|
||||
);
|
||||
|
||||
replace_csp_nonce(
|
||||
&mut asset,
|
||||
SCRIPT_NONCE_TOKEN,
|
||||
&mut csp,
|
||||
"script-src",
|
||||
hash_strings.script,
|
||||
);
|
||||
replace_csp_nonce(
|
||||
&mut asset,
|
||||
STYLE_NONCE_TOKEN,
|
||||
&mut csp,
|
||||
"style-src",
|
||||
hash_strings.style,
|
||||
);
|
||||
|
||||
asset = asset.replace(CSP_TOKEN, &csp);
|
||||
csp_header.replace(csp);
|
||||
}
|
||||
if let Some(csp) = self.csp() {
|
||||
csp_header.replace(set_csp(
|
||||
&mut asset,
|
||||
self.inner.assets.clone(),
|
||||
&asset_path,
|
||||
&self,
|
||||
csp,
|
||||
));
|
||||
}
|
||||
|
||||
asset.as_bytes().to_vec()
|
||||
@ -659,26 +781,57 @@ impl<R: Runtime> WindowManager<R> {
|
||||
})
|
||||
}
|
||||
|
||||
fn initialization_script(&self, plugin_initialization_script: &str) -> String {
|
||||
let key = self.generate_invoke_key();
|
||||
format!(
|
||||
r#"
|
||||
{core_script}
|
||||
{event_initialization_script}
|
||||
if (document.readyState === 'complete') {{
|
||||
window.__TAURI_INVOKE__("__initialized", {{ url: window.location.href }}, {key})
|
||||
}} else {{
|
||||
window.addEventListener('DOMContentLoaded', function () {{
|
||||
window.__TAURI_INVOKE__("__initialized", {{ url: window.location.href }}, {key})
|
||||
}})
|
||||
}}
|
||||
{plugin_initialization_script}
|
||||
"#,
|
||||
key = key,
|
||||
core_script = include_str!("../scripts/core.js").replace("_KEY_VALUE_", &key.to_string()),
|
||||
event_initialization_script = self.event_initialization_script(),
|
||||
plugin_initialization_script = plugin_initialization_script
|
||||
)
|
||||
fn initialization_script(
|
||||
&self,
|
||||
ipc_script: &str,
|
||||
pattern_script: &str,
|
||||
plugin_initialization_script: &str,
|
||||
with_global_tauri: bool,
|
||||
) -> crate::Result<String> {
|
||||
#[derive(Template)]
|
||||
#[default_template("../scripts/init.js")]
|
||||
struct InitJavascript<'a> {
|
||||
origin: Cow<'a, str>,
|
||||
#[raw]
|
||||
pattern_script: &'a str,
|
||||
#[raw]
|
||||
ipc_script: &'a str,
|
||||
#[raw]
|
||||
bundle_script: &'a str,
|
||||
#[raw]
|
||||
core_script: &'a str,
|
||||
#[raw]
|
||||
event_initialization_script: &'a str,
|
||||
#[raw]
|
||||
plugin_initialization_script: &'a str,
|
||||
#[raw]
|
||||
freeze_prototype: &'a str,
|
||||
}
|
||||
|
||||
let bundle_script = if with_global_tauri {
|
||||
include_str!("../scripts/bundle.js")
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
||||
let freeze_prototype = if self.inner.config.tauri.security.freeze_prototype {
|
||||
include_str!("../scripts/freeze_prototype.js")
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
||||
InitJavascript {
|
||||
origin: self.get_browser_origin(),
|
||||
pattern_script,
|
||||
ipc_script,
|
||||
bundle_script,
|
||||
core_script: include_str!("../scripts/core.js"),
|
||||
event_initialization_script: &self.event_initialization_script(),
|
||||
plugin_initialization_script,
|
||||
freeze_prototype,
|
||||
}
|
||||
.render_default(&Default::default())
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
fn event_initialization_script(&self) -> String {
|
||||
@ -702,9 +855,10 @@ impl<R: Runtime> WindowManager<R> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::WindowManager;
|
||||
use crate::{generate_context, plugin::PluginStore, StateManager, Wry};
|
||||
|
||||
use super::WindowManager;
|
||||
|
||||
#[test]
|
||||
fn check_get_url() {
|
||||
let context = generate_context!("test/fixture/src-tauri/tauri.conf.json", crate);
|
||||
@ -1029,3 +1183,31 @@ struct ScaleFactorChanged {
|
||||
fn on_menu_event<R: Runtime>(window: &Window<R>, event: &MenuEvent) -> crate::Result<()> {
|
||||
window.emit_and_trigger(MENU_EVENT, event.menu_item_id.clone())
|
||||
}
|
||||
|
||||
#[cfg(feature = "isolation")]
|
||||
fn request_to_path(request: &tauri_runtime::http::Request, replace: &str) -> String {
|
||||
let mut path = request
|
||||
.uri()
|
||||
.split(&['?', '#'][..])
|
||||
// ignore query string
|
||||
.next()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
.replace(replace, "");
|
||||
|
||||
if path.ends_with('/') {
|
||||
path.pop();
|
||||
}
|
||||
|
||||
let path = percent_encoding::percent_decode(path.as_bytes())
|
||||
.decode_utf8_lossy()
|
||||
.to_string();
|
||||
|
||||
if path.is_empty() {
|
||||
// if the url has no path, we should load `index.html`
|
||||
"index.html".to_string()
|
||||
} else {
|
||||
// skip leading `/`
|
||||
path.chars().skip(1).collect()
|
||||
}
|
||||
}
|
||||
|
94
core/tauri/src/pattern.rs
Normal file
94
core/tauri/src/pattern.rs
Normal file
@ -0,0 +1,94 @@
|
||||
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::marker::PhantomData;
|
||||
#[cfg(feature = "isolation")]
|
||||
use std::sync::Arc;
|
||||
|
||||
use serde::Serialize;
|
||||
use serialize_to_javascript::{default_template, Template};
|
||||
|
||||
use tauri_utils::assets::{Assets, EmbeddedAssets};
|
||||
|
||||
/// An application pattern.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Pattern<A: Assets = EmbeddedAssets> {
|
||||
/// The brownfield pattern.
|
||||
Brownfield(PhantomData<A>),
|
||||
/// Isolation pattern. Recommended for security purposes.
|
||||
#[cfg(feature = "isolation")]
|
||||
Isolation {
|
||||
/// The HTML served on `isolation://index.html`.
|
||||
assets: Arc<A>,
|
||||
|
||||
/// The schema used for the isolation frames.
|
||||
schema: String,
|
||||
|
||||
/// A random string used to ensure that the message went through the isolation frame.
|
||||
///
|
||||
/// This should be regenerated at runtime.
|
||||
key: String,
|
||||
|
||||
/// Cryptographically secure keys
|
||||
crypto_keys: Box<tauri_utils::pattern::isolation::Keys>,
|
||||
},
|
||||
}
|
||||
|
||||
/// The shape of the JavaScript Pattern config
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "lowercase", tag = "pattern")]
|
||||
pub(crate) enum PatternObject {
|
||||
/// Brownfield pattern.
|
||||
Brownfield,
|
||||
/// Isolation pattern. Recommended for security purposes.
|
||||
#[cfg(feature = "isolation")]
|
||||
Isolation {
|
||||
/// Which `IsolationSide` this `PatternObject` is getting injected into
|
||||
side: IsolationSide,
|
||||
},
|
||||
}
|
||||
|
||||
impl From<&Pattern> for PatternObject {
|
||||
fn from(pattern: &Pattern) -> Self {
|
||||
match pattern {
|
||||
Pattern::Brownfield(_) => Self::Brownfield,
|
||||
#[cfg(feature = "isolation")]
|
||||
Pattern::Isolation { .. } => Self::Isolation {
|
||||
side: IsolationSide::default(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Where the JavaScript is injected to
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub(crate) enum IsolationSide {
|
||||
/// Original frame, the Brownfield application
|
||||
Original,
|
||||
/// Secure frame, the isolation security application
|
||||
#[allow(dead_code)]
|
||||
Secure,
|
||||
}
|
||||
|
||||
impl Default for IsolationSide {
|
||||
fn default() -> Self {
|
||||
Self::Original
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[default_template("../scripts/pattern.js")]
|
||||
pub(crate) struct PatternJavascript {
|
||||
pub(crate) pattern: PatternObject,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn format_real_schema(schema: &str) -> String {
|
||||
if cfg!(windows) {
|
||||
format!("https://{}.localhost", schema)
|
||||
} else {
|
||||
format!("{}://localhost", schema)
|
||||
}
|
||||
}
|
@ -12,14 +12,17 @@ use tauri_runtime::{
|
||||
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
|
||||
DetachedWindow, MenuEvent, PendingWindow, WindowEvent,
|
||||
},
|
||||
ActivationPolicy, ClipboardManager, Dispatch, GlobalShortcutManager, Icon, Result, RunEvent,
|
||||
RunIteration, Runtime, RuntimeHandle, UserAttentionType,
|
||||
ClipboardManager, Dispatch, GlobalShortcutManager, Icon, Result, RunEvent, Runtime,
|
||||
RuntimeHandle, UserAttentionType,
|
||||
};
|
||||
#[cfg(feature = "system-tray")]
|
||||
use tauri_runtime::{SystemTray, SystemTrayEvent};
|
||||
use tauri_utils::config::WindowConfig;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[cfg(windows)]
|
||||
use webview2_com::Windows::Win32::Foundation::HWND;
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fmt,
|
||||
@ -60,6 +63,7 @@ impl RuntimeHandle for MockRuntimeHandle {
|
||||
context: self.context.clone(),
|
||||
},
|
||||
menu_ids: Default::default(),
|
||||
js_event_listeners: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
@ -534,6 +538,7 @@ impl Runtime for MockRuntime {
|
||||
context: self.context.clone(),
|
||||
},
|
||||
menu_ids: Default::default(),
|
||||
js_event_listeners: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
@ -551,10 +556,13 @@ impl Runtime for MockRuntime {
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
|
||||
fn set_activation_policy(&mut self, activation_policy: ActivationPolicy) {}
|
||||
fn set_activation_policy(&mut self, activation_policy: tauri_runtime::ActivationPolicy) {}
|
||||
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
fn run_iteration<F: Fn(RunEvent) + 'static>(&mut self, callback: F) -> RunIteration {
|
||||
fn run_iteration<F: Fn(RunEvent) + 'static>(
|
||||
&mut self,
|
||||
callback: F,
|
||||
) -> tauri_runtime::RunIteration {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
|
@ -9,10 +9,10 @@ pub use mock_runtime::*;
|
||||
|
||||
use std::{borrow::Cow, sync::Arc};
|
||||
|
||||
use crate::Manager;
|
||||
use crate::{Manager, Pattern};
|
||||
use tauri_utils::{
|
||||
assets::{AssetKey, Assets, CspHash},
|
||||
config::{CliConfig, Config, TauriConfig},
|
||||
config::{CliConfig, Config, PatternKind, TauriConfig},
|
||||
};
|
||||
|
||||
pub struct NoopAsset {
|
||||
@ -40,6 +40,7 @@ pub fn mock_context<A: Assets>(assets: A) -> crate::Context<A> {
|
||||
config: Config {
|
||||
package: Default::default(),
|
||||
tauri: TauriConfig {
|
||||
pattern: PatternKind::Brownfield,
|
||||
windows: vec![Default::default()],
|
||||
cli: Some(CliConfig {
|
||||
description: None,
|
||||
@ -65,8 +66,11 @@ pub fn mock_context<A: Assets>(assets: A) -> crate::Context<A> {
|
||||
package_info: crate::PackageInfo {
|
||||
name: "test".into(),
|
||||
version: "0.1.0".into(),
|
||||
authors: "Tauri".into(),
|
||||
description: "Tauri test".into(),
|
||||
},
|
||||
_info_plist: (),
|
||||
pattern: Pattern::Brownfield(std::marker::PhantomData),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,7 @@ use crate::api::{
|
||||
use base64::decode;
|
||||
use http::StatusCode;
|
||||
use minisign_verify::{PublicKey, Signature};
|
||||
use tauri_utils::platform::current_exe;
|
||||
use tauri_utils::Env;
|
||||
use tauri_utils::{platform::current_exe, Env};
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
@ -552,7 +551,7 @@ fn copy_files_and_run<R: Read + Seek>(
|
||||
let mut extractor = Extract::from_cursor(archive_buffer, ArchiveFormat::Zip);
|
||||
|
||||
// extract the msi
|
||||
extractor.extract_into(&tmp_dir);
|
||||
extractor.extract_into(&tmp_dir)?;
|
||||
|
||||
let paths = read_dir(&tmp_dir)?;
|
||||
// This consumes the TempDir without deleting directory on the filesystem,
|
||||
@ -648,7 +647,7 @@ fn copy_files_and_run<R: Read + Seek>(archive_buffer: R, extract_path: &Path) ->
|
||||
.tempdir()?;
|
||||
|
||||
// create backup of our current app
|
||||
Move::from_source(extract_path).to_dest(&tmp_dir.path())?;
|
||||
Move::from_source(extract_path).to_dest(tmp_dir.path())?;
|
||||
|
||||
// extract all the files
|
||||
for file in all_files {
|
||||
@ -666,7 +665,7 @@ fn copy_files_and_run<R: Read + Seek>(archive_buffer: R, extract_path: &Path) ->
|
||||
std::fs::remove_file(file)?;
|
||||
}
|
||||
}
|
||||
Move::from_source(&tmp_dir.path()).to_dest(extract_path)?;
|
||||
Move::from_source(tmp_dir.path()).to_dest(extract_path)?;
|
||||
return Err(Error::Extract(err.to_string()));
|
||||
}
|
||||
|
||||
@ -776,7 +775,7 @@ where
|
||||
mod test {
|
||||
use super::*;
|
||||
#[cfg(target_os = "macos")]
|
||||
use std::{env, fs::File};
|
||||
use std::fs::File;
|
||||
|
||||
macro_rules! block {
|
||||
($e:expr) => {
|
||||
|
@ -226,7 +226,7 @@ impl<R: Runtime> Window<R> {
|
||||
/// How to handle this window receiving an [`InvokeMessage`].
|
||||
pub fn on_message(self, payload: InvokePayload) -> crate::Result<()> {
|
||||
let manager = self.manager.clone();
|
||||
match payload.command.as_str() {
|
||||
match payload.cmd.as_str() {
|
||||
"__initialized" => {
|
||||
let payload: PageLoadPayload = serde_json::from_value(payload.inner)?;
|
||||
manager.run_on_page_load(self, payload);
|
||||
@ -235,25 +235,19 @@ impl<R: Runtime> Window<R> {
|
||||
let message = InvokeMessage::new(
|
||||
self.clone(),
|
||||
manager.state(),
|
||||
payload.command.to_string(),
|
||||
payload.cmd.to_string(),
|
||||
payload.inner,
|
||||
);
|
||||
let resolver = InvokeResolver::new(self, payload.callback, payload.error);
|
||||
|
||||
let invoke = Invoke { message, resolver };
|
||||
if manager.verify_invoke_key(payload.key) {
|
||||
if let Some(module) = &payload.tauri_module {
|
||||
let module = module.to_string();
|
||||
crate::endpoints::handle(module, invoke, manager.config(), manager.package_info());
|
||||
} else if payload.command.starts_with("plugin:") {
|
||||
manager.extend_api(invoke);
|
||||
} else {
|
||||
manager.run_invoke_handler(invoke);
|
||||
}
|
||||
if let Some(module) = &payload.tauri_module {
|
||||
let module = module.to_string();
|
||||
crate::endpoints::handle(module, invoke, manager.config(), manager.package_info());
|
||||
} else if payload.cmd.starts_with("plugin:") {
|
||||
manager.extend_api(invoke);
|
||||
} else {
|
||||
panic!(
|
||||
r#"The invoke key "{}" is invalid. This means that an external, possible malicious script is trying to access the system interface."#,
|
||||
payload.key
|
||||
);
|
||||
manager.run_invoke_handler(invoke);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -718,7 +712,7 @@ impl<R: Runtime> Window<R> {
|
||||
mod tests {
|
||||
#[test]
|
||||
fn window_is_send_sync() {
|
||||
crate::test::assert_send::<super::Window>();
|
||||
crate::test::assert_sync::<super::Window>();
|
||||
crate::test_utils::assert_send::<super::Window>();
|
||||
crate::test_utils::assert_sync::<super::Window>();
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ fn create_symlink(original: &Path, link: PathBuf) -> io::Result<Symlink> {
|
||||
Ok(()) => Ok(Symlink::Created(link)),
|
||||
Err(e) => match e.raw_os_error() {
|
||||
Some(ERROR_PRIVILEGE_NOT_HELD) => Ok(Symlink::Privilege),
|
||||
_ => Err(e.into()),
|
||||
_ => Err(e),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
397
core/tauri/tests/restart/Cargo.lock
generated
397
core/tauri/tests/restart/Cargo.lock
generated
@ -34,9 +34,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.44"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1"
|
||||
checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203"
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
@ -103,9 +103,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "blake3"
|
||||
version = "1.1.0"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2607a74355ce2e252d0c483b2d8a348e1bba36036e786ccc2dcd777213c86ffd"
|
||||
checksum = "526c210b4520e416420759af363083471656e819a75e831b8d2c9d5a584f2413"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
@ -199,9 +199,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.71"
|
||||
version = "1.0.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
|
||||
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
]
|
||||
@ -252,18 +252,6 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cocoa"
|
||||
version = "0.24.0"
|
||||
@ -295,12 +283,6 @@ dependencies = [
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-sha1"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb58b6451e8c2a812ad979ed1d83378caa5e927eef2622017a45f251457c2c9d"
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.5"
|
||||
@ -406,9 +388,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.2.1"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
|
||||
checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
@ -465,7 +447,7 @@ checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a"
|
||||
dependencies = [
|
||||
"cssparser-macros",
|
||||
"dtoa-short",
|
||||
"itoa",
|
||||
"itoa 0.4.8",
|
||||
"matches",
|
||||
"phf 0.8.0",
|
||||
"proc-macro2",
|
||||
@ -484,6 +466,12 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cty"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.10.2"
|
||||
@ -496,12 +484,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "757c0ded2af11d8e739c4daea1ac623dd1624b06c844cf3f5a39f1bdbd99bb12"
|
||||
checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4"
|
||||
dependencies = [
|
||||
"darling_core 0.13.0",
|
||||
"darling_macro 0.13.0",
|
||||
"darling_core 0.13.1",
|
||||
"darling_macro 0.13.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -520,9 +508,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c34d8efb62d0c2d7f60ece80f75e5c63c1588ba68032740494b0b9a996466e3"
|
||||
checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
@ -545,20 +533,20 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ade7bff147130fe5e6d39f089c6bd49ec0250f35d70b2eebf72afdfc919f15cc"
|
||||
checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b"
|
||||
dependencies = [
|
||||
"darling_core 0.13.0",
|
||||
"darling_core 0.13.1",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-url"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d33fe99ccedd6e84bc035f1931bb2e6be79739d6242bd895e7311c886c50dc9c"
|
||||
checksum = "3a30bfce702bcfa94e906ef82421f2c0e61c076ad76030c16ee5d2e9a32fe193"
|
||||
dependencies = [
|
||||
"matches",
|
||||
]
|
||||
@ -596,14 +584,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "derive_more"
|
||||
version = "0.99.16"
|
||||
version = "0.99.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40eebddd2156ce1bb37b20bbe5151340a31828b1f2d22ba4141f3531710e38df"
|
||||
checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustc_version",
|
||||
"rustc_version 0.4.0",
|
||||
"syn",
|
||||
]
|
||||
|
||||
@ -672,9 +660,9 @@ checksum = "53dd2e43a7d32952a6054141ee0d75183958620e84e5eab045de362dff13dc99"
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.5.0"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b394ed3d285a429378d3b384b9eb1285267e7df4b166df24b7a6939a04dc392e"
|
||||
checksum = "779d043b6a0b90cc4c0ed7ee380a6504394cee7efd7db050e3774eee387324b2"
|
||||
dependencies = [
|
||||
"instant",
|
||||
]
|
||||
@ -686,7 +674,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92"
|
||||
dependencies = [
|
||||
"memoffset",
|
||||
"rustc_version",
|
||||
"rustc_version 0.3.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -756,9 +744,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.17"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca"
|
||||
checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
@ -771,9 +759,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.17"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888"
|
||||
checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
@ -781,15 +769,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.17"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d"
|
||||
checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.17"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c"
|
||||
checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
@ -798,9 +786,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.17"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377"
|
||||
checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2"
|
||||
|
||||
[[package]]
|
||||
name = "futures-lite"
|
||||
@ -819,12 +807,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.17"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb"
|
||||
checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
@ -832,23 +818,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.17"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11"
|
||||
checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.17"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99"
|
||||
checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.17"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481"
|
||||
checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
@ -858,8 +843,6 @@ dependencies = [
|
||||
"memchr",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"proc-macro-hack",
|
||||
"proc-macro-nested",
|
||||
"slab",
|
||||
]
|
||||
|
||||
@ -1209,7 +1192,7 @@ checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
"itoa",
|
||||
"itoa 0.4.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1292,9 +1275,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.1"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
|
||||
checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
@ -1306,10 +1289,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
||||
|
||||
[[package]]
|
||||
name = "javascriptcore-rs"
|
||||
version = "0.15.1"
|
||||
name = "itoa"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9644bfae308588f4e57616bd8402b982dbcd68d1934c0848e2869ffcc03b562"
|
||||
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||
|
||||
[[package]]
|
||||
name = "javascriptcore-rs"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e207780c1d1cd3c36056695e44010a19dd481574a2106cd2540edda4128a9794"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"glib",
|
||||
@ -1318,9 +1307,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "javascriptcore-rs-sys"
|
||||
version = "0.3.1"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79a4f53f580ab519a92d142d6dbcff5fd59b8e9634f965bdeb892383d787165e"
|
||||
checksum = "2adf2de824b178d76c6017da59f4e7e95de49a766b584c59d47821a6c3dce9e2"
|
||||
dependencies = [
|
||||
"glib-sys 0.14.0",
|
||||
"gobject-sys 0.14.0",
|
||||
@ -1363,9 +1352,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.106"
|
||||
version = "0.2.112"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673"
|
||||
checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
@ -1387,9 +1376,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "loom"
|
||||
version = "0.5.2"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2b9df80a3804094bf49bb29881d18f6f05048db72127e84e09c26fc7c2324f5"
|
||||
checksum = "edc5c7d328e32cc4954e8e01193d7f0ef5ab257b5090b70a964e099a36034309"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"generator",
|
||||
@ -1431,9 +1420,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.0.1"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1"
|
||||
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
|
||||
dependencies = [
|
||||
"regex-automata",
|
||||
]
|
||||
@ -1452,9 +1441,9 @@ checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.4"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
|
||||
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
@ -1520,9 +1509,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ndk-sys"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c44922cb3dbb1c70b5e5f443d63b64363a898564d739ba5198e3a9138442868d"
|
||||
checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121"
|
||||
|
||||
[[package]]
|
||||
name = "new_debug_unreachable"
|
||||
@ -1568,9 +1557,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.0"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
|
||||
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
@ -1578,9 +1567,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num_enum"
|
||||
version = "0.5.4"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9bd055fb730c4f8f4f57d45d35cd6b3f0980535b056dc7ff119cee6a66ed6f"
|
||||
checksum = "085fe377a4b2805c0fbc09484415ec261174614b7f080b0e0d520456ac421a67"
|
||||
dependencies = [
|
||||
"derivative",
|
||||
"num_enum_derive",
|
||||
@ -1588,9 +1577,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num_enum_derive"
|
||||
version = "0.5.4"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "486ea01961c4a818096de679a8b740b26d9033146ac5291b1c98557658f8cdd9"
|
||||
checksum = "5249369707a1e07b39f78d98c8f34e00aca7dcb053812fdbb5ad7be82c1bba38"
|
||||
dependencies = [
|
||||
"proc-macro-crate 1.1.0",
|
||||
"proc-macro2",
|
||||
@ -1628,9 +1617,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.8.0"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
|
||||
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
@ -1722,9 +1711,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.10.0"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9fc3db1018c4b59d7d582a739436478b6035138b6aecbce989fc91c3e98409f"
|
||||
checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
|
||||
dependencies = [
|
||||
"phf_macros 0.10.0",
|
||||
"phf_shared 0.10.0",
|
||||
@ -1821,9 +1810,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.22"
|
||||
version = "0.3.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f"
|
||||
checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
|
||||
|
||||
[[package]]
|
||||
name = "png"
|
||||
@ -1910,17 +1899,11 @@ version = "0.5.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-nested"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.32"
|
||||
version = "1.0.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43"
|
||||
checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
@ -2027,11 +2010,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-handle"
|
||||
version = "0.3.3"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a441a7a6c80ad6473bd4b74ec1c9a4c951794285bf941c2126f607c72e48211"
|
||||
checksum = "e28f55143d0548dad60bb4fbdc835a3d7ac6acc3324506450c5fdd6e42903a76"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"raw-window-handle 0.4.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-handle"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fba75eee94a9d5273a68c9e1e105d9cffe1ef700532325788389e5a83e2522b7"
|
||||
dependencies = [
|
||||
"cty",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2130,16 +2123,25 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.5"
|
||||
name = "rustc_version"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088"
|
||||
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||
dependencies = [
|
||||
"semver 1.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.5"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
@ -2208,18 +2210,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.130"
|
||||
version = "1.0.132"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
|
||||
checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.130"
|
||||
version = "1.0.132"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
|
||||
checksum = "ecc0db5cb2556c0e558887d9bbdcf6ac4471e83ff66cf696e5419024d1606276"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -2228,11 +2230,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.68"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8"
|
||||
checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"itoa 1.0.1",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
@ -2265,7 +2267,27 @@ version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12e47be9471c72889ebafb5e14d5ff930d89ae7a67bbdb5f8abb564f845a927e"
|
||||
dependencies = [
|
||||
"darling 0.13.0",
|
||||
"darling 0.13.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serialize-to-javascript"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/chippers/serialize-to-javascript#38d5026f371bfba4f5197ed143a6667a09375fbd"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serialize-to-javascript-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serialize-to-javascript-impl"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/chippers/serialize-to-javascript#38d5026f371bfba4f5197ed143a6667a09375fbd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
@ -2427,9 +2449,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.81"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966"
|
||||
checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -2485,7 +2507,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tao"
|
||||
version = "0.5.2"
|
||||
source = "git+https://github.com/tauri-apps/tao?branch=next#97cd0497ae827903f7d67aa1c991a77a397c9cb8"
|
||||
source = "git+https://github.com/tauri-apps/tao?branch=next#9f699a345788fbb08bc483a3f335ca4a94339676"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cairo-rs",
|
||||
@ -2512,20 +2534,19 @@ dependencies = [
|
||||
"ndk-sys",
|
||||
"objc",
|
||||
"parking_lot",
|
||||
"raw-window-handle",
|
||||
"raw-window-handle 0.3.4",
|
||||
"scopeguard",
|
||||
"serde",
|
||||
"unicode-segmentation",
|
||||
"webview2-com-sys",
|
||||
"windows",
|
||||
"x11-dl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.4.37"
|
||||
version = "0.4.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6f5515d3add52e0bbdcad7b83c388bb36ba7b754dda3b5f5bc2d38640cdba5c"
|
||||
checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6"
|
||||
dependencies = [
|
||||
"filetime",
|
||||
"libc",
|
||||
@ -2553,12 +2574,13 @@ dependencies = [
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"rand 0.8.4",
|
||||
"raw-window-handle",
|
||||
"raw-window-handle 0.3.4",
|
||||
"regex",
|
||||
"semver 1.0.4",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_repr",
|
||||
"serialize-to-javascript",
|
||||
"state",
|
||||
"tar",
|
||||
"tauri-macros",
|
||||
@ -2587,6 +2609,7 @@ dependencies = [
|
||||
"sha2",
|
||||
"tauri-utils",
|
||||
"thiserror",
|
||||
"uuid",
|
||||
"walkdir",
|
||||
"zstd",
|
||||
]
|
||||
@ -2615,7 +2638,7 @@ dependencies = [
|
||||
"tauri-utils",
|
||||
"thiserror",
|
||||
"uuid",
|
||||
"webview2-com-sys",
|
||||
"webview2-com",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2630,6 +2653,7 @@ dependencies = [
|
||||
"tauri-utils",
|
||||
"uuid",
|
||||
"webview2-com",
|
||||
"windows",
|
||||
"wry",
|
||||
]
|
||||
|
||||
@ -2637,15 +2661,18 @@ dependencies = [
|
||||
name = "tauri-utils"
|
||||
version = "1.0.0-beta.3"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"heck",
|
||||
"html5ever",
|
||||
"kuchiki",
|
||||
"phf 0.10.0",
|
||||
"phf 0.10.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_with",
|
||||
"serialize-to-javascript",
|
||||
"sha2",
|
||||
"thiserror",
|
||||
"url",
|
||||
"zstd",
|
||||
@ -2723,9 +2750,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7"
|
||||
checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
@ -2738,11 +2765,10 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.13.0"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "588b2d10a336da58d877567cd8fb8a14b463e2104910f8132cd054b4b96e29ee"
|
||||
checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bytes",
|
||||
"memchr",
|
||||
"num_cpus",
|
||||
@ -2801,36 +2827,22 @@ dependencies = [
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-serde"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.2.25"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71"
|
||||
checksum = "245da694cc7fc4729f3f418b304cb57789f1bed2a78c575407ab8a23f53cb4d3"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"chrono",
|
||||
"lazy_static",
|
||||
"matchers",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sharded-slab",
|
||||
"smallvec",
|
||||
"thread_local",
|
||||
"tracing",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
"tracing-serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2949,9 +2961,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
|
||||
[[package]]
|
||||
name = "webkit2gtk"
|
||||
version = "0.15.2"
|
||||
version = "0.15.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ca90927b3d0625c84c7de59b70174cc6384237d0599f2b8e510a7ee10509d1d"
|
||||
checksum = "d5725e8ede878b7c00419066868085b83fb7d01eea904c1a0bd0159ad3ce0ba3"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cairo-rs",
|
||||
@ -2972,9 +2984,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "webkit2gtk-sys"
|
||||
version = "0.15.1"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b0e5e08218be3884e56aff0aedcb9e222b311be53214eb6019200caf9b52815"
|
||||
checksum = "b34314407e381b88a72610d0f4eeff1552cbf8ee5420dbe84749fa26aa11b4e3"
|
||||
dependencies = [
|
||||
"atk-sys",
|
||||
"bitflags",
|
||||
@ -2995,9 +3007,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "webview2-com"
|
||||
version = "0.4.0"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2294dee38668da0d71019097dddc6cef525fde7aa4784243dd83f0752e08aa5"
|
||||
checksum = "abdc9ca7cebd96a1005d5ba1e9d70c61c0f6c276a41cddaeecb7842d436ab3bc"
|
||||
dependencies = [
|
||||
"webview2-com-macros",
|
||||
"webview2-com-sys",
|
||||
@ -3006,9 +3018,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "webview2-com-macros"
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2eba35fdbb8fbc8de7e7479532a356dbbf2754d8a6e9c9fbfa430896cbb1ca89"
|
||||
checksum = "07bca4b354035275764ea4ca8d6bfa74cc5b0e8126e7cd675ee327574b59e13d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -3017,9 +3029,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "webview2-com-sys"
|
||||
version = "0.4.0"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14690dcb8b57c5238c4502cfc321f858fa1306edd4109e8e1d7ddee0c29b06a5"
|
||||
checksum = "73472d7f0e9038b58204cb3f582ee138a8c181719dc6825ea03371ad085c6058"
|
||||
dependencies = [
|
||||
"regex",
|
||||
"serde",
|
||||
@ -3061,30 +3073,53 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.19.0"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef84dd25f4c69a271b1bba394532bf400523b43169de21dfc715e8f8e491053d"
|
||||
checksum = "e46c474738425c090573ecf5472d54ee5f78132e6195d0bbfcc2aabc0ed29f37"
|
||||
dependencies = [
|
||||
"const-sha1",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_gen",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_macros",
|
||||
"windows_reader",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_gen"
|
||||
version = "0.19.0"
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac7bb21b8ff5e801232b72a6ff554b4cc0cef9ed9238188c3ca78fe3968a7e5d"
|
||||
checksum = "3022d174000fcaeb6f95933fb04171ea0e21b9289ac57fe4400bfa148e41df79"
|
||||
|
||||
[[package]]
|
||||
name = "windows_gen"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54e0f0e40e950724f92de0f714817c7030a88161738b9b1c58d62c817246fe1c"
|
||||
dependencies = [
|
||||
"windows_quote",
|
||||
"windows_reader",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_macros"
|
||||
version = "0.19.0"
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5566b8c51118769e4a9094a688bf1233a3f36aacbfc78f3b15817fe0b6e0442f"
|
||||
checksum = "03b1584eebf06654708eab4301152032c13c1e47f4a754ffc93c733f10993e85"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f49df16591e9ad429997ec57d462b0cc45168f639d03489e8c2e933ea9c389d7"
|
||||
|
||||
[[package]]
|
||||
name = "windows_macros"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6103bcf1a7396d66f6f08a2d67d8a2ab34efaf4b1d7567301af2c002507c8c3b"
|
||||
dependencies = [
|
||||
"syn",
|
||||
"windows_gen",
|
||||
@ -3094,20 +3129,32 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows_quote"
|
||||
version = "0.19.0"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4af8236a9493c38855f95cdd11b38b342512a5df4ee7473cffa828b5ebb0e39c"
|
||||
checksum = "e414df8d5dd2013f2317fdc414d3ad035effcb7aef1f16bf508ac5743154835a"
|
||||
|
||||
[[package]]
|
||||
name = "windows_reader"
|
||||
version = "0.19.0"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c8d5cf83fb08083438c5c46723e6206b2970da57ce314f80b57724439aaacab"
|
||||
checksum = "8132c9fb77903d852ea20053af816bd15c088a6e8d283b8283e80353347bb6b9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2cb06177184100374f97d5e7261ee0b6adefa8ee32e38f87518ca22b519bb80e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3c27bcbb33ddbed3569e36c14775c99f72b97c72ce49f81d128637fb48a061f"
|
||||
|
||||
[[package]]
|
||||
name = "wry"
|
||||
version = "0.12.2"
|
||||
source = "git+ssh://git@github.com/tauri-sec/wry?branch=next#0f9eb9b1b9288b5be443bced0e8fa58a2479c491"
|
||||
source = "git+ssh://git@github.com/tauri-sec/wry?branch=next#c60bb8f49e971237a1e9ed73fad2cec38dc7c9db"
|
||||
dependencies = [
|
||||
"cocoa",
|
||||
"core-graphics 0.22.3",
|
||||
|
@ -72,7 +72,7 @@ to the Cargo Manifest (`Cargo.toml`) so that Cargo knows to pull in our dependen
|
||||
name = "hello-tauri-webdriver"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
|
||||
# Needed to set up some things for Tauri at build time
|
||||
[build-dependencies]
|
||||
|
39
examples/api/dist/assets/index.4b6f33f7.js
vendored
Normal file
39
examples/api/dist/assets/index.4b6f33f7.js
vendored
Normal file
File diff suppressed because one or more lines are too long
25
examples/api/dist/assets/index.ab727ab4.js
vendored
25
examples/api/dist/assets/index.ab727ab4.js
vendored
File diff suppressed because one or more lines are too long
24
examples/api/dist/assets/vendor.32016365.js
vendored
24
examples/api/dist/assets/vendor.32016365.js
vendored
File diff suppressed because one or more lines are too long
9
examples/api/dist/assets/vendor.3a672f03.js
vendored
Normal file
9
examples/api/dist/assets/vendor.3a672f03.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4
examples/api/dist/index.html
vendored
4
examples/api/dist/index.html
vendored
@ -5,8 +5,8 @@
|
||||
<link rel="stylesheet" href="/global.css" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Svelte + Vite App</title>
|
||||
<script type="module" crossorigin src="/assets/index.ab727ab4.js"></script>
|
||||
<link rel="modulepreload" href="/assets/vendor.32016365.js">
|
||||
<script type="module" crossorigin src="/assets/index.4b6f33f7.js"></script>
|
||||
<link rel="modulepreload" href="/assets/vendor.3a672f03.js">
|
||||
<link rel="stylesheet" href="/assets/index.b706bb41.css">
|
||||
</head>
|
||||
|
||||
|
10
examples/api/isolation-dist/index.html
Normal file
10
examples/api/isolation-dist/index.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Isolation Secure Script</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="index.js"></script>
|
||||
</body>
|
||||
</html>
|
4
examples/api/isolation-dist/index.js
Normal file
4
examples/api/isolation-dist/index.js
Normal file
@ -0,0 +1,4 @@
|
||||
window.__TAURI_ISOLATION_HOOK__= (payload) => {
|
||||
console.log('hook', payload)
|
||||
return payload
|
||||
}
|
189
examples/api/src-tauri/Cargo.lock
generated
189
examples/api/src-tauri/Cargo.lock
generated
@ -14,6 +14,41 @@ version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||
|
||||
[[package]]
|
||||
name = "aead"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aes"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cipher",
|
||||
"cpufeatures",
|
||||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aes-gcm"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6"
|
||||
dependencies = [
|
||||
"aead",
|
||||
"aes",
|
||||
"cipher",
|
||||
"ctr",
|
||||
"ghash",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.18"
|
||||
@ -295,9 +330,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cargo_toml"
|
||||
version = "0.10.1"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6d613611c914a7db07f28526941ce1e956d2f977b0c5e2014fbfa42230d420f"
|
||||
checksum = "363c7cfaa15f101415c4ac9e68706ca4a2277773932828b33f96e59d28c68e62"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
@ -372,6 +407,15 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.0.4"
|
||||
@ -418,16 +462,6 @@ dependencies = [
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "combine"
|
||||
version = "4.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2b2f5d0ee456f3928812dfc8c6d9a1d592b98678f6d56db9b0cd2b7bc6c8db5"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "concurrent-queue"
|
||||
version = "1.2.2"
|
||||
@ -629,6 +663,15 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctr"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea"
|
||||
dependencies = [
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cty"
|
||||
version = "0.2.2"
|
||||
@ -705,6 +748,15 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-url"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a30bfce702bcfa94e906ef82421f2c0e61c076ad76030c16ee5d2e9a32fe193"
|
||||
dependencies = [
|
||||
"matches",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deflate"
|
||||
version = "0.7.20"
|
||||
@ -1156,6 +1208,16 @@ dependencies = [
|
||||
"wasi 0.10.2+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ghash"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99"
|
||||
dependencies = [
|
||||
"opaque-debug",
|
||||
"polyval",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gio"
|
||||
version = "0.14.8"
|
||||
@ -1527,15 +1589,6 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kstring"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b310ccceade8121d7d77fee406160e457c2f4e7c7982d589da3499bc7ea4526"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kuchiki"
|
||||
version = "0.8.1"
|
||||
@ -2240,6 +2293,18 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "polyval"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cpufeatures",
|
||||
"opaque-debug",
|
||||
"universal-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.16"
|
||||
@ -2548,6 +2613,21 @@ dependencies = [
|
||||
"windows 0.29.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.16.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"spin",
|
||||
"untrusted",
|
||||
"web-sys",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-argon2"
|
||||
version = "0.8.3"
|
||||
@ -2765,6 +2845,26 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serialize-to-javascript"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/chippers/serialize-to-javascript#38d5026f371bfba4f5197ed143a6667a09375fbd"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serialize-to-javascript-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serialize-to-javascript-impl"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/chippers/serialize-to-javascript#38d5026f371bfba4f5197ed143a6667a09375fbd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "servo_arc"
|
||||
version = "0.1.1"
|
||||
@ -2849,6 +2949,12 @@ dependencies = [
|
||||
"system-deps 5.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
@ -3054,6 +3160,7 @@ dependencies = [
|
||||
"bincode",
|
||||
"cfg_aliases",
|
||||
"clap",
|
||||
"data-url",
|
||||
"dirs-next",
|
||||
"either",
|
||||
"embed_plist",
|
||||
@ -3080,6 +3187,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_repr",
|
||||
"serialize-to-javascript",
|
||||
"shared_child",
|
||||
"state",
|
||||
"tar",
|
||||
@ -3102,6 +3210,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"cargo_toml",
|
||||
"serde_json",
|
||||
"tauri-codegen",
|
||||
"tauri-utils",
|
||||
"winres",
|
||||
]
|
||||
@ -3112,7 +3221,6 @@ version = "1.0.0-beta.4"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"blake3",
|
||||
"kuchiki",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
@ -3121,6 +3229,7 @@ dependencies = [
|
||||
"sha2",
|
||||
"tauri-utils",
|
||||
"thiserror",
|
||||
"uuid",
|
||||
"walkdir",
|
||||
"zstd",
|
||||
]
|
||||
@ -3129,7 +3238,7 @@ dependencies = [
|
||||
name = "tauri-macros"
|
||||
version = "1.0.0-beta.5"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"heck 0.3.3",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
@ -3173,15 +3282,21 @@ dependencies = [
|
||||
name = "tauri-utils"
|
||||
version = "1.0.0-beta.3"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"base64",
|
||||
"heck 0.4.0",
|
||||
"html5ever",
|
||||
"kuchiki",
|
||||
"once_cell",
|
||||
"phf 0.10.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"ring",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_with",
|
||||
"serialize-to-javascript",
|
||||
"sha2",
|
||||
"thiserror",
|
||||
"url",
|
||||
"zstd",
|
||||
@ -3320,18 +3435,6 @@ dependencies = [
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-attributes"
|
||||
version = "0.1.18"
|
||||
@ -3420,6 +3523,22 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "universal-hash"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.2.2"
|
||||
|
@ -3,16 +3,16 @@ name = "api"
|
||||
version = "0.1.0"
|
||||
description = "An example Tauri Application showcasing the api"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
license = "Apache-2.0 OR MIT"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { path = "../../../core/tauri-build" }
|
||||
tauri-build = { path = "../../../core/tauri-build", features = ["isolation"] }
|
||||
|
||||
[dependencies]
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = [ "derive" ] }
|
||||
tauri = { path = "../../../core/tauri", features = ["api-all", "cli", "macos-private-api", "system-tray", "updater"] }
|
||||
tauri = { path = "../../../core/tauri", features = ["api-all", "cli", "isolation", "macos-private-api", "system-tray", "updater"] }
|
||||
|
||||
[features]
|
||||
default = [ "custom-protocol" ]
|
||||
|
@ -10,6 +10,12 @@
|
||||
"version": "../package.json"
|
||||
},
|
||||
"tauri": {
|
||||
"pattern": {
|
||||
"use": "isolation",
|
||||
"options": {
|
||||
"dir": "../isolation-dist/"
|
||||
}
|
||||
},
|
||||
"macOSPrivateApi": true,
|
||||
"cli": {
|
||||
"description": "Tauri API example",
|
||||
|
@ -3,7 +3,7 @@ name = "commands"
|
||||
version = "0.1.0"
|
||||
description = "A simple Tauri Application showcasing the commands API"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { path = "../../../core/tauri-build", features = [ "codegen" ] }
|
||||
|
@ -3,7 +3,7 @@ name = "helloworld"
|
||||
version = "0.1.0"
|
||||
description = "A very simple Tauri Appplication"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { path = "../../../core/tauri-build", features = [ "codegen" ] }
|
||||
|
@ -48,9 +48,6 @@
|
||||
],
|
||||
"security": {
|
||||
"csp": "default-src 'self'"
|
||||
},
|
||||
"updater": {
|
||||
"active": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
84
examples/isolation/dist/index.html
vendored
Normal file
84
examples/isolation/dist/index.html
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<script>
|
||||
// malicious
|
||||
window.__TAURI_PATTERN__ = Object.freeze({pattern: "malicious"});
|
||||
</script>
|
||||
<script>
|
||||
// malicious defineProperty
|
||||
Object.defineProperty(window, "__TAURI_PATTERN__", {value: Object.freeze({pattern: "malicious"})});
|
||||
</script>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello Tauri!</title>
|
||||
|
||||
<style>
|
||||
body {
|
||||
/* Add a nice colorscheme to our page and text */
|
||||
background-color: #222831;
|
||||
color: #ececec;
|
||||
|
||||
/* Make the body tag the exact size of the window */
|
||||
margin: 0;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
|
||||
/* Vertically and horizontally center children of the body tag */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">console.log("inline", window.__TAURI_PATTERN__);</script>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<h1>Hello, Tauri!</h1>
|
||||
<pre><code></code></pre>
|
||||
<div>
|
||||
<button id="ping">ping</button>
|
||||
<span id="pong"></span></div>
|
||||
</div>
|
||||
<script>
|
||||
const code = document.querySelector("code");
|
||||
const obj = {};
|
||||
|
||||
function updateCode(key, value) {
|
||||
obj[key] = value;
|
||||
code.innerText = JSON.stringify(obj, null, 2);
|
||||
}
|
||||
|
||||
const cb = window.__TAURI__.transformCallback(v => updateCode('response', v));
|
||||
const error = window.__TAURI__.transformCallback(e => updateCode('response', e));
|
||||
window.ipc.postMessage(JSON.stringify({
|
||||
cmd: "ping",
|
||||
callback: cb,
|
||||
error,
|
||||
}));
|
||||
|
||||
updateCode('__TAURI_PATTERN__', window.__TAURI_PATTERN__);
|
||||
</script>
|
||||
|
||||
<!-- set up click handlers on our ping command button -->
|
||||
<script>
|
||||
const ping = document.querySelector("#ping")
|
||||
const pong = document.querySelector('#pong')
|
||||
ping.addEventListener("click", () => {
|
||||
window.__TAURI_INVOKE__("ping")
|
||||
.then(() => {
|
||||
pong.innerText = `ok: ${Date.now()}`
|
||||
})
|
||||
.catch(() => {
|
||||
pong.innerText = `error: ${Date.now()}`
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
1
examples/isolation/dist/linked.js
vendored
Normal file
1
examples/isolation/dist/linked.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
console.log("linked", window.__TAURI_PATTERN__);
|
10
examples/isolation/isolation-dist/index.html
Normal file
10
examples/isolation/isolation-dist/index.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Isolation Secure Script</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="index.js"></script>
|
||||
</body>
|
||||
</html>
|
4
examples/isolation/isolation-dist/index.js
Normal file
4
examples/isolation/isolation-dist/index.js
Normal file
@ -0,0 +1,4 @@
|
||||
window.__TAURI_ISOLATION_HOOK__= (payload) => {
|
||||
console.log('hook', payload)
|
||||
return payload
|
||||
}
|
10
examples/isolation/package.json
Normal file
10
examples/isolation/package.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "isolation",
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"scripts": {
|
||||
"tauri": "node ../../tooling/cli.js/bin/tauri"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "../../tooling/api/dist"
|
||||
}
|
||||
}
|
5
examples/isolation/src-tauri/.gitignore
vendored
Normal file
5
examples/isolation/src-tauri/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
WixTools
|
||||
.cargo
|
1
examples/isolation/src-tauri/.license_template
Symbolic link
1
examples/isolation/src-tauri/.license_template
Symbolic link
@ -0,0 +1 @@
|
||||
../../../.license_template
|
3448
examples/isolation/src-tauri/Cargo.lock
generated
Normal file
3448
examples/isolation/src-tauri/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
21
examples/isolation/src-tauri/Cargo.toml
Normal file
21
examples/isolation/src-tauri/Cargo.toml
Normal file
@ -0,0 +1,21 @@
|
||||
[package]
|
||||
name = "app"
|
||||
version = "0.1.0"
|
||||
description = "An example Tauri Application showcasing the isolation pattern"
|
||||
edition = "2021"
|
||||
license = "Apache-2.0 OR MIT"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { path = "../../../core/tauri-build", features = [ "isolation" ] }
|
||||
|
||||
[dependencies]
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tauri = { path = "../../../core/tauri", features = [ "isolation" ] }
|
||||
|
||||
[features]
|
||||
default = [ "custom-protocol", "isolation" ]
|
||||
isolation = [ "tauri/isolation", "tauri-build/isolation" ]
|
||||
custom-protocol = [ "tauri/custom-protocol" ]
|
1
examples/isolation/src-tauri/LICENSE_APACHE-2.0
Symbolic link
1
examples/isolation/src-tauri/LICENSE_APACHE-2.0
Symbolic link
@ -0,0 +1 @@
|
||||
../../../LICENSE_APACHE-2.0
|
1
examples/isolation/src-tauri/LICENSE_MIT
Symbolic link
1
examples/isolation/src-tauri/LICENSE_MIT
Symbolic link
@ -0,0 +1 @@
|
||||
../../../LICENSE_MIT
|
13
examples/isolation/src-tauri/build.rs
Normal file
13
examples/isolation/src-tauri/build.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use tauri_build::{try_build, Attributes, WindowsAttributes};
|
||||
|
||||
fn main() {
|
||||
try_build(
|
||||
Attributes::new()
|
||||
.windows_attributes(WindowsAttributes::new().window_icon_path("../../.icons/icon.ico")),
|
||||
)
|
||||
.expect("could not build tauri application");
|
||||
}
|
30
examples/isolation/src-tauri/src/main.rs
Normal file
30
examples/isolation/src-tauri/src/main.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#![cfg_attr(
|
||||
all(not(debug_assertions), target_os = "windows"),
|
||||
windows_subsystem = "windows"
|
||||
)]
|
||||
|
||||
use std::time::Instant;
|
||||
|
||||
#[tauri::command]
|
||||
fn ping() {
|
||||
dbg!(format!("ping: {:?}", Instant::now()));
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "isolation"))]
|
||||
fn main() {
|
||||
compile_error!("Feature `isolation` is required to run this example");
|
||||
}
|
||||
|
||||
#[cfg(feature = "isolation")]
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.invoke_handler(tauri::generate_handler![ping])
|
||||
.run(tauri::generate_context!(
|
||||
"../../examples/isolation/src-tauri/tauri.conf.json"
|
||||
))
|
||||
.expect("error while running tauri application");
|
||||
}
|
71
examples/isolation/src-tauri/tauri.conf.json
Normal file
71
examples/isolation/src-tauri/tauri.conf.json
Normal file
@ -0,0 +1,71 @@
|
||||
{
|
||||
"package": {
|
||||
"productName": "isolation",
|
||||
"version": "0.1.0"
|
||||
},
|
||||
"build": {
|
||||
"distDir": "../dist",
|
||||
"devPath": "../dist",
|
||||
"beforeDevCommand": "",
|
||||
"beforeBuildCommand": "",
|
||||
"withGlobalTauri": true
|
||||
},
|
||||
"tauri": {
|
||||
"pattern": {
|
||||
"use": "isolation",
|
||||
"options": {
|
||||
"dir": "../isolation-dist"
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"identifier": "com.tauri.isolation",
|
||||
"icon": [
|
||||
"../../.icons/32x32.png",
|
||||
"../../.icons/128x128.png",
|
||||
"../../.icons/128x128@2x.png",
|
||||
"../../.icons/icon.icns",
|
||||
"../../.icons/icon.ico"
|
||||
],
|
||||
"resources": [],
|
||||
"externalBin": [],
|
||||
"copyright": "",
|
||||
"category": "DeveloperTool",
|
||||
"shortDescription": "",
|
||||
"longDescription": "",
|
||||
"deb": {
|
||||
"depends": [],
|
||||
"useBootstrapper": false
|
||||
},
|
||||
"macOS": {
|
||||
"frameworks": [],
|
||||
"minimumSystemVersion": "",
|
||||
"useBootstrapper": false,
|
||||
"exceptionDomain": "",
|
||||
"signingIdentity": null,
|
||||
"entitlements": null
|
||||
},
|
||||
"windows": {
|
||||
"certificateThumbprint": null,
|
||||
"digestAlgorithm": "sha256",
|
||||
"timestampUrl": ""
|
||||
}
|
||||
},
|
||||
"updater": {
|
||||
"active": false
|
||||
},
|
||||
"windows": [
|
||||
{
|
||||
"title": "Isolation",
|
||||
"width": 800,
|
||||
"height": 600,
|
||||
"resizable": true,
|
||||
"fullscreen": false
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self' img-src: 'self'"
|
||||
}
|
||||
}
|
||||
}
|
13
examples/isolation/yarn.lock
Normal file
13
examples/isolation/yarn.lock
Normal file
@ -0,0 +1,13 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@tauri-apps/api@../../tooling/api/dist":
|
||||
version "1.0.0-beta.8"
|
||||
dependencies:
|
||||
type-fest "2.5.1"
|
||||
|
||||
type-fest@2.5.1:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.5.1.tgz#17ba4f36a6abfabf0a92005d045dca77564607b0"
|
||||
integrity sha512-JDcsxbLR6Z6OcL7TnGAAAGQrY4g7Q4EEALMT4Kp6FQuIc0JLQvOF3l7ejFvx8o5GmLlfMseTWUL++sYFP+o8kw==
|
@ -3,7 +3,7 @@ name = "multiwindow"
|
||||
version = "0.1.0"
|
||||
description = "An example Tauri Multi-Window Application"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
license = "Apache-2.0 OR MIT"
|
||||
|
||||
[build-dependencies]
|
||||
|
@ -3,7 +3,7 @@ name = "navigation"
|
||||
version = "0.1.0"
|
||||
description = "A very simple Tauri Appplication with navigation"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { path = "../../../core/tauri-build", features = [ "codegen" ] }
|
||||
|
@ -3,7 +3,7 @@ name = "resources"
|
||||
version = "0.1.0"
|
||||
description = "A Tauri application that uses Node.js with app resources"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { path = "../../../core/tauri-build", features = [ "codegen" ] }
|
||||
|
@ -3,7 +3,7 @@ name = "sidecar"
|
||||
version = "0.1.0"
|
||||
description = "A Tauri application with a sidecar binary"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { path = "../../../core/tauri-build", features = [ "codegen" ] }
|
||||
|
@ -3,7 +3,7 @@ name = "splashscreen"
|
||||
version = "0.1.0"
|
||||
description = "An example Tauri Application with a splashscreen"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
license = "Apache-2.0 OR MIT"
|
||||
|
||||
[build-dependencies]
|
||||
|
@ -3,7 +3,7 @@ name = "state"
|
||||
version = "0.1.0"
|
||||
description = "A simple Tauri Appplication showcase the state functionality"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { path = "../../../core/tauri-build", features = [ "codegen" ] }
|
||||
|
@ -3,7 +3,7 @@ name = "streaming"
|
||||
version = "0.1.0"
|
||||
description = "A very simple Tauri Appplication"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { path = "../../../core/tauri-build", features = [ "codegen" ] }
|
||||
|
@ -3,7 +3,7 @@ name = "updater-example"
|
||||
version = "0.1.0"
|
||||
description = "A very simple Tauri Appplication"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
license = "Apache-2.0 OR MIT"
|
||||
|
||||
[build-dependencies]
|
||||
|
@ -19,5 +19,8 @@
|
||||
"covector": "^0.5.3",
|
||||
"husky": "^6.0.0",
|
||||
"prettier": "^2.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"typescript": "^4.5.4"
|
||||
}
|
||||
}
|
||||
|
@ -13,17 +13,13 @@
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
interface Window {
|
||||
__TAURI_POST_MESSAGE__: (
|
||||
command: string,
|
||||
args?: { [key: string]: unknown }
|
||||
) => void
|
||||
__TAURI_IPC__: (message: any) => void,
|
||||
ipc: {
|
||||
postMessage: (args: string) => void
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the `__TAURI_INVOKE_KEY__` variable is injected at runtime by Tauri
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
declare let __TAURI_INVOKE_KEY__: number
|
||||
|
||||
/** @ignore */
|
||||
function uid(): number {
|
||||
return window.crypto.getRandomValues(new Uint32Array(1))[0]
|
||||
@ -80,12 +76,14 @@ async function invoke<T>(cmd: string, args: InvokeArgs = {}): Promise<T> {
|
||||
Reflect.deleteProperty(window, callback)
|
||||
}, true)
|
||||
|
||||
window.__TAURI_POST_MESSAGE__(cmd, {
|
||||
__invokeKey: __TAURI_INVOKE_KEY__,
|
||||
callback,
|
||||
error,
|
||||
...args
|
||||
})
|
||||
window.__TAURI_IPC__(
|
||||
{
|
||||
cmd,
|
||||
callback,
|
||||
error,
|
||||
...args
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ name = "tauri_bench"
|
||||
version = "0.1.0"
|
||||
authors = [ "Tauri Programme within The Commons Conservancy" ]
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
license = "Apache-2.0 OR MIT"
|
||||
description = "Cross-platform WebView rendering library"
|
||||
repository = "https://github.com/tauri-apps/wry"
|
||||
|
@ -3,7 +3,7 @@ name = "bench_cpu_intensive"
|
||||
version = "0.1.0"
|
||||
description = "A very simple Tauri Appplication"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { path = "../../../../../core/tauri-build", features = [ "codegen" ] }
|
||||
|
@ -3,7 +3,7 @@ name = "bench_files_transfer"
|
||||
version = "0.1.0"
|
||||
description = "A very simple Tauri Appplication"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { path = "../../../../../core/tauri-build", features = [ "codegen" ] }
|
||||
|
@ -3,7 +3,7 @@ name = "bench_helloworld"
|
||||
version = "0.1.0"
|
||||
description = "A very simple Tauri Appplication"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { path = "../../../../../core/tauri-build", features = [ "codegen" ] }
|
||||
|
@ -13,7 +13,7 @@ keywords = [ "bundle", "cargo", "tauri" ]
|
||||
repository = "https://github.com/tauri-apps/tauri"
|
||||
description = "Wrap rust executables in OS-specific app bundles for Tauri"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
exclude = [
|
||||
".license_template",
|
||||
"CHANGELOG.md",
|
||||
|
@ -8,7 +8,7 @@ authors = [ "Tauri Programme within The Commons Conservancy" ]
|
||||
license = ""
|
||||
repository = ""
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.57"
|
||||
|
||||
[package.metadata.bundle]
|
||||
identifier = "com.tauri.dev"
|
||||
|
136
tooling/cli.rs/Cargo.lock
generated
136
tooling/cli.rs/Cargo.lock
generated
@ -14,6 +14,41 @@ version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||
|
||||
[[package]]
|
||||
name = "aead"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877"
|
||||
dependencies = [
|
||||
"generic-array 0.14.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aes"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cipher",
|
||||
"cpufeatures",
|
||||
"opaque-debug 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aes-gcm"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6"
|
||||
dependencies = [
|
||||
"aead",
|
||||
"aes",
|
||||
"cipher",
|
||||
"ctr",
|
||||
"ghash",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.18"
|
||||
@ -112,6 +147,15 @@ dependencies = [
|
||||
"generic-array 0.14.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95"
|
||||
dependencies = [
|
||||
"generic-array 0.14.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-padding"
|
||||
version = "0.1.5"
|
||||
@ -410,6 +454,15 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctr"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea"
|
||||
dependencies = [
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.13.1"
|
||||
@ -501,6 +554,18 @@ dependencies = [
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b697d66081d42af4fba142d56918a3cb21dc8eb63372c6b85d14f44fb9c5979b"
|
||||
dependencies = [
|
||||
"block-buffer 0.10.0",
|
||||
"crypto-common",
|
||||
"generic-array 0.14.4",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-next"
|
||||
version = "2.0.0"
|
||||
@ -720,6 +785,16 @@ dependencies = [
|
||||
"wasi 0.10.2+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ghash"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99"
|
||||
dependencies = [
|
||||
"opaque-debug 0.3.0",
|
||||
"polyval",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gif"
|
||||
version = "0.11.3"
|
||||
@ -1586,6 +1661,18 @@ dependencies = [
|
||||
"miniz_oxide 0.3.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "polyval"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cpufeatures",
|
||||
"opaque-debug 0.3.0",
|
||||
"universal-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.16"
|
||||
@ -1961,7 +2048,7 @@ dependencies = [
|
||||
"hmac",
|
||||
"pbkdf2",
|
||||
"salsa20",
|
||||
"sha2",
|
||||
"sha2 0.10.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2088,6 +2175,26 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serialize-to-javascript"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/chippers/serialize-to-javascript#38d5026f371bfba4f5197ed143a6667a09375fbd"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serialize-to-javascript-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serialize-to-javascript-impl"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/chippers/serialize-to-javascript#38d5026f371bfba4f5197ed143a6667a09375fbd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "servo_arc"
|
||||
version = "0.1.1"
|
||||
@ -2127,6 +2234,17 @@ dependencies = [
|
||||
"digest 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "900d964dd36bb15bcf2f2b35694c072feab74969a54f2bbeec7a2d725d2bdcb6"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cpufeatures",
|
||||
"digest 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shared_child"
|
||||
version = "1.0.0"
|
||||
@ -2261,7 +2379,7 @@ dependencies = [
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"sha2 0.9.8",
|
||||
"strsim",
|
||||
"tar",
|
||||
"tempfile",
|
||||
@ -2320,6 +2438,8 @@ dependencies = [
|
||||
name = "tauri-utils"
|
||||
version = "1.0.0-beta.3"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"base64",
|
||||
"heck",
|
||||
"html5ever",
|
||||
"kuchiki",
|
||||
@ -2328,6 +2448,8 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_with",
|
||||
"serialize-to-javascript",
|
||||
"sha2 0.9.8",
|
||||
"thiserror",
|
||||
"url",
|
||||
]
|
||||
@ -2522,6 +2644,16 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "universal-hash"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05"
|
||||
dependencies = [
|
||||
"generic-array 0.14.4",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.7.1"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user