aboutsummaryrefslogtreecommitdiffstats
path: root/components/devtools/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/devtools/lib.rs')
-rw-r--r--components/devtools/lib.rs312
1 files changed, 167 insertions, 145 deletions
diff --git a/components/devtools/lib.rs b/components/devtools/lib.rs
index 661d6ac94e1..2227be98549 100644
--- a/components/devtools/lib.rs
+++ b/components/devtools/lib.rs
@@ -19,31 +19,27 @@ extern crate serde;
use crate::actor::{Actor, ActorRegistry};
use crate::actors::browsing_context::BrowsingContextActor;
-use crate::actors::console::ConsoleActor;
+use crate::actors::console::{ConsoleActor, Root};
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::actors::worker::{WorkerActor, WorkerType};
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};
@@ -74,30 +70,10 @@ mod actors {
}
mod protocol;
-#[derive(Serialize)]
-struct ConsoleAPICall {
- from: String,
- #[serde(rename = "type")]
- type_: String,
- message: ConsoleMsg,
-}
-
-#[derive(Serialize)]
-struct ConsoleMsg {
- level: String,
- timeStamp: u64,
- arguments: Vec<String>,
- filename: String,
- lineNumber: usize,
- columnNumber: usize,
-}
-
-#[derive(Serialize)]
-struct PageErrorMsg {
- from: String,
- #[serde(rename = "type")]
- type_: String,
- pageError: PageError,
+#[derive(Clone, Debug, Eq, Hash, PartialEq)]
+enum UniqueId {
+ Pipeline(PipelineId),
+ Worker(WorkerId),
}
#[derive(Serialize)]
@@ -181,6 +157,7 @@ fn run_server(
let root = Box::new(RootActor {
tabs: vec![],
+ workers: vec![],
device: device.name(),
performance: performance.name(),
preference: preference.name(),
@@ -198,10 +175,11 @@ 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();
+ let mut actor_workers: HashMap<WorkerId, String> = HashMap::new();
/// Process the input from a single devtools client until EOF.
fn handle_client(actors: Arc<Mutex<ActorRegistry>>, mut stream: TcpStream) {
@@ -243,129 +221,139 @@ 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);
+ }
+
+ fn handle_title_changed(
+ actors: Arc<Mutex<ActorRegistry>>,
+ pipelines: &HashMap<PipelineId, BrowsingContextId>,
+ browsing_contexts: &HashMap<BrowsingContextId, String>,
+ pipeline: PipelineId,
+ title: String,
+ ) {
+ let bc = match pipelines.get(&pipeline) {
+ Some(bc) => bc,
+ None => return,
+ };
+ let name = match browsing_contexts.get(&bc) {
+ Some(name) => name,
+ None => return,
+ };
+ let actors = actors.lock().unwrap();
+ let browsing_context = actors.find::<BrowsingContextActor>(name);
+ browsing_context.title_changed(pipeline, title);
+ }
+
// 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: (BrowsingContextId, PipelineId, Option<WorkerId>),
script_sender: IpcSender<DevtoolScriptControlMsg>,
- actor_pipelines: &mut HashMap<PipelineId, String>,
- actor_workers: &mut HashMap<(PipelineId, WorkerId), String>,
+ browsing_contexts: &mut HashMap<BrowsingContextId, String>,
+ pipelines: &mut HashMap<PipelineId, BrowsingContextId>,
+ actor_workers: &mut HashMap<WorkerId, String>,
page_info: DevtoolsPageInfo,
) {
let mut actors = actors.lock().unwrap();
- let (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 emulation = EmulationActor::new(actors.new_name("emulation"));
-
- 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 (browsing_context, pipeline, worker_id) = ids;
- let timeline = TimelineActor::new(actors.new_name("timeline"), pipeline, script_sender);
+ let console_name = actors.new_name("console");
- let profiler = ProfilerActor::new(actors.new_name("profiler"));
- let performance = PerformanceActor::new(actors.new_name("performance"));
+ let parent_actor = if let Some(id) = worker_id {
+ assert!(pipelines.get(&pipeline).is_some());
+ assert!(browsing_contexts.get(&browsing_context).is_some());
- // 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 thread_name = thread.name();
+ actors.register(Box::new(thread));
- 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 worker_name = actors.new_name("worker");
+ let worker = WorkerActor {
+ name: worker_name.clone(),
+ console: console_name.clone(),
+ thread: thread_name,
+ id: id,
+ url: page_info.url.clone(),
+ type_: WorkerType::Dedicated,
+ script_chan: script_sender,
+ streams: Default::default(),
};
-
let root = actors.find_mut::<RootActor>("root");
- root.tabs.push(target.name.clone());
-
- (
- target,
- console,
- emulation,
- inspector,
- timeline,
- profiler,
- performance,
- styleSheets,
- thread,
+ root.workers.push(worker.name.clone());
+
+ actor_workers.insert(id, worker_name.clone());
+ actors.register(Box::new(worker));
+
+ Root::DedicatedWorker(worker_name)
+ } else {
+ pipelines.insert(pipeline, browsing_context);
+ Root::BrowsingContext(
+ 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,
+ &mut *actors,
+ );
+ let name = browsing_context_actor.name();
+ browsing_contexts.insert(browsing_context, name.clone());
+ actors.register(Box::new(browsing_context_actor));
+ name
+ },
)
};
- if let Some(id) = worker_id {
- let worker = WorkerActor {
- name: actors.new_name("worker"),
- console: console.name(),
- id: id,
- };
- actor_workers.insert((pipeline, id), worker.name.clone());
- actors.register(Box::new(worker));
- }
+ let console = ConsoleActor {
+ name: console_name,
+ cached_events: Default::default(),
+ root: parent_actor,
+ };
- 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,
+ worker_id: Option<WorkerId>,
page_error: PageError,
- actor_pipelines: &HashMap<PipelineId, String>,
+ browsing_contexts: &HashMap<BrowsingContextId, String>,
+ actor_workers: &HashMap<WorkerId, 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,
+ worker_id,
+ actor_workers,
+ 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 id = worker_id.map_or(UniqueId::Pipeline(id), UniqueId::Worker);
+ console_actor.handle_page_error(page_error, id, &*actors);
}
fn handle_console_message(
@@ -373,37 +361,42 @@ fn run_server(
id: PipelineId,
worker_id: Option<WorkerId>,
console_message: ConsoleMessage,
- actor_pipelines: &HashMap<PipelineId, String>,
- actor_workers: &HashMap<(PipelineId, WorkerId), String>,
+ browsing_contexts: &HashMap<BrowsingContextId, String>,
+ actor_workers: &HashMap<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 id = worker_id.map_or(UniqueId::Pipeline(id), UniqueId::Worker);
+ console_actor.handle_console_api(console_message, id, &*actors);
}
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>,
+ actor_workers: &HashMap<WorkerId, 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(&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 +409,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>,
+ actor_workers: &HashMap<WorkerId, String>,
+ pipelines: &HashMap<PipelineId, BrowsingContextId>,
pipeline_id: PipelineId,
request_id: String,
network_event: NetworkEvent,
@@ -428,7 +422,8 @@ fn run_server(
pipeline_id,
None,
actor_workers,
- actor_pipelines,
+ browsing_contexts,
+ pipelines,
) {
Some(name) => name,
None => return,
@@ -589,6 +584,7 @@ fn run_server(
.expect("Thread spawning failed");
while let Ok(msg) = receiver.recv() {
+ debug!("{:?}", msg);
match msg {
DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::AddClient(stream)) => {
let actors = actors.clone();
@@ -602,6 +598,16 @@ fn run_server(
actor_name,
tick,
)) => handle_framerate_tick(actors.clone(), actor_name, tick),
+ DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::TitleChanged(
+ pipeline,
+ title,
+ )) => handle_title_changed(
+ actors.clone(),
+ &pipelines,
+ &browsing_contexts,
+ pipeline,
+ title,
+ ),
DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::NewGlobal(
ids,
script_sender,
@@ -610,10 +616,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 +634,22 @@ 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,
+ None,
+ page_error,
+ &browsing_contexts,
+ &actor_workers,
+ &pipelines,
+ ),
DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::ReportCSSError(
id,
css_error,
@@ -646,8 +666,9 @@ fn run_server(
id,
None,
console_message,
- &actor_pipelines,
+ &browsing_contexts,
&actor_workers,
+ &pipelines,
)
},
DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::NetworkEvent(
@@ -667,9 +688,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,