aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/constellation/constellation.rs6
-rw-r--r--components/script/dom/bindings/structuredclone.rs16
-rw-r--r--components/script/dom/serviceworker.rs33
-rw-r--r--components/script/dom/serviceworkerglobalscope.rs84
-rw-r--r--components/script/dom/serviceworkerregistration.rs7
-rw-r--r--components/script/dom/webidls/ServiceWorker.webidl2
-rw-r--r--components/script/dom/workerglobalscope.rs6
-rw-r--r--components/script/script_thread.rs17
-rw-r--r--components/script/serviceworker_manager.rs34
-rw-r--r--components/script_traits/lib.rs5
-rw-r--r--components/script_traits/script_msg.rs7
-rw-r--r--tests/html/service-worker/iframe_sw.js6
-rw-r--r--tests/html/service-worker/index.html7
13 files changed, 184 insertions, 46 deletions
diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs
index db54290bf83..5c9b52b7f72 100644
--- a/components/constellation/constellation.rs
+++ b/components/constellation/constellation.rs
@@ -738,6 +738,12 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// store service worker manager for communicating with it.
self.swmanager_chan = Some(sw_sender);
}
+ SWManagerMsg::ConnectServiceWorker(scope_url, pipeline_id, msg_chan) => {
+ if let Some(ref parent_info) = self.pipelines.get(&pipeline_id) {
+ let from_cons_msg = ConstellationControlMsg::ConnectServiceWorker(scope_url, msg_chan);
+ let _ = parent_info.script_chan.send(from_cons_msg);
+ }
+ }
}
}
diff --git a/components/script/dom/bindings/structuredclone.rs b/components/script/dom/bindings/structuredclone.rs
index f9c4e98f2f9..cb0fbce3092 100644
--- a/components/script/dom/bindings/structuredclone.rs
+++ b/components/script/dom/bindings/structuredclone.rs
@@ -12,6 +12,7 @@ use js::jsapi::{JSContext, JS_ReadStructuredClone, JS_STRUCTURED_CLONE_VERSION};
use js::jsapi::{JS_ClearPendingException, JS_WriteStructuredClone};
use libc::size_t;
use std::ptr;
+use std::slice;
/// A buffer for a structured clone.
pub struct StructuredCloneData {
@@ -45,6 +46,21 @@ impl StructuredCloneData {
})
}
+ /// Converts a StructuredCloneData to Vec<u64>
+ pub fn move_to_arraybuffer(self) -> Vec<u64> {
+ unsafe {
+ slice::from_raw_parts(self.data, self.nbytes).to_vec()
+ }
+ }
+
+ /// Converts back to StructuredCloneData using a pointer and no of bytes
+ pub fn make_structured_clone(data: *mut u64, nbytes: size_t) -> StructuredCloneData {
+ StructuredCloneData {
+ data: data,
+ nbytes: nbytes
+ }
+ }
+
/// Reads a structured clone.
///
/// Panics if `JS_ReadStructuredClone` fails.
diff --git a/components/script/dom/serviceworker.rs b/components/script/dom/serviceworker.rs
index 2b79be43dc8..5ae9025c7f1 100644
--- a/components/script/dom/serviceworker.rs
+++ b/components/script/dom/serviceworker.rs
@@ -2,20 +2,24 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-use dom::abstractworker::{SimpleWorkerErrorHandler, WorkerScriptMsg};
+use dom::abstractworker::SimpleWorkerErrorHandler;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::ServiceWorkerBinding::{ServiceWorkerMethods, ServiceWorkerState, Wrap};
+use dom::bindings::error::ErrorResult;
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::USVString;
+use dom::bindings::structuredclone::StructuredCloneData;
use dom::eventtarget::EventTarget;
+use ipc_channel::ipc::IpcSender;
+use js::jsapi::{HandleValue, JSContext};
use script_thread::Runnable;
+use script_traits::DOMMessage;
use std::cell::Cell;
-use std::sync::mpsc::Sender;
use url::Url;
pub type TrustedServiceWorkerAddress = Trusted<ServiceWorker>;
@@ -26,7 +30,7 @@ pub struct ServiceWorker {
script_url: DOMRefCell<String>,
state: Cell<ServiceWorkerState>,
#[ignore_heap_size_of = "Defined in std"]
- sender: Option<Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>>,
+ msg_sender: DOMRefCell<Option<IpcSender<DOMMessage>>>,
skip_waiting: Cell<bool>
}
@@ -35,10 +39,10 @@ impl ServiceWorker {
skip_waiting: bool) -> ServiceWorker {
ServiceWorker {
eventtarget: EventTarget::new_inherited(),
- sender: None,
script_url: DOMRefCell::new(String::from(script_url)),
state: Cell::new(ServiceWorkerState::Installing),
- skip_waiting: Cell::new(skip_waiting)
+ skip_waiting: Cell::new(skip_waiting),
+ msg_sender: DOMRefCell::new(None)
}
}
@@ -69,6 +73,13 @@ impl ServiceWorker {
script_url.as_str(),
skip_waiting)
}
+
+ pub fn store_sender(trusted_worker: TrustedServiceWorkerAddress, sender: IpcSender<DOMMessage>) {
+ let worker = trusted_worker.root();
+ // This channel is used for sending message from the ServiceWorker object to its
+ // corresponding ServiceWorkerGlobalScope
+ *worker.msg_sender.borrow_mut() = Some(sender);
+ }
}
impl ServiceWorkerMethods for ServiceWorker {
@@ -82,6 +93,18 @@ impl ServiceWorkerMethods for ServiceWorker {
USVString(self.script_url.borrow().clone())
}
+ // https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-postmessage
+ fn PostMessage(&self, cx: *mut JSContext, message: HandleValue) -> ErrorResult {
+ let data = try!(StructuredCloneData::write(cx, message));
+ let msg_vec = DOMMessage(data.move_to_arraybuffer());
+ if let Some(ref sender) = *self.msg_sender.borrow() {
+ let _ = sender.send(msg_vec);
+ } else {
+ warn!("Could not communicate message to ServiceWorkerGlobalScope");
+ }
+ Ok(())
+ }
+
// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-container-onerror-attribute
event_handler!(error, GetOnerror, SetOnerror);
diff --git a/components/script/dom/serviceworkerglobalscope.rs b/components/script/dom/serviceworkerglobalscope.rs
index 3d26cbdb67f..f9c95d9af53 100644
--- a/components/script/dom/serviceworkerglobalscope.rs
+++ b/components/script/dom/serviceworkerglobalscope.rs
@@ -5,7 +5,6 @@
use devtools;
use devtools_traits::DevtoolScriptControlMsg;
use dom::abstractworker::WorkerScriptMsg;
-use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::ServiceWorkerGlobalScopeBinding;
use dom::bindings::codegen::Bindings::ServiceWorkerGlobalScopeBinding::ServiceWorkerGlobalScopeMethods;
@@ -14,9 +13,9 @@ use dom::bindings::inheritance::Castable;
use dom::bindings::js::{Root, RootCollection};
use dom::bindings::reflector::Reflectable;
use dom::bindings::str::DOMString;
+use dom::bindings::structuredclone::StructuredCloneData;
use dom::eventtarget::EventTarget;
use dom::messageevent::MessageEvent;
-use dom::serviceworker::TrustedServiceWorkerAddress;
use dom::workerglobalscope::WorkerGlobalScope;
use ipc_channel::ipc::{self, IpcSender, IpcReceiver};
use ipc_channel::router::ROUTER;
@@ -26,8 +25,8 @@ use js::rust::Runtime;
use msg::constellation_msg::PipelineId;
use net_traits::{LoadContext, load_whole_resource, IpcSend, CustomResponseMediator};
use rand::random;
-use script_runtime::{CommonScriptMsg, StackRootTLS, get_reports, new_rt_and_cx};
-use script_traits::{TimerEvent, WorkerGlobalScopeInit, ScopeThings, ServiceWorkerMsg};
+use script_runtime::{CommonScriptMsg, StackRootTLS, get_reports, new_rt_and_cx, ScriptChan};
+use script_traits::{TimerEvent, WorkerGlobalScopeInit, ScopeThings, ServiceWorkerMsg, DOMMessage};
use std::sync::mpsc::{Receiver, RecvError, Select, Sender, channel};
use std::thread;
use std::time::Duration;
@@ -49,6 +48,27 @@ pub enum MixedMessage {
FromServiceWorker(ServiceWorkerScriptMsg),
FromDevtools(DevtoolScriptControlMsg),
FromTimeoutThread(()),
+ PostMessage(DOMMessage)
+}
+
+// Required for run_with_memory_reporting
+#[derive(JSTraceable, Clone)]
+pub struct ServiceWorkerChan {
+ pub sender: Sender<ServiceWorkerScriptMsg>
+}
+
+impl ScriptChan for ServiceWorkerChan {
+ fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
+ self.sender
+ .send(ServiceWorkerScriptMsg::CommonWorker(WorkerScriptMsg::Common(msg)))
+ .map_err(|_| ())
+ }
+
+ fn clone(&self) -> Box<ScriptChan + Send> {
+ box ServiceWorkerChan {
+ sender: self.sender.clone(),
+ }
+ }
}
#[dom_struct]
@@ -61,12 +81,12 @@ pub struct ServiceWorkerGlobalScope {
own_sender: Sender<ServiceWorkerScriptMsg>,
#[ignore_heap_size_of = "Defined in std"]
timer_event_port: Receiver<()>,
- #[ignore_heap_size_of = "Trusted<T> has unclear ownership like JS<T>"]
- worker: DOMRefCell<Option<TrustedServiceWorkerAddress>>,
#[ignore_heap_size_of = "Defined in std"]
swmanager_sender: IpcSender<ServiceWorkerMsg>,
#[ignore_heap_size_of = "Defined in std"]
- scope_url: Url
+ msg_port: Receiver<DOMMessage>,
+ #[ignore_heap_size_of = "Defined in std"]
+ scope_url: Url,
}
impl ServiceWorkerGlobalScope {
@@ -80,7 +100,8 @@ impl ServiceWorkerGlobalScope {
timer_event_chan: IpcSender<TimerEvent>,
timer_event_port: Receiver<()>,
swmanager_sender: IpcSender<ServiceWorkerMsg>,
- scope_url: Url)
+ scope_url: Url,
+ msg_port: Receiver<DOMMessage>)
-> ServiceWorkerGlobalScope {
ServiceWorkerGlobalScope {
workerglobalscope: WorkerGlobalScope::new_inherited(init,
@@ -93,9 +114,9 @@ impl ServiceWorkerGlobalScope {
receiver: receiver,
timer_event_port: timer_event_port,
own_sender: own_sender,
- worker: DOMRefCell::new(None),
swmanager_sender: swmanager_sender,
- scope_url: scope_url
+ scope_url: scope_url,
+ msg_port: msg_port
}
}
@@ -109,7 +130,8 @@ impl ServiceWorkerGlobalScope {
timer_event_chan: IpcSender<TimerEvent>,
timer_event_port: Receiver<()>,
swmanager_sender: IpcSender<ServiceWorkerMsg>,
- scope_url: Url)
+ scope_url: Url,
+ msg_port: Receiver<DOMMessage>)
-> Root<ServiceWorkerGlobalScope> {
let cx = runtime.cx();
let scope = box ServiceWorkerGlobalScope::new_inherited(init,
@@ -122,7 +144,8 @@ impl ServiceWorkerGlobalScope {
timer_event_chan,
timer_event_port,
swmanager_sender,
- scope_url);
+ scope_url,
+ msg_port);
ServiceWorkerGlobalScopeBinding::Wrap(cx, scope)
}
@@ -132,7 +155,8 @@ impl ServiceWorkerGlobalScope {
receiver: Receiver<ServiceWorkerScriptMsg>,
devtools_receiver: IpcReceiver<DevtoolScriptControlMsg>,
swmanager_sender: IpcSender<ServiceWorkerMsg>,
- scope_url: Url) {
+ scope_url: Url,
+ msg_port: Receiver<DOMMessage>) {
let ScopeThings { script_url,
pipeline_id,
init,
@@ -167,7 +191,7 @@ impl ServiceWorkerGlobalScope {
let global = ServiceWorkerGlobalScope::new(
init, url, pipeline_id, devtools_mpsc_port, runtime,
own_sender, receiver,
- timer_ipc_chan, timer_port, swmanager_sender, scope_url);
+ timer_ipc_chan, timer_port, swmanager_sender, scope_url, msg_port);
let scope = global.upcast::<WorkerGlobalScope>();
unsafe {
@@ -214,6 +238,17 @@ impl ServiceWorkerGlobalScope {
self.handle_script_event(msg);
true
}
+ MixedMessage::PostMessage(data) => {
+ let DOMMessage(mut data) = data;
+ let data = StructuredCloneData::make_structured_clone(data.as_mut_ptr(), data.len());
+ let scope = self.upcast::<WorkerGlobalScope>();
+ let target = self.upcast();
+ let _ac = JSAutoCompartment::new(scope.get_cx(), scope.reflector().get_jsobject().get());
+ rooted!(in(scope.get_cx()) let mut message = UndefinedValue());
+ data.read(GlobalRef::Worker(scope), message.handle_mut());
+ MessageEvent::dispatch_jsval(target, GlobalRef::Worker(scope), message.handle());
+ true
+ }
MixedMessage::FromTimeoutThread(_) => {
let _ = self.swmanager_sender.send(ServiceWorkerMsg::Timeout(self.scope_url.clone()));
false
@@ -225,15 +260,7 @@ impl ServiceWorkerGlobalScope {
use self::ServiceWorkerScriptMsg::*;
match msg {
- CommonWorker(WorkerScriptMsg::DOMMessage(data)) => {
- let scope = self.upcast::<WorkerGlobalScope>();
- let target = self.upcast();
- let _ac = JSAutoCompartment::new(scope.get_cx(),
- scope.reflector().get_jsobject().get());
- rooted!(in(scope.get_cx()) let mut message = UndefinedValue());
- data.read(GlobalRef::Worker(scope), message.handle_mut());
- MessageEvent::dispatch_jsval(target, GlobalRef::Worker(scope), message.handle());
- },
+ CommonWorker(WorkerScriptMsg::DOMMessage(_)) => { },
CommonWorker(WorkerScriptMsg::Common(CommonScriptMsg::RunnableMsg(_, runnable))) => {
runnable.handler()
},
@@ -260,17 +287,20 @@ impl ServiceWorkerGlobalScope {
let worker_port = &self.receiver;
let devtools_port = scope.from_devtools_receiver();
let timer_event_port = &self.timer_event_port;
+ let msg_port = &self.msg_port;
let sel = Select::new();
let mut worker_handle = sel.handle(worker_port);
let mut devtools_handle = sel.handle(devtools_port);
let mut timer_port_handle = sel.handle(timer_event_port);
+ let mut msg_port_handle = sel.handle(msg_port);
unsafe {
worker_handle.add();
if scope.from_devtools_sender().is_some() {
devtools_handle.add();
}
timer_port_handle.add();
+ msg_port_handle.add();
}
let ret = sel.wait();
@@ -280,6 +310,8 @@ impl ServiceWorkerGlobalScope {
Ok(MixedMessage::FromDevtools(try!(devtools_port.recv())))
} else if ret == timer_port_handle.id() {
Ok(MixedMessage::FromTimeoutThread(try!(timer_event_port.recv())))
+ } else if ret == msg_port_handle.id() {
+ Ok(MixedMessage::PostMessage(try!(msg_port.recv())))
} else {
panic!("unexpected select result!")
}
@@ -292,6 +324,12 @@ impl ServiceWorkerGlobalScope {
pub fn process_event(&self, msg: CommonScriptMsg) {
self.handle_script_event(ServiceWorkerScriptMsg::CommonWorker(WorkerScriptMsg::Common(msg)));
}
+
+ pub fn script_chan(&self) -> Box<ScriptChan + Send> {
+ box ServiceWorkerChan {
+ sender: self.own_sender.clone()
+ }
+ }
}
#[allow(unsafe_code)]
diff --git a/components/script/dom/serviceworkerregistration.rs b/components/script/dom/serviceworkerregistration.rs
index e20b7e06c47..bb44c1e2f78 100644
--- a/components/script/dom/serviceworkerregistration.rs
+++ b/components/script/dom/serviceworkerregistration.rs
@@ -6,10 +6,11 @@ use dom::bindings::codegen::Bindings::ServiceWorkerBinding::ServiceWorkerState;
use dom::bindings::codegen::Bindings::ServiceWorkerRegistrationBinding::{ServiceWorkerRegistrationMethods, Wrap};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, Root};
+use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::USVString;
use dom::eventtarget::EventTarget;
-use dom::serviceworker::ServiceWorker;
+use dom::serviceworker::{ServiceWorker, TrustedServiceWorkerAddress};
use dom::serviceworkercontainer::Controllable;
use dom::workerglobalscope::prepare_workerscope_init;
use script_traits::{WorkerScriptLoadOrigin, ScopeThings};
@@ -49,6 +50,10 @@ impl ServiceWorkerRegistration {
self.active.as_ref().unwrap()
}
+ pub fn get_trusted_worker(&self) -> TrustedServiceWorkerAddress {
+ Trusted::new(self.active.as_ref().unwrap())
+ }
+
pub fn create_scope_things(global: GlobalRef, script_url: Url) -> ScopeThings {
let worker_load_origin = WorkerScriptLoadOrigin {
referrer_url: None,
diff --git a/components/script/dom/webidls/ServiceWorker.webidl b/components/script/dom/webidls/ServiceWorker.webidl
index efea6603c3f..0d0855f4239 100644
--- a/components/script/dom/webidls/ServiceWorker.webidl
+++ b/components/script/dom/webidls/ServiceWorker.webidl
@@ -7,7 +7,7 @@
interface ServiceWorker : EventTarget {
readonly attribute USVString scriptURL;
readonly attribute ServiceWorkerState state;
- //[Throws] void postMessage(any message/*, optional sequence<Transferable> transfer*/);
+ [Throws] void postMessage(any message/*, optional sequence<Transferable> transfer*/);
// event
attribute EventHandler onstatechange;
diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs
index 9f61753ca64..993321093b2 100644
--- a/components/script/dom/workerglobalscope.rs
+++ b/components/script/dom/workerglobalscope.rs
@@ -392,10 +392,12 @@ impl WorkerGlobalScope {
}
pub fn script_chan(&self) -> Box<ScriptChan + Send> {
- let dedicated =
- self.downcast::<DedicatedWorkerGlobalScope>();
+ let dedicated = self.downcast::<DedicatedWorkerGlobalScope>();
+ let service_worker = self.downcast::<ServiceWorkerGlobalScope>();
if let Some(dedicated) = dedicated {
return dedicated.script_chan();
+ } else if let Some(service_worker) = service_worker {
+ return service_worker.script_chan();
} else {
panic!("need to implement a sender for SharedWorker/ServiceWorker")
}
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index ac6165d5c4f..fb5abc005d8 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -42,7 +42,7 @@ use dom::element::Element;
use dom::event::{Event, EventBubbles, EventCancelable};
use dom::htmlanchorelement::HTMLAnchorElement;
use dom::node::{Node, NodeDamage, window_from_node};
-use dom::serviceworker::TrustedServiceWorkerAddress;
+use dom::serviceworker::{TrustedServiceWorkerAddress, ServiceWorker};
use dom::serviceworkerregistration::ServiceWorkerRegistration;
use dom::servohtmlparser::ParserContext;
use dom::uievent::UIEvent;
@@ -84,7 +84,7 @@ use script_traits::CompositorEvent::{TouchEvent, TouchpadPressureEvent};
use script_traits::webdriver_msg::WebDriverScriptCommand;
use script_traits::{CompositorEvent, ConstellationControlMsg, EventResult};
use script_traits::{InitialScriptState, MouseButton, MouseEventType, MozBrowserEvent};
-use script_traits::{NewLayoutInfo, ScriptMsg as ConstellationMsg};
+use script_traits::{NewLayoutInfo, ScriptMsg as ConstellationMsg, DOMMessage};
use script_traits::{ScriptThreadFactory, TimerEvent, TimerEventRequest, TimerSource};
use script_traits::{TouchEventType, TouchId, UntrustedNodeAddress, WindowSizeData};
use std::borrow::ToOwned;
@@ -924,6 +924,8 @@ impl ScriptThread {
self.handle_css_error_reporting(pipeline_id, filename, line, column, msg),
ConstellationControlMsg::Reload(pipeline_id) =>
self.handle_reload(pipeline_id),
+ ConstellationControlMsg::ConnectServiceWorker(scope_url, chan) =>
+ self.connect_serviceworker_to_scope(scope_url, chan),
msg @ ConstellationControlMsg::AttachLayout(..) |
msg @ ConstellationControlMsg::Viewport(..) |
msg @ ConstellationControlMsg::SetScrollState(..) |
@@ -1456,7 +1458,16 @@ impl ScriptThread {
let scope_things = ServiceWorkerRegistration::create_scope_things(global_ref, script_url);
let _ = self.constellation_chan.send(ConstellationMsg::RegisterServiceWorker(scope_things, scope));
} else {
- warn!("Registration failed for {}", pipeline_id);
+ warn!("Registration failed for {}", scope);
+ }
+ }
+
+ // Set the sender to the corresponding scope of the service worker object.
+ fn connect_serviceworker_to_scope(&self, scope_url: Url, chan: IpcSender<DOMMessage>) {
+ let ref maybe_registration_ref = *self.registration_map.borrow();
+ if let Some(ref registration) = maybe_registration_ref.get(&scope_url) {
+ let trusted_worker = registration.get_trusted_worker();
+ ServiceWorker::store_sender(trusted_worker, chan);
}
}
diff --git a/components/script/serviceworker_manager.rs b/components/script/serviceworker_manager.rs
index 09f5288929a..898bd2b63f3 100644
--- a/components/script/serviceworker_manager.rs
+++ b/components/script/serviceworker_manager.rs
@@ -35,19 +35,23 @@ pub struct ServiceWorkerManager {
// receiver to receive messages from constellation
own_port: Receiver<ServiceWorkerMsg>,
// to receive resource messages
- resource_receiver: Receiver<CustomResponseMediator>
+ resource_receiver: Receiver<CustomResponseMediator>,
+ // to send message to constellation
+ constellation_sender: IpcSender<SWManagerMsg>
}
impl ServiceWorkerManager {
fn new(own_sender: IpcSender<ServiceWorkerMsg>,
from_constellation_receiver: Receiver<ServiceWorkerMsg>,
- resource_port: Receiver<CustomResponseMediator>) -> ServiceWorkerManager {
+ resource_port: Receiver<CustomResponseMediator>,
+ constellation_sender: IpcSender<SWManagerMsg>) -> ServiceWorkerManager {
ServiceWorkerManager {
registered_workers: HashMap::new(),
active_workers: HashMap::new(),
own_sender: own_sender,
own_port: from_constellation_receiver,
- resource_receiver: resource_port
+ resource_receiver: resource_port,
+ constellation_sender: constellation_sender
}
}
@@ -58,8 +62,12 @@ impl ServiceWorkerManager {
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()));
+ let constellation_sender = sw_senders.swmanager_sender.clone();
spawn_named("ServiceWorkerManager".to_owned(), move || {
- ServiceWorkerManager::new(own_sender, from_constellation, resource_port).handle_message();
+ ServiceWorkerManager::new(own_sender,
+ from_constellation,
+ resource_port,
+ constellation_sender).handle_message();
});
}
@@ -93,12 +101,20 @@ impl ServiceWorkerManager {
devtools_sender.clone(),
page_info));
};
+ let (msg_chan, msg_port) = ipc::channel().unwrap();
+ let msg_port = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(msg_port);
ServiceWorkerGlobalScope::run_serviceworker_scope(scope_things.clone(),
- sender.clone(),
- receiver,
- devtools_receiver,
- self.own_sender.clone(),
- scope_url.clone());
+ sender.clone(),
+ receiver,
+ devtools_receiver,
+ self.own_sender.clone(),
+ scope_url.clone(),
+ msg_port);
+ // Send the message to constellation which then talks to the script thread for storing this msg_chan
+ let connection_msg = SWManagerMsg::ConnectServiceWorker(scope_url.clone(),
+ scope_things.pipeline_id,
+ msg_chan);
+ let _ = self.constellation_sender.send(connection_msg);
// We store the activated worker
self.active_workers.insert(scope_url, scope_things.clone());
return Some(sender);
diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs
index 897f20bb3b2..ce708fd34ab 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -71,7 +71,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, SWManagerSenders};
+pub use script_msg::{ServiceWorkerMsg, ScopeThings, SWManagerMsg, SWManagerSenders, DOMMessage};
/// 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.
@@ -208,6 +208,8 @@ pub enum ConstellationControlMsg {
ReportCSSError(PipelineId, String, usize, usize, String),
/// Reload the given page.
Reload(PipelineId),
+ /// Requests the script thread to connect service worker object to its scope
+ ConnectServiceWorker(Url, IpcSender<DOMMessage>)
}
impl fmt::Debug for ConstellationControlMsg {
@@ -237,6 +239,7 @@ impl fmt::Debug for ConstellationControlMsg {
FramedContentChanged(..) => "FramedContentChanged",
ReportCSSError(..) => "ReportCSSError",
Reload(..) => "Reload",
+ ConnectServiceWorker(..) => "ConnectServiceWorker"
})
}
}
diff --git a/components/script_traits/script_msg.rs b/components/script_traits/script_msg.rs
index d183336f6f8..b1a9f2e6a52 100644
--- a/components/script_traits/script_msg.rs
+++ b/components/script_traits/script_msg.rs
@@ -158,6 +158,10 @@ pub struct ScopeThings {
pub worker_id: WorkerId,
}
+/// Message that gets passed to service worker scope on postMessage
+#[derive(Deserialize, Serialize, Debug)]
+pub struct DOMMessage(pub Vec<u64>);
+
/// Channels to allow service worker manager to communicate with constellation and resource thread
pub struct SWManagerSenders {
/// sender for communicating with constellation
@@ -182,4 +186,7 @@ pub enum ServiceWorkerMsg {
pub enum SWManagerMsg {
/// Provide the constellation with a means of communicating with the Service Worker Manager
OwnSender(IpcSender<ServiceWorkerMsg>),
+ /// Message to ask to get a Trusted<ServiceWorker> to constellation
+ ConnectServiceWorker(Url, PipelineId, IpcSender<DOMMessage>)
+
}
diff --git a/tests/html/service-worker/iframe_sw.js b/tests/html/service-worker/iframe_sw.js
index d9c76b8d6f1..51bce022ffe 100644
--- a/tests/html/service-worker/iframe_sw.js
+++ b/tests/html/service-worker/iframe_sw.js
@@ -4,4 +4,8 @@ self.addEventListener('activate', function(e) {
self.addEventListener('fetch', function(e) {
console.log("A fetch event detected by /iframe service worker");
-}); \ No newline at end of file
+});
+
+self.addEventListener('message', function(e) {
+ console.log('Post message payload ' + e.data.msg);
+})
diff --git a/tests/html/service-worker/index.html b/tests/html/service-worker/index.html
index a20fcbb67e4..72081e62a2d 100644
--- a/tests/html/service-worker/index.html
+++ b/tests/html/service-worker/index.html
@@ -23,6 +23,13 @@
console.log("From client worker registered: ", navigator.serviceWorker.controller);
console.log("Registered script source: "+ navigator.serviceWorker.controller.scriptURL);
document.getElementById('iframe_sw').src = 'demo_iframe.html';
+ var payload = { msg: 'Hi from /iframe service worker' };
+
+ // The delay is due to the sender being set in the service worker object after the scope starts.
+ // This won't be needed when service workers are wrapped with Promises.
+ setTimeout(function() {
+ navigator.serviceWorker.controller.postMessage(payload);
+ }, 1000);
function register_zero() {
var reg = navigator.serviceWorker.register('sw.js', { 'scope': './' });