/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use ReferrerPolicy; use hyper::header::Headers; use hyper::method::Method; use msg::constellation_msg::PipelineId; use servo_url::{ImmutableOrigin, ServoUrl}; use std::default::Default; /// An [initiator](https://fetch.spec.whatwg.org/#concept-request-initiator) #[derive(Clone, Copy, MallocSizeOf, PartialEq)] pub enum Initiator { None, Download, ImageSet, Manifest, XSLT, } /// A request [destination](https://fetch.spec.whatwg.org/#concept-request-destination) #[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub enum Destination { None, Audio, Document, Embed, Font, Image, Manifest, Object, Report, Script, ServiceWorker, SharedWorker, Style, Track, Video, Worker, Xslt, } impl Destination { /// https://fetch.spec.whatwg.org/#request-destination-script-like #[inline] pub fn is_script_like(&self) -> bool { *self == Destination::Script || *self == Destination::ServiceWorker || *self == Destination::SharedWorker || *self == Destination::Worker } } /// A request [origin](https://fetch.spec.whatwg.org/#concept-request-origin) #[derive(Clone, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub enum Origin { Client, Origin(ImmutableOrigin), } /// A [referer](https://fetch.spec.whatwg.org/#concept-request-referrer) #[derive(Clone, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub enum Referrer { NoReferrer, /// Default referrer if nothing is specified Client, ReferrerUrl(ServoUrl), } /// A [request mode](https://fetch.spec.whatwg.org/#concept-request-mode) #[derive(Clone, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub enum RequestMode { Navigate, SameOrigin, NoCors, CorsMode, WebSocket { protocols: Vec } } /// Request [credentials mode](https://fetch.spec.whatwg.org/#concept-request-credentials-mode) #[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub enum CredentialsMode { Omit, CredentialsSameOrigin, Include, } /// [Cache mode](https://fetch.spec.whatwg.org/#concept-request-cache-mode) #[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub enum CacheMode { Default, NoStore, Reload, NoCache, ForceCache, OnlyIfCached, } /// [Service-workers mode](https://fetch.spec.whatwg.org/#request-service-workers-mode) #[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub enum ServiceWorkersMode { All, Foreign, None, } /// [Redirect mode](https://fetch.spec.whatwg.org/#concept-request-redirect-mode) #[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub enum RedirectMode { Follow, Error, Manual, } /// [Response tainting](https://fetch.spec.whatwg.org/#concept-request-response-tainting) #[derive(Clone, Copy, MallocSizeOf, PartialEq)] pub enum ResponseTainting { Basic, CorsTainting, Opaque, } /// [Window](https://fetch.spec.whatwg.org/#concept-request-window) #[derive(Clone, Copy, MallocSizeOf, PartialEq)] pub enum Window { NoWindow, Client, // TODO: Environmental settings object } /// [CORS settings attribute](https://html.spec.whatwg.org/multipage/#attr-crossorigin-anonymous) #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] pub enum CorsSettings { Anonymous, UseCredentials, } #[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)] pub struct RequestInit { #[serde(deserialize_with = "::hyper_serde::deserialize", serialize_with = "::hyper_serde::serialize")] #[ignore_malloc_size_of = "Defined in hyper"] pub method: Method, pub url: ServoUrl, #[serde(deserialize_with = "::hyper_serde::deserialize", serialize_with = "::hyper_serde::serialize")] #[ignore_malloc_size_of = "Defined in hyper"] pub headers: Headers, pub unsafe_request: bool, pub body: Option>, pub service_workers_mode: ServiceWorkersMode, // TODO: client object pub destination: Destination, pub synchronous: bool, pub mode: RequestMode, pub cache_mode: CacheMode, pub use_cors_preflight: bool, pub credentials_mode: CredentialsMode, pub use_url_credentials: bool, pub origin: ImmutableOrigin, // XXXManishearth these should be part of the client object pub referrer_url: Option, pub referrer_policy: Option, pub pipeline_id: Option, pub redirect_mode: RedirectMode, pub integrity_metadata: String, // to keep track of redirects pub url_list: Vec, } impl Default for RequestInit { fn default() -> RequestInit { RequestInit { method: Method::Get, url: ServoUrl::parse("about:blank").unwrap(), headers: Headers::new(), unsafe_request: false, body: None, service_workers_mode: ServiceWorkersMode::All, destination: Destination::None, synchronous: false, mode: RequestMode::NoCors, cache_mode: CacheMode::Default, use_cors_preflight: false, credentials_mode: CredentialsMode::Omit, use_url_credentials: false, origin: ImmutableOrigin::new_opaque(), referrer_url: None, referrer_policy: None, pipeline_id: None, redirect_mode: RedirectMode::Follow, integrity_metadata: "".to_owned(), url_list: vec![], } } } /// A [Request](https://fetch.spec.whatwg.org/#concept-request) as defined by /// the Fetch spec. #[derive(Clone, MallocSizeOf)] pub struct Request { /// #[ignore_malloc_size_of = "Defined in hyper"] pub method: Method, /// pub local_urls_only: bool, /// pub sandboxed_storage_area_urls: bool, /// #[ignore_malloc_size_of = "Defined in hyper"] pub headers: Headers, /// pub unsafe_request: bool, /// pub body: Option>, // TODO: client object pub window: Window, // TODO: target browsing context /// pub keep_alive: bool, /// pub service_workers_mode: ServiceWorkersMode, /// pub initiator: Initiator, /// pub destination: Destination, // TODO: priority object /// pub origin: Origin, /// pub referrer: Referrer, /// pub referrer_policy: Option, pub pipeline_id: Option, /// pub synchronous: bool, /// pub mode: RequestMode, /// pub use_cors_preflight: bool, /// pub credentials_mode: CredentialsMode, /// pub use_url_credentials: bool, /// pub cache_mode: CacheMode, /// pub redirect_mode: RedirectMode, /// pub integrity_metadata: String, // Use the last method on url_list to act as spec current url field, and // first method to act as spec url field /// pub url_list: Vec, /// pub redirect_count: u32, /// pub response_tainting: ResponseTainting, } impl Request { pub fn new(url: ServoUrl, origin: Option, pipeline_id: Option) -> Request { Request { method: Method::Get, local_urls_only: false, sandboxed_storage_area_urls: false, headers: Headers::new(), unsafe_request: false, body: None, window: Window::Client, keep_alive: false, service_workers_mode: ServiceWorkersMode::All, initiator: Initiator::None, destination: Destination::None, origin: origin.unwrap_or(Origin::Client), referrer: Referrer::Client, referrer_policy: None, pipeline_id: pipeline_id, synchronous: false, mode: RequestMode::NoCors, use_cors_preflight: false, credentials_mode: CredentialsMode::Omit, use_url_credentials: false, cache_mode: CacheMode::Default, redirect_mode: RedirectMode::Follow, integrity_metadata: String::new(), url_list: vec![url], redirect_count: 0, response_tainting: ResponseTainting::Basic, } } pub fn from_init(init: RequestInit) -> Request { let mut req = Request::new(init.url.clone(), Some(Origin::Origin(init.origin)), init.pipeline_id); req.method = init.method; req.headers = init.headers; req.unsafe_request = init.unsafe_request; req.body = init.body; req.service_workers_mode = init.service_workers_mode; req.destination = init.destination; req.synchronous = init.synchronous; req.mode = init.mode; req.use_cors_preflight = init.use_cors_preflight; req.credentials_mode = init.credentials_mode; req.use_url_credentials = init.use_url_credentials; req.cache_mode = init.cache_mode; req.referrer = if let Some(url) = init.referrer_url { Referrer::ReferrerUrl(url) } else { Referrer::NoReferrer }; req.referrer_policy = init.referrer_policy; req.pipeline_id = init.pipeline_id; req.redirect_mode = init.redirect_mode; let mut url_list = init.url_list; if url_list.is_empty() { url_list.push(init.url); } req.redirect_count = url_list.len() as u32 - 1; req.url_list = url_list; req.integrity_metadata = init.integrity_metadata; req } /// pub fn url(&self) -> ServoUrl { self.url_list.first().unwrap().clone() } /// pub fn current_url(&self) -> ServoUrl { self.url_list.last().unwrap().clone() } /// pub fn current_url_mut(&mut self) -> &mut ServoUrl { self.url_list.last_mut().unwrap() } /// pub fn is_navigation_request(&self) -> bool { self.destination == Destination::Document } /// pub fn is_subresource_request(&self) -> bool { match self.destination { Destination::Audio | Destination::Font | Destination::Image | Destination::Manifest | Destination::Script | Destination::Style | Destination::Track | Destination::Video | Destination::Xslt | Destination::None => true, _ => false, } } } impl Referrer { pub fn to_url(&self) -> Option<&ServoUrl> { match *self { Referrer::NoReferrer | Referrer::Client => None, Referrer::ReferrerUrl(ref url) => Some(url), } } }