Skip to content

Commit

Permalink
Make JNI code more robust
Browse files Browse the repository at this point in the history
  • Loading branch information
paulrouget committed Oct 5, 2018
1 parent 021a24d commit e0ce73a
Show file tree
Hide file tree
Showing 7 changed files with 248 additions and 150 deletions.
26 changes: 15 additions & 11 deletions ports/libsimpleservo/src/api.rs
Expand Up @@ -28,6 +28,14 @@ thread_local! {
/// and that perform_updates need to be called
pub use servo::embedder_traits::EventLoopWaker;

pub struct InitOptions {
pub args: Option<String>,
pub url: Option<String>,
pub width: u32,
pub height: u32,
pub density: f32,
}

/// Delegate resource file reading to the embedder.
pub trait ReadFileTrait {
fn readfile(&self, file: &str) -> Vec<u8>;
Expand Down Expand Up @@ -93,28 +101,24 @@ pub fn servo_version() -> String {
/// Initialize Servo. At that point, we need a valid GL context.
/// In the future, this will be done in multiple steps.
pub fn init(
init_opts: InitOptions,
gl: Rc<gl::Gl>,
argsline: String,
embedder_url: Option<String>,
waker: Box<EventLoopWaker>,
readfile: Box<ReadFileTrait + Send + Sync>,
callbacks: Box<HostTrait>,
width: u32,
height: u32,
density: f32,
) -> Result<(), &'static str> {
resources::set(Box::new(ResourceReader(readfile)));

if !argsline.is_empty() {
let mut args: Vec<String> = serde_json::from_str(&argsline).map_err(|_| {
if let Some(args) = init_opts.args {
let mut args: Vec<String> = serde_json::from_str(&args).map_err(|_| {
"Invalid arguments. Servo arguments must be formatted as a JSON array"
})?;
// opts::from_cmdline_args expects the first argument to be the binary name.
args.insert(0, "servo".to_string());
opts::from_cmdline_args(&args);
}

let embedder_url = embedder_url.as_ref().and_then(|s| {
let embedder_url = init_opts.url.as_ref().and_then(|s| {
ServoUrl::parse(s).ok()
});
let cmdline_url = opts::get().url.clone();
Expand All @@ -135,9 +139,9 @@ pub fn init(
let callbacks = Rc::new(ServoCallbacks {
gl: gl.clone(),
host_callbacks: callbacks,
width: Cell::new(width),
height: Cell::new(height),
density,
width: Cell::new(init_opts.width),
height: Cell::new(init_opts.height),
density: init_opts.density,
waker,
});

Expand Down
68 changes: 32 additions & 36 deletions ports/libsimpleservo/src/capi.rs
Expand Up @@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use api::{self, EventLoopWaker, ServoGlue, SERVO, HostTrait, ReadFileTrait};
use api::{self, EventLoopWaker, InitOptions, ServoGlue, SERVO, HostTrait, ReadFileTrait};
use gl_glue;
use servo::gl;
use std::ffi::{CStr, CString};
Expand Down Expand Up @@ -37,6 +37,16 @@ pub struct CHostCallbacks {
pub on_animating_changed: extern fn(animating: bool),
}

/// Servo options
#[repr(C)]
pub struct CInitOptions {
pub args: *const c_char,
pub url: *const c_char,
pub width: u32,
pub height: u32,
pub density: f32,
}

/// The returned string is not freed. This will leak.
#[no_mangle]
pub extern "C" fn servo_version() -> *const c_char {
Expand All @@ -48,66 +58,52 @@ pub extern "C" fn servo_version() -> *const c_char {
}

fn init(
opts: CInitOptions,
gl: Rc<gl::Gl>,
args: *const c_char,
url: *const c_char,
wakeup: extern fn(),
readfile: extern fn(*const c_char) -> *const c_char,
callbacks: CHostCallbacks,
width: u32,
height: u32,
density: f32) {
let args = unsafe { CStr::from_ptr(args) };
let args = args.to_str().expect("Can't read string").to_string();
callbacks: CHostCallbacks) {
let args = unsafe { CStr::from_ptr(opts.args) };
let args = args.to_str().map(|s| s.to_string()).ok();

let url = unsafe { CStr::from_ptr(url) };
let url = url.to_str().map(|s| s.to_string());
let url = unsafe { CStr::from_ptr(opts.url) };
let url = url.to_str().map(|s| s.to_string()).ok();

let opts = InitOptions {
args,
url,
width: opts.width,
height: opts.height,
density: opts.density,
};

let wakeup = Box::new(WakeupCallback::new(wakeup));
let readfile = Box::new(ReadFileCallback::new(readfile));
let callbacks = Box::new(HostCallbacks::new(callbacks));

api::init(
gl,
args,
url.ok(),
wakeup,
readfile,
callbacks,
width,
height,
density,
).unwrap();
api::init(opts, gl, wakeup, readfile, callbacks).unwrap();
}

#[cfg(target_os = "windows")]
#[no_mangle]
pub extern "C" fn init_with_egl(
args: *const c_char,
url: *const c_char,
opts: CInitOptions,
wakeup: extern fn(),
readfile: extern fn(*const c_char) -> *const c_char,
callbacks: CHostCallbacks,
width: u32,
height: u32,
density: f32) {
callbacks: CHostCallbacks) {
let gl = gl_glue::egl::init().unwrap();
init(gl, args, url, wakeup, readfile, callbacks, width, height, density)
init(opts, gl, wakeup, readfile, callbacks)
}

#[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))]
#[no_mangle]
pub extern "C" fn init_with_gl(
args: *const c_char,
url: *const c_char,
opts: CInitOptions,
wakeup: extern fn(),
readfile: extern fn(*const c_char) -> *const c_char,
callbacks: CHostCallbacks,
width: u32,
height: u32,
density: f32) {
callbacks: CHostCallbacks) {
let gl = gl_glue::gl::init().unwrap();
init(gl, args, url, wakeup, readfile, callbacks, width, height, density)
init(opts, gl, wakeup, readfile, callbacks)
}

#[no_mangle]
Expand Down

0 comments on commit e0ce73a

Please sign in to comment.