mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Support connecting to worker globals from remote devtools.
This commit is contained in:
parent
bce4ec5b70
commit
565e9432c6
13 changed files with 340 additions and 144 deletions
|
@ -10,7 +10,9 @@
|
|||
use crate::actor::{Actor, ActorMessageStatus, ActorRegistry};
|
||||
use crate::actors::browsing_context::BrowsingContextActor;
|
||||
use crate::actors::object::ObjectActor;
|
||||
use crate::actors::worker::WorkerActor;
|
||||
use crate::protocol::JsonPacketStream;
|
||||
use crate::UniqueId;
|
||||
use crate::{ConsoleAPICall, ConsoleMessage, ConsoleMsg, PageErrorMsg};
|
||||
use devtools_traits::CachedConsoleMessage;
|
||||
use devtools_traits::EvaluateJSReply::{ActorValue, BooleanValue, StringValue};
|
||||
|
@ -18,10 +20,10 @@ use devtools_traits::EvaluateJSReply::{NullValue, NumberValue, VoidValue};
|
|||
use devtools_traits::{
|
||||
CachedConsoleMessageTypes, ConsoleAPI, DevtoolScriptControlMsg, LogLevel, PageError,
|
||||
};
|
||||
use ipc_channel::ipc;
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use ipc_channel::ipc::{self, IpcSender};
|
||||
use msg::constellation_msg::TEST_PIPELINE_ID;
|
||||
use serde_json::{self, Map, Number, Value};
|
||||
use std::cell::RefCell;
|
||||
use std::cell::{RefCell, RefMut};
|
||||
use std::collections::HashMap;
|
||||
use std::net::TcpStream;
|
||||
use time::precise_time_ns;
|
||||
|
@ -106,25 +108,68 @@ struct SetPreferencesReply {
|
|||
updated: Vec<String>,
|
||||
}
|
||||
|
||||
pub struct ConsoleActor {
|
||||
pub(crate) enum Root {
|
||||
BrowsingContext(String),
|
||||
DedicatedWorker(String),
|
||||
}
|
||||
|
||||
pub(crate) struct ConsoleActor {
|
||||
pub name: String,
|
||||
pub browsing_context: String,
|
||||
pub cached_events: RefCell<HashMap<PipelineId, Vec<CachedConsoleMessage>>>,
|
||||
pub root: Root,
|
||||
pub cached_events: RefCell<HashMap<UniqueId, Vec<CachedConsoleMessage>>>,
|
||||
}
|
||||
|
||||
impl ConsoleActor {
|
||||
fn script_chan<'a>(
|
||||
&self,
|
||||
registry: &'a ActorRegistry,
|
||||
) -> &'a IpcSender<DevtoolScriptControlMsg> {
|
||||
match &self.root {
|
||||
Root::BrowsingContext(bc) => ®istry.find::<BrowsingContextActor>(bc).script_chan,
|
||||
Root::DedicatedWorker(worker) => ®istry.find::<WorkerActor>(worker).script_chan,
|
||||
}
|
||||
}
|
||||
|
||||
fn streams_mut<'a>(&self, registry: &'a ActorRegistry) -> RefMut<'a, Vec<TcpStream>> {
|
||||
match &self.root {
|
||||
Root::BrowsingContext(bc) => registry
|
||||
.find::<BrowsingContextActor>(bc)
|
||||
.streams
|
||||
.borrow_mut(),
|
||||
Root::DedicatedWorker(worker) => {
|
||||
registry.find::<WorkerActor>(worker).streams.borrow_mut()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn current_unique_id(&self, registry: &ActorRegistry) -> UniqueId {
|
||||
match &self.root {
|
||||
Root::BrowsingContext(bc) => UniqueId::Pipeline(
|
||||
registry
|
||||
.find::<BrowsingContextActor>(bc)
|
||||
.active_pipeline
|
||||
.get(),
|
||||
),
|
||||
Root::DedicatedWorker(w) => UniqueId::Worker(registry.find::<WorkerActor>(w).id),
|
||||
}
|
||||
}
|
||||
|
||||
fn evaluateJS(
|
||||
&self,
|
||||
registry: &ActorRegistry,
|
||||
msg: &Map<String, Value>,
|
||||
) -> Result<EvaluateJSReply, ()> {
|
||||
let browsing_context = registry.find::<BrowsingContextActor>(&self.browsing_context);
|
||||
let input = msg.get("text").unwrap().as_str().unwrap().to_owned();
|
||||
let (chan, port) = ipc::channel().unwrap();
|
||||
browsing_context
|
||||
.script_chan
|
||||
// FIXME: redesign messages so we don't have to fake pipeline ids when
|
||||
// communicating with workers.
|
||||
let pipeline = match self.current_unique_id(registry) {
|
||||
UniqueId::Pipeline(p) => p,
|
||||
UniqueId::Worker(_) => TEST_PIPELINE_ID,
|
||||
};
|
||||
self.script_chan(registry)
|
||||
.send(DevtoolScriptControlMsg::EvaluateJS(
|
||||
browsing_context.active_pipeline.get(),
|
||||
pipeline,
|
||||
input.clone(),
|
||||
chan,
|
||||
))
|
||||
|
@ -196,21 +241,21 @@ impl ConsoleActor {
|
|||
pub(crate) fn handle_page_error(
|
||||
&self,
|
||||
page_error: PageError,
|
||||
pipeline: PipelineId,
|
||||
browsing_context: &BrowsingContextActor,
|
||||
id: UniqueId,
|
||||
registry: &ActorRegistry,
|
||||
) {
|
||||
self.cached_events
|
||||
.borrow_mut()
|
||||
.entry(pipeline)
|
||||
.entry(id.clone())
|
||||
.or_insert(vec![])
|
||||
.push(CachedConsoleMessage::PageError(page_error.clone()));
|
||||
if browsing_context.active_pipeline.get() == pipeline {
|
||||
if id == self.current_unique_id(registry) {
|
||||
let msg = PageErrorMsg {
|
||||
from: self.name(),
|
||||
type_: "pageError".to_owned(),
|
||||
pageError: page_error,
|
||||
};
|
||||
for stream in &mut *browsing_context.streams.borrow_mut() {
|
||||
for stream in &mut *self.streams_mut(registry) {
|
||||
stream.write_json_packet(&msg);
|
||||
}
|
||||
}
|
||||
|
@ -219,8 +264,8 @@ impl ConsoleActor {
|
|||
pub(crate) fn handle_console_api(
|
||||
&self,
|
||||
console_message: ConsoleMessage,
|
||||
pipeline: PipelineId,
|
||||
browsing_context: &BrowsingContextActor,
|
||||
id: UniqueId,
|
||||
registry: &ActorRegistry,
|
||||
) {
|
||||
let level = match console_message.logLevel {
|
||||
LogLevel::Debug => "debug",
|
||||
|
@ -232,7 +277,7 @@ impl ConsoleActor {
|
|||
.to_owned();
|
||||
self.cached_events
|
||||
.borrow_mut()
|
||||
.entry(pipeline)
|
||||
.entry(id.clone())
|
||||
.or_insert(vec![])
|
||||
.push(CachedConsoleMessage::ConsoleAPI(ConsoleAPI {
|
||||
type_: "ConsoleAPI".to_owned(),
|
||||
|
@ -244,7 +289,7 @@ impl ConsoleActor {
|
|||
private: false,
|
||||
arguments: vec![console_message.message.clone()],
|
||||
}));
|
||||
if browsing_context.active_pipeline.get() == pipeline {
|
||||
if id == self.current_unique_id(registry) {
|
||||
let msg = ConsoleAPICall {
|
||||
from: self.name(),
|
||||
type_: "consoleAPICall".to_owned(),
|
||||
|
@ -257,7 +302,7 @@ impl ConsoleActor {
|
|||
columnNumber: console_message.columnNumber,
|
||||
},
|
||||
};
|
||||
for stream in &mut *browsing_context.streams.borrow_mut() {
|
||||
for stream in &mut *self.streams_mut(registry) {
|
||||
stream.write_json_packet(&msg);
|
||||
}
|
||||
}
|
||||
|
@ -278,11 +323,11 @@ impl Actor for ConsoleActor {
|
|||
) -> Result<ActorMessageStatus, ()> {
|
||||
Ok(match msg_type {
|
||||
"clearMessagesCache" => {
|
||||
let browsing_context =
|
||||
registry.find::<BrowsingContextActor>(&self.browsing_context);
|
||||
self.cached_events.borrow_mut().remove(&browsing_context.active_pipeline.get());
|
||||
self.cached_events
|
||||
.borrow_mut()
|
||||
.remove(&self.current_unique_id(registry));
|
||||
ActorMessageStatus::Processed
|
||||
}
|
||||
},
|
||||
|
||||
"getCachedMessages" => {
|
||||
let str_types = msg
|
||||
|
@ -302,13 +347,11 @@ impl Actor for ConsoleActor {
|
|||
s => debug!("unrecognized message type requested: \"{}\"", s),
|
||||
};
|
||||
}
|
||||
let browsing_context =
|
||||
registry.find::<BrowsingContextActor>(&self.browsing_context);
|
||||
let mut messages = vec![];
|
||||
for event in self
|
||||
.cached_events
|
||||
.borrow()
|
||||
.get(&browsing_context.active_pipeline.get())
|
||||
.get(&self.current_unique_id(registry))
|
||||
.unwrap_or(&vec![])
|
||||
.iter()
|
||||
{
|
||||
|
|
|
@ -10,6 +10,7 @@ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry};
|
|||
use crate::actors::browsing_context::{BrowsingContextActor, BrowsingContextActorMsg};
|
||||
use crate::actors::device::DeviceActor;
|
||||
use crate::actors::performance::PerformanceActor;
|
||||
use crate::actors::worker::{WorkerActor, WorkerMsg};
|
||||
use crate::protocol::{ActorDescription, JsonPacketStream};
|
||||
use serde_json::{Map, Value};
|
||||
use std::net::TcpStream;
|
||||
|
@ -72,11 +73,6 @@ struct ListWorkersReply {
|
|||
workers: Vec<WorkerMsg>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct WorkerMsg {
|
||||
id: u32,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ListServiceWorkerRegistrationsReply {
|
||||
from: String,
|
||||
|
@ -110,6 +106,7 @@ struct GetProcessResponse {
|
|||
|
||||
pub struct RootActor {
|
||||
pub tabs: Vec<String>,
|
||||
pub workers: Vec<String>,
|
||||
pub performance: String,
|
||||
pub device: String,
|
||||
pub preference: String,
|
||||
|
@ -203,7 +200,11 @@ impl Actor for RootActor {
|
|||
"listWorkers" => {
|
||||
let reply = ListWorkersReply {
|
||||
from: self.name(),
|
||||
workers: vec![],
|
||||
workers: self
|
||||
.workers
|
||||
.iter()
|
||||
.map(|name| registry.find::<WorkerActor>(name).encodable())
|
||||
.collect(),
|
||||
};
|
||||
stream.write_json_packet(&reply);
|
||||
ActorMessageStatus::Processed
|
||||
|
|
|
@ -3,14 +3,49 @@
|
|||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::actor::{Actor, ActorMessageStatus, ActorRegistry};
|
||||
use devtools_traits::WorkerId;
|
||||
use crate::protocol::JsonPacketStream;
|
||||
use devtools_traits::DevtoolScriptControlMsg::WantsLiveNotifications;
|
||||
use devtools_traits::{DevtoolScriptControlMsg, WorkerId};
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use msg::constellation_msg::TEST_PIPELINE_ID;
|
||||
use serde_json::{Map, Value};
|
||||
use servo_url::ServoUrl;
|
||||
use std::cell::RefCell;
|
||||
use std::net::TcpStream;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[allow(dead_code)]
|
||||
pub enum WorkerType {
|
||||
Dedicated = 0,
|
||||
Shared = 1,
|
||||
Service = 2,
|
||||
}
|
||||
|
||||
pub struct WorkerActor {
|
||||
pub name: String,
|
||||
pub console: String,
|
||||
pub thread: String,
|
||||
pub id: WorkerId,
|
||||
pub url: ServoUrl,
|
||||
pub type_: WorkerType,
|
||||
pub script_chan: IpcSender<DevtoolScriptControlMsg>,
|
||||
pub streams: RefCell<Vec<TcpStream>>,
|
||||
}
|
||||
|
||||
impl WorkerActor {
|
||||
pub(crate) fn encodable(&self) -> WorkerMsg {
|
||||
WorkerMsg {
|
||||
actor: self.name.clone(),
|
||||
consoleActor: self.console.clone(),
|
||||
threadActor: self.thread.clone(),
|
||||
id: self.id.0.to_string(),
|
||||
url: self.url.to_string(),
|
||||
traits: WorkerTraits {
|
||||
isParentInterceptEnabled: false,
|
||||
},
|
||||
type_: self.type_ as u32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Actor for WorkerActor {
|
||||
|
@ -19,11 +54,94 @@ impl Actor for WorkerActor {
|
|||
}
|
||||
fn handle_message(
|
||||
&self,
|
||||
_: &ActorRegistry,
|
||||
_: &str,
|
||||
_: &Map<String, Value>,
|
||||
_: &mut TcpStream,
|
||||
_registry: &ActorRegistry,
|
||||
msg_type: &str,
|
||||
_msg: &Map<String, Value>,
|
||||
stream: &mut TcpStream,
|
||||
) -> Result<ActorMessageStatus, ()> {
|
||||
Ok(ActorMessageStatus::Processed)
|
||||
Ok(match msg_type {
|
||||
"attach" => {
|
||||
let msg = AttachedReply {
|
||||
from: self.name(),
|
||||
type_: "attached".to_owned(),
|
||||
url: self.url.as_str().to_owned(),
|
||||
};
|
||||
self.streams.borrow_mut().push(stream.try_clone().unwrap());
|
||||
stream.write_json_packet(&msg);
|
||||
// FIXME: fix messages to not require forging a pipeline for worker messages
|
||||
self.script_chan
|
||||
.send(WantsLiveNotifications(TEST_PIPELINE_ID, true))
|
||||
.unwrap();
|
||||
ActorMessageStatus::Processed
|
||||
},
|
||||
|
||||
"connect" => {
|
||||
let msg = ConnectReply {
|
||||
from: self.name(),
|
||||
type_: "connected".to_owned(),
|
||||
threadActor: self.thread.clone(),
|
||||
consoleActor: self.console.clone(),
|
||||
};
|
||||
stream.write_json_packet(&msg);
|
||||
ActorMessageStatus::Processed
|
||||
},
|
||||
|
||||
"detach" => {
|
||||
let msg = DetachedReply {
|
||||
from: self.name(),
|
||||
type_: "detached".to_string(),
|
||||
};
|
||||
// FIXME: we should ensure we're removing the correct stream.
|
||||
self.streams.borrow_mut().pop();
|
||||
stream.write_json_packet(&msg);
|
||||
self.script_chan
|
||||
.send(WantsLiveNotifications(TEST_PIPELINE_ID, false))
|
||||
.unwrap();
|
||||
ActorMessageStatus::Processed
|
||||
},
|
||||
|
||||
_ => ActorMessageStatus::Ignored,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct DetachedReply {
|
||||
from: String,
|
||||
#[serde(rename = "type")]
|
||||
type_: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct AttachedReply {
|
||||
from: String,
|
||||
#[serde(rename = "type")]
|
||||
type_: String,
|
||||
url: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ConnectReply {
|
||||
from: String,
|
||||
#[serde(rename = "type")]
|
||||
type_: String,
|
||||
threadActor: String,
|
||||
consoleActor: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct WorkerTraits {
|
||||
isParentInterceptEnabled: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub(crate) struct WorkerMsg {
|
||||
actor: String,
|
||||
consoleActor: String,
|
||||
threadActor: String,
|
||||
id: String,
|
||||
url: String,
|
||||
traits: WorkerTraits,
|
||||
#[serde(rename = "type")]
|
||||
type_: u32,
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue