diff options
author | Rahul Sharma <rsconceptx@gmail.com> | 2016-10-04 23:57:36 +0530 |
---|---|---|
committer | Rahul Sharma <rsconceptx@gmail.com> | 2016-11-22 01:29:37 +0530 |
commit | 114c49111138325f7cf1dacbe9d25fdd035ede86 (patch) | |
tree | b535e703eb5f5f26785082efda94cf7be871bafd /components/script/dom | |
parent | 6cc1976cca808cac2069b241885a9c102ee7424d (diff) | |
download | servo-114c49111138325f7cf1dacbe9d25fdd035ede86.tar.gz servo-114c49111138325f7cf1dacbe9d25fdd035ede86.zip |
Initial work on job queues for service workers
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/bindings/trace.rs | 1 | ||||
-rw-r--r-- | components/script/dom/client.rs | 26 | ||||
-rw-r--r-- | components/script/dom/promise.rs | 13 | ||||
-rw-r--r-- | components/script/dom/serviceworker.rs | 6 | ||||
-rw-r--r-- | components/script/dom/serviceworkercontainer.rs | 55 | ||||
-rw-r--r-- | components/script/dom/serviceworkerregistration.rs | 38 | ||||
-rw-r--r-- | components/script/dom/urlhelper.rs | 14 |
7 files changed, 99 insertions, 54 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 8ecb06fdb1e..8323c6996ae 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -195,7 +195,6 @@ impl JSTraceable for Heap<*mut JSObject> { } } - impl JSTraceable for Heap<JSVal> { fn trace(&self, trc: *mut JSTracer) { trace_jsval(trc, "heap value", self); diff --git a/components/script/dom/client.rs b/components/script/dom/client.rs index bc763d41ea9..496a13d32dc 100644 --- a/components/script/dom/client.rs +++ b/components/script/dom/client.rs @@ -4,20 +4,20 @@ use dom::bindings::codegen::Bindings::ClientBinding::{ClientMethods, Wrap}; use dom::bindings::codegen::Bindings::ClientBinding::FrameType; -use dom::bindings::js::JS; -use dom::bindings::js::Root; +use dom::bindings::js::{JS, Root, MutNullableHeap}; use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::bindings::str::{DOMString, USVString}; use dom::serviceworker::ServiceWorker; use dom::window::Window; use servo_url::ServoUrl; +use std::default::Default; use uuid::Uuid; #[dom_struct] pub struct Client { reflector_: Reflector, - active_worker: Option<JS<ServiceWorker>>, - url: USVString, + active_worker: MutNullableHeap<JS<ServiceWorker>>, + url: ServoUrl, frame_type: FrameType, #[ignore_heap_size_of = "Defined in uuid"] id: Uuid @@ -27,8 +27,8 @@ impl Client { fn new_inherited(url: ServoUrl) -> Client { Client { reflector_: Reflector::new(), - active_worker: None, - url: USVString(url.as_str().to_owned()), + active_worker: Default::default(), + url: url, frame_type: FrameType::None, id: Uuid::new_v4() } @@ -39,12 +39,24 @@ impl Client { window, Wrap) } + + pub fn creation_url(&self) -> ServoUrl { + self.url.clone() + } + + pub fn get_controller(&self) -> Option<Root<ServiceWorker>> { + self.active_worker.get() + } + + pub fn set_controller(&self, worker: &ServiceWorker) { + self.active_worker.set(Some(worker)); + } } impl ClientMethods for Client { // https://w3c.github.io/ServiceWorker/#client-url-attribute fn Url(&self) -> USVString { - self.url.clone() + USVString(self.url.as_str().to_owned()) } // https://w3c.github.io/ServiceWorker/#client-frametype diff --git a/components/script/dom/promise.rs b/components/script/dom/promise.rs index 81149f8e193..0afcfcba266 100644 --- a/components/script/dom/promise.rs +++ b/components/script/dom/promise.rs @@ -23,8 +23,8 @@ use js::conversions::ToJSValConvertible; use js::jsapi::{CallOriginalPromiseResolve, CallOriginalPromiseReject, CallOriginalPromiseThen}; use js::jsapi::{JSAutoCompartment, CallArgs, JS_GetFunctionObject, JS_NewFunction}; use js::jsapi::{JSContext, HandleValue, HandleObject, IsPromiseObject, GetFunctionNativeReserved}; -use js::jsapi::{JS_ClearPendingException, JSObject, AddRawValueRoot, RemoveRawValueRoot}; -use js::jsapi::{MutableHandleObject, NewPromiseObject, ResolvePromise, RejectPromise}; +use js::jsapi::{JS_ClearPendingException, JSObject, AddRawValueRoot, RemoveRawValueRoot, PromiseState}; +use js::jsapi::{MutableHandleObject, NewPromiseObject, ResolvePromise, RejectPromise, GetPromiseState}; use js::jsapi::{SetFunctionNativeReserved, NewFunctionWithReserved, AddPromiseReactions}; use js::jsval::{JSVal, UndefinedValue, ObjectValue, Int32Value}; use std::ptr; @@ -200,6 +200,15 @@ impl Promise { } #[allow(unsafe_code)] + pub fn is_settled(&self) -> bool { + let state = unsafe { GetPromiseState(self.promise_obj()) }; + match state { + PromiseState::Rejected | PromiseState::Fulfilled => true, + _ => false + } + } + + #[allow(unsafe_code)] fn promise_obj(&self) -> HandleObject { let obj = self.reflector().get_jsobject(); unsafe { diff --git a/components/script/dom/serviceworker.rs b/components/script/dom/serviceworker.rs index d61f1120906..63971d7e42e 100644 --- a/components/script/dom/serviceworker.rs +++ b/components/script/dom/serviceworker.rs @@ -46,9 +46,9 @@ impl ServiceWorker { } pub fn install_serviceworker(global: &GlobalScope, - script_url: ServoUrl, - scope_url: ServoUrl, - skip_waiting: bool) -> Root<ServiceWorker> { + script_url: ServoUrl, + scope_url: ServoUrl, + skip_waiting: bool) -> Root<ServiceWorker> { reflect_dom_object(box ServiceWorker::new_inherited(script_url.as_str(), skip_waiting, scope_url), global, Wrap) diff --git a/components/script/dom/serviceworkercontainer.rs b/components/script/dom/serviceworkercontainer.rs index 136ba01fcee..9d8d73b1c43 100644 --- a/components/script/dom/serviceworkercontainer.rs +++ b/components/script/dom/serviceworkercontainer.rs @@ -5,16 +5,16 @@ use dom::bindings::codegen::Bindings::ServiceWorkerContainerBinding::{ServiceWorkerContainerMethods, Wrap}; use dom::bindings::codegen::Bindings::ServiceWorkerContainerBinding::RegistrationOptions; use dom::bindings::error::Error; -use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, MutNullableHeap, Root}; use dom::bindings::reflector::{Reflectable, reflect_dom_object}; use dom::bindings::str::USVString; +use dom::client::Client; use dom::eventtarget::EventTarget; use dom::globalscope::GlobalScope; use dom::promise::Promise; use dom::serviceworker::ServiceWorker; -use dom::serviceworkerregistration::ServiceWorkerRegistration; use script_thread::ScriptThread; +use serviceworkerjob::{Job, JobType}; use std::ascii::AsciiExt; use std::default::Default; use std::rc::Rc; @@ -23,48 +23,44 @@ use std::rc::Rc; pub struct ServiceWorkerContainer { eventtarget: EventTarget, controller: MutNullableHeap<JS<ServiceWorker>>, + client: JS<Client> } impl ServiceWorkerContainer { - fn new_inherited() -> ServiceWorkerContainer { + fn new_inherited(client: &Client) -> ServiceWorkerContainer { ServiceWorkerContainer { eventtarget: EventTarget::new_inherited(), controller: Default::default(), + client: JS::from_ref(client), } } + #[allow(unrooted_must_root)] pub fn new(global: &GlobalScope) -> Root<ServiceWorkerContainer> { - reflect_dom_object(box ServiceWorkerContainer::new_inherited(), global, Wrap) - } -} - -pub trait Controllable { - fn set_controller(&self, active_worker: &ServiceWorker); -} - -impl Controllable for ServiceWorkerContainer { - fn set_controller(&self, active_worker: &ServiceWorker) { - self.controller.set(Some(active_worker)); - self.upcast::<EventTarget>().fire_event(atom!("controllerchange")); + let client = Client::new(&global.as_window()); + let container = ServiceWorkerContainer::new_inherited(&*client); + reflect_dom_object(box container, global, Wrap) } } impl ServiceWorkerContainerMethods for ServiceWorkerContainer { // https://w3c.github.io/ServiceWorker/#service-worker-container-controller-attribute fn GetController(&self) -> Option<Root<ServiceWorker>> { - return self.controller.get() + self.client.get_controller() } #[allow(unrooted_must_root)] - // https://w3c.github.io/ServiceWorker/#service-worker-container-register-method + // https://w3c.github.io/ServiceWorker/#service-worker-container-register-method and - A + // https://w3c.github.io/ServiceWorker/#start-register-algorithm - B fn Register(&self, script_url: USVString, options: &RegistrationOptions) -> Rc<Promise> { + // A: Step 1 let promise = Promise::new(&*self.global()); - let ctx = self.global().get_cx(); + let ctx = (&*self.global()).get_cx(); let USVString(ref script_url) = script_url; let api_base_url = self.global().api_base_url(); - // Step 3-4 + // A: Step 3-5 let script_url = match api_base_url.join(script_url) { Ok(url) => url, Err(_) => { @@ -72,7 +68,7 @@ impl ServiceWorkerContainerMethods for ServiceWorkerContainer { return promise; } }; - // Step 5 + // B: Step 2 match script_url.scheme() { "https" | "http" => {}, _ => { @@ -80,13 +76,13 @@ impl ServiceWorkerContainerMethods for ServiceWorkerContainer { return promise; } } - // Step 6 + // B: Step 3 if script_url.path().to_ascii_lowercase().contains("%2f") || script_url.path().to_ascii_lowercase().contains("%5c") { promise.reject_error(ctx, Error::Type("Script URL contains forbidden characters".to_owned())); return promise; } - // Step 8-9 + // B: Step 4-5 let scope = match options.scope { Some(ref scope) => { let &USVString(ref inner_scope) = scope; @@ -100,7 +96,7 @@ impl ServiceWorkerContainerMethods for ServiceWorkerContainer { }, None => script_url.join("./").unwrap() }; - // Step 11 + // B: Step 6 match scope.scheme() { "https" | "http" => {}, _ => { @@ -108,21 +104,16 @@ impl ServiceWorkerContainerMethods for ServiceWorkerContainer { return promise; } } - // Step 12 + // B: Step 7 if scope.path().to_ascii_lowercase().contains("%2f") || scope.path().to_ascii_lowercase().contains("%5c") { promise.reject_error(ctx, Error::Type("Scope URL contains forbidden characters".to_owned())); return promise; } - let global = self.global(); - let worker_registration = ServiceWorkerRegistration::new(&global, - script_url, - scope.clone(), - self); - ScriptThread::set_registration(scope, &*worker_registration, self.global().pipeline_id()); - - promise.resolve_native(ctx, &*worker_registration); + // B: Step 8 + let job = Job::create_job(JobType::Register, scope, script_url, promise.clone(), &*self.client); + ScriptThread::schedule_job(job, &*self.global()); promise } } diff --git a/components/script/dom/serviceworkerregistration.rs b/components/script/dom/serviceworkerregistration.rs index 58ca0933d69..869c8855676 100644 --- a/components/script/dom/serviceworkerregistration.rs +++ b/components/script/dom/serviceworkerregistration.rs @@ -10,10 +10,11 @@ use dom::bindings::str::USVString; use dom::eventtarget::EventTarget; use dom::globalscope::GlobalScope; use dom::serviceworker::ServiceWorker; -use dom::serviceworkercontainer::Controllable; use dom::workerglobalscope::prepare_workerscope_init; use script_traits::{WorkerScriptLoadOrigin, ScopeThings}; use servo_url::ServoUrl; +use std::cell::Cell; + #[dom_struct] pub struct ServiceWorkerRegistration { @@ -21,7 +22,8 @@ pub struct ServiceWorkerRegistration { active: Option<JS<ServiceWorker>>, installing: Option<JS<ServiceWorker>>, waiting: Option<JS<ServiceWorker>>, - scope: String + scope: ServoUrl, + uninstalling: Cell<bool> } impl ServiceWorkerRegistration { @@ -31,17 +33,16 @@ impl ServiceWorkerRegistration { active: Some(JS::from_ref(active_sw)), installing: None, waiting: None, - scope: scope.as_str().to_owned(), + scope: scope, + uninstalling: Cell::new(false) } } #[allow(unrooted_must_root)] pub fn new(global: &GlobalScope, - script_url: ServoUrl, - scope: ServoUrl, - container: &Controllable) -> Root<ServiceWorkerRegistration> { + script_url: &ServoUrl, + scope: ServoUrl) -> Root<ServiceWorkerRegistration> { 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) } @@ -49,6 +50,14 @@ impl ServiceWorkerRegistration { self.active.as_ref().unwrap() } + pub fn get_uninstalling(&self) -> bool { + self.uninstalling.get() + } + + pub fn set_uninstalling(&self, flag: bool) { + self.uninstalling.set(flag) + } + pub fn create_scope_things(global: &GlobalScope, script_url: ServoUrl) -> ScopeThings { let worker_load_origin = WorkerScriptLoadOrigin { referrer_url: None, @@ -58,7 +67,7 @@ impl ServiceWorkerRegistration { let worker_id = global.get_next_worker_id(); let devtools_chan = global.devtools_chan().cloned(); - let init = prepare_workerscope_init(global, None); + let init = prepare_workerscope_init(&global, None); ScopeThings { script_url: script_url, init: init, @@ -67,6 +76,17 @@ impl ServiceWorkerRegistration { worker_id: worker_id } } + + // https://w3c.github.io/ServiceWorker/#get-newest-worker-algorithm + pub fn get_newest_worker(&self) -> Option<Root<ServiceWorker>> { + if self.installing.as_ref().is_some() { + self.installing.as_ref().map(|sw| Root::from_ref(&**sw)) + } else if self.waiting.as_ref().is_some() { + self.waiting.as_ref().map(|sw| Root::from_ref(&**sw)) + } else { + self.active.as_ref().map(|sw| Root::from_ref(&**sw)) + } + } } pub fn longest_prefix_match(stored_scope: &ServoUrl, potential_match: &ServoUrl) -> bool { @@ -100,6 +120,6 @@ impl ServiceWorkerRegistrationMethods for ServiceWorkerRegistration { // https://w3c.github.io/ServiceWorker/#service-worker-registration-scope-attribute fn Scope(&self) -> USVString { - USVString(self.scope.clone()) + USVString(self.scope.as_str().to_owned()) } } diff --git a/components/script/dom/urlhelper.rs b/components/script/dom/urlhelper.rs index dd22e16f551..ec50b4edb71 100644 --- a/components/script/dom/urlhelper.rs +++ b/components/script/dom/urlhelper.rs @@ -92,4 +92,18 @@ impl UrlHelper { let _ = quirks::set_username(url, &value.0); } } + // https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy + pub fn is_origin_trustworthy(url: &ServoUrl) -> bool { + // Step 3 + if url.scheme() == "http" || url.scheme() == "wss" { + true + // Step 4 + } else if url.host().is_some() { + let host = url.host_str().unwrap(); + host == "127.0.0.0/8" || host == "::1/128" + // Step 5 + } else { + url.scheme() == "file" + } + } } |