1use std::cell::Ref;
6use std::rc::Rc;
7use std::str::FromStr;
8
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::rust::HandleObject;
16use net_traits::ReferrerPolicy as MsgReferrerPolicy;
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 script_bindings::cell::DomRefCell;
24use script_bindings::cformat;
25use script_bindings::reflector::{Reflector, reflect_dom_object_with_proto};
26use servo_url::ServoUrl;
27
28use crate::conversions::Convert;
29use crate::dom::abortsignal::AbortSignal;
30use crate::dom::bindings::codegen::Bindings::HeadersBinding::{HeadersInit, 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::bindings::trace::RootedTraceableBox;
40use crate::dom::globalscope::GlobalScope;
41use crate::dom::headers::{Guard, Headers};
42use crate::dom::promise::Promise;
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::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}
64
65impl Request {
66 fn new_inherited(global: &GlobalScope, url: ServoUrl) -> Request {
67 Request {
68 reflector_: Reflector::new(),
69 request: DomRefCell::new(net_request_from_global(global, url)),
70 body_stream: MutNullableDom::new(None),
71 headers: Default::default(),
72 signal: MutNullableDom::new(None),
73 }
74 }
75
76 pub(crate) fn new(
77 cx: &mut JSContext,
78 global: &GlobalScope,
79 proto: Option<HandleObject>,
80 url: ServoUrl,
81 ) -> DomRoot<Request> {
82 reflect_dom_object_with_proto(
83 cx,
84 Box::new(Request::new_inherited(global, url)),
85 global,
86 proto,
87 )
88 }
89
90 fn from_net_request(
91 cx: &mut JSContext,
92 global: &GlobalScope,
93 proto: Option<HandleObject>,
94 net_request: NetTraitsRequest,
95 ) -> DomRoot<Request> {
96 let r = Request::new(cx, global, proto, net_request.current_url());
97 *r.request.borrow_mut() = net_request;
98 r
99 }
100
101 pub(crate) fn constructor(
103 cx: &mut js::context::JSContext,
104 global: &GlobalScope,
105 proto: Option<HandleObject>,
106 mut input: RequestInfo,
107 init: &RequestInit,
108 ) -> Fallible<DomRoot<Request>> {
109 let temporary_request: NetTraitsRequest;
111
112 let mut fallback_mode: Option<NetTraitsRequestMode> = None;
114
115 let base_url = global.api_base_url();
117
118 let mut signal: Option<DomRoot<AbortSignal>> = None;
120
121 let mut input_body_is_unusable = false;
123
124 match input {
125 RequestInfo::USVString(USVString(ref usv_string)) => {
127 let parsed_url = base_url.join(usv_string);
129 if parsed_url.is_err() {
131 return Err(Error::Type(c"Url could not be parsed".to_owned()));
132 }
133 let url = parsed_url.unwrap();
135 if includes_credentials(&url) {
136 return Err(Error::Type(c"Url includes credentials".to_owned()));
137 }
138 temporary_request = net_request_from_global(global, url);
140 fallback_mode = Some(NetTraitsRequestMode::CorsMode);
142 },
143 RequestInfo::Request(ref input_request) => {
146 input_body_is_unusable = input_request.is_unusable();
148 temporary_request = input_request.request.borrow().clone();
150 signal = Some(input_request.Signal());
152 },
153 }
154
155 let origin = global.origin();
157 let origin = origin.immutable();
158
159 let mut traversable_for_user_prompts = TraversableForUserPrompts::Client;
161
162 if !init.window.handle().is_null_or_undefined() {
169 return Err(Error::Type(c"Window is present and is not null".to_owned()));
170 }
171
172 if !init.window.handle().is_undefined() {
174 traversable_for_user_prompts = TraversableForUserPrompts::NoTraversable;
175 }
176
177 let mut request: NetTraitsRequest;
179 request = net_request_from_global(global, temporary_request.current_url());
180 request.method = temporary_request.method;
181 request.headers = temporary_request.headers.clone();
182 request.unsafe_request = true;
183 request.traversable_for_user_prompts = traversable_for_user_prompts;
184 request.origin = Origin::Client;
186 request.referrer = temporary_request.referrer;
187 request.referrer_policy = temporary_request.referrer_policy;
188 request.mode = temporary_request.mode;
189 request.credentials_mode = temporary_request.credentials_mode;
190 request.cache_mode = temporary_request.cache_mode;
191 request.redirect_mode = temporary_request.redirect_mode;
192 request.integrity_metadata = temporary_request.integrity_metadata;
193 request.reload_navigation = temporary_request.reload_navigation;
195 request.history_navigation = temporary_request.history_navigation;
197
198 if init.body.is_some() ||
200 init.cache.is_some() ||
201 init.credentials.is_some() ||
202 init.duplex.is_some() ||
203 init.integrity.is_some() ||
204 init.headers.is_some() ||
205 init.keepalive.is_some() ||
206 init.method.is_some() ||
207 init.mode.is_some() ||
208 init.redirect.is_some() ||
209 init.referrer.is_some() ||
210 init.referrerPolicy.is_some() ||
211 !init.window.handle().is_undefined()
212 {
213 if request.mode == NetTraitsRequestMode::Navigate {
215 request.mode = NetTraitsRequestMode::SameOrigin;
216 }
217 request.reload_navigation = false;
219 request.history_navigation = false;
221 request.referrer = global.get_referrer();
225 request.referrer_policy = MsgReferrerPolicy::EmptyString;
227 }
232
233 if let Some(init_referrer) = init.referrer.as_ref() {
235 let referrer = &init_referrer.0;
237 if referrer.is_empty() {
239 request.referrer = Referrer::NoReferrer;
240 } else {
242 let parsed_referrer = base_url.join(referrer);
244 if parsed_referrer.is_err() {
246 return Err(Error::Type(c"Failed to parse referrer url".to_owned()));
247 }
248 if let Ok(parsed_referrer) = parsed_referrer {
252 if (parsed_referrer.cannot_be_a_base() &&
253 parsed_referrer.scheme() == "about" &&
254 parsed_referrer.path() == "client") ||
255 parsed_referrer.origin() != *origin
256 {
257 request.referrer = global.get_referrer();
259 } else {
260 request.referrer = Referrer::ReferrerUrl(parsed_referrer);
262 }
263 }
264 }
265 }
266
267 if let Some(init_referrerpolicy) = init.referrerPolicy.as_ref() {
269 let init_referrer_policy = (*init_referrerpolicy).convert();
270 request.referrer_policy = init_referrer_policy;
271 }
272
273 let mode = init.mode.as_ref().map(|m| (*m).convert()).or(fallback_mode);
275
276 if let Some(NetTraitsRequestMode::Navigate) = mode {
278 return Err(Error::Type(c"Request mode is Navigate".to_owned()));
279 }
280
281 if let Some(m) = mode {
283 request.mode = m;
284 }
285
286 if let Some(init_credentials) = init.credentials.as_ref() {
288 let credentials = (*init_credentials).convert();
289 request.credentials_mode = credentials;
290 }
291
292 if let Some(init_cache) = init.cache.as_ref() {
294 let cache = (*init_cache).convert();
295 request.cache_mode = cache;
296 }
297
298 if request.cache_mode == CacheMode::OnlyIfCached &&
301 request.mode != NetTraitsRequestMode::SameOrigin
302 {
303 return Err(Error::Type(
304 c"Cache is 'only-if-cached' and mode is not 'same-origin'".to_owned(),
305 ));
306 }
307
308 if let Some(init_redirect) = init.redirect.as_ref() {
310 let redirect = (*init_redirect).convert();
311 request.redirect_mode = redirect;
312 }
313
314 if let Some(init_integrity) = init.integrity.as_ref() {
316 let integrity = init_integrity.to_string();
317 request.integrity_metadata = integrity;
318 }
319
320 if let Some(init_keepalive) = init.keepalive {
322 request.keep_alive = init_keepalive;
323 }
324
325 if let Some(init_method) = init.method.as_ref() {
328 if !is_method(init_method) {
330 return Err(Error::Type(c"Method is not a method".to_owned()));
331 }
332 if is_forbidden_method(init_method) {
333 return Err(Error::Type(c"Method is forbidden".to_owned()));
334 }
335 let method = match init_method.as_str() {
337 Some(s) => normalize_method(s)
338 .map_err(|e| Error::Type(cformat!("Method is not valid: {:?}", e)))?,
339 None => return Err(Error::Type(c"Method is not a valid UTF8".to_owned())),
340 };
341 request.method = method;
343 }
344
345 if let Some(init_signal) = init.signal.as_ref() {
347 signal = init_signal.clone();
348 }
349 let request = Request::from_net_request(cx, global, proto, request);
359
360 let signals = signal.map_or(vec![], |s| vec![s]);
362 request
365 .signal
366 .set(Some(&AbortSignal::create_dependent_abort_signal(
367 cx, signals, global,
368 )));
369
370 request
376 .headers
377 .or_init(|| Headers::for_request(cx, &request.global()));
378
379 let headers_copy = init
383 .headers
384 .as_ref()
385 .map(|possible_header| match possible_header {
386 HeadersInit::ByteStringSequenceSequence(init_sequence) => {
387 HeadersInit::ByteStringSequenceSequence(init_sequence.clone())
388 },
389 HeadersInit::ByteStringByteStringRecord(init_map) => {
390 HeadersInit::ByteStringByteStringRecord(init_map.clone())
391 },
392 });
393
394 if request.request.borrow().mode == NetTraitsRequestMode::NoCors {
405 let borrowed_request = request.request.borrow();
406 if !is_cors_safelisted_method(&borrowed_request.method) {
408 return Err(Error::Type(
409 c"The mode is 'no-cors' but the method is not a cors-safelisted method"
410 .to_owned(),
411 ));
412 }
413 request.Headers(cx).set_guard(Guard::RequestNoCors);
415 }
416
417 match headers_copy {
418 None => {
419 if let RequestInfo::Request(ref input_request) = input {
426 request
427 .Headers(cx)
428 .copy_from_headers(&input_request.Headers(cx))?;
429 }
430 },
431 Some(headers_copy) => request.Headers(cx).fill(Some(headers_copy))?,
433 }
434
435 request.request.borrow_mut().headers = request.Headers(cx).get_headers_list();
438
439 let input_body = if let RequestInfo::Request(ref mut input_request) = input {
441 let mut input_request_request = input_request.request.borrow_mut();
442 request.body_stream.set(input_request.body().as_deref());
443 input_request_request.body.take()
444 } else {
445 None
446 };
447
448 if init.body.as_ref().is_some_and(|body| body.is_some()) || input_body.is_some() {
451 let req = request.request.borrow();
452 let req_method = &req.method;
453 match *req_method {
454 HttpMethod::GET => {
455 return Err(Error::Type(
456 c"Init's body is non-null, and request method is GET".to_owned(),
457 ));
458 },
459 HttpMethod::HEAD => {
460 return Err(Error::Type(
461 c"Init's body is non-null, and request method is HEAD".to_owned(),
462 ));
463 },
464 _ => {},
465 }
466 }
467
468 let mut init_body = None;
470 if let Some(Some(ref input_init_body)) = init.body {
472 let mut body_with_type =
474 input_init_body.extract(cx, global, request.request.borrow().keep_alive)?;
475
476 if let Some(contents) = body_with_type.content_type.take() {
478 let content_type_header_name = b"Content-Type";
481 if !request
482 .Headers(cx)
483 .Has(ByteString::new(content_type_header_name.to_vec()))
484 .unwrap()
485 {
486 let content_type_header_value = contents.as_bytes();
487 request.Headers(cx).Append(
488 ByteString::new(content_type_header_name.to_vec()),
489 ByteString::new(content_type_header_value.to_vec()),
490 )?;
491
492 if let Ok(header_value) = HeaderValue::from_bytes(&content_type_header_value) {
496 request
497 .request
498 .borrow_mut()
499 .headers
500 .insert(CONTENT_TYPE, header_value);
501 }
502 }
503 }
504
505 let (net_body, stream) = body_with_type.into_net_request_body(cx);
507 request.body_stream.set(Some(&*stream));
508 init_body = Some(net_body);
509 }
510
511 let init_body_is_non_null = init_body.is_some();
518 let final_body = init_body.or(input_body);
519
520 if final_body
522 .as_ref()
523 .is_some_and(|body| body.source_is_null())
524 {
525 if init_body_is_non_null && init.duplex.is_none() {
528 return Err(Error::Type(
529 c"Request with a ReadableStream body must specify duplex".to_owned(),
530 ));
531 }
532 let request_mode = &request.request.borrow().mode;
534 if *request_mode != NetTraitsRequestMode::CorsMode &&
535 *request_mode != NetTraitsRequestMode::SameOrigin
536 {
537 return Err(Error::Type(
538 c"Request mode must be Cors or SameOrigin".to_owned(),
539 ));
540 }
541 }
544
545 if input_body_is_unusable {
552 return Err(Error::Type(c"Input body is unusable".to_owned()));
553 }
554
555 request.request.borrow_mut().body = final_body;
557
558 Ok(request)
559 }
560
561 fn clone_from(cx: &mut js::context::JSContext, r: &Request) -> Fallible<DomRoot<Request>> {
563 let req = r.request.borrow();
564 let url = req.url();
565 let headers_guard = r.Headers(cx).get_guard();
566
567 let mut new_req_inner = req.clone();
569 let body = new_req_inner.body.take();
570
571 let r_clone = Request::new(cx, &r.global(), None, url);
572 *r_clone.request.borrow_mut() = new_req_inner;
573
574 if let Some(body) = body {
577 r_clone.request.borrow_mut().body = Some(body);
578 }
579
580 r_clone.Headers(cx).copy_from_headers(&r.Headers(cx))?;
581 r_clone.Headers(cx).set_guard(headers_guard);
582
583 clone_body_stream_for_dom_body(cx, &r.body_stream, &r_clone.body_stream)?;
584
585 Ok(r_clone)
587 }
588
589 pub(crate) fn request(&self) -> Ref<'_, NetTraitsRequest> {
590 self.request.borrow()
591 }
592}
593
594fn net_request_from_global(global: &GlobalScope, url: ServoUrl) -> NetTraitsRequest {
595 let url = ensure_blob_referenced_by_url_is_kept_alive(global, url);
596 RequestBuilder::new(global.webview_id(), url, global.get_referrer())
597 .with_global_scope(global)
598 .build()
599}
600
601fn normalize_method(m: &str) -> Result<HttpMethod, InvalidMethod> {
603 match_ignore_ascii_case! { m,
604 "delete" => return Ok(HttpMethod::DELETE),
605 "get" => return Ok(HttpMethod::GET),
606 "head" => return Ok(HttpMethod::HEAD),
607 "options" => return Ok(HttpMethod::OPTIONS),
608 "post" => return Ok(HttpMethod::POST),
609 "put" => return Ok(HttpMethod::PUT),
610 _ => (),
611 }
612 debug!("Method: {:?}", m);
613 HttpMethod::from_str(m)
614}
615
616fn is_method(m: &ByteString) -> bool {
618 m.as_str().is_some()
619}
620
621fn is_cors_safelisted_method(m: &HttpMethod) -> bool {
623 m == HttpMethod::GET || m == HttpMethod::HEAD || m == HttpMethod::POST
624}
625
626fn includes_credentials(input: &ServoUrl) -> bool {
628 !input.username().is_empty() || input.password().is_some()
629}
630
631impl RequestMethods<crate::DomTypeHolder> for Request {
632 fn Constructor(
634 cx: &mut js::context::JSContext,
635 global: &GlobalScope,
636 proto: Option<HandleObject>,
637 input: RequestInfo,
638 init: RootedTraceableBox<RequestInit>,
639 ) -> Fallible<DomRoot<Request>> {
640 Self::constructor(cx, global, proto, input, &init)
641 }
642
643 fn Method(&self) -> ByteString {
645 let r = self.request.borrow();
646 ByteString::new(r.method.as_ref().as_bytes().into())
647 }
648
649 fn Url(&self) -> USVString {
651 let r = self.request.borrow();
652 USVString(r.url_list.first().map_or("", |u| u.as_str()).into())
653 }
654
655 fn Headers(&self, cx: &mut js::context::JSContext) -> DomRoot<Headers> {
657 self.headers.or_init(|| Headers::new(cx, &self.global()))
658 }
659
660 fn Destination(&self) -> RequestDestination {
662 self.request.borrow().destination.convert()
663 }
664
665 fn Referrer(&self) -> USVString {
667 let r = self.request.borrow();
668 USVString(match r.referrer {
669 Referrer::NoReferrer => String::from(""),
670 Referrer::Client(_) => String::from("about:client"),
671 Referrer::ReferrerUrl(ref u) => {
672 let u_c = u.clone();
673 u_c.into_string()
674 },
675 })
676 }
677
678 fn ReferrerPolicy(&self) -> ReferrerPolicy {
680 self.request.borrow().referrer_policy.convert()
681 }
682
683 fn Mode(&self) -> RequestMode {
685 self.request.borrow().mode.clone().convert()
686 }
687
688 fn Credentials(&self) -> RequestCredentials {
690 let r = self.request.borrow().clone();
691 r.credentials_mode.convert()
692 }
693
694 fn Cache(&self) -> RequestCache {
696 let r = self.request.borrow().clone();
697 r.cache_mode.convert()
698 }
699
700 fn Redirect(&self) -> RequestRedirect {
702 let r = self.request.borrow().clone();
703 r.redirect_mode.convert()
704 }
705
706 fn Integrity(&self) -> DOMString {
708 self.request.borrow().integrity_metadata.clone().into()
709 }
710
711 fn Duplex(&self) -> RequestDuplex {
713 RequestDuplex::Half
715 }
716
717 fn Keepalive(&self) -> bool {
719 self.request.borrow().keep_alive
720 }
721
722 fn IsReloadNavigation(&self) -> bool {
725 self.request.borrow().reload_navigation
726 }
727
728 fn IsHistoryNavigation(&self) -> bool {
731 self.request.borrow().history_navigation
732 }
733
734 fn GetBody(&self) -> Option<DomRoot<ReadableStream>> {
736 self.body()
737 }
738
739 fn BodyUsed(&self) -> bool {
741 self.is_body_used()
742 }
743
744 fn Signal(&self) -> DomRoot<AbortSignal> {
746 self.signal
747 .get()
748 .expect("Should always be initialized in constructor and clone")
749 }
750
751 fn Clone(&self, cx: &mut js::context::JSContext) -> Fallible<DomRoot<Request>> {
753 if self.is_unusable() {
755 return Err(Error::Type(c"Request is unusable".to_owned()));
756 }
757
758 let cloned_request = Request::clone_from(cx, self)?;
760 let signal = self.signal.get().expect("Should always be initialized");
762 let cloned_signal =
765 AbortSignal::create_dependent_abort_signal(cx, vec![signal], &self.global());
766 cloned_request.signal.set(Some(&cloned_signal));
771 Ok(cloned_request)
773 }
774
775 fn Text(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
777 consume_body(cx, self, BodyType::Text)
778 }
779
780 fn Blob(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
782 consume_body(cx, self, BodyType::Blob)
783 }
784
785 fn FormData(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
787 consume_body(cx, self, BodyType::FormData)
788 }
789
790 fn Json(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
792 consume_body(cx, self, BodyType::Json)
793 }
794
795 fn ArrayBuffer(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
797 consume_body(cx, self, BodyType::ArrayBuffer)
798 }
799
800 fn Bytes(&self, cx: &mut js::context::JSContext) -> Rc<Promise> {
802 consume_body(cx, self, BodyType::Bytes)
803 }
804
805 fn TextStream(&self, cx: &mut js::context::JSContext) -> Fallible<DomRoot<ReadableStream>> {
807 body_text_stream(cx, self)
808 }
809}
810
811impl BodyMixin for Request {
812 fn is_body_used(&self) -> bool {
813 let body_stream = self.body_stream.get();
814 body_stream
815 .as_ref()
816 .is_some_and(|stream| stream.is_disturbed())
817 }
818
819 fn is_unusable(&self) -> bool {
820 let body_stream = self.body_stream.get();
821 body_stream
822 .as_ref()
823 .is_some_and(|stream| stream.is_disturbed() || stream.is_locked())
824 }
825
826 fn body(&self) -> Option<DomRoot<ReadableStream>> {
827 self.body_stream.get()
828 }
829
830 fn get_mime_type(&self, cx: &mut js::context::JSContext) -> Vec<u8> {
831 let headers = self.Headers(cx);
832 headers.extract_mime_type()
833 }
834}
835
836impl Convert<CacheMode> for RequestCache {
837 fn convert(self) -> CacheMode {
838 match self {
839 RequestCache::Default => CacheMode::Default,
840 RequestCache::No_store => CacheMode::NoStore,
841 RequestCache::Reload => CacheMode::Reload,
842 RequestCache::No_cache => CacheMode::NoCache,
843 RequestCache::Force_cache => CacheMode::ForceCache,
844 RequestCache::Only_if_cached => CacheMode::OnlyIfCached,
845 }
846 }
847}
848
849impl Convert<RequestCache> for CacheMode {
850 fn convert(self) -> RequestCache {
851 match self {
852 CacheMode::Default => RequestCache::Default,
853 CacheMode::NoStore => RequestCache::No_store,
854 CacheMode::Reload => RequestCache::Reload,
855 CacheMode::NoCache => RequestCache::No_cache,
856 CacheMode::ForceCache => RequestCache::Force_cache,
857 CacheMode::OnlyIfCached => RequestCache::Only_if_cached,
858 }
859 }
860}
861
862impl Convert<CredentialsMode> for RequestCredentials {
863 fn convert(self) -> CredentialsMode {
864 match self {
865 RequestCredentials::Omit => CredentialsMode::Omit,
866 RequestCredentials::Same_origin => CredentialsMode::CredentialsSameOrigin,
867 RequestCredentials::Include => CredentialsMode::Include,
868 }
869 }
870}
871
872impl Convert<RequestCredentials> for CredentialsMode {
873 fn convert(self) -> RequestCredentials {
874 match self {
875 CredentialsMode::Omit => RequestCredentials::Omit,
876 CredentialsMode::CredentialsSameOrigin => RequestCredentials::Same_origin,
877 CredentialsMode::Include => RequestCredentials::Include,
878 }
879 }
880}
881
882impl Convert<Destination> for RequestDestination {
883 fn convert(self) -> Destination {
884 match self {
885 RequestDestination::_empty => Destination::None,
886 RequestDestination::Audio => Destination::Audio,
887 RequestDestination::Document => Destination::Document,
888 RequestDestination::Embed => Destination::Embed,
889 RequestDestination::Font => Destination::Font,
890 RequestDestination::Frame => Destination::Frame,
891 RequestDestination::Iframe => Destination::IFrame,
892 RequestDestination::Image => Destination::Image,
893 RequestDestination::Manifest => Destination::Manifest,
894 RequestDestination::Json => Destination::Json,
895 RequestDestination::Object => Destination::Object,
896 RequestDestination::Report => Destination::Report,
897 RequestDestination::Script => Destination::Script,
898 RequestDestination::Sharedworker => Destination::SharedWorker,
899 RequestDestination::Style => Destination::Style,
900 RequestDestination::Track => Destination::Track,
901 RequestDestination::Video => Destination::Video,
902 RequestDestination::Worker => Destination::Worker,
903 RequestDestination::Xslt => Destination::Xslt,
904 }
905 }
906}
907
908impl Convert<RequestDestination> for Destination {
909 fn convert(self) -> RequestDestination {
910 match self {
911 Destination::None => RequestDestination::_empty,
912 Destination::Audio => RequestDestination::Audio,
913 Destination::Document => RequestDestination::Document,
914 Destination::Embed => RequestDestination::Embed,
915 Destination::Font => RequestDestination::Font,
916 Destination::Frame => RequestDestination::Frame,
917 Destination::IFrame => RequestDestination::Iframe,
918 Destination::Image => RequestDestination::Image,
919 Destination::Manifest => RequestDestination::Manifest,
920 Destination::Json => RequestDestination::Json,
921 Destination::Object => RequestDestination::Object,
922 Destination::Report => RequestDestination::Report,
923 Destination::Script => RequestDestination::Script,
924 Destination::ServiceWorker | Destination::AudioWorklet | Destination::PaintWorklet => {
925 panic!("ServiceWorker request destination should not be exposed to DOM")
926 },
927 Destination::SharedWorker => RequestDestination::Sharedworker,
928 Destination::Style => RequestDestination::Style,
929 Destination::Track => RequestDestination::Track,
930 Destination::Video => RequestDestination::Video,
931 Destination::Worker => RequestDestination::Worker,
932 Destination::Xslt => RequestDestination::Xslt,
933 Destination::WebIdentity => RequestDestination::_empty,
934 }
935 }
936}
937
938impl Convert<NetTraitsRequestMode> for RequestMode {
939 fn convert(self) -> NetTraitsRequestMode {
940 match self {
941 RequestMode::Navigate => NetTraitsRequestMode::Navigate,
942 RequestMode::Same_origin => NetTraitsRequestMode::SameOrigin,
943 RequestMode::No_cors => NetTraitsRequestMode::NoCors,
944 RequestMode::Cors => NetTraitsRequestMode::CorsMode,
945 }
946 }
947}
948
949impl Convert<RequestMode> for NetTraitsRequestMode {
950 fn convert(self) -> RequestMode {
951 match self {
952 NetTraitsRequestMode::Navigate => RequestMode::Navigate,
953 NetTraitsRequestMode::SameOrigin => RequestMode::Same_origin,
954 NetTraitsRequestMode::NoCors => RequestMode::No_cors,
955 NetTraitsRequestMode::CorsMode => RequestMode::Cors,
956 NetTraitsRequestMode::WebSocket { .. } => {
957 unreachable!("Websocket request mode should never be exposed to Dom")
958 },
959 }
960 }
961}
962
963impl Convert<MsgReferrerPolicy> for ReferrerPolicy {
964 fn convert(self) -> MsgReferrerPolicy {
965 match self {
966 ReferrerPolicy::_empty => MsgReferrerPolicy::EmptyString,
967 ReferrerPolicy::No_referrer => MsgReferrerPolicy::NoReferrer,
968 ReferrerPolicy::No_referrer_when_downgrade => {
969 MsgReferrerPolicy::NoReferrerWhenDowngrade
970 },
971 ReferrerPolicy::Origin => MsgReferrerPolicy::Origin,
972 ReferrerPolicy::Origin_when_cross_origin => MsgReferrerPolicy::OriginWhenCrossOrigin,
973 ReferrerPolicy::Unsafe_url => MsgReferrerPolicy::UnsafeUrl,
974 ReferrerPolicy::Same_origin => MsgReferrerPolicy::SameOrigin,
975 ReferrerPolicy::Strict_origin => MsgReferrerPolicy::StrictOrigin,
976 ReferrerPolicy::Strict_origin_when_cross_origin => {
977 MsgReferrerPolicy::StrictOriginWhenCrossOrigin
978 },
979 }
980 }
981}
982
983impl Convert<ReferrerPolicy> for MsgReferrerPolicy {
984 fn convert(self) -> ReferrerPolicy {
985 match self {
986 MsgReferrerPolicy::EmptyString => ReferrerPolicy::_empty,
987 MsgReferrerPolicy::NoReferrer => ReferrerPolicy::No_referrer,
988 MsgReferrerPolicy::NoReferrerWhenDowngrade => {
989 ReferrerPolicy::No_referrer_when_downgrade
990 },
991 MsgReferrerPolicy::Origin => ReferrerPolicy::Origin,
992 MsgReferrerPolicy::OriginWhenCrossOrigin => ReferrerPolicy::Origin_when_cross_origin,
993 MsgReferrerPolicy::UnsafeUrl => ReferrerPolicy::Unsafe_url,
994 MsgReferrerPolicy::SameOrigin => ReferrerPolicy::Same_origin,
995 MsgReferrerPolicy::StrictOrigin => ReferrerPolicy::Strict_origin,
996 MsgReferrerPolicy::StrictOriginWhenCrossOrigin => {
997 ReferrerPolicy::Strict_origin_when_cross_origin
998 },
999 }
1000 }
1001}
1002
1003impl Convert<RedirectMode> for RequestRedirect {
1004 fn convert(self) -> RedirectMode {
1005 match self {
1006 RequestRedirect::Follow => RedirectMode::Follow,
1007 RequestRedirect::Error => RedirectMode::Error,
1008 RequestRedirect::Manual => RedirectMode::Manual,
1009 }
1010 }
1011}
1012
1013impl Convert<RequestRedirect> for RedirectMode {
1014 fn convert(self) -> RequestRedirect {
1015 match self {
1016 RedirectMode::Follow => RequestRedirect::Follow,
1017 RedirectMode::Error => RequestRedirect::Error,
1018 RedirectMode::Manual => RequestRedirect::Manual,
1019 }
1020 }
1021}