diff options
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | components/devtools/Cargo.toml | 1 | ||||
-rw-r--r-- | components/devtools/actors/console.rs | 97 | ||||
-rw-r--r-- | components/devtools/actors/root.rs | 13 | ||||
-rw-r--r-- | components/devtools/actors/worker.rs | 130 | ||||
-rw-r--r-- | components/devtools/lib.rs | 123 | ||||
-rw-r--r-- | components/devtools_traits/lib.rs | 2 | ||||
-rw-r--r-- | components/script/dom/dedicatedworkerglobalscope.rs | 14 | ||||
-rw-r--r-- | components/script/dom/serviceworkerregistration.rs | 2 | ||||
-rw-r--r-- | components/script/dom/worker.rs | 33 | ||||
-rw-r--r-- | components/script/dom/workerglobalscope.rs | 3 | ||||
-rw-r--r-- | components/script/script_thread.rs | 2 | ||||
-rw-r--r-- | components/script/serviceworker_manager.rs | 19 |
13 files changed, 318 insertions, 122 deletions
diff --git a/Cargo.lock b/Cargo.lock index a4f59fc9b40..b515c91219f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1189,6 +1189,7 @@ dependencies = [ "msg", "serde", "serde_json", + "servo_url", "time", "uuid", ] diff --git a/components/devtools/Cargo.toml b/components/devtools/Cargo.toml index 69d440f0f7a..8b7c6d6e199 100644 --- a/components/devtools/Cargo.toml +++ b/components/devtools/Cargo.toml @@ -22,5 +22,6 @@ log = "0.4" msg = {path = "../msg"} serde = "1.0" serde_json = "1.0" +servo_url = { path = "../url" } time = "0.1" uuid = {version = "0.8", features = ["v4"]} diff --git a/components/devtools/actors/console.rs b/components/devtools/actors/console.rs index 3f23a0c0ee5..6a6ef1243d4 100644 --- a/components/devtools/actors/console.rs +++ b/components/devtools/actors/console.rs @@ -10,7 +10,9 @@ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry}; use crate::actors::browsing_context::BrowsingContextActor; use crate::actors::object::ObjectActor; +use crate::actors::worker::WorkerActor; use crate::protocol::JsonPacketStream; +use crate::UniqueId; use crate::{ConsoleAPICall, ConsoleMessage, ConsoleMsg, PageErrorMsg}; use devtools_traits::CachedConsoleMessage; use devtools_traits::EvaluateJSReply::{ActorValue, BooleanValue, StringValue}; @@ -18,10 +20,10 @@ use devtools_traits::EvaluateJSReply::{NullValue, NumberValue, VoidValue}; use devtools_traits::{ CachedConsoleMessageTypes, ConsoleAPI, DevtoolScriptControlMsg, LogLevel, PageError, }; -use ipc_channel::ipc; -use msg::constellation_msg::PipelineId; +use ipc_channel::ipc::{self, IpcSender}; +use msg::constellation_msg::TEST_PIPELINE_ID; 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 time::precise_time_ns; @@ -106,25 +108,68 @@ struct SetPreferencesReply { updated: Vec<String>, } -pub struct ConsoleActor { +pub(crate) enum Root { + BrowsingContext(String), + DedicatedWorker(String), +} + +pub(crate) struct ConsoleActor { pub name: String, - pub browsing_context: String, - pub cached_events: RefCell<HashMap<PipelineId, Vec<CachedConsoleMessage>>>, + pub root: Root, + pub cached_events: RefCell<HashMap<UniqueId, Vec<CachedConsoleMessage>>>, } 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( &self, registry: &ActorRegistry, msg: &Map<String, Value>, ) -> Result<EvaluateJSReply, ()> { - let browsing_context = registry.find::<BrowsingContextActor>(&self.browsing_context); let input = msg.get("text").unwrap().as_str().unwrap().to_owned(); let (chan, port) = ipc::channel().unwrap(); - browsing_context - .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( - browsing_context.active_pipeline.get(), + pipeline, input.clone(), chan, )) @@ -196,21 +241,21 @@ impl ConsoleActor { pub(crate) fn handle_page_error( &self, page_error: PageError, - pipeline: PipelineId, - browsing_context: &BrowsingContextActor, + id: UniqueId, + registry: &ActorRegistry, ) { self.cached_events .borrow_mut() - .entry(pipeline) + .entry(id.clone()) .or_insert(vec![]) .push(CachedConsoleMessage::PageError(page_error.clone())); - if browsing_context.active_pipeline.get() == pipeline { + if id == self.current_unique_id(registry) { let msg = PageErrorMsg { from: self.name(), type_: "pageError".to_owned(), pageError: page_error, }; - for stream in &mut *browsing_context.streams.borrow_mut() { + for stream in &mut *self.streams_mut(registry) { stream.write_json_packet(&msg); } } @@ -219,8 +264,8 @@ impl ConsoleActor { pub(crate) fn handle_console_api( &self, console_message: ConsoleMessage, - pipeline: PipelineId, - browsing_context: &BrowsingContextActor, + id: UniqueId, + registry: &ActorRegistry, ) { let level = match console_message.logLevel { LogLevel::Debug => "debug", @@ -232,7 +277,7 @@ impl ConsoleActor { .to_owned(); self.cached_events .borrow_mut() - .entry(pipeline) + .entry(id.clone()) .or_insert(vec![]) .push(CachedConsoleMessage::ConsoleAPI(ConsoleAPI { type_: "ConsoleAPI".to_owned(), @@ -244,7 +289,7 @@ impl ConsoleActor { private: false, arguments: vec![console_message.message.clone()], })); - if browsing_context.active_pipeline.get() == pipeline { + if id == self.current_unique_id(registry) { let msg = ConsoleAPICall { from: self.name(), type_: "consoleAPICall".to_owned(), @@ -257,7 +302,7 @@ impl ConsoleActor { columnNumber: console_message.columnNumber, }, }; - for stream in &mut *browsing_context.streams.borrow_mut() { + for stream in &mut *self.streams_mut(registry) { stream.write_json_packet(&msg); } } @@ -278,11 +323,11 @@ impl Actor for ConsoleActor { ) -> Result<ActorMessageStatus, ()> { Ok(match msg_type { "clearMessagesCache" => { - let browsing_context = - registry.find::<BrowsingContextActor>(&self.browsing_context); - self.cached_events.borrow_mut().remove(&browsing_context.active_pipeline.get()); + self.cached_events + .borrow_mut() + .remove(&self.current_unique_id(registry)); ActorMessageStatus::Processed - } + }, "getCachedMessages" => { let str_types = msg @@ -302,13 +347,11 @@ impl Actor for ConsoleActor { s => debug!("unrecognized message type requested: \"{}\"", s), }; } - let browsing_context = - registry.find::<BrowsingContextActor>(&self.browsing_context); let mut messages = vec![]; for event in self .cached_events .borrow() - .get(&browsing_context.active_pipeline.get()) + .get(&self.current_unique_id(registry)) .unwrap_or(&vec![]) .iter() { diff --git a/components/devtools/actors/root.rs b/components/devtools/actors/root.rs index da7483ffb34..0010afd3b9f 100644 --- a/components/devtools/actors/root.rs +++ b/components/devtools/actors/root.rs @@ -10,6 +10,7 @@ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry}; use crate::actors::browsing_context::{BrowsingContextActor, BrowsingContextActorMsg}; use crate::actors::device::DeviceActor; use crate::actors::performance::PerformanceActor; +use crate::actors::worker::{WorkerActor, WorkerMsg}; use crate::protocol::{ActorDescription, JsonPacketStream}; use serde_json::{Map, Value}; use std::net::TcpStream; @@ -73,11 +74,6 @@ struct ListWorkersReply { } #[derive(Serialize)] -struct WorkerMsg { - id: u32, -} - -#[derive(Serialize)] struct ListServiceWorkerRegistrationsReply { from: String, registrations: Vec<u32>, // TODO: follow actual JSON structure. @@ -110,6 +106,7 @@ struct GetProcessResponse { pub struct RootActor { pub tabs: Vec<String>, + pub workers: Vec<String>, pub performance: String, pub device: String, pub preference: String, @@ -203,7 +200,11 @@ impl Actor for RootActor { "listWorkers" => { let reply = ListWorkersReply { from: self.name(), - workers: vec![], + workers: self + .workers + .iter() + .map(|name| registry.find::<WorkerActor>(name).encodable()) + .collect(), }; stream.write_json_packet(&reply); ActorMessageStatus::Processed diff --git a/components/devtools/actors/worker.rs b/components/devtools/actors/worker.rs index 082d719de20..fd578d0d3dc 100644 --- a/components/devtools/actors/worker.rs +++ b/components/devtools/actors/worker.rs @@ -3,14 +3,49 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ 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 servo_url::ServoUrl; +use std::cell::RefCell; use std::net::TcpStream; +#[derive(Clone, Copy)] +#[allow(dead_code)] +pub enum WorkerType { + Dedicated = 0, + Shared = 1, + Service = 2, +} + pub struct WorkerActor { pub name: String, pub console: String, + pub thread: String, 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 { @@ -19,11 +54,94 @@ impl Actor for WorkerActor { } fn handle_message( &self, - _: &ActorRegistry, - _: &str, - _: &Map<String, Value>, - _: &mut TcpStream, + _registry: &ActorRegistry, + msg_type: &str, + _msg: &Map<String, Value>, + stream: &mut TcpStream, ) -> 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, +} diff --git a/components/devtools/lib.rs b/components/devtools/lib.rs index 6d9bd938e14..477e44494ee 100644 --- a/components/devtools/lib.rs +++ b/components/devtools/lib.rs @@ -19,7 +19,7 @@ extern crate serde; use crate::actor::{Actor, ActorRegistry}; use crate::actors::browsing_context::BrowsingContextActor; -use crate::actors::console::ConsoleActor; +use crate::actors::console::{ConsoleActor, Root}; use crate::actors::device::DeviceActor; use crate::actors::framerate::FramerateActor; use crate::actors::network_event::{EventActor, NetworkEventActor, ResponseStartMsg}; @@ -27,7 +27,8 @@ use crate::actors::performance::PerformanceActor; use crate::actors::preference::PreferenceActor; use crate::actors::process::ProcessActor; use crate::actors::root::RootActor; -use crate::actors::worker::WorkerActor; +use crate::actors::thread::ThreadActor; +use crate::actors::worker::{WorkerActor, WorkerType}; use crate::protocol::JsonPacketStream; use crossbeam_channel::{unbounded, Receiver, Sender}; use devtools_traits::{ChromeToDevtoolsControlMsg, ConsoleMessage, DevtoolsControlMsg}; @@ -69,6 +70,12 @@ mod actors { } mod protocol; +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +enum UniqueId { + Pipeline(PipelineId), + Worker(WorkerId), +} + #[derive(Serialize)] struct ConsoleAPICall { from: String, @@ -176,6 +183,7 @@ fn run_server( let root = Box::new(RootActor { tabs: vec![], + workers: vec![], device: device.name(), performance: performance.name(), preference: preference.name(), @@ -197,7 +205,7 @@ fn run_server( let mut pipelines: HashMap<PipelineId, BrowsingContextId> = HashMap::new(); let mut actor_requests: HashMap<String, String> = HashMap::new(); - let mut actor_workers: HashMap<(PipelineId, WorkerId), String> = HashMap::new(); + let mut actor_workers: HashMap<WorkerId, String> = HashMap::new(); /// Process the input from a single devtools client until EOF. fn handle_client(actors: Arc<Mutex<ActorRegistry>>, mut stream: TcpStream) { @@ -258,11 +266,11 @@ fn run_server( // TODO: move this into the root or target modules? fn handle_new_global( actors: Arc<Mutex<ActorRegistry>>, - ids: (Option<BrowsingContextId>, PipelineId, Option<WorkerId>), + ids: (BrowsingContextId, PipelineId, Option<WorkerId>), script_sender: IpcSender<DevtoolScriptControlMsg>, browsing_contexts: &mut HashMap<BrowsingContextId, String>, pipelines: &mut HashMap<PipelineId, BrowsingContextId>, - actor_workers: &mut HashMap<(PipelineId, WorkerId), String>, + actor_workers: &mut HashMap<WorkerId, String>, page_info: DevtoolsPageInfo, ) { let mut actors = actors.lock().unwrap(); @@ -271,47 +279,59 @@ fn run_server( let console_name = actors.new_name("console"); - let browsing_context_name = if let Some(browsing_context) = browsing_context { - pipelines.insert(pipeline, browsing_context); - if let Some(actor) = browsing_contexts.get(&browsing_context) { - actor.to_owned() - } else { - let browsing_context_actor = BrowsingContextActor::new( - console_name.clone(), - browsing_context, - page_info, - pipeline, - script_sender.clone(), - &mut *actors, - ); - let name = browsing_context_actor.name(); - browsing_contexts.insert(browsing_context, name.clone()); - actors.register(Box::new(browsing_context_actor)); - name - } - } else { - "".to_owned() - }; + let parent_actor = if let Some(id) = worker_id { + assert!(pipelines.get(&pipeline).is_some()); + assert!(browsing_contexts.get(&browsing_context).is_some()); - // XXXjdm this new actor is useless if it's not a new worker global - let console = ConsoleActor { - name: console_name, - cached_events: Default::default(), - browsing_context: browsing_context_name, - }; + let thread = ThreadActor::new(actors.new_name("context")); + let thread_name = thread.name(); + actors.register(Box::new(thread)); - if let Some(id) = worker_id { + let worker_name = actors.new_name("worker"); let worker = WorkerActor { - name: actors.new_name("worker"), - console: console.name(), + name: worker_name.clone(), + console: console_name.clone(), + thread: thread_name, id: id, + url: page_info.url.clone(), + type_: WorkerType::Dedicated, + script_chan: script_sender, + streams: Default::default(), }; let root = actors.find_mut::<RootActor>("root"); - root.tabs.push(worker.name.clone()); + root.workers.push(worker.name.clone()); - actor_workers.insert((pipeline, id), worker.name.clone()); + actor_workers.insert(id, worker_name.clone()); actors.register(Box::new(worker)); - } + + Root::DedicatedWorker(worker_name) + } else { + pipelines.insert(pipeline, browsing_context); + Root::BrowsingContext( + if let Some(actor) = browsing_contexts.get(&browsing_context) { + actor.to_owned() + } else { + let browsing_context_actor = BrowsingContextActor::new( + console_name.clone(), + browsing_context, + page_info, + pipeline, + script_sender, + &mut *actors, + ); + let name = browsing_context_actor.name(); + browsing_contexts.insert(browsing_context, name.clone()); + actors.register(Box::new(browsing_context_actor)); + name + }, + ) + }; + + let console = ConsoleActor { + name: console_name, + cached_events: Default::default(), + root: parent_actor, + }; actors.register(Box::new(console)); } @@ -319,15 +339,17 @@ fn run_server( fn handle_page_error( actors: Arc<Mutex<ActorRegistry>>, id: PipelineId, + worker_id: Option<WorkerId>, page_error: PageError, browsing_contexts: &HashMap<BrowsingContextId, String>, + actor_workers: &HashMap<WorkerId, String>, pipelines: &HashMap<PipelineId, BrowsingContextId>, ) { let console_actor_name = match find_console_actor( actors.clone(), id, - None, - &HashMap::new(), + worker_id, + actor_workers, browsing_contexts, pipelines, ) { @@ -336,9 +358,8 @@ fn run_server( }; let actors = actors.lock().unwrap(); let console_actor = actors.find::<ConsoleActor>(&console_actor_name); - let browsing_context_actor = - actors.find::<BrowsingContextActor>(&console_actor.browsing_context); - console_actor.handle_page_error(page_error, id, &browsing_context_actor); + let id = worker_id.map_or(UniqueId::Pipeline(id), UniqueId::Worker); + console_actor.handle_page_error(page_error, id, &*actors); } fn handle_console_message( @@ -347,7 +368,7 @@ fn run_server( worker_id: Option<WorkerId>, console_message: ConsoleMessage, 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( @@ -363,22 +384,21 @@ fn run_server( }; let actors = actors.lock().unwrap(); let console_actor = actors.find::<ConsoleActor>(&console_actor_name); - let browsing_context_actor = - actors.find::<BrowsingContextActor>(&console_actor.browsing_context); - console_actor.handle_console_api(console_message, id, &browsing_context_actor); + let id = worker_id.map_or(UniqueId::Pipeline(id), UniqueId::Worker); + console_actor.handle_console_api(console_message, id, &*actors); } fn find_console_actor( actors: Arc<Mutex<ActorRegistry>>, pipeline: PipelineId, worker_id: Option<WorkerId>, - actor_workers: &HashMap<(PipelineId, WorkerId), String>, + actor_workers: &HashMap<WorkerId, String>, browsing_contexts: &HashMap<BrowsingContextId, String>, pipelines: &HashMap<PipelineId, BrowsingContextId>, ) -> Option<String> { let actors = actors.lock().unwrap(); if let Some(worker_id) = worker_id { - let actor_name = (*actor_workers).get(&(pipeline, worker_id))?; + let actor_name = actor_workers.get(&worker_id)?; Some(actors.find::<WorkerActor>(actor_name).console.clone()) } else { let id = pipelines.get(&pipeline)?; @@ -397,7 +417,7 @@ fn run_server( mut connections: Vec<TcpStream>, browsing_contexts: &HashMap<BrowsingContextId, String>, actor_requests: &mut HashMap<String, String>, - actor_workers: &HashMap<(PipelineId, WorkerId), String>, + actor_workers: &HashMap<WorkerId, String>, pipelines: &HashMap<PipelineId, BrowsingContextId>, pipeline_id: PipelineId, request_id: String, @@ -570,6 +590,7 @@ fn run_server( .expect("Thread spawning failed"); while let Ok(msg) = receiver.recv() { + debug!("{:?}", msg); match msg { DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::AddClient(stream)) => { let actors = actors.clone(); @@ -619,8 +640,10 @@ fn run_server( )) => handle_page_error( actors.clone(), id, + None, page_error, &browsing_contexts, + &actor_workers, &pipelines, ), DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::ReportCSSError( diff --git a/components/devtools_traits/lib.rs b/components/devtools_traits/lib.rs index f55e0990588..2ac1cae598a 100644 --- a/components/devtools_traits/lib.rs +++ b/components/devtools_traits/lib.rs @@ -80,7 +80,7 @@ pub enum ScriptToDevtoolsControlMsg { /// A new global object was created, associated with a particular pipeline. /// The means of communicating directly with it are provided. NewGlobal( - (Option<BrowsingContextId>, PipelineId, Option<WorkerId>), + (BrowsingContextId, PipelineId, Option<WorkerId>), IpcSender<DevtoolScriptControlMsg>, DevtoolsPageInfo, ), diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index 150f7920fff..a4970afcca4 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -43,7 +43,7 @@ use js::jsapi::JS_AddInterruptCallback; use js::jsapi::{Heap, JSContext, JSObject}; use js::jsval::UndefinedValue; 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::request::{CredentialsMode, Destination, ParserMetadata}; use net_traits::request::{Referrer, RequestBuilder, RequestMode}; @@ -180,6 +180,7 @@ pub struct DedicatedWorkerGlobalScope { parent_sender: Box<dyn ScriptChan + Send>, #[ignore_malloc_size_of = "Arc"] image_cache: Arc<dyn ImageCache>, + browsing_context: Option<BrowsingContextId>, } impl WorkerEventLoopMethods for DedicatedWorkerGlobalScope { @@ -221,6 +222,7 @@ impl DedicatedWorkerGlobalScope { receiver: Receiver<DedicatedWorkerScriptMsg>, closing: Arc<AtomicBool>, image_cache: Arc<dyn ImageCache>, + browsing_context: Option<BrowsingContextId>, ) -> DedicatedWorkerGlobalScope { DedicatedWorkerGlobalScope { workerglobalscope: WorkerGlobalScope::new_inherited( @@ -237,6 +239,7 @@ impl DedicatedWorkerGlobalScope { parent_sender: parent_sender, worker: DomRefCell::new(None), image_cache: image_cache, + browsing_context, } } @@ -253,6 +256,7 @@ impl DedicatedWorkerGlobalScope { receiver: Receiver<DedicatedWorkerScriptMsg>, closing: Arc<AtomicBool>, image_cache: Arc<dyn ImageCache>, + browsing_context: Option<BrowsingContextId>, ) -> DomRoot<DedicatedWorkerGlobalScope> { let cx = runtime.cx(); let scope = Box::new(DedicatedWorkerGlobalScope::new_inherited( @@ -267,6 +271,7 @@ impl DedicatedWorkerGlobalScope { receiver, closing, image_cache, + browsing_context, )); unsafe { DedicatedWorkerGlobalScopeBinding::Wrap(SafeJSContext::from_ptr(cx), scope) } } @@ -286,6 +291,7 @@ impl DedicatedWorkerGlobalScope { worker_type: WorkerType, closing: Arc<AtomicBool>, image_cache: Arc<dyn ImageCache>, + browsing_context: Option<BrowsingContextId>, ) { let serialized_worker_url = worker_url.to_string(); let name = format!("WebWorker for {}", serialized_worker_url); @@ -354,6 +360,7 @@ impl DedicatedWorkerGlobalScope { receiver, closing, image_cache, + browsing_context, ); // 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. @@ -467,6 +474,7 @@ impl DedicatedWorkerGlobalScope { } fn handle_mixed_message(&self, msg: MixedMessage) { + // FIXME(#26324): `self.worker` is None in devtools messages. match msg { MixedMessage::FromDevtools(msg) => match msg { DevtoolScriptControlMsg::EvaluateJS(_pipe_id, string, sender) => { @@ -551,6 +559,10 @@ impl DedicatedWorkerGlobalScope { .expect("Sending to parent failed"); Ok(()) } + + pub(crate) fn browsing_context(&self) -> Option<BrowsingContextId> { + self.browsing_context + } } #[allow(unsafe_code)] diff --git a/components/script/dom/serviceworkerregistration.rs b/components/script/dom/serviceworkerregistration.rs index f242da12404..9bb578e0d59 100644 --- a/components/script/dom/serviceworkerregistration.rs +++ b/components/script/dom/serviceworkerregistration.rs @@ -112,7 +112,7 @@ impl ServiceWorkerRegistration { let worker_id = WorkerId(Uuid::new_v4()); let devtools_chan = global.devtools_chan().cloned(); - let init = prepare_workerscope_init(&global, None); + let init = prepare_workerscope_init(&global, None, None); ScopeThings { script_url: script_url, init: init, diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs index 9c0cc91273a..c9555c88517 100644 --- a/components/script/dom/worker.rs +++ b/components/script/dom/worker.rs @@ -20,6 +20,7 @@ use crate::dom::dedicatedworkerglobalscope::{ use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; use crate::dom::messageevent::MessageEvent; +use crate::dom::window::Window; use crate::dom::workerglobalscope::prepare_workerscope_init; use crate::realms::enter_realm; use crate::script_runtime::JSContext; @@ -95,23 +96,34 @@ impl Worker { 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 worker_id = WorkerId(Uuid::new_v4()); if let Some(ref chan) = global.devtools_chan() { let pipeline_id = global.pipeline_id(); let title = format!("Worker for {}", worker_url); - let page_info = DevtoolsPageInfo { - title: title, - url: worker_url.clone(), - }; - let _ = chan.send(ScriptToDevtoolsControlMsg::NewGlobal( - (None, pipeline_id, Some(worker_id)), - devtools_sender.clone(), - page_info, - )); + if let Some(browsing_context) = browsing_context { + let page_info = DevtoolsPageInfo { + title: title, + url: worker_url.clone(), + }; + let _ = chan.send(ScriptToDevtoolsControlMsg::NewGlobal( + (browsing_context, pipeline_id, Some(worker_id)), + devtools_sender.clone(), + 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( init, @@ -126,6 +138,7 @@ impl Worker { worker_options.type_, closing, global.image_cache(), + browsing_context, ); Ok(worker) diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs index 15eb79858fe..684760c3197 100644 --- a/components/script/dom/workerglobalscope.rs +++ b/components/script/dom/workerglobalscope.rs @@ -62,6 +62,7 @@ use uuid::Uuid; pub fn prepare_workerscope_init( global: &GlobalScope, devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>, + worker_id: Option<WorkerId>, ) -> WorkerGlobalScopeInit { let init = WorkerGlobalScopeInit { resource_threads: global.resource_threads().clone(), @@ -71,7 +72,7 @@ pub fn prepare_workerscope_init( from_devtools_sender: devtools_sender, script_to_constellation_chan: global.script_to_constellation_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(), origin: global.origin().immutable().clone(), is_headless: global.is_headless(), diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 7431bcf1032..01d8e7873e2 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -3384,7 +3384,7 @@ impl ScriptThread { url: url, }; chan.send(ScriptToDevtoolsControlMsg::NewGlobal( - (Some(bc), p, w), + (bc, p, w), self.devtools_sender.clone(), page_info.clone(), )) diff --git a/components/script/serviceworker_manager.rs b/components/script/serviceworker_manager.rs index 0383d7bf6da..73ead01fe17 100644 --- a/components/script/serviceworker_manager.rs +++ b/components/script/serviceworker_manager.rs @@ -11,7 +11,6 @@ use crate::dom::abstractworker::WorkerScriptMsg; use crate::dom::serviceworkerglobalscope::{ServiceWorkerGlobalScope, ServiceWorkerScriptMsg}; use crate::dom::serviceworkerregistration::longest_prefix_match; use crossbeam_channel::{unbounded, Receiver, RecvError, Sender}; -use devtools_traits::{DevtoolsPageInfo, ScriptToDevtoolsControlMsg}; use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::router::ROUTER; use net_traits::{CoreResourceMsg, CustomResponseMediator}; @@ -79,23 +78,7 @@ impl ServiceWorkerManager { let scope_things = self.registered_workers.get(&scope_url); if let Some(scope_things) = scope_things { let (sender, receiver) = unbounded(); - 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( - ( - None, - scope_things.init.pipeline_id, - Some(scope_things.worker_id), - ), - devtools_sender, - page_info, - )); - }; + let (_devtools_sender, devtools_receiver) = ipc::channel().unwrap(); ServiceWorkerGlobalScope::run_serviceworker_scope( scope_things.clone(), sender.clone(), |