Skip to content

Commit

Permalink
Breaking change: modify publicly exposed signature to bring consistency.
Browse files Browse the repository at this point in the history
Fixes #42
  • Loading branch information
amodm committed Feb 16, 2022
1 parent 4a27ee0 commit d8fd001
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 98 deletions.
4 changes: 2 additions & 2 deletions src/android.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::process::ExitStatus;

/// Deal with opening of browsers on Android
#[inline]
pub fn open_browser_internal(_: Browser, url: &str) -> Result<ExitStatus> {
pub fn open_browser_internal(_: Browser, url: &str) -> Result<()> {
// Create a VM for executing Java calls
let native_activity = ndk_glue::native_activity();
let vm_ptr = native_activity.vm();
Expand Down Expand Up @@ -61,5 +61,5 @@ pub fn open_browser_internal(_: Browser, url: &str) -> Result<ExitStatus> {
)
.map_err(|_| -> Error { Error::new(ErrorKind::Other, "Failed to start activity") })?;

Ok(ExitStatus::from_raw(0))
Ok(())
}
24 changes: 24 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::{Error, ErrorKind, Result};
use std::process::ExitStatus;

/// Analyses return code from a command ExitStatus to create the right
/// Result<()>
pub fn from_status(res: Result<ExitStatus>) -> Result<()> {
match res {
Ok(status) => {
if let Some(code) = status.code() {
if code == 0 {
Ok(())
} else {
Err(Error::new(
ErrorKind::Other,
format!("return code {}", code),
))
}
} else {
Err(Error::new(ErrorKind::Other, "interrupted by signal"))
}
}
Err(err) => Err(err),
}
}
112 changes: 26 additions & 86 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,47 +26,40 @@
//! }
//! ```
#[cfg(windows)]
mod windows;
#[cfg(windows)]
use windows::*;
#[cfg_attr(target_os = "macos", path = "macos.rs")]
#[cfg_attr(target_os = "android", path = "android.rs")]
#[cfg_attr(target_arch = "wasm32", path = "wasm.rs")]
#[cfg_attr(windows, path = "windows.rs")]
#[cfg_attr(
any(
target_os = "linux",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "haiku"
),
path = "unix.rs"
)]
mod os;

#[cfg(target_os = "android")]
mod android;
#[cfg(target_os = "android")]
use android::*;

#[cfg(target_os = "macos")]
mod macos;
#[cfg(target_os = "macos")]
use macos::*;

#[cfg(any(
target_os = "linux",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "haiku"
))]
mod unix;
#[cfg(any(
#[cfg(not(any(
target_os = "android",
target_os = "windows",
target_os = "macos",
target_os = "linux",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "haiku"
))]
use unix::*;
target_os = "haiku",
target_arch = "wasm32"
)))]
compile_error!("Only Windows, Mac OS, Linux, *BSD and Haiku and Wasm32 are currently supported");

use std::default::Default;
use std::io::{Error, ErrorKind, Result};
use std::process::{ExitStatus, Output};
use std::str::FromStr;
use std::{error, fmt};

#[cfg(target_arch = "wasm32")]
use web_sys::Window;

#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
/// Browser types available
pub enum Browser {
Expand Down Expand Up @@ -165,24 +158,8 @@ impl FromStr for Browser {
/// // ...
/// }
/// ```
#[cfg(not(target_arch = "wasm32"))]
pub fn open(url: &str) -> Result<Output> {
open_browser(Browser::Default, url)
}

#[cfg(target_arch = "wasm32")]
pub fn open(url: &str) -> Result<()> {
let window = web_sys::window();
match window {
Some(w) => {
w.open_with_url(url);
Ok(())
}
None => Err(std::io::Error::new(
ErrorKind::Other,
"should have a window in this context",
)),
}
open_browser(Browser::Default, url)
}

/// Opens the specified URL on the specific browser (if available) requested. Return semantics are
Expand All @@ -196,41 +173,10 @@ pub fn open(url: &str) -> Result<()> {
/// // ...
/// }
/// ```
#[cfg(not(target_arch = "wasm32"))]
pub fn open_browser(browser: Browser, url: &str) -> Result<Output> {
open_browser_internal(browser, url).and_then(|status| {
if let Some(code) = status.code() {
if code == 0 {
Ok(Output {
status: ExitStatus::from_raw(0),
stdout: vec![],
stderr: vec![],
})
} else {
Err(Error::new(
ErrorKind::Other,
format!("return code {}", code),
))
}
} else {
Err(Error::new(ErrorKind::Other, "interrupted by signal"))
}
})
pub fn open_browser(browser: Browser, url: &str) -> Result<()> {
os::open_browser_internal(browser, url)
}

#[cfg(not(any(
target_os = "android",
target_os = "windows",
target_os = "macos",
target_os = "linux",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "haiku",
target_arch = "wasm32"
)))]
compile_error!("Only Windows, Mac OS, Linux, *BSD and Haiku and Wasm32 are currently supported");

#[test]
#[ignore]
fn test_open_firefox() {
Expand All @@ -243,12 +189,6 @@ fn test_open_chrome() {
assert!(open_browser(Browser::Chrome, "http://github.com").is_ok());
}

#[test]
#[cfg(target_arch = "wasm32")]
fn test_open_default_wasm() {
assert!(open("http://github.com").is_ok());
}

#[test]
#[ignore]
fn test_open_safari() {
Expand Down
12 changes: 7 additions & 5 deletions src/macos.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use crate::{Browser, Error, ErrorKind, Result};
pub use std::os::unix::process::ExitStatusExt;
use std::process::{Command, ExitStatus};
use std::process::Command;

mod common;
use common::from_status;

/// Deal with opening of browsers on Mac OS X, using `open` command
#[inline]
pub fn open_browser_internal(browser: Browser, url: &str) -> Result<ExitStatus> {
pub fn open_browser_internal(browser: Browser, url: &str) -> Result<()> {
let mut cmd = Command::new("open");
match browser {
Browser::Default => cmd.arg(url).status(),
Browser::Default => from_status(cmd.arg(url).status()),
_ => {
let app: Option<&str> = match browser {
Browser::Firefox => Some("Firefox"),
Expand All @@ -18,7 +20,7 @@ pub fn open_browser_internal(browser: Browser, url: &str) -> Result<ExitStatus>
_ => None,
};
match app {
Some(name) => cmd.arg("-a").arg(name).arg(url).status(),
Some(name) => from_status(cmd.arg("-a").arg(name).arg(url).status()),
None => Err(Error::new(
ErrorKind::NotFound,
format!("Unsupported browser {:?}", browser),
Expand Down
11 changes: 9 additions & 2 deletions src/unix.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
use crate::{Browser, Error, ErrorKind, Result};
pub use std::os::unix::process::ExitStatusExt;
use std::os::unix::process::ExitStatusExt;
use std::process::{Command, ExitStatus};

mod common;
use common::from_status;

/// Deal with opening of browsers on Linux and *BSD - currently supports only the default browser
///
/// The mechanism of opening the default browser is as follows:
/// 1. Attempt to use $BROWSER env var if available
/// 2. Attempt to open the url via xdg-open, gvfs-open, gnome-open, open, respectively, whichever works
/// first
#[inline]
pub fn open_browser_internal(browser: Browser, url: &str) -> Result<ExitStatus> {
pub fn open_browser_internal(browser: Browser, url: &str) -> Result<()> {
from_status(open_browser_unix(browser, url))
}

fn open_browser_unix(browser: Browser, url: &str) -> Result<ExitStatus> {
match browser {
Browser::Default => open_on_unix_using_browser_env(url)
.or_else(|_| -> Result<ExitStatus> { Command::new("xdg-open").arg(url).status() })
Expand Down
42 changes: 42 additions & 0 deletions src/wasm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use crate::{Browser, ErrorKind, Result};

/// Deal with opening a URL in wasm32. This implementation ignores the browser attribute
/// and always opens URLs in the same browser where wasm32 vm is running.
#[inline]
pub fn open_browser_internal(_: Browser, url: &str) -> Result<()> {
// we can override the target by the env var WEBBROWSER_WASM_TARGET at compile time
let configured_target = option_env!("WEBBROWSER_WASM_TARGET");
let window = web_sys::window();
match window {
Some(w) => {
let target = configured_target.unwrap_or_else(|| "_blank");
wasm_console_log(&format!("target for url {} detected as {}", url, target));

match w.open_with_url_and_target(url, target) {
Ok(x) => match x {
Some(y) => Ok(()),
None => {
const err_msg: &'static str =
"popup blocked? window detected, but open_url failed";
wasm_console_log(&err_msg);
Err(std::io::Error::new(ErrorKind::Other, err_msg))
}
},
Err(_) => {
wasm_console_log("window error while opening url");
Err(std::io::Error::new(ErrorKind::Other, "error opening url"))
}
}
}
None => Err(std::io::Error::new(
ErrorKind::Other,
"should have a window in this context",
)),
}
}

/// Print to browser console
fn wasm_console_log(msg: &str) {
#[cfg(debug_assertions)]
web_sys::console::log_1(&format!("[webbrowser] {}", &msg).into());
}
5 changes: 2 additions & 3 deletions src/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ extern crate winapi;

use crate::{Browser, Error, ErrorKind, Result};
pub use std::os::windows::process::ExitStatusExt;
use std::process::ExitStatus;
use std::ptr;
use widestring::U16CString;

/// Deal with opening of browsers on Windows, using [`ShellExecuteW`](
/// https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-shellexecutew)
/// fucntion.
#[inline]
pub fn open_browser_internal(browser: Browser, url: &str) -> Result<ExitStatus> {
pub fn open_browser_internal(browser: Browser, url: &str) -> Result<()> {
use winapi::shared::winerror::SUCCEEDED;
use winapi::um::combaseapi::{CoInitializeEx, CoUninitialize};
use winapi::um::objbase::{COINIT_APARTMENTTHREADED, COINIT_DISABLE_OLE1DDE};
Expand Down Expand Up @@ -41,7 +40,7 @@ pub fn open_browser_internal(browser: Browser, url: &str) -> Result<ExitStatus>
code
};
if code > 32 {
Ok(ExitStatus::from_raw(0))
Ok(())
} else {
Err(Error::last_os_error())
}
Expand Down

0 comments on commit d8fd001

Please sign in to comment.