Notify devtools about new worker globals

This commit is contained in:
Thiago Pontes 2015-03-27 16:04:53 -03:00
parent 5dd43bf84c
commit 1244f9e016
10 changed files with 117 additions and 14 deletions

View file

@ -0,0 +1,26 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use actor::{Actor, ActorRegistry};
use rustc_serialize::json;
use std::net::TcpStream;
use msg::constellation_msg::WorkerId;
pub struct WorkerActor {
pub name: String,
pub id: WorkerId,
}
impl Actor for WorkerActor {
fn name(&self) -> String {
self.name.clone()
}
fn handle_message(&self,
_: &ActorRegistry,
_: &str,
_: &json::Object,
_: &mut TcpStream) -> Result<bool, ()> {
Ok(true)
}
}

View file

@ -30,6 +30,7 @@ extern crate util;
use actor::{Actor, ActorRegistry};
use actors::console::ConsoleActor;
use actors::worker::WorkerActor;
use actors::inspector::InspectorActor;
use actors::root::RootActor;
use actors::tab::TabActor;
@ -37,7 +38,7 @@ use protocol::JsonPacketStream;
use devtools_traits::{ConsoleMessage, DevtoolsControlMsg};
use devtools_traits::{DevtoolsPageInfo, DevtoolScriptControlMsg};
use msg::constellation_msg::PipelineId;
use msg::constellation_msg::{PipelineId, WorkerId};
use util::task::spawn_named;
use std::borrow::ToOwned;
@ -55,6 +56,7 @@ mod actors {
pub mod inspector;
pub mod root;
pub mod tab;
pub mod worker;
}
mod protocol;
@ -107,6 +109,7 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
let mut actor_pipelines: HashMap<PipelineId, String> = HashMap::new();
/// Process the input from a single devtools client until EOF.
fn handle_client(actors: Arc<Mutex<ActorRegistry>>, mut stream: TcpStream) {
println!("connection established to {}", stream.peer_addr().unwrap());
@ -142,12 +145,16 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
// clients can theoretically connect to multiple globals simultaneously.
// TODO: move this into the root or tab modules?
fn handle_new_global(actors: Arc<Mutex<ActorRegistry>>,
pipeline: PipelineId,
ids: (PipelineId, Option<WorkerId>),
scriptSender: Sender<DevtoolScriptControlMsg>,
actor_pipelines: &mut HashMap<PipelineId, String>,
page_info: DevtoolsPageInfo) {
let mut actors = actors.lock().unwrap();
let (pipeline, worker_id) = ids;
let mut actor_workers: HashMap<(PipelineId, WorkerId), String> = HashMap::new();
//TODO: move all this actor creation into a constructor method on TabActor
let (tab, console, inspector) = {
let console = ConsoleActor {
@ -179,6 +186,15 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
(tab, console, inspector)
};
if let Some(id) = worker_id {
let worker = WorkerActor {
name: actors.new_name("worker"),
id: id,
};
actor_workers.insert((pipeline, id), worker.name.clone());
actors.register(box worker);
}
actor_pipelines.insert(pipeline, tab.name.clone());
actors.register(box tab);
actors.register(box console);
@ -241,8 +257,8 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
})
}
Ok(DevtoolsControlMsg::ServerExitMsg) | Err(RecvError) => break,
Ok(DevtoolsControlMsg::NewGlobal(id, scriptSender, pageinfo)) =>
handle_new_global(actors.clone(), id, scriptSender, &mut actor_pipelines,
Ok(DevtoolsControlMsg::NewGlobal(ids, scriptSender, pageinfo)) =>
handle_new_global(actors.clone(), ids, scriptSender, &mut actor_pipelines,
pageinfo),
Ok(DevtoolsControlMsg::SendConsoleMessage(id, console_message)) =>
handle_console_message(actors.clone(), id, console_message,

View file

@ -20,7 +20,7 @@ extern crate url;
extern crate util;
use rustc_serialize::{Decodable, Decoder};
use msg::constellation_msg::PipelineId;
use msg::constellation_msg::{PipelineId, WorkerId};
use util::str::DOMString;
use url::Url;
@ -41,7 +41,7 @@ pub struct DevtoolsPageInfo {
/// according to changes in the browser.
pub enum DevtoolsControlMsg {
AddClient(TcpStream),
NewGlobal(PipelineId, Sender<DevtoolScriptControlMsg>, DevtoolsPageInfo),
NewGlobal((PipelineId, Option<WorkerId>), Sender<DevtoolScriptControlMsg>, DevtoolsPageInfo),
SendConsoleMessage(PipelineId, ConsoleMessage),
ServerExitMsg
}

View file

@ -311,6 +311,9 @@ pub enum NavigationDirection {
#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct FrameId(pub uint);
#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct WorkerId(pub uint);
#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct PipelineId(pub uint);

View file

@ -14,6 +14,8 @@ use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers};
use dom::window::{self, WindowHelpers};
use script_task::ScriptChan;
use msg::constellation_msg::WorkerId;
use net::resource_task::ResourceTask;
use js::{JSCLASS_IS_GLOBAL, JSCLASS_IS_DOMJSCLASS};
@ -89,6 +91,14 @@ impl<'a> GlobalRef<'a> {
}
}
/// Get next worker id.
pub fn get_next_worker_id(&self) -> WorkerId {
match *self {
GlobalRef::Window(ref window) => window.get_next_worker_id(),
GlobalRef::Worker(ref worker) => worker.get_next_worker_id()
}
}
/// Get the URL for this global scope.
pub fn get_url(&self) -> Url {
match *self {

View file

@ -47,7 +47,7 @@ use js::jsval::JSVal;
use js::rust::{Cx, rt};
use layout_interface::{LayoutRPC, LayoutChan};
use libc;
use msg::constellation_msg::{PipelineId, SubpageId, WindowSizeData};
use msg::constellation_msg::{PipelineId, SubpageId, WindowSizeData, WorkerId};
use net::image_cache_task::ImageCacheTask;
use net::storage_task::StorageType;
use script_traits::ScriptControlChan;
@ -242,6 +242,7 @@ no_jsmanaged_fields!(PropertyDeclarationBlock);
// These three are interdependent, if you plan to put jsmanaged data
// in one of these make sure it is propagated properly to containing structs
no_jsmanaged_fields!(SubpageId, WindowSizeData, PipelineId);
no_jsmanaged_fields!(WorkerId);
no_jsmanaged_fields!(QuirksMode);
no_jsmanaged_fields!(Cx);
no_jsmanaged_fields!(rt);

View file

@ -36,7 +36,7 @@ use timers::{IsInterval, TimerId, TimerManager, TimerCallback};
use devtools_traits::DevtoolsControlChan;
use msg::compositor_msg::ScriptListener;
use msg::constellation_msg::{LoadData, PipelineId, SubpageId, ConstellationChan, WindowSizeData};
use msg::constellation_msg::{LoadData, PipelineId, SubpageId, ConstellationChan, WindowSizeData, WorkerId};
use net::image_cache_task::ImageCacheTask;
use net::resource_task::ResourceTask;
use net::storage_task::{StorageTask, StorageType};
@ -98,6 +98,8 @@ pub struct Window {
local_storage: MutNullableJS<Storage>,
timers: TimerManager,
next_worker_id: Cell<WorkerId>,
/// For providing instructions to an optional devtools server.
devtools_chan: Option<DevtoolsControlChan>,
@ -171,6 +173,13 @@ impl Window {
self.script_chan.clone()
}
pub fn get_next_worker_id(&self) -> WorkerId {
let worker_id = self.next_worker_id.get();
let WorkerId(id_num) = worker_id;
self.next_worker_id.set(WorkerId(id_num + 1));
worker_id
}
pub fn pipeline(&self) -> PipelineId {
self.id
}
@ -814,6 +823,7 @@ impl Window {
session_storage: Default::default(),
local_storage: Default::default(),
timers: TimerManager::new(),
next_worker_id: Cell::new(WorkerId(0)),
id: id,
parent_info: parent_info,
dom_static: GlobalStaticData::new(),

View file

@ -4,6 +4,7 @@
use dom::bindings::codegen::Bindings::WorkerBinding;
use dom::bindings::codegen::Bindings::WorkerBinding::WorkerMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::InheritTypes::{EventCast, EventTargetCast};
use dom::bindings::error::{Fallible, ErrorResult};
@ -14,6 +15,7 @@ use dom::bindings::refcounted::Trusted;
use dom::bindings::structuredclone::StructuredCloneData;
use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::{Reflectable, reflect_dom_object};
use dom::window::WindowHelpers;
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
use dom::errorevent::ErrorEvent;
use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers};
@ -21,6 +23,8 @@ use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
use dom::messageevent::MessageEvent;
use script_task::{ScriptChan, ScriptMsg, Runnable};
use devtools_traits::{DevtoolsControlMsg, DevtoolsPageInfo};
use util::str::DOMString;
use js::jsapi::JSContext;
@ -71,6 +75,23 @@ impl Worker {
let worker = Worker::new(global, sender.clone()).root();
let worker_ref = Trusted::new(global.get_cx(), worker.r(), global.script_chan());
if let GlobalRef::Window(window) = global {
if let Some(ref chan) = window.devtools_chan() {
let pipeline_id = window.Window().root().r().pipeline();
let (devtools_sender, _) = channel();
let title = format!("Worker for {}", worker_url);
let page_info = DevtoolsPageInfo {
title: title,
url: worker_url.clone(),
};
let worker_id = global.get_next_worker_id();
chan.send(
DevtoolsControlMsg::NewGlobal((pipeline_id, Some(worker_id)), devtools_sender.clone(), page_info)
).unwrap();
}
}
DedicatedWorkerGlobalScope::run_worker_scope(
worker_url, worker_ref, resource_task, global.script_chan(),
sender, receiver);

View file

@ -19,6 +19,8 @@ use dom::window::{base64_atob, base64_btoa};
use script_task::{ScriptChan, TimerSource};
use timers::{IsInterval, TimerId, TimerManager, TimerCallback};
use msg::constellation_msg::WorkerId;
use net::resource_task::{ResourceTask, load_whole_resource};
use util::str::DOMString;
@ -28,6 +30,7 @@ use js::rust::Cx;
use std::default::Default;
use std::rc::Rc;
use std::cell::Cell;
use url::{Url, UrlParser};
#[derive(Copy, PartialEq)]
@ -41,6 +44,7 @@ pub struct WorkerGlobalScope {
eventtarget: EventTarget,
worker_url: Url,
js_context: Rc<Cx>,
next_worker_id: Cell<WorkerId>,
resource_task: ResourceTask,
location: MutNullableJS<WorkerLocation>,
navigator: MutNullableJS<WorkerNavigator>,
@ -55,6 +59,7 @@ impl WorkerGlobalScope {
resource_task: ResourceTask) -> WorkerGlobalScope {
WorkerGlobalScope {
eventtarget: EventTarget::new_inherited(EventTargetTypeId::WorkerGlobalScope(type_id)),
next_worker_id: Cell::new(WorkerId(0)),
worker_url: worker_url,
js_context: cx,
resource_task: resource_task,
@ -81,6 +86,13 @@ impl WorkerGlobalScope {
pub fn get_url<'a>(&'a self) -> &'a Url {
&self.worker_url
}
pub fn get_next_worker_id(&self) -> WorkerId {
let worker_id = self.next_worker_id.get();
let WorkerId(id_num) = worker_id;
self.next_worker_id.set(WorkerId(id_num + 1));
worker_id
}
}
impl<'a> WorkerGlobalScopeMethods for JSRef<'a, WorkerGlobalScope> {

View file

@ -57,7 +57,7 @@ use script_traits::ScriptTaskFactory;
use msg::compositor_msg::ReadyState::{FinishedLoading, Loading, PerformingLayout};
use msg::compositor_msg::{LayerId, ScriptListener};
use msg::constellation_msg::{ConstellationChan};
use msg::constellation_msg::{LoadData, PipelineId, SubpageId, MozBrowserEvent};
use msg::constellation_msg::{LoadData, PipelineId, SubpageId, MozBrowserEvent, WorkerId};
use msg::constellation_msg::{Failure, WindowSizeData, PipelineExitType};
use msg::constellation_msg::Msg as ConstellationMsg;
use net::image_cache_task::ImageCacheTask;
@ -1114,20 +1114,24 @@ impl ScriptTask {
chan.send(ConstellationMsg::LoadComplete).unwrap();
// Notify devtools that a new script global exists.
self.notify_devtools(document.r().Title(), final_url, (incomplete.pipeline_id, None));
page_remover.neuter();
}
fn notify_devtools(&self, title: DOMString, url: Url, ids: (PipelineId, Option<WorkerId>)) {
match self.devtools_chan {
None => {}
Some(ref chan) => {
let page_info = DevtoolsPageInfo {
title: document.r().Title(),
url: final_url
title: title,
url: url,
};
chan.send(DevtoolsControlMsg::NewGlobal(incomplete.pipeline_id,
chan.send(DevtoolsControlMsg::NewGlobal(ids,
self.devtools_sender.clone(),
page_info)).unwrap();
}
}
page_remover.neuter();
}
fn scroll_fragment_point(&self, pipeline_id: PipelineId, node: JSRef<Element>) {