Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement postMessage for ServiceWorkers #12910

Merged
merged 3 commits into from Sep 15, 2016
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Prev

make structured clone an enum

  • Loading branch information
creativcoder committed Sep 15, 2016
commit 314dedb96fdea9d7656a3be166aec7749d2b85da
@@ -11,14 +11,15 @@ use js::jsapi::{HandleValue, MutableHandleValue};
use js::jsapi::{JSContext, JS_ReadStructuredClone, JS_STRUCTURED_CLONE_VERSION};
use js::jsapi::{JS_ClearPendingException, JS_WriteStructuredClone};
use libc::size_t;
use script_traits::DOMMessage;
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 {
@@ -41,44 +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) -> DOMMessage {
unsafe {
DOMMessage(slice::from_raw_parts(self.data as *mut u8, self.nbytes).to_vec())
}
}

/// Converts back to StructuredCloneData
pub fn make_structured_clone(data: DOMMessage) -> StructuredCloneData {
let DOMMessage(mut data) = data;
let nbytes = data.len();
let data = data.as_mut_ptr() as *mut u64;
StructuredCloneData {
data: data,
nbytes: nbytes
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 {}
@@ -11,13 +11,13 @@ 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;
use script_traits::{ScriptMsg, DOMMessage};
use std::cell::Cell;
use url::Url;

@@ -27,29 +27,31 @@ pub type TrustedServiceWorkerAddress = Trusted<ServiceWorker>;
pub struct ServiceWorker {
eventtarget: EventTarget,
script_url: DOMRefCell<String>,
scope_url: DOMRefCell<String>,
scope_url: Url,
state: Cell<ServiceWorkerState>,
skip_waiting: Cell<bool>
}

impl ServiceWorker {
fn new_inherited(script_url: &str,
skip_waiting: bool,
scope_url: &str) -> ServiceWorker {
scope_url: Url) -> ServiceWorker {
ServiceWorker {
eventtarget: EventTarget::new_inherited(),
script_url: DOMRefCell::new(String::from(script_url)),
state: Cell::new(ServiceWorkerState::Installing),
scope_url: DOMRefCell::new(String::from(scope_url)),
scope_url: scope_url,
skip_waiting: Cell::new(skip_waiting)
}
}

pub fn new(global: GlobalRef,
script_url: &str,
scope_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, scope_url), 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) {
@@ -65,16 +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,
scope_url: &str,
skip_waiting: bool) -> Root<ServiceWorker> {
ServiceWorker::new(global,
script_url.as_str(),
scope_url,
skip_waiting)
}
}

impl ServiceWorkerMethods for ServiceWorker {
@@ -96,9 +88,9 @@ impl ServiceWorkerMethods for ServiceWorker {
}
// Step 7
let data = try!(StructuredCloneData::write(cx, message));
let msg_vec = data.move_to_arraybuffer();
let scope_url = Url::parse(&*self.scope_url.borrow()).unwrap();
let _ = self.global().r().constellation_chan().send(ScriptMsg::ForwardDOMMessage(msg_vec, scope_url));
let msg_vec = DOMMessage(data.move_to_arraybuffer());
let _ = self.global().r().constellation_chan().send(ScriptMsg::ForwardDOMMessage(msg_vec,
self.scope_url.clone()));
Ok(())
}

@@ -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());
Ok(worker_registration)
@@ -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(), &scope, 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)
@@ -123,9 +123,9 @@ impl ServiceWorkerManager {
}
}

#[inline(always)]
fn forward_message(&self, msg: DOMMessage, sender: &Sender<ServiceWorkerScriptMsg>) {
let data = StructuredCloneData::make_structured_clone(msg);
let DOMMessage(data) = msg;
let data = StructuredCloneData::Vector(data);
let _ = sender.send(ServiceWorkerScriptMsg::CommonWorker(WorkerScriptMsg::DOMMessage(data)));
}

@@ -180,7 +180,7 @@ pub enum ServiceWorkerMsg {
RegisterServiceWorker(ScopeThings, Url),
/// Timeout message sent by active service workers
Timeout(Url),
/// Backup message
/// Message sent by constellation to forward to a running service worker
ForwardDOMMessage(DOMMessage, Url),
/// Exit the service worker manager
Exit,
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.