From 37da1255c445559346077d57568e3423c014ec4d Mon Sep 17 00:00:00 2001 From: Davide Baldo Date: Fri, 18 Aug 2023 12:07:17 +0200 Subject: [PATCH 1/2] feat(rust): added ockam:// scheme association in app for linux and mac --- Cargo.lock | 11 +-- Cargo.toml | 6 ++ .../rust/ockam/ockam_app/src/app/events.rs | 1 + .../rust/ockam/ockam_app/src/app/process.rs | 7 ++ .../rust/ockam/ockam_app/src/lib.rs | 30 ++++++++ .../ockam/ockam_app/src/linux_url_plugin.rs | 69 +++++++++++++++++++ .../rust/ockam/ockam_app/tauri.conf.json | 6 ++ 7 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 implementations/rust/ockam/ockam_app/src/linux_url_plugin.rs diff --git a/Cargo.lock b/Cargo.lock index 7da49c68141..041799ff919 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7150,8 +7150,7 @@ dependencies = [ [[package]] name = "tauri-build" version = "2.0.0-alpha.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc47d3c84f4aeac397cd956267f3b8060c5a2dba78288a5ccf9a8b7a8c1e7025" +source = "git+https://github.com/build-trust/tauri.git?branch=add-url-scheme#7856354fe16197b270dfa36bc095fec33bec4cff" dependencies = [ "anyhow", "cargo_toml", @@ -7317,8 +7316,7 @@ dependencies = [ [[package]] name = "tauri-utils" version = "2.0.0-alpha.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06bcd7c6f67fd6371dcc22da7d7f26ec12c4eae26ad7bc54943bb9f35b5db302" +source = "git+https://github.com/build-trust/tauri.git?branch=add-url-scheme#7856354fe16197b270dfa36bc095fec33bec4cff" dependencies = [ "brotli", "ctor", @@ -8917,3 +8915,8 @@ dependencies = [ "quote", "syn 1.0.109", ] + +[[patch.unused]] +name = "tauri" +version = "2.0.0-alpha.12" +source = "git+https://github.com/build-trust/tauri.git?branch=add-url-scheme#7856354fe16197b270dfa36bc095fec33bec4cff" diff --git a/Cargo.toml b/Cargo.toml index 3867805ce16..7a9296c6b55 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,3 +49,9 @@ inherits = "test" opt-level = 2 [profile.dev.package.adler] opt-level = 1 + +[patch.crates-io] +# temporary fork for url scheme - https://github.com/build-trust/ockam/issues/5667 +tauri = { git = "https://github.com/build-trust/tauri.git", branch = "add-url-scheme" } +tauri-build = { git = "https://github.com/build-trust/tauri.git", branch = "add-url-scheme" } +tauri-utils = { git = "https://github.com/build-trust/tauri.git", branch = "add-url-scheme" } diff --git a/implementations/rust/ockam/ockam_app/src/app/events.rs b/implementations/rust/ockam/ockam_app/src/app/events.rs index 7451af2bb87..e9efea520fd 100644 --- a/implementations/rust/ockam/ockam_app/src/app/events.rs +++ b/implementations/rust/ockam/ockam_app/src/app/events.rs @@ -1,6 +1,7 @@ use tauri::{AppHandle, Manager, Runtime}; pub const SYSTEM_TRAY_ON_UPDATE: &str = "app/system_tray/on_update"; +pub const URL_OPEN: &str = "app/url/open"; #[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)] pub struct SystemTrayOnUpdatePayload { diff --git a/implementations/rust/ockam/ockam_app/src/app/process.rs b/implementations/rust/ockam/ockam_app/src/app/process.rs index 974c030c1c3..fe19e6facc6 100644 --- a/implementations/rust/ockam/ockam_app/src/app/process.rs +++ b/implementations/rust/ockam/ockam_app/src/app/process.rs @@ -4,6 +4,13 @@ use tauri::{AppHandle, RunEvent, Runtime}; /// This is the function dispatching application events pub fn process_application_event(app: &AppHandle, event: RunEvent) { match event { + #[cfg(any(target_os = "macos", target_os = "ios"))] + RunEvent::Opened { urls } => { + urls.into_iter().for_each(|url| { + use tauri::Manager; + app.trigger_global(crate::app::events::URL_OPEN, Some(url.into())); + }); + } RunEvent::ExitRequested { api, .. } => { api.prevent_exit(); } diff --git a/implementations/rust/ockam/ockam_app/src/lib.rs b/implementations/rust/ockam/ockam_app/src/lib.rs index c2efc938ea4..e9d9352d711 100644 --- a/implementations/rust/ockam/ockam_app/src/lib.rs +++ b/implementations/rust/ockam/ockam_app/src/lib.rs @@ -28,6 +28,8 @@ mod cli; mod enroll; mod error; mod invitations; +#[cfg(target_os = "linux")] +mod linux_url_plugin; mod options; mod platform; mod projects; @@ -44,6 +46,29 @@ pub fn run() { exit(-1) } + //On linux only, to handle ockam:// link argument from args we check if + //the app is already running, send a packet to it via unix socket. + //Using unix socket rather than ockam, to fully separate concerns. + #[cfg(target_os = "linux")] + { + use std::io::Write; + use std::os::unix::net::UnixStream; + + let mut args = std::env::args(); + args.next(); //skip the first argument which is the executable name + let args: Vec = args.collect(); + + //if we can connect to the socket then the app is already running + //if it's not running yet the arguments will be checked upon startup + if !args.is_empty() && args[0].starts_with("ockam:") { + if let Ok(mut stream) = UnixStream::connect(linux_url_plugin::open_url_sock_path()) { + stream.write_all(args[0].as_bytes()).unwrap(); + stream.flush().unwrap(); + return; + } + } + } + // For now, the application only consists of a system tray with several menu items #[allow(unused_mut)] let mut builder = tauri::Builder::default() @@ -61,6 +86,11 @@ pub fn run() { builder = builder.plugin(configure_tauri_plugin_log()); } + #[cfg(target_os = "linux")] + { + builder = builder.plugin(linux_url_plugin::init()); + } + let mut app = builder .build(tauri::generate_context!()) .expect("Error while building the Ockam application"); diff --git a/implementations/rust/ockam/ockam_app/src/linux_url_plugin.rs b/implementations/rust/ockam/ockam_app/src/linux_url_plugin.rs new file mode 100644 index 00000000000..eb27c989de8 --- /dev/null +++ b/implementations/rust/ockam/ockam_app/src/linux_url_plugin.rs @@ -0,0 +1,69 @@ +use std::os::unix::fs::PermissionsExt; +use std::time::Duration; + +use tauri::{ + async_runtime::spawn, + plugin::{Builder, TauriPlugin}, + Manager, Runtime, +}; +use tokio::io::AsyncReadExt; +use tokio::net::UnixListener; +use tokio::time::sleep; +use tracing::{info, warn}; + +pub(crate) fn open_url_sock_path() -> String { + let runtime_directory = std::env::var("XDG_RUNTIME_DIR").unwrap_or("/tmp".to_string()); + format!("{runtime_directory}/ockam-open-url-sock") +} +const ONLY_WRITE_FROM_USER_PERMISSIONS: u32 = 0o200; + +pub(crate) fn init() -> TauriPlugin { + Builder::new("linux-url") + .setup(|app, _api| { + let handle = app.clone(); + spawn(async move { + let sock_path = &open_url_sock_path(); + //bind fails if the file already exists + let _ = std::fs::remove_file(sock_path); + let listener = UnixListener::bind(sock_path) + .unwrap_or_else(|_| panic!("cannot listener on {sock_path}")); + //only allow the current user to write to the socket + std::fs::set_permissions( + sock_path, + std::fs::Permissions::from_mode(ONLY_WRITE_FROM_USER_PERMISSIONS), + ) + .unwrap_or_else(|_| panic!("cannot set permissions on {sock_path}")); + + //wait a bit to let the app start + sleep(Duration::from_millis(250)).await; + + //check if we had an ockam:// argument passed to us + if let Some(url) = std::env::args().nth(1) { + if url.starts_with("ockam:") { + info!("received url: {}", url); + handle.trigger_global(crate::app::events::URL_OPEN, Some(url)); + } else { + warn!("ignored argument: {}", url); + } + } + + while let Ok((mut stream, _)) = listener.accept().await { + let mut buffer = [0; 4096]; + if let Ok(read_bytes) = stream.read(&mut buffer).await { + if let Ok(url) = String::from_utf8(buffer[..read_bytes].to_vec()) { + if url.starts_with("ockam:") { + info!("received url: {}", url); + handle.trigger_global(crate::app::events::URL_OPEN, Some(url)); + } else { + warn!("ignored url: {}", url); + } + } + } + //every connection is used only once + drop(stream); + } + }); + Ok(()) + }) + .build() +} diff --git a/implementations/rust/ockam/ockam_app/tauri.conf.json b/implementations/rust/ockam/ockam_app/tauri.conf.json index 126f3140207..59d1e41112d 100644 --- a/implementations/rust/ockam/ockam_app/tauri.conf.json +++ b/implementations/rust/ockam/ockam_app/tauri.conf.json @@ -23,6 +23,12 @@ "category": "DeveloperTool", "identifier": "io.ockam.app", "publisher": "Ockam", + "schemeAssociations": [ + { + "scheme": ["ockam"], + "role": "Editor" + } + ], "externalBin": [], "icon": [ "icons/32x32.png", From 647fba53b608af9c6372c866c48a49747bc80f3a Mon Sep 17 00:00:00 2001 From: Davide Baldo Date: Fri, 8 Sep 2023 18:01:34 +0200 Subject: [PATCH 2/2] ci: switched tauri-cli repository to ockam's fork, to be reverted once upstream merge the patch --- .github/actions/build_binaries/action.yml | 2 +- tools/docker/builder/Dockerfile | 2 +- tools/nix/parts/tauri.nix | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/actions/build_binaries/action.yml b/.github/actions/build_binaries/action.yml index fcad7110017..436845c1f62 100644 --- a/.github/actions/build_binaries/action.yml +++ b/.github/actions/build_binaries/action.yml @@ -88,7 +88,7 @@ runs: if: inputs.build_app == 'true' run: | set -x - cargo install --locked tauri-cli --version 2.0.0-alpha.10 + cargo install tauri-cli --git https://github.com/build-trust/tauri.git --branch add-url-scheme cd implementations/rust/ockam/ockam_app/ cargo tauri build --target ${{ inputs.target }} diff --git a/tools/docker/builder/Dockerfile b/tools/docker/builder/Dockerfile index 8ffdede72fe..1945a463061 100644 --- a/tools/docker/builder/Dockerfile +++ b/tools/docker/builder/Dockerfile @@ -104,7 +104,7 @@ RUN set -xe; \ cargo install --locked cargo-deny; \ cargo install --locked cargo-nextest; \ cargo install --locked cargo-readme; \ - cargo install --locked tauri-cli --version 2.0.0-alpha.10; \ + cargo install tauri-cli --git https://github.com/build-trust/tauri.git --branch add-url-scheme; \ chmod -R a+w "$RUSTUP_HOME" "$CARGO_HOME"; \ # Setup erlang echo "deb http://deb.debian.org/debian bullseye main" >> /etc/apt/sources.list; \ diff --git a/tools/nix/parts/tauri.nix b/tools/nix/parts/tauri.nix index 6b4ebc9e90c..417c36fbb2d 100644 --- a/tools/nix/parts/tauri.nix +++ b/tools/nix/parts/tauri.nix @@ -15,7 +15,7 @@ pname = "tauri-cli"; # NOTE: Bumping version must always be accompanied by updating the two hashes below # https://github.com/tauri-apps/tauri/releases - version = "2.0.0-alpha.10"; + version = "2.0.0-alpha.11"; in # Need to make changes? # https://nixos.org/manual/nixpkgs/stable/#compiling-rust-applications-with-cargo @@ -23,15 +23,15 @@ inherit pname version; src = pkgs.fetchFromGitHub { - owner = "tauri-apps"; + owner = "build-trust"; repo = "tauri"; - rev = "tauri-v${version}"; - hash = "sha256-WOxl+hgzKmKXQryD5tH7SJ9YvZb9QA4R+YUYnarnhKA="; + rev = "7856354fe16197b270dfa36bc095fec33bec4cff"; + hash = "sha256-UxWT5k3ZTbydy2iW9LXuSLIfQhSafN39g566J0xWDDs="; }; sourceRoot = "source/tooling/cli"; cargoDepsName = pname; - cargoHash = "sha256-MQmEOdQWyRbO+hogGQA2xjB9mezq21FClvscs1oWYLE="; + cargoHash = "sha256-4OKYj9rPB998JQTLi/k8ICBgYL/jcxXJT/4MAAR6wzU="; buildInputs = [pkgs.openssl]