1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 use ReferrerPolicy; 6 use hyper::header::Headers; 7 use hyper::method::Method; 8 use msg::constellation_msg::PipelineId; 9 use servo_url::{ImmutableOrigin, ServoUrl}; 10 use std::default::Default; 11 12 /// An [initiator](https://fetch.spec.whatwg.org/#concept-request-initiator) 13 #[derive(Clone, Copy, MallocSizeOf, PartialEq)] 14 pub enum Initiator { 15 None, 16 Download, 17 ImageSet, 18 Manifest, 19 XSLT, 20 } 21 22 /// A request [destination](https://fetch.spec.whatwg.org/#concept-request-destination) 23 #[derive(Clone, Copy, Deserialize, MallocSizeOf, PartialEq, Serialize)] 24 pub enum Destination { 25 None, 26 Audio, 27 Document, 28 Embed, 29 Font, 30 Image, 31 Manifest, 32 Object, 33 Report, 34 Script, 35 ServiceWorker, 36 SharedWorker, 37 Style, 38 Track, 39 Video, 40 Worker, 41 Xslt, 42 } 43 44 impl Destination { 45 /// https://fetch.spec.whatwg.org/#request-destination-script-like 46 #[inline] is_script_like(&self) -> bool47 pub fn is_script_like(&self) -> bool { 48 *self == Destination::Script || 49 *self == Destination::ServiceWorker || 50 *self == Destination::SharedWorker || 51 *self == Destination::Worker 52 } 53 } 54 55 /// A request [origin](https://fetch.spec.whatwg.org/#concept-request-origin) 56 #[derive(Clone, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] 57 pub enum Origin { 58 Client, 59 Origin(ImmutableOrigin), 60 } 61 62 /// A [referer](https://fetch.spec.whatwg.org/#concept-request-referrer) 63 #[derive(Clone, Deserialize, MallocSizeOf, PartialEq, Serialize)] 64 pub enum Referrer { 65 NoReferrer, 66 /// Default referrer if nothing is specified 67 Client, 68 ReferrerUrl(ServoUrl), 69 } 70 71 /// A [request mode](https://fetch.spec.whatwg.org/#concept-request-mode) 72 #[derive(Clone, Deserialize, MallocSizeOf, PartialEq, Serialize)] 73 pub enum RequestMode { 74 Navigate, 75 SameOrigin, 76 NoCors, 77 CorsMode, 78 WebSocket { protocols: Vec<String> } 79 } 80 81 /// Request [credentials mode](https://fetch.spec.whatwg.org/#concept-request-credentials-mode) 82 #[derive(Clone, Copy, Deserialize, MallocSizeOf, PartialEq, Serialize)] 83 pub enum CredentialsMode { 84 Omit, 85 CredentialsSameOrigin, 86 Include, 87 } 88 89 /// [Cache mode](https://fetch.spec.whatwg.org/#concept-request-cache-mode) 90 #[derive(Clone, Copy, Deserialize, MallocSizeOf, PartialEq, Serialize)] 91 pub enum CacheMode { 92 Default, 93 NoStore, 94 Reload, 95 NoCache, 96 ForceCache, 97 OnlyIfCached, 98 } 99 100 /// [Service-workers mode](https://fetch.spec.whatwg.org/#request-service-workers-mode) 101 #[derive(Clone, Copy, Deserialize, MallocSizeOf, PartialEq, Serialize)] 102 pub enum ServiceWorkersMode { 103 All, 104 Foreign, 105 None, 106 } 107 108 /// [Redirect mode](https://fetch.spec.whatwg.org/#concept-request-redirect-mode) 109 #[derive(Clone, Copy, Deserialize, MallocSizeOf, PartialEq, Serialize)] 110 pub enum RedirectMode { 111 Follow, 112 Error, 113 Manual, 114 } 115 116 /// [Response tainting](https://fetch.spec.whatwg.org/#concept-request-response-tainting) 117 #[derive(Clone, Copy, MallocSizeOf, PartialEq)] 118 pub enum ResponseTainting { 119 Basic, 120 CorsTainting, 121 Opaque, 122 } 123 124 /// [Window](https://fetch.spec.whatwg.org/#concept-request-window) 125 #[derive(Clone, Copy, MallocSizeOf, PartialEq)] 126 pub enum Window { 127 NoWindow, 128 Client, // TODO: Environmental settings object 129 } 130 131 /// [CORS settings attribute](https://html.spec.whatwg.org/multipage/#attr-crossorigin-anonymous) 132 #[derive(Clone, Copy, Deserialize, PartialEq, Serialize)] 133 pub enum CorsSettings { 134 Anonymous, 135 UseCredentials, 136 } 137 138 #[derive(Clone, Deserialize, MallocSizeOf, Serialize)] 139 pub struct RequestInit { 140 #[serde(deserialize_with = "::hyper_serde::deserialize", 141 serialize_with = "::hyper_serde::serialize")] 142 #[ignore_malloc_size_of = "Defined in hyper"] 143 pub method: Method, 144 pub url: ServoUrl, 145 #[serde(deserialize_with = "::hyper_serde::deserialize", 146 serialize_with = "::hyper_serde::serialize")] 147 #[ignore_malloc_size_of = "Defined in hyper"] 148 pub headers: Headers, 149 pub unsafe_request: bool, 150 pub body: Option<Vec<u8>>, 151 pub service_workers_mode: ServiceWorkersMode, 152 // TODO: client object 153 pub destination: Destination, 154 pub synchronous: bool, 155 pub mode: RequestMode, 156 pub cache_mode: CacheMode, 157 pub use_cors_preflight: bool, 158 pub credentials_mode: CredentialsMode, 159 pub use_url_credentials: bool, 160 pub origin: ImmutableOrigin, 161 // XXXManishearth these should be part of the client object 162 pub referrer_url: Option<ServoUrl>, 163 pub referrer_policy: Option<ReferrerPolicy>, 164 pub pipeline_id: Option<PipelineId>, 165 pub redirect_mode: RedirectMode, 166 pub integrity_metadata: String, 167 // to keep track of redirects 168 pub url_list: Vec<ServoUrl>, 169 } 170 171 impl Default for RequestInit { default() -> RequestInit172 fn default() -> RequestInit { 173 RequestInit { 174 method: Method::Get, 175 url: ServoUrl::parse("about:blank").unwrap(), 176 headers: Headers::new(), 177 unsafe_request: false, 178 body: None, 179 service_workers_mode: ServiceWorkersMode::All, 180 destination: Destination::None, 181 synchronous: false, 182 mode: RequestMode::NoCors, 183 cache_mode: CacheMode::Default, 184 use_cors_preflight: false, 185 credentials_mode: CredentialsMode::Omit, 186 use_url_credentials: false, 187 origin: ImmutableOrigin::new_opaque(), 188 referrer_url: None, 189 referrer_policy: None, 190 pipeline_id: None, 191 redirect_mode: RedirectMode::Follow, 192 integrity_metadata: "".to_owned(), 193 url_list: vec![], 194 } 195 } 196 } 197 198 /// A [Request](https://fetch.spec.whatwg.org/#concept-request) as defined by 199 /// the Fetch spec. 200 #[derive(Clone, MallocSizeOf)] 201 pub struct Request { 202 /// <https://fetch.spec.whatwg.org/#concept-request-method> 203 #[ignore_malloc_size_of = "Defined in hyper"] 204 pub method: Method, 205 /// <https://fetch.spec.whatwg.org/#local-urls-only-flag> 206 pub local_urls_only: bool, 207 /// <https://fetch.spec.whatwg.org/#sandboxed-storage-area-urls-flag> 208 pub sandboxed_storage_area_urls: bool, 209 /// <https://fetch.spec.whatwg.org/#concept-request-header-list> 210 #[ignore_malloc_size_of = "Defined in hyper"] 211 pub headers: Headers, 212 /// <https://fetch.spec.whatwg.org/#unsafe-request-flag> 213 pub unsafe_request: bool, 214 /// <https://fetch.spec.whatwg.org/#concept-request-body> 215 pub body: Option<Vec<u8>>, 216 // TODO: client object 217 pub window: Window, 218 // TODO: target browsing context 219 /// <https://fetch.spec.whatwg.org/#request-keepalive-flag> 220 pub keep_alive: bool, 221 /// <https://fetch.spec.whatwg.org/#request-service-workers-mode> 222 pub service_workers_mode: ServiceWorkersMode, 223 /// <https://fetch.spec.whatwg.org/#concept-request-initiator> 224 pub initiator: Initiator, 225 /// <https://fetch.spec.whatwg.org/#concept-request-destination> 226 pub destination: Destination, 227 // TODO: priority object 228 /// <https://fetch.spec.whatwg.org/#concept-request-origin> 229 pub origin: Origin, 230 /// <https://fetch.spec.whatwg.org/#concept-request-referrer> 231 pub referrer: Referrer, 232 /// <https://fetch.spec.whatwg.org/#concept-request-referrer-policy> 233 pub referrer_policy: Option<ReferrerPolicy>, 234 pub pipeline_id: Option<PipelineId>, 235 /// <https://fetch.spec.whatwg.org/#synchronous-flag> 236 pub synchronous: bool, 237 /// <https://fetch.spec.whatwg.org/#concept-request-mode> 238 pub mode: RequestMode, 239 /// <https://fetch.spec.whatwg.org/#use-cors-preflight-flag> 240 pub use_cors_preflight: bool, 241 /// <https://fetch.spec.whatwg.org/#concept-request-credentials-mode> 242 pub credentials_mode: CredentialsMode, 243 /// <https://fetch.spec.whatwg.org/#concept-request-use-url-credentials-flag> 244 pub use_url_credentials: bool, 245 /// <https://fetch.spec.whatwg.org/#concept-request-cache-mode> 246 pub cache_mode: CacheMode, 247 /// <https://fetch.spec.whatwg.org/#concept-request-redirect-mode> 248 pub redirect_mode: RedirectMode, 249 /// <https://fetch.spec.whatwg.org/#concept-request-integrity-metadata> 250 pub integrity_metadata: String, 251 // Use the last method on url_list to act as spec current url field, and 252 // first method to act as spec url field 253 /// <https://fetch.spec.whatwg.org/#concept-request-url-list> 254 pub url_list: Vec<ServoUrl>, 255 /// <https://fetch.spec.whatwg.org/#concept-request-redirect-count> 256 pub redirect_count: u32, 257 /// <https://fetch.spec.whatwg.org/#concept-request-response-tainting> 258 pub response_tainting: ResponseTainting, 259 } 260 261 impl Request { new(url: ServoUrl, origin: Option<Origin>, pipeline_id: Option<PipelineId>) -> Request262 pub fn new(url: ServoUrl, 263 origin: Option<Origin>, 264 pipeline_id: Option<PipelineId>) 265 -> Request { 266 Request { 267 method: Method::Get, 268 local_urls_only: false, 269 sandboxed_storage_area_urls: false, 270 headers: Headers::new(), 271 unsafe_request: false, 272 body: None, 273 window: Window::Client, 274 keep_alive: false, 275 service_workers_mode: ServiceWorkersMode::All, 276 initiator: Initiator::None, 277 destination: Destination::None, 278 origin: origin.unwrap_or(Origin::Client), 279 referrer: Referrer::Client, 280 referrer_policy: None, 281 pipeline_id: pipeline_id, 282 synchronous: false, 283 mode: RequestMode::NoCors, 284 use_cors_preflight: false, 285 credentials_mode: CredentialsMode::Omit, 286 use_url_credentials: false, 287 cache_mode: CacheMode::Default, 288 redirect_mode: RedirectMode::Follow, 289 integrity_metadata: String::new(), 290 url_list: vec![url], 291 redirect_count: 0, 292 response_tainting: ResponseTainting::Basic, 293 } 294 } 295 from_init(init: RequestInit) -> Request296 pub fn from_init(init: RequestInit) -> Request { 297 let mut req = Request::new(init.url.clone(), 298 Some(Origin::Origin(init.origin)), 299 init.pipeline_id); 300 req.method = init.method; 301 req.headers = init.headers; 302 req.unsafe_request = init.unsafe_request; 303 req.body = init.body; 304 req.service_workers_mode = init.service_workers_mode; 305 req.destination = init.destination; 306 req.synchronous = init.synchronous; 307 req.mode = init.mode; 308 req.use_cors_preflight = init.use_cors_preflight; 309 req.credentials_mode = init.credentials_mode; 310 req.use_url_credentials = init.use_url_credentials; 311 req.cache_mode = init.cache_mode; 312 req.referrer = if let Some(url) = init.referrer_url { 313 Referrer::ReferrerUrl(url) 314 } else { 315 Referrer::NoReferrer 316 }; 317 req.referrer_policy = init.referrer_policy; 318 req.pipeline_id = init.pipeline_id; 319 req.redirect_mode = init.redirect_mode; 320 let mut url_list = init.url_list; 321 if url_list.is_empty() { 322 url_list.push(init.url); 323 } 324 req.redirect_count = url_list.len() as u32 - 1; 325 req.url_list = url_list; 326 req.integrity_metadata = init.integrity_metadata; 327 req 328 } 329 330 /// <https://fetch.spec.whatwg.org/#concept-request-url> url(&self) -> ServoUrl331 pub fn url(&self) -> ServoUrl { 332 self.url_list.first().unwrap().clone() 333 } 334 335 /// <https://fetch.spec.whatwg.org/#concept-request-current-url> current_url(&self) -> ServoUrl336 pub fn current_url(&self) -> ServoUrl { 337 self.url_list.last().unwrap().clone() 338 } 339 340 /// <https://fetch.spec.whatwg.org/#concept-request-current-url> current_url_mut(&mut self) -> &mut ServoUrl341 pub fn current_url_mut(&mut self) -> &mut ServoUrl { 342 self.url_list.last_mut().unwrap() 343 } 344 345 /// <https://fetch.spec.whatwg.org/#navigation-request> is_navigation_request(&self) -> bool346 pub fn is_navigation_request(&self) -> bool { 347 self.destination == Destination::Document 348 } 349 350 /// <https://fetch.spec.whatwg.org/#subresource-request> is_subresource_request(&self) -> bool351 pub fn is_subresource_request(&self) -> bool { 352 match self.destination { 353 Destination::Audio | Destination::Font | Destination::Image | Destination::Manifest | 354 Destination::Script | Destination::Style | Destination::Track | Destination::Video | 355 Destination::Xslt | Destination::None => true, 356 _ => false, 357 } 358 } 359 } 360 361 impl Referrer { to_url(&self) -> Option<&ServoUrl>362 pub fn to_url(&self) -> Option<&ServoUrl> { 363 match *self { 364 Referrer::NoReferrer | Referrer::Client => None, 365 Referrer::ReferrerUrl(ref url) => Some(url), 366 } 367 } 368 } 369