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"]
|
oculusvr = ["libservo/oculusvr"]
|
||||||
unstable = ["libservo/unstable"]
|
unstable = ["libservo/unstable"]
|
||||||
|
|
||||||
[dependencies]
|
[target.'cfg(not(target_os = "android"))'.dependencies]
|
||||||
backtrace = "0.3"
|
backtrace = "0.3"
|
||||||
bitflags = "1.0"
|
bitflags = "1.0"
|
||||||
euclid = "0.18"
|
euclid = "0.18"
|
||||||
|
@ -44,8 +44,6 @@ libservo = {path = "../../components/servo"}
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
tinyfiledialogs = "3.0"
|
tinyfiledialogs = "3.0"
|
||||||
winit = {version = "0.16", features = ["icon_loading"]}
|
winit = {version = "0.16", features = ["icon_loading"]}
|
||||||
|
|
||||||
[target.'cfg(not(target_os = "android"))'.dependencies]
|
|
||||||
sig = "0.1"
|
sig = "0.1"
|
||||||
|
|
||||||
[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies]
|
[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]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
x11 = "2.0.0"
|
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]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
winapi = "0.2"
|
winapi = "0.2"
|
||||||
user32-sys = "0.2"
|
user32-sys = "0.2"
|
||||||
|
|
|
@ -17,9 +17,7 @@ use servo::servo_url::ServoUrl;
|
||||||
use servo::webrender_api::ScrollLocation;
|
use servo::webrender_api::ScrollLocation;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
|
|
||||||
use std::thread;
|
use std::thread;
|
||||||
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
|
|
||||||
use tinyfiledialogs::{self, MessageBoxIcon};
|
use tinyfiledialogs::{self, MessageBoxIcon};
|
||||||
|
|
||||||
pub struct Browser {
|
pub struct Browser {
|
||||||
|
@ -100,7 +98,8 @@ impl Browser {
|
||||||
String::from("")
|
String::from("")
|
||||||
};
|
};
|
||||||
let title = "URL or search query";
|
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) {
|
if let Some(url) = sanitize_url(&input) {
|
||||||
self.event_queue.push(WindowEvent::LoadUrl(id, url));
|
self.event_queue.push(WindowEvent::LoadUrl(id, url));
|
||||||
}
|
}
|
||||||
|
@ -263,7 +262,11 @@ impl Browser {
|
||||||
self.window.set_inner_size(size);
|
self.window.set_inner_size(size);
|
||||||
}
|
}
|
||||||
EmbedderMsg::Alert(message, sender) => {
|
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(()) {
|
if let Err(e) = sender.send(()) {
|
||||||
let reason = format!("Failed to send Alert response: {}", e);
|
let reason = format!("Failed to send Alert response: {}", e);
|
||||||
self.event_queue.push(WindowEvent::SendError(browser_id, reason));
|
self.event_queue.push(WindowEvent::SendError(browser_id, reason));
|
||||||
|
@ -324,8 +327,7 @@ impl Browser {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
EmbedderMsg::SelectFiles(patterns, multiple_files, sender) => {
|
EmbedderMsg::SelectFiles(patterns, multiple_files, sender) => {
|
||||||
let res = match (opts::get().headless,
|
let res = match (opts::get().headless, get_selected_files(patterns, multiple_files)) {
|
||||||
platform_get_selected_files(patterns, multiple_files)) {
|
|
||||||
(true, _) | (false, None) => sender.send(None),
|
(true, _) | (false, None) => sender.send(None),
|
||||||
(false, Some(files)) => sender.send(Some(files))
|
(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")]
|
#[cfg(target_os = "linux")]
|
||||||
fn platform_get_selected_devices(devices: Vec<String>) -> Option<String> {
|
fn platform_get_selected_devices(devices: Vec<String>) -> Option<String> {
|
||||||
let picker_name = "Choose a device";
|
let picker_name = "Choose a device";
|
||||||
|
@ -403,10 +380,7 @@ fn platform_get_selected_devices(devices: Vec<String>) -> Option<String> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
|
fn get_selected_files(patterns: Vec<FilterPattern>, multiple_files: bool) -> Option<Vec<String>> {
|
||||||
fn platform_get_selected_files(patterns: Vec<FilterPattern>,
|
|
||||||
multiple_files: bool)
|
|
||||||
-> Option<Vec<String>> {
|
|
||||||
let picker_name = if multiple_files { "Pick files" } else { "Pick a file" };
|
let picker_name = if multiple_files { "Pick files" } else { "Pick a file" };
|
||||||
thread::Builder::new().name(picker_name.to_owned()).spawn(move || {
|
thread::Builder::new().name(picker_name.to_owned()).spawn(move || {
|
||||||
let mut filters = vec![];
|
let mut filters = vec![];
|
||||||
|
@ -426,14 +400,6 @@ fn platform_get_selected_files(patterns: Vec<FilterPattern>,
|
||||||
}).unwrap().join().expect("Thread spawning failed")
|
}).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> {
|
fn sanitize_url(request: &str) -> Option<ServoUrl> {
|
||||||
let request = request.trim();
|
let request = request.trim();
|
||||||
ServoUrl::parse(&request).ok()
|
ServoUrl::parse(&request).ok()
|
||||||
|
|
|
@ -5,18 +5,7 @@
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
extern crate winres;
|
extern crate winres;
|
||||||
|
|
||||||
use std::env;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::process;
|
|
||||||
use std::process::{Command, Stdio};
|
|
||||||
|
|
||||||
fn main() {
|
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)]
|
#[cfg(windows)]
|
||||||
{
|
{
|
||||||
let mut res = winres::WindowsResource::new();
|
let mut res = winres::WindowsResource::new();
|
||||||
|
@ -25,89 +14,3 @@ fn main() {
|
||||||
res.compile().unwrap();
|
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 {
|
fn gl_version() -> GlRequest {
|
||||||
return GlRequest::Specific(Api::OpenGl, (3, 2));
|
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 {
|
fn gl_version() -> GlRequest {
|
||||||
GlRequest::Specific(Api::OpenGlEs, (3, 0))
|
GlRequest::Specific(Api::OpenGlEs, (3, 0))
|
||||||
}
|
}
|
||||||
|
@ -634,7 +634,6 @@ impl Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Has no effect on Android.
|
|
||||||
pub fn set_cursor(&self, cursor: CursorKind) {
|
pub fn set_cursor(&self, cursor: CursorKind) {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
WindowKind::Window(ref window, ..) => {
|
WindowKind::Window(ref window, ..) => {
|
||||||
|
|
|
@ -17,316 +17,10 @@
|
||||||
|
|
||||||
#![cfg_attr(feature = "unstable", feature(core_intrinsics))]
|
#![cfg_attr(feature = "unstable", feature(core_intrinsics))]
|
||||||
|
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(not(target_os = "android"))] include!("non_android_main.rs");
|
||||||
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(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
fn setup_logging() {
|
pub fn main() {
|
||||||
// Piping logs from stdout/stderr to logcat happens in android_injected_glue.
|
println!("Cannot start /ports/servo/ on Android. \
|
||||||
env::set_var("RUST_LOG", "error");
|
Use /support/android/apk/ + /ports/libsimpleservo/ instead");
|
||||||
|
|
||||||
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!()
|
|
||||||
}
|
}
|
||||||
|
|
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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use servo::embedder_traits::resources::{self, Resource};
|
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;
|
struct ResourceReader;
|
||||||
|
|
||||||
|
@ -27,86 +36,50 @@ pub fn init() {
|
||||||
resources::set(Box::new(ResourceReader));
|
resources::set(Box::new(ResourceReader));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "android"))]
|
fn resources_dir_path() -> io::Result<PathBuf> {
|
||||||
mod not_android {
|
// This needs to be called before the process is sandboxed
|
||||||
use servo::embedder_traits::resources::{self, Resource};
|
// as we only give permission to read inside the resources directory,
|
||||||
use std::env;
|
// not the permissions the "search" for the resources directory.
|
||||||
use std::fs;
|
let mut dir = CMD_RESOURCE_DIR.lock().unwrap();
|
||||||
use std::io;
|
if let Some(ref path) = *dir {
|
||||||
use std::path::PathBuf;
|
return Ok(PathBuf::from(path));
|
||||||
use std::sync::Mutex;
|
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
static ref CMD_RESOURCE_DIR: Mutex<Option<String>> = Mutex::new(None);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl resources::ResourceReaderMethods for super::ResourceReader {
|
// FIXME: Find a way to not rely on the executable being
|
||||||
fn read(&self, file: Resource) -> Vec<u8> {
|
// under `<servo source>[/$target_triple]/target/debug`
|
||||||
let file = super::filename(file);
|
// or `<servo source>[/$target_triple]/target/release`.
|
||||||
let mut path = resources_dir_path().expect("Can't find resources directory");
|
let mut path = env::current_exe()?;
|
||||||
path.push(file);
|
// Follow symlink
|
||||||
fs::read(path).expect("Can't read file")
|
path = path.canonicalize()?;
|
||||||
|
|
||||||
|
while path.pop() {
|
||||||
|
path.push("resources");
|
||||||
|
if path.is_dir() {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
fn sandbox_access_files_dirs(&self) -> Vec<PathBuf> {
|
path.pop();
|
||||||
vec![resources_dir_path().expect("Can't find resources directory")]
|
// Check for Resources on mac when using a case sensitive filesystem.
|
||||||
}
|
path.push("Resources");
|
||||||
fn sandbox_access_files(&self) -> Vec<PathBuf> {
|
if path.is_dir() {
|
||||||
vec![]
|
break;
|
||||||
}
|
}
|
||||||
|
path.pop();
|
||||||
}
|
}
|
||||||
|
*dir = Some(path.to_str().unwrap().to_owned());
|
||||||
fn resources_dir_path() -> io::Result<PathBuf> {
|
Ok(path)
|
||||||
// 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 `<servo source>[/$target_triple]/target/debug`
|
|
||||||
// or `<servo source>[/$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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "android")]
|
impl resources::ResourceReaderMethods for ResourceReader {
|
||||||
mod android {
|
fn read(&self, file: Resource) -> Vec<u8> {
|
||||||
use android_injected_glue::load_asset;
|
let file = filename(file);
|
||||||
use servo::embedder_traits::resources::{self, Resource};
|
let mut path = resources_dir_path().expect("Can't find resources directory");
|
||||||
use std::path::PathBuf;
|
path.push(file);
|
||||||
|
fs::read(path).expect("Can't read file")
|
||||||
impl resources::ResourceReaderMethods for super::ResourceReader {
|
}
|
||||||
fn read(&self, file: Resource) -> Vec<u8> {
|
fn sandbox_access_files_dirs(&self) -> Vec<PathBuf> {
|
||||||
let file = super::filename(file);
|
vec![resources_dir_path().expect("Can't find resources directory")]
|
||||||
load_asset(file).unwrap_or_else(|_| {
|
}
|
||||||
panic!("Can't load asset");
|
fn sandbox_access_files(&self) -> Vec<PathBuf> {
|
||||||
})
|
vec![]
|
||||||
}
|
|
||||||
fn sandbox_access_files_dirs(&self) -> Vec<PathBuf> {
|
|
||||||
vec![]
|
|
||||||
}
|
|
||||||
fn sandbox_access_files(&self) -> Vec<PathBuf> {
|
|
||||||
vec![]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue