diff --git a/Cargo.lock b/Cargo.lock index f2d918ec898..8f6b74d3f49 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1242,6 +1242,7 @@ dependencies = [ "msg", "serde", "serde_json", + "servo_config", "servo_rand", "servo_url", "time", @@ -5433,6 +5434,7 @@ dependencies = [ "libloading 0.5.2", "libservo", "log", + "serde_json", "servo-media", "surfman", "webxr", diff --git a/components/config/opts.rs b/components/config/opts.rs index 47d92f986d5..c5ca6907bee 100644 --- a/components/config/opts.rs +++ b/components/config/opts.rs @@ -112,9 +112,12 @@ pub struct Opts { /// remote Firefox debugger connections. pub debugger_port: Option, - /// `None` to disable devtools or `Some` with a port number to start a server to listen to - /// remote Firefox devtools connections. - pub devtools_port: Option, + /// Port number to start a server to listen to remote Firefox devtools connections. + /// 0 for random port. + pub devtools_port: u16, + + /// Start the devtools server at startup + pub devtools_server_enabled: bool, /// `None` to disable WebDriver or `Some` with a port number to start a server to listen to /// remote WebDriver commands. @@ -482,7 +485,8 @@ pub fn default_opts() -> Opts { enable_canvas_antialiasing: true, trace_layout: false, debugger_port: None, - devtools_port: None, + devtools_port: 0, + devtools_server_enabled: false, webdriver_port: None, initial_window_size: Size2D::new(1024, 740), multiprocess: false, @@ -802,11 +806,22 @@ pub fn from_cmdline_args(mut opts: Options, args: &[String]) -> ArgumentParsingR }) }); - // Set default port 0 for a random port to be selected. - let devtools_port = opt_match.opt_default("devtools", "0").map(|port| { - port.parse() - .unwrap_or_else(|err| args_fail(&format!("Error parsing option: --devtools ({})", err))) - }); + let (devtools_enabled, devtools_port) = if opt_match.opt_present("devtools") { + let port = opt_match + .opt_str("devtools") + .map(|port| { + port.parse().unwrap_or_else(|err| { + args_fail(&format!("Error parsing option: --devtools ({})", err)) + }) + }) + .unwrap_or(pref!(devtools.server.port)); + (true, port as u16) + } else { + ( + pref!(devtools.server.enabled), + pref!(devtools.server.port) as u16, + ) + }; let webdriver_port = opt_match.opt_default("webdriver", "7000").map(|port| { port.parse().unwrap_or_else(|err| { @@ -874,6 +889,7 @@ pub fn from_cmdline_args(mut opts: Options, args: &[String]) -> ArgumentParsingR trace_layout: debug_options.trace_layout, debugger_port: debugger_port, devtools_port: devtools_port, + devtools_server_enabled: devtools_enabled, webdriver_port: webdriver_port, initial_window_size: initial_window_size, multiprocess: opt_match.opt_present("M"), diff --git a/components/config/prefs.rs b/components/config/prefs.rs index 5ac6b19d940..1ecc245ff9f 100644 --- a/components/config/prefs.rs +++ b/components/config/prefs.rs @@ -123,6 +123,12 @@ mod gen { }, }, }, + devtools: { + server: { + enabled: bool, + port: i64, + }, + }, dom: { webgpu: { enabled: bool, diff --git a/components/devtools/Cargo.toml b/components/devtools/Cargo.toml index 6a6532df54a..68da8489cb7 100644 --- a/components/devtools/Cargo.toml +++ b/components/devtools/Cargo.toml @@ -22,6 +22,7 @@ log = "0.4" msg = { path = "../msg" } serde = "1.0" serde_json = "1.0" +servo_config = { path = "../config" } servo_rand = { path = "../rand" } servo_url = { path = "../url" } time = "0.1" diff --git a/components/servo/lib.rs b/components/servo/lib.rs index c6b368d8b2a..9ea3bc71643 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -356,9 +356,15 @@ where let mem_profiler_chan = profile_mem::Profiler::create(opts.mem_profiler_period); let debugger_chan = opts.debugger_port.map(|port| debugger::start_server(port)); - let devtools_chan = opts - .devtools_port - .map(|port| devtools::start_server(port, embedder_proxy.clone())); + + let devtools_chan = if opts.devtools_server_enabled { + Some(devtools::start_server( + opts.devtools_port, + embedder_proxy.clone(), + )) + } else { + None + }; let coordinates = window.get_coordinates(); let device_pixel_ratio = coordinates.hidpi_factor.get(); diff --git a/ports/libsimpleservo/api/Cargo.toml b/ports/libsimpleservo/api/Cargo.toml index 17e914f5468..97e6b5e53ae 100644 --- a/ports/libsimpleservo/api/Cargo.toml +++ b/ports/libsimpleservo/api/Cargo.toml @@ -30,6 +30,7 @@ libloading = "0.5" [build-dependencies] gl_generator = "0.14" +serde_json = "1.0" [features] debugmozjs = ["libservo/debugmozjs"] diff --git a/ports/libsimpleservo/api/build.rs b/ports/libsimpleservo/api/build.rs index 243e139cf97..16337042c3c 100644 --- a/ports/libsimpleservo/api/build.rs +++ b/ports/libsimpleservo/api/build.rs @@ -3,6 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use gl_generator::{Api, Fallbacks, Profile, Registry}; +use serde_json::{self, Value}; use std::env; use std::fs::File; use std::path::PathBuf; @@ -40,4 +41,30 @@ fn main() { .write_bindings(gl_generator::StructGenerator, &mut file) .unwrap(); } + + // Merge prefs.json and package-prefs.json + let mut default_prefs = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + default_prefs.push("../../../resources/prefs.json"); + let mut prefs: Value = serde_json::from_reader(File::open(&default_prefs).unwrap()).unwrap(); + let mut pkg_prefs = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + pkg_prefs.push("../../../resources/package-prefs.json"); + let pkg_prefs: Value = serde_json::from_reader(File::open(&pkg_prefs).unwrap()).unwrap(); + if target.contains("uwp") { + // Assuming Hololens build + let to_merge = pkg_prefs + .as_object() + .unwrap() + .get("hololens") + .unwrap() + .as_object() + .unwrap(); + for (key, value) in to_merge.iter() { + prefs + .as_object_mut() + .unwrap() + .insert(key.clone(), value.clone()); + } + } + let file = File::create(&dest.join("prefs.json")).unwrap(); + serde_json::to_writer(file, &prefs).unwrap(); } diff --git a/ports/libsimpleservo/api/src/lib.rs b/ports/libsimpleservo/api/src/lib.rs index fc9ce60b8f9..d01239a1e75 100644 --- a/ports/libsimpleservo/api/src/lib.rs +++ b/ports/libsimpleservo/api/src/lib.rs @@ -30,8 +30,7 @@ use servo::euclid::{Point2D, Rect, Scale, Size2D, Vector2D}; use servo::keyboard_types::{Key, KeyState, KeyboardEvent}; use servo::msg::constellation_msg::TraversalDirection; use servo::script_traits::{TouchEventType, TouchId}; -use servo::servo_config::opts; -use servo::servo_config::{pref, set_pref}; +use servo::servo_config::{opts, pref}; use servo::servo_url::ServoUrl; use servo::webrender_api::units::DevicePixel; use servo::webrender_api::ScrollLocation; @@ -62,7 +61,6 @@ pub struct InitOptions { pub coordinates: Coordinates, pub density: f32, pub xr_discovery: Option, - pub enable_subpixel_text_antialiasing: bool, pub gl_context_pointer: Option<*const c_void>, pub native_display_pointer: Option<*const c_void>, pub native_widget: *mut c_void, @@ -227,22 +225,15 @@ pub fn init( ) -> Result<(), &'static str> { resources::set(Box::new(ResourceReaderInstance::new())); - let mut args = mem::replace(&mut init_opts.args, vec![]); - if !args.is_empty() { - // opts::from_cmdline_args expects the first argument to be the binary name. - args.insert(0, "servo".to_string()); - - set_pref!( - gfx.subpixel_text_antialiasing.enabled, - init_opts.enable_subpixel_text_antialiasing - ); - opts::from_cmdline_args(Options::new(), &args); - } - if let Some(prefs) = init_opts.prefs { add_user_prefs(prefs); } + let mut args = mem::replace(&mut init_opts.args, vec![]); + // opts::from_cmdline_args expects the first argument to be the binary name. + args.insert(0, "servo".to_string()); + opts::from_cmdline_args(Options::new(), &args); + let pref_url = ServoUrl::parse(&pref!(shell.homepage)).ok(); let blank_url = ServoUrl::parse("about:blank").ok(); @@ -943,7 +934,7 @@ impl ResourceReaderInstance { impl ResourceReaderMethods for ResourceReaderInstance { fn read(&self, res: Resource) -> Vec { Vec::from(match res { - Resource::Preferences => &include_bytes!("../../../../resources/prefs.json")[..], + Resource::Preferences => &include_bytes!(concat!(env!("OUT_DIR"), "/prefs.json"))[..], Resource::HstsPreloadList => { &include_bytes!("../../../../resources/hsts_preload.json")[..] }, diff --git a/ports/libsimpleservo/capi/src/lib.rs b/ports/libsimpleservo/capi/src/lib.rs index 01044cf70c2..9bace40a29d 100644 --- a/ports/libsimpleservo/capi/src/lib.rs +++ b/ports/libsimpleservo/capi/src/lib.rs @@ -243,7 +243,6 @@ pub struct CInitOptions { pub width: i32, pub height: i32, pub density: f32, - pub enable_subpixel_text_antialiasing: bool, pub vslogger_mod_list: *const *const c_char, pub vslogger_mod_size: u32, pub native_widget: *mut c_void, @@ -446,7 +445,6 @@ unsafe fn init( prefs, density: opts.density, xr_discovery: None, - enable_subpixel_text_antialiasing: opts.enable_subpixel_text_antialiasing, gl_context_pointer: gl_context, native_display_pointer: display, native_widget: opts.native_widget, diff --git a/resources/package-prefs.json b/resources/package-prefs.json index d419d7e4586..035f08714ee 100644 --- a/resources/package-prefs.json +++ b/resources/package-prefs.json @@ -5,6 +5,13 @@ "linux": {}, "android": {}, "windows": {}, + "hololens": { + "_comment": "settings specific to Hololens/UWP builds", + "devtools.server.enabled": true, + "dom.webxr.enabled": true, + "shell.homepage": "https://servo.org/hl-home/", + "gfx.subpixel-text-antialiasing.enabled": false + }, "vr": { "_comment": "settings specific to VR builds", "dom.webvr.enabled": true, diff --git a/resources/prefs.json b/resources/prefs.json index d48175de8b4..0cbf5608f90 100644 --- a/resources/prefs.json +++ b/resources/prefs.json @@ -1,4 +1,6 @@ { + "devtools.server.enabled": false, + "devtools.server.port": 0, "dom.bluetooth.enabled": false, "dom.bluetooth.testing.enabled": false, "dom.canvas_capture.enabled": false, diff --git a/support/hololens/ServoApp/DefaultUrl.h b/support/hololens/ServoApp/DefaultUrl.h index b5d82e65478..ba1719dc530 100644 --- a/support/hololens/ServoApp/DefaultUrl.h +++ b/support/hololens/ServoApp/DefaultUrl.h @@ -1,8 +1,6 @@ #pragma once -#define DEFAULT_URL_PROD L"https://servo.org/hl-home/" - // For development purpose. -// Will override DEFAULT_URL_PROD or any locally stored preferences. +// Will override shell.homepage preference: // #define OVERRIDE_DEFAULT_URL L"data:text/html," // #define OVERRIDE_DEFAULT_URL L"http://localhost:8000/test.html" diff --git a/support/hololens/ServoApp/ServoControl/Servo.cpp b/support/hololens/ServoApp/ServoControl/Servo.cpp index 6f724d4bcbb..7adef0a8511 100644 --- a/support/hololens/ServoApp/ServoControl/Servo.cpp +++ b/support/hololens/ServoApp/ServoControl/Servo.cpp @@ -147,14 +147,6 @@ Servo::Servo(std::optional initUrl, hstring args, GLsizei width, auto prefs = localSettings.Containers().Lookup(L"servoUserPrefs"); - if (!prefs.Values().HasKey(L"shell.homepage")) { - prefs.Values().Insert(L"shell.homepage", box_value(DEFAULT_URL_PROD)); - } - - if (!prefs.Values().HasKey(L"dom.webxr.enabled")) { - prefs.Values().Insert(L"dom.webxr.enabled", box_value(true)); - } - std::vector cprefs; for (auto pref : prefs.Values()) { @@ -172,22 +164,9 @@ Servo::Servo(std::optional initUrl, hstring args, GLsizei width, auto val = unbox_value(value); cpref.value = &val; } else if (type == Windows::Foundation::PropertyType::String) { - hstring strValue; - if (pref.Key() == L"shell.homepage") { - if (initUrl.has_value()) { - strValue = *initUrl; - } else { -#ifdef OVERRIDE_DEFAULT_URL - strValue = OVERRIDE_DEFAULT_URL; -#else - strValue = unbox_value(value); -#endif - } - } else { - strValue = unbox_value(value); - } cpref.pref_type = capi::CPrefType::Str; - cpref.value = *hstring2char(strValue); + auto val = unbox_value(value); + cpref.value = *hstring2char(val); } else if (type == Windows::Foundation::PropertyType::Int64) { cpref.pref_type = capi::CPrefType::Int; auto val = unbox_value(value); @@ -205,15 +184,22 @@ Servo::Servo(std::optional initUrl, hstring args, GLsizei width, cprefs.push_back(cpref); } + if (initUrl.has_value()) { + setNonPersistentHomepage(*initUrl, cprefs); + } else { +#ifdef OVERRIDE_DEFAULT_URL + setNonPersistentHomepage(OVERRIDE_DEFAULT_URL, cprefs); +#endif + } + capi::CPrefList prefsList = {cprefs.size(), cprefs.data()}; capi::CInitOptions o; o.prefs = &prefsList; - o.args = *hstring2char(args + L" --devtools"); + o.args = *hstring2char(args); o.width = mWindowWidth; o.height = mWindowHeight; o.density = dpi; - o.enable_subpixel_text_antialiasing = false; o.native_widget = eglNativeWindow; // Note about logs: @@ -385,6 +371,20 @@ std::vector Servo::GetPrefs() { return vec; } +void setNonPersistentHomepage(hstring url, std::vector &cprefs) { + for (auto cpref : cprefs) { + if (strcmp(cpref.key, "shell.homepage") == 0) { + cpref.value = *hstring2char(url); + return; + } + } + capi::CPref cpref; + cpref.key = "shell.homepage"; + cpref.pref_type = capi::CPrefType::Str; + cpref.value = *hstring2char(url); + cprefs.push_back(cpref); +} + winrt::hstring char2hstring(const char *c_str) { // FIXME: any better way of doing this? auto str = std::string(c_str); diff --git a/support/hololens/ServoApp/ServoControl/Servo.h b/support/hololens/ServoApp/ServoControl/Servo.h index 2d8e3b0f091..e6eaf428be1 100644 --- a/support/hololens/ServoApp/ServoControl/Servo.h +++ b/support/hololens/ServoApp/ServoControl/Servo.h @@ -21,6 +21,7 @@ using namespace capi; hstring char2hstring(const char *); std::unique_ptr hstring2char(hstring); +void setNonPersistentHomepage(hstring, std::vector &); class ServoDelegate; diff --git a/support/hololens/ServoApp/ServoControl/ServoControl.cpp b/support/hololens/ServoApp/ServoControl/ServoControl.cpp index db4710f0606..d0d1e814e91 100644 --- a/support/hololens/ServoApp/ServoControl/ServoControl.cpp +++ b/support/hololens/ServoApp/ServoControl/ServoControl.cpp @@ -661,6 +661,8 @@ void ServoControl::OnServoDevtoolsStarted(bool success, const unsigned int port, hstring token) { RunOnUIThread([=] { auto status = success ? DevtoolsStatus::Running : DevtoolsStatus::Failed; + // This port works, let's save it for future use. + Servo::SetIntPref(L"devtools.server.port", port); mOnDevtoolsStatusChangedEvent(status, port, token); }); }