diff options
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/bindings/structuredclone.rs | 44 | ||||
-rw-r--r-- | components/script/dom/bluetooth.rs | 267 | ||||
-rw-r--r-- | components/script/dom/serviceworker.rs | 48 | ||||
-rw-r--r-- | components/script/dom/serviceworkercontainer.rs | 3 | ||||
-rw-r--r-- | components/script/dom/serviceworkerglobalscope.rs | 43 | ||||
-rw-r--r-- | components/script/dom/serviceworkerregistration.rs | 8 | ||||
-rw-r--r-- | components/script/dom/webidls/Bluetooth.webidl | 17 | ||||
-rw-r--r-- | components/script/dom/webidls/DOMTokenList.webidl | 1 | ||||
-rw-r--r-- | components/script/dom/webidls/ServiceWorker.webidl | 2 | ||||
-rw-r--r-- | components/script/dom/worker.rs | 5 | ||||
-rw-r--r-- | components/script/dom/workerglobalscope.rs | 8 |
11 files changed, 310 insertions, 136 deletions
diff --git a/components/script/dom/bindings/structuredclone.rs b/components/script/dom/bindings/structuredclone.rs index f9c4e98f2f9..21963eec172 100644 --- a/components/script/dom/bindings/structuredclone.rs +++ b/components/script/dom/bindings/structuredclone.rs @@ -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 {} diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs index 6540f6c971f..2940a211bf3 100644 --- a/components/script/dom/bluetooth.rs +++ b/components/script/dom/bluetooth.rs @@ -4,8 +4,7 @@ use bluetooth_blacklist::{Blacklist, uuid_is_blacklisted}; use core::clone::Clone; -use dom::bindings::codegen::Bindings::BluetoothBinding; -use dom::bindings::codegen::Bindings::BluetoothBinding::{BluetoothMethods, BluetoothScanFilter}; +use dom::bindings::codegen::Bindings::BluetoothBinding::{self, BluetoothMethods, BluetoothRequestDeviceFilter}; use dom::bindings::codegen::Bindings::BluetoothBinding::RequestDeviceOptions; use dom::bindings::error::Error::{self, Security, Type}; use dom::bindings::error::Fallible; @@ -15,13 +14,13 @@ use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::str::DOMString; use dom::bluetoothadvertisingdata::BluetoothAdvertisingData; use dom::bluetoothdevice::BluetoothDevice; -use dom::bluetoothuuid::BluetoothUUID; +use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID}; use ipc_channel::ipc::{self, IpcSender}; use net_traits::bluetooth_scanfilter::{BluetoothScanfilter, BluetoothScanfilterSequence}; use net_traits::bluetooth_scanfilter::{RequestDeviceoptions, ServiceUUIDSequence}; use net_traits::bluetooth_thread::{BluetoothError, BluetoothMethodMsg}; -const FILTER_EMPTY_ERROR: &'static str = "'filters' member must be non - empty to find any devices."; +const FILTER_EMPTY_ERROR: &'static str = "'filters' member, if present, must be nonempty to find any devices."; const FILTER_ERROR: &'static str = "A filter must restrict the devices in some way."; const FILTER_NAME_TOO_LONG_ERROR: &'static str = "A 'name' or 'namePrefix' can't be longer then 29 bytes."; // 248 is the maximum number of UTF-8 code units in a Bluetooth Device Name. @@ -31,9 +30,11 @@ const MAX_DEVICE_NAME_LENGTH: usize = 248; // The length and identifier of the length field take 2 bytes. // That leaves 29 bytes for the name. const MAX_FILTER_NAME_LENGTH: usize = 29; -const NAME_PREFIX_ERROR: &'static str = "'namePrefix', if present, must be non - empty."; +const NAME_PREFIX_ERROR: &'static str = "'namePrefix', if present, must be nonempty."; const NAME_TOO_LONG_ERROR: &'static str = "A device name can't be longer than 248 bytes."; const SERVICE_ERROR: &'static str = "'services', if present, must contain at least one service."; +const OPTIONS_ERROR: &'static str = "Fields of 'options' conflict with each other. + Either 'acceptAllDevices' member must be true, or 'filters' member must be set to a value."; // https://webbluetoothcg.github.io/web-bluetooth/#bluetooth #[dom_struct] @@ -59,80 +60,196 @@ impl Bluetooth { let global_ref = global_root.r(); global_ref.as_window().bluetooth_thread() } -} -fn canonicalize_filter(filter: &BluetoothScanFilter, global: GlobalRef) -> Fallible<BluetoothScanfilter> { - if filter.services.is_none() && filter.name.is_none() && filter.namePrefix.is_none() { - return Err(Type(FILTER_ERROR.to_owned())); - } + // https://webbluetoothcg.github.io/web-bluetooth/#request-bluetooth-devices + fn request_bluetooth_devices(&self, + filters: &Option<Vec<BluetoothRequestDeviceFilter>>, + optional_services: &Option<Vec<BluetoothServiceUUID>>) + -> Fallible<Root<BluetoothDevice>> { + // TODO: Step 1: Triggered by user activation. - let mut services_vec = vec!(); - if let Some(ref services) = filter.services { - if services.is_empty() { - return Err(Type(SERVICE_ERROR.to_owned())); - } - for service in services { - let uuid = try!(BluetoothUUID::GetService(global, service.clone())).to_string(); - if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) { - return Err(Security) - } - services_vec.push(uuid); - } - } + // Step 2. + let option = try!(convert_request_device_options(self.global().r(), filters, optional_services)); - let mut name = String::new(); - if let Some(ref filter_name) = filter.name { - //NOTE: DOMString::len() gives back the size in bytes - if filter_name.len() > MAX_DEVICE_NAME_LENGTH { - return Err(Type(NAME_TOO_LONG_ERROR.to_owned())); - } - if filter_name.len() > MAX_FILTER_NAME_LENGTH { - return Err(Type(FILTER_NAME_TOO_LONG_ERROR.to_owned())); - } - name = filter_name.to_string(); - } + // TODO: Step 3-5: Implement the permission API. - let mut name_prefix = String::new(); - if let Some(ref filter_name_prefix) = filter.namePrefix { - if filter_name_prefix.is_empty() { - return Err(Type(NAME_PREFIX_ERROR.to_owned())); - } - if filter_name_prefix.len() > MAX_DEVICE_NAME_LENGTH { - return Err(Type(NAME_TOO_LONG_ERROR.to_owned())); - } - if filter_name_prefix.len() > MAX_FILTER_NAME_LENGTH { - return Err(Type(FILTER_NAME_TOO_LONG_ERROR.to_owned())); + // Note: Steps 6-8 are implemented in + // components/net/bluetooth_thread.rs in request_device function. + let (sender, receiver) = ipc::channel().unwrap(); + self.get_bluetooth_thread().send(BluetoothMethodMsg::RequestDevice(option, sender)).unwrap(); + let device = receiver.recv().unwrap(); + + // TODO: Step 9-10: Implement the permission API. + + // Step 11: This step is optional. + + // Step 12-13. + match device { + Ok(device) => { + let ad_data = BluetoothAdvertisingData::new(self.global().r(), + device.appearance, + device.tx_power, + device.rssi); + Ok(BluetoothDevice::new(self.global().r(), + DOMString::from(device.id), + device.name.map(DOMString::from), + &ad_data)) + }, + Err(error) => { + Err(Error::from(error)) + }, } - name_prefix = filter_name_prefix.to_string(); - } - Ok(BluetoothScanfilter::new(name, name_prefix, services_vec)) + } } -fn convert_request_device_options(options: &RequestDeviceOptions, - global: GlobalRef) +// https://webbluetoothcg.github.io/web-bluetooth/#request-bluetooth-devices +fn convert_request_device_options(global: GlobalRef, + filters: &Option<Vec<BluetoothRequestDeviceFilter>>, + optional_services: &Option<Vec<BluetoothServiceUUID>>) -> Fallible<RequestDeviceoptions> { - if options.filters.is_empty() { - return Err(Type(FILTER_EMPTY_ERROR.to_owned())); - } + // Step 2.2: There is no requiredServiceUUIDS, we scan for all devices. + let mut uuid_filters = vec!(); + + if let &Some(ref filters) = filters { + // Step 2.1. + if filters.is_empty() { + return Err(Type(FILTER_EMPTY_ERROR.to_owned())); + } + + // Step 2.3: There is no requiredServiceUUIDS, we scan for all devices. - let mut filters = vec!(); - for filter in &options.filters { - filters.push(try!(canonicalize_filter(&filter, global))); + // Step 2.4. + for filter in filters { + // Step 2.4.8. + uuid_filters.push(try!(canonicalize_filter(&filter, global))); + } } - let mut optional_services = vec!(); - if let Some(ref opt_services) = options.optionalServices { + let mut optional_services_uuids = vec!(); + if let &Some(ref opt_services) = optional_services { for opt_service in opt_services { + // Step 2.5 - 2.6. let uuid = try!(BluetoothUUID::GetService(global, opt_service.clone())).to_string(); + + // Step 2.7. + // Note: What we are doing here is adding the not blacklisted UUIDs to the result vector, + // insted of removing them from an already filled vector. if !uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) { - optional_services.push(uuid); + optional_services_uuids.push(uuid); } } } - Ok(RequestDeviceoptions::new(BluetoothScanfilterSequence::new(filters), - ServiceUUIDSequence::new(optional_services))) + Ok(RequestDeviceoptions::new(BluetoothScanfilterSequence::new(uuid_filters), + ServiceUUIDSequence::new(optional_services_uuids))) +} + +// https://webbluetoothcg.github.io/web-bluetooth/#request-bluetooth-devices +fn canonicalize_filter(filter: &BluetoothRequestDeviceFilter, global: GlobalRef) -> Fallible<BluetoothScanfilter> { + // Step 2.4.1. + if filter.services.is_none() && + filter.name.is_none() && + filter.namePrefix.is_none() && + filter.manufacturerId.is_none() && + filter.serviceDataUUID.is_none() { + return Err(Type(FILTER_ERROR.to_owned())); + } + + // Step 2.4.2: There is no empty canonicalizedFilter member, + // we create a BluetoothScanfilter instance at the end of the function. + + // Step 2.4.3. + let services_vec = match filter.services { + Some(ref services) => { + // Step 2.4.3.1. + if services.is_empty() { + return Err(Type(SERVICE_ERROR.to_owned())); + } + + let mut services_vec = vec!(); + + for service in services { + // Step 2.4.3.2 - 2.4.3.3. + let uuid = try!(BluetoothUUID::GetService(global, service.clone())).to_string(); + + // Step 2.4.3.4. + if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) { + return Err(Security) + } + + services_vec.push(uuid); + } + // Step 2.4.3.5. + services_vec + // Step 2.4.3.6: There is no requiredServiceUUIDS, we scan for all devices. + }, + None => vec!(), + }; + + // Step 2.4.4. + let name = match filter.name { + Some(ref name) => { + // Step 2.4.4.1. + // Note: DOMString::len() gives back the size in bytes. + if name.len() > MAX_DEVICE_NAME_LENGTH { + return Err(Type(NAME_TOO_LONG_ERROR.to_owned())); + } + if name.len() > MAX_FILTER_NAME_LENGTH { + return Err(Type(FILTER_NAME_TOO_LONG_ERROR.to_owned())); + } + + // Step 2.4.4.2. + name.to_string() + }, + None => String::new(), + }; + + // Step 2.4.5. + let name_prefix = match filter.namePrefix { + Some(ref name_prefix) => { + // Step 2.4.5.1. + if name_prefix.is_empty() { + return Err(Type(NAME_PREFIX_ERROR.to_owned())); + } + if name_prefix.len() > MAX_DEVICE_NAME_LENGTH { + return Err(Type(NAME_TOO_LONG_ERROR.to_owned())); + } + if name_prefix.len() > MAX_FILTER_NAME_LENGTH { + return Err(Type(FILTER_NAME_TOO_LONG_ERROR.to_owned())); + } + + // Step 2.4.5.2. + name_prefix.to_string() + }, + None => String::new(), + }; + + // Step 2.4.6. + let manufacturer_id = filter.manufacturerId; + + // Step 2.4.7. + let service_data_uuid = match filter.serviceDataUUID { + Some(ref service_data_uuid) => { + // Step 2.4.7.1 - 2.4.7.2. + let uuid = try!(BluetoothUUID::GetService(global, service_data_uuid.clone())).to_string(); + + // Step 2.4.7.3. + if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) { + return Err(Security) + } + + // Step 2.4.7.4. + uuid + }, + None => String::new(), + }; + + Ok(BluetoothScanfilter::new(name, + name_prefix, + services_vec, + manufacturer_id, + service_data_uuid)) } impl From<BluetoothError> for Error { @@ -150,24 +267,18 @@ impl From<BluetoothError> for Error { impl BluetoothMethods for Bluetooth { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice fn RequestDevice(&self, option: &RequestDeviceOptions) -> Fallible<Root<BluetoothDevice>> { - let (sender, receiver) = ipc::channel().unwrap(); - let option = try!(convert_request_device_options(option, self.global().r())); - self.get_bluetooth_thread().send(BluetoothMethodMsg::RequestDevice(option, sender)).unwrap(); - let device = receiver.recv().unwrap(); - match device { - Ok(device) => { - let ad_data = BluetoothAdvertisingData::new(self.global().r(), - device.appearance, - device.tx_power, - device.rssi); - Ok(BluetoothDevice::new(self.global().r(), - DOMString::from(device.id), - device.name.map(DOMString::from), - &ad_data)) - }, - Err(error) => { - Err(Error::from(error)) - }, + // Step 1. + // TODO(#4282): Reject promise. + if (option.filters.is_some() && option.acceptAllDevices) || + (option.filters.is_none() && !option.acceptAllDevices) { + return Err(Type(OPTIONS_ERROR.to_owned())); } + // Step 2. + if !option.acceptAllDevices { + return self.request_bluetooth_devices(&option.filters, &option.optionalServices); + } + + self.request_bluetooth_devices(&None, &option.optionalServices) + // TODO(#4282): Step 3-5: Reject and resolve promise. } } diff --git a/components/script/dom/serviceworker.rs b/components/script/dom/serviceworker.rs index 2b79be43dc8..9c37d73bd9e 100644 --- a/components/script/dom/serviceworker.rs +++ b/components/script/dom/serviceworker.rs @@ -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); diff --git a/components/script/dom/serviceworkercontainer.rs b/components/script/dom/serviceworkercontainer.rs index d6379c30183..73e19690e2e 100644 --- a/components/script/dom/serviceworkercontainer.rs +++ b/components/script/dom/serviceworkercontainer.rs @@ -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) diff --git a/components/script/dom/serviceworkerglobalscope.rs b/components/script/dom/serviceworkerglobalscope.rs index 16d5348b6e5..f473c6cadb2 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; @@ -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)] diff --git a/components/script/dom/serviceworkerregistration.rs b/components/script/dom/serviceworkerregistration.rs index ccf238dde8a..d246dc4423b 100644 --- a/components/script/dom/serviceworkerregistration.rs +++ b/components/script/dom/serviceworkerregistration.rs @@ -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) diff --git a/components/script/dom/webidls/Bluetooth.webidl b/components/script/dom/webidls/Bluetooth.webidl index 63cea97ca19..6c575db150c 100644 --- a/components/script/dom/webidls/Bluetooth.webidl +++ b/components/script/dom/webidls/Bluetooth.webidl @@ -4,24 +4,31 @@ // https://webbluetoothcg.github.io/web-bluetooth/#bluetooth -dictionary BluetoothScanFilter { +dictionary BluetoothRequestDeviceFilter { sequence<BluetoothServiceUUID> services; DOMString name; DOMString namePrefix; + unsigned short manufacturerId; + BluetoothServiceUUID serviceDataUUID; }; dictionary RequestDeviceOptions { - required sequence<BluetoothScanFilter> filters; + sequence<BluetoothRequestDeviceFilter> filters; sequence<BluetoothServiceUUID> optionalServices /*= []*/; + boolean acceptAllDevices = false; }; [Pref="dom.bluetooth.enabled", Exposed=(Window,Worker)] interface Bluetooth { - // Promise<BluetoothDevice> requestDevice(RequestDeviceOptions options); - [Throws] - BluetoothDevice requestDevice(RequestDeviceOptions options); +// [SecureContext] +// readonly attribute BluetoothDevice? referringDevice; +// [SecureContext] +// Promise<BluetoothDevice> requestDevice(RequestDeviceOptions options); + [Throws] + BluetoothDevice requestDevice(optional RequestDeviceOptions options); }; // Bluetooth implements EventTarget; +// Bluetooth implements BluetoothDeviceEventHandlers; // Bluetooth implements CharacteristicEventHandlers; // Bluetooth implements ServiceEventHandlers; diff --git a/components/script/dom/webidls/DOMTokenList.webidl b/components/script/dom/webidls/DOMTokenList.webidl index 7285ac687e1..11bdbda8570 100644 --- a/components/script/dom/webidls/DOMTokenList.webidl +++ b/components/script/dom/webidls/DOMTokenList.webidl @@ -25,4 +25,5 @@ interface DOMTokenList { attribute DOMString value; stringifier; + iterable<DOMString?>; }; 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/worker.rs b/components/script/dom/worker.rs index 9438569a5d1..1df110a12e5 100644 --- a/components/script/dom/worker.rs +++ b/components/script/dom/worker.rs @@ -140,6 +140,7 @@ impl Worker { worker.upcast().fire_simple_event("error"); } + #[allow(unsafe_code)] fn dispatch_error(&self, error_info: ErrorInfo) { let global = self.global(); let event = ErrorEvent::new(global.r(), @@ -150,14 +151,14 @@ impl Worker { error_info.filename.as_str().into(), error_info.lineno, error_info.column, - NullHandleValue); + unsafe { NullHandleValue }); let handled = !event.upcast::<Event>().fire(self.upcast::<EventTarget>()); if handled { return; } - global.r().report_an_error(error_info, NullHandleValue); + global.r().report_an_error(error_info, unsafe { NullHandleValue }); } } diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs index 95e9bb13106..bb9a9c3f4ab 100644 --- a/components/script/dom/workerglobalscope.rs +++ b/components/script/dom/workerglobalscope.rs @@ -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") } } |