mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Auto merge of #26325 - jdm:devtools-nav, r=gterzian
Improve devtools experience when navigating The primary motivation for this work was to fix #15425, and these changes make it possible to use the devtools to meaningfully inspect multiple pages when navigating between them. Navigating through session history is not yet supported. These changes also include improvements to the dedicated worker support, which broke at some point. We now can observe console messages in workers.
This commit is contained in:
commit
1aab10f20a
17 changed files with 693 additions and 265 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1192,6 +1192,7 @@ dependencies = [
|
||||||
"msg",
|
"msg",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"servo_url",
|
||||||
"time",
|
"time",
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
|
@ -22,5 +22,6 @@ log = "0.4"
|
||||||
msg = {path = "../msg"}
|
msg = {path = "../msg"}
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
servo_url = { path = "../url" }
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
uuid = {version = "0.8", features = ["v4"]}
|
uuid = {version = "0.8", features = ["v4"]}
|
||||||
|
|
|
@ -8,10 +8,22 @@
|
||||||
//! Supports dynamic attaching and detaching which control notifications of navigation, etc.
|
//! Supports dynamic attaching and detaching which control notifications of navigation, etc.
|
||||||
|
|
||||||
use crate::actor::{Actor, ActorMessageStatus, ActorRegistry};
|
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 crate::protocol::JsonPacketStream;
|
||||||
use devtools_traits::DevtoolScriptControlMsg::{self, WantsLiveNotifications};
|
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 serde_json::{Map, Value};
|
||||||
|
use std::cell::{Cell, RefCell};
|
||||||
use std::net::TcpStream;
|
use std::net::TcpStream;
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
@ -108,8 +120,8 @@ pub struct BrowsingContextActorMsg {
|
||||||
|
|
||||||
pub struct BrowsingContextActor {
|
pub struct BrowsingContextActor {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub title: String,
|
pub title: RefCell<String>,
|
||||||
pub url: String,
|
pub url: RefCell<String>,
|
||||||
pub console: String,
|
pub console: String,
|
||||||
pub emulation: String,
|
pub emulation: String,
|
||||||
pub inspector: String,
|
pub inspector: String,
|
||||||
|
@ -118,6 +130,10 @@ pub struct BrowsingContextActor {
|
||||||
pub performance: String,
|
pub performance: String,
|
||||||
pub styleSheets: String,
|
pub styleSheets: String,
|
||||||
pub thread: 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 {
|
impl Actor for BrowsingContextActor {
|
||||||
|
@ -127,7 +143,7 @@ impl Actor for BrowsingContextActor {
|
||||||
|
|
||||||
fn handle_message(
|
fn handle_message(
|
||||||
&self,
|
&self,
|
||||||
registry: &ActorRegistry,
|
_registry: &ActorRegistry,
|
||||||
msg_type: &str,
|
msg_type: &str,
|
||||||
msg: &Map<String, Value>,
|
msg: &Map<String, Value>,
|
||||||
stream: &mut TcpStream,
|
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(options) = msg.get("options").and_then(|o| o.as_object()) {
|
||||||
if let Some(val) = options.get("performReload") {
|
if let Some(val) = options.get("performReload") {
|
||||||
if val.as_bool().unwrap_or(false) {
|
if val.as_bool().unwrap_or(false) {
|
||||||
let console_actor = registry.find::<ConsoleActor>(&self.console);
|
let _ = self
|
||||||
let _ = console_actor
|
|
||||||
.script_chan
|
.script_chan
|
||||||
.send(DevtoolScriptControlMsg::Reload(console_actor.pipeline));
|
.send(DevtoolScriptControlMsg::Reload(self.active_pipeline.get()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,38 +174,31 @@ impl Actor for BrowsingContextActor {
|
||||||
javascriptEnabled: true,
|
javascriptEnabled: true,
|
||||||
traits: AttachedTraits {
|
traits: AttachedTraits {
|
||||||
reconfigure: false,
|
reconfigure: false,
|
||||||
frames: false,
|
frames: true,
|
||||||
logInPage: false,
|
logInPage: false,
|
||||||
canRewind: false,
|
canRewind: false,
|
||||||
watchpoints: false,
|
watchpoints: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let console_actor = registry.find::<ConsoleActor>(&self.console);
|
self.streams.borrow_mut().push(stream.try_clone().unwrap());
|
||||||
console_actor
|
|
||||||
.streams
|
|
||||||
.borrow_mut()
|
|
||||||
.push(stream.try_clone().unwrap());
|
|
||||||
stream.write_json_packet(&msg);
|
stream.write_json_packet(&msg);
|
||||||
console_actor
|
self.script_chan
|
||||||
.script_chan
|
.send(WantsLiveNotifications(self.active_pipeline.get(), true))
|
||||||
.send(WantsLiveNotifications(console_actor.pipeline, true))
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ActorMessageStatus::Processed
|
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.
|
// that the correct stream is removed.
|
||||||
"detach" => {
|
"detach" => {
|
||||||
let msg = BrowsingContextDetachedReply {
|
let msg = BrowsingContextDetachedReply {
|
||||||
from: self.name(),
|
from: self.name(),
|
||||||
type_: "detached".to_owned(),
|
type_: "detached".to_owned(),
|
||||||
};
|
};
|
||||||
let console_actor = registry.find::<ConsoleActor>(&self.console);
|
self.streams.borrow_mut().pop();
|
||||||
console_actor.streams.borrow_mut().pop();
|
|
||||||
stream.write_json_packet(&msg);
|
stream.write_json_packet(&msg);
|
||||||
console_actor
|
self.script_chan
|
||||||
.script_chan
|
.send(WantsLiveNotifications(self.active_pipeline.get(), false))
|
||||||
.send(WantsLiveNotifications(console_actor.pipeline, false))
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ActorMessageStatus::Processed
|
ActorMessageStatus::Processed
|
||||||
},
|
},
|
||||||
|
@ -199,10 +207,11 @@ impl Actor for BrowsingContextActor {
|
||||||
let msg = ListFramesReply {
|
let msg = ListFramesReply {
|
||||||
from: self.name(),
|
from: self.name(),
|
||||||
frames: vec![FrameMsg {
|
frames: vec![FrameMsg {
|
||||||
id: 0, //FIXME should match outerwindow id
|
//FIXME: shouldn't ignore pipeline namespace field
|
||||||
|
id: self.active_pipeline.get().index.0.get(),
|
||||||
parentID: 0,
|
parentID: 0,
|
||||||
url: self.url.clone(),
|
url: self.url.borrow().clone(),
|
||||||
title: self.title.clone(),
|
title: self.title.borrow().clone(),
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
stream.write_json_packet(&msg);
|
stream.write_json_packet(&msg);
|
||||||
|
@ -224,16 +233,82 @@ impl Actor for BrowsingContextActor {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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: RefCell::new(String::from(title)),
|
||||||
|
url: RefCell::new(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 {
|
pub fn encodable(&self) -> BrowsingContextActorMsg {
|
||||||
BrowsingContextActorMsg {
|
BrowsingContextActorMsg {
|
||||||
actor: self.name(),
|
actor: self.name(),
|
||||||
traits: BrowsingContextTraits {
|
traits: BrowsingContextTraits {
|
||||||
isBrowsingContext: true,
|
isBrowsingContext: true,
|
||||||
},
|
},
|
||||||
title: self.title.clone(),
|
title: self.title.borrow().clone(),
|
||||||
url: self.url.clone(),
|
url: self.url.borrow().clone(),
|
||||||
browsingContextId: 0, //FIXME should come from constellation
|
//FIXME: shouldn't ignore pipeline namespace field
|
||||||
outerWindowID: 0, //FIXME: this should probably be the pipeline id
|
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(),
|
consoleActor: self.console.clone(),
|
||||||
emulationActor: self.emulation.clone(),
|
emulationActor: self.emulation.clone(),
|
||||||
inspectorActor: self.inspector.clone(),
|
inspectorActor: self.inspector.clone(),
|
||||||
|
@ -243,4 +318,52 @@ impl BrowsingContextActor {
|
||||||
styleSheetsActor: self.styleSheets.clone(),
|
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);
|
||||||
|
}
|
||||||
|
*self.url.borrow_mut() = url.as_str().to_owned();
|
||||||
|
if let Some(ref t) = title {
|
||||||
|
*self.title.borrow_mut() = t.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn title_changed(&self, pipeline: PipelineId, title: String) {
|
||||||
|
if pipeline != self.active_pipeline.get() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*self.title.borrow_mut() = title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct TabNavigated {
|
||||||
|
from: String,
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
type_: String,
|
||||||
|
url: String,
|
||||||
|
title: Option<String>,
|
||||||
|
nativeConsoleAPI: bool,
|
||||||
|
state: String,
|
||||||
|
isFrameSwitching: bool,
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,19 +8,23 @@
|
||||||
//! inspection, JS evaluation, autocompletion) in Servo.
|
//! inspection, JS evaluation, autocompletion) in Servo.
|
||||||
|
|
||||||
use crate::actor::{Actor, ActorMessageStatus, ActorRegistry};
|
use crate::actor::{Actor, ActorMessageStatus, ActorRegistry};
|
||||||
|
use crate::actors::browsing_context::BrowsingContextActor;
|
||||||
use crate::actors::object::ObjectActor;
|
use crate::actors::object::ObjectActor;
|
||||||
|
use crate::actors::worker::WorkerActor;
|
||||||
use crate::protocol::JsonPacketStream;
|
use crate::protocol::JsonPacketStream;
|
||||||
use crate::{ConsoleAPICall, ConsoleMessage, ConsoleMsg, PageErrorMsg};
|
use crate::UniqueId;
|
||||||
use devtools_traits::CachedConsoleMessage;
|
use devtools_traits::CachedConsoleMessage;
|
||||||
|
use devtools_traits::ConsoleMessage;
|
||||||
use devtools_traits::EvaluateJSReply::{ActorValue, BooleanValue, StringValue};
|
use devtools_traits::EvaluateJSReply::{ActorValue, BooleanValue, StringValue};
|
||||||
use devtools_traits::EvaluateJSReply::{NullValue, NumberValue, VoidValue};
|
use devtools_traits::EvaluateJSReply::{NullValue, NumberValue, VoidValue};
|
||||||
use devtools_traits::{
|
use devtools_traits::{
|
||||||
CachedConsoleMessageTypes, ConsoleAPI, DevtoolScriptControlMsg, LogLevel, PageError,
|
CachedConsoleMessageTypes, ConsoleAPI, DevtoolScriptControlMsg, LogLevel, PageError,
|
||||||
};
|
};
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::TEST_PIPELINE_ID;
|
||||||
use serde_json::{self, Map, Number, Value};
|
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 std::net::TcpStream;
|
||||||
use time::precise_time_ns;
|
use time::precise_time_ns;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
@ -104,15 +108,52 @@ struct SetPreferencesReply {
|
||||||
updated: Vec<String>,
|
updated: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ConsoleActor {
|
pub(crate) enum Root {
|
||||||
|
BrowsingContext(String),
|
||||||
|
DedicatedWorker(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct ConsoleActor {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub pipeline: PipelineId,
|
pub root: Root,
|
||||||
pub script_chan: IpcSender<DevtoolScriptControlMsg>,
|
pub cached_events: RefCell<HashMap<UniqueId, Vec<CachedConsoleMessage>>>,
|
||||||
pub streams: RefCell<Vec<TcpStream>>,
|
|
||||||
pub cached_events: RefCell<Vec<CachedConsoleMessage>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConsoleActor {
|
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(
|
fn evaluateJS(
|
||||||
&self,
|
&self,
|
||||||
registry: &ActorRegistry,
|
registry: &ActorRegistry,
|
||||||
|
@ -120,9 +161,15 @@ impl ConsoleActor {
|
||||||
) -> Result<EvaluateJSReply, ()> {
|
) -> Result<EvaluateJSReply, ()> {
|
||||||
let input = msg.get("text").unwrap().as_str().unwrap().to_owned();
|
let input = msg.get("text").unwrap().as_str().unwrap().to_owned();
|
||||||
let (chan, port) = ipc::channel().unwrap();
|
let (chan, port) = ipc::channel().unwrap();
|
||||||
self.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(
|
.send(DevtoolScriptControlMsg::EvaluateJS(
|
||||||
self.pipeline,
|
pipeline,
|
||||||
input.clone(),
|
input.clone(),
|
||||||
chan,
|
chan,
|
||||||
))
|
))
|
||||||
|
@ -191,21 +238,35 @@ impl ConsoleActor {
|
||||||
std::result::Result::Ok(reply)
|
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,
|
||||||
|
id: UniqueId,
|
||||||
|
registry: &ActorRegistry,
|
||||||
|
) {
|
||||||
self.cached_events
|
self.cached_events
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
|
.entry(id.clone())
|
||||||
|
.or_insert(vec![])
|
||||||
.push(CachedConsoleMessage::PageError(page_error.clone()));
|
.push(CachedConsoleMessage::PageError(page_error.clone()));
|
||||||
|
if id == self.current_unique_id(registry) {
|
||||||
let msg = PageErrorMsg {
|
let msg = PageErrorMsg {
|
||||||
from: self.name(),
|
from: self.name(),
|
||||||
type_: "pageError".to_owned(),
|
type_: "pageError".to_owned(),
|
||||||
pageError: page_error,
|
pageError: page_error,
|
||||||
};
|
};
|
||||||
for stream in &mut *self.streams.borrow_mut() {
|
for stream in &mut *self.streams_mut(registry) {
|
||||||
stream.write_json_packet(&msg);
|
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,
|
||||||
|
id: UniqueId,
|
||||||
|
registry: &ActorRegistry,
|
||||||
|
) {
|
||||||
let level = match console_message.logLevel {
|
let level = match console_message.logLevel {
|
||||||
LogLevel::Debug => "debug",
|
LogLevel::Debug => "debug",
|
||||||
LogLevel::Info => "info",
|
LogLevel::Info => "info",
|
||||||
|
@ -216,6 +277,8 @@ impl ConsoleActor {
|
||||||
.to_owned();
|
.to_owned();
|
||||||
self.cached_events
|
self.cached_events
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
|
.entry(id.clone())
|
||||||
|
.or_insert(vec![])
|
||||||
.push(CachedConsoleMessage::ConsoleAPI(ConsoleAPI {
|
.push(CachedConsoleMessage::ConsoleAPI(ConsoleAPI {
|
||||||
type_: "ConsoleAPI".to_owned(),
|
type_: "ConsoleAPI".to_owned(),
|
||||||
level: level.clone(),
|
level: level.clone(),
|
||||||
|
@ -226,6 +289,7 @@ impl ConsoleActor {
|
||||||
private: false,
|
private: false,
|
||||||
arguments: vec![console_message.message.clone()],
|
arguments: vec![console_message.message.clone()],
|
||||||
}));
|
}));
|
||||||
|
if id == self.current_unique_id(registry) {
|
||||||
let msg = ConsoleAPICall {
|
let msg = ConsoleAPICall {
|
||||||
from: self.name(),
|
from: self.name(),
|
||||||
type_: "consoleAPICall".to_owned(),
|
type_: "consoleAPICall".to_owned(),
|
||||||
|
@ -238,11 +302,12 @@ impl ConsoleActor {
|
||||||
columnNumber: console_message.columnNumber,
|
columnNumber: console_message.columnNumber,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
for stream in &mut *self.streams.borrow_mut() {
|
for stream in &mut *self.streams_mut(registry) {
|
||||||
stream.write_json_packet(&msg);
|
stream.write_json_packet(&msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Actor for ConsoleActor {
|
impl Actor for ConsoleActor {
|
||||||
fn name(&self) -> String {
|
fn name(&self) -> String {
|
||||||
|
@ -257,6 +322,13 @@ impl Actor for ConsoleActor {
|
||||||
stream: &mut TcpStream,
|
stream: &mut TcpStream,
|
||||||
) -> Result<ActorMessageStatus, ()> {
|
) -> Result<ActorMessageStatus, ()> {
|
||||||
Ok(match msg_type {
|
Ok(match msg_type {
|
||||||
|
"clearMessagesCache" => {
|
||||||
|
self.cached_events
|
||||||
|
.borrow_mut()
|
||||||
|
.remove(&self.current_unique_id(registry));
|
||||||
|
ActorMessageStatus::Processed
|
||||||
|
},
|
||||||
|
|
||||||
"getCachedMessages" => {
|
"getCachedMessages" => {
|
||||||
let str_types = msg
|
let str_types = msg
|
||||||
.get("messageTypes")
|
.get("messageTypes")
|
||||||
|
@ -276,7 +348,13 @@ impl Actor for ConsoleActor {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
let mut messages = vec![];
|
let mut messages = vec![];
|
||||||
for event in self.cached_events.borrow().iter() {
|
for event in self
|
||||||
|
.cached_events
|
||||||
|
.borrow()
|
||||||
|
.get(&self.current_unique_id(registry))
|
||||||
|
.unwrap_or(&vec![])
|
||||||
|
.iter()
|
||||||
|
{
|
||||||
let include = match event {
|
let include = match event {
|
||||||
CachedConsoleMessage::PageError(_)
|
CachedConsoleMessage::PageError(_)
|
||||||
if message_types.contains(CachedConsoleMessageTypes::PAGE_ERROR) =>
|
if message_types.contains(CachedConsoleMessageTypes::PAGE_ERROR) =>
|
||||||
|
@ -365,6 +443,13 @@ impl Actor for ConsoleActor {
|
||||||
// Emit an eager reply so that the client starts listening
|
// Emit an eager reply so that the client starts listening
|
||||||
// for an async event with the resultID
|
// for an async event with the resultID
|
||||||
stream.write_json_packet(&early_reply);
|
stream.write_json_packet(&early_reply);
|
||||||
|
|
||||||
|
if msg.get("eager").and_then(|v| v.as_bool()).unwrap_or(false) {
|
||||||
|
// We don't support the side-effect free evaluation that eager evalaution
|
||||||
|
// really needs.
|
||||||
|
return Ok(ActorMessageStatus::Processed);
|
||||||
|
}
|
||||||
|
|
||||||
let reply = self.evaluateJS(®istry, &msg).unwrap();
|
let reply = self.evaluateJS(®istry, &msg).unwrap();
|
||||||
let msg = EvaluateJSEvent {
|
let msg = EvaluateJSEvent {
|
||||||
from: self.name(),
|
from: self.name(),
|
||||||
|
@ -395,3 +480,29 @@ impl Actor for ConsoleActor {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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,
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
//! (http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/inspector.js).
|
//! (http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/inspector.js).
|
||||||
|
|
||||||
use crate::actor::{Actor, ActorMessageStatus, ActorRegistry};
|
use crate::actor::{Actor, ActorMessageStatus, ActorRegistry};
|
||||||
|
use crate::actors::browsing_context::BrowsingContextActor;
|
||||||
use crate::protocol::JsonPacketStream;
|
use crate::protocol::JsonPacketStream;
|
||||||
use devtools_traits::DevtoolScriptControlMsg::{GetChildren, GetDocumentElement, GetRootNode};
|
use devtools_traits::DevtoolScriptControlMsg::{GetChildren, GetDocumentElement, GetRootNode};
|
||||||
use devtools_traits::DevtoolScriptControlMsg::{GetLayout, ModifyAttribute};
|
use devtools_traits::DevtoolScriptControlMsg::{GetLayout, ModifyAttribute};
|
||||||
|
@ -22,7 +23,7 @@ pub struct InspectorActor {
|
||||||
pub pageStyle: RefCell<Option<String>>,
|
pub pageStyle: RefCell<Option<String>>,
|
||||||
pub highlighter: RefCell<Option<String>>,
|
pub highlighter: RefCell<Option<String>>,
|
||||||
pub script_chan: IpcSender<DevtoolScriptControlMsg>,
|
pub script_chan: IpcSender<DevtoolScriptControlMsg>,
|
||||||
pub pipeline: PipelineId,
|
pub browsing_context: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
@ -596,13 +597,15 @@ impl Actor for InspectorActor {
|
||||||
_msg: &Map<String, Value>,
|
_msg: &Map<String, Value>,
|
||||||
stream: &mut TcpStream,
|
stream: &mut TcpStream,
|
||||||
) -> Result<ActorMessageStatus, ()> {
|
) -> Result<ActorMessageStatus, ()> {
|
||||||
|
let browsing_context = registry.find::<BrowsingContextActor>(&self.browsing_context);
|
||||||
|
let pipeline = browsing_context.active_pipeline.get();
|
||||||
Ok(match msg_type {
|
Ok(match msg_type {
|
||||||
"getWalker" => {
|
"getWalker" => {
|
||||||
if self.walker.borrow().is_none() {
|
if self.walker.borrow().is_none() {
|
||||||
let walker = WalkerActor {
|
let walker = WalkerActor {
|
||||||
name: registry.new_name("walker"),
|
name: registry.new_name("walker"),
|
||||||
script_chan: self.script_chan.clone(),
|
script_chan: self.script_chan.clone(),
|
||||||
pipeline: self.pipeline,
|
pipeline: pipeline,
|
||||||
};
|
};
|
||||||
let mut walker_name = self.walker.borrow_mut();
|
let mut walker_name = self.walker.borrow_mut();
|
||||||
*walker_name = Some(walker.name());
|
*walker_name = Some(walker.name());
|
||||||
|
@ -610,13 +613,10 @@ impl Actor for InspectorActor {
|
||||||
}
|
}
|
||||||
|
|
||||||
let (tx, rx) = ipc::channel().unwrap();
|
let (tx, rx) = ipc::channel().unwrap();
|
||||||
self.script_chan
|
self.script_chan.send(GetRootNode(pipeline, tx)).unwrap();
|
||||||
.send(GetRootNode(self.pipeline, tx))
|
|
||||||
.unwrap();
|
|
||||||
let root_info = rx.recv().unwrap().ok_or(())?;
|
let root_info = rx.recv().unwrap().ok_or(())?;
|
||||||
|
|
||||||
let node =
|
let node = root_info.encode(registry, false, self.script_chan.clone(), pipeline);
|
||||||
root_info.encode(registry, false, self.script_chan.clone(), self.pipeline);
|
|
||||||
|
|
||||||
let msg = GetWalkerReply {
|
let msg = GetWalkerReply {
|
||||||
from: self.name(),
|
from: self.name(),
|
||||||
|
@ -634,7 +634,7 @@ impl Actor for InspectorActor {
|
||||||
let style = PageStyleActor {
|
let style = PageStyleActor {
|
||||||
name: registry.new_name("pageStyle"),
|
name: registry.new_name("pageStyle"),
|
||||||
script_chan: self.script_chan.clone(),
|
script_chan: self.script_chan.clone(),
|
||||||
pipeline: self.pipeline,
|
pipeline: pipeline,
|
||||||
};
|
};
|
||||||
let mut pageStyle = self.pageStyle.borrow_mut();
|
let mut pageStyle = self.pageStyle.borrow_mut();
|
||||||
*pageStyle = Some(style.name());
|
*pageStyle = Some(style.name());
|
||||||
|
|
|
@ -10,6 +10,7 @@ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry};
|
||||||
use crate::actors::browsing_context::{BrowsingContextActor, BrowsingContextActorMsg};
|
use crate::actors::browsing_context::{BrowsingContextActor, BrowsingContextActorMsg};
|
||||||
use crate::actors::device::DeviceActor;
|
use crate::actors::device::DeviceActor;
|
||||||
use crate::actors::performance::PerformanceActor;
|
use crate::actors::performance::PerformanceActor;
|
||||||
|
use crate::actors::worker::{WorkerActor, WorkerMsg};
|
||||||
use crate::protocol::{ActorDescription, JsonPacketStream};
|
use crate::protocol::{ActorDescription, JsonPacketStream};
|
||||||
use serde_json::{Map, Value};
|
use serde_json::{Map, Value};
|
||||||
use std::net::TcpStream;
|
use std::net::TcpStream;
|
||||||
|
@ -72,11 +73,6 @@ struct ListWorkersReply {
|
||||||
workers: Vec<WorkerMsg>,
|
workers: Vec<WorkerMsg>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
|
||||||
struct WorkerMsg {
|
|
||||||
id: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct ListServiceWorkerRegistrationsReply {
|
struct ListServiceWorkerRegistrationsReply {
|
||||||
from: String,
|
from: String,
|
||||||
|
@ -110,6 +106,7 @@ struct GetProcessResponse {
|
||||||
|
|
||||||
pub struct RootActor {
|
pub struct RootActor {
|
||||||
pub tabs: Vec<String>,
|
pub tabs: Vec<String>,
|
||||||
|
pub workers: Vec<String>,
|
||||||
pub performance: String,
|
pub performance: String,
|
||||||
pub device: String,
|
pub device: String,
|
||||||
pub preference: String,
|
pub preference: String,
|
||||||
|
@ -203,7 +200,11 @@ impl Actor for RootActor {
|
||||||
"listWorkers" => {
|
"listWorkers" => {
|
||||||
let reply = ListWorkersReply {
|
let reply = ListWorkersReply {
|
||||||
from: self.name(),
|
from: self.name(),
|
||||||
workers: vec![],
|
workers: self
|
||||||
|
.workers
|
||||||
|
.iter()
|
||||||
|
.map(|name| registry.find::<WorkerActor>(name).encodable())
|
||||||
|
.collect(),
|
||||||
};
|
};
|
||||||
stream.write_json_packet(&reply);
|
stream.write_json_packet(&reply);
|
||||||
ActorMessageStatus::Processed
|
ActorMessageStatus::Processed
|
||||||
|
|
|
@ -3,14 +3,49 @@
|
||||||
* 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 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 serde_json::{Map, Value};
|
||||||
|
use servo_url::ServoUrl;
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::net::TcpStream;
|
use std::net::TcpStream;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum WorkerType {
|
||||||
|
Dedicated = 0,
|
||||||
|
Shared = 1,
|
||||||
|
Service = 2,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct WorkerActor {
|
pub struct WorkerActor {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub console: String,
|
pub console: String,
|
||||||
|
pub thread: String,
|
||||||
pub id: WorkerId,
|
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 {
|
impl Actor for WorkerActor {
|
||||||
|
@ -19,11 +54,94 @@ impl Actor for WorkerActor {
|
||||||
}
|
}
|
||||||
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::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,
|
||||||
|
}
|
||||||
|
|
|
@ -19,31 +19,27 @@ extern crate serde;
|
||||||
|
|
||||||
use crate::actor::{Actor, ActorRegistry};
|
use crate::actor::{Actor, ActorRegistry};
|
||||||
use crate::actors::browsing_context::BrowsingContextActor;
|
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::device::DeviceActor;
|
||||||
use crate::actors::emulation::EmulationActor;
|
|
||||||
use crate::actors::framerate::FramerateActor;
|
use crate::actors::framerate::FramerateActor;
|
||||||
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::preference::PreferenceActor;
|
||||||
use crate::actors::process::ProcessActor;
|
use crate::actors::process::ProcessActor;
|
||||||
use crate::actors::profiler::ProfilerActor;
|
|
||||||
use crate::actors::root::RootActor;
|
use crate::actors::root::RootActor;
|
||||||
use crate::actors::stylesheets::StyleSheetsActor;
|
|
||||||
use crate::actors::thread::ThreadActor;
|
use crate::actors::thread::ThreadActor;
|
||||||
use crate::actors::timeline::TimelineActor;
|
use crate::actors::worker::{WorkerActor, WorkerType};
|
||||||
use crate::actors::worker::WorkerActor;
|
|
||||||
use crate::protocol::JsonPacketStream;
|
use crate::protocol::JsonPacketStream;
|
||||||
use crossbeam_channel::{unbounded, Receiver, Sender};
|
use crossbeam_channel::{unbounded, Receiver, Sender};
|
||||||
use devtools_traits::{ChromeToDevtoolsControlMsg, ConsoleMessage, DevtoolsControlMsg};
|
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 devtools_traits::{PageError, ScriptToDevtoolsControlMsg, WorkerId};
|
||||||
use embedder_traits::{EmbedderMsg, EmbedderProxy, PromptDefinition, PromptOrigin, PromptResult};
|
use embedder_traits::{EmbedderMsg, EmbedderProxy, PromptDefinition, PromptOrigin, PromptResult};
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::{BrowsingContextId, PipelineId};
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::net::{Shutdown, TcpListener, TcpStream};
|
use std::net::{Shutdown, TcpListener, TcpStream};
|
||||||
|
@ -74,30 +70,10 @@ mod actors {
|
||||||
}
|
}
|
||||||
mod protocol;
|
mod protocol;
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||||
struct ConsoleAPICall {
|
enum UniqueId {
|
||||||
from: String,
|
Pipeline(PipelineId),
|
||||||
#[serde(rename = "type")]
|
Worker(WorkerId),
|
||||||
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(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
@ -181,6 +157,7 @@ fn run_server(
|
||||||
|
|
||||||
let root = Box::new(RootActor {
|
let root = Box::new(RootActor {
|
||||||
tabs: vec![],
|
tabs: vec![],
|
||||||
|
workers: vec![],
|
||||||
device: device.name(),
|
device: device.name(),
|
||||||
performance: performance.name(),
|
performance: performance.name(),
|
||||||
preference: preference.name(),
|
preference: preference.name(),
|
||||||
|
@ -198,10 +175,11 @@ fn run_server(
|
||||||
|
|
||||||
let mut accepted_connections: Vec<TcpStream> = Vec::new();
|
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_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.
|
/// Process the input from a single devtools client until EOF.
|
||||||
fn handle_client(actors: Arc<Mutex<ActorRegistry>>, mut stream: TcpStream) {
|
fn handle_client(actors: Arc<Mutex<ActorRegistry>>, mut stream: TcpStream) {
|
||||||
|
@ -243,129 +221,139 @@ fn run_server(
|
||||||
framerate_actor.add_tick(tick);
|
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;
|
// We need separate actor representations for each script global that exists;
|
||||||
// clients can theoretically connect to multiple globals simultaneously.
|
// clients can theoretically connect to multiple globals simultaneously.
|
||||||
// TODO: move this into the root or target modules?
|
// TODO: move this into the root or target modules?
|
||||||
fn handle_new_global(
|
fn handle_new_global(
|
||||||
actors: Arc<Mutex<ActorRegistry>>,
|
actors: Arc<Mutex<ActorRegistry>>,
|
||||||
ids: (PipelineId, Option<WorkerId>),
|
ids: (BrowsingContextId, PipelineId, Option<WorkerId>),
|
||||||
script_sender: IpcSender<DevtoolScriptControlMsg>,
|
script_sender: IpcSender<DevtoolScriptControlMsg>,
|
||||||
actor_pipelines: &mut HashMap<PipelineId, String>,
|
browsing_contexts: &mut HashMap<BrowsingContextId, String>,
|
||||||
actor_workers: &mut HashMap<(PipelineId, WorkerId), String>,
|
pipelines: &mut HashMap<PipelineId, BrowsingContextId>,
|
||||||
|
actor_workers: &mut HashMap<WorkerId, String>,
|
||||||
page_info: DevtoolsPageInfo,
|
page_info: DevtoolsPageInfo,
|
||||||
) {
|
) {
|
||||||
let mut actors = actors.lock().unwrap();
|
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 console_name = actors.new_name("console");
|
||||||
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 parent_actor = if let Some(id) = worker_id {
|
||||||
|
assert!(pipelines.get(&pipeline).is_some());
|
||||||
|
assert!(browsing_contexts.get(&browsing_context).is_some());
|
||||||
|
|
||||||
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 thread = ThreadActor::new(actors.new_name("context"));
|
||||||
|
let thread_name = thread.name();
|
||||||
|
actors.register(Box::new(thread));
|
||||||
|
|
||||||
let DevtoolsPageInfo { title, url } = page_info;
|
let worker_name = actors.new_name("worker");
|
||||||
let target = BrowsingContextActor {
|
let worker = WorkerActor {
|
||||||
name: actors.new_name("target"),
|
name: worker_name.clone(),
|
||||||
title: String::from(title),
|
console: console_name.clone(),
|
||||||
url: url.into_string(),
|
thread: thread_name,
|
||||||
console: console.name(),
|
id: id,
|
||||||
emulation: emulation.name(),
|
url: page_info.url.clone(),
|
||||||
inspector: inspector.name(),
|
type_: WorkerType::Dedicated,
|
||||||
timeline: timeline.name(),
|
script_chan: script_sender,
|
||||||
profiler: profiler.name(),
|
streams: Default::default(),
|
||||||
performance: performance.name(),
|
|
||||||
styleSheets: styleSheets.name(),
|
|
||||||
thread: thread.name(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let root = actors.find_mut::<RootActor>("root");
|
let root = actors.find_mut::<RootActor>("root");
|
||||||
root.tabs.push(target.name.clone());
|
root.workers.push(worker.name.clone());
|
||||||
|
|
||||||
(
|
actor_workers.insert(id, worker_name.clone());
|
||||||
target,
|
actors.register(Box::new(worker));
|
||||||
console,
|
|
||||||
emulation,
|
Root::DedicatedWorker(worker_name)
|
||||||
inspector,
|
} else {
|
||||||
timeline,
|
pipelines.insert(pipeline, browsing_context);
|
||||||
profiler,
|
Root::BrowsingContext(
|
||||||
performance,
|
if let Some(actor) = browsing_contexts.get(&browsing_context) {
|
||||||
styleSheets,
|
actor.to_owned()
|
||||||
thread,
|
} 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 console = ConsoleActor {
|
||||||
let worker = WorkerActor {
|
name: console_name,
|
||||||
name: actors.new_name("worker"),
|
cached_events: Default::default(),
|
||||||
console: console.name(),
|
root: parent_actor,
|
||||||
id: id,
|
|
||||||
};
|
};
|
||||||
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(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(
|
fn handle_page_error(
|
||||||
actors: Arc<Mutex<ActorRegistry>>,
|
actors: Arc<Mutex<ActorRegistry>>,
|
||||||
id: PipelineId,
|
id: PipelineId,
|
||||||
|
worker_id: Option<WorkerId>,
|
||||||
page_error: PageError,
|
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,
|
||||||
|
worker_id,
|
||||||
|
actor_workers,
|
||||||
|
browsing_contexts,
|
||||||
|
pipelines,
|
||||||
) {
|
) {
|
||||||
let console_actor_name =
|
|
||||||
match find_console_actor(actors.clone(), id, None, &HashMap::new(), actor_pipelines) {
|
|
||||||
Some(name) => name,
|
Some(name) => name,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
let actors = actors.lock().unwrap();
|
let actors = actors.lock().unwrap();
|
||||||
let console_actor = actors.find::<ConsoleActor>(&console_actor_name);
|
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(
|
fn handle_console_message(
|
||||||
|
@ -373,37 +361,42 @@ fn run_server(
|
||||||
id: PipelineId,
|
id: PipelineId,
|
||||||
worker_id: Option<WorkerId>,
|
worker_id: Option<WorkerId>,
|
||||||
console_message: ConsoleMessage,
|
console_message: ConsoleMessage,
|
||||||
actor_pipelines: &HashMap<PipelineId, String>,
|
browsing_contexts: &HashMap<BrowsingContextId, String>,
|
||||||
actor_workers: &HashMap<(PipelineId, WorkerId), String>,
|
actor_workers: &HashMap<WorkerId, String>,
|
||||||
|
pipelines: &HashMap<PipelineId, BrowsingContextId>,
|
||||||
) {
|
) {
|
||||||
let console_actor_name = match find_console_actor(
|
let console_actor_name = match find_console_actor(
|
||||||
actors.clone(),
|
actors.clone(),
|
||||||
id,
|
id,
|
||||||
worker_id,
|
worker_id,
|
||||||
actor_workers,
|
actor_workers,
|
||||||
actor_pipelines,
|
browsing_contexts,
|
||||||
|
pipelines,
|
||||||
) {
|
) {
|
||||||
Some(name) => name,
|
Some(name) => name,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
let actors = actors.lock().unwrap();
|
let actors = actors.lock().unwrap();
|
||||||
let console_actor = actors.find::<ConsoleActor>(&console_actor_name);
|
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(
|
fn find_console_actor(
|
||||||
actors: Arc<Mutex<ActorRegistry>>,
|
actors: Arc<Mutex<ActorRegistry>>,
|
||||||
id: PipelineId,
|
pipeline: PipelineId,
|
||||||
worker_id: Option<WorkerId>,
|
worker_id: Option<WorkerId>,
|
||||||
actor_workers: &HashMap<(PipelineId, WorkerId), String>,
|
actor_workers: &HashMap<WorkerId, String>,
|
||||||
actor_pipelines: &HashMap<PipelineId, String>,
|
browsing_contexts: &HashMap<BrowsingContextId, String>,
|
||||||
|
pipelines: &HashMap<PipelineId, BrowsingContextId>,
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
let actors = actors.lock().unwrap();
|
let actors = actors.lock().unwrap();
|
||||||
if let Some(worker_id) = worker_id {
|
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())
|
Some(actors.find::<WorkerActor>(actor_name).console.clone())
|
||||||
} else {
|
} else {
|
||||||
let actor_name = (*actor_pipelines).get(&id)?;
|
let id = pipelines.get(&pipeline)?;
|
||||||
|
let actor_name = browsing_contexts.get(id)?;
|
||||||
Some(
|
Some(
|
||||||
actors
|
actors
|
||||||
.find::<BrowsingContextActor>(actor_name)
|
.find::<BrowsingContextActor>(actor_name)
|
||||||
|
@ -416,9 +409,10 @@ fn run_server(
|
||||||
fn handle_network_event(
|
fn handle_network_event(
|
||||||
actors: Arc<Mutex<ActorRegistry>>,
|
actors: Arc<Mutex<ActorRegistry>>,
|
||||||
mut connections: Vec<TcpStream>,
|
mut connections: Vec<TcpStream>,
|
||||||
actor_pipelines: &HashMap<PipelineId, String>,
|
browsing_contexts: &HashMap<BrowsingContextId, String>,
|
||||||
actor_requests: &mut HashMap<String, 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,
|
pipeline_id: PipelineId,
|
||||||
request_id: String,
|
request_id: String,
|
||||||
network_event: NetworkEvent,
|
network_event: NetworkEvent,
|
||||||
|
@ -428,7 +422,8 @@ fn run_server(
|
||||||
pipeline_id,
|
pipeline_id,
|
||||||
None,
|
None,
|
||||||
actor_workers,
|
actor_workers,
|
||||||
actor_pipelines,
|
browsing_contexts,
|
||||||
|
pipelines,
|
||||||
) {
|
) {
|
||||||
Some(name) => name,
|
Some(name) => name,
|
||||||
None => return,
|
None => return,
|
||||||
|
@ -589,6 +584,7 @@ fn run_server(
|
||||||
.expect("Thread spawning failed");
|
.expect("Thread spawning failed");
|
||||||
|
|
||||||
while let Ok(msg) = receiver.recv() {
|
while let Ok(msg) = receiver.recv() {
|
||||||
|
debug!("{:?}", msg);
|
||||||
match msg {
|
match msg {
|
||||||
DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::AddClient(stream)) => {
|
DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::AddClient(stream)) => {
|
||||||
let actors = actors.clone();
|
let actors = actors.clone();
|
||||||
|
@ -602,6 +598,16 @@ fn run_server(
|
||||||
actor_name,
|
actor_name,
|
||||||
tick,
|
tick,
|
||||||
)) => handle_framerate_tick(actors.clone(), 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(
|
DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::NewGlobal(
|
||||||
ids,
|
ids,
|
||||||
script_sender,
|
script_sender,
|
||||||
|
@ -610,10 +616,15 @@ fn run_server(
|
||||||
actors.clone(),
|
actors.clone(),
|
||||||
ids,
|
ids,
|
||||||
script_sender,
|
script_sender,
|
||||||
&mut actor_pipelines,
|
&mut browsing_contexts,
|
||||||
|
&mut pipelines,
|
||||||
&mut actor_workers,
|
&mut actor_workers,
|
||||||
pageinfo,
|
pageinfo,
|
||||||
),
|
),
|
||||||
|
DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::Navigate(
|
||||||
|
browsing_context,
|
||||||
|
state,
|
||||||
|
)) => handle_navigate(actors.clone(), &browsing_contexts, browsing_context, state),
|
||||||
DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::ConsoleAPI(
|
DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::ConsoleAPI(
|
||||||
id,
|
id,
|
||||||
console_message,
|
console_message,
|
||||||
|
@ -623,13 +634,22 @@ fn run_server(
|
||||||
id,
|
id,
|
||||||
worker_id,
|
worker_id,
|
||||||
console_message,
|
console_message,
|
||||||
&actor_pipelines,
|
&browsing_contexts,
|
||||||
&actor_workers,
|
&actor_workers,
|
||||||
|
&pipelines,
|
||||||
),
|
),
|
||||||
DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::ReportPageError(
|
DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::ReportPageError(
|
||||||
id,
|
id,
|
||||||
page_error,
|
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(
|
DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::ReportCSSError(
|
||||||
id,
|
id,
|
||||||
css_error,
|
css_error,
|
||||||
|
@ -646,8 +666,9 @@ fn run_server(
|
||||||
id,
|
id,
|
||||||
None,
|
None,
|
||||||
console_message,
|
console_message,
|
||||||
&actor_pipelines,
|
&browsing_contexts,
|
||||||
&actor_workers,
|
&actor_workers,
|
||||||
|
&pipelines,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::NetworkEvent(
|
DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::NetworkEvent(
|
||||||
|
@ -667,9 +688,10 @@ fn run_server(
|
||||||
handle_network_event(
|
handle_network_event(
|
||||||
actors.clone(),
|
actors.clone(),
|
||||||
connections,
|
connections,
|
||||||
&actor_pipelines,
|
&browsing_contexts,
|
||||||
&mut actor_requests,
|
&mut actor_requests,
|
||||||
&actor_workers,
|
&actor_workers,
|
||||||
|
&pipelines,
|
||||||
pipeline_id,
|
pipeline_id,
|
||||||
request_id,
|
request_id,
|
||||||
network_event,
|
network_event,
|
||||||
|
|
|
@ -21,7 +21,7 @@ extern crate serde;
|
||||||
use http::method::Method;
|
use http::method::Method;
|
||||||
use http::HeaderMap;
|
use http::HeaderMap;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::{BrowsingContextId, PipelineId};
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::net::TcpStream;
|
use std::net::TcpStream;
|
||||||
use time::{self, Duration, Tm};
|
use time::{self, Duration, Tm};
|
||||||
|
@ -29,7 +29,7 @@ use uuid::Uuid;
|
||||||
|
|
||||||
// Information would be attached to NewGlobal to be received and show in devtools.
|
// Information would be attached to NewGlobal to be received and show in devtools.
|
||||||
// Extend these fields if we need more information.
|
// Extend these fields if we need more information.
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
pub struct DevtoolsPageInfo {
|
pub struct DevtoolsPageInfo {
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub url: ServoUrl,
|
pub url: ServoUrl,
|
||||||
|
@ -65,16 +65,27 @@ pub enum ChromeToDevtoolsControlMsg {
|
||||||
NetworkEvent(String, NetworkEvent),
|
NetworkEvent(String, NetworkEvent),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The state of a page navigation.
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub enum NavigationState {
|
||||||
|
/// A browsing context is about to navigate to a given URL.
|
||||||
|
Start(ServoUrl),
|
||||||
|
/// A browsing context has completed navigating to the provided pipeline.
|
||||||
|
Stop(PipelineId, DevtoolsPageInfo),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
/// Events that the devtools server must act upon.
|
/// Events that the devtools server must act upon.
|
||||||
pub enum ScriptToDevtoolsControlMsg {
|
pub enum ScriptToDevtoolsControlMsg {
|
||||||
/// A new global object was created, associated with a particular pipeline.
|
/// A new global object was created, associated with a particular pipeline.
|
||||||
/// The means of communicating directly with it are provided.
|
/// The means of communicating directly with it are provided.
|
||||||
NewGlobal(
|
NewGlobal(
|
||||||
(PipelineId, Option<WorkerId>),
|
(BrowsingContextId, PipelineId, Option<WorkerId>),
|
||||||
IpcSender<DevtoolScriptControlMsg>,
|
IpcSender<DevtoolScriptControlMsg>,
|
||||||
DevtoolsPageInfo,
|
DevtoolsPageInfo,
|
||||||
),
|
),
|
||||||
|
/// The given browsing context is performing a navigation.
|
||||||
|
Navigate(BrowsingContextId, NavigationState),
|
||||||
/// A particular page has invoked the console API.
|
/// A particular page has invoked the console API.
|
||||||
ConsoleAPI(PipelineId, ConsoleMessage, Option<WorkerId>),
|
ConsoleAPI(PipelineId, ConsoleMessage, Option<WorkerId>),
|
||||||
/// An animation frame with the given timestamp was processed in a script thread.
|
/// An animation frame with the given timestamp was processed in a script thread.
|
||||||
|
@ -86,6 +97,9 @@ pub enum ScriptToDevtoolsControlMsg {
|
||||||
|
|
||||||
/// Report a page error for the given pipeline
|
/// Report a page error for the given pipeline
|
||||||
ReportPageError(PipelineId, PageError),
|
ReportPageError(PipelineId, PageError),
|
||||||
|
|
||||||
|
/// Report a page title change
|
||||||
|
TitleChanged(PipelineId, String),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serialized JS return values
|
/// Serialized JS return values
|
||||||
|
|
|
@ -43,7 +43,7 @@ use js::jsapi::JS_AddInterruptCallback;
|
||||||
use js::jsapi::{Heap, JSContext, JSObject};
|
use js::jsapi::{Heap, JSContext, JSObject};
|
||||||
use js::jsval::UndefinedValue;
|
use js::jsval::UndefinedValue;
|
||||||
use js::rust::{CustomAutoRooter, CustomAutoRooterGuard, HandleValue};
|
use js::rust::{CustomAutoRooter, CustomAutoRooterGuard, HandleValue};
|
||||||
use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId};
|
use msg::constellation_msg::{BrowsingContextId, PipelineId, TopLevelBrowsingContextId};
|
||||||
use net_traits::image_cache::ImageCache;
|
use net_traits::image_cache::ImageCache;
|
||||||
use net_traits::request::{CredentialsMode, Destination, ParserMetadata};
|
use net_traits::request::{CredentialsMode, Destination, ParserMetadata};
|
||||||
use net_traits::request::{Referrer, RequestBuilder, RequestMode};
|
use net_traits::request::{Referrer, RequestBuilder, RequestMode};
|
||||||
|
@ -180,6 +180,7 @@ pub struct DedicatedWorkerGlobalScope {
|
||||||
parent_sender: Box<dyn ScriptChan + Send>,
|
parent_sender: Box<dyn ScriptChan + Send>,
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
image_cache: Arc<dyn ImageCache>,
|
image_cache: Arc<dyn ImageCache>,
|
||||||
|
browsing_context: Option<BrowsingContextId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WorkerEventLoopMethods for DedicatedWorkerGlobalScope {
|
impl WorkerEventLoopMethods for DedicatedWorkerGlobalScope {
|
||||||
|
@ -221,6 +222,7 @@ impl DedicatedWorkerGlobalScope {
|
||||||
receiver: Receiver<DedicatedWorkerScriptMsg>,
|
receiver: Receiver<DedicatedWorkerScriptMsg>,
|
||||||
closing: Arc<AtomicBool>,
|
closing: Arc<AtomicBool>,
|
||||||
image_cache: Arc<dyn ImageCache>,
|
image_cache: Arc<dyn ImageCache>,
|
||||||
|
browsing_context: Option<BrowsingContextId>,
|
||||||
) -> DedicatedWorkerGlobalScope {
|
) -> DedicatedWorkerGlobalScope {
|
||||||
DedicatedWorkerGlobalScope {
|
DedicatedWorkerGlobalScope {
|
||||||
workerglobalscope: WorkerGlobalScope::new_inherited(
|
workerglobalscope: WorkerGlobalScope::new_inherited(
|
||||||
|
@ -237,6 +239,7 @@ impl DedicatedWorkerGlobalScope {
|
||||||
parent_sender: parent_sender,
|
parent_sender: parent_sender,
|
||||||
worker: DomRefCell::new(None),
|
worker: DomRefCell::new(None),
|
||||||
image_cache: image_cache,
|
image_cache: image_cache,
|
||||||
|
browsing_context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,6 +256,7 @@ impl DedicatedWorkerGlobalScope {
|
||||||
receiver: Receiver<DedicatedWorkerScriptMsg>,
|
receiver: Receiver<DedicatedWorkerScriptMsg>,
|
||||||
closing: Arc<AtomicBool>,
|
closing: Arc<AtomicBool>,
|
||||||
image_cache: Arc<dyn ImageCache>,
|
image_cache: Arc<dyn ImageCache>,
|
||||||
|
browsing_context: Option<BrowsingContextId>,
|
||||||
) -> DomRoot<DedicatedWorkerGlobalScope> {
|
) -> DomRoot<DedicatedWorkerGlobalScope> {
|
||||||
let cx = runtime.cx();
|
let cx = runtime.cx();
|
||||||
let scope = Box::new(DedicatedWorkerGlobalScope::new_inherited(
|
let scope = Box::new(DedicatedWorkerGlobalScope::new_inherited(
|
||||||
|
@ -267,6 +271,7 @@ impl DedicatedWorkerGlobalScope {
|
||||||
receiver,
|
receiver,
|
||||||
closing,
|
closing,
|
||||||
image_cache,
|
image_cache,
|
||||||
|
browsing_context,
|
||||||
));
|
));
|
||||||
unsafe { DedicatedWorkerGlobalScopeBinding::Wrap(SafeJSContext::from_ptr(cx), scope) }
|
unsafe { DedicatedWorkerGlobalScopeBinding::Wrap(SafeJSContext::from_ptr(cx), scope) }
|
||||||
}
|
}
|
||||||
|
@ -286,6 +291,7 @@ impl DedicatedWorkerGlobalScope {
|
||||||
worker_type: WorkerType,
|
worker_type: WorkerType,
|
||||||
closing: Arc<AtomicBool>,
|
closing: Arc<AtomicBool>,
|
||||||
image_cache: Arc<dyn ImageCache>,
|
image_cache: Arc<dyn ImageCache>,
|
||||||
|
browsing_context: Option<BrowsingContextId>,
|
||||||
) {
|
) {
|
||||||
let serialized_worker_url = worker_url.to_string();
|
let serialized_worker_url = worker_url.to_string();
|
||||||
let name = format!("WebWorker for {}", serialized_worker_url);
|
let name = format!("WebWorker for {}", serialized_worker_url);
|
||||||
|
@ -354,6 +360,7 @@ impl DedicatedWorkerGlobalScope {
|
||||||
receiver,
|
receiver,
|
||||||
closing,
|
closing,
|
||||||
image_cache,
|
image_cache,
|
||||||
|
browsing_context,
|
||||||
);
|
);
|
||||||
// FIXME(njn): workers currently don't have a unique ID suitable for using in reporter
|
// FIXME(njn): workers currently don't have a unique ID suitable for using in reporter
|
||||||
// registration (#6631), so we instead use a random number and cross our fingers.
|
// registration (#6631), so we instead use a random number and cross our fingers.
|
||||||
|
@ -467,6 +474,7 @@ impl DedicatedWorkerGlobalScope {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_mixed_message(&self, msg: MixedMessage) {
|
fn handle_mixed_message(&self, msg: MixedMessage) {
|
||||||
|
// FIXME(#26324): `self.worker` is None in devtools messages.
|
||||||
match msg {
|
match msg {
|
||||||
MixedMessage::FromDevtools(msg) => match msg {
|
MixedMessage::FromDevtools(msg) => match msg {
|
||||||
DevtoolScriptControlMsg::EvaluateJS(_pipe_id, string, sender) => {
|
DevtoolScriptControlMsg::EvaluateJS(_pipe_id, string, sender) => {
|
||||||
|
@ -551,6 +559,10 @@ impl DedicatedWorkerGlobalScope {
|
||||||
.expect("Sending to parent failed");
|
.expect("Sending to parent failed");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn browsing_context(&self) -> Option<BrowsingContextId> {
|
||||||
|
self.browsing_context
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
|
|
@ -934,6 +934,14 @@ impl Document {
|
||||||
pub fn title_changed(&self) {
|
pub fn title_changed(&self) {
|
||||||
if self.browsing_context().is_some() {
|
if self.browsing_context().is_some() {
|
||||||
self.send_title_to_embedder();
|
self.send_title_to_embedder();
|
||||||
|
let global = self.window.upcast::<GlobalScope>();
|
||||||
|
if let Some(ref chan) = global.devtools_chan() {
|
||||||
|
let title = String::from(self.Title());
|
||||||
|
let _ = chan.send(ScriptToDevtoolsControlMsg::TitleChanged(
|
||||||
|
global.pipeline_id(),
|
||||||
|
title,
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,7 @@ impl ServiceWorkerRegistration {
|
||||||
|
|
||||||
let worker_id = WorkerId(Uuid::new_v4());
|
let worker_id = WorkerId(Uuid::new_v4());
|
||||||
let devtools_chan = global.devtools_chan().cloned();
|
let devtools_chan = global.devtools_chan().cloned();
|
||||||
let init = prepare_workerscope_init(&global, None);
|
let init = prepare_workerscope_init(&global, None, None);
|
||||||
ScopeThings {
|
ScopeThings {
|
||||||
script_url: script_url,
|
script_url: script_url,
|
||||||
init: init,
|
init: init,
|
||||||
|
|
|
@ -2008,15 +2008,21 @@ impl Window {
|
||||||
|
|
||||||
// Step 8
|
// Step 8
|
||||||
if doc.prompt_to_unload(false) {
|
if doc.prompt_to_unload(false) {
|
||||||
if self.window_proxy().parent().is_some() {
|
let window_proxy = self.window_proxy();
|
||||||
|
if window_proxy.parent().is_some() {
|
||||||
// Step 10
|
// Step 10
|
||||||
// If browsingContext is a nested browsing context,
|
// If browsingContext is a nested browsing context,
|
||||||
// then put it in the delaying load events mode.
|
// then put it in the delaying load events mode.
|
||||||
self.window_proxy().start_delaying_load_events_mode();
|
window_proxy.start_delaying_load_events_mode();
|
||||||
}
|
}
|
||||||
// TODO: step 11, navigationType.
|
// TODO: step 11, navigationType.
|
||||||
// Step 12, 13
|
// Step 12, 13
|
||||||
ScriptThread::navigate(pipeline_id, load_data, replace);
|
ScriptThread::navigate(
|
||||||
|
window_proxy.browsing_context_id(),
|
||||||
|
pipeline_id,
|
||||||
|
load_data,
|
||||||
|
replace,
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ use crate::dom::dedicatedworkerglobalscope::{
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::messageevent::MessageEvent;
|
use crate::dom::messageevent::MessageEvent;
|
||||||
|
use crate::dom::window::Window;
|
||||||
use crate::dom::workerglobalscope::prepare_workerscope_init;
|
use crate::dom::workerglobalscope::prepare_workerscope_init;
|
||||||
use crate::realms::enter_realm;
|
use crate::realms::enter_realm;
|
||||||
use crate::script_runtime::JSContext;
|
use crate::script_runtime::JSContext;
|
||||||
|
@ -95,23 +96,34 @@ impl Worker {
|
||||||
pipeline_id: global.pipeline_id(),
|
pipeline_id: global.pipeline_id(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let browsing_context = global
|
||||||
|
.downcast::<Window>()
|
||||||
|
.map(|w| w.window_proxy().browsing_context_id())
|
||||||
|
.or_else(|| {
|
||||||
|
global
|
||||||
|
.downcast::<DedicatedWorkerGlobalScope>()
|
||||||
|
.and_then(|w| w.browsing_context())
|
||||||
|
});
|
||||||
|
|
||||||
let (devtools_sender, devtools_receiver) = ipc::channel().unwrap();
|
let (devtools_sender, devtools_receiver) = ipc::channel().unwrap();
|
||||||
let worker_id = WorkerId(Uuid::new_v4());
|
let worker_id = WorkerId(Uuid::new_v4());
|
||||||
if let Some(ref chan) = global.devtools_chan() {
|
if let Some(ref chan) = global.devtools_chan() {
|
||||||
let pipeline_id = global.pipeline_id();
|
let pipeline_id = global.pipeline_id();
|
||||||
let title = format!("Worker for {}", worker_url);
|
let title = format!("Worker for {}", worker_url);
|
||||||
|
if let Some(browsing_context) = browsing_context {
|
||||||
let page_info = DevtoolsPageInfo {
|
let page_info = DevtoolsPageInfo {
|
||||||
title: title,
|
title: title,
|
||||||
url: worker_url.clone(),
|
url: worker_url.clone(),
|
||||||
};
|
};
|
||||||
let _ = chan.send(ScriptToDevtoolsControlMsg::NewGlobal(
|
let _ = chan.send(ScriptToDevtoolsControlMsg::NewGlobal(
|
||||||
(pipeline_id, Some(worker_id)),
|
(browsing_context, pipeline_id, Some(worker_id)),
|
||||||
devtools_sender.clone(),
|
devtools_sender.clone(),
|
||||||
page_info,
|
page_info,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let init = prepare_workerscope_init(global, Some(devtools_sender));
|
let init = prepare_workerscope_init(global, Some(devtools_sender), Some(worker_id));
|
||||||
|
|
||||||
DedicatedWorkerGlobalScope::run_worker_scope(
|
DedicatedWorkerGlobalScope::run_worker_scope(
|
||||||
init,
|
init,
|
||||||
|
@ -126,6 +138,7 @@ impl Worker {
|
||||||
worker_options.type_,
|
worker_options.type_,
|
||||||
closing,
|
closing,
|
||||||
global.image_cache(),
|
global.image_cache(),
|
||||||
|
browsing_context,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(worker)
|
Ok(worker)
|
||||||
|
|
|
@ -62,6 +62,7 @@ use uuid::Uuid;
|
||||||
pub fn prepare_workerscope_init(
|
pub fn prepare_workerscope_init(
|
||||||
global: &GlobalScope,
|
global: &GlobalScope,
|
||||||
devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
|
devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
|
||||||
|
worker_id: Option<WorkerId>,
|
||||||
) -> WorkerGlobalScopeInit {
|
) -> WorkerGlobalScopeInit {
|
||||||
let init = WorkerGlobalScopeInit {
|
let init = WorkerGlobalScopeInit {
|
||||||
resource_threads: global.resource_threads().clone(),
|
resource_threads: global.resource_threads().clone(),
|
||||||
|
@ -71,7 +72,7 @@ pub fn prepare_workerscope_init(
|
||||||
from_devtools_sender: devtools_sender,
|
from_devtools_sender: devtools_sender,
|
||||||
script_to_constellation_chan: global.script_to_constellation_chan().clone(),
|
script_to_constellation_chan: global.script_to_constellation_chan().clone(),
|
||||||
scheduler_chan: global.scheduler_chan().clone(),
|
scheduler_chan: global.scheduler_chan().clone(),
|
||||||
worker_id: WorkerId(Uuid::new_v4()),
|
worker_id: worker_id.unwrap_or_else(|| WorkerId(Uuid::new_v4())),
|
||||||
pipeline_id: global.pipeline_id(),
|
pipeline_id: global.pipeline_id(),
|
||||||
origin: global.origin().immutable().clone(),
|
origin: global.origin().immutable().clone(),
|
||||||
is_headless: global.is_headless(),
|
is_headless: global.is_headless(),
|
||||||
|
|
|
@ -93,7 +93,7 @@ use canvas_traits::webgl::WebGLPipeline;
|
||||||
use crossbeam_channel::{unbounded, Receiver, Sender};
|
use crossbeam_channel::{unbounded, Receiver, Sender};
|
||||||
use devtools_traits::CSSError;
|
use devtools_traits::CSSError;
|
||||||
use devtools_traits::{DevtoolScriptControlMsg, DevtoolsPageInfo};
|
use devtools_traits::{DevtoolScriptControlMsg, DevtoolsPageInfo};
|
||||||
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
|
use devtools_traits::{NavigationState, ScriptToDevtoolsControlMsg, WorkerId};
|
||||||
use embedder_traits::{EmbedderMsg, EventLoopWaker};
|
use embedder_traits::{EmbedderMsg, EventLoopWaker};
|
||||||
use euclid::default::{Point2D, Rect};
|
use euclid::default::{Point2D, Rect};
|
||||||
use euclid::Vector2D;
|
use euclid::Vector2D;
|
||||||
|
@ -947,6 +947,7 @@ impl ScriptThread {
|
||||||
|
|
||||||
/// Step 13 of https://html.spec.whatwg.org/multipage/#navigate
|
/// Step 13 of https://html.spec.whatwg.org/multipage/#navigate
|
||||||
pub fn navigate(
|
pub fn navigate(
|
||||||
|
browsing_context: BrowsingContextId,
|
||||||
pipeline_id: PipelineId,
|
pipeline_id: PipelineId,
|
||||||
mut load_data: LoadData,
|
mut load_data: LoadData,
|
||||||
replace: HistoryEntryReplacement,
|
replace: HistoryEntryReplacement,
|
||||||
|
@ -985,6 +986,12 @@ impl ScriptThread {
|
||||||
.queue(task, global.upcast())
|
.queue(task, global.upcast())
|
||||||
.expect("Enqueing navigate js task on the DOM manipulation task source failed");
|
.expect("Enqueing navigate js task on the DOM manipulation task source failed");
|
||||||
} else {
|
} else {
|
||||||
|
if let Some(ref sender) = script_thread.devtools_chan {
|
||||||
|
let _ = sender.send(ScriptToDevtoolsControlMsg::Navigate(
|
||||||
|
browsing_context, NavigationState::Start(load_data.url.clone())
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
script_thread
|
script_thread
|
||||||
.script_sender
|
.script_sender
|
||||||
.send((pipeline_id, ScriptMsg::LoadUrl(load_data, replace)))
|
.send((pipeline_id, ScriptMsg::LoadUrl(load_data, replace)))
|
||||||
|
@ -3341,7 +3348,7 @@ impl ScriptThread {
|
||||||
self.notify_devtools(
|
self.notify_devtools(
|
||||||
document.Title(),
|
document.Title(),
|
||||||
final_url.clone(),
|
final_url.clone(),
|
||||||
(incomplete.pipeline_id, None),
|
(incomplete.browsing_context_id, incomplete.pipeline_id, None),
|
||||||
);
|
);
|
||||||
|
|
||||||
let parse_input = DOMString::new();
|
let parse_input = DOMString::new();
|
||||||
|
@ -3372,7 +3379,7 @@ impl ScriptThread {
|
||||||
&self,
|
&self,
|
||||||
title: DOMString,
|
title: DOMString,
|
||||||
url: ServoUrl,
|
url: ServoUrl,
|
||||||
ids: (PipelineId, Option<WorkerId>),
|
(bc, p, w): (BrowsingContextId, PipelineId, Option<WorkerId>),
|
||||||
) {
|
) {
|
||||||
if let Some(ref chan) = self.devtools_chan {
|
if let Some(ref chan) = self.devtools_chan {
|
||||||
let page_info = DevtoolsPageInfo {
|
let page_info = DevtoolsPageInfo {
|
||||||
|
@ -3380,11 +3387,14 @@ impl ScriptThread {
|
||||||
url: url,
|
url: url,
|
||||||
};
|
};
|
||||||
chan.send(ScriptToDevtoolsControlMsg::NewGlobal(
|
chan.send(ScriptToDevtoolsControlMsg::NewGlobal(
|
||||||
ids,
|
(bc, p, w),
|
||||||
self.devtools_sender.clone(),
|
self.devtools_sender.clone(),
|
||||||
page_info,
|
page_info.clone(),
|
||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let state = NavigationState::Stop(p, page_info);
|
||||||
|
let _ = chan.send(ScriptToDevtoolsControlMsg::Navigate(bc, state));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ use crate::dom::abstractworker::WorkerScriptMsg;
|
||||||
use crate::dom::serviceworkerglobalscope::{ServiceWorkerGlobalScope, ServiceWorkerScriptMsg};
|
use crate::dom::serviceworkerglobalscope::{ServiceWorkerGlobalScope, ServiceWorkerScriptMsg};
|
||||||
use crate::dom::serviceworkerregistration::longest_prefix_match;
|
use crate::dom::serviceworkerregistration::longest_prefix_match;
|
||||||
use crossbeam_channel::{unbounded, Receiver, RecvError, Sender};
|
use crossbeam_channel::{unbounded, Receiver, RecvError, Sender};
|
||||||
use devtools_traits::{DevtoolsPageInfo, ScriptToDevtoolsControlMsg};
|
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use net_traits::{CoreResourceMsg, CustomResponseMediator};
|
use net_traits::{CoreResourceMsg, CustomResponseMediator};
|
||||||
|
@ -79,19 +78,7 @@ impl ServiceWorkerManager {
|
||||||
let scope_things = self.registered_workers.get(&scope_url);
|
let scope_things = self.registered_workers.get(&scope_url);
|
||||||
if let Some(scope_things) = scope_things {
|
if let Some(scope_things) = scope_things {
|
||||||
let (sender, receiver) = unbounded();
|
let (sender, receiver) = unbounded();
|
||||||
let (devtools_sender, devtools_receiver) = ipc::channel().unwrap();
|
let (_devtools_sender, devtools_receiver) = ipc::channel().unwrap();
|
||||||
if let Some(ref chan) = scope_things.devtools_chan {
|
|
||||||
let title = format!("ServiceWorker for {}", scope_things.script_url);
|
|
||||||
let page_info = DevtoolsPageInfo {
|
|
||||||
title: title,
|
|
||||||
url: scope_things.script_url.clone(),
|
|
||||||
};
|
|
||||||
let _ = chan.send(ScriptToDevtoolsControlMsg::NewGlobal(
|
|
||||||
(scope_things.init.pipeline_id, Some(scope_things.worker_id)),
|
|
||||||
devtools_sender,
|
|
||||||
page_info,
|
|
||||||
));
|
|
||||||
};
|
|
||||||
ServiceWorkerGlobalScope::run_serviceworker_scope(
|
ServiceWorkerGlobalScope::run_serviceworker_scope(
|
||||||
scope_things.clone(),
|
scope_things.clone(),
|
||||||
sender.clone(),
|
sender.clone(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue