1use std::cell::Ref;
6use std::str::FromStr;
7
8use bytes::Bytes;
9use cssparser::match_ignore_ascii_case;
10use dom_struct::dom_struct;
11use http::Method as HttpMethod;
12use http::header::{CONTENT_TYPE, HeaderValue};
13use http::method::InvalidMethod;
14use js::context::JSContext;
15use js::gc::HandleValue;
16use js::rust::HandleObject;
17use net_traits::fetch::headers::is_forbidden_method;
18use net_traits::request::{
19 CacheMode, CredentialsMode, Destination, Origin, RedirectMode, Referrer,
20 Request as NetTraitsRequest, RequestBuilder, RequestMode as NetTraitsRequestMode,
21 TraversableForUserPrompts,
22};
23use net_traits::{FetchMetadata, NetworkError, ReferrerPolicy as MsgReferrerPolicy};
24use script_bindings::cell::DomRefCell;
25use script_bindings::cformat;
26use script_bindings::reflector::{Reflector, reflect_dom_object_with_proto};
27use servo_url::ServoUrl;
28
29use crate::conversions::Convert;
30use crate::dom::RootedPromise;
31use crate::dom::abortsignal::AbortSignal;
32use crate::dom::bindings::codegen::Bindings::HeadersBinding::HeadersMethods;
33use crate::dom::bindings::codegen::Bindings::RequestBinding::{
34 ReferrerPolicy, RequestCache, RequestCredentials, RequestDestination, RequestDuplex,
35 RequestInfo, RequestInit, 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::globalscope::GlobalScope;
42use crate::dom::headers::{Guard, Headers};
43use crate::dom::stream::readablestream::ReadableStream;
44use crate::fetch::body::{
45 BodyMixin, BodyType, Extractable, body_text_stream, clone_body_stream_for_dom_body,
46 consume_body,
47};
48use crate::fetch::fetch::{FetchCallState, RequestWithGlobalScope};
49use crate::url::ensure_blob_referenced_by_url_is_kept_alive;
50
51#[dom_struct]
52pub(crate) struct Request {
53 reflector_: Reflector,
54 #[no_trace]
55 request: DomRefCell<NetTraitsRequest>,
57 body_stream: MutNullableDom<ReadableStream>,
59 headers: MutNullableDom<Headers>,
61 signal: MutNullableDom<AbortSignal>,
63 state: Option<FetchCallState>,
65}
66
67impl Request {
68 fn new_inherited(
69 global: &GlobalScope,
70 url: ServoUrl,
71 state: Option<&FetchCallState>,
72 ) -> Request {
73 Request {
74 reflector_: Reflector::new(),
75 request: DomRefCell::new(net_request_from_global(global, url)),
76 body_stream: MutNullableDom::new(None),
77 headers: Default::default(),
78 signal: MutNullableDom::new(None),
79 state: state.cloned(),
80 }
81 }
82
83 pub(crate) fn new(
84 cx: &mut JSContext,
85 global: &GlobalScope,
86 proto: Option<HandleObject>,
87 url: ServoUrl,
88 state: Option<&FetchCallState>,
89 ) -> DomRoot<Request> {
90 reflect_dom_object_with_proto(
91 cx,
92 Box::new(Request::new_inherited(global, url, state)),
93 global,
94 proto,
95 )
96 }
97
98 fn from_net_request(
99 cx: &mut JSContext,
100 global: &GlobalScope,
101 proto: Option<HandleObject>,
102 net_request: NetTraitsRequest,
103 state: Option<&FetchCallState>,
104 ) -> DomRoot<Request> {
105 let request = Request::new(cx, global, proto, net_request.current_url(), state);
106 *request.request.borrow_mut() = net_request;
107 request
108 }
109
110 pub(crate) fn constructor(
112 cx: &mut js::context::JSContext,
113 global: &GlobalScope,
114 proto: Option<HandleObject>,
115 mut input: RequestInfo,
116 init: &RequestInit,
117 state: Option<&FetchCallState>,
118 ) -> Fallible<DomRoot<Request>> {
119 let temporary_request: NetTraitsRequest;
121
122 let mut fallback_mode: Option<NetTraitsRequestMode> = None;
124
125 let base_url = global.api_base_url();
127
128 let mut signal: Option<DomRoot<AbortSignal>> = None;
130
131 let mut input_body_is_unusable = false;
133
134 match input {
135 RequestInfo::USVString(USVString(ref usv_string)) => {
137 let parsed_url = base_url.join(usv_string);
139 if parsed_url.is_err() {
141 return Err(Error::Type(c"Url could not be parsed".to_owned()));
142 }
143 let url = parsed_url.unwrap();
145 if includes_credentials(&url) {
146 return Err(Error::Type(c"Url includes credentials".to_owned()));
147 }
148 temporary_request = net_request_from_global(global, url);
150 fallback_mode = Some(NetTraitsRequestMode::CorsMode);
152 },
153 RequestInfo::Request(ref input_request) => {
156 input_body_is_unusable = input_request.is_unusable();
158 temporary_request = input_request.request.borrow().clone();
160 signal = Some(input_request.Signal());
162 },
163 }
164
165 let origin = global.origin();
167 let origin = origin.immutable();
168
169 let mut traversable_for_user_prompts = TraversableForUserPrompts::Client;
171
172 if !init.window.get().is_null_or_undefined() {
179 return Err(Error::Type(c"Window is present and is not null".to_owned()));
180 }
181
182 if !init.window.get().is_undefined() {
184 traversable_for_user_prompts = TraversableForUserPrompts::NoTraversable;
185 }
186
187 let mut request: NetTraitsRequest;
189 request = net_request_from_global(global, temporary_request.current_url());
190 request.method = temporary_request.method;
191 request.headers = temporary_request.headers;
192 request.unsafe_request = true;
193 request.traversable_for_user_prompts = traversable_for_user_prompts;
194 request.origin = Origin::Client;
196 request.referrer = temporary_request.referrer;
197 request.referrer_policy = temporary_request.referrer_policy;
198 request.mode = temporary_request.mode;
199 request.credentials_mode = temporary_request.credentials_mode;
200 request.cache_mode = temporary_request.cache_mode;
201 request.redirect_mode = temporary_request.redirect_mode;
202 request.integrity_metadata = temporary_request.integrity_metadata;
203 request.reload_navigation = temporary_request.reload_navigation;
205 request.history_navigation = temporary_request.history_navigation;
207
208 if init.body.is_some() ||
210 init.cache.is_some() ||
211 init.credentials.is_some() ||
212 init.duplex.is_some() ||
213 init.integrity.is_some() ||
214 init.headers.is_some() ||
215 init.keepalive.is_some() ||
216 init.method.is_some() ||
217 init.mode.is_some() ||
218 init.redirect.is_some() ||
219 init.referrer.is_some() ||
220 init.referrerPolicy.is_some() ||
221 !init.window.get().is_undefined()
222 {
223 if request.mode == NetTraitsRequestMode::Navigate {
225 request.mode = NetTraitsRequestMode::SameOrigin;
226 }
227 request.reload_navigation = false;
229 request.history_navigation = false;
231 request.referrer = global.get_referrer();
235 request.referrer_policy = MsgReferrerPolicy::EmptyString;
237 }
242
243 if let Some(init_referrer) = init.referrer.as_ref() {
245 let referrer = &init_referrer.0;
247 if referrer.is_empty() {
249 request.referrer = Referrer::NoReferrer;
250 } else {
252 let parsed_referrer = base_url.join(referrer);
254 if parsed_referrer.is_err() {
256 return Err(Error::Type(c"Failed to parse referrer url".to_owned()));
257 }
258 if let Ok(parsed_referrer) = parsed_referrer {
262 if (parsed_referrer.cannot_be_a_base() &&
263 parsed_referrer.scheme() == "about" &&
264 parsed_referrer.path() == "client") ||
265 parsed_referrer.origin() != *origin
266 {
267 request.referrer = global.get_referrer();
269 } else {
270 request.referrer = Referrer::ReferrerUrl(parsed_referrer);
272 }
273 }
274 }
275 }
276
277 if let Some(init_referrerpolicy) = init.referrerPolicy.as_ref() {
279 let init_referrer_policy = (*init_referrerpolicy).convert();
280 request.referrer_policy = init_referrer_policy;
281 }
282
283 let mode = init.mode.as_ref().map(|m| (*m).convert()).or(fallback_mode);
285
286 if let Some(NetTraitsRequestMode::Navigate) = mode {
288 return Err(Error::Type(c"Request mode is Navigate".to_owned()));
289 }
290
291 if let Some(m) = mode {
293 request.mode = m;
294 }
295
296 if let Some(init_credentials) = init.credentials.as_ref() {
298 let credentials = (*init_credentials).convert();
299 request.credentials_mode = credentials;
300 }
301
302 if let Some(init_cache) = init.cache.as_ref() {
304 let cache = (*init_cache).convert();
305 request.cache_mode = cache;
306 }
307
308 if request.cache_mode == CacheMode::OnlyIfCached &&
311 request.mode != NetTraitsRequestMode::SameOrigin
312 {
313 return Err(Error::Type(
314 c"Cache is 'only-if-cached' and mode is not 'same-origin'".to_owned(),
315 ));
316 }
317
318 if let Some(init_redirect) = init.redirect.as_ref() {
320 let redirect = (*init_redirect).convert();
321 request.redirect_mode = redirect;
322 }
323
324 if let Some(init_integrity) = init.integrity.as_ref() {
326 let integrity = init_integrity.to_string();
327 request.integrity_metadata = integrity;
328 }
329
330 if let Some(init_keepalive) = init.keepalive {
332 request.keep_alive = init_keepalive;
333 }
334
335 if let Some(init_method) = init.method.as_ref() {
338 if !is_method(init_method) {
340 return Err(Error::Type(c"Method is not a method".to_owned()));
341 }
342 if is_forbidden_method(init_method) {
343 return Err(Error::Type(c"Method is forbidden".to_owned()));
344 }
345 let method = match init_method.as_str() {
347 Some(s) => normalize_method(s)
348 .map_err(|e| Error::Type(cformat!("Method is not valid: {:?}", e)))?,
349 None => return Err(Error::Type(c"Method is not a valid UTF8".to_owned())),
350 };
351 request.method = method;
353 }
354
355 if let Some(init_signal) = init.signal.as_ref() {
357 signal = init_signal.clone();
358 }
359 let request = Request::from_net_request(cx, global, proto, request, state);
369
370 let signals = signal.map_or(vec![], |s| vec![s]);
372 request
375 .signal
376 .set(Some(&AbortSignal::create_dependent_abort_signal(
377 cx, signals, global,
378 )));
379
380 request
386 .headers
387 .or_init(|| Headers::for_request(cx, &request.global()));
388
389 if request.request.borrow().mode == NetTraitsRequestMode::NoCors {
399 let borrowed_request = request.request.borrow();
400 if !is_cors_safelisted_method(&borrowed_request.method) {
402 return Err(Error::Type(
403 c"The mode is 'no-cors' but the method is not a cors-safelisted method"
404 .to_owned(),
405 ));
406 }
407 request.Headers(cx).set_guard(Guard::RequestNoCors);
409 }
410
411 match init.headers.as_ref() {
412 None => {
413 if let RequestInfo::Request(ref input_request) = input {
420 request
421 .Headers(cx)
422 .copy_from_headers(&input_request.Headers(cx))?;
423 }
424 },
425 Some(headers) => request.Headers(cx).fill(Some(headers))?,
427 }
428
429 request.request.borrow_mut().headers = request.Headers(cx).get_headers_list();
432
433 let input_body = if let RequestInfo::Request(ref mut input_request) = input {
435 let mut input_request_request = input_request.request.borrow_mut();
436 request.body_stream.set(input_request.body().as_deref());
437 input_request_request.body.take()
438 } else {
439 None
440 };
441
442 if init.body.as_ref().is_some_and(|body| body.is_some()) || input_body.is_some() {
445 let req = request.request.borrow();
446 let req_method = &req.method;
447 match *req_method {
448 HttpMethod::GET => {
449 return Err(Error::Type(
450 c"Init's body is non-null, and request method is GET".to_owned(),
451 ));
452 },
453 HttpMethod::HEAD => {
454 return Err(Error::Type(
455 c"Init's body is non-null, and request method is HEAD".to_owned(),
456 ));
457 },
458 _ => {},
459 }
460 }
461
462 let mut init_body = None;
464 if let Some(Some(ref input_init_body)) = init.body {
466 let mut body_with_type =
468 input_init_body.extract(cx, global, request.request.borrow().keep_alive)?;
469
470 if let Some(contents) = body_with_type.content_type.take() {
472 let content_type_header_name = b"Content-Type";
475 let headers = request.Headers(cx);
476 if !headers
477 .Has(ByteString::new(content_type_header_name.to_vec()))
478 .unwrap()
479 {
480 let content_type_header_value = contents.as_bytes(cx.no_gc());
481 headers.Append(
482 ByteString::new(content_type_header_name.to_vec()),
483 ByteString::new(content_type_header_value.to_vec()),
484 )?;
485
486 if let Ok(header_value) = HeaderValue::from_bytes(&content_type_header_value) {
490 request
491 .request
492 .borrow_mut()
493 .headers
494 .insert(CONTENT_TYPE, header_value);
495 }
496 }
497 }
498
499 let (net_body, stream) = body_with_type.into_net_request_body(cx);
501 request.body_stream.set(Some(&*stream));
502 init_body = Some(net_body);
503 }
504
505 let init_body_is_non_null = init_body.is_some();
512 let final_body = init_body.or(input_body);
513
514 if final_body
516 .as_ref()
517 .is_some_and(|body| body.source_is_null())
518 {
519 if init_body_is_non_null && init.duplex.is_none() {
522 return Err(Error::Type(
523 c"Request with a ReadableStream body must specify duplex".to_owned(),
524 ));
525 }
526 let request_mode = &request.request.borrow().mode;
528 if *request_mode != NetTraitsRequestMode::CorsMode &&
529 *request_mode != NetTraitsRequestMode::SameOrigin
530 {
531 return Err(Error::Type(
532 c"Request mode must be Cors or SameOrigin".to_owned(),
533 ));
534 }
535 }
538
539 if input_body_is_unusable {
546 return Err(Error::Type(c"Input body is unusable".to_owned()));
547 }
548
549 request.request.borrow_mut().body = final_body;
551
552 Ok(request)
553 }
554
555 fn clone_from(cx: &mut js::context::JSContext, r: &Request) -> Fallible<DomRoot<Request>> {
557 let req = r.request.borrow();
558 let url = req.url();
559 let headers_guard = r.Headers(cx).get_guard();
560
561 let mut new_req_inner = req.clone();
563 let body = new_req_inner.body.take();
564
565 let r_clone = Request::new(cx, &r.global(), None, url, None );
566 *r_clone.request.borrow_mut() = new_req_inner;
567
568 if let Some(body) = body {
571 r_clone.request.borrow_mut().body = Some(body);
572 }
573
574 r_clone.Headers(cx).copy_from_headers(&r.Headers(cx))?;
575 r_clone.Headers(cx).set_guard(headers_guard);
576
577 clone_body_stream_for_dom_body(cx, &r.body_stream, &r_clone.body_stream)?;
578
579 Ok(r_clone)
581 }
582
583 pub(crate) fn request(&self) -> Ref<'_, NetTraitsRequest> {
584 self.request.borrow()
585 }
586
587 pub(crate) fn abort_fetch(
589 &self,
590 cx: &mut JSContext,
591 abort_reason: HandleValue,
592 global: &GlobalScope,
593 ) {
594 if let Some(fetch_call_state) = &self.state {
595 fetch_call_state.abort_fetch(cx, self, abort_reason, global);
596 }
597 }
598
599 pub(crate) fn process_response(
600 &self,
601 cx: &mut JSContext,
602 fetch_metadata: Result<FetchMetadata, NetworkError>,
603 ) {
604 if let Some(fetch_call_state) = &self.state {
605 fetch_call_state.process_response(cx, fetch_metadata);
606 }
607 }
608
609 pub(crate) fn process_response_chunk(&self, cx: &mut JSContext, chunk: Bytes) {
610 if let Some(fetch_call_state) = &self.state {
611 fetch_call_state.process_response_chunk(cx, chunk);
612 }
613 }
614
615 pub(crate) fn process_response_eof(
616 &self,
617 cx: &mut JSContext,
618 response: &Result<(), NetworkError>,
619 ) {
620 if let Some(fetch_call_state) = &self.state {
621 fetch_call_state.process_response_eof(cx, response);
622 }
623 }
624}
625
626fn net_request_from_global(global: &GlobalScope, url: ServoUrl) -> NetTraitsRequest {
627 let url = ensure_blob_referenced_by_url_is_kept_alive(global, url);
628 RequestBuilder::new(global.webview_id(), url, global.get_referrer())
629 .with_global_scope(global)
630 .build()
631}
632
633fn normalize_method(m: &str) -> Result<HttpMethod, InvalidMethod> {
635 match_ignore_ascii_case! { m,
636 "delete" => return Ok(HttpMethod::DELETE),
637 "get" => return Ok(HttpMethod::GET),
638 "head" => return Ok(HttpMethod::HEAD),
639 "options" => return Ok(HttpMethod::OPTIONS),
640 "post" => return Ok(HttpMethod::POST),
641 "put" => return Ok(HttpMethod::PUT),
642 _ => (),
643 }
644 debug!("Method: {:?}", m);
645 HttpMethod::from_str(m)
646}
647
648fn is_method(m: &ByteString) -> bool {
650 m.as_str().is_some()
651}
652
653fn is_cors_safelisted_method(m: &HttpMethod) -> bool {
655 m == HttpMethod::GET || m == HttpMethod::HEAD || m == HttpMethod::POST
656}
657
658fn includes_credentials(input: &ServoUrl) -> bool {
660 !input.username().is_empty() || input.password().is_some()
661}
662
663impl RequestMethods<crate::DomTypeHolder> for Request {
664 fn Constructor(
666 cx: &mut js::context::JSContext,
667 global: &GlobalScope,
668 proto: Option<HandleObject>,
669 input: RequestInfo,
670 init: &RequestInit,
671 ) -> Fallible<DomRoot<Request>> {
672 Self::constructor(cx, global, proto, input, init, None )
673 }
674
675 fn Method(&self) -> ByteString {
677 let r = self.request.borrow();
678 ByteString::new(r.method.as_ref().as_bytes().into())
679 }
680
681 fn Url(&self) -> USVString {
683 let r = self.request.borrow();
684 USVString(r.url_list.first().map_or("", |u| u.as_str()).into())
685 }
686
687 fn Headers(&self, cx: &mut js::context::JSContext) -> DomRoot<Headers> {
689 self.headers.or_init(|| Headers::new(cx, &self.global()))
690 }
691
692 fn Destination(&self) -> RequestDestination {
694 self.request.borrow().destination.convert()
695 }
696
697 fn Referrer(&self) -> USVString {
699 let r = self.request.borrow();
700 USVString(match r.referrer {
701 Referrer::NoReferrer => String::new(),
702 Referrer::Client(_) => String::from("about:client"),
703 Referrer::ReferrerUrl(ref u) => {
704 let u_c = u.clone();
705 u_c.into_string()
706 },
707 })
708 }
709
710 fn ReferrerPolicy(&self) -> ReferrerPolicy {
712 self.request.borrow().referrer_policy.convert()
713 }
714
715 fn Mode(&self) -> RequestMode {
717 self.request.borrow().mode.clone().convert()
718 }
719
720 fn Credentials(&self) -> RequestCredentials {
722 self.request.borrow().credentials_mode.convert()
723 }
724
725 fn Cache(&self) -> RequestCache {
727 self.request.borrow().cache_mode.convert()
728 }
729
730 fn Redirect(&self) -> RequestRedirect {
732 self.request.borrow().redirect_mode.convert()
733 }
734
735 fn Integrity(&self) -> DOMString {
737 self.request.borrow().integrity_metadata.clone().into()
738 }
739
740 fn Duplex(&self) -> RequestDuplex {
742 RequestDuplex::Half
744 }
745
746 fn Keepalive(&self) -> bool {
748 self.request.borrow().keep_alive
749 }
750
751 fn IsReloadNavigation(&self) -> bool {
754 self.request.borrow().reload_navigation
755 }
756
757 fn IsHistoryNavigation(&self) -> bool {
760 self.request.borrow().history_navigation
761 }
762
763 fn GetBody(&self) -> Option<DomRoot<ReadableStream>> {
765 self.body()
766 }
767
768 fn BodyUsed(&self) -> bool {
770 self.is_body_used()
771 }
772
773 fn Signal(&self) -> DomRoot<AbortSignal> {
775 self.signal
776 .get()
777 .expect("Should always be initialized in constructor and clone")
778 }
779
780 fn Clone(&self, cx: &mut js::context::JSContext) -> Fallible<DomRoot<Request>> {
782 if self.is_unusable() {
784 return Err(Error::Type(c"Request is unusable".to_owned()));
785 }
786
787 let cloned_request = Request::clone_from(cx, self)?;
789 let signal = self.signal.get().expect("Should always be initialized");
791 let cloned_signal =
794 AbortSignal::create_dependent_abort_signal(cx, vec![signal], &self.global());
795 cloned_request.signal.set(Some(&cloned_signal));
800 Ok(cloned_request)
802 }
803
804 fn Text(&self, cx: &mut js::context::JSContext) -> RootedPromise {
806 consume_body(cx, self, BodyType::Text)
807 }
808
809 fn Blob(&self, cx: &mut js::context::JSContext) -> RootedPromise {
811 consume_body(cx, self, BodyType::Blob)
812 }
813
814 fn FormData(&self, cx: &mut js::context::JSContext) -> RootedPromise {
816 consume_body(cx, self, BodyType::FormData)
817 }
818
819 fn Json(&self, cx: &mut js::context::JSContext) -> RootedPromise {
821 consume_body(cx, self, BodyType::Json)
822 }
823
824 fn ArrayBuffer(&self, cx: &mut js::context::JSContext) -> RootedPromise {
826 consume_body(cx, self, BodyType::ArrayBuffer)
827 }
828
829 fn Bytes(&self, cx: &mut js::context::JSContext) -> RootedPromise {
831 consume_body(cx, self, BodyType::Bytes)
832 }
833
834 fn TextStream(&self, cx: &mut js::context::JSContext) -> Fallible<DomRoot<ReadableStream>> {
836 body_text_stream(cx, self)
837 }
838}
839
840impl BodyMixin for Request {
841 fn is_body_used(&self) -> bool {
842 let body_stream = self.body_stream.get();
843 body_stream
844 .as_ref()
845 .is_some_and(|stream| stream.is_disturbed())
846 }
847
848 fn is_unusable(&self) -> bool {
849 let body_stream = self.body_stream.get();
850 body_stream
851 .as_ref()
852 .is_some_and(|stream| stream.is_disturbed() || stream.is_locked())
853 }
854
855 fn body(&self) -> Option<DomRoot<ReadableStream>> {
856 self.body_stream.get()
857 }
858
859 fn get_mime_type(&self, cx: &mut js::context::JSContext) -> Vec<u8> {
860 let headers = self.Headers(cx);
861 headers.extract_mime_type()
862 }
863}
864
865impl Convert<CacheMode> for RequestCache {
866 fn convert(self) -> CacheMode {
867 match self {
868 RequestCache::Default => CacheMode::Default,
869 RequestCache::No_store => CacheMode::NoStore,
870 RequestCache::Reload => CacheMode::Reload,
871 RequestCache::No_cache => CacheMode::NoCache,
872 RequestCache::Force_cache => CacheMode::ForceCache,
873 RequestCache::Only_if_cached => CacheMode::OnlyIfCached,
874 }
875 }
876}
877
878impl Convert<RequestCache> for CacheMode {
879 fn convert(self) -> RequestCache {
880 match self {
881 CacheMode::Default => RequestCache::Default,
882 CacheMode::NoStore => RequestCache::No_store,
883 CacheMode::Reload => RequestCache::Reload,
884 CacheMode::NoCache => RequestCache::No_cache,
885 CacheMode::ForceCache => RequestCache::Force_cache,
886 CacheMode::OnlyIfCached => RequestCache::Only_if_cached,
887 }
888 }
889}
890
891impl Convert<CredentialsMode> for RequestCredentials {
892 fn convert(self) -> CredentialsMode {
893 match self {
894 RequestCredentials::Omit => CredentialsMode::Omit,
895 RequestCredentials::Same_origin => CredentialsMode::CredentialsSameOrigin,
896 RequestCredentials::Include => CredentialsMode::Include,
897 }
898 }
899}
900
901impl Convert<RequestCredentials> for CredentialsMode {
902 fn convert(self) -> RequestCredentials {
903 match self {
904 CredentialsMode::Omit => RequestCredentials::Omit,
905 CredentialsMode::CredentialsSameOrigin => RequestCredentials::Same_origin,
906 CredentialsMode::Include => RequestCredentials::Include,
907 }
908 }
909}
910
911impl Convert<Destination> for RequestDestination {
912 fn convert(self) -> Destination {
913 match self {
914 RequestDestination::_empty => Destination::None,
915 RequestDestination::Audio => Destination::Audio,
916 RequestDestination::Document => Destination::Document,
917 RequestDestination::Embed => Destination::Embed,
918 RequestDestination::Font => Destination::Font,
919 RequestDestination::Frame => Destination::Frame,
920 RequestDestination::Iframe => Destination::IFrame,
921 RequestDestination::Image => Destination::Image,
922 RequestDestination::Manifest => Destination::Manifest,
923 RequestDestination::Json => Destination::Json,
924 RequestDestination::Object => Destination::Object,
925 RequestDestination::Report => Destination::Report,
926 RequestDestination::Script => Destination::Script,
927 RequestDestination::Sharedworker => Destination::SharedWorker,
928 RequestDestination::Style => Destination::Style,
929 RequestDestination::Text => Destination::Text,
930 RequestDestination::Track => Destination::Track,
931 RequestDestination::Video => Destination::Video,
932 RequestDestination::Worker => Destination::Worker,
933 RequestDestination::Xslt => Destination::Xslt,
934 }
935 }
936}
937
938impl Convert<RequestDestination> for Destination {
939 fn convert(self) -> RequestDestination {
940 match self {
941 Destination::None => RequestDestination::_empty,
942 Destination::Audio => RequestDestination::Audio,
943 Destination::Document => RequestDestination::Document,
944 Destination::Embed => RequestDestination::Embed,
945 Destination::Font => RequestDestination::Font,
946 Destination::Frame => RequestDestination::Frame,
947 Destination::IFrame => RequestDestination::Iframe,
948 Destination::Image => RequestDestination::Image,
949 Destination::Manifest => RequestDestination::Manifest,
950 Destination::Json => RequestDestination::Json,
951 Destination::Object => RequestDestination::Object,
952 Destination::Report => RequestDestination::Report,
953 Destination::Script => RequestDestination::Script,
954 Destination::ServiceWorker | Destination::AudioWorklet | Destination::PaintWorklet => {
955 panic!("ServiceWorker request destination should not be exposed to DOM")
956 },
957 Destination::SharedWorker => RequestDestination::Sharedworker,
958 Destination::Style => RequestDestination::Style,
959 Destination::Text => RequestDestination::Text,
960 Destination::Track => RequestDestination::Track,
961 Destination::Video => RequestDestination::Video,
962 Destination::Worker => RequestDestination::Worker,
963 Destination::Xslt => RequestDestination::Xslt,
964 Destination::WebIdentity => RequestDestination::_empty,
965 }
966 }
967}
968
969impl Convert<NetTraitsRequestMode> for RequestMode {
970 fn convert(self) -> NetTraitsRequestMode {
971 match self {
972 RequestMode::Navigate => NetTraitsRequestMode::Navigate,
973 RequestMode::Same_origin => NetTraitsRequestMode::SameOrigin,
974 RequestMode::No_cors => NetTraitsRequestMode::NoCors,
975 RequestMode::Cors => NetTraitsRequestMode::CorsMode,
976 }
977 }
978}
979
980impl Convert<RequestMode> for NetTraitsRequestMode {
981 fn convert(self) -> RequestMode {
982 match self {
983 NetTraitsRequestMode::Navigate => RequestMode::Navigate,
984 NetTraitsRequestMode::SameOrigin => RequestMode::Same_origin,
985 NetTraitsRequestMode::NoCors => RequestMode::No_cors,
986 NetTraitsRequestMode::CorsMode => RequestMode::Cors,
987 NetTraitsRequestMode::WebSocket { .. } => {
988 unreachable!("Websocket request mode should never be exposed to Dom")
989 },
990 }
991 }
992}
993
994impl Convert<MsgReferrerPolicy> for ReferrerPolicy {
995 fn convert(self) -> MsgReferrerPolicy {
996 match self {
997 ReferrerPolicy::_empty => MsgReferrerPolicy::EmptyString,
998 ReferrerPolicy::No_referrer => MsgReferrerPolicy::NoReferrer,
999 ReferrerPolicy::No_referrer_when_downgrade => {
1000 MsgReferrerPolicy::NoReferrerWhenDowngrade
1001 },
1002 ReferrerPolicy::Origin => MsgReferrerPolicy::Origin,
1003 ReferrerPolicy::Origin_when_cross_origin => MsgReferrerPolicy::OriginWhenCrossOrigin,
1004 ReferrerPolicy::Unsafe_url => MsgReferrerPolicy::UnsafeUrl,
1005 ReferrerPolicy::Same_origin => MsgReferrerPolicy::SameOrigin,
1006 ReferrerPolicy::Strict_origin => MsgReferrerPolicy::StrictOrigin,
1007 ReferrerPolicy::Strict_origin_when_cross_origin => {
1008 MsgReferrerPolicy::StrictOriginWhenCrossOrigin
1009 },
1010 }
1011 }
1012}
1013
1014impl Convert<ReferrerPolicy> for MsgReferrerPolicy {
1015 fn convert(self) -> ReferrerPolicy {
1016 match self {
1017 MsgReferrerPolicy::EmptyString => ReferrerPolicy::_empty,
1018 MsgReferrerPolicy::NoReferrer => ReferrerPolicy::No_referrer,
1019 MsgReferrerPolicy::NoReferrerWhenDowngrade => {
1020 ReferrerPolicy::No_referrer_when_downgrade
1021 },
1022 MsgReferrerPolicy::Origin => ReferrerPolicy::Origin,
1023 MsgReferrerPolicy::OriginWhenCrossOrigin => ReferrerPolicy::Origin_when_cross_origin,
1024 MsgReferrerPolicy::UnsafeUrl => ReferrerPolicy::Unsafe_url,
1025 MsgReferrerPolicy::SameOrigin => ReferrerPolicy::Same_origin,
1026 MsgReferrerPolicy::StrictOrigin => ReferrerPolicy::Strict_origin,
1027 MsgReferrerPolicy::StrictOriginWhenCrossOrigin => {
1028 ReferrerPolicy::Strict_origin_when_cross_origin
1029 },
1030 }
1031 }
1032}
1033
1034impl Convert<RedirectMode> for RequestRedirect {
1035 fn convert(self) -> RedirectMode {
1036 match self {
1037 RequestRedirect::Follow => RedirectMode::Follow,
1038 RequestRedirect::Error => RedirectMode::Error,
1039 RequestRedirect::Manual => RedirectMode::Manual,
1040 }
1041 }
1042}
1043
1044impl Convert<RequestRedirect> for RedirectMode {
1045 fn convert(self) -> RequestRedirect {
1046 match self {
1047 RedirectMode::Follow => RequestRedirect::Follow,
1048 RedirectMode::Error => RequestRedirect::Error,
1049 RedirectMode::Manual => RequestRedirect::Manual,
1050 }
1051 }
1052}