mirror of
https://github.com/servo/servo.git
synced 2025-07-30 18:50:36 +01:00
Auto merge of #12910 - creativcoder:swsender, r=jdm
Implement postMessage for ServiceWorkers <!-- Please describe your changes on the following line: --> Fixes #12773 r? @jdm Changes: * Implements `postMessage` on `ServiceWorker` object. * Removes unused channels from sw and their scopes. * Fixes a crash when calling `scope.script_chan()` in sw-scopes event handling. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #12773 <!-- Either: --> - [X] There are tests for these changes at `tests/html/service-worker` <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/12910) <!-- Reviewable:end -->
This commit is contained in:
commit
0ec4ea4ee1
19 changed files with 256 additions and 118 deletions
|
@ -12,11 +12,14 @@ 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 {
|
||||
data: *mut u64,
|
||||
nbytes: size_t,
|
||||
pub enum StructuredCloneData {
|
||||
/// A non-serializable (default) variant
|
||||
Struct(*mut u64, size_t),
|
||||
/// A variant that can be serialized
|
||||
Vector(Vec<u8>)
|
||||
}
|
||||
|
||||
impl StructuredCloneData {
|
||||
|
@ -39,26 +42,47 @@ impl StructuredCloneData {
|
|||
}
|
||||
return Err(Error::DataClone);
|
||||
}
|
||||
Ok(StructuredCloneData {
|
||||
data: data,
|
||||
nbytes: nbytes,
|
||||
})
|
||||
Ok(StructuredCloneData::Struct(data, nbytes))
|
||||
}
|
||||
|
||||
/// Converts a StructuredCloneData to Vec<u8> for inter-thread sharing
|
||||
pub fn move_to_arraybuffer(self) -> Vec<u8> {
|
||||
match self {
|
||||
StructuredCloneData::Struct(data, nbytes) => {
|
||||
unsafe {
|
||||
slice::from_raw_parts(data as *mut u8, nbytes).to_vec()
|
||||
}
|
||||
}
|
||||
StructuredCloneData::Vector(msg) => msg
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads a structured clone.
|
||||
///
|
||||
/// Panics if `JS_ReadStructuredClone` fails.
|
||||
pub fn read(self, global: GlobalRef, rval: MutableHandleValue) {
|
||||
fn read_clone(global: GlobalRef, data: *mut u64, nbytes: size_t, rval: MutableHandleValue) {
|
||||
unsafe {
|
||||
assert!(JS_ReadStructuredClone(global.get_cx(),
|
||||
self.data,
|
||||
self.nbytes,
|
||||
data,
|
||||
nbytes,
|
||||
JS_STRUCTURED_CLONE_VERSION,
|
||||
rval,
|
||||
ptr::null(),
|
||||
ptr::null_mut()));
|
||||
}
|
||||
}
|
||||
|
||||
/// Thunk for the actual `read_clone` method. Resolves proper variant for read_clone.
|
||||
pub fn read(self, global: GlobalRef, rval: MutableHandleValue) {
|
||||
match self {
|
||||
StructuredCloneData::Vector(mut vec_msg) => {
|
||||
let nbytes = vec_msg.len();
|
||||
let data = vec_msg.as_mut_ptr() as *mut u64;
|
||||
StructuredCloneData::read_clone(global, data, nbytes, rval);
|
||||
}
|
||||
StructuredCloneData::Struct(data, nbytes) => StructuredCloneData::read_clone(global, data, nbytes, rval)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for StructuredCloneData {}
|
||||
|
|
|
@ -2,20 +2,23 @@
|
|||
* 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, Error};
|
||||
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::reflector::{Reflectable, reflect_dom_object};
|
||||
use dom::bindings::str::USVString;
|
||||
use dom::bindings::structuredclone::StructuredCloneData;
|
||||
use dom::eventtarget::EventTarget;
|
||||
use js::jsapi::{HandleValue, JSContext};
|
||||
use script_thread::Runnable;
|
||||
use script_traits::{ScriptMsg, DOMMessage};
|
||||
use std::cell::Cell;
|
||||
use std::sync::mpsc::Sender;
|
||||
use url::Url;
|
||||
|
||||
pub type TrustedServiceWorkerAddress = Trusted<ServiceWorker>;
|
||||
|
@ -24,28 +27,31 @@ pub type TrustedServiceWorkerAddress = Trusted<ServiceWorker>;
|
|||
pub struct ServiceWorker {
|
||||
eventtarget: EventTarget,
|
||||
script_url: DOMRefCell<String>,
|
||||
scope_url: Url,
|
||||
state: Cell<ServiceWorkerState>,
|
||||
#[ignore_heap_size_of = "Defined in std"]
|
||||
sender: Option<Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>>,
|
||||
skip_waiting: Cell<bool>
|
||||
}
|
||||
|
||||
impl ServiceWorker {
|
||||
fn new_inherited(script_url: &str,
|
||||
skip_waiting: bool) -> ServiceWorker {
|
||||
skip_waiting: bool,
|
||||
scope_url: Url) -> ServiceWorker {
|
||||
ServiceWorker {
|
||||
eventtarget: EventTarget::new_inherited(),
|
||||
sender: None,
|
||||
script_url: DOMRefCell::new(String::from(script_url)),
|
||||
state: Cell::new(ServiceWorkerState::Installing),
|
||||
scope_url: scope_url,
|
||||
skip_waiting: Cell::new(skip_waiting)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(global: GlobalRef,
|
||||
script_url: &str,
|
||||
pub fn install_serviceworker(global: GlobalRef,
|
||||
script_url: Url,
|
||||
scope_url: Url,
|
||||
skip_waiting: bool) -> Root<ServiceWorker> {
|
||||
reflect_dom_object(box ServiceWorker::new_inherited(script_url, skip_waiting), global, Wrap)
|
||||
reflect_dom_object(box ServiceWorker::new_inherited(script_url.as_str(),
|
||||
skip_waiting,
|
||||
scope_url), global, Wrap)
|
||||
}
|
||||
|
||||
pub fn dispatch_simple_error(address: TrustedServiceWorkerAddress) {
|
||||
|
@ -61,14 +67,6 @@ impl ServiceWorker {
|
|||
pub fn get_script_url(&self) -> Url {
|
||||
Url::parse(&self.script_url.borrow().clone()).unwrap()
|
||||
}
|
||||
|
||||
pub fn install_serviceworker(global: GlobalRef,
|
||||
script_url: Url,
|
||||
skip_waiting: bool) -> Root<ServiceWorker> {
|
||||
ServiceWorker::new(global,
|
||||
script_url.as_str(),
|
||||
skip_waiting)
|
||||
}
|
||||
}
|
||||
|
||||
impl ServiceWorkerMethods for ServiceWorker {
|
||||
|
@ -82,6 +80,20 @@ 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 {
|
||||
// Step 1
|
||||
if let ServiceWorkerState::Redundant = self.state.get() {
|
||||
return Err(Error::InvalidState);
|
||||
}
|
||||
// Step 7
|
||||
let data = try!(StructuredCloneData::write(cx, message));
|
||||
let msg_vec = DOMMessage(data.move_to_arraybuffer());
|
||||
let _ = self.global().r().constellation_chan().send(ScriptMsg::ForwardDOMMessage(msg_vec,
|
||||
self.scope_url.clone()));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-container-onerror-attribute
|
||||
event_handler!(error, GetOnerror, SetOnerror);
|
||||
|
||||
|
|
|
@ -95,10 +95,9 @@ impl ServiceWorkerContainerMethods for ServiceWorkerContainer {
|
|||
return Err(Error::Type("Scope URL contains forbidden characters".to_owned()));
|
||||
}
|
||||
|
||||
let scope_str = scope.as_str().to_owned();
|
||||
let worker_registration = ServiceWorkerRegistration::new(self.global().r(),
|
||||
script_url,
|
||||
scope_str.clone(),
|
||||
scope.clone(),
|
||||
self);
|
||||
ScriptThread::set_registration(scope, &*worker_registration, self.global().r().pipeline_id());
|
||||
Ok(worker_registration)
|
||||
|
|
|
@ -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;
|
||||
|
@ -16,7 +15,6 @@ use dom::bindings::reflector::Reflectable;
|
|||
use dom::bindings::str::DOMString;
|
||||
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,13 +24,12 @@ 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_runtime::{CommonScriptMsg, StackRootTLS, get_reports, new_rt_and_cx, ScriptChan};
|
||||
use script_traits::{TimerEvent, WorkerGlobalScopeInit, ScopeThings, ServiceWorkerMsg};
|
||||
use std::sync::mpsc::{Receiver, RecvError, Select, Sender, channel};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use style::thread_state;
|
||||
use style::thread_state::{IN_WORKER, SCRIPT};
|
||||
use style::thread_state::{self, IN_WORKER, SCRIPT};
|
||||
use url::Url;
|
||||
use util::prefs::PREFS;
|
||||
use util::thread::spawn_named;
|
||||
|
@ -48,7 +45,26 @@ pub enum ServiceWorkerScriptMsg {
|
|||
pub enum MixedMessage {
|
||||
FromServiceWorker(ServiceWorkerScriptMsg),
|
||||
FromDevtools(DevtoolScriptControlMsg),
|
||||
FromTimeoutThread(()),
|
||||
FromTimeoutThread(())
|
||||
}
|
||||
|
||||
#[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 +77,9 @@ 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
|
||||
scope_url: Url,
|
||||
}
|
||||
|
||||
impl ServiceWorkerGlobalScope {
|
||||
|
@ -93,7 +106,6 @@ 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
|
||||
}
|
||||
|
@ -228,8 +240,7 @@ impl ServiceWorkerGlobalScope {
|
|||
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());
|
||||
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());
|
||||
|
@ -292,6 +303,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)]
|
||||
|
|
|
@ -25,21 +25,21 @@ pub struct ServiceWorkerRegistration {
|
|||
}
|
||||
|
||||
impl ServiceWorkerRegistration {
|
||||
fn new_inherited(active_sw: &ServiceWorker, scope: String) -> ServiceWorkerRegistration {
|
||||
fn new_inherited(active_sw: &ServiceWorker, scope: Url) -> ServiceWorkerRegistration {
|
||||
ServiceWorkerRegistration {
|
||||
eventtarget: EventTarget::new_inherited(),
|
||||
active: Some(JS::from_ref(active_sw)),
|
||||
installing: None,
|
||||
waiting: None,
|
||||
scope: scope,
|
||||
scope: scope.as_str().to_owned(),
|
||||
}
|
||||
}
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn new(global: GlobalRef,
|
||||
script_url: Url,
|
||||
scope: String,
|
||||
scope: Url,
|
||||
container: &Controllable) -> Root<ServiceWorkerRegistration> {
|
||||
let active_worker = ServiceWorker::install_serviceworker(global, script_url.clone(), true);
|
||||
let active_worker = ServiceWorker::install_serviceworker(global, script_url.clone(), scope.clone(), true);
|
||||
active_worker.set_transition_state(ServiceWorkerState::Installed);
|
||||
container.set_controller(&*active_worker.clone());
|
||||
reflect_dom_object(box ServiceWorkerRegistration::new_inherited(&*active_worker, scope), global, Wrap)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -397,12 +397,14 @@ 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")
|
||||
panic!("need to implement a sender for SharedWorker")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1450,7 +1450,7 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,12 +8,14 @@
|
|||
//! active_workers map
|
||||
|
||||
use devtools_traits::{DevtoolsPageInfo, ScriptToDevtoolsControlMsg};
|
||||
use dom::abstractworker::WorkerScriptMsg;
|
||||
use dom::bindings::structuredclone::StructuredCloneData;
|
||||
use dom::serviceworkerglobalscope::{ServiceWorkerGlobalScope, ServiceWorkerScriptMsg};
|
||||
use dom::serviceworkerregistration::longest_prefix_match;
|
||||
use ipc_channel::ipc::{self, IpcSender};
|
||||
use ipc_channel::router::ROUTER;
|
||||
use net_traits::{CustomResponseMediator, CoreResourceMsg};
|
||||
use script_traits::{ServiceWorkerMsg, ScopeThings, SWManagerMsg, SWManagerSenders};
|
||||
use script_traits::{ServiceWorkerMsg, ScopeThings, SWManagerMsg, SWManagerSenders, DOMMessage};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::mpsc::{channel, Sender, Receiver, RecvError};
|
||||
use url::Url;
|
||||
|
@ -29,7 +31,7 @@ pub struct ServiceWorkerManager {
|
|||
// map of registered service worker descriptors
|
||||
registered_workers: HashMap<Url, ScopeThings>,
|
||||
// map of active service worker descriptors
|
||||
active_workers: HashMap<Url, ScopeThings>,
|
||||
active_workers: HashMap<Url, Sender<ServiceWorkerScriptMsg>>,
|
||||
// own sender to send messages here
|
||||
own_sender: IpcSender<ServiceWorkerMsg>,
|
||||
// receiver to receive messages from constellation
|
||||
|
@ -59,56 +61,52 @@ impl ServiceWorkerManager {
|
|||
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, resource_port).handle_message();
|
||||
ServiceWorkerManager::new(own_sender,
|
||||
from_constellation,
|
||||
resource_port).handle_message();
|
||||
});
|
||||
}
|
||||
|
||||
pub fn prepare_activation(&mut self, load_url: &Url) -> Option<Sender<ServiceWorkerScriptMsg>> {
|
||||
let mut scope_url = None;
|
||||
pub fn get_matching_scope(&self, load_url: &Url) -> Option<Url> {
|
||||
for scope in self.registered_workers.keys() {
|
||||
if longest_prefix_match(&scope, load_url) {
|
||||
scope_url = Some(scope.clone());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(scope_url) = scope_url {
|
||||
if self.active_workers.contains_key(&scope_url) {
|
||||
// do not run the same worker if already active.
|
||||
warn!("Service worker for {:?} already active", scope_url);
|
||||
return None;
|
||||
}
|
||||
let scope_things = self.registered_workers.get(&scope_url);
|
||||
if let Some(scope_things) = scope_things {
|
||||
let (sender, receiver) = channel();
|
||||
let (devtools_sender, devtools_receiver) = ipc::channel().unwrap();
|
||||
if let Some(ref chan) = scope_things.devtools_chan {
|
||||
let title = format!("ServiceWorker for {}", scope_things.script_url);
|
||||
let page_info = DevtoolsPageInfo {
|
||||
title: title,
|
||||
url: scope_things.script_url.clone(),
|
||||
};
|
||||
let _ = chan.send(ScriptToDevtoolsControlMsg::NewGlobal((scope_things.pipeline_id,
|
||||
Some(scope_things.worker_id)),
|
||||
devtools_sender.clone(),
|
||||
page_info));
|
||||
};
|
||||
ServiceWorkerGlobalScope::run_serviceworker_scope(scope_things.clone(),
|
||||
sender.clone(),
|
||||
receiver,
|
||||
devtools_receiver,
|
||||
self.own_sender.clone(),
|
||||
scope_url.clone());
|
||||
// We store the activated worker
|
||||
self.active_workers.insert(scope_url, scope_things.clone());
|
||||
return Some(sender);
|
||||
} else {
|
||||
warn!("Unable to activate service worker");
|
||||
return Some(scope.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn wakeup_serviceworker(&mut self, scope_url: Url) -> Option<Sender<ServiceWorkerScriptMsg>> {
|
||||
let scope_things = self.registered_workers.get(&scope_url);
|
||||
if let Some(scope_things) = scope_things {
|
||||
let (sender, receiver) = channel();
|
||||
let (devtools_sender, devtools_receiver) = ipc::channel().unwrap();
|
||||
if let Some(ref chan) = scope_things.devtools_chan {
|
||||
let title = format!("ServiceWorker for {}", scope_things.script_url);
|
||||
let page_info = DevtoolsPageInfo {
|
||||
title: title,
|
||||
url: scope_things.script_url.clone(),
|
||||
};
|
||||
let _ = chan.send(ScriptToDevtoolsControlMsg::NewGlobal((scope_things.pipeline_id,
|
||||
Some(scope_things.worker_id)),
|
||||
devtools_sender,
|
||||
page_info));
|
||||
};
|
||||
ServiceWorkerGlobalScope::run_serviceworker_scope(scope_things.clone(),
|
||||
sender.clone(),
|
||||
receiver,
|
||||
devtools_receiver,
|
||||
self.own_sender.clone(),
|
||||
scope_url.clone());
|
||||
// We store the activated worker
|
||||
self.active_workers.insert(scope_url, sender.clone());
|
||||
return Some(sender);
|
||||
} else {
|
||||
warn!("Unable to activate service worker");
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_message(&mut self) {
|
||||
while let Ok(message) = self.receive_message() {
|
||||
let should_continue = match message {
|
||||
|
@ -125,6 +123,12 @@ impl ServiceWorkerManager {
|
|||
}
|
||||
}
|
||||
|
||||
fn forward_message(&self, msg: DOMMessage, sender: &Sender<ServiceWorkerScriptMsg>) {
|
||||
let DOMMessage(data) = msg;
|
||||
let data = StructuredCloneData::Vector(data);
|
||||
let _ = sender.send(ServiceWorkerScriptMsg::CommonWorker(WorkerScriptMsg::DOMMessage(data)));
|
||||
}
|
||||
|
||||
fn handle_message_from_constellation(&mut self, msg: ServiceWorkerMsg) -> bool {
|
||||
match msg {
|
||||
ServiceWorkerMsg::RegisterServiceWorker(scope_things, scope) => {
|
||||
|
@ -139,7 +143,19 @@ impl ServiceWorkerManager {
|
|||
if self.active_workers.contains_key(&scope) {
|
||||
let _ = self.active_workers.remove(&scope);
|
||||
} else {
|
||||
warn!("ScopeThings for {:?} is not active", scope);
|
||||
warn!("ServiceWorker for {:?} is not active", scope);
|
||||
}
|
||||
true
|
||||
},
|
||||
ServiceWorkerMsg::ForwardDOMMessage(msg, scope_url) => {
|
||||
if self.active_workers.contains_key(&scope_url) {
|
||||
if let Some(ref sender) = self.active_workers.get(&scope_url) {
|
||||
self.forward_message(msg, &sender);
|
||||
}
|
||||
} else {
|
||||
if let Some(ref sender) = self.wakeup_serviceworker(scope_url) {
|
||||
self.forward_message(msg, &sender);
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
@ -147,12 +163,20 @@ impl ServiceWorkerManager {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn handle_message_from_resource(&mut self, mediator: CustomResponseMediator) -> bool {
|
||||
if serviceworker_enabled() {
|
||||
let worker_sender = self.prepare_activation(&mediator.load_url);
|
||||
if let Some(ref sender) = worker_sender {
|
||||
let _ = sender.send(ServiceWorkerScriptMsg::Response(mediator));
|
||||
if let Some(scope) = self.get_matching_scope(&mediator.load_url) {
|
||||
if self.active_workers.contains_key(&scope) {
|
||||
if let Some(sender) = self.active_workers.get(&scope) {
|
||||
let _ = sender.send(ServiceWorkerScriptMsg::Response(mediator));
|
||||
}
|
||||
} else {
|
||||
if let Some(sender) = self.wakeup_serviceworker(scope) {
|
||||
let _ = sender.send(ServiceWorkerScriptMsg::Response(mediator));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let _ = mediator.response_chan.send(None);
|
||||
}
|
||||
} else {
|
||||
let _ = mediator.response_chan.send(None);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue