1use std::cell::Ref;
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::conversions::Convert;
28use crate::dom::RootedPromise;
29use crate::dom::abortsignal::AbortSignal;
30use crate::dom::bindings::codegen::Bindings::HeadersBinding::HeadersMethods;
31use crate::dom::bindings::codegen::Bindings::RequestBinding::{
32 ReferrerPolicy, RequestCache, RequestCredentials, RequestDestination, RequestDuplex,
33 RequestInfo, RequestInit, RequestMethods, RequestMode, RequestRedirect,
34};
35use crate::dom::bindings::error::{Error, Fallible};
36use crate::dom::bindings::reflector::DomGlobal;
37use crate::dom::bindings::root::{DomRoot, MutNullableDom};
38use crate::dom::bindings::str::{ByteString, DOMString, USVString};
39use crate::dom::globalscope::GlobalScope;
40use crate::dom::headers::{Guard, Headers};
41use crate::dom::stream::readablestream::ReadableStream;
42use crate::fetch::body::{
43 BodyMixin, BodyType, Extractable, body_text_stream, clone_body_stream_for_dom_body,
44 consume_body,
45};
46use crate::fetch::fetch::RequestWithGlobalScope;
47use crate::url::ensure_blob_referenced_by_url_is_kept_alive;
48
49#[dom_struct]
50pub(crate) struct Request {
51 reflector_: Reflector,
52 #[no_trace]
53 request: DomRefCell<NetTraitsRequest>,
55 body_stream: MutNullableDom<ReadableStream>,
57 headers: MutNullableDom<Headers>,
59 signal: MutNullableDom<AbortSignal>,
61}
62
63impl Request {
64 fn new_inherited(global: &GlobalScope, url: ServoUrl) -> Request {
65 Request {
66 reflector_: Reflector::new(),
67 request: DomRefCell::new(net_request_from_global(global, url)),
68 body_stream: MutNullableDom::new(None),
69 headers: Default::default(),
70 signal: MutNullableDom::new(None),
71 }
72 }
73
74 pub(crate) fn new(
75 cx: &mut JSContext,
76 global: &GlobalScope,
77 proto: Option<HandleObject>,
78 url: ServoUrl,
79 ) -> DomRoot<Request> {
80 reflect_dom_object_with_proto(
81 cx,
82 Box::new(Request::new_inherited(global, url)),
83 global,
84 proto,
85 )
86 }
87
88 fn from_net_request(
89 cx: &mut JSContext,
90 global: &GlobalScope,
91 proto: Option<HandleObject>,
92 net_request: NetTraitsRequest,
93 ) -> DomRoot<Request> {
94 let r = Request::new(cx, global, proto, net_request.current_url());
95 *r.request.borrow_mut() = net_request;
96 r
97 }
98
99 pub(crate) fn constructor(
101 cx: &mut js::context::JSContext,
102 global: &GlobalScope,
103 proto: Option<HandleObject>,
104 mut input: RequestInfo,
105 init: &RequestInit,
106 ) -> Fallible<DomRoot<Request>> {
107 let temporary_request: NetTraitsRequest;
109
110 let mut fallback_mode: Option<NetTraitsRequestMode> = None;
112
113 let base_url = global.api_base_url();
115
116 let mut signal: Option<DomRoot<AbortSignal>> = None;
118
119 let mut input_body_is_unusable = false;
121
122 match input {
123 RequestInfo::USVString(USVString(ref usv_string)) => {
125 let parsed_url = base_url.join(usv_string);
127 if parsed_url.is_err() {
129 return Err(Error::Type(c"Url could not be parsed".to_owned()));
130 }
131 let url = parsed_url.unwrap();
133 if includes_credentials(&url) {
134 return Err(Error::Type(c"Url includes credentials".to_owned()));
135 }
136 temporary_request = net_request_from_global(global, url);
138 fallback_mode = Some(NetTraitsRequestMode::CorsMode);
140 },
141 RequestInfo::Request(ref input_request) => {
144 input_body_is_unusable = input_request.is_unusable();
146 temporary_request = input_request.request.borrow().clone();
148 signal = Some(input_request.Signal());
150 },
151 }
152
153 let origin = global.origin();
155 let origin = origin.immutable();
156
157 let mut traversable_for_user_prompts = TraversableForUserPrompts::Client;
159
160 if !init.window.get().is_null_or_undefined() {
167 return Err(Error::Type(c"Window is present and is not null".to_owned()));
168 }
169
170 if !init.window.get().is_undefined() {
172 traversable_for_user_prompts = TraversableForUserPrompts::NoTraversable;
173 }
174
175 let mut request: NetTraitsRequest;
177 request = net_request_from_global(global, temporary_request.current_url());
178 request.method = temporary_request.method;
179 request.headers = temporary_request.headers;
180 request.unsafe_request = true;
181 request.traversable_for_user_prompts = traversable_for_user_prompts;
182 request.origin = Origin::Client;
184 request.referrer = temporary_request.referrer;
185 request.referrer_policy = temporary_request.referrer_policy;
186 request.mode = temporary_request.mode;
187 request.credentials_mode = temporary_request.credentials_mode;
188 request.cache_mode = temporary_request.cache_mode;
189 request.redirect_mode = temporary_request.redirect_mode;
190 request.integrity_metadata = temporary_request.integrity_metadata;
191 request.reload_navigation = temporary_request.reload_navigation;
193 request.history_navigation = temporary_request.history_navigation;
195
196 if init.body.is_some() ||
198 init.cache.is_some() ||
199 init.credentials.is_some() ||
200 init.duplex.is_some() ||
201 init.integrity.is_some() ||
202 init.headers.is_some() ||
203 init.keepalive.is_some() ||
204 init.method.is_some() ||
205 init.mode.is_some() ||
206 init.redirect.is_some() ||
207 init.referrer.is_some() ||
208 init.referrerPolicy.is_some() ||
209 !init.window.get().is_undefined()
210 {
211 if request.mode == NetTraitsRequestMode::Navigate {
213 request.mode = NetTraitsRequestMode::SameOrigin;
214 }
215 request.reload_navigation = false;
217 request.history_navigation = false;
219 request.referrer = global.get_referrer();
223 request.referrer_policy = MsgReferrerPolicy::EmptyString;
225 }
230
231 if let Some(init_referrer) = init.referrer.as_ref() {
233 let referrer = &init_referrer.0;
235 if referrer.is_empty() {
237 request.referrer = Referrer::NoReferrer;
238 } else {
240 let parsed_referrer = base_url.join(referrer);
242 if parsed_referrer.is_err() {
244 return Err(Error::Type(c"Failed to parse referrer url".to_owned()));
245 }
246 if let Ok(parsed_referrer) = parsed_referrer {
250 if (parsed_referrer.cannot_be_a_base() &&
251 parsed_referrer.scheme() == "about" &&
252 parsed_referrer.path() == "client") ||
253 parsed_referrer.origin() != *origin
254 {
255 request.referrer = global.get_referrer();
257 } else {
258 request.referrer = Referrer::ReferrerUrl(parsed_referrer);
260 }
261 }
262 }
263 }
264
265 if let Some(init_referrerpolicy) = init.referrerPolicy.as_ref() {
267 let init_referrer_policy = (*init_referrerpolicy).convert();
268 request.referrer_policy = init_referrer_policy;
269 }
270
271 let mode = init.mode.as_ref().map(|m| (*m).convert()).or(fallback_mode);
273
274 if let Some(NetTraitsRequestMode::Navigate) = mode {
276 return Err(Error::Type(c"Request mode is Navigate".to_owned()));
277 }
278
279 if let Some(m) = mode {
281 request.mode = m;
282 }
283
284 if let Some(init_credentials) = init.credentials.as_ref() {
286 let credentials = (*init_credentials).convert();
287 request.credentials_mode = credentials;
288 }
289
290 if let Some(init_cache) = init.cache.as_ref() {
292 let cache = (*init_cache).convert();
293 request.cache_mode = cache;
294 }
295
296 if request.cache_mode == CacheMode::OnlyIfCached &&
299 request.mode != NetTraitsRequestMode::SameOrigin
300 {
301 return Err(Error::Type(
302 c"Cache is 'only-if-cached' and mode is not 'same-origin'".to_owned(),
303 ));
304 }
305
306 if let Some(init_redirect) = init.redirect.as_ref() {
308 let redirect = (*init_redirect).convert();
309 request.redirect_mode = redirect;
310 }
311
312 if let Some(init_integrity) = init.integrity.as_ref() {
314 let integrity = init_integrity.to_string();
315 request.integrity_metadata = integrity;
316 }
317
318 if let Some(init_keepalive) = init.keepalive {
320 request.keep_alive = init_keepalive;
321 }
322
323 if let Some(init_method) = init.method.as_ref() {
326 if !is_method(init_method) {
328 return Err(Error::Type(c"Method is not a method".to_owned()));
329 }
330 if is_forbidden_method(init_method) {
331 return Err(Error::Type(c"Method is forbidden".to_owned()));
332 }
333 let method = match init_method.as_str() {
335 Some(s) => normalize_method(s)
336 .map_err(|e| Error::Type(cformat!("Method is not valid: {:?}", e)))?,
337 None => return Err(Error::Type(c"Method is not a valid UTF8".to_owned())),
338 };
339 request.method = method;
341 }
342
343 if let Some(init_signal) = init.signal.as_ref() {
345 signal = init_signal.clone();
346 }
347 let request = Request::from_net_request(cx, global, proto, request);
357
358 let signals = signal.map_or(vec![], |s| vec![s]);
360 request
363 .signal
364 .set(Some(&AbortSignal::create_dependent_abort_signal(
365 cx, signals, global,
366 )));
367
368 request
374 .headers
375 .or_init(|| Headers::for_request(cx, &request.global()));
376
377 if request.request.borrow().mode == NetTraitsRequestMode::NoCors {
387 let borrowed_request = request.request.borrow();
388 if !is_cors_safelisted_method(&borrowed_request.method) {
390 return Err(Error::Type(
391 c"The mode is 'no-cors' but the method is not a cors-safelisted method"
392 .to_owned(),
393 ));
394 }
395 request.Headers(cx).set_guard(Guard::RequestNoCors);
397 }
398
399 match init.headers.as_ref() {
400 None => {
401 if let RequestInfo::Request(ref input_request) = input {
408 request
409 .Headers(cx)
410 .copy_from_headers(&input_request.Headers(cx))?;
411 }
412 },
413 Some(headers) => request.Headers(cx).fill(Some(headers))?,
415 }
416
417 request.request.borrow_mut().headers = request.Headers(cx).get_headers_list();
420
421 let input_body = if let RequestInfo::Request(ref mut input_request) = input {
423 let mut input_request_request = input_request.request.borrow_mut();
424 request.body_stream.set(input_request.body().as_deref());
425 input_request_request.body.take()
426 } else {
427 None
428 };
429
430 if init.body.as_ref().is_some_and(|body| body.is_some()) || input_body.is_some() {
433 let req = request.request.borrow();
434 let req_method = &req.method;
435 match *req_method {
436 HttpMethod::GET => {
437 return Err(Error::Type(
438 c"Init's body is non-null, and request method is GET".to_owned(),
439 ));
440 },
441 HttpMethod::HEAD => {
442 return Err(Error::Type(
443 c"Init's body is non-null, and request method is HEAD".to_owned(),
444 ));
445 },
446 _ => {},
447 }
448 }
449
450 let mut init_body = None;
452 if let Some(Some(ref input_init_body)) = init.body {
454 let mut body_with_type =
456 input_init_body.extract(cx, global, request.request.borrow().keep_alive)?;
457
458 if let Some(contents) = body_with_type.content_type.take() {
460 let content_type_header_name = b"Content-Type";
463 let headers = request.Headers(cx);
464 if !headers
465 .Has(ByteString::new(content_type_header_name.to_vec()))
466 .unwrap()
467 {
468 let content_type_header_value = contents.as_bytes(cx.no_gc());
469 headers.Append(
470 ByteString::new(content_type_header_name.to_vec()),
471 ByteString::new(content_type_header_value.to_vec()),
472 )?;
473
474 if let Ok(header_value) = HeaderValue::from_bytes(&content_type_header_value) {
478 request
479 .request
480 .borrow_mut()
481 .headers
482 .insert(CONTENT_TYPE, header_value);
483 }
484 }
485 }
486
487 let (net_body, stream) = body_with_type.into_net_request_body(cx);
489 request.body_stream.set(Some(&*stream));
490 init_body = Some(net_body);
491 }
492
493 let init_body_is_non_null = init_body.is_some();
500 let final_body = init_body.or(input_body);
501
502 if final_body
504 .as_ref()
505 .is_some_and(|body| body.source_is_null())
506 {
507 if init_body_is_non_null && init.duplex.is_none() {
510 return Err(Error::Type(
511 c"Request with a ReadableStream body must specify duplex".to_owned(),
512 ));
513 }
514 let request_mode = &request.request.borrow().mode;
516 if *request_mode != NetTraitsRequestMode::CorsMode &&
517 *request_mode != NetTraitsRequestMode::SameOrigin
518 {
519 return Err(Error::Type(
520 c"Request mode must be Cors or SameOrigin".to_owned(),
521 ));
522 }
523 }
526
527 if input_body_is_unusable {
534 return Err(Error::Type(c"Input body is unusable".to_owned()));
535 }
536
537 request.request.borrow_mut().body = final_body;
539
540 Ok(request)
541 }
542
543 fn clone_from(cx: &mut js::context::JSContext, r: &Request) -> Fallible<DomRoot<Request>> {
545 let req = r.request.borrow();
546 let url = req.url();
547 let headers_guard = r.Headers(cx).get_guard();
548
549 let mut new_req_inner = req.clone();
551 let body = new_req_inner.body.take();
552
553 let r_clone = Request::new(cx, &r.global(), None, url);
554 *r_clone.request.borrow_mut() = new_req_inner;
555
556 if let Some(body) = body {
559 r_clone.request.borrow_mut().body = Some(body);
560 }
561
562 r_clone.Headers(cx).copy_from_headers(&r.Headers(cx))?;
563 r_clone.Headers(cx).set_guard(headers_guard);
564
565 clone_body_stream_for_dom_body(cx, &r.body_stream, &r_clone.body_stream)?;
566
567 Ok(r_clone)
569 }
570
571 pub(crate) fn request(&self) -> Ref<'_, NetTraitsRequest> {
572 self.request.borrow()
573 }
574}
575
576fn net_request_from_global(global: &GlobalScope, url: ServoUrl) -> NetTraitsRequest {
577 let url = ensure_blob_referenced_by_url_is_kept_alive(global, url);
578 RequestBuilder::new(global.webview_id(), url, global.get_referrer())
579 .with_global_scope(global)
580 .build()
581}
582
583fn normalize_method(m: &str) -> Result<HttpMethod, InvalidMethod> {
585 match_ignore_ascii_case! { m,
586 "delete" => return Ok(HttpMethod::DELETE),
587 "get" => return Ok(HttpMethod::GET),
588 "head" => return Ok(HttpMethod::HEAD),
589 "options" => return Ok(HttpMethod::OPTIONS),
590 "post" => return Ok(HttpMethod::POST),
591 "put" => return Ok(HttpMethod::PUT),
592 _ => (),
593 }
594 debug!("Method: {:?}", m);
595 HttpMethod::from_str(m)
596}
597
598fn is_method(m: &ByteString) -> bool {
600 m.as_str().is_some()
601}
602
603fn is_cors_safelisted_method(m: &HttpMethod) -> bool {
605 m == HttpMethod::GET || m == HttpMethod::HEAD || m == HttpMethod::POST
606}
607
608fn includes_credentials(input: &ServoUrl) -> bool {
610 !input.username().is_empty() || input.password().is_some()
611}
612
613impl RequestMethods<crate::DomTypeHolder> for Request {
614 fn Constructor(
616 cx: &mut js::context::JSContext,
617 global: &GlobalScope,
618 proto: Option<HandleObject>,
619 input: RequestInfo,
620 init: &RequestInit,
621 ) -> Fallible<DomRoot<Request>> {
622 Self::constructor(cx, global, proto, input, init)
623 }
624
625 fn Method(&self) -> ByteString {
627 let r = self.request.borrow();
628 ByteString::new(r.method.as_ref().as_bytes().into())
629 }
630
631 fn Url(&self) -> USVString {
633 let r = self.request.borrow();
634 USVString(r.url_list.first().map_or("", |u| u.as_str()).into())
635 }
636
637 fn Headers(&self, cx: &mut js::context::JSContext) -> DomRoot<Headers> {
639 self.headers.or_init(|| Headers::new(cx, &self.global()))
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::new(),
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 self.request.borrow().credentials_mode.convert()
673 }
674
675 fn Cache(&self) -> RequestCache {
677 self.request.borrow().cache_mode.convert()
678 }
679
680 fn Redirect(&self) -> RequestRedirect {
682 self.request.borrow().redirect_mode.convert()
683 }
684
685 fn Integrity(&self) -> DOMString {
687 self.request.borrow().integrity_metadata.clone().into()
688 }
689
690 fn Duplex(&self) -> RequestDuplex {
692 RequestDuplex::Half
694 }
695
696 fn Keepalive(&self) -> bool {
698 self.request.borrow().keep_alive
699 }
700
701 fn IsReloadNavigation(&self) -> bool {
704 self.request.borrow().reload_navigation
705 }
706
707 fn IsHistoryNavigation(&self) -> bool {
710 self.request.borrow().history_navigation
711 }
712
713 fn GetBody(&self) -> Option<DomRoot<ReadableStream>> {
715 self.body()
716 }
717
718 fn BodyUsed(&self) -> bool {
720 self.is_body_used()
721 }
722
723 fn Signal(&self) -> DomRoot<AbortSignal> {
725 self.signal
726 .get()
727 .expect("Should always be initialized in constructor and clone")
728 }
729
730 fn Clone(&self, cx: &mut js::context::JSContext) -> Fallible<DomRoot<Request>> {
732 if self.is_unusable() {
734 return Err(Error::Type(c"Request is unusable".to_owned()));
735 }
736
737 let cloned_request = Request::clone_from(cx, self)?;
739 let signal = self.signal.get().expect("Should always be initialized");
741 let cloned_signal =
744 AbortSignal::create_dependent_abort_signal(cx, vec![signal], &self.global());
745 cloned_request.signal.set(Some(&cloned_signal));
750 Ok(cloned_request)
752 }
753
754 fn Text(&self, cx: &mut js::context::JSContext) -> RootedPromise {
756 consume_body(cx, self, BodyType::Text)
757 }
758
759 fn Blob(&self, cx: &mut js::context::JSContext) -> RootedPromise {
761 consume_body(cx, self, BodyType::Blob)
762 }
763
764 fn FormData(&self, cx: &mut js::context::JSContext) -> RootedPromise {
766 consume_body(cx, self, BodyType::FormData)
767 }
768
769 fn Json(&self, cx: &mut js::context::JSContext) -> RootedPromise {
771 consume_body(cx, self, BodyType::Json)
772 }
773
774 fn ArrayBuffer(&self, cx: &mut js::context::JSContext) -> RootedPromise {
776 consume_body(cx, self, BodyType::ArrayBuffer)
777 }
778
779 fn Bytes(&self, cx: &mut js::context::JSContext) -> RootedPromise {
781 consume_body(cx, self, BodyType::Bytes)
782 }
783
784 fn TextStream(&self, cx: &mut js::context::JSContext) -> Fallible<DomRoot<ReadableStream>> {
786 body_text_stream(cx, self)
787 }
788}
789
790impl BodyMixin for Request {
791 fn is_body_used(&self) -> bool {
792 let body_stream = self.body_stream.get();
793 body_stream
794 .as_ref()
795 .is_some_and(|stream| stream.is_disturbed())
796 }
797
798 fn is_unusable(&self) -> bool {
799 let body_stream = self.body_stream.get();
800 body_stream
801 .as_ref()
802 .is_some_and(|stream| stream.is_disturbed() || stream.is_locked())
803 }
804
805 fn body(&self) -> Option<DomRoot<ReadableStream>> {
806 self.body_stream.get()
807 }
808
809 fn get_mime_type(&self, cx: &mut js::context::JSContext) -> Vec<u8> {
810 let headers = self.Headers(cx);
811 headers.extract_mime_type()
812 }
813}
814
815impl Convert<CacheMode> for RequestCache {
816 fn convert(self) -> CacheMode {
817 match self {
818 RequestCache::Default => CacheMode::Default,
819 RequestCache::No_store => CacheMode::NoStore,
820 RequestCache::Reload => CacheMode::Reload,
821 RequestCache::No_cache => CacheMode::NoCache,
822 RequestCache::Force_cache => CacheMode::ForceCache,
823 RequestCache::Only_if_cached => CacheMode::OnlyIfCached,
824 }
825 }
826}
827
828impl Convert<RequestCache> for CacheMode {
829 fn convert(self) -> RequestCache {
830 match self {
831 CacheMode::Default => RequestCache::Default,
832 CacheMode::NoStore => RequestCache::No_store,
833 CacheMode::Reload => RequestCache::Reload,
834 CacheMode::NoCache => RequestCache::No_cache,
835 CacheMode::ForceCache => RequestCache::Force_cache,
836 CacheMode::OnlyIfCached => RequestCache::Only_if_cached,
837 }
838 }
839}
840
841impl Convert<CredentialsMode> for RequestCredentials {
842 fn convert(self) -> CredentialsMode {
843 match self {
844 RequestCredentials::Omit => CredentialsMode::Omit,
845 RequestCredentials::Same_origin => CredentialsMode::CredentialsSameOrigin,
846 RequestCredentials::Include => CredentialsMode::Include,
847 }
848 }
849}
850
851impl Convert<RequestCredentials> for CredentialsMode {
852 fn convert(self) -> RequestCredentials {
853 match self {
854 CredentialsMode::Omit => RequestCredentials::Omit,
855 CredentialsMode::CredentialsSameOrigin => RequestCredentials::Same_origin,
856 CredentialsMode::Include => RequestCredentials::Include,
857 }
858 }
859}
860
861impl Convert<Destination> for RequestDestination {
862 fn convert(self) -> Destination {
863 match self {
864 RequestDestination::_empty => Destination::None,
865 RequestDestination::Audio => Destination::Audio,
866 RequestDestination::Document => Destination::Document,
867 RequestDestination::Embed => Destination::Embed,
868 RequestDestination::Font => Destination::Font,
869 RequestDestination::Frame => Destination::Frame,
870 RequestDestination::Iframe => Destination::IFrame,
871 RequestDestination::Image => Destination::Image,
872 RequestDestination::Manifest => Destination::Manifest,
873 RequestDestination::Json => Destination::Json,
874 RequestDestination::Object => Destination::Object,
875 RequestDestination::Report => Destination::Report,
876 RequestDestination::Script => Destination::Script,
877 RequestDestination::Sharedworker => Destination::SharedWorker,
878 RequestDestination::Style => Destination::Style,
879 RequestDestination::Text => Destination::Text,
880 RequestDestination::Track => Destination::Track,
881 RequestDestination::Video => Destination::Video,
882 RequestDestination::Worker => Destination::Worker,
883 RequestDestination::Xslt => Destination::Xslt,
884 }
885 }
886}
887
888impl Convert<RequestDestination> for Destination {
889 fn convert(self) -> RequestDestination {
890 match self {
891 Destination::None => RequestDestination::_empty,
892 Destination::Audio => RequestDestination::Audio,
893 Destination::Document => RequestDestination::Document,
894 Destination::Embed => RequestDestination::Embed,
895 Destination::Font => RequestDestination::Font,
896 Destination::Frame => RequestDestination::Frame,
897 Destination::IFrame => RequestDestination::Iframe,
898 Destination::Image => RequestDestination::Image,
899 Destination::Manifest => RequestDestination::Manifest,
900 Destination::Json => RequestDestination::Json,
901 Destination::Object => RequestDestination::Object,
902 Destination::Report => RequestDestination::Report,
903 Destination::Script => RequestDestination::Script,
904 Destination::ServiceWorker | Destination::AudioWorklet | Destination::PaintWorklet => {
905 panic!("ServiceWorker request destination should not be exposed to DOM")
906 },
907 Destination::SharedWorker => RequestDestination::Sharedworker,
908 Destination::Style => RequestDestination::Style,
909 Destination::Text => RequestDestination::Text,
910 Destination::Track => RequestDestination::Track,
911 Destination::Video => RequestDestination::Video,
912 Destination::Worker => RequestDestination::Worker,
913 Destination::Xslt => RequestDestination::Xslt,
914 Destination::WebIdentity => RequestDestination::_empty,
915 }
916 }
917}
918
919impl Convert<NetTraitsRequestMode> for RequestMode {
920 fn convert(self) -> NetTraitsRequestMode {
921 match self {
922 RequestMode::Navigate => NetTraitsRequestMode::Navigate,
923 RequestMode::Same_origin => NetTraitsRequestMode::SameOrigin,
924 RequestMode::No_cors => NetTraitsRequestMode::NoCors,
925 RequestMode::Cors => NetTraitsRequestMode::CorsMode,
926 }
927 }
928}
929
930impl Convert<RequestMode> for NetTraitsRequestMode {
931 fn convert(self) -> RequestMode {
932 match self {
933 NetTraitsRequestMode::Navigate => RequestMode::Navigate,
934 NetTraitsRequestMode::SameOrigin => RequestMode::Same_origin,
935 NetTraitsRequestMode::NoCors => RequestMode::No_cors,
936 NetTraitsRequestMode::CorsMode => RequestMode::Cors,
937 NetTraitsRequestMode::WebSocket { .. } => {
938 unreachable!("Websocket request mode should never be exposed to Dom")
939 },
940 }
941 }
942}
943
944impl Convert<MsgReferrerPolicy> for ReferrerPolicy {
945 fn convert(self) -> MsgReferrerPolicy {
946 match self {
947 ReferrerPolicy::_empty => MsgReferrerPolicy::EmptyString,
948 ReferrerPolicy::No_referrer => MsgReferrerPolicy::NoReferrer,
949 ReferrerPolicy::No_referrer_when_downgrade => {
950 MsgReferrerPolicy::NoReferrerWhenDowngrade
951 },
952 ReferrerPolicy::Origin => MsgReferrerPolicy::Origin,
953 ReferrerPolicy::Origin_when_cross_origin => MsgReferrerPolicy::OriginWhenCrossOrigin,
954 ReferrerPolicy::Unsafe_url => MsgReferrerPolicy::UnsafeUrl,
955 ReferrerPolicy::Same_origin => MsgReferrerPolicy::SameOrigin,
956 ReferrerPolicy::Strict_origin => MsgReferrerPolicy::StrictOrigin,
957 ReferrerPolicy::Strict_origin_when_cross_origin => {
958 MsgReferrerPolicy::StrictOriginWhenCrossOrigin
959 },
960 }
961 }
962}
963
964impl Convert<ReferrerPolicy> for MsgReferrerPolicy {
965 fn convert(self) -> ReferrerPolicy {
966 match self {
967 MsgReferrerPolicy::EmptyString => ReferrerPolicy::_empty,
968 MsgReferrerPolicy::NoReferrer => ReferrerPolicy::No_referrer,
969 MsgReferrerPolicy::NoReferrerWhenDowngrade => {
970 ReferrerPolicy::No_referrer_when_downgrade
971 },
972 MsgReferrerPolicy::Origin => ReferrerPolicy::Origin,
973 MsgReferrerPolicy::OriginWhenCrossOrigin => ReferrerPolicy::Origin_when_cross_origin,
974 MsgReferrerPolicy::UnsafeUrl => ReferrerPolicy::Unsafe_url,
975 MsgReferrerPolicy::SameOrigin => ReferrerPolicy::Same_origin,
976 MsgReferrerPolicy::StrictOrigin => ReferrerPolicy::Strict_origin,
977 MsgReferrerPolicy::StrictOriginWhenCrossOrigin => {
978 ReferrerPolicy::Strict_origin_when_cross_origin
979 },
980 }
981 }
982}
983
984impl Convert<RedirectMode> for RequestRedirect {
985 fn convert(self) -> RedirectMode {
986 match self {
987 RequestRedirect::Follow => RedirectMode::Follow,
988 RequestRedirect::Error => RedirectMode::Error,
989 RequestRedirect::Manual => RedirectMode::Manual,
990 }
991 }
992}
993
994impl Convert<RequestRedirect> for RedirectMode {
995 fn convert(self) -> RequestRedirect {
996 match self {
997 RedirectMode::Follow => RequestRedirect::Follow,
998 RedirectMode::Error => RequestRedirect::Error,
999 RedirectMode::Manual => RequestRedirect::Manual,
1000 }
1001 }
1002}