diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 81587cf0c1b..2b0462c8017 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -35,7 +35,7 @@ use net_traits::bluetooth_thread::BluetoothMethodMsg; use net_traits::filemanager_thread::FileManagerThreadMsg; use net_traits::image_cache_thread::ImageCacheThread; use net_traits::storage_thread::StorageThreadMsg; -use net_traits::{self, ResourceThreads, IpcSend, CustomResponseMediator, CoreResourceMsg}; +use net_traits::{self, ResourceThreads, IpcSend}; use offscreen_gl_context::{GLContextAttributes, GLLimits}; use pipeline::{ChildProcess, InitialPipelineState, Pipeline}; use profile_traits::mem; @@ -98,9 +98,6 @@ pub struct Constellation { /// Receives messages from scripts. script_receiver: Receiver, - /// Receive messages from resource thread - resource_receiver: Receiver, - /// Receives messages from the compositor compositor_receiver: Receiver, @@ -440,13 +437,6 @@ impl Constellation let (ipc_panic_sender, ipc_panic_receiver) = ipc::channel().expect("ipc channel failure"); let panic_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_panic_receiver); - let (resource_ipc_sender, resource_ipc_receiver) = ipc::channel().expect("ipc channel failure"); - let resource_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(resource_ipc_receiver); - - state.public_resource_threads.sender() - .send(CoreResourceMsg::NetworkMediator(resource_ipc_sender)) - .expect("network sender sending failure"); - let swmanager_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(swmanager_receiver); let mut constellation: Constellation = Constellation { @@ -467,7 +457,6 @@ impl Constellation swmanager_chan: None, swmanager_receiver: swmanager_receiver, swmanager_sender: sw_mgr_clone, - resource_receiver: resource_receiver, pipelines: HashMap::new(), frames: HashMap::new(), subpage_map: HashMap::new(), @@ -638,8 +627,7 @@ impl Constellation Compositor(FromCompositorMsg), Layout(FromLayoutMsg), Panic(PanicMsg), - FromSWManager(SWManagerMsg), - FromResource(CustomResponseMediator), + FromSWManager(SWManagerMsg) } // Get one incoming request. @@ -659,7 +647,6 @@ impl Constellation let receiver_from_layout = &self.layout_receiver; let receiver_from_panic = &self.panic_receiver; let receiver_from_swmanager = &self.swmanager_receiver; - let receiver_from_resource = &self.resource_receiver; select! { msg = receiver_from_script.recv() => Request::Script(msg.expect("Unexpected script channel panic in constellation")), @@ -670,9 +657,7 @@ impl Constellation msg = receiver_from_panic.recv() => Request::Panic(msg.expect("Unexpected panic channel panic in constellation")), msg = receiver_from_swmanager.recv() => - Request::FromSWManager(msg.expect("Unexpected panic channel panic in constellation")), - msg = receiver_from_resource.recv() => - Request::FromResource(msg.expect("Unexpected panic channel panic in constellation")) + Request::FromSWManager(msg.expect("Unexpected panic channel panic in constellation")) } }; @@ -692,9 +677,6 @@ impl Constellation Request::FromSWManager(message) => { self.handle_request_from_swmanager(message); } - Request::FromResource(message) => { - self.handle_request_from_resource(message); - } } } @@ -707,14 +689,6 @@ impl Constellation } } - fn handle_request_from_resource(&self, mediator: CustomResponseMediator) { - if let Some(ref mgr) = self.swmanager_chan { - let _ = mgr.send(ServiceWorkerMsg::ActivateWorker(mediator)); - } else { - warn!("activation request to service worker manager failed"); - } - } - fn handle_request_from_compositor(&mut self, message: FromCompositorMsg) { match message { FromCompositorMsg::Exit => { @@ -985,10 +959,6 @@ impl Constellation FromScriptMsg::GetScrollOffset(pid, lid, send) => { self.compositor_proxy.send(ToCompositorMsg::GetScrollOffset(pid, lid, send)); } - FromScriptMsg::NetworkRequest(mediator) => { - debug!("activation request for service worker received"); - self.handle_activate_worker(mediator); - } FromScriptMsg::RegisterServiceWorker(scope_things, scope) => { debug!("constellation got store registration scope message"); self.handle_register_serviceworker(scope_things, scope); @@ -1028,14 +998,6 @@ impl Constellation } } - fn handle_activate_worker(&self, mediator: CustomResponseMediator) { - if let Some(ref mgr) = self.swmanager_chan { - let _ = mgr.send(ServiceWorkerMsg::ActivateWorker(mediator)); - } else { - warn!("activation request to service worker manager failed"); - } - } - fn handle_exit(&mut self) { // TODO: add a timer, which forces shutdown if threads aren't responsive. if self.shutting_down { return; } diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs index 240ee99e4f7..5b0bed160c0 100644 --- a/components/constellation/pipeline.rs +++ b/components/constellation/pipeline.rs @@ -19,13 +19,13 @@ use layers::geometry::DevicePixel; use layout_traits::LayoutThreadFactory; use msg::constellation_msg::{FrameId, FrameType, LoadData, PanicMsg, PipelineId}; use msg::constellation_msg::{PipelineNamespaceId, SubpageId}; -use net_traits::ResourceThreads; use net_traits::bluetooth_thread::BluetoothMethodMsg; use net_traits::image_cache_thread::ImageCacheThread; +use net_traits::{ResourceThreads, IpcSend}; use profile_traits::mem as profile_mem; use profile_traits::time; use script_traits::{ConstellationControlMsg, InitialScriptState, MozBrowserEvent}; -use script_traits::{LayoutControlMsg, LayoutMsg, NewLayoutInfo, ScriptMsg, SWManagerMsg}; +use script_traits::{LayoutControlMsg, LayoutMsg, NewLayoutInfo, ScriptMsg, SWManagerMsg, SWManagerSenders}; use script_traits::{ScriptThreadFactory, TimerEventRequest, WindowSizeData}; use std::collections::HashMap; use std::io::Error as IOError; @@ -551,7 +551,10 @@ impl UnprivilegedPipelineContent { self.prefs.clone() } - pub fn swmanager_chan(&self) -> IpcSender { - self.swmanager_thread.clone() + pub fn swmanager_senders(&self) -> SWManagerSenders { + SWManagerSenders { + swmanager_sender: self.swmanager_thread.clone(), + resource_sender: self.resource_threads.sender() + } } } diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index d8344e12502..80a7b91e335 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -59,7 +59,7 @@ pub fn factory(user_agent: String, http_state: HttpState, devtools_chan: Option>, profiler_chan: ProfilerChan, - constellation_chan: Option>, + swmanager_chan: Option>, connector: Arc>) -> Box>, http_state: HttpState, devtools_chan: Option>, - constellation_chan: Option>, + swmanager_chan: Option>, cancel_listener: CancellationListener, user_agent: String) { let factory = NetworkHttpRequestFactory { @@ -143,7 +143,7 @@ fn load_for_consumer(load_data: LoadData, let ui_provider = TFDProvider; match load(&load_data, &ui_provider, &http_state, devtools_chan, &factory, - user_agent, &cancel_listener, constellation_chan) { + user_agent, &cancel_listener, swmanager_chan) { Err(error) => { match error.error { LoadErrorType::ConnectionAborted { .. } => unreachable!(), @@ -864,7 +864,7 @@ pub fn load(load_data: &LoadData, request_factory: &HttpRequestFactory, user_agent: String, cancel_listener: &CancellationListener, - constellation_chan: Option>) + swmanager_chan: Option>) -> Result where A: HttpRequest + 'static, B: UIProvider { let max_redirects = PREFS.get("network.http.redirection-limit").as_i64().unwrap() as u32; let mut iters = 0; @@ -886,9 +886,9 @@ pub fn load(load_data: &LoadData, response_chan: msg_sender, load_url: doc_url.clone() }; - if let Some(sender) = constellation_chan { + if let Some(sender) = swmanager_chan { let _ = sender.send(response_mediator); - if let Ok(Some(custom_response)) = msg_receiver.try_recv() { + if let Ok(Some(custom_response)) = msg_receiver.recv() { let metadata = Metadata::default(doc_url.clone()); let readable_response = to_readable_response(custom_response); return StreamedResponse::from_http_response(box readable_response, metadata); diff --git a/components/net/resource_thread.rs b/components/net/resource_thread.rs index 64f96876ea7..9ee16b911ad 100644 --- a/components/net/resource_thread.rs +++ b/components/net/resource_thread.rs @@ -280,7 +280,7 @@ impl ResourceChannelManager { consumer.send(cookie_jar.cookies_for_url(&url, source)).unwrap(); } CoreResourceMsg::NetworkMediator(mediator_chan) => { - self.resource_manager.constellation_chan = Some(mediator_chan) + self.resource_manager.swmanager_chan = Some(mediator_chan) } CoreResourceMsg::GetCookiesDataForUrl(url, consumer, source) => { let mut cookie_jar = group.cookie_jar.write().unwrap(); @@ -459,7 +459,7 @@ pub struct CoreResourceManager { user_agent: String, mime_classifier: Arc, devtools_chan: Option>, - constellation_chan: Option>, + swmanager_chan: Option>, profiler_chan: ProfilerChan, filemanager_chan: IpcSender, cancel_load_map: HashMap>, @@ -475,7 +475,7 @@ impl CoreResourceManager { user_agent: user_agent, mime_classifier: Arc::new(MimeClassifier::new()), devtools_chan: devtools_channel, - constellation_chan: None, + swmanager_chan: None, profiler_chan: profiler_chan, filemanager_chan: filemanager_chan, cancel_load_map: HashMap::new(), @@ -547,7 +547,7 @@ impl CoreResourceManager { http_state, self.devtools_chan.clone(), self.profiler_chan.clone(), - self.constellation_chan.clone(), + self.swmanager_chan.clone(), resource_grp.connector.clone()) }, "data" => from_factory(data_loader::factory), diff --git a/components/script/lib.rs b/components/script/lib.rs index 604e3770176..78a84f83586 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -114,9 +114,8 @@ mod unpremultiplytable; mod webdriver_handlers; use dom::bindings::codegen::RegisterBindings; -use ipc_channel::ipc::IpcSender; use js::jsapi::{Handle, JSContext, JSObject, SetDOMProxyInformation}; -use script_traits::SWManagerMsg; +use script_traits::SWManagerSenders; use serviceworker_manager::ServiceWorkerManager; use std::ptr; use util::opts; @@ -163,13 +162,13 @@ fn perform_platform_specific_initialization() { fn perform_platform_specific_initialization() {} #[allow(unsafe_code)] -pub fn init(from_swmanager_sender: IpcSender) { +pub fn init(sw_senders: SWManagerSenders) { unsafe { SetDOMProxyInformation(ptr::null(), 0, Some(script_thread::shadow_check_callback)); } // Spawn the service worker manager passing the constellation sender - ServiceWorkerManager::spawn_manager(from_swmanager_sender); + ServiceWorkerManager::spawn_manager(sw_senders); // Create the global vtables used by the (generated) DOM // bindings to implement JS proxies. diff --git a/components/script/serviceworker_manager.rs b/components/script/serviceworker_manager.rs index d394a9908ee..3d1476a4509 100644 --- a/components/script/serviceworker_manager.rs +++ b/components/script/serviceworker_manager.rs @@ -10,10 +10,12 @@ use devtools_traits::{DevtoolsPageInfo, ScriptToDevtoolsControlMsg}; use dom::serviceworkerglobalscope::ServiceWorkerGlobalScope; use dom::serviceworkerregistration::longest_prefix_match; -use ipc_channel::ipc::{self, IpcSender, IpcReceiver}; -use script_traits::{ServiceWorkerMsg, ScopeThings, SWManagerMsg}; +use ipc_channel::ipc::{self, IpcSender}; +use ipc_channel::router::ROUTER; +use net_traits::{CustomResponseMediator, CoreResourceMsg}; +use script_traits::{ServiceWorkerMsg, ScopeThings, SWManagerMsg, SWManagerSenders}; use std::collections::HashMap; -use std::sync::mpsc::channel; +use std::sync::mpsc::{channel, Receiver}; use url::Url; use util::thread::spawn_named; @@ -25,25 +27,33 @@ pub struct ServiceWorkerManager { // own sender to send messages here own_sender: IpcSender, // receiver to receive messages from constellation - own_port: IpcReceiver, + own_port: Receiver, + // to receive resource messages + resource_receiver: Receiver } impl ServiceWorkerManager { fn new(own_sender: IpcSender, - from_constellation_receiver: IpcReceiver) -> ServiceWorkerManager { + from_constellation_receiver: Receiver, + resource_port: Receiver) -> ServiceWorkerManager { ServiceWorkerManager { registered_workers: HashMap::new(), active_workers: HashMap::new(), own_sender: own_sender, - own_port: from_constellation_receiver + own_port: from_constellation_receiver, + resource_receiver: resource_port } } - pub fn spawn_manager(from_swmanager_sender: IpcSender) { + pub fn spawn_manager(sw_senders: SWManagerSenders) { let (own_sender, from_constellation_receiver) = ipc::channel().unwrap(); - from_swmanager_sender.send(SWManagerMsg::OwnSender(own_sender.clone())).unwrap(); + let (resource_chan, resource_port) = ipc::channel().unwrap(); + let from_constellation = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(from_constellation_receiver); + let resource_port = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(resource_port); + let _ = sw_senders.resource_sender.send(CoreResourceMsg::NetworkMediator(resource_chan)); + let _ = sw_senders.swmanager_sender.send(SWManagerMsg::OwnSender(own_sender.clone())); spawn_named("ServiceWorkerManager".to_owned(), move || { - ServiceWorkerManager::new(own_sender, from_constellation_receiver).start(); + ServiceWorkerManager::new(own_sender, from_constellation, resource_port).handle_message(); }); } @@ -83,7 +93,7 @@ impl ServiceWorkerManager { devtools_receiver, self.own_sender.clone(), scope_url.clone()); - // store the worker in active_workers map + // We store the activated worker self.active_workers.insert(scope_url.clone(), scope_things.clone()); } else { warn!("Unable to activate service worker"); @@ -91,33 +101,63 @@ impl ServiceWorkerManager { } } - fn start(&mut self) { - while let Ok(msg) = self.own_port.recv() { - match msg { - ServiceWorkerMsg::RegisterServiceWorker(scope_things, scope) => { - if self.registered_workers.contains_key(&scope) { - warn!("ScopeThings for {:?} already stored in SW-Manager", scope); - } else { - self.registered_workers.insert(scope, scope_things); - } - } - ServiceWorkerMsg::Timeout(scope) => { - if self.active_workers.contains_key(&scope) { - let _ = self.active_workers.remove(&scope); - } else { - warn!("ScopeThings for {:?} is not active", scope); - } - } - ServiceWorkerMsg::ActivateWorker(mediator) => { - self.prepare_activation(&mediator.load_url); - // TODO XXXcreativcoder this net_sender will need to be send to the appropriate service worker - // so that it may do the sending of custom responses. - // For now we just send a None from here itself - let _ = mediator.response_chan.send(None); + fn handle_message(&mut self) { + while self.receive_message() { + // process message + } + } + fn handle_message_from_constellation(&mut self, msg: ServiceWorkerMsg) -> bool { + match msg { + ServiceWorkerMsg::RegisterServiceWorker(scope_things, scope) => { + if self.registered_workers.contains_key(&scope) { + warn!("ScopeThings for {:?} already stored in SW-Manager", scope); + } else { + self.registered_workers.insert(scope, scope_things); } - ServiceWorkerMsg::Exit => break + true } + ServiceWorkerMsg::Timeout(scope) => { + if self.active_workers.contains_key(&scope) { + let _ = self.active_workers.remove(&scope); + } else { + warn!("ScopeThings for {:?} is not active", scope); + } + true + } + ServiceWorkerMsg::Exit => false + } + } + + #[inline] + fn handle_message_from_resource(&mut self, mediator: CustomResponseMediator) -> bool { + self.prepare_activation(&mediator.load_url); + // TODO XXXcreativcoder This mediator will need to be send to the appropriate service worker + // so that it may do the sending of custom responses. + // For now we just send a None from here itself + let _ = mediator.response_chan.send(None); + true + } + + #[allow(unsafe_code)] + fn receive_message(&mut self) -> bool { + enum Message { + FromResource(CustomResponseMediator), + FromConstellation(ServiceWorkerMsg) + } + let message = { + let msg_from_constellation = &self.own_port; + let msg_from_resource = &self.resource_receiver; + select! { + msg = msg_from_constellation.recv() => + Message::FromConstellation(msg.expect("Unexpected constellation channel panic in sw-manager")), + msg = msg_from_resource.recv() => + Message::FromResource(msg.expect("Unexpected resource channel panic in sw-manager")) + } + }; + match message { + Message::FromConstellation(msg) => self.handle_message_from_constellation(msg), + Message::FromResource(mediator) => self.handle_message_from_resource(mediator) } } } diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index af3844f84ba..cf50e87bb4e 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -68,7 +68,7 @@ use util::ipc::OptionalOpaqueIpcSender; use webdriver_msg::{LoadStatus, WebDriverScriptCommand}; pub use script_msg::{LayoutMsg, ScriptMsg, EventResult, LogEntry}; -pub use script_msg::{ServiceWorkerMsg, ScopeThings, SWManagerMsg}; +pub use script_msg::{ServiceWorkerMsg, ScopeThings, SWManagerMsg, SWManagerSenders}; /// The address of a node. Layout sends these back. They must be validated via /// `from_untrusted_node_address` before they can be used, because we do not trust layout. diff --git a/components/script_traits/script_msg.rs b/components/script_traits/script_msg.rs index 959050ee2ea..ca6b6328793 100644 --- a/components/script_traits/script_msg.rs +++ b/components/script_traits/script_msg.rs @@ -18,7 +18,7 @@ use gfx_traits::LayerId; use ipc_channel::ipc::IpcSender; use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData}; use msg::constellation_msg::{NavigationDirection, PipelineId, SubpageId}; -use net_traits::CustomResponseMediator; +use net_traits::CoreResourceMsg; use offscreen_gl_context::{GLContextAttributes, GLLimits}; use style_traits::cursor::Cursor; use style_traits::viewport::ViewportConstraints; @@ -110,8 +110,6 @@ pub enum ScriptMsg { ActivateDocument(PipelineId), /// Set the document state for a pipeline (used by screenshot / reftests) SetDocumentState(PipelineId, DocumentState), - /// Message from network to constellation - NetworkRequest(CustomResponseMediator), /// Update the pipeline Url, which can change after redirections. SetFinalUrl(PipelineId, Url), /// Check if an alert dialog box should be presented @@ -160,20 +158,26 @@ pub struct ScopeThings { pub worker_id: WorkerId, } +/// Channels to allow service worker manager to communicate with constellation and resource thread +pub struct SWManagerSenders { + /// sender for communicating with constellation + pub swmanager_sender: IpcSender, + /// sender for communicating with resource thread + pub resource_sender: IpcSender +} + /// Messages sent to Service Worker Manager thread #[derive(Deserialize, Serialize)] pub enum ServiceWorkerMsg { /// Message to register the service worker RegisterServiceWorker(ScopeThings, Url), - /// Message to activate the worker - ActivateWorker(CustomResponseMediator), /// Timeout message sent by active service workers Timeout(Url), /// Exit the service worker manager Exit, } -/// Messages outgoing from the Service Worker Manager thread +/// Messages outgoing from the Service Worker Manager thread to constellation #[derive(Deserialize, Serialize)] pub enum SWManagerMsg { /// Provide the constellation with a means of communicating with the Service Worker Manager diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 0b8f5756a36..e31f25644a2 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -83,7 +83,7 @@ use profile::mem as profile_mem; use profile::time as profile_time; use profile_traits::mem; use profile_traits::time; -use script_traits::{ConstellationMsg, ScriptMsg, SWManagerMsg}; +use script_traits::{ConstellationMsg, ScriptMsg, SWManagerSenders}; use std::cmp::max; use std::rc::Rc; use std::sync::mpsc::Sender; @@ -159,7 +159,7 @@ impl Browser where Window: WindowMethods + 'static { // Create the constellation, which maintains the engine // pipelines, including the script and layout threads, as well // as the navigation context. - let (constellation_chan, swmanager_sender) = create_constellation(opts.clone(), + let (constellation_chan, sw_senders) = create_constellation(opts.clone(), compositor_proxy.clone_compositor_proxy(), time_profiler_chan.clone(), mem_profiler_chan.clone(), @@ -168,7 +168,7 @@ impl Browser where Window: WindowMethods + 'static { webrender_api_sender.clone()); // Send the constellation's swmanager sender to service worker manager thread - script::init(swmanager_sender); + script::init(sw_senders); if cfg!(feature = "webdriver") { if let Some(port) = opts.webdriver_port { @@ -230,7 +230,7 @@ fn create_constellation(opts: opts::Opts, devtools_chan: Option>, supports_clipboard: bool, webrender_api_sender: Option) - -> (Sender, IpcSender) { + -> (Sender, SWManagerSenders) { let bluetooth_thread: IpcSender = BluetoothThreadFactory::new(); let (public_resource_threads, private_resource_threads) = @@ -242,6 +242,8 @@ fn create_constellation(opts: opts::Opts, let font_cache_thread = FontCacheThread::new(public_resource_threads.sender(), webrender_api_sender.as_ref().map(|wr| wr.create_api())); + let resource_sender = public_resource_threads.sender(); + let initial_state = InitialConstellationState { compositor_proxy: compositor_proxy, devtools_chan: devtools_chan, @@ -264,7 +266,13 @@ fn create_constellation(opts: opts::Opts, constellation_chan.send(ConstellationMsg::InitLoadUrl(url)).unwrap(); }; - (constellation_chan, from_swmanager_sender) + // channels to communicate with Service Worker Manager + let sw_senders = SWManagerSenders { + swmanager_sender: from_swmanager_sender, + resource_sender: resource_sender + }; + + (constellation_chan, sw_senders) } // A logger that logs to two downstream loggers. @@ -311,9 +319,9 @@ pub fn run_content_process(token: String) { create_sandbox(); } - // Send the constellation sender to service worker manager thread - let from_swmanager_sender = unprivileged_content.swmanager_chan(); - script::init(from_swmanager_sender); + // send the required channels to the service worker manager + let sw_senders = unprivileged_content.swmanager_senders(); + script::init(sw_senders); unprivileged_content.start_all::