script/dom/serviceworker/
navigationpreloadmanager.rs1use dom_struct::dom_struct;
6use js::context::JSContext;
7use js::realm::CurrentRealm;
8use net_traits::trim_http_whitespace;
9use script_bindings::reflector::{Reflector, reflect_dom_object};
10
11use crate::dom::bindings::codegen::Bindings::NavigationPreloadManagerBinding::{
12 NavigationPreloadManagerMethods, NavigationPreloadState,
13};
14use crate::dom::bindings::error::Error;
15use crate::dom::bindings::root::{Dom, DomRoot};
16use crate::dom::bindings::str::ByteString;
17use crate::dom::globalscope::GlobalScope;
18use crate::dom::promise::{Promise, RootedPromise};
19use crate::dom::serviceworkerregistration::ServiceWorkerRegistration;
20
21#[dom_struct]
22pub(crate) struct NavigationPreloadManager {
23 reflector_: Reflector,
24 serviceworker_registration: Dom<ServiceWorkerRegistration>,
25}
26
27impl NavigationPreloadManager {
28 fn new_inherited(registration: &ServiceWorkerRegistration) -> NavigationPreloadManager {
29 NavigationPreloadManager {
30 reflector_: Reflector::new(),
31 serviceworker_registration: Dom::from_ref(registration),
32 }
33 }
34
35 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
36 pub(crate) fn new(
37 cx: &mut JSContext,
38 global: &GlobalScope,
39 registration: &ServiceWorkerRegistration,
40 ) -> DomRoot<NavigationPreloadManager> {
41 let manager = NavigationPreloadManager::new_inherited(registration);
42 reflect_dom_object(cx, Box::new(manager), global)
43 }
44}
45
46impl NavigationPreloadManagerMethods<crate::DomTypeHolder> for NavigationPreloadManager {
47 fn Enable(&self, cx: &mut CurrentRealm) -> RootedPromise {
49 let promise = Promise::new_in_realm(cx);
51
52 if !self.serviceworker_registration.is_active() {
55 promise.reject_error(
56 cx,
57 Error::InvalidState(Some("Registration has no active worker".into())),
58 );
59 } else {
60 self.serviceworker_registration
62 .set_navigation_preload_enabled(true);
63
64 promise.resolve_native(cx, &());
66 }
67
68 promise
70 }
71
72 fn Disable(&self, cx: &mut CurrentRealm) -> RootedPromise {
74 let promise = Promise::new_in_realm(cx);
76
77 if !self.serviceworker_registration.is_active() {
80 promise.reject_error(
81 cx,
82 Error::InvalidState(Some("Registration has no active worker".into())),
83 );
84 } else {
85 self.serviceworker_registration
87 .set_navigation_preload_enabled(false);
88
89 promise.resolve_native(cx, &());
91 }
92
93 promise
95 }
96
97 fn SetHeaderValue(&self, cx: &mut CurrentRealm, value: ByteString) -> RootedPromise {
99 let value = Vec::<u8>::from(value);
101 let normalized_value = trim_http_whitespace(&value);
102
103 let promise = Promise::new_in_realm(cx);
105 if normalized_value.contains(&b'\0') {
106 promise.reject_error(cx, Error::Type(c"Invalid header value".to_owned()));
107 return promise;
108 }
109
110 if !self.serviceworker_registration.is_active() {
113 promise.reject_error(
114 cx,
115 Error::InvalidState(Some("Registration has no active worker".into())),
116 );
117 } else {
118 self.serviceworker_registration
120 .set_navigation_preload_header_value(ByteString::new(normalized_value.to_vec()));
121
122 promise.resolve_native(cx, &());
124 }
125
126 promise
128 }
129
130 fn GetState(&self, cx: &mut CurrentRealm) -> RootedPromise {
132 let promise = Promise::new_in_realm(cx);
134
135 let mut state = NavigationPreloadState::empty();
138
139 if self
141 .serviceworker_registration
142 .get_navigation_preload_enabled()
143 {
144 state.enabled = true;
145 }
146
147 state.headerValue = Some(
149 self.serviceworker_registration
150 .get_navigation_preload_header_value(),
151 );
152
153 promise.resolve_native(cx, &state);
155
156 promise
158 }
159}