1use std::rc::Rc;
6use std::str::FromStr;
7
8use cssparser::match_ignore_ascii_case;
9use dom_struct::dom_struct;
10use http::Method as HttpMethod;
11use http::header::{HeaderName, HeaderValue};
12use http::method::InvalidMethod;
13use js::rust::HandleObject;
14use net_traits::ReferrerPolicy as MsgReferrerPolicy;
15use net_traits::fetch::headers::is_forbidden_method;
16use net_traits::request::{
17 CacheMode, CredentialsMode, Destination, Origin, RedirectMode, Referrer,
18 Request as NetTraitsRequest, RequestBuilder, RequestMode as NetTraitsRequestMode,
19 TraversableForUserPrompts,
20};
21use script_bindings::cell::DomRefCell;
22use script_bindings::cformat;
23use script_bindings::reflector::{Reflector, reflect_dom_object_with_proto};
24use servo_url::ServoUrl;
25
26use crate::body::{
27 BodyMixin, BodyType, Extractable, body_text_stream, clone_body_stream_for_dom_body,
28 consume_body,
29};
30use crate::conversions::Convert;
31use crate::dom::abortsignal::AbortSignal;
32use crate::dom::bindings::codegen::Bindings::HeadersBinding::{HeadersInit, HeadersMethods};
33use crate::dom::bindings::codegen::Bindings::RequestBinding::{
34 ReferrerPolicy, RequestCache, RequestCredentials, RequestDestination, RequestInfo, RequestInit,
35 RequestMethods, RequestMode, RequestRedirect,
36};
37use crate::dom::bindings::error::{Error, Fallible};
38use crate::dom::bindings::reflector::DomGlobal;
39use crate::dom::bindings::root::{DomRoot, MutNullableDom};
40use crate::dom::bindings::str::{ByteString, DOMString, USVString};
41use crate::dom::bindings::trace::RootedTraceableBox;
42use crate::dom::globalscope::GlobalScope;
43use crate::dom::headers::{Guard, Headers};
44use crate::dom::promise::Promise;
45use crate::dom::stream::readablestream::ReadableStream;
46use crate::fetch::RequestWithGlobalScope;
47use crate::script_runtime::CanGc;
48use crate::url::ensure_blob_referenced_by_url_is_kept_alive;
49
50#[dom_struct]
51pub(crate) struct Request {
52 reflector_: Reflector,
53 #[no_trace]
54 request: DomRefCell<NetTraitsRequest>,
56 body_stream: MutNullableDom<ReadableStream>,
58 headers: MutNullableDom<Headers>,
60 signal: MutNullableDom<AbortSignal>,
62}
63
64impl Request {
65 fn new_inherited(global: &GlobalScope, url: ServoUrl) -> Request {
66 Request {
67 reflector_: Reflector::new(),
68 request: DomRefCell::new(net_request_from_global(global, url)),
69 body_stream: MutNullableDom::new(None),
70 headers: Default::default(),
71 signal: MutNullableDom::new(None),
72 }
73 }
74
75 fn new(
76 global: &GlobalScope,
77 proto: Option<HandleObject>,
78 url: ServoUrl,
79 can_gc: CanGc,
80 ) -> DomRoot<Request> {
81 reflect_dom_object_with_proto(
82 Box::new(Request::new_inherited(global, url)),
83 global,
84 proto,
85 can_gc,
86 )
87 }
88
89 fn from_net_request(
90 global: &GlobalScope,
91 proto: Option<HandleObject>,
92 net_request: NetTraitsRequest,
93 can_gc: CanGc,
94 ) -> DomRoot<Request> {
95 let r = Request::new(global, proto, net_request.current_url(), can_gc);
96 *r.request.borrow_mut() = net_request;
97 r
98 }
99
100 pub(crate) fn constructor(
102 cx: &mut js::context::JSContext,
103 global: &GlobalScope,
104 proto: Option<HandleObject>,
105 mut input: RequestInfo,
106 init: &RequestInit,
107 ) -> Fallible<DomRoot<Request>> {
108 let temporary_request: NetTraitsRequest;
110
111 let mut fallback_mode: Option<NetTraitsRequestMode> = None;
113
114 let base_url = global.api_base_url();
116
117 let mut signal: Option<DomRoot<AbortSignal>> = None;
119
120 let mut input_body_is_unusable = false;
122
123 match input {
124 RequestInfo::USVString(USVString(ref usv_string)) => {
126 let parsed_url = base_url.join(usv_string);
128 if parsed_url.is_err() {
130 return Err(Error::Type(c"Url could not be parsed".to_owned()));
131 }
132 let url = parsed_url.unwrap();
134 if includes_credentials(&url) {
135 return Err(Error::Type(c"Url includes credentials".to_owned()));
136 }
137 temporary_request = net_request_from_global(global, url);
139 fallback_mode = Some(NetTraitsRequestMode::CorsMode);
141 },
142 RequestInfo::Request(ref input_request) => {
145 input_body_is_unusable = input_request.is_unusable();
147 temporary_request = input_request.request.borrow().clone();
149 signal = Some(input_request.Signal());
151 },
152 }
153
154 let origin = global.origin();
156 let origin = origin.immutable();
157
158 let mut traversable_for_user_prompts = TraversableForUserPrompts::Client;
160
161 if !init.window.handle().is_null_or_undefined() {
168 return Err(Error::Type(c"Window is present and is not null".to_owned()));
169 }
170
171 if !init.window.handle().is_undefined() {
173 traversable_for_user_prompts = TraversableForUserPrompts::NoTraversable;
174 }
175
176 let mut request: NetTraitsRequest;
178 request = net_request_from_global(global, temporary_request.current_url());
179 request.method = temporary_request.method;
180 request.headers = temporary_request.headers.clone();
181 request.unsafe_request = true;
182 request.traversable_for_user_prompts = traversable_for_user_prompts;
183 request.origin = Origin::Client;
185 request.referrer = temporary_request.referrer;
186 request.referrer_policy = temporary_request.referrer_policy;
187 request.mode = temporary_request.mode;
188 request.credentials_mode = temporary_request.credentials_mode;
189 request.cache_mode = temporary_request.cache_mode;
190 request.redirect_mode = temporary_request.redirect_mode;
191 request.integrity_metadata = temporary_request.integrity_metadata;
192
193 if init.body.is_some() ||
195 init.cache.is_some() ||
196 init.credentials.is_some() ||
197 init.integrity.is_some() ||
198 init.headers.is_some() ||
199 init.keepalive.is_some() ||
200 init.method.is_some() ||
201 init.mode.is_some() ||
202 init.redirect.is_some() ||
203 init.referrer.is_some() ||
204 init.referrerPolicy.is_some() ||
205 !init.window.handle().is_undefined()
206 {
207 if request.mode == NetTraitsRequestMode::Navigate {
209 request.mode = NetTraitsRequestMode::SameOrigin;
210 }
211 request.referrer = global.get_referrer();
219 request.referrer_policy = MsgReferrerPolicy::EmptyString;
221 }
226
227 if let Some(init_referrer) = init.referrer.as_ref() {
229 let referrer = &init_referrer.0;
231 if referrer.is_empty() {
233 request.referrer = Referrer::NoReferrer;
234 } else {
236 let parsed_referrer = base_url.join(referrer);
238 if parsed_referrer.is_err() {
240 return Err(Error::Type(c"Failed to parse referrer url".to_owned()));
241 }
242 if let Ok(parsed_referrer) = parsed_referrer {
246 if (parsed_referrer.cannot_be_a_base() &&
247 parsed_referrer.scheme() == "about" &&
248 parsed_referrer.path() == "client") ||
249 parsed_referrer.origin() != *origin
250 {
251 request.referrer = global.get_referrer();
253 } else {
254 request.referrer = Referrer::ReferrerUrl(parsed_referrer);
256 }
257 }
258 }
259 }
260
261 if let Some(init_referrerpolicy) = init.referrerPolicy.as_ref() {
263 let init_referrer_policy = (*init_referrerpolicy).convert();
264 request.referrer_policy = init_referrer_policy;
265 }
266
267 let mode = init.mode.as_ref().map(|m| (*m).convert()).or(fallback_mode);
269
270 if let Some(NetTraitsRequestMode::Navigate) = mode {
272 return Err(Error::Type(c"Request mode is Navigate".to_owned()));
273 }
274
275 if let Some(m) = mode {
277 request.mode = m;
278 }
279
280 if let Some(init_credentials) = init.credentials.as_ref() {
282 let credentials = (*init_credentials).convert();
283 request.credentials_mode = credentials;
284 }
285
286 if let Some(init_cache) = init.cache.as_ref() {
288 let cache = (*init_cache).convert();
289 request.cache_mode = cache;
290 }
291
292 if request.cache_mode == CacheMode::OnlyIfCached &&
295 request.mode != NetTraitsRequestMode::SameOrigin
296 {
297 return Err(Error::Type(
298 c"Cache is 'only-if-cached' and mode is not 'same-origin'".to_owned(),
299 ));
300 }
301
302 if let Some(init_redirect) = init.redirect.as_ref() {
304 let redirect = (*init_redirect).convert();
305 request.redirect_mode = redirect;
306 }
307
308 if let Some(init_integrity) = init.integrity.as_ref() {
310 let integrity = init_integrity.to_string();
311 request.integrity_metadata = integrity;
312 }
313
314 if let Some(init_keepalive) = init.keepalive {
316 request.keep_alive = init_keepalive;
317 }
318
319 if let Some(init_method) = init.method.as_ref() {
322 if !is_method(init_method) {
324 return Err(Error::Type(c"Method is not a method".to_owned()));
325 }
326 if is_forbidden_method(init_method) {
327 return Err(Error::Type(c"Method is forbidden".to_owned()));
328 }
329 let method = match init_method.as_str() {
331 Some(s) => normalize_method(s)
332 .map_err(|e| Error::Type(cformat!("Method is not valid: {:?}", e)))?,
333 None => return Err(Error::Type(c"Method is not a valid UTF8".to_owned())),
334 };
335 request.method = method;
337 }
338
339 if let Some(init_signal) = init.signal.as_ref() {
341 signal = init_signal.clone();
342 }
343 let r = Request::from_net_request(global, proto, request, CanGc::from_cx(cx));
353
354 let signals = signal.map_or(vec![], |s| vec![s]);
356 r.signal
359 .set(Some(&AbortSignal::create_dependent_abort_signal(
360 cx, signals, global,
361 )));
362
363 r.headers
369 .or_init(|| Headers::for_request(&r.global(), CanGc::from_cx(cx)));
370
371 let headers_copy = init
375 .headers
376 .as_ref()
377 .map(|possible_header| match possible_header {
378 HeadersInit::ByteStringSequenceSequence(init_sequence) => {
379 HeadersInit::ByteStringSequenceSequence(init_sequence.clone())
380 },
381 HeadersInit::ByteStringByteStringRecord(init_map) => {
382 HeadersInit::ByteStringByteStringRecord(init_map.clone())
383 },
384 });
385
386 if r.request.borrow().mode == NetTraitsRequestMode::NoCors {
397 let borrowed_request = r.request.borrow();
398 if !is_cors_safelisted_method(&borrowed_request.method) {
400 return Err(Error::Type(
401 c"The mode is 'no-cors' but the method is not a cors-safelisted method"
402 .to_owned(),
403 ));
404 }
405 r.Headers(cx).set_guard(Guard::RequestNoCors);
407 }
408
409 match headers_copy {
410 None => {
411 if let RequestInfo::Request(ref input_request) = input {
418 r.Headers(cx).copy_from_headers(input_request.Headers(cx))?;
419 }
420 },
421 Some(headers_copy) => r.Headers(cx).fill(Some(headers_copy))?,
423 }
424
425 r.request.borrow_mut().headers = r.Headers(cx).get_headers_list();
428
429 let input_body = if let RequestInfo::Request(ref mut input_request) = input {
431 let mut input_request_request = input_request.request.borrow_mut();
432 r.body_stream.set(input_request.body().as_deref());
433 input_request_request.body.take()
434 } else {
435 None
436 };
437
438 if init.body.as_ref().is_some_and(|body| body.is_some()) || input_body.is_some() {
441 let req = r.request.borrow();
442 let req_method = &req.method;
443 match *req_method {
444 HttpMethod::GET => {
445 return Err(Error::Type(
446 c"Init's body is non-null, and request method is GET".to_owned(),
447 ));
448 },
449 HttpMethod::HEAD => {
450 return Err(Error::Type(
451 c"Init's body is non-null, and request method is HEAD".to_owned(),
452 ));
453 },
454 _ => {},
455 }
456 }
457
458 let mut init_body = None;
460 if let Some(Some(ref input_init_body)) = init.body {
462 let mut body_with_type =
464 input_init_body.extract(cx, global, r.request.borrow().keep_alive)?;
465
466 if let Some(contents) = body_with_type.content_type.take() {
468 let ct_header_name = b"Content-Type";
469 if !r
472 .Headers(cx)
473 .Has(ByteString::new(ct_header_name.to_vec()))
474 .unwrap()
475 {
476 let ct_header_val = contents.as_bytes();
477 r.Headers(cx).Append(
478 ByteString::new(ct_header_name.to_vec()),
479 ByteString::new(ct_header_val.to_vec()),
480 )?;
481
482 if let Ok(v) = HeaderValue::from_bytes(&ct_header_val) {
486 r.request
487 .borrow_mut()
488 .headers
489 .insert(HeaderName::from_bytes(ct_header_name).unwrap(), v);
490 }
491 }
492 }
493
494 let (net_body, stream) = body_with_type.into_net_request_body();
496 r.body_stream.set(Some(&*stream));
497 init_body = Some(net_body);
498 }
499
500 let final_body = init_body.or(input_body);
507
508 if final_body
510 .as_ref()
511 .is_some_and(|body| body.source_is_null())
512 {
513 let request_mode = &r.request.borrow().mode;
517 if *request_mode != NetTraitsRequestMode::CorsMode &&
518 *request_mode != NetTraitsRequestMode::SameOrigin
519 {
520 return Err(Error::Type(
521 c"Request mode must be Cors or SameOrigin".to_owned(),
522 ));
523 }
524 }
527
528 if input_body_is_unusable {
535 return Err(Error::Type(c"Input body is unusable".to_owned()));
536 }
537
538 r.request.borrow_mut().body = final_body;
540
541 Ok(r)
542 }
543
544 fn clone_from(cx: &mut js::context::JSContext, r: &Request) -> Fallible<DomRoot<Request>> {
546 let req = r.request.borrow();
547 let url = req.url();
548 let headers_guard = r.Headers(cx).get_guard();
549
550 let mut new_req_inner = req.clone();
552 let body = new_req_inner.body.take();
553
554 let r_clone = Request::new(&r.global(), None, url, CanGc::from_cx(cx));
555 *r_clone.request.borrow_mut() = new_req_inner;
556
557 if let Some(body) = body {
560 r_clone.request.borrow_mut().body = Some(body);
561 }
562
563 r_clone.Headers(cx).copy_from_headers(r.Headers(cx))?;
564 r_clone.Headers(cx).set_guard(headers_guard);
565
566 clone_body_stream_for_dom_body(cx, &r.body_stream, &r_clone.body_stream)?;
567
568 Ok(r_clone)
570 }
571
572 pub(crate) fn get_request(&self) -> NetTraitsRequest {
573 self.request.borrow().clone()
574 }
575}
576
577fn net_request_from_global(global: &GlobalScope, url: ServoUrl) -> NetTraitsRequest {
578 let url = ensure_blob_referenced_by_url_is_kept_alive(global, url);
579 RequestBuilder::new(global.webview_id(), url, global.get_referrer())
580 .with_global_scope(global)
581 .build()
582}
583
584fn normalize_method(m: &str) -> Result<HttpMethod, InvalidMethod> {
586 match_ignore_ascii_case! { m,
587 "delete" => return Ok(HttpMethod::DELETE),
588 "get" => return Ok(HttpMethod::GET),
589 "head" => return Ok(HttpMethod::HEAD),
590 "options" => return Ok(HttpMethod::OPTIONS),
591 "post" => return Ok(HttpMethod::POST),
592 "put" => return Ok(HttpMethod::PUT),
593 _ => (),
594 }
595 debug!("Method: {:?}", m);
596 HttpMethod::from_str(m)
597}
598
599fn is_method(m: &ByteString) -> bool {
601 m.as_str().is_some()
602}
603
604fn is_cors_safelisted_method(m: &HttpMethod) -> bool {
606 m == HttpMethod::GET || m == HttpMethod::HEAD || m == HttpMethod::POST
607}
608
609fn includes_credentials(input: &ServoUrl) -> bool {
611 !input.username().is_empty() || input.password().is_some()
612}
613
614impl RequestMethods<crate::DomTypeHolder> for Request {
615 fn Constructor(
617 cx: &mut js::context::JSContext,
618 global: &GlobalScope,
619 proto: Option<HandleObject>,
620 input: RequestInfo,
621 init: RootedTraceableBox<RequestInit>,
622 ) -> Fallible<DomRoot<Request>> {
623 Self::constructor(cx, global, proto, input, &init)
624 }
625
626 fn Method(&self) -> ByteString {
628 let r = self.request.borrow();
629 ByteString::new(r.method.as_ref().as_bytes().into())
630 }
631
632 fn Url(&self) -> USVString {
634 let r = self.request.borrow();
635 USVString(r.url_list.first().map_or("", |u| u.as_str()).into())
636 }
637
638 fn Headers(&self, cx: &mut js::context::JSContext) -> DomRoot<Headers> {
640 self.headers
641 .or_init(|| Headers::new(&self.global(), CanGc::from_cx(cx)))
642 }
643
644 fn Destination(&self) -> RequestDestination {
646 self.request.borrow().destination.convert()
647 }
648
649 fn Referrer(&self) -> USVString {
651 let r = self.request.borrow();
652 USVString(match r.referrer {
653 Referrer::NoReferrer => String::from(""),
654 Referrer::Client(_) => String::from("about:client"),
655 Referrer::ReferrerUrl(ref u) => {
656 let u_c = u.clone();
657 u_c.into_string()
658 },
659 })
660 }
661
662 fn ReferrerPolicy(&self) -> ReferrerPolicy {
664 self.request.borrow().referrer_policy.convert()
665 }
666
667 fn Mode(&self) -> RequestMode {
669 self.request.borrow().mode.clone().convert()
670 }
671
672 fn Credentials(&self) -> RequestCredentials {
674 let r = self.request.borrow().clone();
675 r.credentials_mode.convert()
676 }
677
678 fn Cache(&self) -> RequestCache {
680 let r = self.request.borrow().clone();
681 r.cache_mode.convert()
682 }
683
684 fn Redirect(&self) -> RequestRedirect {
686 let r = self.request.borrow().clone();
687 r.redirect_mode.convert()
688 }
689
690 fn Integrity(&self) -> DOMString {
692 self.request.borrow().integrity_metadata.clone().into()
693 }
694
695 fn Keepalive(&self) -> bool {
697 self.request.borrow().keep_alive
698 }
699
700 fn GetBody(&self) -> Option<DomRoot<ReadableStream>> {
702 self.body()
703 }
704
705 fn BodyUsed(&self) -> bool {
707 self.is_body_used()
708 }
709
710 fn Signal(&self) -> DomRoot<AbortSignal> {
712 self.signal
713 .get()
714 .expect("Should always be initialized in constructor and clone")
715 }
716
717 fn Clone(&self, cx: &mut js::context::JSContext) -> Fallible<DomRoot<Request>> {
719 if self.is_unusable() {
721 return Err(Error::Type(c"Request is unusable".to_owned()));
722 }
723
724 let cloned_request = Request::clone_from(cx, self)?;
726 let signal = self.signal.get().expect("Should always be initialized");
728 let cloned_signal =
731 AbortSignal::create_dependent_abort_signal(cx, vec![signal], &self.global());
732 cloned_request.signal.set(Some(&cloned_signal));
737 Ok(cloned_request)
739 }
740
741 fn Text(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
743 consume_body(cx, self, BodyType::Text)
744 }
745
746 fn Blob(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
748 consume_body(cx, self, BodyType::Blob)
749 }
750
751 fn FormData(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
753 consume_body(cx, self, BodyType::FormData)
754 }
755
756 fn Json(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
758 consume_body(cx, self, BodyType::Json)
759 }
760
761 fn ArrayBuffer(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
763 consume_body(cx, self, BodyType::ArrayBuffer)
764 }
765
766 fn Bytes(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
768 consume_body(cx, self, BodyType::Bytes)
769 }
770
771 fn TextStream(&self, cx: &mut js::context::JSContext) -> Fallible<DomRoot<ReadableStream>> {
773 body_text_stream(cx, self)
774 }
775}
776
777impl BodyMixin for Request {
778 fn is_body_used(&self) -> bool {
779 let body_stream = self.body_stream.get();
780 body_stream
781 .as_ref()
782 .is_some_and(|stream| stream.is_disturbed())
783 }
784
785 fn is_unusable(&self) -> bool {
786 let body_stream = self.body_stream.get();
787 body_stream
788 .as_ref()
789 .is_some_and(|stream| stream.is_disturbed() || stream.is_locked())
790 }
791
792 fn body(&self) -> Option<DomRoot<ReadableStream>> {
793 self.body_stream.get()
794 }
795
796 fn get_mime_type(&self, cx: &mut js::context::JSContext) -> Vec<u8> {
797 let headers = self.Headers(cx);
798 headers.extract_mime_type()
799 }
800}
801
802impl Convert<CacheMode> for RequestCache {
803 fn convert(self) -> CacheMode {
804 match self {
805 RequestCache::Default => CacheMode::Default,
806 RequestCache::No_store => CacheMode::NoStore,
807 RequestCache::Reload => CacheMode::Reload,
808 RequestCache::No_cache => CacheMode::NoCache,
809 RequestCache::Force_cache => CacheMode::ForceCache,
810 RequestCache::Only_if_cached => CacheMode::OnlyIfCached,
811 }
812 }
813}
814
815impl Convert<RequestCache> for CacheMode {
816 fn convert(self) -> RequestCache {
817 match self {
818 CacheMode::Default => RequestCache::Default,
819 CacheMode::NoStore => RequestCache::No_store,
820 CacheMode::Reload => RequestCache::Reload,
821 CacheMode::NoCache => RequestCache::No_cache,
822 CacheMode::ForceCache => RequestCache::Force_cache,
823 CacheMode::OnlyIfCached => RequestCache::Only_if_cached,
824 }
825 }
826}
827
828impl Convert<CredentialsMode> for RequestCredentials {
829 fn convert(self) -> CredentialsMode {
830 match self {
831 RequestCredentials::Omit => CredentialsMode::Omit,
832 RequestCredentials::Same_origin => CredentialsMode::CredentialsSameOrigin,
833 RequestCredentials::Include => CredentialsMode::Include,
834 }
835 }
836}
837
838impl Convert<RequestCredentials> for CredentialsMode {
839 fn convert(self) -> RequestCredentials {
840 match self {
841 CredentialsMode::Omit => RequestCredentials::Omit,
842 CredentialsMode::CredentialsSameOrigin => RequestCredentials::Same_origin,
843 CredentialsMode::Include => RequestCredentials::Include,
844 }
845 }
846}
847
848impl Convert<Destination> for RequestDestination {
849 fn convert(self) -> Destination {
850 match self {
851 RequestDestination::_empty => Destination::None,
852 RequestDestination::Audio => Destination::Audio,
853 RequestDestination::Document => Destination::Document,
854 RequestDestination::Embed => Destination::Embed,
855 RequestDestination::Font => Destination::Font,
856 RequestDestination::Frame => Destination::Frame,
857 RequestDestination::Iframe => Destination::IFrame,
858 RequestDestination::Image => Destination::Image,
859 RequestDestination::Manifest => Destination::Manifest,
860 RequestDestination::Json => Destination::Json,
861 RequestDestination::Object => Destination::Object,
862 RequestDestination::Report => Destination::Report,
863 RequestDestination::Script => Destination::Script,
864 RequestDestination::Sharedworker => Destination::SharedWorker,
865 RequestDestination::Style => Destination::Style,
866 RequestDestination::Track => Destination::Track,
867 RequestDestination::Video => Destination::Video,
868 RequestDestination::Worker => Destination::Worker,
869 RequestDestination::Xslt => Destination::Xslt,
870 }
871 }
872}
873
874impl Convert<RequestDestination> for Destination {
875 fn convert(self) -> RequestDestination {
876 match self {
877 Destination::None => RequestDestination::_empty,
878 Destination::Audio => RequestDestination::Audio,
879 Destination::Document => RequestDestination::Document,
880 Destination::Embed => RequestDestination::Embed,
881 Destination::Font => RequestDestination::Font,
882 Destination::Frame => RequestDestination::Frame,
883 Destination::IFrame => RequestDestination::Iframe,
884 Destination::Image => RequestDestination::Image,
885 Destination::Manifest => RequestDestination::Manifest,
886 Destination::Json => RequestDestination::Json,
887 Destination::Object => RequestDestination::Object,
888 Destination::Report => RequestDestination::Report,
889 Destination::Script => RequestDestination::Script,
890 Destination::ServiceWorker | Destination::AudioWorklet | Destination::PaintWorklet => {
891 panic!("ServiceWorker request destination should not be exposed to DOM")
892 },
893 Destination::SharedWorker => RequestDestination::Sharedworker,
894 Destination::Style => RequestDestination::Style,
895 Destination::Track => RequestDestination::Track,
896 Destination::Video => RequestDestination::Video,
897 Destination::Worker => RequestDestination::Worker,
898 Destination::Xslt => RequestDestination::Xslt,
899 Destination::WebIdentity => RequestDestination::_empty,
900 }
901 }
902}
903
904impl Convert<NetTraitsRequestMode> for RequestMode {
905 fn convert(self) -> NetTraitsRequestMode {
906 match self {
907 RequestMode::Navigate => NetTraitsRequestMode::Navigate,
908 RequestMode::Same_origin => NetTraitsRequestMode::SameOrigin,
909 RequestMode::No_cors => NetTraitsRequestMode::NoCors,
910 RequestMode::Cors => NetTraitsRequestMode::CorsMode,
911 }
912 }
913}
914
915impl Convert<RequestMode> for NetTraitsRequestMode {
916 fn convert(self) -> RequestMode {
917 match self {
918 NetTraitsRequestMode::Navigate => RequestMode::Navigate,
919 NetTraitsRequestMode::SameOrigin => RequestMode::Same_origin,
920 NetTraitsRequestMode::NoCors => RequestMode::No_cors,
921 NetTraitsRequestMode::CorsMode => RequestMode::Cors,
922 NetTraitsRequestMode::WebSocket { .. } => {
923 unreachable!("Websocket request mode should never be exposed to Dom")
924 },
925 }
926 }
927}
928
929impl Convert<MsgReferrerPolicy> for ReferrerPolicy {
930 fn convert(self) -> MsgReferrerPolicy {
931 match self {
932 ReferrerPolicy::_empty => MsgReferrerPolicy::EmptyString,
933 ReferrerPolicy::No_referrer => MsgReferrerPolicy::NoReferrer,
934 ReferrerPolicy::No_referrer_when_downgrade => {
935 MsgReferrerPolicy::NoReferrerWhenDowngrade
936 },
937 ReferrerPolicy::Origin => MsgReferrerPolicy::Origin,
938 ReferrerPolicy::Origin_when_cross_origin => MsgReferrerPolicy::OriginWhenCrossOrigin,
939 ReferrerPolicy::Unsafe_url => MsgReferrerPolicy::UnsafeUrl,
940 ReferrerPolicy::Same_origin => MsgReferrerPolicy::SameOrigin,
941 ReferrerPolicy::Strict_origin => MsgReferrerPolicy::StrictOrigin,
942 ReferrerPolicy::Strict_origin_when_cross_origin => {
943 MsgReferrerPolicy::StrictOriginWhenCrossOrigin
944 },
945 }
946 }
947}
948
949impl Convert<ReferrerPolicy> for MsgReferrerPolicy {
950 fn convert(self) -> ReferrerPolicy {
951 match self {
952 MsgReferrerPolicy::EmptyString => ReferrerPolicy::_empty,
953 MsgReferrerPolicy::NoReferrer => ReferrerPolicy::No_referrer,
954 MsgReferrerPolicy::NoReferrerWhenDowngrade => {
955 ReferrerPolicy::No_referrer_when_downgrade
956 },
957 MsgReferrerPolicy::Origin => ReferrerPolicy::Origin,
958 MsgReferrerPolicy::OriginWhenCrossOrigin => ReferrerPolicy::Origin_when_cross_origin,
959 MsgReferrerPolicy::UnsafeUrl => ReferrerPolicy::Unsafe_url,
960 MsgReferrerPolicy::SameOrigin => ReferrerPolicy::Same_origin,
961 MsgReferrerPolicy::StrictOrigin => ReferrerPolicy::Strict_origin,
962 MsgReferrerPolicy::StrictOriginWhenCrossOrigin => {
963 ReferrerPolicy::Strict_origin_when_cross_origin
964 },
965 }
966 }
967}
968
969impl Convert<RedirectMode> for RequestRedirect {
970 fn convert(self) -> RedirectMode {
971 match self {
972 RequestRedirect::Follow => RedirectMode::Follow,
973 RequestRedirect::Error => RedirectMode::Error,
974 RequestRedirect::Manual => RedirectMode::Manual,
975 }
976 }
977}
978
979impl Convert<RequestRedirect> for RedirectMode {
980 fn convert(self) -> RequestRedirect {
981 match self {
982 RedirectMode::Follow => RequestRedirect::Follow,
983 RedirectMode::Error => RequestRedirect::Error,
984 RedirectMode::Manual => RequestRedirect::Manual,
985 }
986 }
987}