mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
serviceworker: make job queue unique per origin
This commit is contained in:
parent
7e74f73301
commit
89eb7c2aa2
19 changed files with 839 additions and 592 deletions
|
@ -86,6 +86,7 @@ use msg::constellation_msg::{
|
|||
BlobId, BroadcastChannelRouterId, BrowsingContextId, HistoryStateId, MessagePortId,
|
||||
MessagePortRouterId, PipelineId, TopLevelBrowsingContextId,
|
||||
};
|
||||
use msg::constellation_msg::{ServiceWorkerId, ServiceWorkerRegistrationId};
|
||||
use net_traits::filemanager_thread::RelativePos;
|
||||
use net_traits::image::base::{Image, ImageMetadata};
|
||||
use net_traits::image_cache::{ImageCache, PendingImageId};
|
||||
|
@ -179,6 +180,9 @@ unsafe_no_jsmanaged_fields!(MessagePortImpl);
|
|||
unsafe_no_jsmanaged_fields!(MessagePortId);
|
||||
unsafe_no_jsmanaged_fields!(MessagePortRouterId);
|
||||
|
||||
unsafe_no_jsmanaged_fields!(ServiceWorkerId);
|
||||
unsafe_no_jsmanaged_fields!(ServiceWorkerRegistrationId);
|
||||
|
||||
unsafe_no_jsmanaged_fields!(BroadcastChannelRouterId);
|
||||
|
||||
unsafe_no_jsmanaged_fields!(BlobId);
|
||||
|
|
|
@ -47,6 +47,7 @@ impl Client {
|
|||
self.active_worker.get()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn set_controller(&self, worker: &ServiceWorker) {
|
||||
self.active_worker.set(Some(worker));
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ use crate::dom::paintworkletglobalscope::PaintWorkletGlobalScope;
|
|||
use crate::dom::performance::Performance;
|
||||
use crate::dom::performanceobserver::VALID_ENTRY_TYPES;
|
||||
use crate::dom::promise::Promise;
|
||||
use crate::dom::serviceworker::ServiceWorker;
|
||||
use crate::dom::serviceworkerregistration::ServiceWorkerRegistration;
|
||||
use crate::dom::window::Window;
|
||||
use crate::dom::workerglobalscope::WorkerGlobalScope;
|
||||
use crate::dom::workletglobalscope::WorkletGlobalScope;
|
||||
|
@ -81,6 +83,7 @@ use js::rust::{HandleValue, MutableHandleValue};
|
|||
use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
|
||||
use msg::constellation_msg::{
|
||||
BlobId, BroadcastChannelRouterId, MessagePortId, MessagePortRouterId, PipelineId,
|
||||
ServiceWorkerId, ServiceWorkerRegistrationId,
|
||||
};
|
||||
use net_traits::blob_url_store::{get_blob_origin, BlobBuf};
|
||||
use net_traits::filemanager_thread::{
|
||||
|
@ -135,6 +138,13 @@ pub struct GlobalScope {
|
|||
/// The blobs managed by this global, if any.
|
||||
blob_state: DomRefCell<BlobState>,
|
||||
|
||||
/// <https://w3c.github.io/ServiceWorker/#environment-settings-object-service-worker-registration-object-map>
|
||||
registration_map:
|
||||
DomRefCell<HashMap<ServiceWorkerRegistrationId, Dom<ServiceWorkerRegistration>>>,
|
||||
|
||||
/// <https://w3c.github.io/ServiceWorker/#environment-settings-object-service-worker-object-map>
|
||||
worker_map: DomRefCell<HashMap<ServiceWorkerId, Dom<ServiceWorker>>>,
|
||||
|
||||
/// Pipeline id associated with this global.
|
||||
pipeline_id: PipelineId,
|
||||
|
||||
|
@ -567,6 +577,8 @@ impl GlobalScope {
|
|||
blob_state: DomRefCell::new(BlobState::UnManaged),
|
||||
eventtarget: EventTarget::new_inherited(),
|
||||
crypto: Default::default(),
|
||||
registration_map: DomRefCell::new(HashMap::new()),
|
||||
worker_map: DomRefCell::new(HashMap::new()),
|
||||
pipeline_id,
|
||||
devtools_wants_updates: Default::default(),
|
||||
console_timers: DomRefCell::new(Default::default()),
|
||||
|
@ -645,6 +657,72 @@ impl GlobalScope {
|
|||
);
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/ServiceWorker/#get-the-service-worker-registration-object>
|
||||
pub fn get_serviceworker_registration(
|
||||
&self,
|
||||
script_url: &ServoUrl,
|
||||
scope: &ServoUrl,
|
||||
registration_id: ServiceWorkerRegistrationId,
|
||||
installing_worker: Option<ServiceWorkerId>,
|
||||
_waiting_worker: Option<ServiceWorkerId>,
|
||||
_active_worker: Option<ServiceWorkerId>,
|
||||
) -> DomRoot<ServiceWorkerRegistration> {
|
||||
// Step 1
|
||||
let mut registrations = self.registration_map.borrow_mut();
|
||||
|
||||
if let Some(registration) = registrations.get(®istration_id) {
|
||||
// Step 3
|
||||
return DomRoot::from_ref(&**registration);
|
||||
}
|
||||
|
||||
// Step 2.1 -> 2.5
|
||||
let new_registration =
|
||||
ServiceWorkerRegistration::new(self, scope.clone(), registration_id.clone());
|
||||
|
||||
// Step 2.6
|
||||
if let Some(worker_id) = installing_worker {
|
||||
let worker = self.get_serviceworker(script_url, scope, worker_id);
|
||||
new_registration.set_installing(&*worker);
|
||||
}
|
||||
|
||||
// TODO: 2.7 (waiting worker)
|
||||
|
||||
// TODO: 2.8 (active worker)
|
||||
|
||||
// Step 2.9
|
||||
registrations.insert(registration_id, Dom::from_ref(&*new_registration));
|
||||
|
||||
// Step 3
|
||||
new_registration
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/ServiceWorker/#get-the-service-worker-object>
|
||||
pub fn get_serviceworker(
|
||||
&self,
|
||||
script_url: &ServoUrl,
|
||||
scope: &ServoUrl,
|
||||
worker_id: ServiceWorkerId,
|
||||
) -> DomRoot<ServiceWorker> {
|
||||
// Step 1
|
||||
let mut workers = self.worker_map.borrow_mut();
|
||||
|
||||
if let Some(worker) = workers.get(&worker_id) {
|
||||
// Step 3
|
||||
DomRoot::from_ref(&**worker)
|
||||
} else {
|
||||
// Step 2.1
|
||||
// TODO: step 2.2, worker state.
|
||||
let new_worker =
|
||||
ServiceWorker::new(self, script_url.clone(), scope.clone(), worker_id.clone());
|
||||
|
||||
// Step 2.3
|
||||
workers.insert(worker_id, Dom::from_ref(&*new_worker));
|
||||
|
||||
// Step 3
|
||||
new_worker
|
||||
}
|
||||
}
|
||||
|
||||
/// Complete the transfer of a message-port.
|
||||
fn complete_port_transfer(&self, port_id: MessagePortId, tasks: VecDeque<PortMessageTask>) {
|
||||
let should_start = if let MessagePortState::Managed(_id, message_ports) =
|
||||
|
|
|
@ -46,7 +46,7 @@ impl NavigationPreloadManagerMethods for NavigationPreloadManager {
|
|||
let promise = Promise::new_in_current_realm(&*self.global(), comp);
|
||||
|
||||
// 2.
|
||||
if self.serviceworker_registration.active().is_none() {
|
||||
if self.serviceworker_registration.is_active() {
|
||||
promise.reject_native(&DOMException::new(
|
||||
&self.global(),
|
||||
DOMErrorName::InvalidStateError,
|
||||
|
@ -68,7 +68,7 @@ impl NavigationPreloadManagerMethods for NavigationPreloadManager {
|
|||
let promise = Promise::new_in_current_realm(&*self.global(), comp);
|
||||
|
||||
// 2.
|
||||
if self.serviceworker_registration.active().is_none() {
|
||||
if self.serviceworker_registration.is_active() {
|
||||
promise.reject_native(&DOMException::new(
|
||||
&self.global(),
|
||||
DOMErrorName::InvalidStateError,
|
||||
|
@ -90,7 +90,7 @@ impl NavigationPreloadManagerMethods for NavigationPreloadManager {
|
|||
let promise = Promise::new_in_current_realm(&*self.global(), comp);
|
||||
|
||||
// 2.
|
||||
if self.serviceworker_registration.active().is_none() {
|
||||
if self.serviceworker_registration.is_active() {
|
||||
promise.reject_native(&DOMException::new(
|
||||
&self.global(),
|
||||
DOMErrorName::InvalidStateError,
|
||||
|
@ -114,7 +114,7 @@ impl NavigationPreloadManagerMethods for NavigationPreloadManager {
|
|||
let mut state = NavigationPreloadState::empty();
|
||||
|
||||
// 3.
|
||||
if let Some(_) = self.serviceworker_registration.active() {
|
||||
if self.serviceworker_registration.is_active() {
|
||||
if self
|
||||
.serviceworker_registration
|
||||
.get_navigation_preload_enabled()
|
||||
|
|
|
@ -23,6 +23,7 @@ use crate::task::TaskOnce;
|
|||
use dom_struct::dom_struct;
|
||||
use js::jsapi::{Heap, JSObject};
|
||||
use js::rust::{CustomAutoRooter, CustomAutoRooterGuard, HandleValue};
|
||||
use msg::constellation_msg::ServiceWorkerId;
|
||||
use script_traits::{DOMMessage, ScriptMsg};
|
||||
use servo_url::ServoUrl;
|
||||
use std::cell::Cell;
|
||||
|
@ -35,31 +36,35 @@ pub struct ServiceWorker {
|
|||
script_url: DomRefCell<String>,
|
||||
scope_url: ServoUrl,
|
||||
state: Cell<ServiceWorkerState>,
|
||||
skip_waiting: Cell<bool>,
|
||||
worker_id: ServiceWorkerId,
|
||||
}
|
||||
|
||||
impl ServiceWorker {
|
||||
fn new_inherited(script_url: &str, skip_waiting: bool, scope_url: ServoUrl) -> ServiceWorker {
|
||||
fn new_inherited(
|
||||
script_url: &str,
|
||||
scope_url: ServoUrl,
|
||||
worker_id: ServiceWorkerId,
|
||||
) -> ServiceWorker {
|
||||
ServiceWorker {
|
||||
eventtarget: EventTarget::new_inherited(),
|
||||
script_url: DomRefCell::new(String::from(script_url)),
|
||||
state: Cell::new(ServiceWorkerState::Installing),
|
||||
scope_url: scope_url,
|
||||
skip_waiting: Cell::new(skip_waiting),
|
||||
worker_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn install_serviceworker(
|
||||
pub fn new(
|
||||
global: &GlobalScope,
|
||||
script_url: ServoUrl,
|
||||
scope_url: ServoUrl,
|
||||
skip_waiting: bool,
|
||||
worker_id: ServiceWorkerId,
|
||||
) -> DomRoot<ServiceWorker> {
|
||||
reflect_dom_object(
|
||||
Box::new(ServiceWorker::new_inherited(
|
||||
script_url.as_str(),
|
||||
skip_waiting,
|
||||
scope_url,
|
||||
worker_id,
|
||||
)),
|
||||
global,
|
||||
)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
use crate::dom::bindings::codegen::Bindings::ServiceWorkerContainerBinding::RegistrationOptions;
|
||||
use crate::dom::bindings::codegen::Bindings::ServiceWorkerContainerBinding::ServiceWorkerContainerMethods;
|
||||
use crate::dom::bindings::error::Error;
|
||||
use crate::dom::bindings::refcounted::TrustedPromise;
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
||||
use crate::dom::bindings::str::USVString;
|
||||
|
@ -13,10 +14,17 @@ use crate::dom::eventtarget::EventTarget;
|
|||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::promise::Promise;
|
||||
use crate::dom::serviceworker::ServiceWorker;
|
||||
use crate::dom::serviceworkerregistration::ServiceWorkerRegistration;
|
||||
use crate::realms::enter_realm;
|
||||
use crate::realms::InRealm;
|
||||
use crate::script_thread::ScriptThread;
|
||||
use crate::serviceworkerjob::{Job, JobType};
|
||||
use crate::task::TaskCanceller;
|
||||
use crate::task_source::dom_manipulation::DOMManipulationTaskSource;
|
||||
use crate::task_source::TaskSource;
|
||||
use crate::task_source::TaskSourceName;
|
||||
use dom_struct::dom_struct;
|
||||
use ipc_channel::ipc;
|
||||
use ipc_channel::router::ROUTER;
|
||||
use script_traits::{Job, JobError, JobResult, JobResultValue, JobType, ScriptMsg};
|
||||
use std::default::Default;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
@ -50,45 +58,33 @@ impl ServiceWorkerContainerMethods for ServiceWorkerContainer {
|
|||
self.client.get_controller()
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root)] // Job is unrooted
|
||||
/// https://w3c.github.io/ServiceWorker/#navigator-service-worker-register and - A
|
||||
/// https://w3c.github.io/ServiceWorker/#start-register-algorithm - B
|
||||
/// https://w3c.github.io/ServiceWorker/#dom-serviceworkercontainer-register - A
|
||||
/// and https://w3c.github.io/ServiceWorker/#start-register - B
|
||||
fn Register(
|
||||
&self,
|
||||
script_url: USVString,
|
||||
options: &RegistrationOptions,
|
||||
comp: InRealm,
|
||||
) -> Rc<Promise> {
|
||||
// A: Step 2.
|
||||
let global = self.client.global();
|
||||
|
||||
// A: Step 1
|
||||
let promise = Promise::new_in_current_realm(&*self.global(), comp);
|
||||
let promise = Promise::new_in_current_realm(&*global, comp);
|
||||
let USVString(ref script_url) = script_url;
|
||||
let api_base_url = self.global().api_base_url();
|
||||
// A: Step 3-5
|
||||
|
||||
// A: Step 3
|
||||
let api_base_url = global.api_base_url();
|
||||
let script_url = match api_base_url.join(script_url) {
|
||||
Ok(url) => url,
|
||||
Err(_) => {
|
||||
// B: Step 1
|
||||
promise.reject_error(Error::Type("Invalid script URL".to_owned()));
|
||||
return promise;
|
||||
},
|
||||
};
|
||||
// B: Step 2
|
||||
match script_url.scheme() {
|
||||
"https" | "http" => {},
|
||||
_ => {
|
||||
promise.reject_error(Error::Type("Only secure origins are allowed".to_owned()));
|
||||
return promise;
|
||||
},
|
||||
}
|
||||
// B: Step 3
|
||||
if script_url.path().to_ascii_lowercase().contains("%2f") ||
|
||||
script_url.path().to_ascii_lowercase().contains("%5c")
|
||||
{
|
||||
promise.reject_error(Error::Type(
|
||||
"Script URL contains forbidden characters".to_owned(),
|
||||
));
|
||||
return promise;
|
||||
}
|
||||
// B: Step 4-5
|
||||
|
||||
// A: Step 4-5
|
||||
let scope = match options.scope {
|
||||
Some(ref scope) => {
|
||||
let &USVString(ref inner_scope) = scope;
|
||||
|
@ -102,6 +98,27 @@ impl ServiceWorkerContainerMethods for ServiceWorkerContainer {
|
|||
},
|
||||
None => script_url.join("./").unwrap(),
|
||||
};
|
||||
|
||||
// A: Step 6 -> invoke B.
|
||||
|
||||
// B: Step 3
|
||||
match script_url.scheme() {
|
||||
"https" | "http" => {},
|
||||
_ => {
|
||||
promise.reject_error(Error::Type("Only secure origins are allowed".to_owned()));
|
||||
return promise;
|
||||
},
|
||||
}
|
||||
// B: Step 4
|
||||
if script_url.path().to_ascii_lowercase().contains("%2f") ||
|
||||
script_url.path().to_ascii_lowercase().contains("%5c")
|
||||
{
|
||||
promise.reject_error(Error::Type(
|
||||
"Script URL contains forbidden characters".to_owned(),
|
||||
));
|
||||
return promise;
|
||||
}
|
||||
|
||||
// B: Step 6
|
||||
match scope.scheme() {
|
||||
"https" | "http" => {},
|
||||
|
@ -120,17 +137,134 @@ impl ServiceWorkerContainerMethods for ServiceWorkerContainer {
|
|||
return promise;
|
||||
}
|
||||
|
||||
// B: Step 8
|
||||
// Setup the callback for reject/resolve of the promise,
|
||||
// from steps running "in-parallel" from here in the serviceworker manager.
|
||||
let (task_source, task_canceller) = (
|
||||
global.dom_manipulation_task_source(),
|
||||
global.task_canceller(TaskSourceName::DOMManipulation),
|
||||
);
|
||||
|
||||
let mut handler = RegisterJobResultHandler {
|
||||
trusted_promise: Some(TrustedPromise::new(promise.clone())),
|
||||
task_source,
|
||||
task_canceller,
|
||||
};
|
||||
|
||||
let (job_result_sender, job_result_receiver) = ipc::channel().expect("ipc channel failure");
|
||||
|
||||
ROUTER.add_route(
|
||||
job_result_receiver.to_opaque(),
|
||||
Box::new(move |message| {
|
||||
let msg = message.to();
|
||||
match msg {
|
||||
Ok(msg) => handler.handle(msg),
|
||||
Err(err) => warn!("Error receiving a JobResult: {:?}", err),
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
let scope_things =
|
||||
ServiceWorkerRegistration::create_scope_things(&*global, script_url.clone());
|
||||
|
||||
// B: Step 8 - 13
|
||||
let job = Job::create_job(
|
||||
JobType::Register,
|
||||
scope,
|
||||
script_url,
|
||||
promise.clone(),
|
||||
options.type_,
|
||||
&*self.client,
|
||||
job_result_sender,
|
||||
self.client.creation_url(),
|
||||
Some(scope_things),
|
||||
);
|
||||
// Job is unrooted here, do not do anything other than immediately scheduling
|
||||
ScriptThread::schedule_job(job);
|
||||
|
||||
// B: Step 14: schedule job.
|
||||
let _ = global
|
||||
.script_to_constellation_chan()
|
||||
.send(ScriptMsg::ScheduleJob(job));
|
||||
|
||||
// A: Step 7
|
||||
promise
|
||||
}
|
||||
}
|
||||
|
||||
/// Callback for resolve/reject job promise for Register.
|
||||
/// <https://w3c.github.io/ServiceWorker/#register>
|
||||
struct RegisterJobResultHandler {
|
||||
trusted_promise: Option<TrustedPromise>,
|
||||
task_source: DOMManipulationTaskSource,
|
||||
task_canceller: TaskCanceller,
|
||||
}
|
||||
|
||||
impl RegisterJobResultHandler {
|
||||
/// <https://w3c.github.io/ServiceWorker/#reject-job-promise>
|
||||
/// <https://w3c.github.io/ServiceWorker/#resolve-job-promise>
|
||||
/// Handle a result to either resolve or reject the register job promise.
|
||||
pub fn handle(&mut self, result: JobResult) {
|
||||
match result {
|
||||
JobResult::RejectPromise(error) => {
|
||||
let promise = self
|
||||
.trusted_promise
|
||||
.take()
|
||||
.expect("No promise to resolve for SW Register job.");
|
||||
|
||||
// Step 1
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
task!(reject_promise_with_security_error: move || {
|
||||
let promise = promise.root();
|
||||
let _ac = enter_realm(&*promise.global());
|
||||
match error {
|
||||
JobError::TypeError => {
|
||||
promise.reject_error(Error::Type("Failed to register a ServiceWorker".to_string()));
|
||||
},
|
||||
JobError::SecurityError => {
|
||||
promise.reject_error(Error::Security);
|
||||
},
|
||||
}
|
||||
|
||||
}),
|
||||
&self.task_canceller,
|
||||
);
|
||||
|
||||
// TODO: step 2, handle equivalent jobs.
|
||||
},
|
||||
JobResult::ResolvePromise(job, value) => {
|
||||
let promise = self
|
||||
.trusted_promise
|
||||
.take()
|
||||
.expect("No promise to resolve for SW Register job.");
|
||||
|
||||
// Step 1
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
task!(resolve_promise: move || {
|
||||
let promise = promise.root();
|
||||
let global = promise.global();
|
||||
let _ac = enter_realm(&*global);
|
||||
|
||||
// Step 1.1
|
||||
let JobResultValue::Registration {
|
||||
id,
|
||||
installing_worker,
|
||||
waiting_worker,
|
||||
active_worker,
|
||||
} = value;
|
||||
|
||||
// Step 1.2 (Job type is "register").
|
||||
let registration = global.get_serviceworker_registration(
|
||||
&job.script_url,
|
||||
&job.scope_url,
|
||||
id,
|
||||
installing_worker,
|
||||
waiting_worker,
|
||||
active_worker,
|
||||
);
|
||||
|
||||
// Step 1.4
|
||||
promise.resolve_native(&*registration);
|
||||
}),
|
||||
&self.task_canceller,
|
||||
);
|
||||
|
||||
// TODO: step 2, handle equivalent jobs.
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::ServiceWorkerBinding::ServiceWorkerState;
|
||||
use crate::dom::bindings::codegen::Bindings::ServiceWorkerRegistrationBinding::ServiceWorkerRegistrationMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::ServiceWorkerRegistrationBinding::ServiceWorkerUpdateViaCache;
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||
|
@ -16,6 +15,7 @@ use crate::dom::serviceworker::ServiceWorker;
|
|||
use crate::dom::workerglobalscope::prepare_workerscope_init;
|
||||
use devtools_traits::WorkerId;
|
||||
use dom_struct::dom_struct;
|
||||
use msg::constellation_msg::ServiceWorkerRegistrationId;
|
||||
use script_traits::{ScopeThings, WorkerScriptLoadOrigin};
|
||||
use servo_url::ServoUrl;
|
||||
use std::cell::Cell;
|
||||
|
@ -24,58 +24,60 @@ use uuid::Uuid;
|
|||
#[dom_struct]
|
||||
pub struct ServiceWorkerRegistration {
|
||||
eventtarget: EventTarget,
|
||||
active: Option<Dom<ServiceWorker>>,
|
||||
installing: Option<Dom<ServiceWorker>>,
|
||||
waiting: Option<Dom<ServiceWorker>>,
|
||||
active: DomRefCell<Option<Dom<ServiceWorker>>>,
|
||||
installing: DomRefCell<Option<Dom<ServiceWorker>>>,
|
||||
waiting: DomRefCell<Option<Dom<ServiceWorker>>>,
|
||||
navigation_preload: MutNullableDom<NavigationPreloadManager>,
|
||||
scope: ServoUrl,
|
||||
navigation_preload_enabled: Cell<bool>,
|
||||
navigation_preload_header_value: DomRefCell<Option<ByteString>>,
|
||||
update_via_cache: ServiceWorkerUpdateViaCache,
|
||||
uninstalling: Cell<bool>,
|
||||
registration_id: ServiceWorkerRegistrationId,
|
||||
}
|
||||
|
||||
impl ServiceWorkerRegistration {
|
||||
fn new_inherited(active_sw: &ServiceWorker, scope: ServoUrl) -> ServiceWorkerRegistration {
|
||||
fn new_inherited(
|
||||
scope: ServoUrl,
|
||||
registration_id: ServiceWorkerRegistrationId,
|
||||
) -> ServiceWorkerRegistration {
|
||||
ServiceWorkerRegistration {
|
||||
eventtarget: EventTarget::new_inherited(),
|
||||
active: Some(Dom::from_ref(active_sw)),
|
||||
installing: None,
|
||||
waiting: None,
|
||||
active: DomRefCell::new(None),
|
||||
installing: DomRefCell::new(None),
|
||||
waiting: DomRefCell::new(None),
|
||||
navigation_preload: MutNullableDom::new(None),
|
||||
scope: scope,
|
||||
navigation_preload_enabled: Cell::new(false),
|
||||
navigation_preload_header_value: DomRefCell::new(None),
|
||||
update_via_cache: ServiceWorkerUpdateViaCache::Imports,
|
||||
uninstalling: Cell::new(false),
|
||||
registration_id,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn new(
|
||||
global: &GlobalScope,
|
||||
script_url: &ServoUrl,
|
||||
scope: ServoUrl,
|
||||
registration_id: ServiceWorkerRegistrationId,
|
||||
) -> DomRoot<ServiceWorkerRegistration> {
|
||||
let active_worker =
|
||||
ServiceWorker::install_serviceworker(global, script_url.clone(), scope.clone(), true);
|
||||
active_worker.set_transition_state(ServiceWorkerState::Installed);
|
||||
|
||||
reflect_dom_object(
|
||||
Box::new(ServiceWorkerRegistration::new_inherited(
|
||||
&*active_worker,
|
||||
scope,
|
||||
registration_id,
|
||||
)),
|
||||
global,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn active(&self) -> Option<&ServiceWorker> {
|
||||
self.active.as_ref().map(|sw| &**sw)
|
||||
/// Does this registration have an active worker?
|
||||
pub fn is_active(&self) -> bool {
|
||||
self.active.borrow().is_some()
|
||||
}
|
||||
|
||||
pub fn get_installed(&self) -> &ServiceWorker {
|
||||
self.active.as_ref().unwrap()
|
||||
pub fn set_installing(&self, worker: &ServiceWorker) {
|
||||
*self.installing.borrow_mut() = Some(Dom::from_ref(worker));
|
||||
}
|
||||
|
||||
pub fn get_navigation_preload_header_value(&self) -> Option<ByteString> {
|
||||
|
@ -124,13 +126,14 @@ impl ServiceWorkerRegistration {
|
|||
|
||||
// https://w3c.github.io/ServiceWorker/#get-newest-worker-algorithm
|
||||
pub fn get_newest_worker(&self) -> Option<DomRoot<ServiceWorker>> {
|
||||
if self.installing.as_ref().is_some() {
|
||||
self.installing.as_ref().map(|sw| DomRoot::from_ref(&**sw))
|
||||
} else if self.waiting.as_ref().is_some() {
|
||||
self.waiting.as_ref().map(|sw| DomRoot::from_ref(&**sw))
|
||||
} else {
|
||||
self.active.as_ref().map(|sw| DomRoot::from_ref(&**sw))
|
||||
}
|
||||
let installing = self.installing.borrow();
|
||||
let waiting = self.waiting.borrow();
|
||||
let active = self.active.borrow();
|
||||
installing
|
||||
.as_ref()
|
||||
.map(|sw| DomRoot::from_ref(&**sw))
|
||||
.or_else(|| waiting.as_ref().map(|sw| DomRoot::from_ref(&**sw)))
|
||||
.or_else(|| active.as_ref().map(|sw| DomRoot::from_ref(&**sw)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,17 +157,26 @@ pub fn longest_prefix_match(stored_scope: &ServoUrl, potential_match: &ServoUrl)
|
|||
impl ServiceWorkerRegistrationMethods for ServiceWorkerRegistration {
|
||||
// https://w3c.github.io/ServiceWorker/#service-worker-registration-installing-attribute
|
||||
fn GetInstalling(&self) -> Option<DomRoot<ServiceWorker>> {
|
||||
self.installing.as_ref().map(|sw| DomRoot::from_ref(&**sw))
|
||||
self.installing
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.map(|sw| DomRoot::from_ref(&**sw))
|
||||
}
|
||||
|
||||
// https://w3c.github.io/ServiceWorker/#service-worker-registration-active-attribute
|
||||
fn GetActive(&self) -> Option<DomRoot<ServiceWorker>> {
|
||||
self.active.as_ref().map(|sw| DomRoot::from_ref(&**sw))
|
||||
self.active
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.map(|sw| DomRoot::from_ref(&**sw))
|
||||
}
|
||||
|
||||
// https://w3c.github.io/ServiceWorker/#service-worker-registration-waiting-attribute
|
||||
fn GetWaiting(&self) -> Option<DomRoot<ServiceWorker>> {
|
||||
self.waiting.as_ref().map(|sw| DomRoot::from_ref(&**sw))
|
||||
self.waiting
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.map(|sw| DomRoot::from_ref(&**sw))
|
||||
}
|
||||
|
||||
// https://w3c.github.io/ServiceWorker/#service-worker-registration-scope-attribute
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue