Auto merge of #25288 - jdm:devtools-revival, r=manishearth

Update devtools server for Firefox 71.

Based on reading code under https://searchfox.org/mozilla-central/source/devtools/shared/specs/, https://searchfox.org/mozilla-central/source/devtools/shared/front/, https://searchfox.org/mozilla-central/source/devtools/shared/specs/, and https://searchfox.org/mozilla-central/source/devtools/server/actors/, as well as dumping the protocol output when using Firefox to debug itself. This makes the JS console usable again in nightly Firefox from about:debugging.

---
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix #24092
- [x] These changes do not require tests because ha ha ha devtools tests.
This commit is contained in:
bors-servo 2019-12-13 20:59:49 -05:00 committed by GitHub
commit ecaf65408c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 339 additions and 21 deletions

View file

@ -15,7 +15,18 @@ use serde_json::{Map, Value};
use std::net::TcpStream; use std::net::TcpStream;
#[derive(Serialize)] #[derive(Serialize)]
struct BrowsingContextTraits; struct BrowsingContextTraits {
isBrowsingContext: bool,
}
#[derive(Serialize)]
struct AttachedTraits {
reconfigure: bool,
frames: bool,
logInPage: bool,
canRewind: bool,
watchpoints: bool,
}
#[derive(Serialize)] #[derive(Serialize)]
struct BrowsingContextAttachedReply { struct BrowsingContextAttachedReply {
@ -25,7 +36,7 @@ struct BrowsingContextAttachedReply {
threadActor: String, threadActor: String,
cacheDisabled: bool, cacheDisabled: bool,
javascriptEnabled: bool, javascriptEnabled: bool,
traits: BrowsingContextTraits, traits: AttachedTraits,
} }
#[derive(Serialize)] #[derive(Serialize)]
@ -71,6 +82,7 @@ pub struct BrowsingContextActorMsg {
title: String, title: String,
url: String, url: String,
outerWindowID: u32, outerWindowID: u32,
browsingContextId: u32,
consoleActor: String, consoleActor: String,
emulationActor: String, emulationActor: String,
inspectorActor: String, inspectorActor: String,
@ -78,6 +90,20 @@ pub struct BrowsingContextActorMsg {
profilerActor: String, profilerActor: String,
performanceActor: String, performanceActor: String,
styleSheetsActor: String, styleSheetsActor: String,
traits: BrowsingContextTraits,
// Part of the official protocol, but not yet implemented.
/*storageActor: String,
memoryActor: String,
framerateActor: String,
reflowActor: String,
cssPropertiesActor: String,
animationsActor: String,
webExtensionInspectedWindowActor: String,
accessibilityActor: String,
screenshotActor: String,
changesActor: String,
webSocketActor: String,
manifestActor: String,*/
} }
pub struct BrowsingContextActor { pub struct BrowsingContextActor {
@ -127,11 +153,17 @@ impl Actor for BrowsingContextActor {
"attach" => { "attach" => {
let msg = BrowsingContextAttachedReply { let msg = BrowsingContextAttachedReply {
from: self.name(), from: self.name(),
type_: "targetAttached".to_owned(), type_: "tabAttached".to_owned(),
threadActor: self.thread.clone(), threadActor: self.thread.clone(),
cacheDisabled: false, cacheDisabled: false,
javascriptEnabled: true, javascriptEnabled: true,
traits: BrowsingContextTraits, traits: AttachedTraits {
reconfigure: false,
frames: false,
logInPage: false,
canRewind: false,
watchpoints: false,
},
}; };
let console_actor = registry.find::<ConsoleActor>(&self.console); let console_actor = registry.find::<ConsoleActor>(&self.console);
console_actor console_actor
@ -166,7 +198,12 @@ impl Actor for BrowsingContextActor {
"listFrames" => { "listFrames" => {
let msg = ListFramesReply { let msg = ListFramesReply {
from: self.name(), from: self.name(),
frames: vec![], frames: vec![FrameMsg {
id: 0, //FIXME should match outerwindow id
parentID: 0,
url: self.url.clone(),
title: self.title.clone(),
}],
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed
@ -190,8 +227,12 @@ impl BrowsingContextActor {
pub fn encodable(&self) -> BrowsingContextActorMsg { pub fn encodable(&self) -> BrowsingContextActorMsg {
BrowsingContextActorMsg { BrowsingContextActorMsg {
actor: self.name(), actor: self.name(),
traits: BrowsingContextTraits {
isBrowsingContext: true,
},
title: self.title.clone(), title: self.title.clone(),
url: self.url.clone(), url: self.url.clone(),
browsingContextId: 0, //FIXME should come from constellation
outerWindowID: 0, //FIXME: this should probably be the pipeline id outerWindowID: 0, //FIXME: this should probably be the pipeline id
consoleActor: self.console.clone(), consoleActor: self.console.clone(),
emulationActor: self.emulation.clone(), emulationActor: self.emulation.clone(),

View file

@ -39,9 +39,7 @@ impl EncodableConsoleMessage for CachedConsoleMessage {
} }
#[derive(Serialize)] #[derive(Serialize)]
struct StartedListenersTraits { struct StartedListenersTraits;
customNetworkRequest: bool,
}
#[derive(Serialize)] #[derive(Serialize)]
struct StartedListenersReply { struct StartedListenersReply {
@ -309,13 +307,15 @@ impl Actor for ConsoleActor {
"startListeners" => { "startListeners" => {
//TODO: actually implement listener filters that support starting/stopping //TODO: actually implement listener filters that support starting/stopping
let listeners = msg.get("listeners").unwrap().as_array().unwrap().to_owned();
let msg = StartedListenersReply { let msg = StartedListenersReply {
from: self.name(), from: self.name(),
nativeConsoleAPI: true, nativeConsoleAPI: true,
startedListeners: vec!["PageError".to_owned(), "ConsoleAPI".to_owned()], startedListeners: listeners
traits: StartedListenersTraits { .into_iter()
customNetworkRequest: true, .map(|s| s.as_str().unwrap().to_owned())
}, .collect(),
traits: StartedListenersTraits,
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
ActorMessageStatus::Processed ActorMessageStatus::Processed

View file

@ -41,7 +41,7 @@ impl Actor for DeviceActor {
from: self.name(), from: self.name(),
value: SystemInfo { value: SystemInfo {
apptype: "servo".to_string(), apptype: "servo".to_string(),
platformVersion: "63.0".to_string(), platformVersion: "71.0".to_string(),
}, },
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);

View file

@ -0,0 +1,81 @@
/* 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 https://mozilla.org/MPL/2.0/. */
use crate::actor::{Actor, ActorMessageStatus, ActorRegistry};
use crate::protocol::JsonPacketStream;
use serde_json::{Map, Value};
use std::net::TcpStream;
pub struct PreferenceActor {
name: String,
}
impl PreferenceActor {
pub fn new(name: String) -> Self {
Self { name }
}
}
impl Actor for PreferenceActor {
fn name(&self) -> String {
self.name.clone()
}
fn handle_message(
&self,
_registry: &ActorRegistry,
msg_type: &str,
_msg: &Map<String, Value>,
stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(match msg_type {
"getBoolPref" => {
let reply = BoolReply {
from: self.name(),
value: false,
};
stream.write_json_packet(&reply);
ActorMessageStatus::Processed
},
"getCharPref" => {
let reply = CharReply {
from: self.name(),
value: "".to_owned(),
};
stream.write_json_packet(&reply);
ActorMessageStatus::Processed
},
"getIntPref" => {
let reply = IntReply {
from: self.name(),
value: 0,
};
stream.write_json_packet(&reply);
ActorMessageStatus::Processed
},
_ => ActorMessageStatus::Ignored,
})
}
}
#[derive(Serialize)]
struct BoolReply {
from: String,
value: bool,
}
#[derive(Serialize)]
struct CharReply {
from: String,
value: String,
}
#[derive(Serialize)]
struct IntReply {
from: String,
value: i32,
}

View file

@ -0,0 +1,51 @@
/* 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 https://mozilla.org/MPL/2.0/. */
use crate::actor::{Actor, ActorMessageStatus, ActorRegistry};
use crate::protocol::JsonPacketStream;
use serde_json::{Map, Value};
use std::net::TcpStream;
#[derive(Serialize)]
struct ListWorkersReply {
from: String,
workers: Vec<u32>, // TODO: use proper JSON structure.
}
pub struct ProcessActor {
name: String,
}
impl ProcessActor {
pub fn new(name: String) -> Self {
Self { name }
}
}
impl Actor for ProcessActor {
fn name(&self) -> String {
self.name.clone()
}
fn handle_message(
&self,
_registry: &ActorRegistry,
msg_type: &str,
_msg: &Map<String, Value>,
stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> {
Ok(match msg_type {
"listWorkers" => {
let reply = ListWorkersReply {
from: self.name(),
workers: vec![],
};
stream.write_json_packet(&reply);
ActorMessageStatus::Processed
},
_ => ActorMessageStatus::Ignored,
})
}
}

View file

@ -37,6 +37,7 @@ struct GetRootReply {
selected: u32, selected: u32,
performanceActor: String, performanceActor: String,
deviceActor: String, deviceActor: String,
preferenceActor: String,
} }
#[derive(Serialize)] #[derive(Serialize)]
@ -46,6 +47,12 @@ struct ListTabsReply {
tabs: Vec<BrowsingContextActorMsg>, tabs: Vec<BrowsingContextActorMsg>,
} }
#[derive(Serialize)]
struct GetTabReply {
from: String,
tab: BrowsingContextActorMsg,
}
#[derive(Serialize)] #[derive(Serialize)]
pub struct RootActorMsg { pub struct RootActorMsg {
from: String, from: String,
@ -59,16 +66,54 @@ pub struct ProtocolDescriptionReply {
types: Types, types: Types,
} }
#[derive(Serialize)]
struct ListWorkersReply {
from: String,
workers: Vec<WorkerMsg>,
}
#[derive(Serialize)]
struct WorkerMsg {
id: u32,
}
#[derive(Serialize)]
struct ListServiceWorkerRegistrationsReply {
from: String,
registrations: Vec<u32>, // TODO: follow actual JSON structure.
}
#[derive(Serialize)] #[derive(Serialize)]
pub struct Types { pub struct Types {
performance: ActorDescription, performance: ActorDescription,
device: ActorDescription, device: ActorDescription,
} }
#[derive(Serialize)]
struct ListProcessesResponse {
from: String,
processes: Vec<ProcessForm>,
}
#[derive(Serialize)]
struct ProcessForm {
actor: String,
id: u32,
isParent: bool,
}
#[derive(Serialize)]
struct GetProcessResponse {
from: String,
form: ProcessForm,
}
pub struct RootActor { pub struct RootActor {
pub tabs: Vec<String>, pub tabs: Vec<String>,
pub performance: String, pub performance: String,
pub device: String, pub device: String,
pub preference: String,
pub process: String,
} }
impl Actor for RootActor { impl Actor for RootActor {
@ -93,12 +138,39 @@ impl Actor for RootActor {
ActorMessageStatus::Processed ActorMessageStatus::Processed
}, },
"listProcesses" => {
let reply = ListProcessesResponse {
from: self.name(),
processes: vec![ProcessForm {
actor: self.process.clone(),
id: 0,
isParent: true,
}],
};
stream.write_json_packet(&reply);
ActorMessageStatus::Processed
},
"getProcess" => {
let reply = GetProcessResponse {
from: self.name(),
form: ProcessForm {
actor: self.process.clone(),
id: 0,
isParent: true,
},
};
stream.write_json_packet(&reply);
ActorMessageStatus::Processed
},
"getRoot" => { "getRoot" => {
let actor = GetRootReply { let actor = GetRootReply {
from: "root".to_owned(), from: "root".to_owned(),
selected: 0, selected: 0,
performanceActor: self.performance.clone(), performanceActor: self.performance.clone(),
deviceActor: self.device.clone(), deviceActor: self.device.clone(),
preferenceActor: self.preference.clone(),
}; };
stream.write_json_packet(&actor); stream.write_json_packet(&actor);
ActorMessageStatus::Processed ActorMessageStatus::Processed
@ -119,6 +191,34 @@ impl Actor for RootActor {
ActorMessageStatus::Processed ActorMessageStatus::Processed
}, },
"listServiceWorkerRegistrations" => {
let reply = ListServiceWorkerRegistrationsReply {
from: self.name(),
registrations: vec![],
};
stream.write_json_packet(&reply);
ActorMessageStatus::Processed
},
"listWorkers" => {
let reply = ListWorkersReply {
from: self.name(),
workers: vec![],
};
stream.write_json_packet(&reply);
ActorMessageStatus::Processed
},
"getTab" => {
let tab = registry.find::<BrowsingContextActor>(&self.tabs[0]);
let reply = GetTabReply {
from: self.name(),
tab: tab.encodable(),
};
stream.write_json_packet(&reply);
ActorMessageStatus::Processed
},
"protocolDescription" => { "protocolDescription" => {
let msg = ProtocolDescriptionReply { let msg = ProtocolDescriptionReply {
from: self.name(), from: self.name(),

View file

@ -3,9 +3,16 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::actor::{Actor, ActorMessageStatus, ActorRegistry}; use crate::actor::{Actor, ActorMessageStatus, ActorRegistry};
use crate::protocol::JsonPacketStream;
use serde_json::{Map, Value}; use serde_json::{Map, Value};
use std::net::TcpStream; use std::net::TcpStream;
#[derive(Serialize)]
struct GetStyleSheetsReply {
from: String,
styleSheets: Vec<u32>, // TODO: real JSON structure.
}
pub struct StyleSheetsActor { pub struct StyleSheetsActor {
pub name: String, pub name: String,
} }
@ -16,12 +23,23 @@ impl Actor for StyleSheetsActor {
} }
fn handle_message( fn handle_message(
&self, &self,
_: &ActorRegistry, _registry: &ActorRegistry,
_: &str, msg_type: &str,
_: &Map<String, Value>, _msg: &Map<String, Value>,
_: &mut TcpStream, stream: &mut TcpStream,
) -> Result<ActorMessageStatus, ()> { ) -> Result<ActorMessageStatus, ()> {
Ok(ActorMessageStatus::Ignored) Ok(match msg_type {
"getStyleSheets" => {
let msg = GetStyleSheetsReply {
from: self.name(),
styleSheets: vec![],
};
stream.write_json_packet(&msg);
ActorMessageStatus::Processed
},
_ => ActorMessageStatus::Ignored,
})
} }
} }

View file

@ -8,11 +8,15 @@ use serde_json::{Map, Value};
use std::net::TcpStream; use std::net::TcpStream;
#[derive(Serialize)] #[derive(Serialize)]
struct ThreadAttachedReply { struct ThreadAttached {
from: String, from: String,
#[serde(rename = "type")] #[serde(rename = "type")]
type_: String, type_: String,
actor: String, actor: String,
frame: u32,
error: u32,
recordingEndpoint: u32,
executionPoint: u32,
poppedFrames: Vec<PoppedFrameMsg>, poppedFrames: Vec<PoppedFrameMsg>,
why: WhyMsg, why: WhyMsg,
} }
@ -54,6 +58,11 @@ struct SourcesReply {
#[derive(Serialize)] #[derive(Serialize)]
enum Source {} enum Source {}
#[derive(Serialize)]
struct VoidAttachedReply {
from: String,
}
pub struct ThreadActor { pub struct ThreadActor {
name: String, name: String,
} }
@ -78,16 +87,21 @@ impl Actor for ThreadActor {
) -> Result<ActorMessageStatus, ()> { ) -> Result<ActorMessageStatus, ()> {
Ok(match msg_type { Ok(match msg_type {
"attach" => { "attach" => {
let msg = ThreadAttachedReply { let msg = ThreadAttached {
from: self.name(), from: self.name(),
type_: "paused".to_owned(), type_: "paused".to_owned(),
actor: registry.new_name("pause"), actor: registry.new_name("pause"),
frame: 0,
error: 0,
recordingEndpoint: 0,
executionPoint: 0,
poppedFrames: vec![], poppedFrames: vec![],
why: WhyMsg { why: WhyMsg {
type_: "attached".to_owned(), type_: "attached".to_owned(),
}, },
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
stream.write_json_packet(&VoidAttachedReply { from: self.name() });
ActorMessageStatus::Processed ActorMessageStatus::Processed
}, },
@ -97,6 +111,7 @@ impl Actor for ThreadActor {
type_: "resumed".to_owned(), type_: "resumed".to_owned(),
}; };
stream.write_json_packet(&msg); stream.write_json_packet(&msg);
stream.write_json_packet(&VoidAttachedReply { from: self.name() });
ActorMessageStatus::Processed ActorMessageStatus::Processed
}, },

View file

@ -26,6 +26,8 @@ use crate::actors::framerate::FramerateActor;
use crate::actors::inspector::InspectorActor; use crate::actors::inspector::InspectorActor;
use crate::actors::network_event::{EventActor, NetworkEventActor, ResponseStartMsg}; use crate::actors::network_event::{EventActor, NetworkEventActor, ResponseStartMsg};
use crate::actors::performance::PerformanceActor; use crate::actors::performance::PerformanceActor;
use crate::actors::preference::PreferenceActor;
use crate::actors::process::ProcessActor;
use crate::actors::profiler::ProfilerActor; use crate::actors::profiler::ProfilerActor;
use crate::actors::root::RootActor; use crate::actors::root::RootActor;
use crate::actors::stylesheets::StyleSheetsActor; use crate::actors::stylesheets::StyleSheetsActor;
@ -60,6 +62,8 @@ mod actors {
pub mod network_event; pub mod network_event;
pub mod object; pub mod object;
pub mod performance; pub mod performance;
pub mod preference;
pub mod process;
pub mod profiler; pub mod profiler;
pub mod root; pub mod root;
pub mod stylesheets; pub mod stylesheets;
@ -156,15 +160,23 @@ fn run_server(
let device = DeviceActor::new(registry.new_name("device")); let device = DeviceActor::new(registry.new_name("device"));
let preference = PreferenceActor::new(registry.new_name("preference"));
let process = ProcessActor::new(registry.new_name("process"));
let root = Box::new(RootActor { let root = Box::new(RootActor {
tabs: vec![], tabs: vec![],
device: device.name(), device: device.name(),
performance: performance.name(), performance: performance.name(),
preference: preference.name(),
process: process.name(),
}); });
registry.register(root); registry.register(root);
registry.register(Box::new(performance)); registry.register(Box::new(performance));
registry.register(Box::new(device)); registry.register(Box::new(device));
registry.register(Box::new(preference));
registry.register(Box::new(process));
registry.find::<RootActor>("root"); registry.find::<RootActor>("root");
let actors = registry.create_shareable(); let actors = registry.create_shareable();