#![allow(unsafe_code, trivial_numeric_casts)]
use app::App;
use errors::*;
use libc;
use std::process::Command;
#[repr(C)]
struct __CFString(libc::c_void);
type CFStringRef = *const __CFString;
type CFAllocatorRef = *const libc::c_void;
type CFIndex = libc::c_long;
type CFStringEncoding = u32;
#[link(name = "CoreFoundation", kind = "framework")]
extern "C" {
static kCFAllocatorDefault: CFAllocatorRef;
static kCFAllocatorNull: CFAllocatorRef;
fn CFStringCreateWithBytes(
alloc: CFAllocatorRef,
bytes: *const u8,
numBytes: CFIndex,
encoding: CFStringEncoding,
isExternalRepresentation: u8,
contentsDeallocator: CFAllocatorRef,
) -> CFStringRef;
}
#[link(name = "CoreServices", kind = "framework")]
extern "C" {
fn LSSetDefaultHandlerForURLScheme(scheme: CFStringRef, bundle_id: CFStringRef);
}
fn convert_to_cfstring(content: &str) -> CFStringRef {
unsafe {
CFStringCreateWithBytes(
kCFAllocatorDefault,
content.as_ptr(),
content.len() as CFIndex,
0x0800_0100 as CFStringEncoding,
false as u8,
kCFAllocatorNull,
)
}
}
pub fn open(uri: String) -> Result<()> {
let output = Command::new("open").arg(uri).output().chain_err(
|| "Could not execute open",
)?;
if output.status.success() {
Ok(())
} else {
Err(
"Executing open failed. See terminal output for errors.".into(),
)
}
}
pub fn install(app: &App, schemes: &[String]) -> Result<()> {
let bundle_id = convert_to_cfstring(app.bundle_id.as_str());
for scheme in schemes {
unsafe {
LSSetDefaultHandlerForURLScheme(convert_to_cfstring(scheme.as_str()), bundle_id);
}
}
Ok(())
}