mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
new android port: Remove Android code from /ports/servo/
This commit is contained in:
parent
6e7f7fc8eb
commit
cbaf19c65c
7 changed files with 306 additions and 534 deletions
|
@ -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"
|
||||
|
|
|
@ -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<String> {
|
||||
// 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<String> {
|
||||
tinyfiledialogs::input_box(title, title, url)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn platform_get_selected_devices(devices: Vec<String>) -> Option<String> {
|
||||
let picker_name = "Choose a device";
|
||||
|
@ -403,10 +380,7 @@ fn platform_get_selected_devices(devices: Vec<String>) -> Option<String> {
|
|||
None
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
|
||||
fn platform_get_selected_files(patterns: Vec<FilterPattern>,
|
||||
multiple_files: bool)
|
||||
-> Option<Vec<String>> {
|
||||
fn get_selected_files(patterns: Vec<FilterPattern>, multiple_files: bool) -> Option<Vec<String>> {
|
||||
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<FilterPattern>,
|
|||
}).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<FilterPattern>,
|
||||
_multiple_files: bool)
|
||||
-> Option<Vec<String>> {
|
||||
warn!("File picker not implemented");
|
||||
None
|
||||
}
|
||||
|
||||
fn sanitize_url(request: &str) -> Option<ServoUrl> {
|
||||
let request = request.trim();
|
||||
ServoUrl::parse(&request).ok()
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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, ..) => {
|
||||
|
|
|
@ -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::<String>() {
|
||||
Some(s) => &**s,
|
||||
None => "Box<Any>",
|
||||
}
|
||||
},
|
||||
};
|
||||
let current_thread = thread::current();
|
||||
let name = current_thread.name().unwrap_or("<unnamed>");
|
||||
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<String> {
|
||||
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<String> {
|
||||
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");
|
||||
}
|
||||
|
|
243
ports/servo/non_android_main.rs
Normal file
243
ports/servo/non_android_main.rs
Normal file
|
@ -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<String> = 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::<String>() {
|
||||
Some(s) => &**s,
|
||||
None => "Box<Any>",
|
||||
}
|
||||
},
|
||||
};
|
||||
let current_thread = thread::current();
|
||||
let name = current_thread.name().unwrap_or("<unnamed>");
|
||||
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!()
|
||||
}
|
||||
|
|
@ -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<Option<String>> = Mutex::new(None);
|
||||
}
|
||||
|
||||
struct ResourceReader;
|
||||
|
||||
|
@ -27,35 +36,7 @@ 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<Option<String>> = Mutex::new(None);
|
||||
}
|
||||
|
||||
impl resources::ResourceReaderMethods for super::ResourceReader {
|
||||
fn read(&self, file: Resource) -> Vec<u8> {
|
||||
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")
|
||||
}
|
||||
fn sandbox_access_files_dirs(&self) -> Vec<PathBuf> {
|
||||
vec![resources_dir_path().expect("Can't find resources directory")]
|
||||
}
|
||||
fn sandbox_access_files(&self) -> Vec<PathBuf> {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
fn resources_dir_path() -> io::Result<PathBuf> {
|
||||
fn resources_dir_path() -> io::Result<PathBuf> {
|
||||
// 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.
|
||||
|
@ -86,27 +67,19 @@ mod not_android {
|
|||
}
|
||||
*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 {
|
||||
impl resources::ResourceReaderMethods for ResourceReader {
|
||||
fn read(&self, file: Resource) -> Vec<u8> {
|
||||
let file = super::filename(file);
|
||||
load_asset(file).unwrap_or_else(|_| {
|
||||
panic!("Can't load asset");
|
||||
})
|
||||
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<PathBuf> {
|
||||
vec![]
|
||||
vec![resources_dir_path().expect("Can't find resources directory")]
|
||||
}
|
||||
fn sandbox_access_files(&self) -> Vec<PathBuf> {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue