From 00fa5d3088e2de170ee3d4642aef8d854f0665de Mon Sep 17 00:00:00 2001 From: Narfinger Date: Thu, 19 Feb 2026 12:24:56 +0900 Subject: [PATCH] devtools: Allow specifiying an address to listen to and default to localhost (#42502) Previously we listened to 0.0.0.0. which means any connection coming to a specific port. That seems a bit ill advised as not everybody has a good firewall setup. Now we default listen only on 127.0.0.1 but optionally can describe a full SocketAddr such as "192.168.1.23:1234". Side note: Cleaned up the ipc-channel syntax. Signed-off-by: Narfinger Testing: Currently we don't have an automatic way to test this. Manually run devtools and it connects. --------- Signed-off-by: Narfinger --- Cargo.toml | 2 +- components/config/prefs.rs | 7 +++---- components/devtools/lib.rs | 28 +++++++++++++++++++++------- components/servo/servo.rs | 1 - ports/servoshell/prefs.rs | 10 +++++----- 5 files changed, 30 insertions(+), 18 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 82de3f1815d..0c5f68681c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -111,7 +111,7 @@ icu_segmenter = "1.5.0" image = { version = "0.25", default-features = false, features = ["avif", "rayon", "bmp", "gif", "ico", "jpeg", "png", "webp"] } imsz = "0.4" indexmap = { version = "2.11.4", features = ["std"] } -ipc-channel = { version = "0.21" } +ipc-channel = "0.21" itertools = "0.14" js = { package = "mozjs", version = "=0.15.0", default-features = false, features = ["libz-sys", "intl"] } keyboard-types = { version = "0.8.3", features = ["serde", "webdriver"] } diff --git a/components/config/prefs.rs b/components/config/prefs.rs index 817ccaff44e..43f91a94dc4 100644 --- a/components/config/prefs.rs +++ b/components/config/prefs.rs @@ -87,9 +87,8 @@ pub struct Preferences { pub css_animations_testing_enabled: bool, /// Start the devtools server at startup pub devtools_server_enabled: bool, - /// Port number to start a server to listen to remote Firefox devtools connections. - /// 0 for random port. - pub devtools_server_port: i64, + /// The address +port the devtools server listens to, default to 127.0.0.1:7000. + pub devtools_server_listen_address: String, // feature: WebGPU | #24706 | Web/API/WebGPU_API pub dom_webgpu_enabled: bool, /// List of comma-separated backends to be used by wgpu. @@ -342,7 +341,7 @@ impl Preferences { Self { css_animations_testing_enabled: false, devtools_server_enabled: false, - devtools_server_port: 0, + devtools_server_listen_address: String::new(), dom_abort_controller_enabled: true, dom_adoptedstylesheet_enabled: false, dom_allow_scripts_to_close_windows: false, diff --git a/components/devtools/lib.rs b/components/devtools/lib.rs index d905a12519e..1fff670fd79 100644 --- a/components/devtools/lib.rs +++ b/components/devtools/lib.rs @@ -14,7 +14,8 @@ use std::borrow::ToOwned; use std::collections::HashMap; use std::io::Read; -use std::net::{Shutdown, TcpListener, TcpStream}; +use std::net::{Ipv4Addr, Shutdown, SocketAddr, TcpListener, TcpStream}; +use std::str::FromStr; use std::sync::{Arc, Mutex}; use std::thread; @@ -36,6 +37,7 @@ use rand::{RngCore, rng}; use resource::{ResourceArrayType, ResourceAvailable}; use rustc_hash::FxHashMap; use serde::Serialize; +use servo_config::pref; use crate::actor::{Actor, ActorError, ActorRegistry}; use crate::actors::browsing_context::BrowsingContextActor; @@ -110,7 +112,6 @@ pub(crate) struct ActorMsg { /// Spin up a devtools server that listens for connections on the specified port. pub fn start_server( - port: u16, embedder: EmbedderProxy, mem_profiler_chan: ProfilerChan, ) -> Sender { @@ -123,8 +124,7 @@ pub fn start_server( .spawn(move || { mem_profiler_chan.run_with_memory_reporting( || { - if let Some(instance) = - DevtoolsInstance::create(sender, receiver, port, embedder) + if let Some(instance) = DevtoolsInstance::create(sender, receiver, embedder) { instance.run() } @@ -172,10 +172,20 @@ impl DevtoolsInstance { fn create( sender: Sender, receiver: Receiver, - port: u16, embedder: EmbedderProxy, ) -> Option { - let bound = TcpListener::bind(("0.0.0.0", port)).ok().and_then(|l| { + let address = if pref!(devtools_server_listen_address).is_empty() { + SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), 7000) + } else if let Ok(addr) = SocketAddr::from_str(&pref!(devtools_server_listen_address)) { + addr + } else if let Ok(port) = pref!(devtools_server_listen_address).parse() { + SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port) + } else { + SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), 7000) + }; + println!("Binding devtools to {address}"); + + let bound = TcpListener::bind(address).ok().and_then(|l| { l.local_addr() .map(|addr| addr.port()) .ok() @@ -183,7 +193,11 @@ impl DevtoolsInstance { }); // A token shared with the embedder to bypass permission prompt. - let port = if bound.is_some() { Ok(port) } else { Err(()) }; + let port = if bound.is_some() { + Ok(address.port()) + } else { + Err(()) + }; let token = format!("{:X}", rng().next_u32()); embedder.send(EmbedderMsg::OnDevtoolsStarted(port, token.clone())); diff --git a/components/servo/servo.rs b/components/servo/servo.rs index 5f281d6dd24..bec81afd6da 100644 --- a/components/servo/servo.rs +++ b/components/servo/servo.rs @@ -769,7 +769,6 @@ impl Servo { let devtools_sender = if pref!(devtools_server_enabled) { Some(devtools::start_server( - pref!(devtools_server_port) as u16, embedder_proxy.clone(), mem_profiler_chan.clone(), )) diff --git a/ports/servoshell/prefs.rs b/ports/servoshell/prefs.rs index 83b8019250a..d9860f4339b 100644 --- a/ports/servoshell/prefs.rs +++ b/ports/servoshell/prefs.rs @@ -407,9 +407,9 @@ struct CmdArgs { #[bpaf(argument("1.0"))] device_pixel_ratio: Option, - /// Start remote devtools server on port. - #[bpaf(argument("0"))] - devtools: Option, + /// Start remote devtools server on port listening on this address.
: and are valid values. + #[bpaf(argument("127.0.0.1:7000"))] + devtools: Option, /// /// Whether or not to enable experimental web platform features. @@ -569,9 +569,9 @@ fn update_preferences_from_command_line_arguemnts( preferences: &mut Preferences, cmd_args: &CmdArgs, ) { - if let Some(port) = cmd_args.devtools { + if let Some(listen_address) = &cmd_args.devtools { preferences.devtools_server_enabled = true; - preferences.devtools_server_port = port as i64; + preferences.devtools_server_listen_address = listen_address.clone(); } if cmd_args.enable_experimental_web_platform_features {