feat(core): Use Wry custom protocol instead of embedded server (#1296)

Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
This commit is contained in:
Noah Klayman 2021-02-25 17:07:30 -08:00 committed by GitHub
parent c16a2730ff
commit 0c691f40a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 239 additions and 649 deletions

View File

@ -0,0 +1,5 @@
---
"tauri": minor
---
Replaces the embedded-server mode with Wry's custom protocol feature. This allows assets to be transferred to the webview directly, instead of through a localhost server.

View File

@ -62,7 +62,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
feature: [embedded-server, api-all]
feature: [custom-protocol, api-all]
steps:
- uses: actions/checkout@v2

125
cli/core/Cargo.lock generated
View File

@ -144,9 +144,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
[[package]]
name = "bytemuck"
version = "1.5.0"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a4bad0c5981acc24bc09e532f35160f952e35422603f0563cd7a73c2c2e65a0"
checksum = "bed57e2090563b83ba8f83366628ce535a7584c9afa4c9fc0612a03925c6df58"
[[package]]
name = "byteorder"
@ -183,9 +183,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.0.66"
version = "1.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
[[package]]
name = "cfg-if"
@ -275,12 +275,6 @@ dependencies = [
"unreachable",
]
[[package]]
name = "const_fn"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6"
[[package]]
name = "core-foundation"
version = "0.9.1"
@ -335,34 +329,35 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
version = "0.9.1"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d"
checksum = "d60ab4a8dba064f2fbb5aa270c28da5cf4bbd0e72dae1140a6b0353a779dbe00"
dependencies = [
"cfg-if 1.0.0",
"const_fn",
"crossbeam-utils",
"lazy_static",
"loom",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.1"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
checksum = "bae8f328835f8f5a6ceb6a7842a7f2d0c03692adb5c889347235d59194731fe3"
dependencies = [
"autocfg",
"cfg-if 1.0.0",
"lazy_static",
"loom",
]
[[package]]
name = "darling"
version = "0.12.0"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11947000d710ff98138229f633039982f0fef2d9a3f546c21d610fee5f8631d5"
checksum = "a06d4a9551359071d1890820e3571252b91229e0712e7c36b08940e603c5a8fc"
dependencies = [
"darling_core",
"darling_macro",
@ -370,9 +365,9 @@ dependencies = [
[[package]]
name = "darling_core"
version = "0.12.0"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae53b4d9cc89c40314ccf2bf9e6ff1eb19c31e3434542445a41893dbf041aec2"
checksum = "b443e5fb0ddd56e0c9bfa47dc060c5306ee500cb731f2b91432dd65589a77684"
dependencies = [
"fnv",
"ident_case",
@ -384,9 +379,9 @@ dependencies = [
[[package]]
name = "darling_macro"
version = "0.12.0"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9cd9ac4d50d023af5e710cae1501afb063efcd917bd3fc026e8ed6493cc9755"
checksum = "c0220073ce504f12a70efc4e7cdaea9e9b1b324872e7ad96a208056d7a638b81"
dependencies = [
"darling_core",
"quote",
@ -454,15 +449,6 @@ version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "error-chain"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc"
dependencies = [
"version_check",
]
[[package]]
name = "failure"
version = "0.1.8"
@ -525,9 +511,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "form_urlencoded"
version = "1.0.0"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ece68d15c92e84fa4f19d3780f1294e5ca82a78a6d515f1efaabcc144688be00"
checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
dependencies = [
"matches",
"percent-encoding",
@ -568,6 +554,19 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
[[package]]
name = "generator"
version = "0.6.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9fed24fd1e18827652b4d55652899a1e9da8e54d91624dc3437a5bc3a9f9a9c"
dependencies = [
"cc",
"libc",
"log",
"rustversion",
"winapi 0.3.9",
]
[[package]]
name = "generic-array"
version = "0.12.3"
@ -633,9 +632,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "handlebars"
version = "3.5.2"
version = "3.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "964d0e99a61fe9b1b347389b77ebf8b7e1587b70293676aaca7d27e59b9073b2"
checksum = "cdb0867bbc5a3da37a753e78021d5fcf8a4db00e18dd2dd90fd36e24190e162d"
dependencies = [
"log",
"pest",
@ -704,9 +703,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de910d521f7cc3135c4de8db1cb910e0b5ed1dc6f57c381cd07e8e661ce10094"
checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21"
dependencies = [
"matches",
"unicode-bidi",
@ -877,6 +876,17 @@ dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "loom"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d44c73b4636e497b4917eb21c33539efa3816741a2d3ff26c6316f1b529481a4"
dependencies = [
"cfg-if 1.0.0",
"generator",
"scoped-tls",
]
[[package]]
name = "maplit"
version = "1.0.2"
@ -1279,14 +1289,11 @@ dependencies = [
[[package]]
name = "publicsuffix"
version = "1.5.4"
version = "1.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bbaa49075179162b49acac1c6aa45fb4dafb5f13cf6794276d77bc7fd95757b"
checksum = "dfe62f914117aacd6c015acc535085fc18c38efd6848cc23448f99808ec25edb"
dependencies = [
"error-chain",
"idna",
"lazy_static",
"regex",
"url",
]
@ -1489,6 +1496,12 @@ version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232"
[[package]]
name = "rustversion"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd"
[[package]]
name = "ryu"
version = "1.0.5"
@ -1538,6 +1551,12 @@ dependencies = [
"syn",
]
[[package]]
name = "scoped-tls"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
[[package]]
name = "scoped_threadpool"
version = "0.1.9"
@ -1552,9 +1571,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "security-framework"
version = "2.0.0"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1759c2e3c8580017a484a7ac56d3abc5a6c1feadf88db2f3633f12ae4268c69"
checksum = "c6af1b6204f89cf0069736daf8b852573e3bc34898eee600e95d3dd855c12e81"
dependencies = [
"bitflags",
"core-foundation",
@ -1565,9 +1584,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
version = "2.0.0"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f99b9d5e26d2a71633cc4f2ebae7cc9f874044e0c351a27e17892d76dce5678b"
checksum = "31531d257baab426203cf81c5ce1b0b55159dda7ed602ac81b582ccd62265741"
dependencies = [
"core-foundation-sys",
"libc",
@ -1709,9 +1728,9 @@ dependencies = [
[[package]]
name = "tar"
version = "0.4.32"
version = "0.4.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0313546c01d59e29be4f09687bcb4fb6690cec931cc3607b6aec7a0e417f4cc6"
checksum = "c0bcfbd6a598361fda270d82469fff3d65089dc33e175c9a131f7b4cd395f228"
dependencies = [
"filetime",
"libc",
@ -1806,18 +1825,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.23"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76cc616c6abf8c8928e2fdcc0dbfab37175edd8fb49a4641066ad1364fdab146"
checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.23"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1"
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
dependencies = [
"proc-macro2",
"quote",
@ -1966,9 +1985,9 @@ dependencies = [
[[package]]
name = "url"
version = "2.2.0"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e"
checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b"
dependencies = [
"form_urlencoded",
"idna",

View File

@ -188,22 +188,6 @@ pub enum Port {
Random,
}
/// The embeddedServer configuration object.
#[skip_serializing_none]
#[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct EmbeddedServerConfig {
/// The embedded server host.
pub host: Option<String>,
/// The embedded server port.
/// If it's `random`, we'll generate one at runtime.
pub port: Option<Port>,
/// The base path of the embedded server.
/// The path should always start and end in a forward slash, which the deserializer will ensure
pub public_path: Option<String>,
}
/// The window configuration object.
#[skip_serializing_none]
#[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
@ -498,8 +482,6 @@ pub struct TauriConfig {
pub windows: Vec<WindowConfig>,
/// The CLI configuration.
pub cli: Option<CliConfig>,
#[serde(default)]
pub embedded_server: EmbeddedServerConfig,
/// The bundler configuration.
#[serde(default)]
pub bundle: BundleConfig,

View File

@ -79,7 +79,6 @@
"useBootstrapper": false
}
},
"embeddedServer": {},
"windows": []
},
"allOf": [
@ -649,38 +648,6 @@
},
"additionalProperties": false
},
"EmbeddedServerConfig": {
"description": "The embeddedServer configuration object.",
"type": "object",
"properties": {
"host": {
"description": "The embedded server host.",
"type": [
"string",
"null"
]
},
"port": {
"description": "The embedded server port. If it's `random`, we'll generate one at runtime.",
"anyOf": [
{
"$ref": "#/definitions/Port"
},
{
"type": "null"
}
]
},
"publicPath": {
"description": "The base path of the embedded server. The path should always start and end in a forward slash, which the deserializer will ensure",
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
},
"FsAllowlistConfig": {
"type": "object",
"properties": {
@ -806,20 +773,6 @@
},
"additionalProperties": false
},
"Port": {
"anyOf": [
{
"description": "Port with a numeric value.",
"type": "integer",
"format": "uint16",
"minimum": 0.0
},
{
"description": "Random port.",
"type": "null"
}
]
},
"SecurityConfig": {
"type": "object",
"properties": {
@ -930,14 +883,6 @@
}
]
},
"embeddedServer": {
"default": {},
"allOf": [
{
"$ref": "#/definitions/EmbeddedServerConfig"
}
]
},
"security": {
"anyOf": [
{

View File

@ -56,7 +56,7 @@ struct CargoConfig {
}
pub fn build_project(debug: bool) -> crate::Result<()> {
let mut args = vec!["build", "--features=embedded-server"];
let mut args = vec!["build", "--features=custom-protocol"];
if !debug {
args.push("--release");

View File

@ -14,9 +14,6 @@ mod settings;
#[cfg(target_os = "windows")]
mod wix;
#[cfg(windows)]
use std::process::Command;
pub use self::{
category::AppCategory,
common::{print_error, print_info},
@ -56,30 +53,6 @@ pub fn bundle_project(settings: Settings) -> crate::Result<Vec<PathBuf>> {
settings.copy_resources(settings.project_out_directory())?;
settings.copy_binaries(settings.project_out_directory())?;
#[cfg(windows)]
{
let exempt_output = Command::new("CheckNetIsolation")
.args(&vec!["LoopbackExempt", "-s"])
.output()
.expect("failed to read LoopbackExempt -s");
if !exempt_output.status.success() {
panic!("Failed to execute CheckNetIsolation LoopbackExempt -s");
}
let output_str = String::from_utf8_lossy(&exempt_output.stdout).to_lowercase();
if !output_str.contains("win32webviewhost_cw5n1h2txyewy") {
println!("Running Loopback command");
runas::Command::new("powershell")
.args(&[
"CheckNetIsolation LoopbackExempt -a -n=\"Microsoft.Win32WebViewHost_cw5n1h2txyewy\"",
])
.force_prompt(true)
.status()
.expect("failed to run Loopback command");
}
}
print_finished(&paths)?;
Ok(paths)

View File

@ -147,19 +147,6 @@
</Feature>
</Feature>
<SetProperty Id="ARPINSTALLLOCATION" Value="[INSTALLDIR]" After="CostFinalize"/>
{{#if embedded_server}}
<InstallExecuteSequence>
<Custom Action='LoopBackCmd' After='InstallFiles'/>
</InstallExecuteSequence>
{{/if}}
<SetProperty Id="ARPINSTALLLOCATION" Value="[INSTALLDIR]" After="CostFinalize"/>
</Product>
{{#if embedded_server}}
<Fragment>
<CustomAction Id="LoopBackCmd" Directory="ApplicationProgramsFolder" Execute="commit" Impersonate="no" ExeCommand="cmd.exe /c &quot;CheckNetIsolation.exe LoopbackExempt -a -n=&quot;Microsoft.Win32WebViewHost_cw5n1h2txyewy&quot;&quot;" Return="ignore" />
</Fragment>
{{/if}}
</Wix>

View File

@ -442,8 +442,6 @@ pub fn build_wix_app_installer(
let mut data = BTreeMap::new();
data.insert("embedded_server", to_json(true));
data.insert("product_name", to_json(settings.bundle_name()));
data.insert("version", to_json(settings.version_string()));
let manufacturer = settings.bundle_identifier().to_string();

View File

@ -20,7 +20,7 @@ tauri = <%= tauriDep || `{ version = "0.5" }` %>
winres = "0.1"
[features]
embedded-server = [ "tauri/embedded-server" ]
custom-protocol = [ "tauri/custom-protocol" ]
[[bin]]
name = "app"

View File

@ -67,8 +67,8 @@ describe('Tauri Build', () => {
it.each`
mode | flag
${'embedded-server'} | ${'debug'}
${'embedded-server'} | ${'release'}
${'custom-protocol'} | ${'debug'}
${'custom-protocol'} | ${'release'}
`('works with the $mode $flag mode', ({ mode, flag }) => {
return runBuildTest({
debug: flag === 'debug',

View File

@ -27,7 +27,7 @@ serde_derive = "1.0"
tauri = { path = "../../../../../../../tauri", features =["api-all"]}
[features]
embedded-server = [ "tauri/embedded-server" ]
custom-protocol = [ "tauri/custom-protocol" ]
[[bin]]
name = "app"

View File

@ -1,5 +1,5 @@
use serde::{
de::{Deserializer, Error as DeError, Visitor},
de::{Deserializer, Visitor},
Deserialize,
};
use serde_json::Value as JsonValue;
@ -155,135 +155,6 @@ impl Default for WindowConfig {
}
}
/// The embedded server port.
#[derive(PartialEq, Debug, Deserialize)]
pub enum Port {
/// Port with a numeric value.
Value(u16),
/// Random port.
Random,
}
/// The embeddedServer configuration object.
#[derive(PartialEq, Deserialize, Debug)]
#[serde(tag = "embeddedServer", rename_all = "camelCase")]
pub struct EmbeddedServerConfig {
/// The embedded server host.
#[serde(default = "default_host")]
pub host: String,
/// The embedded server port.
/// If it's `random`, we'll generate one at runtime.
#[serde(default = "default_port", deserialize_with = "port_deserializer")]
pub port: Port,
/// The base path of the embedded server.
/// The path should always start and end in a forward slash, which the deserializer will ensure
#[serde(
default = "default_public_path",
deserialize_with = "public_path_deserializer"
)]
pub public_path: String,
}
fn default_host() -> String {
"http://127.0.0.1".to_string()
}
fn default_port() -> Port {
Port::Random
}
fn default_public_path() -> String {
"/".to_string()
}
impl Default for EmbeddedServerConfig {
fn default() -> Self {
Self {
host: default_host(),
port: default_port(),
public_path: default_public_path(),
}
}
}
fn port_deserializer<'de, D>(deserializer: D) -> Result<Port, D::Error>
where
D: Deserializer<'de>,
{
struct PortDeserializer;
impl<'de> Visitor<'de> for PortDeserializer {
type Value = Port;
fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("a port number or the 'random' string")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: DeError,
{
if value != "random" {
Err(DeError::custom(
"expected a 'random' string or a port number",
))
} else {
Ok(Port::Random)
}
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: DeError,
{
Ok(Port::Value(value as u16))
}
}
deserializer.deserialize_any(PortDeserializer {})
}
fn public_path_deserializer<'de, D>(deserializer: D) -> Result<String, D::Error>
where
D: Deserializer<'de>,
{
struct PublicPathDeserializer;
impl<'de> Visitor<'de> for PublicPathDeserializer {
type Value = String;
fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("a string starting and ending in a forward slash /")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: DeError,
{
match value.len() {
0 => return Ok("/".into()),
1 if value == "/" => return Ok("/".into()),
1 => return Ok(format!("/{}/", value)),
_ => {}
}
// we know there are at least 2 characters in the string
let mut chars = value.chars();
let first = chars.next().unwrap();
let last = chars.last().unwrap();
match (first == '/', last == '/') {
(true, true) => Ok(value.into()),
(true, false) => Ok(format!("{}/", value)),
(false, true) => Ok(format!("/{}", value)),
_ => Ok(format!("/{}/", value)),
}
}
}
deserializer.deserialize_any(PublicPathDeserializer {})
}
/// A CLI argument definition
#[derive(PartialEq, Deserialize, Debug, Default)]
#[serde(rename_all = "camelCase")]
@ -446,9 +317,6 @@ pub struct TauriConfig {
/// The window configuration.
#[serde(default = "default_window_config")]
pub windows: Vec<WindowConfig>,
/// The embeddedServer configuration.
#[serde(default)]
pub embedded_server: EmbeddedServerConfig,
/// The CLI configuration.
#[serde(default)]
pub cli: Option<CliConfig>,
@ -461,7 +329,6 @@ impl Default for TauriConfig {
fn default() -> Self {
Self {
windows: default_window_config(),
embedded_server: EmbeddedServerConfig::default(),
cli: None,
bundle: BundleConfig::default(),
}
@ -542,8 +409,6 @@ mod test {
let b_config = BuildConfig::default();
// get default dev path
let d_path = default_dev_path();
// get default embedded server
let de_server = EmbeddedServerConfig::default();
// get default window
let d_windows = default_window_config();
// get default title
@ -573,11 +438,6 @@ mod test {
decorations: true,
always_on_top: false,
}],
embedded_server: EmbeddedServerConfig {
host: String::from("http://127.0.0.1"),
port: Port::Random,
public_path: "/".into(),
},
bundle: BundleConfig {
identifier: String::from(""),
},
@ -593,7 +453,6 @@ mod test {
// test the configs
assert_eq!(t_config, tauri);
assert_eq!(b_config, build);
assert_eq!(de_server, tauri.embedded_server);
assert_eq!(d_bundle, tauri.bundle);
assert_eq!(d_path, String::from("http://localhost:8080"));
assert_eq!(d_title, tauri.windows[0].title);

View File

@ -23,7 +23,6 @@ serde = { version = "1.0", features = [ "derive" ] }
base64 = "0.13.0"
webbrowser = "0.5.5"
lazy_static = "1.4.0"
tiny_http = { version = "0.8", optional = true }
tokio = { version = "1.2", features = ["rt", "rt-multi-thread", "sync"] }
futures = "0.3"
async-trait = "0.1"
@ -32,7 +31,7 @@ thiserror = "1.0.24"
once_cell = "1.7.0"
tauri-api = { version = "0.7.5", path = "../tauri-api" }
tauri-macros = { version = "0.1", path = "../tauri-macros" }
wry = { git = "https://github.com/tauri-apps/wry", rev = "e0b63d2d9179e4f79ff57affc59338372cefae8b" }
wry = { git = "https://github.com/tauri-apps/wry", rev = "a607d6aba95e6ee0d9620394b7ee0092527095dc" }
rand = "0.8"
[target."cfg(target_os = \"windows\")".dependencies]
@ -49,7 +48,7 @@ serde = { version = "1.0", features = [ "derive" ] }
[features]
cli = [ "tauri-api/cli" ]
embedded-server = [ "tiny_http" ]
custom-protocol = [ ]
api-all = [ "tauri-api/notification", "tauri-api/global-shortcut" ]
updater = [ ]

View File

@ -2,8 +2,8 @@ use cfg_aliases::cfg_aliases;
fn main() {
cfg_aliases! {
embedded_server: { feature = "embedded-server" },
dev: { not(feature = "embedded-server") },
custom_protocol: { feature = "custom-protocol" },
dev: { not(feature = "custom-protocol") },
api_all: { feature = "api-all" },

View File

@ -68,12 +68,6 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "ascii"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbf56136a5198c7b01a49e3afcbef6cf84597273d298f54432926024107b0109"
[[package]]
name = "async-trait"
version = "0.1.42"
@ -298,12 +292,6 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "chunked_transfer"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e"
[[package]]
name = "clap"
version = "3.0.0-beta.2"
@ -1272,6 +1260,12 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "infer"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8906512588cd815b8f759fd0ac11de2a84c985c0f792f70df611e9325c270c1f"
[[package]]
name = "instant"
version = "0.1.9"
@ -1826,9 +1820,9 @@ checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4"
[[package]]
name = "once_cell"
version = "1.6.0"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ad167a2f54e832b82dbe003a046280dceffe5227b5f79e08e363a29638cfddd"
checksum = "10acf907b94fc1b1a152d08ef97e7759650268cf986bf127f387e602b02c7e5a"
[[package]]
name = "openssl"
@ -2430,9 +2424,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "security-framework"
version = "2.0.0"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1759c2e3c8580017a484a7ac56d3abc5a6c1feadf88db2f3633f12ae4268c69"
checksum = "c6af1b6204f89cf0069736daf8b852573e3bc34898eee600e95d3dd855c12e81"
dependencies = [
"bitflags 1.2.1",
"core-foundation 0.9.1",
@ -2443,9 +2437,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
version = "2.0.0"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f99b9d5e26d2a71633cc4f2ebae7cc9f874044e0c351a27e17892d76dce5678b"
checksum = "31531d257baab426203cf81c5ce1b0b55159dda7ed602ac81b582ccd62265741"
dependencies = [
"core-foundation-sys 0.8.2",
"libc",
@ -2739,7 +2733,6 @@ dependencies = [
"tauri-api",
"tauri-macros",
"thiserror",
"tiny_http",
"tokio",
"uuid",
"webbrowser",
@ -2898,19 +2891,6 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "tiny_http"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eded47106b8e52d8ed8119f0ea6e8c0f5881e69783e0297b5a8462958f334bc1"
dependencies = [
"ascii",
"chrono",
"chunked_transfer",
"log",
"url",
]
[[package]]
name = "tinyfiledialogs"
version = "3.3.10"
@ -3535,7 +3515,7 @@ dependencies = [
[[package]]
name = "wry"
version = "0.5.1"
source = "git+https://github.com/tauri-apps/wry?rev=e0b63d2d9179e4f79ff57affc59338372cefae8b#e0b63d2d9179e4f79ff57affc59338372cefae8b"
source = "git+https://github.com/tauri-apps/wry?rev=0611ccbf74a88f43a1eb6e56275591d7b4461aa7#0611ccbf74a88f43a1eb6e56275591d7b4461aa7"
dependencies = [
"cairo-rs",
"cocoa",
@ -3546,8 +3526,8 @@ dependencies = [
"glib",
"gtk",
"image",
"infer",
"libc",
"mime_guess",
"objc",
"once_cell",
"serde",

View File

@ -20,7 +20,7 @@ tauri = { path = "../../..", features =["api-all", "cli"]}
winres = "0.1"
[features]
embedded-server = [ "tauri/embedded-server" ]
custom-protocol = [ "tauri/custom-protocol" ]
[[bin]]
name = "app"

View File

@ -58,12 +58,6 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "ascii"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbf56136a5198c7b01a49e3afcbef6cf84597273d298f54432926024107b0109"
[[package]]
name = "async-trait"
version = "0.1.42"
@ -277,12 +271,6 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "chunked_transfer"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e"
[[package]]
name = "cocoa"
version = "0.24.0"
@ -1229,6 +1217,12 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "infer"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8906512588cd815b8f759fd0ac11de2a84c985c0f792f70df611e9325c270c1f"
[[package]]
name = "instant"
version = "0.1.9"
@ -1783,9 +1777,9 @@ checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4"
[[package]]
name = "once_cell"
version = "1.6.0"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ad167a2f54e832b82dbe003a046280dceffe5227b5f79e08e363a29638cfddd"
checksum = "10acf907b94fc1b1a152d08ef97e7759650268cf986bf127f387e602b02c7e5a"
[[package]]
name = "openssl"
@ -2381,9 +2375,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "security-framework"
version = "2.0.0"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1759c2e3c8580017a484a7ac56d3abc5a6c1feadf88db2f3633f12ae4268c69"
checksum = "c6af1b6204f89cf0069736daf8b852573e3bc34898eee600e95d3dd855c12e81"
dependencies = [
"bitflags 1.2.1",
"core-foundation 0.9.1",
@ -2394,9 +2388,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
version = "2.0.0"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f99b9d5e26d2a71633cc4f2ebae7cc9f874044e0c351a27e17892d76dce5678b"
checksum = "31531d257baab426203cf81c5ce1b0b55159dda7ed602ac81b582ccd62265741"
dependencies = [
"core-foundation-sys 0.8.2",
"libc",
@ -2684,7 +2678,6 @@ dependencies = [
"tauri-api",
"tauri-macros",
"thiserror",
"tiny_http",
"tokio",
"uuid",
"webbrowser",
@ -2824,19 +2817,6 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "tiny_http"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eded47106b8e52d8ed8119f0ea6e8c0f5881e69783e0297b5a8462958f334bc1"
dependencies = [
"ascii",
"chrono",
"chunked_transfer",
"log",
"url",
]
[[package]]
name = "tinyfiledialogs"
version = "3.3.10"
@ -3449,7 +3429,7 @@ dependencies = [
[[package]]
name = "wry"
version = "0.5.1"
source = "git+https://github.com/tauri-apps/wry?rev=e0b63d2d9179e4f79ff57affc59338372cefae8b#e0b63d2d9179e4f79ff57affc59338372cefae8b"
source = "git+https://github.com/tauri-apps/wry?rev=0611ccbf74a88f43a1eb6e56275591d7b4461aa7#0611ccbf74a88f43a1eb6e56275591d7b4461aa7"
dependencies = [
"cairo-rs",
"cocoa",
@ -3460,8 +3440,8 @@ dependencies = [
"glib",
"gtk",
"image",
"infer",
"libc",
"mime_guess",
"objc",
"once_cell",
"serde",

View File

@ -20,8 +20,8 @@ tauri = { path = "../../..", features =["api-all"]}
winres = "0.1"
[features]
default = [ "embedded-server" ]
embedded-server = [ "tauri/embedded-server" ]
default = [ "custom-protocol" ]
custom-protocol = [ "tauri/custom-protocol" ]
[[bin]]
name = "helloworld"

View File

@ -66,12 +66,6 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "ascii"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbf56136a5198c7b01a49e3afcbef6cf84597273d298f54432926024107b0109"
[[package]]
name = "async-trait"
version = "0.1.42"
@ -285,12 +279,6 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "chunked_transfer"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e"
[[package]]
name = "cocoa"
version = "0.24.0"
@ -1227,6 +1215,12 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "infer"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8906512588cd815b8f759fd0ac11de2a84c985c0f792f70df611e9325c270c1f"
[[package]]
name = "instant"
version = "0.1.9"
@ -1781,9 +1775,9 @@ checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4"
[[package]]
name = "once_cell"
version = "1.6.0"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ad167a2f54e832b82dbe003a046280dceffe5227b5f79e08e363a29638cfddd"
checksum = "10acf907b94fc1b1a152d08ef97e7759650268cf986bf127f387e602b02c7e5a"
[[package]]
name = "openssl"
@ -2379,9 +2373,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "security-framework"
version = "2.0.0"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1759c2e3c8580017a484a7ac56d3abc5a6c1feadf88db2f3633f12ae4268c69"
checksum = "c6af1b6204f89cf0069736daf8b852573e3bc34898eee600e95d3dd855c12e81"
dependencies = [
"bitflags 1.2.1",
"core-foundation 0.9.1",
@ -2392,9 +2386,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
version = "2.0.0"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f99b9d5e26d2a71633cc4f2ebae7cc9f874044e0c351a27e17892d76dce5678b"
checksum = "31531d257baab426203cf81c5ce1b0b55159dda7ed602ac81b582ccd62265741"
dependencies = [
"core-foundation-sys 0.8.2",
"libc",
@ -2682,7 +2676,6 @@ dependencies = [
"tauri-api",
"tauri-macros",
"thiserror",
"tiny_http",
"tokio",
"uuid",
"webbrowser",
@ -2822,19 +2815,6 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "tiny_http"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eded47106b8e52d8ed8119f0ea6e8c0f5881e69783e0297b5a8462958f334bc1"
dependencies = [
"ascii",
"chrono",
"chunked_transfer",
"log",
"url",
]
[[package]]
name = "tinyfiledialogs"
version = "3.3.10"
@ -3447,7 +3427,7 @@ dependencies = [
[[package]]
name = "wry"
version = "0.5.1"
source = "git+https://github.com/tauri-apps/wry?rev=e0b63d2d9179e4f79ff57affc59338372cefae8b#e0b63d2d9179e4f79ff57affc59338372cefae8b"
source = "git+https://github.com/tauri-apps/wry?rev=0611ccbf74a88f43a1eb6e56275591d7b4461aa7#0611ccbf74a88f43a1eb6e56275591d7b4461aa7"
dependencies = [
"cairo-rs",
"cocoa",
@ -3458,8 +3438,8 @@ dependencies = [
"glib",
"gtk",
"image",
"infer",
"libc",
"mime_guess",
"objc",
"once_cell",
"serde",

View File

@ -28,8 +28,8 @@ tauri = { path = "../../..", features =["api-all"]}
winres = "0.1"
[features]
default = [ "embedded-server" ]
embedded-server = [ "tauri/embedded-server" ]
default = [ "custom-protocol" ]
custom-protocol = [ "tauri/custom-protocol" ]
[[bin]]
name = "app"

View File

@ -14,8 +14,8 @@ mod webview_manager;
pub use crate::api::config::WindowUrl;
pub use webview::{
wry::WryApplication, ApplicationDispatcherExt, ApplicationExt, Callback, Icon, Message,
WebviewBuilderExt,
wry::WryApplication, ApplicationDispatcherExt, ApplicationExt, Callback, CustomProtocol, Icon,
Message, WebviewBuilderExt,
};
pub use webview_manager::{WebviewDispatcher, WebviewManager};
@ -133,6 +133,7 @@ trait WebviewInitializer<A: ApplicationExt> {
) -> crate::Result<(
<A as ApplicationExt>::WebviewBuilder,
Vec<Callback<A::Dispatcher>>,
Option<CustomProtocol>,
)>;
async fn on_webview_created(
@ -151,6 +152,7 @@ impl<A: ApplicationExt + 'static> WebviewInitializer<A> for Arc<App<A>> {
) -> crate::Result<(
<A as ApplicationExt>::WebviewBuilder,
Vec<Callback<A::Dispatcher>>,
Option<CustomProtocol>,
)> {
let webview_manager = WebviewManager::new(
self.clone(),
@ -271,7 +273,7 @@ impl<A: ApplicationExt + 'static, C: AsTauriContext> AppBuilder<A, C> {
crate::async_runtime::block_on(crate::plugin::initialization_script(A::plugin_store()));
let context = Context::new::<C>()?;
let url = utils::get_url(&context)?;
let url = utils::get_url(&context);
Ok(App {
invoke_handler: self.invoke_handler,
@ -292,9 +294,6 @@ fn run<A: ApplicationExt + 'static>(mut application: App<A>) -> crate::Result<()
crate::plugin::initialize(A::plugin_store(), plugin_config).await
})?;
#[cfg(embedded_server)]
utils::spawn_server(application.url.to_string(), &application.context);
let webviews = application.webviews.take().unwrap();
let application = Arc::new(application);
@ -307,10 +306,10 @@ fn run<A: ApplicationExt + 'static>(mut application: App<A>) -> crate::Result<()
application.dispatchers.clone(),
webview_label.to_string(),
);
let (webview_builder, callbacks) =
let (webview_builder, callbacks, custom_protocol) =
crate::async_runtime::block_on(application.init_webview(webview))?;
let dispatcher = webview_app.create_webview(webview_builder, callbacks)?;
let dispatcher = webview_app.create_webview(webview_builder, callbacks, custom_protocol)?;
crate::async_runtime::block_on(application.on_webview_created(
webview_label,
dispatcher,

View File

@ -1,12 +1,8 @@
#[cfg(dev)]
use std::io::Read;
use std::sync::Arc;
#[cfg(dev)]
use crate::api::assets::{AssetFetch, Assets};
use std::{io::Read, sync::Arc};
use crate::{
api::{
assets::{AssetFetch, Assets},
config::WindowUrl,
rpc::{format_callback, format_callback_result},
},
@ -15,11 +11,9 @@ use crate::{
};
use super::{
webview::{Callback, WebviewBuilderExtPrivate},
webview::{Callback, CustomProtocol, WebviewBuilderExtPrivate},
App, Context, Webview, WebviewManager,
};
#[cfg(embedded_server)]
use crate::api::tcp::{get_available_port, port_is_available};
use serde::Deserialize;
use serde_json::Value as JsonValue;
@ -38,36 +32,12 @@ struct Message {
// setup content for dev-server
#[cfg(dev)]
#[allow(clippy::unnecessary_wraps)]
pub(super) fn get_url(context: &Context) -> crate::Result<String> {
pub(super) fn get_url(context: &Context) -> String {
let config = &context.config;
if config.build.dev_path.starts_with("http") {
#[cfg(windows)]
{
let exempt_output = std::process::Command::new("CheckNetIsolation")
.args(&vec!["LoopbackExempt", "-s"])
.output()
.expect("failed to read LoopbackExempt -s");
if !exempt_output.status.success() {
panic!("Failed to execute CheckNetIsolation LoopbackExempt -s");
}
let output_str = String::from_utf8_lossy(&exempt_output.stdout).to_lowercase();
if !output_str.contains("win32webviewhost_cw5n1h2txyewy") {
println!("Running Loopback command");
runas::Command::new("powershell")
.args(&[
"CheckNetIsolation LoopbackExempt -a -n=\"Microsoft.Win32WebViewHost_cw5n1h2txyewy\"",
])
.force_prompt(true)
.status()
.expect("failed to run Loopback command");
}
}
Ok(config.build.dev_path.clone())
config.build.dev_path.clone()
} else {
Ok(format!(
format!(
"data:text/html;base64,{}",
base64::encode(
context
@ -82,80 +52,14 @@ pub(super) fn get_url(context: &Context) -> crate::Result<String> {
})
.expect("Unable to find `index.html` under your devPath folder")
)
))
)
}
}
// setup content for embedded server
#[cfg(embedded_server)]
pub(super) fn get_url(context: &Context) -> crate::Result<String> {
let (port, valid) = setup_port(&context);
if valid {
Ok(setup_server_url(port, &context))
} else {
Err(crate::Error::PortNotAvailable(port))
}
}
// get the port for the embedded server
#[cfg(embedded_server)]
#[allow(dead_code)]
fn setup_port(context: &Context) -> (String, bool) {
let config = &context.config;
match config.tauri.embedded_server.port {
tauri_api::config::Port::Random => match get_available_port() {
Some(available_port) => (available_port.to_string(), true),
None => ("0".to_string(), false),
},
tauri_api::config::Port::Value(port) => {
let port_valid = port_is_available(port);
(port.to_string(), port_valid)
}
}
}
// setup the server url for embedded server
#[cfg(embedded_server)]
#[allow(dead_code)]
fn setup_server_url(port: String, context: &Context) -> String {
let config = &context.config;
let mut url = format!("{}:{}", config.tauri.embedded_server.host, port);
if !url.starts_with("http") {
url = format!("http://{}", url);
}
url
}
// spawn the embedded server
#[cfg(embedded_server)]
pub(super) fn spawn_server(server_url: String, context: &Context) {
let assets = context.assets;
let public_path = context.config.tauri.embedded_server.public_path.clone();
std::thread::spawn(move || {
let server = tiny_http::Server::http(server_url.replace("http://", "").replace("https://", ""))
.expect("Unable to spawn server");
for request in server.incoming_requests() {
let url = request.url().replace(&server_url, "");
let url = match url.as_str() {
"/" => "/index.html",
url => {
if url.starts_with(&public_path) {
&url[public_path.len() - 1..]
} else {
eprintln!(
"found url not matching public path.\nurl: {}\npublic path: {}",
url, public_path
);
url
}
}
}
.to_string();
request
.respond(crate::server::asset_response(&url, assets))
.expect("unable to setup response");
}
});
#[cfg(custom_protocol)]
pub(super) fn get_url(_: &Context) -> String {
// Custom protocol doesn't require any setup, so just return URL
"tauri://index.html".into()
}
// spawn an updater process.
@ -237,6 +141,7 @@ fn event_initialization_script() -> String {
pub(super) type BuiltWebview<A> = (
<A as ApplicationExt>::WebviewBuilder,
Vec<Callback<<A as ApplicationExt>::Dispatcher>>,
Option<CustomProtocol>,
);
// build the webview.
@ -255,7 +160,7 @@ pub(super) fn build_webview<A: ApplicationExt + 'static>(
WindowUrl::Custom(url) => url.to_string(),
};
let (webview_builder, callbacks) = if webview.url == WindowUrl::App {
let (webview_builder, callbacks, custom_protocol) = if webview.url == WindowUrl::App {
let mut webview_builder = webview.builder.url(webview_url)
.initialization_script(&initialization_script(plugin_initialization_script, &context.tauri_script))
.initialization_script(&format!(
@ -322,12 +227,53 @@ pub(super) fn build_webview<A: ApplicationExt + 'static>(
}
}),
};
(webview_builder, vec![tauri_invoke_handler])
let assets = context.assets;
let custom_protocol = CustomProtocol {
name: "tauri".into(),
handler: Box::new(move |path| {
let mut path = path.to_string().replace("tauri://", "");
if path.ends_with('/') {
path.pop();
}
let path =
if let Some((first, components)) = path.split('/').collect::<Vec<&str>>().split_first() {
match components.len() {
0 => first.to_string(),
_ => components.join("/"),
}
} else {
path
};
let asset_response = assets
.get(&Assets::format_key(&path), AssetFetch::Decompress)
.ok_or(crate::Error::AssetNotFound(path))
.and_then(|(read, _)| {
read
.bytes()
.collect::<Result<Vec<u8>, _>>()
.map_err(Into::into)
});
match asset_response {
Ok(asset) => Ok(asset),
Err(e) => {
#[cfg(debug_assertions)]
eprintln!("{:?}", e); // TODO log::error!
Err(e)
}
}
}),
};
(
webview_builder,
vec![tauri_invoke_handler],
Some(custom_protocol),
)
} else {
(webview.builder.url(webview_url), Vec::new())
(webview.builder.url(webview_url), Vec::new(), None)
};
Ok((webview_builder, callbacks))
Ok((webview_builder, callbacks, custom_protocol))
}
/// Asynchronously executes the given task
@ -406,7 +352,6 @@ async fn on_message<A: ApplicationExt + 'static>(
#[cfg(test)]
mod test {
use crate::{Context, FromTauriContext};
use proptest::prelude::*;
#[derive(FromTauriContext)]
#[config_path = "test/fixture/src-tauri/tauri.conf.json"]
@ -416,33 +361,13 @@ mod test {
fn check_get_url() {
let context = Context::new::<TauriContext>().unwrap();
let res = super::get_url(&context);
#[cfg(embedded_server)]
match res {
Ok(u) => assert!(u.contains("http://")),
_ => panic!("setup content failed"),
}
#[cfg(custom_protocol)]
assert!(res == "tauri://index.html");
#[cfg(dev)]
{
let config = &context.config;
match res {
Ok(u) => assert_eq!(u, config.build.dev_path),
_ => panic!("setup content failed"),
}
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(10000))]
#[cfg(embedded_server)]
#[test]
fn check_server_url(port in (any::<u32>().prop_map(|v| v.to_string()))) {
let p = port.clone();
let context = Context::new::<TauriContext>().unwrap();
let url = super::setup_server_url(port, &context);
assert!(url.contains(&p));
assert_eq!(res, config.build.dev_path);
}
}
}

View File

@ -34,8 +34,6 @@ pub enum Message {
Show,
/// Hides the window.
Hide,
/// Updates the transparency flag.
SetTransparent(bool),
/// Updates the hasDecorations flag.
SetDecorations(bool),
/// Updates the window alwaysOnTop flag.
@ -167,6 +165,14 @@ pub struct Callback<D> {
pub function: Box<dyn FnMut(D, Vec<JsonValue>) + Send>,
}
/// Uses a custom handler to resolve file requests
pub struct CustomProtocol {
/// Name of the protocol
pub name: String,
/// Handler for protocol
pub handler: Box<dyn Fn(&str) -> crate::Result<Vec<u8>> + Send + Sync>,
}
/// Webview dispatcher. A thread-safe handle to the webview API.
pub trait ApplicationDispatcherExt: Clone + Send + Sync + Sized {
/// The webview builder type.
@ -180,6 +186,7 @@ pub trait ApplicationDispatcherExt: Clone + Send + Sync + Sized {
&self,
webview_builder: Self::WebviewBuilder,
callbacks: Vec<Callback<Self>>,
custom_protocol: Option<CustomProtocol>,
) -> crate::Result<Self>;
/// Updates the window resizable flag.
@ -206,9 +213,6 @@ pub trait ApplicationDispatcherExt: Clone + Send + Sync + Sized {
/// Hides the window.
fn hide(&self) -> crate::Result<()>;
/// Updates the transparency flag.
fn set_transparent(&self, resizable: bool) -> crate::Result<()>;
/// Updates the hasDecorations flag.
fn set_decorations(&self, decorations: bool) -> crate::Result<()>;
@ -272,6 +276,7 @@ pub trait ApplicationExt: Sized {
&mut self,
webview_builder: Self::WebviewBuilder,
callbacks: Vec<Callback<Self::Dispatcher>>,
custom_protocol: Option<CustomProtocol>,
) -> crate::Result<Self::Dispatcher>;
/// Run the application.

View File

@ -1,5 +1,5 @@
use super::{
ApplicationDispatcherExt, ApplicationExt, Callback, Icon, WebviewBuilderExt,
ApplicationDispatcherExt, ApplicationExt, Callback, CustomProtocol, Icon, WebviewBuilderExt,
WebviewBuilderExtPrivate, WindowConfig,
};
@ -190,6 +190,7 @@ impl ApplicationDispatcherExt for WryDispatcher {
&self,
attributes: Self::WebviewBuilder,
callbacks: Vec<Callback<Self>>,
custom_protocol: Option<CustomProtocol>,
) -> crate::Result<Self> {
let mut wry_callbacks = Vec::new();
let app_dispatcher = self.1.clone();
@ -212,7 +213,14 @@ impl ApplicationDispatcherExt for WryDispatcher {
.1
.lock()
.unwrap()
.add_window(attributes, Some(wry_callbacks), None)
.add_window_with_configs(
attributes,
Some(wry_callbacks),
custom_protocol.map(|p| wry::CustomProtocol {
name: p.name.clone(),
handler: Box::new(move |a| (*p.handler)(a).map_err(|_| wry::Error::InitScriptError)),
}),
)
.map_err(|_| crate::Error::FailedToSendMessage)?;
Ok(Self(
Arc::new(Mutex::new(window_dispatcher)),
@ -292,15 +300,6 @@ impl ApplicationDispatcherExt for WryDispatcher {
.map_err(|_| crate::Error::FailedToSendMessage)
}
fn set_transparent(&self, transparent: bool) -> crate::Result<()> {
self
.0
.lock()
.unwrap()
.set_transparent(transparent)
.map_err(|_| crate::Error::FailedToSendMessage)
}
fn set_decorations(&self, decorations: bool) -> crate::Result<()> {
self
.0
@ -442,6 +441,7 @@ impl ApplicationExt for WryApplication {
&mut self,
webview_builder: Self::WebviewBuilder,
callbacks: Vec<Callback<Self::Dispatcher>>,
custom_protocol: Option<CustomProtocol>,
) -> crate::Result<Self::Dispatcher> {
let mut wry_callbacks = Vec::new();
let app_dispatcher = Arc::new(Mutex::new(self.inner.application_proxy()));
@ -462,7 +462,14 @@ impl ApplicationExt for WryApplication {
let dispatcher = self
.inner
.add_window(webview_builder.finish()?, Some(wry_callbacks), None)
.add_window_with_configs(
webview_builder.finish()?,
Some(wry_callbacks),
custom_protocol.map(|p| wry::CustomProtocol {
name: p.name.clone(),
handler: Box::new(move |a| (*p.handler)(a).map_err(|_| wry::Error::InitScriptError)),
}),
)
.map_err(|_| crate::Error::CreateWebview)?;
Ok(WryDispatcher(
Arc::new(Mutex::new(dispatcher)),

View File

@ -96,11 +96,6 @@ impl<A: ApplicationDispatcherExt> WebviewDispatcher<A> {
self.dispatcher.hide()
}
/// Sets the window transparent flag.
pub fn set_transparent(&self, transparent: bool) -> crate::Result<()> {
self.dispatcher.set_transparent(transparent)
}
/// Whether the window should have borders and bars.
pub fn set_decorations(&self, decorations: bool) -> crate::Result<()> {
self.dispatcher.set_decorations(decorations)
@ -247,13 +242,14 @@ impl<A: ApplicationExt + 'static> WebviewManager<A> {
.lock()
.await
.push(label.to_string());
let (webview_builder, callbacks) = self.application.init_webview(webview).await?;
let (webview_builder, callbacks, custom_protocol) =
self.application.init_webview(webview).await?;
let window_dispatcher = self
.current_webview()
.await?
.dispatcher
.create_webview(webview_builder, callbacks)?;
let window_dispatcher = self.current_webview().await?.dispatcher.create_webview(
webview_builder,
callbacks,
custom_protocol,
)?;
let webview_manager = Self::new(
self.application.clone(),
self.dispatchers.clone(),

View File

@ -36,9 +36,6 @@ pub enum Cmd {
Unminimize,
Show,
Hide,
SetTransparent {
transparent: bool,
},
SetDecorations {
decorations: bool,
},
@ -130,7 +127,6 @@ impl Cmd {
Self::Unminimize => current_webview.unminimize()?,
Self::Show => current_webview.show()?,
Self::Hide => current_webview.hide()?,
Self::SetTransparent { transparent } => current_webview.set_transparent(transparent)?,
Self::SetDecorations { decorations } => current_webview.set_decorations(decorations)?,
Self::SetAlwaysOnTop { always_on_top } => {
current_webview.set_always_on_top(always_on_top)?

View File

@ -16,9 +16,6 @@ pub enum Error {
/// Embedded asset not found.
#[error("asset not found: {0}")]
AssetNotFound(String),
/// Embedded server port not available.
#[error("failed to setup server, port {0} not available")]
PortNotAvailable(String),
/// Failed to serialize/deserialize.
#[error("JSON error: {0}")]
Json(serde_json::Error),

View File

@ -6,9 +6,6 @@
//! Tauri uses (and contributes to) the MIT licensed project that you can find at [webview](https://github.com/webview/webview).
#![warn(missing_docs, rust_2018_idioms)]
/// The embedded server helpers.
#[cfg(embedded_server)]
pub mod server;
/// The Tauri-specific settings for your app e.g. notification permission status.
pub mod settings;

View File

@ -1,39 +0,0 @@
use std::io::Read;
use tauri_api::assets::{AssetFetch, Assets};
use tiny_http::{Response, StatusCode};
/// Returns the HTTP response of the given asset path.
pub fn asset_response(path: &str, assets: &'static Assets) -> Response<impl Read> {
let (asset, _) = assets
.get(path, AssetFetch::Compress)
.unwrap_or_else(|| panic!("Could not read asset {}", path));
let mut headers = Vec::new();
// Content-Encoding
const CONTENT_ENCODING: &str = "Content-Encoding: gzip";
let content_encoding = CONTENT_ENCODING
.parse()
.unwrap_or_else(|_| panic!("Could not add {} header", CONTENT_ENCODING));
headers.push(content_encoding);
// Content-Type
let mime = if path.ends_with(".svg") {
"Content-Type: image/svg+xml"
} else if path.ends_with(".css") {
"Content-Type: text/css"
} else if path.ends_with(".html") {
"Content-Type: text/html"
} else if path.ends_with(".js") {
"Content-Type: text/javascript"
} else {
"Content-Type: application/octet-stream"
};
let content_type = mime
.parse()
.unwrap_or_else(|_| panic!("Could not add {} header", mime));
headers.push(content_type);
Response::new(StatusCode(200), headers, asset, None, None)
}