diff --git a/ports/servo/Cargo.toml b/ports/servo/Cargo.toml index aa77bcfe6aa..7c1d5a1b8d3 100644 --- a/ports/servo/Cargo.toml +++ b/ports/servo/Cargo.toml @@ -33,7 +33,7 @@ googlevr = ["libservo/googlevr"] oculusvr = ["libservo/oculusvr"] unstable = ["libservo/unstable"] -[dependencies] +[target.'cfg(not(target_os = "android"))'.dependencies] backtrace = "0.3" bitflags = "1.0" euclid = "0.18" @@ -44,8 +44,6 @@ libservo = {path = "../../components/servo"} log = "0.4" tinyfiledialogs = "3.0" winit = {version = "0.16", features = ["icon_loading"]} - -[target.'cfg(not(target_os = "android"))'.dependencies] sig = "0.1" [target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies] @@ -54,10 +52,6 @@ osmesa-sys = "0.1.2" [target.'cfg(target_os = "linux")'.dependencies] x11 = "2.0.0" -[target.'cfg(target_os = "android")'.dependencies] -android_injected_glue = "0.2" -servo-egl = "0.2" - [target.'cfg(target_os = "windows")'.dependencies] winapi = "0.2" user32-sys = "0.2" diff --git a/ports/servo/browser.rs b/ports/servo/browser.rs index f2a8d5709ac..277d98ba537 100644 --- a/ports/servo/browser.rs +++ b/ports/servo/browser.rs @@ -17,9 +17,7 @@ use servo::servo_url::ServoUrl; use servo::webrender_api::ScrollLocation; use std::mem; use std::rc::Rc; -#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))] use std::thread; -#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))] use tinyfiledialogs::{self, MessageBoxIcon}; pub struct Browser { @@ -100,7 +98,8 @@ impl Browser { String::from("") }; let title = "URL or search query"; - if let Some(input) = get_url_input(title, &url) { + let input = tinyfiledialogs::input_box(title, title, &url); + if let Some(input) = input { if let Some(url) = sanitize_url(&input) { self.event_queue.push(WindowEvent::LoadUrl(id, url)); } @@ -263,7 +262,11 @@ impl Browser { self.window.set_inner_size(size); } EmbedderMsg::Alert(message, sender) => { - display_alert_dialog(message.to_owned()); + if !opts::get().headless { + let _ = thread::Builder::new().name("display alert dialog".to_owned()).spawn(move || { + tinyfiledialogs::message_box_ok("Alert!", &message, MessageBoxIcon::Warning); + }).unwrap().join().expect("Thread spawning failed"); + } if let Err(e) = sender.send(()) { let reason = format!("Failed to send Alert response: {}", e); self.event_queue.push(WindowEvent::SendError(browser_id, reason)); @@ -324,8 +327,7 @@ impl Browser { }; }, EmbedderMsg::SelectFiles(patterns, multiple_files, sender) => { - let res = match (opts::get().headless, - platform_get_selected_files(patterns, multiple_files)) { + let res = match (opts::get().headless, get_selected_files(patterns, multiple_files)) { (true, _) | (false, None) => sender.send(None), (false, Some(files)) => sender.send(Some(files)) }; @@ -346,31 +348,6 @@ impl Browser { } -#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))] -fn display_alert_dialog(message: String) { - if !opts::get().headless { - let _ = thread::Builder::new().name("display alert dialog".to_owned()).spawn(move || { - tinyfiledialogs::message_box_ok("Alert!", &message, MessageBoxIcon::Warning); - }).unwrap().join().expect("Thread spawning failed"); - } -} - -#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))] -fn display_alert_dialog(_message: String) { - // tinyfiledialogs not supported on Android -} - -#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))] -fn get_url_input(_title: &str, _url: &str) -> Option { - // tinyfiledialogs not supported on Android - None -} - -#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))] -fn get_url_input(title: &str, url: &str) -> Option { - tinyfiledialogs::input_box(title, title, url) -} - #[cfg(target_os = "linux")] fn platform_get_selected_devices(devices: Vec) -> Option { let picker_name = "Choose a device"; @@ -403,10 +380,7 @@ fn platform_get_selected_devices(devices: Vec) -> Option { None } -#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))] -fn platform_get_selected_files(patterns: Vec, - multiple_files: bool) - -> Option> { +fn get_selected_files(patterns: Vec, multiple_files: bool) -> Option> { let picker_name = if multiple_files { "Pick files" } else { "Pick a file" }; thread::Builder::new().name(picker_name.to_owned()).spawn(move || { let mut filters = vec![]; @@ -426,14 +400,6 @@ fn platform_get_selected_files(patterns: Vec, }).unwrap().join().expect("Thread spawning failed") } -#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))] -fn platform_get_selected_files(_patterns: Vec, - _multiple_files: bool) - -> Option> { - warn!("File picker not implemented"); - None -} - fn sanitize_url(request: &str) -> Option { let request = request.trim(); ServoUrl::parse(&request).ok() diff --git a/ports/servo/build.rs b/ports/servo/build.rs index 378f5e8b4c5..f7e7f49c919 100644 --- a/ports/servo/build.rs +++ b/ports/servo/build.rs @@ -5,18 +5,7 @@ #[cfg(windows)] extern crate winres; -use std::env; -use std::path::Path; -use std::process; -use std::process::{Command, Stdio}; - fn main() { - // build.rs is not platform-specific, so we have to check the target here. - let target = env::var("TARGET").unwrap(); - if target.contains("android") { - android_main() - } - #[cfg(windows)] { let mut res = winres::WindowsResource::new(); @@ -25,89 +14,3 @@ fn main() { res.compile().unwrap(); } } - -fn android_main() { - // Get the NDK path from NDK_HOME env. - let ndk_path = env::var_os("ANDROID_NDK").expect("Please set the ANDROID_NDK environment variable"); - let ndk_path = Path::new(&ndk_path); - - // Build up the path to the NDK compilers - // Options for host are: "linux-x86_64" "linux-x86" "darwin-x86_64" "darwin-x86" - // per: https://android.googlesource.com/platform/ndk/+/ics-mr0/docs/STANDALONE-TOOLCHAIN.html - - let host = env::var("HOST").unwrap(); - let google_host = match host.as_ref() { - "i686-unknown-linux-gnu" => "linux-x86", - "x86_64-apple-darwin" => "darwin-x86_64", - "x86_64-unknown-linux-gnu" => "linux-x86_64", - _ => panic!("Unknown support android cross-compile host: {}", host) - }; - - let target = env::var("TARGET").unwrap(); - let arch = if target.contains("arm") { - "arch-arm" - } else if target.contains("aarch64") { - "arch-arm64" - } else if target.contains("x86") || target.contains("i686") { - "arch-x86" - } else if target.contains("mips") { - "arch-mips" - } else { - panic!("Invalid target architecture {}", target); - }; - - let platform = if target.contains("aarch64") { - "android-21" - } else { - "android-18" - }; - - let (toolchain, prefix) = if target.contains("armv7") { - let toolchain = "arm-linux-androideabi"; - (toolchain.into(), toolchain.into()) - } else if target.contains("i686") { - ("x86".into(), target) - } else { - (target.clone(), target) - }; - - let toolchain_path = ndk_path.join("toolchains").join(format!("{}-4.9", toolchain)).join("prebuilt"). - join(google_host); - println!("toolchain path is: {}", toolchain_path.to_str().unwrap()); - - // Get the output directory. - let out_dir = env::var("OUT_DIR").expect("Cargo should have set the OUT_DIR environment variable"); - let directory = Path::new(&out_dir); - - // compiling android_native_app_glue.c - if Command::new(toolchain_path.join("bin").join(format!("{}-gcc", prefix))) - .arg(ndk_path.join("sources").join("android").join("native_app_glue").join("android_native_app_glue.c")) - .arg("-c") - .arg("-o").arg(directory.join("android_native_app_glue.o")) - .arg("--sysroot").arg(ndk_path.join("platforms").join(platform).join(arch)) - .stdout(Stdio::inherit()) - .stderr(Stdio::inherit()) - .status().unwrap().code().unwrap() != 0 - { - println!("Error while executing gcc"); - process::exit(1) - } - - // compiling libandroid_native_app_glue.a - if Command::new(toolchain_path.join("bin").join(format!("{}-ar", prefix))) - .arg("rcs") - .arg(directory.join("libandroid_native_app_glue.a")) - .arg(directory.join("android_native_app_glue.o")) - .stdout(Stdio::inherit()) - .stderr(Stdio::inherit()) - .status().unwrap().code().unwrap() != 0 - { - println!("Error while executing ar"); - process::exit(1) - } - - println!("cargo:rustc-link-lib=static=android_native_app_glue"); - println!("cargo:rustc-link-search=native={}", out_dir); - println!("cargo:rustc-link-lib=log"); - println!("cargo:rustc-link-lib=android"); -} diff --git a/ports/servo/glutin_app/window.rs b/ports/servo/glutin_app/window.rs index e1a50f8cf55..0837b689c41 100644 --- a/ports/servo/glutin_app/window.rs +++ b/ports/servo/glutin_app/window.rs @@ -401,12 +401,12 @@ impl Window { } } - #[cfg(not(any(target_arch = "arm", target_arch = "aarch64", target_os = "android")))] + #[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))] fn gl_version() -> GlRequest { return GlRequest::Specific(Api::OpenGl, (3, 2)); } - #[cfg(any(target_arch = "arm", target_arch = "aarch64", target_os = "android"))] + #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] fn gl_version() -> GlRequest { GlRequest::Specific(Api::OpenGlEs, (3, 0)) } @@ -634,7 +634,6 @@ impl Window { } } - /// Has no effect on Android. pub fn set_cursor(&self, cursor: CursorKind) { match self.kind { WindowKind::Window(ref window, ..) => { diff --git a/ports/servo/main.rs b/ports/servo/main.rs index 5060f87ed48..5d9174d9e73 100644 --- a/ports/servo/main.rs +++ b/ports/servo/main.rs @@ -17,316 +17,10 @@ #![cfg_attr(feature = "unstable", feature(core_intrinsics))] -#[cfg(target_os = "android")] -extern crate android_injected_glue; -extern crate backtrace; -#[macro_use] extern crate bitflags; -extern crate euclid; -#[cfg(target_os = "windows")] extern crate gdi32; -extern crate gleam; -extern crate glutin; -#[cfg(not(target_os = "android"))] -#[macro_use] extern crate lazy_static; -// The window backed by glutin -#[macro_use] extern crate log; -#[cfg(any(target_os = "linux", target_os = "macos"))] extern crate osmesa_sys; -extern crate servo; -#[cfg(all(feature = "unstable", not(target_os = "android")))] -#[macro_use] -extern crate sig; -#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))] -extern crate tinyfiledialogs; -extern crate winit; -#[cfg(target_os = "windows")] extern crate winapi; -#[cfg(target_os = "windows")] extern crate user32; - -mod glutin_app; -mod resources; - -use backtrace::Backtrace; -use servo::Servo; -use servo::compositing::windowing::WindowEvent; -use servo::config; -use servo::config::opts::{self, ArgumentParsingResult, parse_url_or_filename}; -use servo::config::servo_version; -use servo::ipc_channel::ipc; -use servo::servo_config::prefs::PREFS; -use servo::servo_url::ServoUrl; -use std::env; -use std::panic; -use std::process; -use std::thread; - -mod browser; - -pub mod platform { - #[cfg(target_os = "macos")] - pub use platform::macos::deinit; - - #[cfg(target_os = "macos")] - pub mod macos; - - #[cfg(not(target_os = "macos"))] - pub fn deinit() {} -} - -#[cfg(all(feature = "unstable", not(target_os = "android")))] -fn install_crash_handler() { - use backtrace::Backtrace; - use sig::ffi::Sig; - use std::intrinsics::abort; - use std::thread; - - fn handler(_sig: i32) { - let name = thread::current() - .name() - .map(|n| format!(" for thread \"{}\"", n)) - .unwrap_or("".to_owned()); - println!("Stack trace{}\n{:?}", name, Backtrace::new()); - unsafe { - // N.B. Using process::abort() here causes the crash handler to be - // triggered recursively. - abort(); - } - } - - signal!(Sig::SEGV, handler); // handle segfaults - signal!(Sig::ILL, handler); // handle stack overflow and unsupported CPUs - signal!(Sig::IOT, handler); // handle double panics - signal!(Sig::BUS, handler); // handle invalid memory access -} - -#[cfg(any(not(feature = "unstable"), target_os = "android"))] -fn install_crash_handler() {} - -fn main() { - install_crash_handler(); - - resources::init(); - - if cfg!(target_os = "android") && env::var_os("HOST_FILE").is_none() { - let mut path = config::basedir::default_config_dir(); - path.push("android_hosts"); - env::set_var("HOST_FILE", path); - } - - // Parse the command line options and store them globally - let opts_result = opts::from_cmdline_args(&*args()); - - let content_process_token = if let ArgumentParsingResult::ContentProcess(token) = opts_result { - Some(token) - } else { - if opts::get().is_running_problem_test && env::var("RUST_LOG").is_err() { - env::set_var("RUST_LOG", "compositing::constellation"); - } - - None - }; - - // TODO: once log-panics is released, can this be replaced by - // log_panics::init()? - panic::set_hook(Box::new(|info| { - warn!("Panic hook called."); - let msg = match info.payload().downcast_ref::<&'static str>() { - Some(s) => *s, - None => { - match info.payload().downcast_ref::() { - Some(s) => &**s, - None => "Box", - } - }, - }; - let current_thread = thread::current(); - let name = current_thread.name().unwrap_or(""); - if let Some(location) = info.location() { - println!("{} (thread {}, at {}:{})", - msg, - name, - location.file(), - location.line()); - } else { - println!("{} (thread {})", msg, name); - } - if env::var("RUST_BACKTRACE").is_ok() { - println!("{:?}", Backtrace::new()); - } - - error!("{}", msg); - })); - - setup_logging(); - - if let Some(token) = content_process_token { - return servo::run_content_process(token); - } - - if opts::get().is_printing_version { - println!("{}", servo_version()); - process::exit(0); - } - - let window = glutin_app::create_window(); - - let mut browser = browser::Browser::new(window.clone()); - - // If the url is not provided, we fallback to the homepage in PREFS, - // or a blank page in case the homepage is not set either. - let cwd = env::current_dir().unwrap(); - let cmdline_url = opts::get().url.clone(); - let pref_url = PREFS.get("shell.homepage").as_string() - .and_then(|str| parse_url_or_filename(&cwd, str).ok()); - let blank_url = ServoUrl::parse("about:blank").ok(); - - let target_url = cmdline_url.or(pref_url).or(blank_url).unwrap(); - - let mut servo = Servo::new(window.clone()); - - let (sender, receiver) = ipc::channel().unwrap(); - servo.handle_events(vec![WindowEvent::NewBrowser(target_url, sender)]); - let browser_id = receiver.recv().unwrap(); - browser.set_browser_id(browser_id); - servo.handle_events(vec![WindowEvent::SelectBrowser(browser_id)]); - - servo.setup_logging(); - - window.run(|| { - let win_events = window.get_events(); - - // FIXME: this could be handled by Servo. We don't need - // a repaint_synchronously function exposed. - let need_resize = win_events.iter().any(|e| match *e { - WindowEvent::Resize => true, - _ => false, - }); - - browser.handle_window_events(win_events); - - let mut servo_events = servo.get_events(); - loop { - browser.handle_servo_events(servo_events); - servo.handle_events(browser.get_events()); - if browser.shutdown_requested() { - return true; - } - servo_events = servo.get_events(); - if servo_events.is_empty() { - break; - } - } - - if need_resize { - servo.repaint_synchronously(); - } - false - }); - - servo.deinit(); - - platform::deinit() -} +#[cfg(not(target_os = "android"))] include!("non_android_main.rs"); #[cfg(target_os = "android")] -fn setup_logging() { - // Piping logs from stdout/stderr to logcat happens in android_injected_glue. - env::set_var("RUST_LOG", "error"); - - unsafe { android_injected_glue::ffi::app_dummy() }; -} - -#[cfg(not(target_os = "android"))] -fn setup_logging() {} - -#[cfg(target_os = "android")] -/// Attempt to read parameters from a file since they are not passed to us in Android environments. -/// The first line should be the "servo" argument and the last should be the URL to load. -/// Blank lines and those beginning with a '#' are ignored. -/// Each line should be a separate parameter as would be parsed by the shell. -/// For example, "servo -p 10 http://en.wikipedia.org/wiki/Rust" would take 4 lines. -fn args() -> Vec { - use std::error::Error; - use std::fs::File; - use std::io::{BufRead, BufReader}; - - let mut params_file = config::basedir::default_config_dir(); - params_file.push("android_params"); - match File::open(params_file.to_str().unwrap()) { - Ok(f) => { - let mut vec = Vec::new(); - let file = BufReader::new(&f); - for line in file.lines() { - let l = line.unwrap().trim().to_owned(); - // ignore blank lines and those that start with a '#' - match l.is_empty() || l.as_bytes()[0] == b'#' { - true => (), - false => vec.push(l), - } - } - vec - }, - Err(e) => { - debug!("Failed to open params file '{}': {}", - params_file.to_str().unwrap(), - Error::description(&e)); - vec!["servo".to_owned(), "http://en.wikipedia.org/wiki/Rust".to_owned()] - }, - } -} - -#[cfg(not(target_os = "android"))] -fn args() -> Vec { - env::args().collect() -} - - -#[cfg(target_os = "android")] -#[no_mangle] -#[inline(never)] -#[allow(non_snake_case)] -pub extern "C" fn android_main(app: *mut ()) { - android_injected_glue::android_main2(app as *mut _, move |_, _| main()); -} - -// These functions aren't actually called. They are here as a link -// hack because Skia references them. - -#[allow(non_snake_case)] -#[no_mangle] -pub extern "C" fn glBindVertexArrayOES(_array: usize) -{ - unimplemented!() -} - -#[allow(non_snake_case)] -#[no_mangle] -pub extern "C" fn glDeleteVertexArraysOES(_n: isize, _arrays: *const ()) -{ - unimplemented!() -} - -#[allow(non_snake_case)] -#[no_mangle] -pub extern "C" fn glGenVertexArraysOES(_n: isize, _arrays: *const ()) -{ - unimplemented!() -} - -#[allow(non_snake_case)] -#[no_mangle] -pub extern "C" fn glRenderbufferStorageMultisampleIMG(_: isize, _: isize, _: isize, _: isize, _: isize) -{ - unimplemented!() -} - -#[allow(non_snake_case)] -#[no_mangle] -pub extern "C" fn glFramebufferTexture2DMultisampleIMG(_: isize, _: isize, _: isize, _: isize, _: isize, _: isize) -{ - unimplemented!() -} - -#[allow(non_snake_case)] -#[no_mangle] -pub extern "C" fn glDiscardFramebufferEXT(_: isize, _: isize, _: *const ()) -{ - unimplemented!() +pub fn main() { + println!("Cannot start /ports/servo/ on Android. \ + Use /support/android/apk/ + /ports/libsimpleservo/ instead"); } diff --git a/ports/servo/non_android_main.rs b/ports/servo/non_android_main.rs new file mode 100644 index 00000000000..b4a50fc8112 --- /dev/null +++ b/ports/servo/non_android_main.rs @@ -0,0 +1,243 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +extern crate backtrace; +#[macro_use] extern crate bitflags; +extern crate euclid; +#[cfg(target_os = "windows")] extern crate gdi32; +extern crate gleam; +extern crate glutin; +#[macro_use] extern crate lazy_static; +// The window backed by glutin +#[macro_use] extern crate log; +#[cfg(any(target_os = "linux", target_os = "macos"))] extern crate osmesa_sys; +extern crate servo; +#[cfg(feature = "unstable")] +#[macro_use] +extern crate sig; +#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))] +extern crate tinyfiledialogs; +extern crate winit; +#[cfg(target_os = "windows")] extern crate winapi; +#[cfg(target_os = "windows")] extern crate user32; + +mod glutin_app; +mod resources; + +use backtrace::Backtrace; +use servo::Servo; +use servo::compositing::windowing::WindowEvent; +use servo::config::opts::{self, ArgumentParsingResult, parse_url_or_filename}; +use servo::config::servo_version; +use servo::ipc_channel::ipc; +use servo::servo_config::prefs::PREFS; +use servo::servo_url::ServoUrl; +use std::env; +use std::panic; +use std::process; +use std::thread; + +mod browser; + +pub mod platform { + #[cfg(target_os = "macos")] + pub use platform::macos::deinit; + + #[cfg(target_os = "macos")] + pub mod macos; + + #[cfg(not(target_os = "macos"))] + pub fn deinit() {} +} + +#[cfg(feature = "unstable")] +fn install_crash_handler() { + use backtrace::Backtrace; + use sig::ffi::Sig; + use std::intrinsics::abort; + use std::thread; + + fn handler(_sig: i32) { + let name = thread::current() + .name() + .map(|n| format!(" for thread \"{}\"", n)) + .unwrap_or("".to_owned()); + println!("Stack trace{}\n{:?}", name, Backtrace::new()); + unsafe { + // N.B. Using process::abort() here causes the crash handler to be + // triggered recursively. + abort(); + } + } + + signal!(Sig::SEGV, handler); // handle segfaults + signal!(Sig::ILL, handler); // handle stack overflow and unsupported CPUs + signal!(Sig::IOT, handler); // handle double panics + signal!(Sig::BUS, handler); // handle invalid memory access +} + +pub fn main() { + install_crash_handler(); + + resources::init(); + + // Parse the command line options and store them globally + let args: Vec = env::args().collect(); + let opts_result = opts::from_cmdline_args(&args); + + let content_process_token = if let ArgumentParsingResult::ContentProcess(token) = opts_result { + Some(token) + } else { + if opts::get().is_running_problem_test && env::var("RUST_LOG").is_err() { + env::set_var("RUST_LOG", "compositing::constellation"); + } + + None + }; + + // TODO: once log-panics is released, can this be replaced by + // log_panics::init()? + panic::set_hook(Box::new(|info| { + warn!("Panic hook called."); + let msg = match info.payload().downcast_ref::<&'static str>() { + Some(s) => *s, + None => { + match info.payload().downcast_ref::() { + Some(s) => &**s, + None => "Box", + } + }, + }; + let current_thread = thread::current(); + let name = current_thread.name().unwrap_or(""); + if let Some(location) = info.location() { + println!("{} (thread {}, at {}:{})", + msg, + name, + location.file(), + location.line()); + } else { + println!("{} (thread {})", msg, name); + } + if env::var("RUST_BACKTRACE").is_ok() { + println!("{:?}", Backtrace::new()); + } + + error!("{}", msg); + })); + + if let Some(token) = content_process_token { + return servo::run_content_process(token); + } + + if opts::get().is_printing_version { + println!("{}", servo_version()); + process::exit(0); + } + + let window = glutin_app::create_window(); + + let mut browser = browser::Browser::new(window.clone()); + + // If the url is not provided, we fallback to the homepage in PREFS, + // or a blank page in case the homepage is not set either. + let cwd = env::current_dir().unwrap(); + let cmdline_url = opts::get().url.clone(); + let pref_url = PREFS.get("shell.homepage").as_string() + .and_then(|str| parse_url_or_filename(&cwd, str).ok()); + let blank_url = ServoUrl::parse("about:blank").ok(); + + let target_url = cmdline_url.or(pref_url).or(blank_url).unwrap(); + + let mut servo = Servo::new(window.clone()); + + let (sender, receiver) = ipc::channel().unwrap(); + servo.handle_events(vec![WindowEvent::NewBrowser(target_url, sender)]); + let browser_id = receiver.recv().unwrap(); + browser.set_browser_id(browser_id); + servo.handle_events(vec![WindowEvent::SelectBrowser(browser_id)]); + + servo.setup_logging(); + + window.run(|| { + let win_events = window.get_events(); + + // FIXME: this could be handled by Servo. We don't need + // a repaint_synchronously function exposed. + let need_resize = win_events.iter().any(|e| match *e { + WindowEvent::Resize => true, + _ => false, + }); + + browser.handle_window_events(win_events); + + let mut servo_events = servo.get_events(); + loop { + browser.handle_servo_events(servo_events); + servo.handle_events(browser.get_events()); + if browser.shutdown_requested() { + return true; + } + servo_events = servo.get_events(); + if servo_events.is_empty() { + break; + } + } + + if need_resize { + servo.repaint_synchronously(); + } + false + }); + + servo.deinit(); + + platform::deinit() +} + +// These functions aren't actually called. They are here as a link +// hack because Skia references them. + +#[allow(non_snake_case)] +#[no_mangle] +pub extern "C" fn glBindVertexArrayOES(_array: usize) +{ + unimplemented!() +} + +#[allow(non_snake_case)] +#[no_mangle] +pub extern "C" fn glDeleteVertexArraysOES(_n: isize, _arrays: *const ()) +{ + unimplemented!() +} + +#[allow(non_snake_case)] +#[no_mangle] +pub extern "C" fn glGenVertexArraysOES(_n: isize, _arrays: *const ()) +{ + unimplemented!() +} + +#[allow(non_snake_case)] +#[no_mangle] +pub extern "C" fn glRenderbufferStorageMultisampleIMG(_: isize, _: isize, _: isize, _: isize, _: isize) +{ + unimplemented!() +} + +#[allow(non_snake_case)] +#[no_mangle] +pub extern "C" fn glFramebufferTexture2DMultisampleIMG(_: isize, _: isize, _: isize, _: isize, _: isize, _: isize) +{ + unimplemented!() +} + +#[allow(non_snake_case)] +#[no_mangle] +pub extern "C" fn glDiscardFramebufferEXT(_: isize, _: isize, _: *const ()) +{ + unimplemented!() +} + diff --git a/ports/servo/resources.rs b/ports/servo/resources.rs index 2738a8a0eb4..4417881dfcf 100644 --- a/ports/servo/resources.rs +++ b/ports/servo/resources.rs @@ -3,6 +3,15 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use servo::embedder_traits::resources::{self, Resource}; +use std::env; +use std::fs; +use std::io; +use std::path::PathBuf; +use std::sync::Mutex; + +lazy_static! { + static ref CMD_RESOURCE_DIR: Mutex> = Mutex::new(None); +} struct ResourceReader; @@ -27,86 +36,50 @@ pub fn init() { resources::set(Box::new(ResourceReader)); } -#[cfg(not(target_os = "android"))] -mod not_android { - use servo::embedder_traits::resources::{self, Resource}; - use std::env; - use std::fs; - use std::io; - use std::path::PathBuf; - use std::sync::Mutex; - - lazy_static! { - static ref CMD_RESOURCE_DIR: Mutex> = Mutex::new(None); +fn resources_dir_path() -> io::Result { + // This needs to be called before the process is sandboxed + // as we only give permission to read inside the resources directory, + // not the permissions the "search" for the resources directory. + let mut dir = CMD_RESOURCE_DIR.lock().unwrap(); + if let Some(ref path) = *dir { + return Ok(PathBuf::from(path)); } - impl resources::ResourceReaderMethods for super::ResourceReader { - fn read(&self, file: Resource) -> Vec { - let file = super::filename(file); - let mut path = resources_dir_path().expect("Can't find resources directory"); - path.push(file); - fs::read(path).expect("Can't read file") + // FIXME: Find a way to not rely on the executable being + // under `[/$target_triple]/target/debug` + // or `[/$target_triple]/target/release`. + let mut path = env::current_exe()?; + // Follow symlink + path = path.canonicalize()?; + + while path.pop() { + path.push("resources"); + if path.is_dir() { + break; } - fn sandbox_access_files_dirs(&self) -> Vec { - vec![resources_dir_path().expect("Can't find resources directory")] - } - fn sandbox_access_files(&self) -> Vec { - vec![] + path.pop(); + // Check for Resources on mac when using a case sensitive filesystem. + path.push("Resources"); + if path.is_dir() { + break; } + path.pop(); } - - fn resources_dir_path() -> io::Result { - // This needs to be called before the process is sandboxed - // as we only give permission to read inside the resources directory, - // not the permissions the "search" for the resources directory. - let mut dir = CMD_RESOURCE_DIR.lock().unwrap(); - if let Some(ref path) = *dir { - return Ok(PathBuf::from(path)); - } - - // FIXME: Find a way to not rely on the executable being - // under `[/$target_triple]/target/debug` - // or `[/$target_triple]/target/release`. - let mut path = env::current_exe()?; - // Follow symlink - path = path.canonicalize()?; - - while path.pop() { - path.push("resources"); - if path.is_dir() { - break; - } - path.pop(); - // Check for Resources on mac when using a case sensitive filesystem. - path.push("Resources"); - if path.is_dir() { - break; - } - path.pop(); - } - *dir = Some(path.to_str().unwrap().to_owned()); - Ok(path) - } + *dir = Some(path.to_str().unwrap().to_owned()); + Ok(path) } -#[cfg(target_os = "android")] -mod android { - use android_injected_glue::load_asset; - use servo::embedder_traits::resources::{self, Resource}; - use std::path::PathBuf; - - impl resources::ResourceReaderMethods for super::ResourceReader { - fn read(&self, file: Resource) -> Vec { - let file = super::filename(file); - load_asset(file).unwrap_or_else(|_| { - panic!("Can't load asset"); - }) - } - fn sandbox_access_files_dirs(&self) -> Vec { - vec![] - } - fn sandbox_access_files(&self) -> Vec { - vec![] - } +impl resources::ResourceReaderMethods for ResourceReader { + fn read(&self, file: Resource) -> Vec { + let file = filename(file); + let mut path = resources_dir_path().expect("Can't find resources directory"); + path.push(file); + fs::read(path).expect("Can't read file") + } + fn sandbox_access_files_dirs(&self) -> Vec { + vec![resources_dir_path().expect("Can't find resources directory")] + } + fn sandbox_access_files(&self) -> Vec { + vec![] } }