Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Campfire serve and open-browser #638

Merged
merged 12 commits into from
Aug 9, 2023
2 changes: 1 addition & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ rustflags = ["--cfg=web_sys_unstable_apis"]

[alias]
campfire = "run --package campfire --"
campfire-ndf = "run --package campfire --no-default-features --"
campfire-slim = "run --package campfire --no-default-features --"
cf = "run --package campfire --"
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ jobs:
sudo apt install -y libxcb-xfixes0-dev mesa-vulkan-drivers

- name: Run golden image tests
run: cargo campfire-ndf golden-images --ambient-path=./ambient check
run: cargo campfire-slim golden-images --ambient-path=./ambient check
- uses: actions/upload-artifact@v3
if: always()
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
- run: rustup target add --toolchain stable wasm32-wasi
- name: Release all packages required for API
run: cargo run -p campfire-ndf release publish --execute
run: cargo run -p campfire-slim release publish --execute

publish-release:
needs: [create-release, build-app, publish-api]
Expand Down
116 changes: 116 additions & 0 deletions Cargo.lock

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

10 changes: 9 additions & 1 deletion campfire/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,20 @@ num_cpus = "1.15.0"
home = "0.5"
tracing = "0.1"
cfg-if = "1.0"
notify = { version = "6.0", optional = true }
flume = { version = "0.10", optional = true }
walkdir = { version = "2.3.2", optional = true }
notify-debouncer-full = { version = "0.2", optional = true, default-features = false }

[target.'cfg(target_os="windows")'.dependencies]
openssl = { version = "0.10", features = ["vendored"], optional = true }

[target.'cfg(target_os="linux")'.dependencies]
nix = "0.26"

[target.'cfg(not(target_os="windows"))'.dependencies]
openssl = { version = "0.10", optional = true }

[features]
default = ["openssl"]
default = ["openssl", "serve"]
serve = ["dep:notify", "dep:flume", "walkdir", "notify-debouncer-full"]
95 changes: 57 additions & 38 deletions campfire/src/web/browser.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use anyhow::Context;
use openssl::hash::MessageDigest;
use tokio::process::Command;
use std::process::Command;

pub async fn open() -> anyhow::Result<()> {
let cert_file = tokio::fs::read("./localhost.crt")
Expand All @@ -20,50 +20,44 @@ pub async fn open() -> anyhow::Result<()> {

eprintln!("Got SPKI: {:?}", &spki);

open_browser(&spki, "http://localhost:5173").await?;
spawn(&spki, "http://localhost:5173")?;

Ok(())
}

#[allow(unused_variables)]
async fn open_browser(spki: &str, url: &str) -> anyhow::Result<()> {
cfg_if::cfg_if! {
if #[cfg(target_os = "macos")] {
let mut command = Command::new("open");
command
// Feeding a url to chrome here makes `--args spki` not be fed to chrome
.args(["-a", "Google Chrome", "--args"])
.arg(format!("--ignore-certificate-errors-spki-list={spki}"));

}
else if #[cfg(target_os = "linux")] {
let _spki = spki;
let _url = url;
let mut command = Command::new("google-chrome");
command
.args(["-a", "Google Chrome", url, "--args"])
.arg(format!("--ignore-certificate-errors-spki-list={spki}"))
.spawn()
.context("Failed to spawn browser")?;

anyhow::bail!("Launching the browser for linux is not supported. This is because cargo will cleanup the browser background process when campfire terminates")
}
else {
let mut command = Command::new("google-chrome");
command
.arg(format!("--ignore-certificate-errors-spki-list={spki}"))
.spawn()
.context("Failed to spawn browser")?;

anyhow::bail!("Launching the browser for windows is not yet supported.")
}
}
#[cfg(target_os = "linux")]
fn detach_process(child: &mut Command) -> &mut Command {
use std::os::unix::process::CommandExt;
// Safety
// Does not access any memory from *this* process.
unsafe {
child.pre_exec(|| {
// Detach the child by moving it to a new process group
if let Err(e) = nix::unistd::setsid() {
// Safety: e is repr(i32) and it thus safe to format
eprintln!("Failed to detach child {e}")
};

Ok(())
})
};

// Prevent output from leaking into the parent terminal
child
.stdin(std::process::Stdio::null())
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
}

let status = command
#[cfg(target_os = "macos")]
fn spawn(spki: &str, _url: &str) -> anyhow::Result<()> {
let status = std::process::Command::new("open")
// Feeding a url to chrome here makes `--args spki` not be fed to chrome
.args(["-a", "Google Chrome", "--args"])
.arg(format!("--ignore-certificate-errors-spki-list={spki}"))
.spawn()
.context("Failed to spawn browser")?
.context("Failed to open Google Chrome")?
.wait()
.await
.context("Failed to wait for launch command to exit")?;

if !status.success() {
Expand All @@ -72,3 +66,28 @@ async fn open_browser(spki: &str, url: &str) -> anyhow::Result<()> {

Ok(())
}

#[cfg(target_os = "linux")]
fn spawn(spki: &str, url: &str) -> anyhow::Result<()> {
let status = detach_process(
std::process::Command::new("google-chrome")
.arg(url)
// Feeding a url to chrome here makes `--args spki` not be fed to chrome
.arg(format!("--ignore-certificate-errors-spki-list={spki}")),
)
.spawn()
.context("Failed to open Google Chrome")?
.wait()
.context("Failed to wait for launch command to exit")?;

if !status.success() {
anyhow::bail!("Failed to launch browser. Process exited with {status:?}");
}

Ok(())
}

#[cfg(target_os = "windows")]
fn spawn(_spki: &str, _url: &str) -> anyhow::Result<()> {
anyhow::bail!("Launching the browser for windows is not yet supported.")
}
Loading
Loading