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::{CONTENT_TYPE, HeaderValue};
12use http::method::InvalidMethod;
13use js::context::JSContext;
14use js::rust::HandleObject;
15use net_traits::ReferrerPolicy as MsgReferrerPolicy;
16use net_traits::fetch::headers::is_forbidden_method;
17use net_traits::request::{
18 CacheMode, CredentialsMode, Destination, Origin, RedirectMode, Referrer,
19 Request as NetTraitsRequest, RequestBuilder, RequestMode as NetTraitsRequestMode,
20 TraversableForUserPrompts,
21};
22use script_bindings::cell::DomRefCell;
23use script_bindings::cformat;
24use script_bindings::reflector::{Reflector, reflect_dom_object_with_proto};
25use servo_url::ServoUrl;
26
27use crate::body::{
28 BodyMixin, BodyType, Extractable, body_text_stream, clone_body_stream_for_dom_body,
29 consume_body,
30};
31use crate::conversions::Convert;
32use crate::dom::abortsignal::AbortSignal;
33use crate::dom::bindings::codegen::Bindings::HeadersBinding::{HeadersInit, HeadersMethods};
34use crate::dom::bindings::codegen::Bindings::RequestBinding::{
35 ReferrerPolicy, RequestCache, RequestCredentials, RequestDestination, RequestDuplex,
36 RequestInfo, RequestInit, RequestMethods, RequestMode, RequestRedirect,
37};
38use crate::dom::bindings::error::{Error, Fallible};
39use crate::dom::bindings::reflector::DomGlobal;
40use crate::dom::bindings::root::{DomRoot, MutNullableDom};
41use crate::dom::bindings::str::{ByteString, DOMString, USVString};
42use crate::dom::bindings::trace::RootedTraceableBox;
43use crate::dom::globalscope::GlobalScope;
44use crate::dom::headers::{Guard, Headers};
45use crate::dom::promise::Promise;
46use crate::dom::stream::readablestream::ReadableStream;
47use crate::fetch::RequestWithGlobalScope;
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 cx: &mut JSContext,
77 global: &GlobalScope,
78 proto: Option<HandleObject>,
79 url: ServoUrl,
80 ) -> DomRoot<Request> {
81 reflect_dom_object_with_proto(
82 cx,
83 Box::new(Request::new_inherited(global, url)),
84 global,
85 proto,
86 )
87 }
88
89 fn from_net_request(
90 cx: &mut JSContext,
91 global: &GlobalScope,
92 proto: Option<HandleObject>,
93 net_request: NetTraitsRequest,
94 ) -> DomRoot<Request> {
95 let r = Request::new(cx, global, proto, net_request.current_url());
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 request.reload_navigation = temporary_request.reload_navigation;
194 request.history_navigation = temporary_request.history_navigation;
196
197 if init.body.is_some() ||
199 init.cache.is_some() ||
200 init.credentials.is_some() ||
201 init.duplex.is_some() ||
202 init.integrity.is_some() ||
203 init.headers.is_some() ||
204 init.keepalive.is_some() ||
205 init.method.is_some() ||
206 init.mode.is_some() ||
207 init.redirect.is_some() ||
208 init.referrer.is_some() ||
209 init.referrerPolicy.is_some() ||
210 !init.window.handle().is_undefined()
211 {
212 if request.mode == NetTraitsRequestMode::Navigate {
214 request.mode = NetTraitsRequestMode::SameOrigin;
215 }
216 request.reload_navigation = false;
218 request.history_navigation = false;
220 request.referrer = global.get_referrer();
224 request.referrer_policy = MsgReferrerPolicy::EmptyString;
226 }
231
232 if let Some(init_referrer) = init.referrer.as_ref() {
234 let referrer = &init_referrer.0;
236 if referrer.is_empty() {
238 request.referrer = Referrer::NoReferrer;
239 } else {
241 let parsed_referrer = base_url.join(referrer);
243 if parsed_referrer.is_err() {
245 return Err(Error::Type(c"Failed to parse referrer url".to_owned()));
246 }
247 if let Ok(parsed_referrer) = parsed_referrer {
251 if (parsed_referrer.cannot_be_a_base() &&
252 parsed_referrer.scheme() == "about" &&
253 parsed_referrer.path() == "client") ||
254 parsed_referrer.origin() != *origin
255 {
256 request.referrer = global.get_referrer();
258 } else {
259 request.referrer = Referrer::ReferrerUrl(parsed_referrer);
261 }
262 }
263 }
264 }
265
266 if let Some(init_referrerpolicy) = init.referrerPolicy.as_ref() {
268 let init_referrer_policy = (*init_referrerpolicy).convert();
269 request.referrer_policy = init_referrer_policy;
270 }
271
272 let mode = init.mode.as_ref().map(|m| (*m).convert()).or(fallback_mode);
274
275 if let Some(NetTraitsRequestMode::Navigate) = mode {
277 return Err(Error::Type(c"Request mode is Navigate".to_owned()));
278 }
279
280 if let Some(m) = mode {
282 request.mode = m;
283 }
284
285 if let Some(init_credentials) = init.credentials.as_ref() {
287 let credentials = (*init_credentials).convert();
288 request.credentials_mode = credentials;
289 }
290
291 if let Some(init_cache) = init.cache.as_ref() {
293 let cache = (*init_cache).convert();
294 request.cache_mode = cache;
295 }
296
297 if request.cache_mode == CacheMode::OnlyIfCached &&
300 request.mode != NetTraitsRequestMode::SameOrigin
301 {
302 return Err(Error::Type(
303 c"Cache is 'only-if-cached' and mode is not 'same-origin'".to_owned(),
304 ));
305 }
306
307 if let Some(init_redirect) = init.redirect.as_ref() {
309 let redirect = (*init_redirect).convert();
310 request.redirect_mode = redirect;
311 }
312
313 if let Some(init_integrity) = init.integrity.as_ref() {
315 let integrity = init_integrity.to_string();
316 request.integrity_metadata = integrity;
317 }
318
319 if let Some(init_keepalive) = init.keepalive {
321 request.keep_alive = init_keepalive;
322 }
323
324 if let Some(init_method) = init.method.as_ref() {
327 if !is_method(init_method) {
329 return Err(Error::Type(c"Method is not a method".to_owned()));
330 }
331 if is_forbidden_method(init_method) {
332 return Err(Error::Type(c"Method is forbidden".to_owned()));
333 }
334 let method = match init_method.as_str() {
336 Some(s) => normalize_method(s)
337 .map_err(|e| Error::Type(cformat!("Method is not valid: {:?}", e)))?,
338 None => return Err(Error::Type(c"Method is not a valid UTF8".to_owned())),
339 };
340 request.method = method;
342 }
343
344 if let Some(init_signal) = init.signal.as_ref() {
346 signal = init_signal.clone();
347 }
348 let request = Request::from_net_request(cx, global, proto, request);
358
359 let signals = signal.map_or(vec![], |s| vec![s]);
361 request
364 .signal
365 .set(Some(&AbortSignal::create_dependent_abort_signal(
366 cx, signals, global,
367 )));
368
369 request
375 .headers
376 .or_init(|| Headers::for_request(cx, &request.global()));
377
378 let headers_copy = init
382 .headers
383 .as_ref()
384 .map(|possible_header| match possible_header {
385 HeadersInit::ByteStringSequenceSequence(init_sequence) => {
386 HeadersInit::ByteStringSequenceSequence(init_sequence.clone())
387 },
388 HeadersInit::ByteStringByteStringRecord(init_map) => {
389 HeadersInit::ByteStringByteStringRecord(init_map.clone())
390 },
391 });
392
393 if request.request.borrow().mode == NetTraitsRequestMode::NoCors {
404 let borrowed_request = request.request.borrow();
405 if !is_cors_safelisted_method(&borrowed_request.method) {
407 return Err(Error::Type(
408 c"The mode is 'no-cors' but the method is not a cors-safelisted method"
409 .to_owned(),
410 ));
411 }
412 request.Headers(cx).set_guard(Guard::RequestNoCors);
414 }
415
416 match headers_copy {
417 None => {
418 if let RequestInfo::Request(ref input_request) = input {
425 request
426 .Headers(cx)
427 .copy_from_headers(&input_request.Headers(cx))?;
428 }
429 },
430 Some(headers_copy) => request.Headers(cx).fill(Some(headers_copy))?,
432 }
433
434 request.request.borrow_mut().headers = request.Headers(cx).get_headers_list();
437
438 let input_body = if let RequestInfo::Request(ref mut input_request) = input {
440 let mut input_request_request = input_request.request.borrow_mut();
441 request.body_stream.set(input_request.body().as_deref());
442 input_request_request.body.take()
443 } else {
444 None
445 };
446
447 if init.body.as_ref().is_some_and(|body| body.is_some()) || input_body.is_some() {
450 let req = request.request.borrow();
451 let req_method = &req.method;
452 match *req_method {
453 HttpMethod::GET => {
454 return Err(Error::Type(
455 c"Init's body is non-null, and request method is GET".to_owned(),
456 ));
457 },
458 HttpMethod::HEAD => {
459 return Err(Error::Type(
460 c"Init's body is non-null, and request method is HEAD".to_owned(),
461 ));
462 },
463 _ => {},
464 }
465 }
466
467 let mut init_body = None;
469 if let Some(Some(ref input_init_body)) = init.body {
471 let mut body_with_type =
473 input_init_body.extract(cx, global, request.request.borrow().keep_alive)?;
474
475 if let Some(contents) = body_with_type.content_type.take() {
477 let content_type_header_name = b"Content-Type";
480 if !request
481 .Headers(cx)
482 .Has(ByteString::new(content_type_header_name.to_vec()))
483 .unwrap()
484 {
485 let content_type_header_value = contents.as_bytes();
486 request.Headers(cx).Append(
487 ByteString::new(content_type_header_name.to_vec()),
488 ByteString::new(content_type_header_value.to_vec()),
489 )?;
490
491 if let Ok(header_value) = HeaderValue::from_bytes(&content_type_header_value) {
495 request
496 .request
497 .borrow_mut()
498 .headers
499 .insert(CONTENT_TYPE, header_value);
500 }
501 }
502 }
503
504 let (net_body, stream) = body_with_type.into_net_request_body(cx);
506 request.body_stream.set(Some(&*stream));
507 init_body = Some(net_body);
508 }
509
510 let init_body_is_non_null = init_body.is_some();
517 let final_body = init_body.or(input_body);
518
519 if final_body
521 .as_ref()
522 .is_some_and(|body| body.source_is_null())
523 {
524 if init_body_is_non_null && init.duplex.is_none() {
527 return Err(Error::Type(
528 c"Request with a ReadableStream body must specify duplex".to_owned(),
529 ));
530 }
531 let request_mode = &request.request.borrow().mode;
533 if *request_mode != NetTraitsRequestMode::CorsMode &&
534 *request_mode != NetTraitsRequestMode::SameOrigin
535 {
536 return Err(Error::Type(
537 c"Request mode must be Cors or SameOrigin".to_owned(),
538 ));
539 }
540 }
543
544 if input_body_is_unusable {
551 return Err(Error::Type(c"Input body is unusable".to_owned()));
552 }
553
554 request.request.borrow_mut().body = final_body;
556
557 Ok(request)
558 }
559
560 fn clone_from(cx: &mut js::context::JSContext, r: &Request) -> Fallible<DomRoot<Request>> {
562 let req = r.request.borrow();
563 let url = req.url();
564 let headers_guard = r.Headers(cx).get_guard();
565
566 let mut new_req_inner = req.clone();
568 let body = new_req_inner.body.take();
569
570 let r_clone = Request::new(cx, &r.global(), None, url);
571 *r_clone.request.borrow_mut() = new_req_inner;
572
573 if let Some(body) = body {
576 r_clone.request.borrow_mut().body = Some(body);
577 }
578
579 r_clone.Headers(cx).copy_from_headers(&r.Headers(cx))?;
580 r_clone.Headers(cx).set_guard(headers_guard);
581
582 clone_body_stream_for_dom_body(cx, &r.body_stream, &r_clone.body_stream)?;
583
584 Ok(r_clone)
586 }
587
588 pub(crate) fn get_request(&self) -> NetTraitsRequest {
589 self.request.borrow().clone()
590 }
591}
592
593fn net_request_from_global(global: &GlobalScope, url: ServoUrl) -> NetTraitsRequest {
594 let url = ensure_blob_referenced_by_url_is_kept_alive(global, url);
595 RequestBuilder::new(global.webview_id(), url, global.get_referrer())
596 .with_global_scope(global)
597 .build()
598}
599
600fn normalize_method(m: &str) -> Result<HttpMethod, InvalidMethod> {
602 match_ignore_ascii_case! { m,
603 "delete" => return Ok(HttpMethod::DELETE),
604 "get" => return Ok(HttpMethod::GET),
605 "head" => return Ok(HttpMethod::HEAD),
606 "options" => return Ok(HttpMethod::OPTIONS),
607 "post" => return Ok(HttpMethod::POST),
608 "put" => return Ok(HttpMethod::PUT),
609 _ => (),
610 }
611 debug!("Method: {:?}", m);
612 HttpMethod::from_str(m)
613}
614
615fn is_method(m: &ByteString) -> bool {
617 m.as_str().is_some()
618}
619
620fn is_cors_safelisted_method(m: &HttpMethod) -> bool {
622 m == HttpMethod::GET || m == HttpMethod::HEAD || m == HttpMethod::POST
623}
624
625fn includes_credentials(input: &ServoUrl) -> bool {
627 !input.username().is_empty() || input.password().is_some()
628}
629
630impl RequestMethods<crate::DomTypeHolder> for Request {
631 fn Constructor(
633 cx: &mut js::context::JSContext,
634 global: &GlobalScope,
635 proto: Option<HandleObject>,
636 input: RequestInfo,
637 init: RootedTraceableBox<RequestInit>,
638 ) -> Fallible<DomRoot<Request>> {
639 Self::constructor(cx, global, proto, input, &init)
640 }
641
642 fn Method(&self) -> ByteString {
644 let r = self.request.borrow();
645 ByteString::new(r.method.as_ref().as_bytes().into())
646 }
647
648 fn Url(&self) -> USVString {
650 let r = self.request.borrow();
651 USVString(r.url_list.first().map_or("", |u| u.as_str()).into())
652 }
653
654 fn Headers(&self, cx: &mut js::context::JSContext) -> DomRoot<Headers> {
656 self.headers.or_init(|| Headers::new(cx, &self.global()))
657 }
658
659 fn Destination(&self) -> RequestDestination {
661 self.request.borrow().destination.convert()
662 }
663
664 fn Referrer(&self) -> USVString {
666 let r = self.request.borrow();
667 USVString(match r.referrer {
668 Referrer::NoReferrer => String::from(""),
669 Referrer::Client(_) => String::from("about:client"),
670 Referrer::ReferrerUrl(ref u) => {
671 let u_c = u.clone();
672 u_c.into_string()
673 },
674 })
675 }
676
677 fn ReferrerPolicy(&self) -> ReferrerPolicy {
679 self.request.borrow().referrer_policy.convert()
680 }
681
682 fn Mode(&self) -> RequestMode {
684 self.request.borrow().mode.clone().convert()
685 }
686
687 fn Credentials(&self) -> RequestCredentials {
689 let r = self.request.borrow().clone();
690 r.credentials_mode.convert()
691 }
692
693 fn Cache(&self) -> RequestCache {
695 let r = self.request.borrow().clone();
696 r.cache_mode.convert()
697 }
698
699 fn Redirect(&self) -> RequestRedirect {
701 let r = self.request.borrow().clone();
702 r.redirect_mode.convert()
703 }
704
705 fn Integrity(&self) -> DOMString {
707 self.request.borrow().integrity_metadata.clone().into()
708 }
709
710 fn Duplex(&self) -> RequestDuplex {
712 RequestDuplex::Half
714 }
715
716 fn Keepalive(&self) -> bool {
718 self.request.borrow().keep_alive
719 }
720
721 fn IsReloadNavigation(&self) -> bool {
724 self.request.borrow().reload_navigation
725 }
726
727 fn IsHistoryNavigation(&self) -> bool {
730 self.request.borrow().history_navigation
731 }
732
733 fn GetBody(&self) -> Option<DomRoot<ReadableStream>> {
735 self.body()
736 }
737
738 fn BodyUsed(&self) -> bool {
740 self.is_body_used()
741 }
742
743 fn Signal(&self) -> DomRoot<AbortSignal> {
745 self.signal
746 .get()
747 .expect("Should always be initialized in constructor and clone")
748 }
749
750 fn Clone(&self, cx: &mut js::context::JSContext) -> Fallible<DomRoot<Request>> {
752 if self.is_unusable() {
754 return Err(Error::Type(c"Request is unusable".to_owned()));
755 }
756
757 let cloned_request = Request::clone_from(cx, self)?;
759 let signal = self.signal.get().expect("Should always be initialized");
761 let cloned_signal =
764 AbortSignal::create_dependent_abort_signal(cx, vec![signal], &self.global());
765 cloned_request.signal.set(Some(&cloned_signal));
770 Ok(cloned_request)
772 }
773
774 fn Text(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
776 consume_body(cx, self, BodyType::Text)
777 }
778
779 fn Blob(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
781 consume_body(cx, self, BodyType::Blob)
782 }
783
784 fn FormData(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
786 consume_body(cx, self, BodyType::FormData)
787 }
788
789 fn Json(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
791 consume_body(cx, self, BodyType::Json)
792 }
793
794 fn ArrayBuffer(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
796 consume_body(cx, self, BodyType::ArrayBuffer)
797 }
798
799 fn Bytes(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
801 consume_body(cx, self, BodyType::Bytes)
802 }
803
804 fn TextStream(&self, cx: &mut js::context::JSContext) -> Fallible<DomRoot<ReadableStream>> {
806 body_text_stream(cx, self)
807 }
808}
809
810impl BodyMixin for Request {
811 fn is_body_used(&self) -> bool {
812 let body_stream = self.body_stream.get();
813 body_stream
814 .as_ref()
815 .is_some_and(|stream| stream.is_disturbed())
816 }
817
818 fn is_unusable(&self) -> bool {
819 let body_stream = self.body_stream.get();
820 body_stream
821 .as_ref()
822 .is_some_and(|stream| stream.is_disturbed() || stream.is_locked())
823 }
824
825 fn body(&self) -> Option<DomRoot<ReadableStream>> {
826 self.body_stream.get()
827 }
828
829 fn get_mime_type(&self, cx: &mut js::context::JSContext) -> Vec<u8> {
830 let headers = self.Headers(cx);
831 headers.extract_mime_type()
832 }
833}
834
835impl Convert<CacheMode> for RequestCache {
836 fn convert(self) -> CacheMode {
837 match self {
838 RequestCache::Default => CacheMode::Default,
839 RequestCache::No_store => CacheMode::NoStore,
840 RequestCache::Reload => CacheMode::Reload,
841 RequestCache::No_cache => CacheMode::NoCache,
842 RequestCache::Force_cache => CacheMode::ForceCache,
843 RequestCache::Only_if_cached => CacheMode::OnlyIfCached,
844 }
845 }
846}
847
848impl Convert<RequestCache> for CacheMode {
849 fn convert(self) -> RequestCache {
850 match self {
851 CacheMode::Default => RequestCache::Default,
852 CacheMode::NoStore => RequestCache::No_store,
853 CacheMode::Reload => RequestCache::Reload,
854 CacheMode::NoCache => RequestCache::No_cache,
855 CacheMode::ForceCache => RequestCache::Force_cache,
856 CacheMode::OnlyIfCached => RequestCache::Only_if_cached,
857 }
858 }
859}
860
861impl Convert<CredentialsMode> for RequestCredentials {
862 fn convert(self) -> CredentialsMode {
863 match self {
864 RequestCredentials::Omit => CredentialsMode::Omit,
865 RequestCredentials::Same_origin => CredentialsMode::CredentialsSameOrigin,
866 RequestCredentials::Include => CredentialsMode::Include,
867 }
868 }
869}
870
871impl Convert<RequestCredentials> for CredentialsMode {
872 fn convert(self) -> RequestCredentials {
873 match self {
874 CredentialsMode::Omit => RequestCredentials::Omit,
875 CredentialsMode::CredentialsSameOrigin => RequestCredentials::Same_origin,
876 CredentialsMode::Include => RequestCredentials::Include,
877 }
878 }
879}
880
881impl Convert<Destination> for RequestDestination {
882 fn convert(self) -> Destination {
883 match self {
884 RequestDestination::_empty => Destination::None,
885 RequestDestination::Audio => Destination::Audio,
886 RequestDestination::Document => Destination::Document,
887 RequestDestination::Embed => Destination::Embed,
888 RequestDestination::Font => Destination::Font,
889 RequestDestination::Frame => Destination::Frame,
890 RequestDestination::Iframe => Destination::IFrame,
891 RequestDestination::Image => Destination::Image,
892 RequestDestination::Manifest => Destination::Manifest,
893 RequestDestination::Json => Destination::Json,
894 RequestDestination::Object => Destination::Object,
895 RequestDestination::Report => Destination::Report,
896 RequestDestination::Script => Destination::Script,
897 RequestDestination::Sharedworker => Destination::SharedWorker,
898 RequestDestination::Style => Destination::Style,
899 RequestDestination::Track => Destination::Track,
900 RequestDestination::Video => Destination::Video,
901 RequestDestination::Worker => Destination::Worker,
902 RequestDestination::Xslt => Destination::Xslt,
903 }
904 }
905}
906
907impl Convert<RequestDestination> for Destination {
908 fn convert(self) -> RequestDestination {
909 match self {
910 Destination::None => RequestDestination::_empty,
911 Destination::Audio => RequestDestination::Audio,
912 Destination::Document => RequestDestination::Document,
913 Destination::Embed => RequestDestination::Embed,
914 Destination::Font => RequestDestination::Font,
915 Destination::Frame => RequestDestination::Frame,
916 Destination::IFrame => RequestDestination::Iframe,
917 Destination::Image => RequestDestination::Image,
918 Destination::Manifest => RequestDestination::Manifest,
919 Destination::Json => RequestDestination::Json,
920 Destination::Object => RequestDestination::Object,
921 Destination::Report => RequestDestination::Report,
922 Destination::Script => RequestDestination::Script,
923 Destination::ServiceWorker | Destination::AudioWorklet | Destination::PaintWorklet => {
924 panic!("ServiceWorker request destination should not be exposed to DOM")
925 },
926 Destination::SharedWorker => RequestDestination::Sharedworker,
927 Destination::Style => RequestDestination::Style,
928 Destination::Track => RequestDestination::Track,
929 Destination::Video => RequestDestination::Video,
930 Destination::Worker => RequestDestination::Worker,
931 Destination::Xslt => RequestDestination::Xslt,
932 Destination::WebIdentity => RequestDestination::_empty,
933 }
934 }
935}
936
937impl Convert<NetTraitsRequestMode> for RequestMode {
938 fn convert(self) -> NetTraitsRequestMode {
939 match self {
940 RequestMode::Navigate => NetTraitsRequestMode::Navigate,
941 RequestMode::Same_origin => NetTraitsRequestMode::SameOrigin,
942 RequestMode::No_cors => NetTraitsRequestMode::NoCors,
943 RequestMode::Cors => NetTraitsRequestMode::CorsMode,
944 }
945 }
946}
947
948impl Convert<RequestMode> for NetTraitsRequestMode {
949 fn convert(self) -> RequestMode {
950 match self {
951 NetTraitsRequestMode::Navigate => RequestMode::Navigate,
952 NetTraitsRequestMode::SameOrigin => RequestMode::Same_origin,
953 NetTraitsRequestMode::NoCors => RequestMode::No_cors,
954 NetTraitsRequestMode::CorsMode => RequestMode::Cors,
955 NetTraitsRequestMode::WebSocket { .. } => {
956 unreachable!("Websocket request mode should never be exposed to Dom")
957 },
958 }
959 }
960}
961
962impl Convert<MsgReferrerPolicy> for ReferrerPolicy {
963 fn convert(self) -> MsgReferrerPolicy {
964 match self {
965 ReferrerPolicy::_empty => MsgReferrerPolicy::EmptyString,
966 ReferrerPolicy::No_referrer => MsgReferrerPolicy::NoReferrer,
967 ReferrerPolicy::No_referrer_when_downgrade => {
968 MsgReferrerPolicy::NoReferrerWhenDowngrade
969 },
970 ReferrerPolicy::Origin => MsgReferrerPolicy::Origin,
971 ReferrerPolicy::Origin_when_cross_origin => MsgReferrerPolicy::OriginWhenCrossOrigin,
972 ReferrerPolicy::Unsafe_url => MsgReferrerPolicy::UnsafeUrl,
973 ReferrerPolicy::Same_origin => MsgReferrerPolicy::SameOrigin,
974 ReferrerPolicy::Strict_origin => MsgReferrerPolicy::StrictOrigin,
975 ReferrerPolicy::Strict_origin_when_cross_origin => {
976 MsgReferrerPolicy::StrictOriginWhenCrossOrigin
977 },
978 }
979 }
980}
981
982impl Convert<ReferrerPolicy> for MsgReferrerPolicy {
983 fn convert(self) -> ReferrerPolicy {
984 match self {
985 MsgReferrerPolicy::EmptyString => ReferrerPolicy::_empty,
986 MsgReferrerPolicy::NoReferrer => ReferrerPolicy::No_referrer,
987 MsgReferrerPolicy::NoReferrerWhenDowngrade => {
988 ReferrerPolicy::No_referrer_when_downgrade
989 },
990 MsgReferrerPolicy::Origin => ReferrerPolicy::Origin,
991 MsgReferrerPolicy::OriginWhenCrossOrigin => ReferrerPolicy::Origin_when_cross_origin,
992 MsgReferrerPolicy::UnsafeUrl => ReferrerPolicy::Unsafe_url,
993 MsgReferrerPolicy::SameOrigin => ReferrerPolicy::Same_origin,
994 MsgReferrerPolicy::StrictOrigin => ReferrerPolicy::Strict_origin,
995 MsgReferrerPolicy::StrictOriginWhenCrossOrigin => {
996 ReferrerPolicy::Strict_origin_when_cross_origin
997 },
998 }
999 }
1000}
1001
1002impl Convert<RedirectMode> for RequestRedirect {
1003 fn convert(self) -> RedirectMode {
1004 match self {
1005 RequestRedirect::Follow => RedirectMode::Follow,
1006 RequestRedirect::Error => RedirectMode::Error,
1007 RequestRedirect::Manual => RedirectMode::Manual,
1008 }
1009 }
1010}
1011
1012impl Convert<RequestRedirect> for RedirectMode {
1013 fn convert(self) -> RequestRedirect {
1014 match self {
1015 RedirectMode::Follow => RequestRedirect::Follow,
1016 RedirectMode::Error => RequestRedirect::Error,
1017 RedirectMode::Manual => RequestRedirect::Manual,
1018 }
1019 }
1020}