aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/bindings/global.rs22
-rw-r--r--components/script/dom/dedicatedworkerglobalscope.rs84
-rw-r--r--components/script/dom/worker.rs33
-rw-r--r--components/script/dom/workerglobalscope.rs35
4 files changed, 142 insertions, 32 deletions
diff --git a/components/script/dom/bindings/global.rs b/components/script/dom/bindings/global.rs
index cfdd3df4af5..91c4a86625b 100644
--- a/components/script/dom/bindings/global.rs
+++ b/components/script/dom/bindings/global.rs
@@ -13,7 +13,7 @@ use dom::bindings::js::{JS, Root};
use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::DocumentHelpers;
use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers};
-use dom::window::{self, WindowHelpers};
+use dom::window::{self, WindowHelpers, ScriptHelpers};
use devtools_traits::ScriptToDevtoolsControlMsg;
use script_task::{ScriptChan, ScriptPort, ScriptMsg, ScriptTask};
@@ -24,8 +24,7 @@ use profile_traits::mem;
use ipc_channel::ipc::IpcSender;
use js::{JSCLASS_IS_GLOBAL, JSCLASS_IS_DOMJSCLASS};
use js::jsapi::{GetGlobalForObjectCrossCompartment};
-use js::jsapi::{JSContext, JSObject};
-use js::jsapi::{JS_GetClass};
+use js::jsapi::{JSContext, JSObject, JS_GetClass, MutableHandleValue};
use url::Url;
/// A freely-copyable reference to a rooted global object.
@@ -165,6 +164,23 @@ impl<'a> GlobalRef<'a> {
GlobalRef::Worker(ref worker) => worker.process_event(msg),
}
}
+
+ /// Evaluate the JS messages on the `RootedValue` of this global
+ pub fn evaluate_js_on_global_with_result(&self, code: &str, rval: MutableHandleValue) {
+ match *self {
+ GlobalRef::Window(window) => window.evaluate_js_on_global_with_result(code, rval),
+ GlobalRef::Worker(worker) => worker.evaluate_js_on_global_with_result(code, rval),
+ }
+ }
+
+ /// Set the `bool` value to indicate whether developer tools has requested
+ /// updates from the global
+ pub fn set_devtools_wants_updates(&self, send_updates: bool) {
+ match *self {
+ GlobalRef::Window(window) => window.set_devtools_wants_updates(send_updates),
+ GlobalRef::Worker(worker) => worker.set_devtools_wants_updates(send_updates),
+ }
+ }
}
impl<'a> Reflectable for GlobalRef<'a> {
diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs
index 5c44f5aff6a..5fe286bc640 100644
--- a/components/script/dom/dedicatedworkerglobalscope.rs
+++ b/components/script/dom/dedicatedworkerglobalscope.rs
@@ -2,6 +2,7 @@
* 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 devtools;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding;
use dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding::DedicatedWorkerGlobalScopeMethods;
@@ -26,7 +27,7 @@ use script_task::StackRootTLS;
use msg::constellation_msg::{ConstellationChan, PipelineId};
-use devtools_traits::ScriptToDevtoolsControlMsg;
+use devtools_traits::{ScriptToDevtoolsControlMsg, DevtoolScriptControlMsg};
use net_traits::{load_whole_resource, ResourceTask};
use profile_traits::mem::{self, Reporter, ReporterRequest};
@@ -34,7 +35,7 @@ use util::task::spawn_named;
use util::task_state;
use util::task_state::{SCRIPT, IN_WORKER};
-use ipc_channel::ipc::{self, IpcSender};
+use ipc_channel::ipc::{self, IpcSender, IpcReceiver};
use ipc_channel::router::ROUTER;
use js::jsapi::{JSContext, RootedValue, HandleValue};
use js::jsapi::{JSAutoRequest, JSAutoCompartment};
@@ -45,7 +46,7 @@ use url::Url;
use rand::random;
use std::mem::replace;
use std::rc::Rc;
-use std::sync::mpsc::{Sender, Receiver, channel};
+use std::sync::mpsc::{Sender, Receiver, channel, Select};
/// A ScriptChan that can be cloned freely and will silently send a TrustedWorkerAddress with
/// every message. While this SendableWorkerScriptChan is alive, the associated Worker object
@@ -110,6 +111,8 @@ impl DedicatedWorkerGlobalScope {
id: PipelineId,
mem_profiler_chan: mem::ProfilerChan,
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
+ devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
+ devtools_port: Receiver<DevtoolScriptControlMsg>,
runtime: Rc<Runtime>,
resource_task: ResourceTask,
constellation_chan: ConstellationChan,
@@ -119,8 +122,8 @@ impl DedicatedWorkerGlobalScope {
-> DedicatedWorkerGlobalScope {
DedicatedWorkerGlobalScope {
workerglobalscope: WorkerGlobalScope::new_inherited(
- WorkerGlobalScopeTypeId::DedicatedGlobalScope, worker_url,
- runtime, resource_task, mem_profiler_chan, devtools_chan, constellation_chan),
+ WorkerGlobalScopeTypeId::DedicatedGlobalScope, worker_url, runtime, resource_task,
+ mem_profiler_chan, devtools_chan, devtools_sender, devtools_port, constellation_chan),
id: id,
receiver: receiver,
own_sender: own_sender,
@@ -133,6 +136,8 @@ impl DedicatedWorkerGlobalScope {
id: PipelineId,
mem_profiler_chan: mem::ProfilerChan,
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
+ devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
+ devtools_port: Receiver<DevtoolScriptControlMsg>,
runtime: Rc<Runtime>,
resource_task: ResourceTask,
constellation_chan: ConstellationChan,
@@ -141,17 +146,20 @@ impl DedicatedWorkerGlobalScope {
receiver: Receiver<(TrustedWorkerAddress, ScriptMsg)>)
-> Root<DedicatedWorkerGlobalScope> {
let scope = box DedicatedWorkerGlobalScope::new_inherited(
- worker_url, id, mem_profiler_chan, devtools_chan, runtime.clone(), resource_task,
- constellation_chan, parent_sender, own_sender, receiver);
+ worker_url, id, mem_profiler_chan, devtools_chan, devtools_sender, devtools_port,
+ runtime.clone(), resource_task, constellation_chan, parent_sender, own_sender, receiver);
DedicatedWorkerGlobalScopeBinding::Wrap(runtime.cx(), scope)
}
}
impl DedicatedWorkerGlobalScope {
+ #[allow(unsafe_code)]
pub fn run_worker_scope(worker_url: Url,
id: PipelineId,
mem_profiler_chan: mem::ProfilerChan,
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
+ devtools_ipc_chan: Option<IpcSender<DevtoolScriptControlMsg>>,
+ devtools_ipc_port: IpcReceiver<DevtoolScriptControlMsg>,
worker: TrustedWorkerAddress,
resource_task: ResourceTask,
constellation_chan: ConstellationChan,
@@ -180,11 +188,16 @@ impl DedicatedWorkerGlobalScope {
let runtime = Rc::new(ScriptTask::new_rt_and_cx());
let serialized_url = url.serialize();
let parent_sender_for_reporter = parent_sender.clone();
+
+ let (devtools_mpsc_chan, devtools_mpsc_port) = channel();
+ ROUTER.route_ipc_receiver_to_mpsc_sender(devtools_ipc_port, devtools_mpsc_chan);
+
let global = DedicatedWorkerGlobalScope::new(
- url, id, mem_profiler_chan.clone(), devtools_chan, runtime.clone(),
- resource_task, constellation_chan, parent_sender, own_sender, receiver);
+ url, id, mem_profiler_chan.clone(), devtools_chan, devtools_ipc_chan, devtools_mpsc_port,
+ runtime.clone(), resource_task, constellation_chan, parent_sender, own_sender, receiver);
// 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.
+ let scope = WorkerGlobalScopeCast::from_ref(global.r());
let reporter_name = format!("worker-reporter-{}", random::<u64>());
{
@@ -216,13 +229,58 @@ impl DedicatedWorkerGlobalScope {
Reporter(reporter_sender)));
}
+ enum MixedMessage {
+ FromWorker((TrustedWorkerAddress, ScriptMsg)),
+ FromDevtools(DevtoolScriptControlMsg),
+ }
+
loop {
- match global.r().receiver.recv() {
- Ok((linked_worker, msg)) => {
+ let worker_port = &global.r().receiver;
+ let devtools_port = scope.devtools_port();
+
+ let event = {
+ let sel = Select::new();
+ let mut worker_handle = sel.handle(worker_port);
+ let mut devtools_handle = sel.handle(devtools_port);
+ unsafe {
+ worker_handle.add();
+ if scope.devtools_sender().is_some() {
+ devtools_handle.add();
+ }
+ }
+ let ret = sel.wait();
+ if ret == worker_handle.id() {
+ match worker_port.recv() {
+ Ok(stuff) => MixedMessage::FromWorker(stuff),
+ Err(_) => break,
+ }
+ } else if ret == devtools_handle.id() {
+ match devtools_port.recv() {
+ Ok(stuff) => MixedMessage::FromDevtools(stuff),
+ Err(_) => break,
+ }
+ } else {
+ panic!("unexpected select result!")
+ }
+ };
+
+ match event {
+ MixedMessage::FromDevtools(msg) => {
+ let global_ref = GlobalRef::Worker(scope);
+ match msg {
+ DevtoolScriptControlMsg::EvaluateJS(_pipe_id, string, sender) =>
+ devtools::handle_evaluate_js(&global_ref, string, sender),
+ DevtoolScriptControlMsg::GetCachedMessages(pipe_id, message_types, sender) =>
+ devtools::handle_get_cached_messages(pipe_id, message_types, sender),
+ DevtoolScriptControlMsg::WantsLiveNotifications(_pipe_id, bool_val) =>
+ devtools::handle_wants_live_notifications(&global_ref, bool_val),
+ _ => debug!("got an unusable devtools control message inside the worker!"),
+ }
+ },
+ MixedMessage::FromWorker((linked_worker, msg)) => {
let _ar = AutoWorkerReset::new(global.r(), linked_worker);
global.r().handle_event(msg);
- }
- Err(_) => break,
+ },
}
}
diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs
index e536200fb43..2ef505308a3 100644
--- a/components/script/dom/worker.rs
+++ b/components/script/dom/worker.rs
@@ -77,23 +77,28 @@ impl Worker {
let worker = Worker::new(global, sender.clone());
let worker_ref = Trusted::new(global.get_cx(), worker.r(), global.script_chan());
- if let Some(ref chan) = global.devtools_chan() {
- let pipeline_id = global.pipeline();
- let (devtools_sender, _) = ipc::channel().unwrap();
- 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(ScriptToDevtoolsControlMsg::NewGlobal((pipeline_id, Some(worker_id)),
- devtools_sender.clone(),
- page_info)).unwrap();
- }
+ let (devtools_sender, devtools_receiver) = ipc::channel().unwrap();
+ let optional_sender = match global.devtools_chan() {
+ Some(ref chan) => {
+ let pipeline_id = global.pipeline();
+ 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(ScriptToDevtoolsControlMsg::NewGlobal((pipeline_id, Some(worker_id)),
+ devtools_sender.clone(),
+ page_info)).unwrap();
+ Some(devtools_sender)
+ },
+ None => None,
+ };
DedicatedWorkerGlobalScope::run_worker_scope(
worker_url, global.pipeline(), global.mem_profiler_chan(), global.devtools_chan(),
- worker_ref, resource_task, constellation_chan, global.script_chan(), sender, receiver);
+ optional_sender, devtools_receiver, worker_ref, resource_task,
+ constellation_chan, global.script_chan(), sender, receiver);
Ok(worker)
}
diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs
index ebdb35a0fde..a99bcab8ebd 100644
--- a/components/script/dom/workerglobalscope.rs
+++ b/components/script/dom/workerglobalscope.rs
@@ -20,7 +20,7 @@ use dom::window::{base64_atob, base64_btoa};
use script_task::{ScriptChan, TimerSource, ScriptPort, ScriptMsg};
use timers::{IsInterval, TimerId, TimerManager, TimerCallback};
-use devtools_traits::ScriptToDevtoolsControlMsg;
+use devtools_traits::{ScriptToDevtoolsControlMsg, DevtoolScriptControlMsg};
use msg::constellation_msg::{ConstellationChan, PipelineId, WorkerId};
use profile_traits::mem;
@@ -35,6 +35,7 @@ use url::{Url, UrlParser};
use std::default::Default;
use std::cell::Cell;
use std::rc::Rc;
+use std::sync::mpsc::Receiver;
#[derive(JSTraceable, Copy, Clone, PartialEq)]
pub enum WorkerGlobalScopeTypeId {
@@ -56,6 +57,19 @@ pub struct WorkerGlobalScope {
timers: TimerManager,
mem_profiler_chan: mem::ProfilerChan,
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
+
+ /// Optional `IpcSender` for sending the `DevtoolScriptControlMsg`
+ /// to the server from within the worker
+ devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
+
+ /// This `Receiver` will be ignored later if the corresponding
+ /// `IpcSender` doesn't exist
+ devtools_receiver: Receiver<DevtoolScriptControlMsg>,
+
+ /// A flag to indicate whether the developer tools has requested live updates
+ /// from the worker
+ devtools_wants_updates: Cell<bool>,
+
constellation_chan: ConstellationChan,
}
@@ -66,6 +80,8 @@ impl WorkerGlobalScope {
resource_task: ResourceTask,
mem_profiler_chan: mem::ProfilerChan,
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
+ devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
+ devtools_receiver: Receiver<DevtoolScriptControlMsg>,
constellation_chan: ConstellationChan)
-> WorkerGlobalScope {
WorkerGlobalScope {
@@ -81,6 +97,9 @@ impl WorkerGlobalScope {
timers: TimerManager::new(),
mem_profiler_chan: mem_profiler_chan,
devtools_chan: devtools_chan,
+ devtools_sender: devtools_sender,
+ devtools_receiver: devtools_receiver,
+ devtools_wants_updates: Cell::new(false),
constellation_chan: constellation_chan,
}
}
@@ -93,6 +112,14 @@ impl WorkerGlobalScope {
self.devtools_chan.clone()
}
+ pub fn devtools_sender(&self) -> Option<IpcSender<DevtoolScriptControlMsg>> {
+ self.devtools_sender.clone()
+ }
+
+ pub fn devtools_port(&self) -> &Receiver<DevtoolScriptControlMsg> {
+ &self.devtools_receiver
+ }
+
pub fn constellation_chan(&self) -> ConstellationChan {
self.constellation_chan.clone()
}
@@ -251,6 +278,7 @@ pub trait WorkerGlobalScopeHelpers {
fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>);
fn process_event(self, msg: ScriptMsg);
fn get_cx(self) -> *mut JSContext;
+ fn set_devtools_wants_updates(self, value: bool);
}
impl<'a> WorkerGlobalScopeHelpers for &'a WorkerGlobalScope {
@@ -297,5 +325,8 @@ impl<'a> WorkerGlobalScopeHelpers for &'a WorkerGlobalScope {
fn get_cx(self) -> *mut JSContext {
self.runtime.cx()
}
-}
+ fn set_devtools_wants_updates(self, value: bool) {
+ self.devtools_wants_updates.set(value);
+ }
+}