diff options
Diffstat (limited to 'components')
35 files changed, 380 insertions, 184 deletions
diff --git a/components/canvas/Cargo.toml b/components/canvas/Cargo.toml index 2281ea30242..7e3267148e6 100644 --- a/components/canvas/Cargo.toml +++ b/components/canvas/Cargo.toml @@ -40,7 +40,7 @@ style = { path = "../style" } style_traits = { path = "../style_traits" } # NOTE: the sm-angle feature only enables angle on windows, not other platforms! surfman = { version = "0.3", features = ["sm-angle","sm-angle-default"] } -surfman-chains = "0.4" +surfman-chains = "0.5" surfman-chains-api = "0.2" time = { version = "0.1.0", optional = true } webrender = { git = "https://github.com/servo/webrender" } diff --git a/components/canvas/webgl_thread.rs b/components/canvas/webgl_thread.rs index 3c27c523866..168a7e9f070 100644 --- a/components/canvas/webgl_thread.rs +++ b/components/canvas/webgl_thread.rs @@ -827,22 +827,30 @@ impl WebGLThread { debug!("Swapping {:?}", context_id); swap_chain - .swap_buffers(&mut self.device, &mut data.ctx) + .swap_buffers( + &mut self.device, + &mut data.ctx, + if data.attributes.preserve_drawing_buffer { + surfman_chains::PreserveBuffer::Yes(&*data.gl) + } else { + surfman_chains::PreserveBuffer::No + }, + ) .unwrap(); debug_assert_eq!(data.gl.get_error(), gl::NO_ERROR); - // TODO: if preserveDrawingBuffer is true, then blit the front buffer to the back buffer - // https://github.com/servo/servo/issues/24604 - debug!("Clearing {:?}", context_id); - let alpha = data - .state - .requested_flags - .contains(ContextAttributeFlags::ALPHA); - let clear_color = [0.0, 0.0, 0.0, !alpha as i32 as f32]; - swap_chain - .clear_surface(&mut self.device, &mut data.ctx, &*data.gl, clear_color) - .unwrap(); - debug_assert_eq!(data.gl.get_error(), gl::NO_ERROR); + if !data.attributes.preserve_drawing_buffer { + debug!("Clearing {:?}", context_id); + let alpha = data + .state + .requested_flags + .contains(ContextAttributeFlags::ALPHA); + let clear_color = [0.0, 0.0, 0.0, !alpha as i32 as f32]; + swap_chain + .clear_surface(&mut self.device, &mut data.ctx, &*data.gl, clear_color) + .unwrap(); + debug_assert_eq!(data.gl.get_error(), gl::NO_ERROR); + } // Rebind framebuffers as appropriate. debug!("Rebinding {:?}", context_id); diff --git a/components/devtools/actor.rs b/components/devtools/actor.rs index 158092ee1a8..641c6f717d4 100644 --- a/components/devtools/actor.rs +++ b/components/devtools/actor.rs @@ -3,6 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ /// General actor system infrastructure. +use crate::StreamId; use devtools_traits::PreciseTime; use serde_json::{Map, Value}; use std::any::Any; @@ -21,18 +22,20 @@ pub enum ActorMessageStatus { /// A common trait for all devtools actors that encompasses an immutable name /// and the ability to process messages that are directed to particular actors. /// TODO: ensure the name is immutable -pub trait Actor: Any + ActorAsAny { +pub(crate) trait Actor: Any + ActorAsAny { fn handle_message( &self, registry: &ActorRegistry, msg_type: &str, msg: &Map<String, Value>, stream: &mut TcpStream, + id: StreamId, ) -> Result<ActorMessageStatus, ()>; fn name(&self) -> String; + fn cleanup(&self, _id: StreamId) {} } -pub trait ActorAsAny { +pub(crate) trait ActorAsAny { fn actor_as_any(&self) -> &dyn Any; fn actor_as_any_mut(&mut self) -> &mut dyn Any; } @@ -71,6 +74,12 @@ impl ActorRegistry { } } + pub(crate) fn cleanup(&self, id: StreamId) { + for actor in self.actors.values() { + actor.cleanup(id); + } + } + /// Creating shareable registry pub fn create_shareable(self) -> Arc<Mutex<ActorRegistry>> { if let Some(shareable) = self.shareable { @@ -131,11 +140,11 @@ impl ActorRegistry { } /// Add an actor to the registry of known actors that can receive messages. - pub fn register(&mut self, actor: Box<dyn Actor + Send>) { + pub(crate) fn register(&mut self, actor: Box<dyn Actor + Send>) { self.actors.insert(actor.name(), actor); } - pub fn register_later(&self, actor: Box<dyn Actor + Send>) { + pub(crate) fn register_later(&self, actor: Box<dyn Actor + Send>) { let mut actors = self.new_actors.borrow_mut(); actors.push(actor); } @@ -154,10 +163,11 @@ impl ActorRegistry { /// Attempt to process a message as directed by its `to` property. If the actor is not /// found or does not indicate that it knew how to process the message, ignore the failure. - pub fn handle_message( + pub(crate) fn handle_message( &mut self, msg: &Map<String, Value>, stream: &mut TcpStream, + id: StreamId, ) -> Result<(), ()> { let to = match msg.get("to") { Some(to) => to.as_str().unwrap(), @@ -171,7 +181,7 @@ impl ActorRegistry { None => debug!("message received for unknown actor \"{}\"", to), Some(actor) => { let msg_type = msg.get("type").unwrap().as_str().unwrap(); - if actor.handle_message(self, msg_type, msg, stream)? != + if actor.handle_message(self, msg_type, msg, stream, id)? != ActorMessageStatus::Processed { debug!( diff --git a/components/devtools/actors/browsing_context.rs b/components/devtools/actors/browsing_context.rs index 708c9f69de9..beee86e50b5 100644 --- a/components/devtools/actors/browsing_context.rs +++ b/components/devtools/actors/browsing_context.rs @@ -17,6 +17,7 @@ use crate::actors::tab::TabDescriptorActor; use crate::actors::thread::ThreadActor; use crate::actors::timeline::TimelineActor; use crate::protocol::JsonPacketStream; +use crate::StreamId; use devtools_traits::DevtoolScriptControlMsg::{self, WantsLiveNotifications}; use devtools_traits::DevtoolsPageInfo; use devtools_traits::NavigationState; @@ -24,6 +25,7 @@ use ipc_channel::ipc::IpcSender; use msg::constellation_msg::{BrowsingContextId, PipelineId}; use serde_json::{Map, Value}; use std::cell::{Cell, RefCell}; +use std::collections::HashMap; use std::net::TcpStream; #[derive(Serialize)] @@ -118,7 +120,7 @@ pub struct BrowsingContextActorMsg { manifestActor: String,*/ } -pub struct BrowsingContextActor { +pub(crate) struct BrowsingContextActor { pub name: String, pub title: RefCell<String>, pub url: RefCell<String>, @@ -131,7 +133,7 @@ pub struct BrowsingContextActor { pub styleSheets: String, pub thread: String, pub tab: String, - pub streams: RefCell<Vec<TcpStream>>, + pub streams: RefCell<HashMap<StreamId, TcpStream>>, pub browsing_context_id: BrowsingContextId, pub active_pipeline: Cell<PipelineId>, pub script_chan: IpcSender<DevtoolScriptControlMsg>, @@ -148,6 +150,7 @@ impl Actor for BrowsingContextActor { msg_type: &str, msg: &Map<String, Value>, stream: &mut TcpStream, + id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(match msg_type { "reconfigure" => { @@ -160,7 +163,7 @@ impl Actor for BrowsingContextActor { } } } - stream.write_json_packet(&ReconfigureReply { from: self.name() }); + let _ = stream.write_json_packet(&ReconfigureReply { from: self.name() }); ActorMessageStatus::Processed }, @@ -181,26 +184,26 @@ impl Actor for BrowsingContextActor { watchpoints: false, }, }; - self.streams.borrow_mut().push(stream.try_clone().unwrap()); - stream.write_json_packet(&msg); + + if stream.write_json_packet(&msg).is_err() { + return Ok(ActorMessageStatus::Processed); + } + self.streams + .borrow_mut() + .insert(id, stream.try_clone().unwrap()); self.script_chan .send(WantsLiveNotifications(self.active_pipeline.get(), true)) .unwrap(); ActorMessageStatus::Processed }, - //FIXME: The current implementation won't work for multiple connections. Need to ensure - // that the correct stream is removed. "detach" => { let msg = BrowsingContextDetachedReply { from: self.name(), type_: "detached".to_owned(), }; - self.streams.borrow_mut().pop(); - stream.write_json_packet(&msg); - self.script_chan - .send(WantsLiveNotifications(self.active_pipeline.get(), false)) - .unwrap(); + let _ = stream.write_json_packet(&msg); + self.cleanup(id); ActorMessageStatus::Processed }, @@ -215,7 +218,7 @@ impl Actor for BrowsingContextActor { title: self.title.borrow().clone(), }], }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, @@ -224,13 +227,22 @@ impl Actor for BrowsingContextActor { from: self.name(), workers: vec![], }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, _ => ActorMessageStatus::Ignored, }) } + + fn cleanup(&self, id: StreamId) { + self.streams.borrow_mut().remove(&id); + if self.streams.borrow().is_empty() { + self.script_chan + .send(WantsLiveNotifications(self.active_pipeline.get(), false)) + .unwrap(); + } + } } impl BrowsingContextActor { @@ -284,7 +296,7 @@ impl BrowsingContextActor { styleSheets: styleSheets.name(), tab: tabdesc.name(), thread: thread.name(), - streams: RefCell::new(Vec::new()), + streams: RefCell::new(HashMap::new()), browsing_context_id: id, active_pipeline: Cell::new(pipeline), }; @@ -347,8 +359,8 @@ impl BrowsingContextActor { state: state.to_owned(), isFrameSwitching: false, }; - for stream in &mut *self.streams.borrow_mut() { - stream.write_json_packet(&msg); + for stream in self.streams.borrow_mut().values_mut() { + let _ = stream.write_json_packet(&msg); } } diff --git a/components/devtools/actors/console.rs b/components/devtools/actors/console.rs index 4576a296775..86e4f39dd33 100644 --- a/components/devtools/actors/console.rs +++ b/components/devtools/actors/console.rs @@ -12,7 +12,7 @@ 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::{StreamId, UniqueId}; use devtools_traits::CachedConsoleMessage; use devtools_traits::ConsoleMessage; use devtools_traits::EvaluateJSReply::{ActorValue, BooleanValue, StringValue}; @@ -23,7 +23,7 @@ use devtools_traits::{ use ipc_channel::ipc::{self, IpcSender}; use msg::constellation_msg::TEST_PIPELINE_ID; use serde_json::{self, Map, Number, Value}; -use std::cell::{RefCell, RefMut}; +use std::cell::RefCell; use std::collections::HashMap; use std::net::TcpStream; use time::precise_time_ns; @@ -130,15 +130,20 @@ impl ConsoleActor { } } - fn streams_mut<'a>(&self, registry: &'a ActorRegistry) -> RefMut<'a, Vec<TcpStream>> { + fn streams_mut<'a>(&self, registry: &'a ActorRegistry, cb: impl Fn(&mut TcpStream)) { match &self.root { Root::BrowsingContext(bc) => registry .find::<BrowsingContextActor>(bc) .streams - .borrow_mut(), - Root::DedicatedWorker(worker) => { - registry.find::<WorkerActor>(worker).streams.borrow_mut() - }, + .borrow_mut() + .values_mut() + .for_each(cb), + Root::DedicatedWorker(worker) => registry + .find::<WorkerActor>(worker) + .streams + .borrow_mut() + .values_mut() + .for_each(cb), } } @@ -255,9 +260,9 @@ impl ConsoleActor { type_: "pageError".to_owned(), pageError: page_error, }; - for stream in &mut *self.streams_mut(registry) { - stream.write_json_packet(&msg); - } + self.streams_mut(registry, |stream| { + let _ = stream.write_json_packet(&msg); + }); } } @@ -303,9 +308,9 @@ impl ConsoleActor { columnNumber: console_message.columnNumber, }, }; - for stream in &mut *self.streams_mut(registry) { - stream.write_json_packet(&msg); - } + self.streams_mut(registry, |stream| { + let _ = stream.write_json_packet(&msg); + }); } } } @@ -321,6 +326,7 @@ impl Actor for ConsoleActor { msg_type: &str, msg: &Map<String, Value>, stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(match msg_type { "clearMessagesCache" => { @@ -380,7 +386,7 @@ impl Actor for ConsoleActor { from: self.name(), messages: messages, }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, @@ -396,7 +402,7 @@ impl Actor for ConsoleActor { .collect(), traits: StartedListenersTraits, }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, @@ -413,7 +419,7 @@ impl Actor for ConsoleActor { .map(|listener| listener.as_str().unwrap().to_owned()) .collect(), }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, @@ -425,13 +431,13 @@ impl Actor for ConsoleActor { matches: vec![], matchProp: "".to_owned(), }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, "evaluateJS" => { let msg = self.evaluateJS(®istry, &msg); - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, @@ -443,7 +449,9 @@ impl Actor for ConsoleActor { }; // Emit an eager reply so that the client starts listening // for an async event with the resultID - stream.write_json_packet(&early_reply); + if stream.write_json_packet(&early_reply).is_err() { + return Ok(ActorMessageStatus::Processed); + } 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 @@ -464,7 +472,7 @@ impl Actor for ConsoleActor { helperResult: reply.helperResult, }; // Send the data from evaluateJS along with a resultID - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, @@ -473,7 +481,7 @@ impl Actor for ConsoleActor { from: self.name(), updated: vec![], }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, diff --git a/components/devtools/actors/device.rs b/components/devtools/actors/device.rs index 11785d8c0b8..c54b72b6d5d 100644 --- a/components/devtools/actors/device.rs +++ b/components/devtools/actors/device.rs @@ -5,6 +5,7 @@ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry}; use crate::protocol::JsonPacketStream; use crate::protocol::{ActorDescription, Method}; +use crate::StreamId; use serde_json::{Map, Value}; use std::net::TcpStream; @@ -34,6 +35,7 @@ impl Actor for DeviceActor { msg_type: &str, _msg: &Map<String, Value>, stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(match msg_type { "getDescription" => { @@ -44,7 +46,7 @@ impl Actor for DeviceActor { platformVersion: "71.0".to_string(), }, }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, diff --git a/components/devtools/actors/emulation.rs b/components/devtools/actors/emulation.rs index 94b769a106f..58f13b16d34 100644 --- a/components/devtools/actors/emulation.rs +++ b/components/devtools/actors/emulation.rs @@ -3,6 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry}; +use crate::StreamId; use serde_json::{Map, Value}; use std::net::TcpStream; @@ -21,6 +22,7 @@ impl Actor for EmulationActor { msg_type: &str, _msg: &Map<String, Value>, _stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(match msg_type { _ => ActorMessageStatus::Ignored, diff --git a/components/devtools/actors/framerate.rs b/components/devtools/actors/framerate.rs index 243c7ea4c4c..6203be2c57e 100644 --- a/components/devtools/actors/framerate.rs +++ b/components/devtools/actors/framerate.rs @@ -4,6 +4,7 @@ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry}; use crate::actors::timeline::HighResolutionStamp; +use crate::StreamId; use devtools_traits::DevtoolScriptControlMsg; use ipc_channel::ipc::IpcSender; use msg::constellation_msg::PipelineId; @@ -32,6 +33,7 @@ impl Actor for FramerateActor { _msg_type: &str, _msg: &Map<String, Value>, _stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(ActorMessageStatus::Ignored) } diff --git a/components/devtools/actors/inspector.rs b/components/devtools/actors/inspector.rs index d2f0929ac89..d01267b68e7 100644 --- a/components/devtools/actors/inspector.rs +++ b/components/devtools/actors/inspector.rs @@ -8,6 +8,7 @@ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry}; use crate::actors::browsing_context::BrowsingContextActor; use crate::protocol::JsonPacketStream; +use crate::StreamId; use devtools_traits::DevtoolScriptControlMsg::{GetChildren, GetDocumentElement, GetRootNode}; use devtools_traits::DevtoolScriptControlMsg::{GetLayout, ModifyAttribute}; use devtools_traits::{ComputedNodeLayout, DevtoolScriptControlMsg, NodeInfo}; @@ -68,17 +69,18 @@ impl Actor for HighlighterActor { msg_type: &str, _msg: &Map<String, Value>, stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(match msg_type { "showBoxModel" => { let msg = ShowBoxModelReply { from: self.name() }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, "hideBoxModel" => { let msg = HideBoxModelReply { from: self.name() }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, @@ -103,6 +105,7 @@ impl Actor for NodeActor { msg_type: &str, msg: &Map<String, Value>, stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(match msg_type { "modifyAttributes" => { @@ -123,7 +126,7 @@ impl Actor for NodeActor { )) .unwrap(); let reply = ModifyAttributeReply { from: self.name() }; - stream.write_json_packet(&reply); + let _ = stream.write_json_packet(&reply); ActorMessageStatus::Processed }, @@ -289,11 +292,12 @@ impl Actor for WalkerActor { msg_type: &str, msg: &Map<String, Value>, stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(match msg_type { "querySelector" => { let msg = QuerySelectorReply { from: self.name() }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, @@ -310,13 +314,13 @@ impl Actor for WalkerActor { from: self.name(), node: node, }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, "clearPseudoClassLocks" => { let msg = ClearPseudoclassesReply { from: self.name() }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, @@ -343,7 +347,7 @@ impl Actor for WalkerActor { .collect(), from: self.name(), }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, @@ -471,6 +475,7 @@ impl Actor for PageStyleActor { msg_type: &str, msg: &Map<String, Value>, stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(match msg_type { "getApplied" => { @@ -481,7 +486,7 @@ impl Actor for PageStyleActor { sheets: vec![], from: self.name(), }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, @@ -491,7 +496,7 @@ impl Actor for PageStyleActor { computed: vec![], from: self.name(), }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, @@ -576,7 +581,7 @@ impl Actor for PageStyleActor { }; let msg = serde_json::to_string(&msg).unwrap(); let msg = serde_json::from_str::<Value>(&msg).unwrap(); - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, @@ -596,6 +601,7 @@ impl Actor for InspectorActor { msg_type: &str, _msg: &Map<String, Value>, stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { let browsing_context = registry.find::<BrowsingContextActor>(&self.browsing_context); let pipeline = browsing_context.active_pipeline.get(); @@ -625,7 +631,7 @@ impl Actor for InspectorActor { root: node, }, }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, @@ -647,7 +653,7 @@ impl Actor for InspectorActor { actor: self.pageStyle.borrow().clone().unwrap(), }, }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, @@ -670,7 +676,7 @@ impl Actor for InspectorActor { actor: self.highlighter.borrow().clone().unwrap(), }, }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, diff --git a/components/devtools/actors/memory.rs b/components/devtools/actors/memory.rs index 3240a105260..67f83548f9c 100644 --- a/components/devtools/actors/memory.rs +++ b/components/devtools/actors/memory.rs @@ -3,6 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry}; +use crate::StreamId; use serde_json::{Map, Value}; use std::net::TcpStream; @@ -34,6 +35,7 @@ impl Actor for MemoryActor { _msg_type: &str, _msg: &Map<String, Value>, _stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(ActorMessageStatus::Ignored) } diff --git a/components/devtools/actors/network_event.rs b/components/devtools/actors/network_event.rs index 8af38f52c0c..622ac6002eb 100644 --- a/components/devtools/actors/network_event.rs +++ b/components/devtools/actors/network_event.rs @@ -8,6 +8,7 @@ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry}; use crate::protocol::JsonPacketStream; +use crate::StreamId; use devtools_traits::HttpRequest as DevtoolsHttpRequest; use devtools_traits::HttpResponse as DevtoolsHttpResponse; use headers::{ContentType, Cookie, HeaderMapExt}; @@ -180,6 +181,7 @@ impl Actor for NetworkEventActor { msg_type: &str, _msg: &Map<String, Value>, stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(match msg_type { "getRequestHeaders" => { @@ -201,7 +203,7 @@ impl Actor for NetworkEventActor { headerSize: headersSize, rawHeaders: rawHeadersString, }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, "getRequestCookies" => { @@ -217,7 +219,7 @@ impl Actor for NetworkEventActor { from: self.name(), cookies: cookies, }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, "getRequestPostData" => { @@ -226,7 +228,7 @@ impl Actor for NetworkEventActor { postData: self.request.body.clone(), postDataDiscarded: false, }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, "getResponseHeaders" => { @@ -251,7 +253,7 @@ impl Actor for NetworkEventActor { headerSize: headersSize, rawHeaders: rawHeadersString, }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); } ActorMessageStatus::Processed }, @@ -268,7 +270,7 @@ impl Actor for NetworkEventActor { from: self.name(), cookies: cookies, }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, "getResponseContent" => { @@ -277,7 +279,7 @@ impl Actor for NetworkEventActor { content: self.response.body.clone(), contentDiscarded: self.response.body.is_none(), }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, "getEventTimings" => { @@ -297,7 +299,7 @@ impl Actor for NetworkEventActor { timings: timingsObj, totalTime: total, }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, "getSecurityInfo" => { @@ -308,7 +310,7 @@ impl Actor for NetworkEventActor { state: "insecure".to_owned(), }, }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, _ => ActorMessageStatus::Ignored, diff --git a/components/devtools/actors/object.rs b/components/devtools/actors/object.rs index fc2a2002e7d..b10f5e9fd65 100644 --- a/components/devtools/actors/object.rs +++ b/components/devtools/actors/object.rs @@ -3,6 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry}; +use crate::StreamId; use serde_json::{Map, Value}; use std::net::TcpStream; @@ -21,6 +22,7 @@ impl Actor for ObjectActor { _: &str, _: &Map<String, Value>, _: &mut TcpStream, + _: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(ActorMessageStatus::Ignored) } diff --git a/components/devtools/actors/performance.rs b/components/devtools/actors/performance.rs index d26e4aee1d6..497922a2745 100644 --- a/components/devtools/actors/performance.rs +++ b/components/devtools/actors/performance.rs @@ -4,6 +4,7 @@ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry}; use crate::protocol::{ActorDescription, JsonPacketStream, Method}; +use crate::StreamId; use serde_json::{Map, Value}; use std::net::TcpStream; @@ -57,6 +58,7 @@ impl Actor for PerformanceActor { msg_type: &str, _msg: &Map<String, Value>, stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(match msg_type { "connect" => { @@ -72,7 +74,7 @@ impl Actor for PerformanceActor { }, }, }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, "canCurrentlyRecord" => { @@ -83,7 +85,7 @@ impl Actor for PerformanceActor { errors: vec![], }, }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, _ => ActorMessageStatus::Ignored, diff --git a/components/devtools/actors/preference.rs b/components/devtools/actors/preference.rs index aefd8638631..a690148342f 100644 --- a/components/devtools/actors/preference.rs +++ b/components/devtools/actors/preference.rs @@ -4,6 +4,7 @@ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry}; use crate::protocol::JsonPacketStream; +use crate::StreamId; use serde_json::{Map, Value}; use std::net::TcpStream; @@ -28,6 +29,7 @@ impl Actor for PreferenceActor { msg_type: &str, _msg: &Map<String, Value>, stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(match msg_type { "getBoolPref" => { @@ -35,7 +37,7 @@ impl Actor for PreferenceActor { from: self.name(), value: false, }; - stream.write_json_packet(&reply); + let _ = stream.write_json_packet(&reply); ActorMessageStatus::Processed }, @@ -44,7 +46,7 @@ impl Actor for PreferenceActor { from: self.name(), value: "".to_owned(), }; - stream.write_json_packet(&reply); + let _ = stream.write_json_packet(&reply); ActorMessageStatus::Processed }, @@ -53,7 +55,7 @@ impl Actor for PreferenceActor { from: self.name(), value: 0, }; - stream.write_json_packet(&reply); + let _ = stream.write_json_packet(&reply); ActorMessageStatus::Processed }, diff --git a/components/devtools/actors/process.rs b/components/devtools/actors/process.rs index de9a9f96ed1..8b2d54d5ee7 100644 --- a/components/devtools/actors/process.rs +++ b/components/devtools/actors/process.rs @@ -4,6 +4,7 @@ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry}; use crate::protocol::JsonPacketStream; +use crate::StreamId; use serde_json::{Map, Value}; use std::net::TcpStream; @@ -34,6 +35,7 @@ impl Actor for ProcessActor { msg_type: &str, _msg: &Map<String, Value>, stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(match msg_type { "listWorkers" => { @@ -41,7 +43,7 @@ impl Actor for ProcessActor { from: self.name(), workers: vec![], }; - stream.write_json_packet(&reply); + let _ = stream.write_json_packet(&reply); ActorMessageStatus::Processed }, diff --git a/components/devtools/actors/profiler.rs b/components/devtools/actors/profiler.rs index a6aacb66caa..f7d5a338525 100644 --- a/components/devtools/actors/profiler.rs +++ b/components/devtools/actors/profiler.rs @@ -3,6 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry}; +use crate::StreamId; use serde_json::{Map, Value}; use std::net::TcpStream; @@ -21,6 +22,7 @@ impl Actor for ProfilerActor { _msg_type: &str, _msg: &Map<String, Value>, _stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(ActorMessageStatus::Ignored) } diff --git a/components/devtools/actors/root.rs b/components/devtools/actors/root.rs index 1965d973728..1f0ae9cd33e 100644 --- a/components/devtools/actors/root.rs +++ b/components/devtools/actors/root.rs @@ -12,6 +12,7 @@ use crate::actors::performance::PerformanceActor; use crate::actors::tab::{TabDescriptorActor, TabDescriptorActorMsg}; use crate::actors::worker::{WorkerActor, WorkerMsg}; use crate::protocol::{ActorDescription, JsonPacketStream}; +use crate::StreamId; use serde_json::{Map, Value}; use std::net::TcpStream; @@ -124,6 +125,7 @@ impl Actor for RootActor { msg_type: &str, _msg: &Map<String, Value>, stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(match msg_type { "listAddons" => { @@ -131,7 +133,7 @@ impl Actor for RootActor { from: "root".to_owned(), addons: vec![], }; - stream.write_json_packet(&actor); + let _ = stream.write_json_packet(&actor); ActorMessageStatus::Processed }, @@ -144,7 +146,7 @@ impl Actor for RootActor { isParent: true, }], }; - stream.write_json_packet(&reply); + let _ = stream.write_json_packet(&reply); ActorMessageStatus::Processed }, @@ -157,7 +159,7 @@ impl Actor for RootActor { isParent: true, }, }; - stream.write_json_packet(&reply); + let _ = stream.write_json_packet(&reply); ActorMessageStatus::Processed }, @@ -169,7 +171,7 @@ impl Actor for RootActor { deviceActor: self.device.clone(), preferenceActor: self.preference.clone(), }; - stream.write_json_packet(&actor); + let _ = stream.write_json_packet(&actor); ActorMessageStatus::Processed }, @@ -188,7 +190,7 @@ impl Actor for RootActor { }) .collect(), }; - stream.write_json_packet(&actor); + let _ = stream.write_json_packet(&actor); ActorMessageStatus::Processed }, @@ -197,7 +199,7 @@ impl Actor for RootActor { from: self.name(), registrations: vec![], }; - stream.write_json_packet(&reply); + let _ = stream.write_json_packet(&reply); ActorMessageStatus::Processed }, @@ -210,7 +212,7 @@ impl Actor for RootActor { .map(|name| registry.find::<WorkerActor>(name).encodable()) .collect(), }; - stream.write_json_packet(&reply); + let _ = stream.write_json_packet(&reply); ActorMessageStatus::Processed }, @@ -220,7 +222,7 @@ impl Actor for RootActor { from: self.name(), tab: tab.encodable(®istry), }; - stream.write_json_packet(&reply); + let _ = stream.write_json_packet(&reply); ActorMessageStatus::Processed }, @@ -232,7 +234,7 @@ impl Actor for RootActor { device: DeviceActor::description(), }, }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, diff --git a/components/devtools/actors/stylesheets.rs b/components/devtools/actors/stylesheets.rs index ccec3a7d30f..141a30ae106 100644 --- a/components/devtools/actors/stylesheets.rs +++ b/components/devtools/actors/stylesheets.rs @@ -4,6 +4,7 @@ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry}; use crate::protocol::JsonPacketStream; +use crate::StreamId; use serde_json::{Map, Value}; use std::net::TcpStream; @@ -27,6 +28,7 @@ impl Actor for StyleSheetsActor { msg_type: &str, _msg: &Map<String, Value>, stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(match msg_type { "getStyleSheets" => { @@ -34,7 +36,7 @@ impl Actor for StyleSheetsActor { from: self.name(), styleSheets: vec![], }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, diff --git a/components/devtools/actors/tab.rs b/components/devtools/actors/tab.rs index 1f83d246233..bd2ab331769 100644 --- a/components/devtools/actors/tab.rs +++ b/components/devtools/actors/tab.rs @@ -6,6 +6,7 @@ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry}; use crate::actors::browsing_context::{BrowsingContextActor, BrowsingContextActorMsg}; use crate::actors::root::RootActor; use crate::protocol::JsonPacketStream; +use crate::StreamId; use serde_json::{Map, Value}; use std::net::TcpStream; @@ -48,13 +49,14 @@ impl Actor for TabDescriptorActor { msg_type: &str, _msg: &Map<String, Value>, stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(match msg_type { "getTarget" => { let frame = registry .find::<BrowsingContextActor>(&self.browsing_context_actor) .encodable(); - stream.write_json_packet(&GetTargetReply { + let _ = stream.write_json_packet(&GetTargetReply { from: self.name(), frame, }); diff --git a/components/devtools/actors/thread.rs b/components/devtools/actors/thread.rs index f0e2f1e98a2..084a7bcf506 100644 --- a/components/devtools/actors/thread.rs +++ b/components/devtools/actors/thread.rs @@ -4,6 +4,7 @@ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry}; use crate::protocol::JsonPacketStream; +use crate::StreamId; use serde_json::{Map, Value}; use std::net::TcpStream; @@ -84,6 +85,7 @@ impl Actor for ThreadActor { msg_type: &str, _msg: &Map<String, Value>, stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(match msg_type { "attach" => { @@ -100,8 +102,8 @@ impl Actor for ThreadActor { type_: "attached".to_owned(), }, }; - stream.write_json_packet(&msg); - stream.write_json_packet(&VoidAttachedReply { from: self.name() }); + let _ = stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&VoidAttachedReply { from: self.name() }); ActorMessageStatus::Processed }, @@ -110,8 +112,8 @@ impl Actor for ThreadActor { from: self.name(), type_: "resumed".to_owned(), }; - stream.write_json_packet(&msg); - stream.write_json_packet(&VoidAttachedReply { from: self.name() }); + let _ = stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&VoidAttachedReply { from: self.name() }); ActorMessageStatus::Processed }, @@ -120,12 +122,12 @@ impl Actor for ThreadActor { from: self.name(), type_: "interrupted".to_owned(), }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, "reconfigure" => { - stream.write_json_packet(&ReconfigureReply { from: self.name() }); + let _ = stream.write_json_packet(&ReconfigureReply { from: self.name() }); ActorMessageStatus::Processed }, @@ -134,7 +136,7 @@ impl Actor for ThreadActor { from: self.name(), sources: vec![], }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, diff --git a/components/devtools/actors/timeline.rs b/components/devtools/actors/timeline.rs index 7ed53f9f8d4..b21990ae0b0 100644 --- a/components/devtools/actors/timeline.rs +++ b/components/devtools/actors/timeline.rs @@ -6,6 +6,7 @@ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry}; use crate::actors::framerate::FramerateActor; use crate::actors::memory::{MemoryActor, TimelineMemoryReply}; use crate::protocol::JsonPacketStream; +use crate::StreamId; use devtools_traits::DevtoolScriptControlMsg; use devtools_traits::DevtoolScriptControlMsg::{DropTimelineMarkers, SetTimelineMarkers}; use devtools_traits::{PreciseTime, TimelineMarker, TimelineMarkerType}; @@ -14,6 +15,7 @@ use msg::constellation_msg::PipelineId; use serde::{Serialize, Serializer}; use serde_json::{Map, Value}; use std::cell::RefCell; +use std::error::Error; use std::net::TcpStream; use std::sync::{Arc, Mutex}; use std::thread; @@ -166,7 +168,9 @@ impl TimelineActor { while let Ok(Some(marker)) = receiver.try_recv() { markers.push(emitter.marker(marker)); } - emitter.send(markers); + if emitter.send(markers).is_err() { + break; + } thread::sleep(Duration::from_millis(DEFAULT_TIMELINE_DATA_PULL_TIMEOUT)); }) @@ -185,6 +189,7 @@ impl Actor for TimelineActor { msg_type: &str, msg: &Map<String, Value>, stream: &mut TcpStream, + _id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(match msg_type { "start" => { @@ -199,6 +204,7 @@ impl Actor for TimelineActor { )) .unwrap(); + //TODO: support multiple connections by using root actor's streams instead. *self.stream.borrow_mut() = stream.try_clone().ok(); // init memory actor @@ -235,7 +241,7 @@ impl Actor for TimelineActor { from: self.name(), value: HighResolutionStamp::new(registry.start_stamp(), PreciseTime::now()), }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, @@ -245,7 +251,7 @@ impl Actor for TimelineActor { value: HighResolutionStamp::new(registry.start_stamp(), PreciseTime::now()), }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); self.script_sender .send(DropTimelineMarkers( self.pipeline, @@ -253,6 +259,7 @@ impl Actor for TimelineActor { )) .unwrap(); + //TODO: move this to the cleanup method. if let Some(ref actor_name) = *self.framerate_actor.borrow() { registry.drop_actor_later(actor_name.clone()); } @@ -272,7 +279,7 @@ impl Actor for TimelineActor { value: self.is_recording.lock().unwrap().clone(), }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, @@ -311,7 +318,7 @@ impl Emitter { } } - fn send(&mut self, markers: Vec<TimelineMarkerReply>) { + fn send(&mut self, markers: Vec<TimelineMarkerReply>) -> Result<(), Box<dyn Error>> { let end_time = PreciseTime::now(); let reply = MarkersEmitterReply { type_: "markers".to_owned(), @@ -319,7 +326,7 @@ impl Emitter { from: self.from.clone(), endTime: HighResolutionStamp::new(self.start_stamp, end_time), }; - self.stream.write_json_packet(&reply); + self.stream.write_json_packet(&reply)?; if let Some(ref actor_name) = self.framerate_actor { let mut lock = self.registry.lock(); @@ -331,7 +338,7 @@ impl Emitter { delta: HighResolutionStamp::new(self.start_stamp, end_time), timestamps: framerate_actor.take_pending_ticks(), }; - self.stream.write_json_packet(&framerateReply); + self.stream.write_json_packet(&framerateReply)?; } if let Some(ref actor_name) = self.memory_actor { @@ -343,7 +350,9 @@ impl Emitter { delta: HighResolutionStamp::new(self.start_stamp, end_time), measurement: memory_actor.measure(), }; - self.stream.write_json_packet(&memoryReply); + self.stream.write_json_packet(&memoryReply)?; } + + Ok(()) } } diff --git a/components/devtools/actors/worker.rs b/components/devtools/actors/worker.rs index fd578d0d3dc..cf7b26448fa 100644 --- a/components/devtools/actors/worker.rs +++ b/components/devtools/actors/worker.rs @@ -4,6 +4,7 @@ use crate::actor::{Actor, ActorMessageStatus, ActorRegistry}; use crate::protocol::JsonPacketStream; +use crate::StreamId; use devtools_traits::DevtoolScriptControlMsg::WantsLiveNotifications; use devtools_traits::{DevtoolScriptControlMsg, WorkerId}; use ipc_channel::ipc::IpcSender; @@ -11,6 +12,7 @@ use msg::constellation_msg::TEST_PIPELINE_ID; use serde_json::{Map, Value}; use servo_url::ServoUrl; use std::cell::RefCell; +use std::collections::HashMap; use std::net::TcpStream; #[derive(Clone, Copy)] @@ -21,7 +23,7 @@ pub enum WorkerType { Service = 2, } -pub struct WorkerActor { +pub(crate) struct WorkerActor { pub name: String, pub console: String, pub thread: String, @@ -29,7 +31,7 @@ pub struct WorkerActor { pub url: ServoUrl, pub type_: WorkerType, pub script_chan: IpcSender<DevtoolScriptControlMsg>, - pub streams: RefCell<Vec<TcpStream>>, + pub streams: RefCell<HashMap<StreamId, TcpStream>>, } impl WorkerActor { @@ -58,6 +60,7 @@ impl Actor for WorkerActor { msg_type: &str, _msg: &Map<String, Value>, stream: &mut TcpStream, + id: StreamId, ) -> Result<ActorMessageStatus, ()> { Ok(match msg_type { "attach" => { @@ -66,8 +69,12 @@ impl Actor for WorkerActor { 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); + if stream.write_json_packet(&msg).is_err() { + return Ok(ActorMessageStatus::Processed); + } + self.streams + .borrow_mut() + .insert(id, stream.try_clone().unwrap()); // FIXME: fix messages to not require forging a pipeline for worker messages self.script_chan .send(WantsLiveNotifications(TEST_PIPELINE_ID, true)) @@ -82,7 +89,7 @@ impl Actor for WorkerActor { threadActor: self.thread.clone(), consoleActor: self.console.clone(), }; - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); ActorMessageStatus::Processed }, @@ -91,18 +98,23 @@ impl Actor for WorkerActor { 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(); + let _ = stream.write_json_packet(&msg); + self.cleanup(id); ActorMessageStatus::Processed }, _ => ActorMessageStatus::Ignored, }) } + + fn cleanup(&self, id: StreamId) { + self.streams.borrow_mut().remove(&id); + if self.streams.borrow().is_empty() { + self.script_chan + .send(WantsLiveNotifications(TEST_PIPELINE_ID, false)) + .unwrap(); + } + } } #[derive(Serialize)] diff --git a/components/devtools/lib.rs b/components/devtools/lib.rs index 62238c656ee..28c6675da42 100644 --- a/components/devtools/lib.rs +++ b/components/devtools/lib.rs @@ -127,6 +127,9 @@ pub fn start_server(port: u16, embedder: EmbedderProxy) -> Sender<DevtoolsContro sender } +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub(crate) struct StreamId(u32); + fn run_server( sender: Sender<DevtoolsControlMsg>, receiver: Receiver<DevtoolsControlMsg>, @@ -188,22 +191,25 @@ fn run_server( 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) { + fn handle_client(actors: Arc<Mutex<ActorRegistry>>, mut stream: TcpStream, id: StreamId) { debug!("connection established to {}", stream.peer_addr().unwrap()); { let actors = actors.lock().unwrap(); let msg = actors.find::<RootActor>("root").encodable(); - stream.write_json_packet(&msg); + if let Err(e) = stream.write_json_packet(&msg) { + warn!("Error writing response: {:?}", e); + return; + } } 'outer: loop { match stream.read_json_packet() { Ok(Some(json_packet)) => { - if let Err(()) = actors - .lock() - .unwrap() - .handle_message(json_packet.as_object().unwrap(), &mut stream) - { + if let Err(()) = actors.lock().unwrap().handle_message( + json_packet.as_object().unwrap(), + &mut stream, + id, + ) { debug!("error: devtools actor stopped responding"); let _ = stream.shutdown(Shutdown::Both); break 'outer; @@ -219,6 +225,8 @@ fn run_server( }, } } + + actors.lock().unwrap().cleanup(id); } fn handle_framerate_tick(actors: Arc<Mutex<ActorRegistry>>, actor_name: String, tick: f64) { @@ -451,7 +459,7 @@ fn run_server( eventActor: actor.event_actor(), }; for stream in &mut connections { - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); } }, NetworkEvent::HttpResponse(httpresponse) => { @@ -464,7 +472,7 @@ fn run_server( updateType: "requestHeaders".to_owned(), }; for stream in &mut connections { - stream.write_merged_json_packet(&msg, &actor.request_headers()); + let _ = stream.write_merged_json_packet(&msg, &actor.request_headers()); } let msg = NetworkEventUpdateMsg { @@ -473,7 +481,7 @@ fn run_server( updateType: "requestCookies".to_owned(), }; for stream in &mut connections { - stream.write_merged_json_packet(&msg, &actor.request_cookies()); + let _ = stream.write_merged_json_packet(&msg, &actor.request_cookies()); } //Send a networkEventUpdate (responseStart) to the client @@ -485,7 +493,7 @@ fn run_server( }; for stream in &mut connections { - stream.write_json_packet(&msg); + let _ = stream.write_json_packet(&msg); } let msg = NetworkEventUpdateMsg { from: netevent_actor_name.clone(), @@ -496,7 +504,7 @@ fn run_server( totalTime: actor.total_time(), }; for stream in &mut connections { - stream.write_merged_json_packet(&msg, &extra); + let _ = stream.write_merged_json_packet(&msg, &extra); } let msg = NetworkEventUpdateMsg { @@ -508,7 +516,7 @@ fn run_server( state: "insecure".to_owned(), }; for stream in &mut connections { - stream.write_merged_json_packet(&msg, &extra); + let _ = stream.write_merged_json_packet(&msg, &extra); } let msg = NetworkEventUpdateMsg { @@ -517,7 +525,7 @@ fn run_server( updateType: "responseContent".to_owned(), }; for stream in &mut connections { - stream.write_merged_json_packet(&msg, &actor.response_content()); + let _ = stream.write_merged_json_packet(&msg, &actor.response_content()); } let msg = NetworkEventUpdateMsg { @@ -526,7 +534,7 @@ fn run_server( updateType: "responseCookies".to_owned(), }; for stream in &mut connections { - stream.write_merged_json_packet(&msg, &actor.response_cookies()); + let _ = stream.write_merged_json_packet(&msg, &actor.response_cookies()); } let msg = NetworkEventUpdateMsg { @@ -535,7 +543,7 @@ fn run_server( updateType: "responseHeaders".to_owned(), }; for stream in &mut connections { - stream.write_merged_json_packet(&msg, &actor.response_headers()); + let _ = stream.write_merged_json_packet(&msg, &actor.response_headers()); } }, } @@ -583,15 +591,18 @@ fn run_server( }) .expect("Thread spawning failed"); + let mut next_id = StreamId(0); while let Ok(msg) = receiver.recv() { debug!("{:?}", msg); match msg { DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::AddClient(stream)) => { let actors = actors.clone(); + let id = next_id; + next_id = StreamId(id.0 + 1); accepted_connections.push(stream.try_clone().unwrap()); thread::Builder::new() .name("DevtoolsClientHandler".to_owned()) - .spawn(move || handle_client(actors, stream.try_clone().unwrap())) + .spawn(move || handle_client(actors, stream.try_clone().unwrap(), id)) .expect("Thread spawning failed"); }, DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::FramerateTick( diff --git a/components/devtools/protocol.rs b/components/devtools/protocol.rs index 29fbaa2beeb..b01c982a762 100644 --- a/components/devtools/protocol.rs +++ b/components/devtools/protocol.rs @@ -8,6 +8,7 @@ use serde::Serialize; use serde_json::{self, Value}; +use std::error::Error; use std::io::{Read, Write}; use std::net::TcpStream; @@ -26,29 +27,38 @@ pub struct Method { } pub trait JsonPacketStream { - fn write_json_packet<T: Serialize>(&mut self, obj: &T); - fn write_merged_json_packet<T: Serialize, U: Serialize>(&mut self, base: &T, extra: &U); + fn write_json_packet<T: Serialize>(&mut self, obj: &T) -> Result<(), Box<dyn Error>>; + fn write_merged_json_packet<T: Serialize, U: Serialize>( + &mut self, + base: &T, + extra: &U, + ) -> Result<(), Box<dyn Error>>; fn read_json_packet(&mut self) -> Result<Option<Value>, String>; } impl JsonPacketStream for TcpStream { - fn write_json_packet<T: Serialize>(&mut self, obj: &T) { - let s = serde_json::to_string(obj).unwrap(); + fn write_json_packet<T: Serialize>(&mut self, obj: &T) -> Result<(), Box<dyn Error>> { + let s = serde_json::to_string(obj)?; debug!("<- {}", s); - write!(self, "{}:{}", s.len(), s).unwrap(); + write!(self, "{}:{}", s.len(), s)?; + Ok(()) } - fn write_merged_json_packet<T: Serialize, U: Serialize>(&mut self, base: &T, extra: &U) { - let mut obj = serde_json::to_value(base).unwrap(); + fn write_merged_json_packet<T: Serialize, U: Serialize>( + &mut self, + base: &T, + extra: &U, + ) -> Result<(), Box<dyn Error>> { + let mut obj = serde_json::to_value(base)?; let obj = obj.as_object_mut().unwrap(); - let extra = serde_json::to_value(extra).unwrap(); + let extra = serde_json::to_value(extra)?; let extra = extra.as_object().unwrap(); for (key, value) in extra { obj.insert(key.to_owned(), value.to_owned()); } - self.write_json_packet(obj); + self.write_json_packet(obj) } fn read_json_packet(&mut self) -> Result<Option<Value>, String> { @@ -74,7 +84,9 @@ impl JsonPacketStream for TcpStream { Err(_) => return Err("packet length missing / not parsable".to_owned()), }; let mut packet = String::new(); - self.take(packet_len).read_to_string(&mut packet).unwrap(); + self.take(packet_len) + .read_to_string(&mut packet) + .map_err(|e| e.to_string())?; debug!("{}", packet); return match serde_json::from_str(&packet) { Ok(json) => Ok(Some(json)), diff --git a/components/script/dom/mediasession.rs b/components/script/dom/mediasession.rs index f77efe3f54f..49112ba921b 100644 --- a/components/script/dom/mediasession.rs +++ b/components/script/dom/mediasession.rs @@ -20,7 +20,7 @@ use crate::dom::bindings::str::DOMString; use crate::dom::htmlmediaelement::HTMLMediaElement; use crate::dom::mediametadata::MediaMetadata; use crate::dom::window::Window; -use crate::realms::{AlreadyInRealm, InRealm}; +use crate::realms::{enter_realm, InRealm}; use dom_struct::dom_struct; use embedder_traits::MediaMetadata as EmbedderMediaMetadata; use embedder_traits::MediaSessionEvent; @@ -80,8 +80,8 @@ impl MediaSession { if let Some(media) = self.media_instance.get() { match action { MediaSessionActionType::Play => { - let in_realm_proof = AlreadyInRealm::assert(&self.global()); - media.Play(InRealm::Already(&in_realm_proof)); + let realm = enter_realm(self); + media.Play(InRealm::Entered(&realm)); }, MediaSessionActionType::Pause => { media.Pause(); diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 76ed789e8ad..a4d27057446 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -614,6 +614,7 @@ pub mod xrinputsourceschangeevent; pub mod xrjointpose; pub mod xrjointspace; pub mod xrlayer; +pub mod xrlayerevent; pub mod xrmediabinding; pub mod xrpose; pub mod xrprojectionlayer; diff --git a/components/script/dom/webglframebuffer.rs b/components/script/dom/webglframebuffer.rs index 9539ac90507..8172b1b6c4e 100644 --- a/components/script/dom/webglframebuffer.rs +++ b/components/script/dom/webglframebuffer.rs @@ -205,6 +205,9 @@ impl WebGLFramebuffer { } pub fn is_deleted(&self) -> bool { + // TODO: if a framebuffer has an attachment which is invalid due to + // being outside a webxr rAF, should this make the framebuffer invalid? + // https://github.com/immersive-web/layers/issues/196 self.is_deleted.get() } @@ -447,6 +450,9 @@ impl WebGLFramebuffer { } else { self.status.get() } + // TODO: if a framebuffer has an attachment which is invalid due to + // being outside a webxr rAF, should this make the framebuffer incomplete? + // https://github.com/immersive-web/layers/issues/196 } pub fn check_status_for_rendering(&self) -> CompleteForRendering { @@ -497,6 +503,10 @@ impl WebGLFramebuffer { self.is_initialized.set(true); } + // TODO: if a framebuffer has an attachment which is invalid due to + // being outside a webxr rAF, should this make the framebuffer incomplete? + // https://github.com/immersive-web/layers/issues/196 + CompleteForRendering::Complete } diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 168d31fdf5d..9ef96b1cd19 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -3563,7 +3563,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 fn IsTexture(&self, texture: Option<&WebGLTexture>) -> bool { texture.map_or(false, |tex| { - self.validate_ownership(tex).is_ok() && tex.target().is_some() && !tex.is_deleted() + self.validate_ownership(tex).is_ok() && tex.target().is_some() && !tex.is_invalid() }) } diff --git a/components/script/dom/webgltexture.rs b/components/script/dom/webgltexture.rs index 02cedeb5755..7456f772dec 100644 --- a/components/script/dom/webgltexture.rs +++ b/components/script/dom/webgltexture.rs @@ -9,11 +9,13 @@ use crate::dom::bindings::codegen::Bindings::EXTTextureFilterAnisotropicBinding: use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants as constants; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; +use crate::dom::bindings::root::Dom; use crate::dom::bindings::root::{DomRoot, MutNullableDom}; use crate::dom::webgl_validations::types::TexImageTarget; use crate::dom::webglframebuffer::WebGLFramebuffer; use crate::dom::webglobject::WebGLObject; use crate::dom::webglrenderingcontext::{Operation, WebGLRenderingContext}; +use crate::dom::xrsession::XRSession; use canvas_traits::webgl::{ webgl_channel, TexDataType, TexFormat, TexParameter, TexParameterBool, TexParameterInt, WebGLResult, WebGLTextureId, @@ -31,10 +33,11 @@ pub enum TexParameterValue { // Textures generated for WebXR are owned by the WebXR device, not by the WebGL thread // so the GL texture should not be deleted when the texture is garbage collected. -#[derive(Clone, Copy, Debug, Eq, JSTraceable, MallocSizeOf, PartialEq)] +#[unrooted_must_root_lint::must_root] +#[derive(JSTraceable, MallocSizeOf)] enum WebGLTextureOwner { WebGL, - WebXR, + WebXR(Dom<XRSession>), } const MAX_LEVEL_COUNT: usize = 31; @@ -71,14 +74,16 @@ impl WebGLTexture { fn new_inherited( context: &WebGLRenderingContext, id: WebGLTextureId, - owner: WebGLTextureOwner, + owner: Option<&XRSession>, ) -> Self { Self { webgl_object: WebGLObject::new_inherited(context), id: id, target: Cell::new(None), is_deleted: Cell::new(false), - owner: owner, + owner: owner + .map(|session| WebGLTextureOwner::WebXR(Dom::from_ref(session))) + .unwrap_or(WebGLTextureOwner::WebGL), immutable_levels: Cell::new(None), face_count: Cell::new(0), base_mipmap_level: 0, @@ -101,22 +106,18 @@ impl WebGLTexture { pub fn new(context: &WebGLRenderingContext, id: WebGLTextureId) -> DomRoot<Self> { reflect_dom_object( - Box::new(WebGLTexture::new_inherited( - context, - id, - WebGLTextureOwner::WebGL, - )), + Box::new(WebGLTexture::new_inherited(context, id, None)), &*context.global(), ) } - pub fn new_webxr(context: &WebGLRenderingContext, id: WebGLTextureId) -> DomRoot<Self> { + pub fn new_webxr( + context: &WebGLRenderingContext, + id: WebGLTextureId, + session: &XRSession, + ) -> DomRoot<Self> { reflect_dom_object( - Box::new(WebGLTexture::new_inherited( - context, - id, - WebGLTextureOwner::WebXR, - )), + Box::new(WebGLTexture::new_inherited(context, id, Some(session))), &*context.global(), ) } @@ -129,7 +130,7 @@ impl WebGLTexture { // NB: Only valid texture targets come here pub fn bind(&self, target: u32) -> WebGLResult<()> { - if self.is_deleted.get() { + if self.is_invalid() { return Err(WebGLError::InvalidOperation); } @@ -246,7 +247,7 @@ impl WebGLTexture { } // We don't delete textures owned by WebXR - if self.owner == WebGLTextureOwner::WebXR { + if let WebGLTextureOwner::WebXR(_) = self.owner { return; } @@ -258,7 +259,13 @@ impl WebGLTexture { } } - pub fn is_deleted(&self) -> bool { + pub fn is_invalid(&self) -> bool { + // https://immersive-web.github.io/layers/#xrwebglsubimagetype + if let WebGLTextureOwner::WebXR(ref session) = self.owner { + if session.is_outside_raf() { + return true; + } + } self.is_deleted.get() } diff --git a/components/script/dom/webidls/XRLayerEvent.webidl b/components/script/dom/webidls/XRLayerEvent.webidl index c90b9bfb27b..9a05272138e 100644 --- a/components/script/dom/webidls/XRLayerEvent.webidl +++ b/components/script/dom/webidls/XRLayerEvent.webidl @@ -3,12 +3,11 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ // https://immersive-web.github.io/layers/#xrlayerevent-interface - -// [SecureContext, Exposed=Window] -// interface XRLayerEvent : Event { -// constructor(DOMString type, XRLayerEventInit eventInitDict); -// [SameObject] readonly attribute XRLayer layer; -// }; +[SecureContext, Exposed=Window, Pref="dom.webxr.layers.enabled"] +interface XRLayerEvent : Event { + constructor(DOMString type, XRLayerEventInit eventInitDict); + [SameObject] readonly attribute XRLayer layer; +}; dictionary XRLayerEventInit : EventInit { required XRLayer layer; diff --git a/components/script/dom/xrlayerevent.rs b/components/script/dom/xrlayerevent.rs new file mode 100644 index 00000000000..d3485fa1c51 --- /dev/null +++ b/components/script/dom/xrlayerevent.rs @@ -0,0 +1,62 @@ +/* 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 https://mozilla.org/MPL/2.0/. */ + +use crate::dom::bindings::codegen::Bindings::EventBinding::EventBinding::EventMethods; +use crate::dom::bindings::codegen::Bindings::XRLayerEventBinding::XRLayerEventInit; +use crate::dom::bindings::codegen::Bindings::XRLayerEventBinding::XRLayerEventMethods; +use crate::dom::bindings::reflector::reflect_dom_object; +use crate::dom::bindings::root::Dom; +use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::str::DOMString; +use crate::dom::event::Event; +use crate::dom::window::Window; +use crate::dom::xrlayer::XRLayer; +use dom_struct::dom_struct; +use servo_atoms::Atom; + +// https://w3c.github.io/uievents/#interface-uievent +#[dom_struct] +pub struct XRLayerEvent { + event: Event, + layer: Dom<XRLayer>, +} + +impl XRLayerEvent { + pub fn new_inherited(layer: &XRLayer) -> XRLayerEvent { + XRLayerEvent { + event: Event::new_inherited(), + layer: Dom::from_ref(layer), + } + } + + pub fn new(window: &Window, layer: &XRLayer) -> DomRoot<XRLayerEvent> { + reflect_dom_object(Box::new(XRLayerEvent::new_inherited(layer)), window) + } + + #[allow(non_snake_case)] + pub fn Constructor( + window: &Window, + type_: DOMString, + init: &XRLayerEventInit, + ) -> DomRoot<XRLayerEvent> { + let event = XRLayerEvent::new(window, &init.layer); + let type_ = Atom::from(type_); + let bubbles = init.parent.bubbles; + let cancelable = init.parent.cancelable; + event.event.init_event(type_, bubbles, cancelable); + event + } +} + +impl XRLayerEventMethods for XRLayerEvent { + // https://immersive-web.github.io/layers/#dom-xrlayerevent-layer + fn Layer(&self) -> DomRoot<XRLayer> { + DomRoot::from_ref(&self.layer) + } + + // https://dom.spec.whatwg.org/#dom-event-istrusted + fn IsTrusted(&self) -> bool { + self.event.IsTrusted() + } +} diff --git a/components/script/dom/xrwebgllayer.rs b/components/script/dom/xrwebgllayer.rs index 7f0a7883961..dd1e4eff57f 100644 --- a/components/script/dom/xrwebgllayer.rs +++ b/components/script/dom/xrwebgllayer.rs @@ -193,10 +193,11 @@ impl XRWebGLLayer { let framebuffer = self.framebuffer.as_ref()?; let context = framebuffer.upcast::<WebGLObject>().context(); let sub_images = frame.get_sub_images(self.layer_id()?)?; + let session = self.session(); // TODO: Cache this texture let color_texture_id = WebGLTextureId::maybe_new(sub_images.sub_image.as_ref()?.color_texture)?; - let color_texture = WebGLTexture::new_webxr(context, color_texture_id); + let color_texture = WebGLTexture::new_webxr(context, color_texture_id, session); let target = self.texture_target(); // Save the current bindings @@ -230,7 +231,8 @@ impl XRWebGLLayer { if let Some(id) = sub_images.sub_image.as_ref()?.depth_stencil_texture { // TODO: Cache this texture let depth_stencil_texture_id = WebGLTextureId::maybe_new(id)?; - let depth_stencil_texture = WebGLTexture::new_webxr(context, depth_stencil_texture_id); + let depth_stencil_texture = + WebGLTexture::new_webxr(context, depth_stencil_texture_id, session); framebuffer .texture2d_even_if_opaque( constants::DEPTH_STENCIL_ATTACHMENT, diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 2bcc5694074..09e6a3ef078 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -144,9 +144,8 @@ mod media_platform { #[cfg(feature = "uwp")] fn set_gstreamer_log_handler() { - use gstreamer::{debug_add_log_function, debug_remove_default_log_function, DebugLevel}; + use gstreamer::{debug_add_log_function, DebugLevel}; - debug_remove_default_log_function(); debug_add_log_function(|cat, level, file, function, line, _, message| { let message = format!( "{:?} {:?} {:?}:{:?}:{:?} {:?}", diff --git a/components/webrender_surfman/Cargo.toml b/components/webrender_surfman/Cargo.toml index 82ae827cbb7..663b30be7b1 100644 --- a/components/webrender_surfman/Cargo.toml +++ b/components/webrender_surfman/Cargo.toml @@ -13,5 +13,5 @@ path = "lib.rs" [dependencies] euclid = "0.20" surfman = "0.3" -surfman-chains = "0.4" +surfman-chains = "0.5" diff --git a/components/webrender_surfman/lib.rs b/components/webrender_surfman/lib.rs index 530ca0ebfc7..533614256c1 100644 --- a/components/webrender_surfman/lib.rs +++ b/components/webrender_surfman/lib.rs @@ -147,7 +147,7 @@ impl WebrenderSurfman { let ref mut device = self.0.device.borrow_mut(); let ref mut context = self.0.context.borrow_mut(); if let Some(ref swap_chain) = self.0.swap_chain { - return swap_chain.swap_buffers(device, context); + return swap_chain.swap_buffers(device, context, surfman_chains::PreserveBuffer::No); } let mut surface = device.unbind_surface_from_context(context)?.unwrap(); device.present_surface(context, &mut surface)?; |