mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Support navigating browsing contexts in the devtools.
Break the association between pipelines and browsing context actors. Now there is one browsing context actor per actual browsing context, and individual actors keep track of known pipelines as necessary. There is also one console/performance/timeline/inspector/etc. actor per browsing context. This also centralizes more information in the browsing context actor. Rather than duplicating state for the active pipeline in actors that need to use it, each actor now remembers the name of its associated browsing context actor and obtains that state whenever it's necessary.
This commit is contained in:
parent
0540c4a284
commit
7c48644cad
9 changed files with 348 additions and 184 deletions
|
@ -8,10 +8,22 @@
|
|||
//! Supports dynamic attaching and detaching which control notifications of navigation, etc.
|
||||
|
||||
use crate::actor::{Actor, ActorMessageStatus, ActorRegistry};
|
||||
use crate::actors::console::ConsoleActor;
|
||||
use crate::actors::emulation::EmulationActor;
|
||||
use crate::actors::inspector::InspectorActor;
|
||||
use crate::actors::performance::PerformanceActor;
|
||||
use crate::actors::profiler::ProfilerActor;
|
||||
use crate::actors::root::RootActor;
|
||||
use crate::actors::stylesheets::StyleSheetsActor;
|
||||
use crate::actors::thread::ThreadActor;
|
||||
use crate::actors::timeline::TimelineActor;
|
||||
use crate::protocol::JsonPacketStream;
|
||||
use devtools_traits::DevtoolScriptControlMsg::{self, WantsLiveNotifications};
|
||||
use devtools_traits::DevtoolsPageInfo;
|
||||
use devtools_traits::NavigationState;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use msg::constellation_msg::{BrowsingContextId, PipelineId};
|
||||
use serde_json::{Map, Value};
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::net::TcpStream;
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
@ -118,6 +130,10 @@ pub struct BrowsingContextActor {
|
|||
pub performance: String,
|
||||
pub styleSheets: String,
|
||||
pub thread: String,
|
||||
pub streams: RefCell<Vec<TcpStream>>,
|
||||
pub browsing_context_id: BrowsingContextId,
|
||||
pub active_pipeline: Cell<PipelineId>,
|
||||
pub script_chan: IpcSender<DevtoolScriptControlMsg>,
|
||||
}
|
||||
|
||||
impl Actor for BrowsingContextActor {
|
||||
|
@ -127,7 +143,7 @@ impl Actor for BrowsingContextActor {
|
|||
|
||||
fn handle_message(
|
||||
&self,
|
||||
registry: &ActorRegistry,
|
||||
_registry: &ActorRegistry,
|
||||
msg_type: &str,
|
||||
msg: &Map<String, Value>,
|
||||
stream: &mut TcpStream,
|
||||
|
@ -137,10 +153,9 @@ impl Actor for BrowsingContextActor {
|
|||
if let Some(options) = msg.get("options").and_then(|o| o.as_object()) {
|
||||
if let Some(val) = options.get("performReload") {
|
||||
if val.as_bool().unwrap_or(false) {
|
||||
let console_actor = registry.find::<ConsoleActor>(&self.console);
|
||||
let _ = console_actor
|
||||
let _ = self
|
||||
.script_chan
|
||||
.send(DevtoolScriptControlMsg::Reload(console_actor.pipeline));
|
||||
.send(DevtoolScriptControlMsg::Reload(self.active_pipeline.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -165,32 +180,25 @@ impl Actor for BrowsingContextActor {
|
|||
watchpoints: false,
|
||||
},
|
||||
};
|
||||
let console_actor = registry.find::<ConsoleActor>(&self.console);
|
||||
console_actor
|
||||
.streams
|
||||
.borrow_mut()
|
||||
.push(stream.try_clone().unwrap());
|
||||
self.streams.borrow_mut().push(stream.try_clone().unwrap());
|
||||
stream.write_json_packet(&msg);
|
||||
console_actor
|
||||
.script_chan
|
||||
.send(WantsLiveNotifications(console_actor.pipeline, true))
|
||||
self.script_chan
|
||||
.send(WantsLiveNotifications(self.active_pipeline.get(), true))
|
||||
.unwrap();
|
||||
ActorMessageStatus::Processed
|
||||
},
|
||||
|
||||
//FIXME: The current implementation won't work for multiple connections. Need to ensure 105
|
||||
//FIXME: The current implementation won't work for multiple connections. Need to ensure
|
||||
// that the correct stream is removed.
|
||||
"detach" => {
|
||||
let msg = BrowsingContextDetachedReply {
|
||||
from: self.name(),
|
||||
type_: "detached".to_owned(),
|
||||
};
|
||||
let console_actor = registry.find::<ConsoleActor>(&self.console);
|
||||
console_actor.streams.borrow_mut().pop();
|
||||
self.streams.borrow_mut().pop();
|
||||
stream.write_json_packet(&msg);
|
||||
console_actor
|
||||
.script_chan
|
||||
.send(WantsLiveNotifications(console_actor.pipeline, false))
|
||||
self.script_chan
|
||||
.send(WantsLiveNotifications(self.active_pipeline.get(), false))
|
||||
.unwrap();
|
||||
ActorMessageStatus::Processed
|
||||
},
|
||||
|
@ -224,6 +232,70 @@ impl Actor for BrowsingContextActor {
|
|||
}
|
||||
|
||||
impl BrowsingContextActor {
|
||||
pub(crate) fn new(
|
||||
console: String,
|
||||
id: BrowsingContextId,
|
||||
page_info: DevtoolsPageInfo,
|
||||
pipeline: PipelineId,
|
||||
script_sender: IpcSender<DevtoolScriptControlMsg>,
|
||||
actors: &mut ActorRegistry,
|
||||
) -> BrowsingContextActor {
|
||||
let emulation = EmulationActor::new(actors.new_name("emulation"));
|
||||
|
||||
let name = actors.new_name("target");
|
||||
|
||||
let inspector = InspectorActor {
|
||||
name: actors.new_name("inspector"),
|
||||
walker: RefCell::new(None),
|
||||
pageStyle: RefCell::new(None),
|
||||
highlighter: RefCell::new(None),
|
||||
script_chan: script_sender.clone(),
|
||||
browsing_context: name.clone(),
|
||||
};
|
||||
|
||||
let timeline =
|
||||
TimelineActor::new(actors.new_name("timeline"), pipeline, script_sender.clone());
|
||||
|
||||
let profiler = ProfilerActor::new(actors.new_name("profiler"));
|
||||
let performance = PerformanceActor::new(actors.new_name("performance"));
|
||||
|
||||
// the strange switch between styleSheets and stylesheets is due
|
||||
// to an inconsistency in devtools. See Bug #1498893 in bugzilla
|
||||
let styleSheets = StyleSheetsActor::new(actors.new_name("stylesheets"));
|
||||
let thread = ThreadActor::new(actors.new_name("context"));
|
||||
|
||||
let DevtoolsPageInfo { title, url } = page_info;
|
||||
let target = BrowsingContextActor {
|
||||
name: name,
|
||||
script_chan: script_sender,
|
||||
title: String::from(title),
|
||||
url: url.into_string(),
|
||||
console: console,
|
||||
emulation: emulation.name(),
|
||||
inspector: inspector.name(),
|
||||
timeline: timeline.name(),
|
||||
profiler: profiler.name(),
|
||||
performance: performance.name(),
|
||||
styleSheets: styleSheets.name(),
|
||||
thread: thread.name(),
|
||||
streams: RefCell::new(Vec::new()),
|
||||
browsing_context_id: id,
|
||||
active_pipeline: Cell::new(pipeline),
|
||||
};
|
||||
|
||||
actors.register(Box::new(emulation));
|
||||
actors.register(Box::new(inspector));
|
||||
actors.register(Box::new(timeline));
|
||||
actors.register(Box::new(profiler));
|
||||
actors.register(Box::new(performance));
|
||||
actors.register(Box::new(styleSheets));
|
||||
actors.register(Box::new(thread));
|
||||
|
||||
let root = actors.find_mut::<RootActor>("root");
|
||||
root.tabs.push(target.name.clone());
|
||||
target
|
||||
}
|
||||
|
||||
pub fn encodable(&self) -> BrowsingContextActorMsg {
|
||||
BrowsingContextActorMsg {
|
||||
actor: self.name(),
|
||||
|
@ -232,8 +304,10 @@ impl BrowsingContextActor {
|
|||
},
|
||||
title: self.title.clone(),
|
||||
url: self.url.clone(),
|
||||
browsingContextId: 0, //FIXME should come from constellation
|
||||
outerWindowID: 0, //FIXME: this should probably be the pipeline id
|
||||
//FIXME: shouldn't ignore pipeline namespace field
|
||||
browsingContextId: self.browsing_context_id.index.0.get(),
|
||||
//FIXME: shouldn't ignore pipeline namespace field
|
||||
outerWindowID: self.active_pipeline.get().index.0.get(),
|
||||
consoleActor: self.console.clone(),
|
||||
emulationActor: self.emulation.clone(),
|
||||
inspectorActor: self.inspector.clone(),
|
||||
|
@ -243,4 +317,40 @@ impl BrowsingContextActor {
|
|||
styleSheetsActor: self.styleSheets.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn navigate(&self, state: NavigationState) {
|
||||
let (pipeline, title, url, state) = match state {
|
||||
NavigationState::Start(url) => (None, None, url, "start"),
|
||||
NavigationState::Stop(pipeline, info) => {
|
||||
(Some(pipeline), Some(info.title), info.url, "stop")
|
||||
},
|
||||
};
|
||||
if let Some(p) = pipeline {
|
||||
self.active_pipeline.set(p);
|
||||
}
|
||||
let msg = TabNavigated {
|
||||
from: self.name(),
|
||||
type_: "tabNavigated".to_owned(),
|
||||
url: url.as_str().to_owned(),
|
||||
title: title,
|
||||
nativeConsoleAPI: true,
|
||||
state: state.to_owned(),
|
||||
isFrameSwitching: false,
|
||||
};
|
||||
for stream in &mut *self.streams.borrow_mut() {
|
||||
stream.write_json_packet(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct TabNavigated {
|
||||
from: String,
|
||||
#[serde(rename = "type")]
|
||||
type_: String,
|
||||
url: String,
|
||||
title: Option<String>,
|
||||
nativeConsoleAPI: bool,
|
||||
state: String,
|
||||
isFrameSwitching: bool,
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
//! inspection, JS evaluation, autocompletion) in Servo.
|
||||
|
||||
use crate::actor::{Actor, ActorMessageStatus, ActorRegistry};
|
||||
use crate::actors::browsing_context::BrowsingContextActor;
|
||||
use crate::actors::object::ObjectActor;
|
||||
use crate::protocol::JsonPacketStream;
|
||||
use crate::{ConsoleAPICall, ConsoleMessage, ConsoleMsg, PageErrorMsg};
|
||||
|
@ -17,10 +18,11 @@ use devtools_traits::EvaluateJSReply::{NullValue, NumberValue, VoidValue};
|
|||
use devtools_traits::{
|
||||
CachedConsoleMessageTypes, ConsoleAPI, DevtoolScriptControlMsg, LogLevel, PageError,
|
||||
};
|
||||
use ipc_channel::ipc::{self, IpcSender};
|
||||
use ipc_channel::ipc;
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use serde_json::{self, Map, Number, Value};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::net::TcpStream;
|
||||
use time::precise_time_ns;
|
||||
use uuid::Uuid;
|
||||
|
@ -106,10 +108,8 @@ struct SetPreferencesReply {
|
|||
|
||||
pub struct ConsoleActor {
|
||||
pub name: String,
|
||||
pub pipeline: PipelineId,
|
||||
pub script_chan: IpcSender<DevtoolScriptControlMsg>,
|
||||
pub streams: RefCell<Vec<TcpStream>>,
|
||||
pub cached_events: RefCell<Vec<CachedConsoleMessage>>,
|
||||
pub browsing_context: String,
|
||||
pub cached_events: RefCell<HashMap<PipelineId, Vec<CachedConsoleMessage>>>,
|
||||
}
|
||||
|
||||
impl ConsoleActor {
|
||||
|
@ -118,11 +118,13 @@ impl ConsoleActor {
|
|||
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();
|
||||
self.script_chan
|
||||
browsing_context
|
||||
.script_chan
|
||||
.send(DevtoolScriptControlMsg::EvaluateJS(
|
||||
self.pipeline,
|
||||
browsing_context.active_pipeline.get(),
|
||||
input.clone(),
|
||||
chan,
|
||||
))
|
||||
|
@ -191,21 +193,35 @@ impl ConsoleActor {
|
|||
std::result::Result::Ok(reply)
|
||||
}
|
||||
|
||||
pub(crate) fn handle_page_error(&self, page_error: PageError) {
|
||||
pub(crate) fn handle_page_error(
|
||||
&self,
|
||||
page_error: PageError,
|
||||
pipeline: PipelineId,
|
||||
browsing_context: &BrowsingContextActor,
|
||||
) {
|
||||
self.cached_events
|
||||
.borrow_mut()
|
||||
.entry(pipeline)
|
||||
.or_insert(vec![])
|
||||
.push(CachedConsoleMessage::PageError(page_error.clone()));
|
||||
let msg = PageErrorMsg {
|
||||
from: self.name(),
|
||||
type_: "pageError".to_owned(),
|
||||
pageError: page_error,
|
||||
};
|
||||
for stream in &mut *self.streams.borrow_mut() {
|
||||
stream.write_json_packet(&msg);
|
||||
if browsing_context.active_pipeline.get() == pipeline {
|
||||
let msg = PageErrorMsg {
|
||||
from: self.name(),
|
||||
type_: "pageError".to_owned(),
|
||||
pageError: page_error,
|
||||
};
|
||||
for stream in &mut *browsing_context.streams.borrow_mut() {
|
||||
stream.write_json_packet(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn handle_console_api(&self, console_message: ConsoleMessage) {
|
||||
pub(crate) fn handle_console_api(
|
||||
&self,
|
||||
console_message: ConsoleMessage,
|
||||
pipeline: PipelineId,
|
||||
browsing_context: &BrowsingContextActor,
|
||||
) {
|
||||
let level = match console_message.logLevel {
|
||||
LogLevel::Debug => "debug",
|
||||
LogLevel::Info => "info",
|
||||
|
@ -216,6 +232,8 @@ impl ConsoleActor {
|
|||
.to_owned();
|
||||
self.cached_events
|
||||
.borrow_mut()
|
||||
.entry(pipeline)
|
||||
.or_insert(vec![])
|
||||
.push(CachedConsoleMessage::ConsoleAPI(ConsoleAPI {
|
||||
type_: "ConsoleAPI".to_owned(),
|
||||
level: level.clone(),
|
||||
|
@ -226,20 +244,22 @@ impl ConsoleActor {
|
|||
private: false,
|
||||
arguments: vec![console_message.message.clone()],
|
||||
}));
|
||||
let msg = ConsoleAPICall {
|
||||
from: self.name(),
|
||||
type_: "consoleAPICall".to_owned(),
|
||||
message: ConsoleMsg {
|
||||
level: level,
|
||||
timeStamp: precise_time_ns(),
|
||||
arguments: vec![console_message.message],
|
||||
filename: console_message.filename,
|
||||
lineNumber: console_message.lineNumber,
|
||||
columnNumber: console_message.columnNumber,
|
||||
},
|
||||
};
|
||||
for stream in &mut *self.streams.borrow_mut() {
|
||||
stream.write_json_packet(&msg);
|
||||
if browsing_context.active_pipeline.get() == pipeline {
|
||||
let msg = ConsoleAPICall {
|
||||
from: self.name(),
|
||||
type_: "consoleAPICall".to_owned(),
|
||||
message: ConsoleMsg {
|
||||
level: level,
|
||||
timeStamp: precise_time_ns(),
|
||||
arguments: vec![console_message.message],
|
||||
filename: console_message.filename,
|
||||
lineNumber: console_message.lineNumber,
|
||||
columnNumber: console_message.columnNumber,
|
||||
},
|
||||
};
|
||||
for stream in &mut *browsing_context.streams.borrow_mut() {
|
||||
stream.write_json_packet(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -275,8 +295,16 @@ 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().iter() {
|
||||
for event in self
|
||||
.cached_events
|
||||
.borrow()
|
||||
.get(&browsing_context.active_pipeline.get())
|
||||
.unwrap_or(&vec![])
|
||||
.iter()
|
||||
{
|
||||
let include = match event {
|
||||
CachedConsoleMessage::PageError(_)
|
||||
if message_types.contains(CachedConsoleMessageTypes::PAGE_ERROR) =>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
//! (http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/inspector.js).
|
||||
|
||||
use crate::actor::{Actor, ActorMessageStatus, ActorRegistry};
|
||||
use crate::actors::browsing_context::BrowsingContextActor;
|
||||
use crate::protocol::JsonPacketStream;
|
||||
use devtools_traits::DevtoolScriptControlMsg::{GetChildren, GetDocumentElement, GetRootNode};
|
||||
use devtools_traits::DevtoolScriptControlMsg::{GetLayout, ModifyAttribute};
|
||||
|
@ -22,7 +23,7 @@ pub struct InspectorActor {
|
|||
pub pageStyle: RefCell<Option<String>>,
|
||||
pub highlighter: RefCell<Option<String>>,
|
||||
pub script_chan: IpcSender<DevtoolScriptControlMsg>,
|
||||
pub pipeline: PipelineId,
|
||||
pub browsing_context: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
@ -596,13 +597,15 @@ impl Actor for InspectorActor {
|
|||
_msg: &Map<String, Value>,
|
||||
stream: &mut TcpStream,
|
||||
) -> Result<ActorMessageStatus, ()> {
|
||||
let browsing_context = registry.find::<BrowsingContextActor>(&self.browsing_context);
|
||||
let pipeline = browsing_context.active_pipeline.get();
|
||||
Ok(match msg_type {
|
||||
"getWalker" => {
|
||||
if self.walker.borrow().is_none() {
|
||||
let walker = WalkerActor {
|
||||
name: registry.new_name("walker"),
|
||||
script_chan: self.script_chan.clone(),
|
||||
pipeline: self.pipeline,
|
||||
pipeline: pipeline,
|
||||
};
|
||||
let mut walker_name = self.walker.borrow_mut();
|
||||
*walker_name = Some(walker.name());
|
||||
|
@ -610,13 +613,10 @@ impl Actor for InspectorActor {
|
|||
}
|
||||
|
||||
let (tx, rx) = ipc::channel().unwrap();
|
||||
self.script_chan
|
||||
.send(GetRootNode(self.pipeline, tx))
|
||||
.unwrap();
|
||||
self.script_chan.send(GetRootNode(pipeline, tx)).unwrap();
|
||||
let root_info = rx.recv().unwrap().ok_or(())?;
|
||||
|
||||
let node =
|
||||
root_info.encode(registry, false, self.script_chan.clone(), self.pipeline);
|
||||
let node = root_info.encode(registry, false, self.script_chan.clone(), pipeline);
|
||||
|
||||
let msg = GetWalkerReply {
|
||||
from: self.name(),
|
||||
|
@ -634,7 +634,7 @@ impl Actor for InspectorActor {
|
|||
let style = PageStyleActor {
|
||||
name: registry.new_name("pageStyle"),
|
||||
script_chan: self.script_chan.clone(),
|
||||
pipeline: self.pipeline,
|
||||
pipeline: pipeline,
|
||||
};
|
||||
let mut pageStyle = self.pageStyle.borrow_mut();
|
||||
*pageStyle = Some(style.name());
|
||||
|
|
|
@ -21,29 +21,24 @@ use crate::actor::{Actor, ActorRegistry};
|
|||
use crate::actors::browsing_context::BrowsingContextActor;
|
||||
use crate::actors::console::ConsoleActor;
|
||||
use crate::actors::device::DeviceActor;
|
||||
use crate::actors::emulation::EmulationActor;
|
||||
use crate::actors::framerate::FramerateActor;
|
||||
use crate::actors::inspector::InspectorActor;
|
||||
use crate::actors::network_event::{EventActor, NetworkEventActor, ResponseStartMsg};
|
||||
use crate::actors::performance::PerformanceActor;
|
||||
use crate::actors::preference::PreferenceActor;
|
||||
use crate::actors::process::ProcessActor;
|
||||
use crate::actors::profiler::ProfilerActor;
|
||||
use crate::actors::root::RootActor;
|
||||
use crate::actors::stylesheets::StyleSheetsActor;
|
||||
use crate::actors::thread::ThreadActor;
|
||||
use crate::actors::timeline::TimelineActor;
|
||||
use crate::actors::worker::WorkerActor;
|
||||
use crate::protocol::JsonPacketStream;
|
||||
use crossbeam_channel::{unbounded, Receiver, Sender};
|
||||
use devtools_traits::{ChromeToDevtoolsControlMsg, ConsoleMessage, DevtoolsControlMsg};
|
||||
use devtools_traits::{DevtoolScriptControlMsg, DevtoolsPageInfo, LogLevel, NetworkEvent};
|
||||
use devtools_traits::{
|
||||
DevtoolScriptControlMsg, DevtoolsPageInfo, LogLevel, NavigationState, NetworkEvent,
|
||||
};
|
||||
use devtools_traits::{PageError, ScriptToDevtoolsControlMsg, WorkerId};
|
||||
use embedder_traits::{EmbedderMsg, EmbedderProxy, PromptDefinition, PromptOrigin, PromptResult};
|
||||
use ipc_channel::ipc::{self, IpcSender};
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use msg::constellation_msg::{BrowsingContextId, PipelineId};
|
||||
use std::borrow::ToOwned;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
use std::collections::HashMap;
|
||||
use std::net::{Shutdown, TcpListener, TcpStream};
|
||||
|
@ -198,7 +193,8 @@ fn run_server(
|
|||
|
||||
let mut accepted_connections: Vec<TcpStream> = Vec::new();
|
||||
|
||||
let mut actor_pipelines: HashMap<PipelineId, String> = HashMap::new();
|
||||
let mut browsing_contexts: HashMap<BrowsingContextId, String> = HashMap::new();
|
||||
let mut pipelines: HashMap<PipelineId, BrowsingContextId> = HashMap::new();
|
||||
let mut actor_requests: HashMap<String, String> = HashMap::new();
|
||||
|
||||
let mut actor_workers: HashMap<(PipelineId, WorkerId), String> = HashMap::new();
|
||||
|
@ -243,91 +239,65 @@ fn run_server(
|
|||
framerate_actor.add_tick(tick);
|
||||
}
|
||||
|
||||
fn handle_navigate(
|
||||
actors: Arc<Mutex<ActorRegistry>>,
|
||||
browsing_contexts: &HashMap<BrowsingContextId, String>,
|
||||
browsing_context: BrowsingContextId,
|
||||
state: NavigationState,
|
||||
) {
|
||||
let actor_name = browsing_contexts.get(&browsing_context).unwrap();
|
||||
actors
|
||||
.lock()
|
||||
.unwrap()
|
||||
.find::<BrowsingContextActor>(actor_name)
|
||||
.navigate(state);
|
||||
}
|
||||
|
||||
// We need separate actor representations for each script global that exists;
|
||||
// clients can theoretically connect to multiple globals simultaneously.
|
||||
// TODO: move this into the root or target modules?
|
||||
fn handle_new_global(
|
||||
actors: Arc<Mutex<ActorRegistry>>,
|
||||
ids: (PipelineId, Option<WorkerId>),
|
||||
ids: (Option<BrowsingContextId>, PipelineId, Option<WorkerId>),
|
||||
script_sender: IpcSender<DevtoolScriptControlMsg>,
|
||||
actor_pipelines: &mut HashMap<PipelineId, String>,
|
||||
browsing_contexts: &mut HashMap<BrowsingContextId, String>,
|
||||
pipelines: &mut HashMap<PipelineId, BrowsingContextId>,
|
||||
actor_workers: &mut HashMap<(PipelineId, WorkerId), String>,
|
||||
page_info: DevtoolsPageInfo,
|
||||
) {
|
||||
let mut actors = actors.lock().unwrap();
|
||||
|
||||
let (pipeline, worker_id) = ids;
|
||||
let (browsing_context, pipeline, worker_id) = ids;
|
||||
|
||||
//TODO: move all this actor creation into a constructor method on BrowsingContextActor
|
||||
let (
|
||||
target,
|
||||
console,
|
||||
emulation,
|
||||
inspector,
|
||||
timeline,
|
||||
profiler,
|
||||
performance,
|
||||
styleSheets,
|
||||
thread,
|
||||
) = {
|
||||
let console = ConsoleActor {
|
||||
name: actors.new_name("console"),
|
||||
script_chan: script_sender.clone(),
|
||||
pipeline: pipeline,
|
||||
streams: RefCell::new(Vec::new()),
|
||||
cached_events: RefCell::new(Vec::new()),
|
||||
};
|
||||
let console_name = actors.new_name("console");
|
||||
|
||||
let emulation = EmulationActor::new(actors.new_name("emulation"));
|
||||
let browsing_context_name = if let Some(browsing_context) = browsing_context {
|
||||
pipelines.insert(pipeline, browsing_context);
|
||||
if let Some(actor) = browsing_contexts.get(&browsing_context) {
|
||||
actor.to_owned()
|
||||
} else {
|
||||
let browsing_context_actor = BrowsingContextActor::new(
|
||||
console_name.clone(),
|
||||
browsing_context,
|
||||
page_info,
|
||||
pipeline,
|
||||
script_sender.clone(),
|
||||
&mut *actors,
|
||||
);
|
||||
let name = browsing_context_actor.name();
|
||||
browsing_contexts.insert(browsing_context, name.clone());
|
||||
actors.register(Box::new(browsing_context_actor));
|
||||
name
|
||||
}
|
||||
} else {
|
||||
"".to_owned()
|
||||
};
|
||||
|
||||
let inspector = InspectorActor {
|
||||
name: actors.new_name("inspector"),
|
||||
walker: RefCell::new(None),
|
||||
pageStyle: RefCell::new(None),
|
||||
highlighter: RefCell::new(None),
|
||||
script_chan: script_sender.clone(),
|
||||
pipeline: pipeline,
|
||||
};
|
||||
|
||||
let timeline = TimelineActor::new(actors.new_name("timeline"), pipeline, script_sender);
|
||||
|
||||
let profiler = ProfilerActor::new(actors.new_name("profiler"));
|
||||
let performance = PerformanceActor::new(actors.new_name("performance"));
|
||||
|
||||
// the strange switch between styleSheets and stylesheets is due
|
||||
// to an inconsistency in devtools. See Bug #1498893 in bugzilla
|
||||
let styleSheets = StyleSheetsActor::new(actors.new_name("stylesheets"));
|
||||
let thread = ThreadActor::new(actors.new_name("context"));
|
||||
|
||||
let DevtoolsPageInfo { title, url } = page_info;
|
||||
let target = BrowsingContextActor {
|
||||
name: actors.new_name("target"),
|
||||
title: String::from(title),
|
||||
url: url.into_string(),
|
||||
console: console.name(),
|
||||
emulation: emulation.name(),
|
||||
inspector: inspector.name(),
|
||||
timeline: timeline.name(),
|
||||
profiler: profiler.name(),
|
||||
performance: performance.name(),
|
||||
styleSheets: styleSheets.name(),
|
||||
thread: thread.name(),
|
||||
};
|
||||
|
||||
let root = actors.find_mut::<RootActor>("root");
|
||||
root.tabs.push(target.name.clone());
|
||||
|
||||
(
|
||||
target,
|
||||
console,
|
||||
emulation,
|
||||
inspector,
|
||||
timeline,
|
||||
profiler,
|
||||
performance,
|
||||
styleSheets,
|
||||
thread,
|
||||
)
|
||||
// XXXjdm this new actor is useless if it's not a new worker global
|
||||
let console = ConsoleActor {
|
||||
name: console_name,
|
||||
cached_events: Default::default(),
|
||||
browsing_context: browsing_context_name,
|
||||
};
|
||||
|
||||
if let Some(id) = worker_id {
|
||||
|
@ -336,36 +306,39 @@ fn run_server(
|
|||
console: console.name(),
|
||||
id: id,
|
||||
};
|
||||
let root = actors.find_mut::<RootActor>("root");
|
||||
root.tabs.push(worker.name.clone());
|
||||
|
||||
actor_workers.insert((pipeline, id), worker.name.clone());
|
||||
actors.register(Box::new(worker));
|
||||
}
|
||||
|
||||
actor_pipelines.insert(pipeline, target.name.clone());
|
||||
actors.register(Box::new(target));
|
||||
actors.register(Box::new(console));
|
||||
actors.register(Box::new(emulation));
|
||||
actors.register(Box::new(inspector));
|
||||
actors.register(Box::new(timeline));
|
||||
actors.register(Box::new(profiler));
|
||||
actors.register(Box::new(performance));
|
||||
actors.register(Box::new(styleSheets));
|
||||
actors.register(Box::new(thread));
|
||||
}
|
||||
|
||||
fn handle_page_error(
|
||||
actors: Arc<Mutex<ActorRegistry>>,
|
||||
id: PipelineId,
|
||||
page_error: PageError,
|
||||
actor_pipelines: &HashMap<PipelineId, String>,
|
||||
browsing_contexts: &HashMap<BrowsingContextId, String>,
|
||||
pipelines: &HashMap<PipelineId, BrowsingContextId>,
|
||||
) {
|
||||
let console_actor_name =
|
||||
match find_console_actor(actors.clone(), id, None, &HashMap::new(), actor_pipelines) {
|
||||
Some(name) => name,
|
||||
None => return,
|
||||
};
|
||||
let console_actor_name = match find_console_actor(
|
||||
actors.clone(),
|
||||
id,
|
||||
None,
|
||||
&HashMap::new(),
|
||||
browsing_contexts,
|
||||
pipelines,
|
||||
) {
|
||||
Some(name) => name,
|
||||
None => return,
|
||||
};
|
||||
let actors = actors.lock().unwrap();
|
||||
let console_actor = actors.find::<ConsoleActor>(&console_actor_name);
|
||||
console_actor.handle_page_error(page_error);
|
||||
let browsing_context_actor =
|
||||
actors.find::<BrowsingContextActor>(&console_actor.browsing_context);
|
||||
console_actor.handle_page_error(page_error, id, &browsing_context_actor);
|
||||
}
|
||||
|
||||
fn handle_console_message(
|
||||
|
@ -373,37 +346,43 @@ fn run_server(
|
|||
id: PipelineId,
|
||||
worker_id: Option<WorkerId>,
|
||||
console_message: ConsoleMessage,
|
||||
actor_pipelines: &HashMap<PipelineId, String>,
|
||||
browsing_contexts: &HashMap<BrowsingContextId, String>,
|
||||
actor_workers: &HashMap<(PipelineId, WorkerId), String>,
|
||||
pipelines: &HashMap<PipelineId, BrowsingContextId>,
|
||||
) {
|
||||
let console_actor_name = match find_console_actor(
|
||||
actors.clone(),
|
||||
id,
|
||||
worker_id,
|
||||
actor_workers,
|
||||
actor_pipelines,
|
||||
browsing_contexts,
|
||||
pipelines,
|
||||
) {
|
||||
Some(name) => name,
|
||||
None => return,
|
||||
};
|
||||
let actors = actors.lock().unwrap();
|
||||
let console_actor = actors.find::<ConsoleActor>(&console_actor_name);
|
||||
console_actor.handle_console_api(console_message);
|
||||
let browsing_context_actor =
|
||||
actors.find::<BrowsingContextActor>(&console_actor.browsing_context);
|
||||
console_actor.handle_console_api(console_message, id, &browsing_context_actor);
|
||||
}
|
||||
|
||||
fn find_console_actor(
|
||||
actors: Arc<Mutex<ActorRegistry>>,
|
||||
id: PipelineId,
|
||||
pipeline: PipelineId,
|
||||
worker_id: Option<WorkerId>,
|
||||
actor_workers: &HashMap<(PipelineId, WorkerId), String>,
|
||||
actor_pipelines: &HashMap<PipelineId, String>,
|
||||
browsing_contexts: &HashMap<BrowsingContextId, String>,
|
||||
pipelines: &HashMap<PipelineId, BrowsingContextId>,
|
||||
) -> Option<String> {
|
||||
let actors = actors.lock().unwrap();
|
||||
if let Some(worker_id) = worker_id {
|
||||
let actor_name = (*actor_workers).get(&(id, worker_id))?;
|
||||
let actor_name = (*actor_workers).get(&(pipeline, worker_id))?;
|
||||
Some(actors.find::<WorkerActor>(actor_name).console.clone())
|
||||
} else {
|
||||
let actor_name = (*actor_pipelines).get(&id)?;
|
||||
let id = pipelines.get(&pipeline)?;
|
||||
let actor_name = browsing_contexts.get(id)?;
|
||||
Some(
|
||||
actors
|
||||
.find::<BrowsingContextActor>(actor_name)
|
||||
|
@ -416,9 +395,10 @@ fn run_server(
|
|||
fn handle_network_event(
|
||||
actors: Arc<Mutex<ActorRegistry>>,
|
||||
mut connections: Vec<TcpStream>,
|
||||
actor_pipelines: &HashMap<PipelineId, String>,
|
||||
browsing_contexts: &HashMap<BrowsingContextId, String>,
|
||||
actor_requests: &mut HashMap<String, String>,
|
||||
actor_workers: &HashMap<(PipelineId, WorkerId), String>,
|
||||
pipelines: &HashMap<PipelineId, BrowsingContextId>,
|
||||
pipeline_id: PipelineId,
|
||||
request_id: String,
|
||||
network_event: NetworkEvent,
|
||||
|
@ -428,7 +408,8 @@ fn run_server(
|
|||
pipeline_id,
|
||||
None,
|
||||
actor_workers,
|
||||
actor_pipelines,
|
||||
browsing_contexts,
|
||||
pipelines,
|
||||
) {
|
||||
Some(name) => name,
|
||||
None => return,
|
||||
|
@ -610,10 +591,15 @@ fn run_server(
|
|||
actors.clone(),
|
||||
ids,
|
||||
script_sender,
|
||||
&mut actor_pipelines,
|
||||
&mut browsing_contexts,
|
||||
&mut pipelines,
|
||||
&mut actor_workers,
|
||||
pageinfo,
|
||||
),
|
||||
DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::Navigate(
|
||||
browsing_context,
|
||||
state,
|
||||
)) => handle_navigate(actors.clone(), &browsing_contexts, browsing_context, state),
|
||||
DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::ConsoleAPI(
|
||||
id,
|
||||
console_message,
|
||||
|
@ -623,13 +609,20 @@ fn run_server(
|
|||
id,
|
||||
worker_id,
|
||||
console_message,
|
||||
&actor_pipelines,
|
||||
&browsing_contexts,
|
||||
&actor_workers,
|
||||
&pipelines,
|
||||
),
|
||||
DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::ReportPageError(
|
||||
id,
|
||||
page_error,
|
||||
)) => handle_page_error(actors.clone(), id, page_error, &actor_pipelines),
|
||||
)) => handle_page_error(
|
||||
actors.clone(),
|
||||
id,
|
||||
page_error,
|
||||
&browsing_contexts,
|
||||
&pipelines,
|
||||
),
|
||||
DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::ReportCSSError(
|
||||
id,
|
||||
css_error,
|
||||
|
@ -646,8 +639,9 @@ fn run_server(
|
|||
id,
|
||||
None,
|
||||
console_message,
|
||||
&actor_pipelines,
|
||||
&browsing_contexts,
|
||||
&actor_workers,
|
||||
&pipelines,
|
||||
)
|
||||
},
|
||||
DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::NetworkEvent(
|
||||
|
@ -667,9 +661,10 @@ fn run_server(
|
|||
handle_network_event(
|
||||
actors.clone(),
|
||||
connections,
|
||||
&actor_pipelines,
|
||||
&browsing_contexts,
|
||||
&mut actor_requests,
|
||||
&actor_workers,
|
||||
&pipelines,
|
||||
pipeline_id,
|
||||
request_id,
|
||||
network_event,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue