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::{BodyMixin, BodyType, Extractable, clone_body_stream_for_dom_body, consume_body};
27use crate::conversions::Convert;
28use crate::dom::abortsignal::AbortSignal;
29use crate::dom::bindings::codegen::Bindings::HeadersBinding::{HeadersInit, HeadersMethods};
30use crate::dom::bindings::codegen::Bindings::RequestBinding::{
31 ReferrerPolicy, RequestCache, RequestCredentials, RequestDestination, RequestInfo, RequestInit,
32 RequestMethods, RequestMode, RequestRedirect,
33};
34use crate::dom::bindings::error::{Error, Fallible};
35use crate::dom::bindings::reflector::DomGlobal;
36use crate::dom::bindings::root::{DomRoot, MutNullableDom};
37use crate::dom::bindings::str::{ByteString, DOMString, USVString};
38use crate::dom::bindings::trace::RootedTraceableBox;
39use crate::dom::globalscope::GlobalScope;
40use crate::dom::headers::{Guard, Headers};
41use crate::dom::promise::Promise;
42use crate::dom::stream::readablestream::ReadableStream;
43use crate::fetch::RequestWithGlobalScope;
44use crate::script_runtime::CanGc;
45use crate::url::ensure_blob_referenced_by_url_is_kept_alive;
46
47#[dom_struct]
48pub(crate) struct Request {
49 reflector_: Reflector,
50 #[no_trace]
51 request: DomRefCell<NetTraitsRequest>,
53 body_stream: MutNullableDom<ReadableStream>,
55 headers: MutNullableDom<Headers>,
57 signal: MutNullableDom<AbortSignal>,
59}
60
61impl Request {
62 fn new_inherited(global: &GlobalScope, url: ServoUrl) -> Request {
63 Request {
64 reflector_: Reflector::new(),
65 request: DomRefCell::new(net_request_from_global(global, url)),
66 body_stream: MutNullableDom::new(None),
67 headers: Default::default(),
68 signal: MutNullableDom::new(None),
69 }
70 }
71
72 fn new(
73 global: &GlobalScope,
74 proto: Option<HandleObject>,
75 url: ServoUrl,
76 can_gc: CanGc,
77 ) -> DomRoot<Request> {
78 reflect_dom_object_with_proto(
79 Box::new(Request::new_inherited(global, url)),
80 global,
81 proto,
82 can_gc,
83 )
84 }
85
86 fn from_net_request(
87 global: &GlobalScope,
88 proto: Option<HandleObject>,
89 net_request: NetTraitsRequest,
90 can_gc: CanGc,
91 ) -> DomRoot<Request> {
92 let r = Request::new(global, proto, net_request.current_url(), can_gc);
93 *r.request.borrow_mut() = net_request;
94 r
95 }
96
97 pub(crate) fn constructor(
99 cx: &mut js::context::JSContext,
100 global: &GlobalScope,
101 proto: Option<HandleObject>,
102 mut input: RequestInfo,
103 init: &RequestInit,
104 ) -> Fallible<DomRoot<Request>> {
105 let temporary_request: NetTraitsRequest;
107
108 let mut fallback_mode: Option<NetTraitsRequestMode> = None;
110
111 let base_url = global.api_base_url();
113
114 let mut signal: Option<DomRoot<AbortSignal>> = None;
116
117 let mut input_body_is_unusable = false;
119
120 match input {
121 RequestInfo::USVString(USVString(ref usv_string)) => {
123 let parsed_url = base_url.join(usv_string);
125 if parsed_url.is_err() {
127 return Err(Error::Type(c"Url could not be parsed".to_owned()));
128 }
129 let url = parsed_url.unwrap();
131 if includes_credentials(&url) {
132 return Err(Error::Type(c"Url includes credentials".to_owned()));
133 }
134 temporary_request = net_request_from_global(global, url);
136 fallback_mode = Some(NetTraitsRequestMode::CorsMode);
138 },
139 RequestInfo::Request(ref input_request) => {
142 input_body_is_unusable = input_request.is_unusable();
144 temporary_request = input_request.request.borrow().clone();
146 signal = Some(input_request.Signal());
148 },
149 }
150
151 let origin = global.origin().immutable();
153
154 let mut traversable_for_user_prompts = TraversableForUserPrompts::Client;
156
157 if !init.window.handle().is_null_or_undefined() {
164 return Err(Error::Type(c"Window is present and is not null".to_owned()));
165 }
166
167 if !init.window.handle().is_undefined() {
169 traversable_for_user_prompts = TraversableForUserPrompts::NoTraversable;
170 }
171
172 let mut request: NetTraitsRequest;
174 request = net_request_from_global(global, temporary_request.current_url());
175 request.method = temporary_request.method;
176 request.headers = temporary_request.headers.clone();
177 request.unsafe_request = true;
178 request.traversable_for_user_prompts = traversable_for_user_prompts;
179 request.origin = Origin::Client;
181 request.referrer = temporary_request.referrer;
182 request.referrer_policy = temporary_request.referrer_policy;
183 request.mode = temporary_request.mode;
184 request.credentials_mode = temporary_request.credentials_mode;
185 request.cache_mode = temporary_request.cache_mode;
186 request.redirect_mode = temporary_request.redirect_mode;
187 request.integrity_metadata = temporary_request.integrity_metadata;
188
189 if init.body.is_some() ||
191 init.cache.is_some() ||
192 init.credentials.is_some() ||
193 init.integrity.is_some() ||
194 init.headers.is_some() ||
195 init.keepalive.is_some() ||
196 init.method.is_some() ||
197 init.mode.is_some() ||
198 init.redirect.is_some() ||
199 init.referrer.is_some() ||
200 init.referrerPolicy.is_some() ||
201 !init.window.handle().is_undefined()
202 {
203 if request.mode == NetTraitsRequestMode::Navigate {
205 request.mode = NetTraitsRequestMode::SameOrigin;
206 }
207 request.referrer = global.get_referrer();
215 request.referrer_policy = MsgReferrerPolicy::EmptyString;
217 }
222
223 if let Some(init_referrer) = init.referrer.as_ref() {
225 let referrer = &init_referrer.0;
227 if referrer.is_empty() {
229 request.referrer = Referrer::NoReferrer;
230 } else {
232 let parsed_referrer = base_url.join(referrer);
234 if parsed_referrer.is_err() {
236 return Err(Error::Type(c"Failed to parse referrer url".to_owned()));
237 }
238 if let Ok(parsed_referrer) = parsed_referrer {
242 if (parsed_referrer.cannot_be_a_base() &&
243 parsed_referrer.scheme() == "about" &&
244 parsed_referrer.path() == "client") ||
245 parsed_referrer.origin() != *origin
246 {
247 request.referrer = global.get_referrer();
249 } else {
250 request.referrer = Referrer::ReferrerUrl(parsed_referrer);
252 }
253 }
254 }
255 }
256
257 if let Some(init_referrerpolicy) = init.referrerPolicy.as_ref() {
259 let init_referrer_policy = (*init_referrerpolicy).convert();
260 request.referrer_policy = init_referrer_policy;
261 }
262
263 let mode = init.mode.as_ref().map(|m| (*m).convert()).or(fallback_mode);
265
266 if let Some(NetTraitsRequestMode::Navigate) = mode {
268 return Err(Error::Type(c"Request mode is Navigate".to_owned()));
269 }
270
271 if let Some(m) = mode {
273 request.mode = m;
274 }
275
276 if let Some(init_credentials) = init.credentials.as_ref() {
278 let credentials = (*init_credentials).convert();
279 request.credentials_mode = credentials;
280 }
281
282 if let Some(init_cache) = init.cache.as_ref() {
284 let cache = (*init_cache).convert();
285 request.cache_mode = cache;
286 }
287
288 if request.cache_mode == CacheMode::OnlyIfCached &&
291 request.mode != NetTraitsRequestMode::SameOrigin
292 {
293 return Err(Error::Type(
294 c"Cache is 'only-if-cached' and mode is not 'same-origin'".to_owned(),
295 ));
296 }
297
298 if let Some(init_redirect) = init.redirect.as_ref() {
300 let redirect = (*init_redirect).convert();
301 request.redirect_mode = redirect;
302 }
303
304 if let Some(init_integrity) = init.integrity.as_ref() {
306 let integrity = init_integrity.clone().to_string();
307 request.integrity_metadata = integrity;
308 }
309
310 if let Some(init_keepalive) = init.keepalive {
312 request.keep_alive = init_keepalive;
313 }
314
315 if let Some(init_method) = init.method.as_ref() {
318 if !is_method(init_method) {
320 return Err(Error::Type(c"Method is not a method".to_owned()));
321 }
322 if is_forbidden_method(init_method) {
323 return Err(Error::Type(c"Method is forbidden".to_owned()));
324 }
325 let method = match init_method.as_str() {
327 Some(s) => normalize_method(s)
328 .map_err(|e| Error::Type(cformat!("Method is not valid: {:?}", e)))?,
329 None => return Err(Error::Type(c"Method is not a valid UTF8".to_owned())),
330 };
331 request.method = method;
333 }
334
335 if let Some(init_signal) = init.signal.as_ref() {
337 signal = init_signal.clone();
338 }
339 let r = Request::from_net_request(global, proto, request, CanGc::from_cx(cx));
349
350 let signals = signal.map_or(vec![], |s| vec![s]);
352 r.signal
355 .set(Some(&AbortSignal::create_dependent_abort_signal(
356 signals,
357 global,
358 CanGc::from_cx(cx),
359 )));
360
361 r.headers
367 .or_init(|| Headers::for_request(&r.global(), CanGc::from_cx(cx)));
368
369 let headers_copy = init
373 .headers
374 .as_ref()
375 .map(|possible_header| match possible_header {
376 HeadersInit::ByteStringSequenceSequence(init_sequence) => {
377 HeadersInit::ByteStringSequenceSequence(init_sequence.clone())
378 },
379 HeadersInit::ByteStringByteStringRecord(init_map) => {
380 HeadersInit::ByteStringByteStringRecord(init_map.clone())
381 },
382 });
383
384 if r.request.borrow().mode == NetTraitsRequestMode::NoCors {
395 let borrowed_request = r.request.borrow();
396 if !is_cors_safelisted_method(&borrowed_request.method) {
398 return Err(Error::Type(
399 c"The mode is 'no-cors' but the method is not a cors-safelisted method"
400 .to_owned(),
401 ));
402 }
403 r.Headers(cx).set_guard(Guard::RequestNoCors);
405 }
406
407 match headers_copy {
408 None => {
409 if let RequestInfo::Request(ref input_request) = input {
416 r.Headers(cx).copy_from_headers(input_request.Headers(cx))?;
417 }
418 },
419 Some(headers_copy) => r.Headers(cx).fill(Some(headers_copy))?,
421 }
422
423 r.request.borrow_mut().headers = r.Headers(cx).get_headers_list();
426
427 let input_body = if let RequestInfo::Request(ref mut input_request) = input {
429 let mut input_request_request = input_request.request.borrow_mut();
430 r.body_stream.set(input_request.body().as_deref());
431 input_request_request.body.take()
432 } else {
433 None
434 };
435
436 if init.body.as_ref().is_some_and(|body| body.is_some()) || input_body.is_some() {
439 let req = r.request.borrow();
440 let req_method = &req.method;
441 match *req_method {
442 HttpMethod::GET => {
443 return Err(Error::Type(
444 c"Init's body is non-null, and request method is GET".to_owned(),
445 ));
446 },
447 HttpMethod::HEAD => {
448 return Err(Error::Type(
449 c"Init's body is non-null, and request method is HEAD".to_owned(),
450 ));
451 },
452 _ => {},
453 }
454 }
455
456 let mut init_body = None;
458 if let Some(Some(ref input_init_body)) = init.body {
460 let mut body_with_type =
462 input_init_body.extract(cx, global, r.request.borrow().keep_alive)?;
463
464 if let Some(contents) = body_with_type.content_type.take() {
466 let ct_header_name = b"Content-Type";
467 if !r
470 .Headers(cx)
471 .Has(ByteString::new(ct_header_name.to_vec()))
472 .unwrap()
473 {
474 let ct_header_val = contents.as_bytes();
475 r.Headers(cx).Append(
476 ByteString::new(ct_header_name.to_vec()),
477 ByteString::new(ct_header_val.to_vec()),
478 )?;
479
480 if let Ok(v) = HeaderValue::from_bytes(&ct_header_val) {
484 r.request
485 .borrow_mut()
486 .headers
487 .insert(HeaderName::from_bytes(ct_header_name).unwrap(), v);
488 }
489 }
490 }
491
492 let (net_body, stream) = body_with_type.into_net_request_body();
494 r.body_stream.set(Some(&*stream));
495 init_body = Some(net_body);
496 }
497
498 let final_body = init_body.or(input_body);
505
506 if final_body
508 .as_ref()
509 .is_some_and(|body| body.source_is_null())
510 {
511 let request_mode = &r.request.borrow().mode;
515 if *request_mode != NetTraitsRequestMode::CorsMode &&
516 *request_mode != NetTraitsRequestMode::SameOrigin
517 {
518 return Err(Error::Type(
519 c"Request mode must be Cors or SameOrigin".to_owned(),
520 ));
521 }
522 }
525
526 if input_body_is_unusable {
533 return Err(Error::Type(c"Input body is unusable".to_owned()));
534 }
535
536 r.request.borrow_mut().body = final_body;
538
539 Ok(r)
540 }
541
542 fn clone_from(cx: &mut js::context::JSContext, r: &Request) -> Fallible<DomRoot<Request>> {
544 let req = r.request.borrow();
545 let url = req.url();
546 let headers_guard = r.Headers(cx).get_guard();
547
548 let mut new_req_inner = req.clone();
550 let body = new_req_inner.body.take();
551
552 let r_clone = Request::new(&r.global(), None, url, CanGc::from_cx(cx));
553 *r_clone.request.borrow_mut() = new_req_inner;
554
555 if let Some(body) = body {
558 r_clone.request.borrow_mut().body = Some(body);
559 }
560
561 r_clone.Headers(cx).copy_from_headers(r.Headers(cx))?;
562 r_clone.Headers(cx).set_guard(headers_guard);
563
564 clone_body_stream_for_dom_body(cx, &r.body_stream, &r_clone.body_stream)?;
565
566 Ok(r_clone)
568 }
569
570 pub(crate) fn get_request(&self) -> NetTraitsRequest {
571 self.request.borrow().clone()
572 }
573}
574
575fn net_request_from_global(global: &GlobalScope, url: ServoUrl) -> NetTraitsRequest {
576 let url = ensure_blob_referenced_by_url_is_kept_alive(global, url);
577 RequestBuilder::new(global.webview_id(), url, global.get_referrer())
578 .with_global_scope(global)
579 .build()
580}
581
582fn normalize_method(m: &str) -> Result<HttpMethod, InvalidMethod> {
584 match_ignore_ascii_case! { m,
585 "delete" => return Ok(HttpMethod::DELETE),
586 "get" => return Ok(HttpMethod::GET),
587 "head" => return Ok(HttpMethod::HEAD),
588 "options" => return Ok(HttpMethod::OPTIONS),
589 "post" => return Ok(HttpMethod::POST),
590 "put" => return Ok(HttpMethod::PUT),
591 _ => (),
592 }
593 debug!("Method: {:?}", m);
594 HttpMethod::from_str(m)
595}
596
597fn is_method(m: &ByteString) -> bool {
599 m.as_str().is_some()
600}
601
602fn is_cors_safelisted_method(m: &HttpMethod) -> bool {
604 m == HttpMethod::GET || m == HttpMethod::HEAD || m == HttpMethod::POST
605}
606
607fn includes_credentials(input: &ServoUrl) -> bool {
609 !input.username().is_empty() || input.password().is_some()
610}
611
612impl RequestMethods<crate::DomTypeHolder> for Request {
613 fn Constructor(
615 cx: &mut js::context::JSContext,
616 global: &GlobalScope,
617 proto: Option<HandleObject>,
618 input: RequestInfo,
619 init: RootedTraceableBox<RequestInit>,
620 ) -> Fallible<DomRoot<Request>> {
621 Self::constructor(cx, global, proto, input, &init)
622 }
623
624 fn Method(&self) -> ByteString {
626 let r = self.request.borrow();
627 ByteString::new(r.method.as_ref().as_bytes().into())
628 }
629
630 fn Url(&self) -> USVString {
632 let r = self.request.borrow();
633 USVString(r.url_list.first().map_or("", |u| u.as_str()).into())
634 }
635
636 fn Headers(&self, cx: &mut js::context::JSContext) -> DomRoot<Headers> {
638 self.headers
639 .or_init(|| Headers::new(&self.global(), CanGc::from_cx(cx)))
640 }
641
642 fn Destination(&self) -> RequestDestination {
644 self.request.borrow().destination.convert()
645 }
646
647 fn Referrer(&self) -> USVString {
649 let r = self.request.borrow();
650 USVString(match r.referrer {
651 Referrer::NoReferrer => String::from(""),
652 Referrer::Client(_) => String::from("about:client"),
653 Referrer::ReferrerUrl(ref u) => {
654 let u_c = u.clone();
655 u_c.into_string()
656 },
657 })
658 }
659
660 fn ReferrerPolicy(&self) -> ReferrerPolicy {
662 self.request.borrow().referrer_policy.convert()
663 }
664
665 fn Mode(&self) -> RequestMode {
667 self.request.borrow().mode.clone().convert()
668 }
669
670 fn Credentials(&self) -> RequestCredentials {
672 let r = self.request.borrow().clone();
673 r.credentials_mode.convert()
674 }
675
676 fn Cache(&self) -> RequestCache {
678 let r = self.request.borrow().clone();
679 r.cache_mode.convert()
680 }
681
682 fn Redirect(&self) -> RequestRedirect {
684 let r = self.request.borrow().clone();
685 r.redirect_mode.convert()
686 }
687
688 fn Integrity(&self) -> DOMString {
690 self.request.borrow().integrity_metadata.clone().into()
691 }
692
693 fn Keepalive(&self) -> bool {
695 self.request.borrow().keep_alive
696 }
697
698 fn GetBody(&self) -> Option<DomRoot<ReadableStream>> {
700 self.body()
701 }
702
703 fn BodyUsed(&self) -> bool {
705 self.is_body_used()
706 }
707
708 fn Signal(&self) -> DomRoot<AbortSignal> {
710 self.signal
711 .get()
712 .expect("Should always be initialized in constructor and clone")
713 }
714
715 fn Clone(&self, cx: &mut js::context::JSContext) -> Fallible<DomRoot<Request>> {
717 if self.is_unusable() {
719 return Err(Error::Type(c"Request is unusable".to_owned()));
720 }
721
722 let cloned_request = Request::clone_from(cx, self)?;
724 let signal = self.signal.get().expect("Should always be initialized");
726 let cloned_signal = AbortSignal::create_dependent_abort_signal(
729 vec![signal],
730 &self.global(),
731 CanGc::from_cx(cx),
732 );
733 cloned_request.signal.set(Some(&cloned_signal));
738 Ok(cloned_request)
740 }
741
742 fn Text(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
744 consume_body(cx, self, BodyType::Text)
745 }
746
747 fn Blob(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
749 consume_body(cx, self, BodyType::Blob)
750 }
751
752 fn FormData(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
754 consume_body(cx, self, BodyType::FormData)
755 }
756
757 fn Json(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
759 consume_body(cx, self, BodyType::Json)
760 }
761
762 fn ArrayBuffer(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
764 consume_body(cx, self, BodyType::ArrayBuffer)
765 }
766
767 fn Bytes(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
769 consume_body(cx, self, BodyType::Bytes)
770 }
771}
772
773impl BodyMixin for Request {
774 fn is_body_used(&self) -> bool {
775 let body_stream = self.body_stream.get();
776 body_stream
777 .as_ref()
778 .is_some_and(|stream| stream.is_disturbed())
779 }
780
781 fn is_unusable(&self) -> bool {
782 let body_stream = self.body_stream.get();
783 body_stream
784 .as_ref()
785 .is_some_and(|stream| stream.is_disturbed() || stream.is_locked())
786 }
787
788 fn body(&self) -> Option<DomRoot<ReadableStream>> {
789 self.body_stream.get()
790 }
791
792 fn get_mime_type(&self, cx: &mut js::context::JSContext) -> Vec<u8> {
793 let headers = self.Headers(cx);
794 headers.extract_mime_type()
795 }
796}
797
798impl Convert<CacheMode> for RequestCache {
799 fn convert(self) -> CacheMode {
800 match self {
801 RequestCache::Default => CacheMode::Default,
802 RequestCache::No_store => CacheMode::NoStore,
803 RequestCache::Reload => CacheMode::Reload,
804 RequestCache::No_cache => CacheMode::NoCache,
805 RequestCache::Force_cache => CacheMode::ForceCache,
806 RequestCache::Only_if_cached => CacheMode::OnlyIfCached,
807 }
808 }
809}
810
811impl Convert<RequestCache> for CacheMode {
812 fn convert(self) -> RequestCache {
813 match self {
814 CacheMode::Default => RequestCache::Default,
815 CacheMode::NoStore => RequestCache::No_store,
816 CacheMode::Reload => RequestCache::Reload,
817 CacheMode::NoCache => RequestCache::No_cache,
818 CacheMode::ForceCache => RequestCache::Force_cache,
819 CacheMode::OnlyIfCached => RequestCache::Only_if_cached,
820 }
821 }
822}
823
824impl Convert<CredentialsMode> for RequestCredentials {
825 fn convert(self) -> CredentialsMode {
826 match self {
827 RequestCredentials::Omit => CredentialsMode::Omit,
828 RequestCredentials::Same_origin => CredentialsMode::CredentialsSameOrigin,
829 RequestCredentials::Include => CredentialsMode::Include,
830 }
831 }
832}
833
834impl Convert<RequestCredentials> for CredentialsMode {
835 fn convert(self) -> RequestCredentials {
836 match self {
837 CredentialsMode::Omit => RequestCredentials::Omit,
838 CredentialsMode::CredentialsSameOrigin => RequestCredentials::Same_origin,
839 CredentialsMode::Include => RequestCredentials::Include,
840 }
841 }
842}
843
844impl Convert<Destination> for RequestDestination {
845 fn convert(self) -> Destination {
846 match self {
847 RequestDestination::_empty => Destination::None,
848 RequestDestination::Audio => Destination::Audio,
849 RequestDestination::Document => Destination::Document,
850 RequestDestination::Embed => Destination::Embed,
851 RequestDestination::Font => Destination::Font,
852 RequestDestination::Frame => Destination::Frame,
853 RequestDestination::Iframe => Destination::IFrame,
854 RequestDestination::Image => Destination::Image,
855 RequestDestination::Manifest => Destination::Manifest,
856 RequestDestination::Json => Destination::Json,
857 RequestDestination::Object => Destination::Object,
858 RequestDestination::Report => Destination::Report,
859 RequestDestination::Script => Destination::Script,
860 RequestDestination::Sharedworker => Destination::SharedWorker,
861 RequestDestination::Style => Destination::Style,
862 RequestDestination::Track => Destination::Track,
863 RequestDestination::Video => Destination::Video,
864 RequestDestination::Worker => Destination::Worker,
865 RequestDestination::Xslt => Destination::Xslt,
866 }
867 }
868}
869
870impl Convert<RequestDestination> for Destination {
871 fn convert(self) -> RequestDestination {
872 match self {
873 Destination::None => RequestDestination::_empty,
874 Destination::Audio => RequestDestination::Audio,
875 Destination::Document => RequestDestination::Document,
876 Destination::Embed => RequestDestination::Embed,
877 Destination::Font => RequestDestination::Font,
878 Destination::Frame => RequestDestination::Frame,
879 Destination::IFrame => RequestDestination::Iframe,
880 Destination::Image => RequestDestination::Image,
881 Destination::Manifest => RequestDestination::Manifest,
882 Destination::Json => RequestDestination::Json,
883 Destination::Object => RequestDestination::Object,
884 Destination::Report => RequestDestination::Report,
885 Destination::Script => RequestDestination::Script,
886 Destination::ServiceWorker | Destination::AudioWorklet | Destination::PaintWorklet => {
887 panic!("ServiceWorker request destination should not be exposed to DOM")
888 },
889 Destination::SharedWorker => RequestDestination::Sharedworker,
890 Destination::Style => RequestDestination::Style,
891 Destination::Track => RequestDestination::Track,
892 Destination::Video => RequestDestination::Video,
893 Destination::Worker => RequestDestination::Worker,
894 Destination::Xslt => RequestDestination::Xslt,
895 Destination::WebIdentity => RequestDestination::_empty,
896 }
897 }
898}
899
900impl Convert<NetTraitsRequestMode> for RequestMode {
901 fn convert(self) -> NetTraitsRequestMode {
902 match self {
903 RequestMode::Navigate => NetTraitsRequestMode::Navigate,
904 RequestMode::Same_origin => NetTraitsRequestMode::SameOrigin,
905 RequestMode::No_cors => NetTraitsRequestMode::NoCors,
906 RequestMode::Cors => NetTraitsRequestMode::CorsMode,
907 }
908 }
909}
910
911impl Convert<RequestMode> for NetTraitsRequestMode {
912 fn convert(self) -> RequestMode {
913 match self {
914 NetTraitsRequestMode::Navigate => RequestMode::Navigate,
915 NetTraitsRequestMode::SameOrigin => RequestMode::Same_origin,
916 NetTraitsRequestMode::NoCors => RequestMode::No_cors,
917 NetTraitsRequestMode::CorsMode => RequestMode::Cors,
918 NetTraitsRequestMode::WebSocket { .. } => {
919 unreachable!("Websocket request mode should never be exposed to Dom")
920 },
921 }
922 }
923}
924
925impl Convert<MsgReferrerPolicy> for ReferrerPolicy {
926 fn convert(self) -> MsgReferrerPolicy {
927 match self {
928 ReferrerPolicy::_empty => MsgReferrerPolicy::EmptyString,
929 ReferrerPolicy::No_referrer => MsgReferrerPolicy::NoReferrer,
930 ReferrerPolicy::No_referrer_when_downgrade => {
931 MsgReferrerPolicy::NoReferrerWhenDowngrade
932 },
933 ReferrerPolicy::Origin => MsgReferrerPolicy::Origin,
934 ReferrerPolicy::Origin_when_cross_origin => MsgReferrerPolicy::OriginWhenCrossOrigin,
935 ReferrerPolicy::Unsafe_url => MsgReferrerPolicy::UnsafeUrl,
936 ReferrerPolicy::Same_origin => MsgReferrerPolicy::SameOrigin,
937 ReferrerPolicy::Strict_origin => MsgReferrerPolicy::StrictOrigin,
938 ReferrerPolicy::Strict_origin_when_cross_origin => {
939 MsgReferrerPolicy::StrictOriginWhenCrossOrigin
940 },
941 }
942 }
943}
944
945impl Convert<ReferrerPolicy> for MsgReferrerPolicy {
946 fn convert(self) -> ReferrerPolicy {
947 match self {
948 MsgReferrerPolicy::EmptyString => ReferrerPolicy::_empty,
949 MsgReferrerPolicy::NoReferrer => ReferrerPolicy::No_referrer,
950 MsgReferrerPolicy::NoReferrerWhenDowngrade => {
951 ReferrerPolicy::No_referrer_when_downgrade
952 },
953 MsgReferrerPolicy::Origin => ReferrerPolicy::Origin,
954 MsgReferrerPolicy::OriginWhenCrossOrigin => ReferrerPolicy::Origin_when_cross_origin,
955 MsgReferrerPolicy::UnsafeUrl => ReferrerPolicy::Unsafe_url,
956 MsgReferrerPolicy::SameOrigin => ReferrerPolicy::Same_origin,
957 MsgReferrerPolicy::StrictOrigin => ReferrerPolicy::Strict_origin,
958 MsgReferrerPolicy::StrictOriginWhenCrossOrigin => {
959 ReferrerPolicy::Strict_origin_when_cross_origin
960 },
961 }
962 }
963}
964
965impl Convert<RedirectMode> for RequestRedirect {
966 fn convert(self) -> RedirectMode {
967 match self {
968 RequestRedirect::Follow => RedirectMode::Follow,
969 RequestRedirect::Error => RedirectMode::Error,
970 RequestRedirect::Manual => RedirectMode::Manual,
971 }
972 }
973}
974
975impl Convert<RequestRedirect> for RedirectMode {
976 fn convert(self) -> RequestRedirect {
977 match self {
978 RedirectMode::Follow => RequestRedirect::Follow,
979 RedirectMode::Error => RequestRedirect::Error,
980 RedirectMode::Manual => RequestRedirect::Manual,
981 }
982 }
983}