1use content_security_policy::Destination;
6use headers::{Error, Header};
7use http::{HeaderName, HeaderValue};
8use net_traits::request::RequestMode;
9
10static SEC_FETCH_DEST: HeaderName = HeaderName::from_static("sec-fetch-dest");
11
12static SEC_FETCH_MODE: HeaderName = HeaderName::from_static("sec-fetch-mode");
13
14static SEC_FETCH_SITE: HeaderName = HeaderName::from_static("sec-fetch-site");
15
16static SEC_FETCH_USER: HeaderName = HeaderName::from_static("sec-fetch-user");
17
18pub struct SecFetchDest(pub Destination);
20
21pub enum SecFetchMode {
26 SameOrigin,
27 Cors,
28 NoCors,
29 Navigate,
30 WebSocket,
31}
32
33pub struct SecFetchUser;
35
36#[derive(Eq, PartialEq)]
38pub enum SecFetchSite {
39 None,
40 SameOrigin,
41 SameSite,
42 CrossSite,
43}
44
45impl Header for SecFetchDest {
46 fn name() -> &'static HeaderName {
47 &SEC_FETCH_DEST
48 }
49
50 fn decode<'i, I>(_: &mut I) -> Result<Self, Error>
51 where
52 Self: Sized,
53 I: Iterator<Item = &'i HeaderValue>,
54 {
55 Err(Error::invalid())
57 }
58
59 fn encode<E>(&self, values: &mut E)
60 where
61 E: Extend<HeaderValue>,
62 {
63 let value = HeaderValue::from_static(destination_as_str(self.0));
64 values.extend(std::iter::once(value));
65 }
66}
67
68impl From<Destination> for SecFetchDest {
69 fn from(value: Destination) -> Self {
70 Self(value)
71 }
72}
73
74impl Header for SecFetchMode {
75 fn name() -> &'static HeaderName {
76 &SEC_FETCH_MODE
77 }
78
79 fn decode<'i, I>(_: &mut I) -> Result<Self, Error>
80 where
81 Self: Sized,
82 I: Iterator<Item = &'i HeaderValue>,
83 {
84 Err(Error::invalid())
86 }
87
88 fn encode<E>(&self, values: &mut E)
89 where
90 E: Extend<HeaderValue>,
91 {
92 let value = HeaderValue::from_static(self.as_str());
93 values.extend(std::iter::once(value));
94 }
95}
96
97impl<'a> From<&'a RequestMode> for SecFetchMode {
98 fn from(value: &'a RequestMode) -> Self {
99 match value {
100 RequestMode::SameOrigin => Self::SameOrigin,
101 RequestMode::CorsMode => Self::Cors,
102 RequestMode::NoCors => Self::NoCors,
103 RequestMode::Navigate => Self::Navigate,
104 RequestMode::WebSocket { .. } => Self::WebSocket,
105 }
106 }
107}
108
109impl Header for SecFetchSite {
110 fn name() -> &'static HeaderName {
111 &SEC_FETCH_SITE
112 }
113
114 fn decode<'i, I>(_: &mut I) -> Result<Self, Error>
115 where
116 Self: Sized,
117 I: Iterator<Item = &'i HeaderValue>,
118 {
119 Err(Error::invalid())
121 }
122
123 fn encode<E>(&self, values: &mut E)
124 where
125 E: Extend<HeaderValue>,
126 {
127 let s = match self {
128 Self::None => "none",
129 Self::SameSite => "same-site",
130 Self::CrossSite => "cross-site",
131 Self::SameOrigin => "same-origin",
132 };
133 let value = HeaderValue::from_static(s);
134 values.extend(std::iter::once(value));
135 }
136}
137
138impl Header for SecFetchUser {
139 fn name() -> &'static HeaderName {
140 &SEC_FETCH_USER
141 }
142
143 fn decode<'i, I>(_: &mut I) -> Result<Self, Error>
144 where
145 Self: Sized,
146 I: Iterator<Item = &'i HeaderValue>,
147 {
148 Err(Error::invalid())
150 }
151
152 fn encode<E>(&self, values: &mut E)
153 where
154 E: Extend<HeaderValue>,
155 {
156 let value = HeaderValue::from_static("?1");
157 values.extend(std::iter::once(value));
158 }
159}
160
161const fn destination_as_str(destination: Destination) -> &'static str {
162 match destination {
163 Destination::None => "empty",
164 Destination::Audio => "audio",
165 Destination::AudioWorklet => "audioworklet",
166 Destination::Document => "document",
167 Destination::Embed => "embed",
168 Destination::Font => "font",
169 Destination::Frame => "frame",
170 Destination::IFrame => "iframe",
171 Destination::Image => "image",
172 Destination::Json => "json",
173 Destination::Manifest => "manifest",
174 Destination::Object => "object",
175 Destination::PaintWorklet => "paintworklet",
176 Destination::Report => "report",
177 Destination::Script => "script",
178 Destination::ServiceWorker => "serviceworker",
179 Destination::SharedWorker => "sharedworker",
180 Destination::Style => "style",
181 Destination::Track => "track",
182 Destination::Video => "video",
183 Destination::WebIdentity => "webidentity",
184 Destination::Worker => "worker",
185 Destination::Xslt => "xslt",
186 }
187}
188
189impl SecFetchMode {
190 fn as_str(&self) -> &'static str {
192 match self {
193 Self::SameOrigin => "same-origin",
194 Self::Cors => "cors",
195 Self::NoCors => "no-cors",
196 Self::Navigate => "navigate",
197 Self::WebSocket => "websocket",
198 }
199 }
200}