aboutsummaryrefslogtreecommitdiffstats
path: root/components/net_traits
diff options
context:
space:
mode:
Diffstat (limited to 'components/net_traits')
-rw-r--r--components/net_traits/Cargo.toml42
-rw-r--r--components/net_traits/blob_url_store.rs75
-rw-r--r--components/net_traits/fetch/headers.rs18
-rw-r--r--components/net_traits/filemanager_thread.rs190
-rw-r--r--components/net_traits/image/base.rs121
-rw-r--r--components/net_traits/image_cache.rs156
-rw-r--r--components/net_traits/lib.rs859
-rw-r--r--components/net_traits/pub_domains.rs159
-rw-r--r--components/net_traits/quality.rs87
-rw-r--r--components/net_traits/request.rs749
-rw-r--r--components/net_traits/response.rs364
-rw-r--r--components/net_traits/storage_thread.rs48
-rw-r--r--components/net_traits/tests/image.rs28
-rw-r--r--components/net_traits/tests/lib.rs212
-rw-r--r--components/net_traits/tests/pub_domains.rs122
-rw-r--r--components/net_traits/tests/whitespace.rs25
16 files changed, 0 insertions, 3255 deletions
diff --git a/components/net_traits/Cargo.toml b/components/net_traits/Cargo.toml
deleted file mode 100644
index 13005f40790..00000000000
--- a/components/net_traits/Cargo.toml
+++ /dev/null
@@ -1,42 +0,0 @@
-[package]
-name = "net_traits"
-version = "0.0.1"
-authors = ["The Servo Project Developers"]
-license = "MPL-2.0"
-edition = "2018"
-publish = false
-
-[lib]
-name = "net_traits"
-path = "lib.rs"
-test = false
-doctest = false
-
-[dependencies]
-content-security-policy = { workspace = true }
-cookie = { workspace = true }
-embedder_traits = { path = "../embedder_traits" }
-headers = { workspace = true }
-http = { workspace = true }
-hyper = { workspace = true }
-hyper_serde = { workspace = true }
-image = { workspace = true }
-ipc-channel = { workspace = true }
-lazy_static = { workspace = true }
-log = { workspace = true }
-malloc_size_of = { path = "../malloc_size_of" }
-malloc_size_of_derive = { workspace = true }
-mime = { workspace = true }
-msg = { path = "../msg" }
-num-traits = { workspace = true }
-percent-encoding = { workspace = true }
-pixels = { path = "../pixels" }
-rustls = { workspace = true }
-serde = { workspace = true }
-servo_arc = { path = "../servo_arc" }
-servo_rand = { path = "../rand" }
-servo_url = { path = "../url" }
-time = { workspace = true }
-url = { workspace = true }
-uuid = { workspace = true }
-webrender_api = { git = "https://github.com/servo/webrender" }
diff --git a/components/net_traits/blob_url_store.rs b/components/net_traits/blob_url_store.rs
deleted file mode 100644
index ab853b702c9..00000000000
--- a/components/net_traits/blob_url_store.rs
+++ /dev/null
@@ -1,75 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-use std::str::FromStr;
-
-use serde::{Deserialize, Serialize};
-use servo_url::ServoUrl;
-use url::Url;
-use uuid::Uuid;
-
-use crate::filemanager_thread::FileOrigin;
-
-/// Errors returned to Blob URL Store request
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
-pub enum BlobURLStoreError {
- /// Invalid File UUID
- InvalidFileID,
- /// Invalid URL origin
- InvalidOrigin,
- /// Invalid entry content
- InvalidEntry,
- /// Invalid range
- InvalidRange,
- /// External error, from like file system, I/O etc.
- External(String),
-}
-
-/// Standalone blob buffer object
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub struct BlobBuf {
- pub filename: Option<String>,
- /// MIME type string
- pub type_string: String,
- /// Size of content in bytes
- pub size: u64,
- /// Content of blob
- pub bytes: Vec<u8>,
-}
-
-/// Parse URL as Blob URL scheme's definition
-///
-/// <https://w3c.github.io/FileAPI/#DefinitionOfScheme>
-pub fn parse_blob_url(url: &ServoUrl) -> Result<(Uuid, FileOrigin), ()> {
- let url_inner = Url::parse(url.path()).map_err(|_| ())?;
- let segs = url_inner
- .path_segments()
- .map(|c| c.collect::<Vec<_>>())
- .ok_or(())?;
-
- if url.query().is_some() || segs.len() > 1 {
- return Err(());
- }
-
- let id = {
- let id = segs.first().ok_or(())?;
- Uuid::from_str(id).map_err(|_| ())?
- };
- Ok((id, get_blob_origin(&ServoUrl::from_url(url_inner))))
-}
-
-/// Given an URL, returning the Origin that a Blob created under this
-/// URL should have.
-///
-/// HACK(izgzhen): Not well-specified on spec, and it is a bit a hack
-/// both due to ambiguity of spec and that we have to serialization the
-/// Origin here.
-pub fn get_blob_origin(url: &ServoUrl) -> FileOrigin {
- if url.scheme() == "file" {
- // NOTE: by default this is "null" (Opaque), which is not ideal
- "file://".to_string()
- } else {
- url.origin().ascii_serialization()
- }
-}
diff --git a/components/net_traits/fetch/headers.rs b/components/net_traits/fetch/headers.rs
deleted file mode 100644
index ae95066bcf5..00000000000
--- a/components/net_traits/fetch/headers.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-use headers::HeaderMap;
-
-/// <https://fetch.spec.whatwg.org/#concept-header-list-get>
-pub fn get_value_from_header_list(name: &str, headers: &HeaderMap) -> Option<Vec<u8>> {
- let values = headers.get_all(name).iter().map(|val| val.as_bytes());
-
- // Step 1
- if values.size_hint() == (0, Some(0)) {
- return None;
- }
-
- // Step 2
- return Some(values.collect::<Vec<&[u8]>>().join(&[0x2C, 0x20][..]));
-}
diff --git a/components/net_traits/filemanager_thread.rs b/components/net_traits/filemanager_thread.rs
deleted file mode 100644
index ee18e295393..00000000000
--- a/components/net_traits/filemanager_thread.rs
+++ /dev/null
@@ -1,190 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-use std::cmp::{max, min};
-use std::ops::Range;
-use std::path::PathBuf;
-
-use embedder_traits::FilterPattern;
-use ipc_channel::ipc::IpcSender;
-use malloc_size_of_derive::MallocSizeOf;
-use num_traits::ToPrimitive;
-use serde::{Deserialize, Serialize};
-use uuid::Uuid;
-
-use crate::blob_url_store::{BlobBuf, BlobURLStoreError};
-
-// HACK: Not really process-safe now, we should send Origin
-// directly instead of this in future, blocked on #11722
-/// File manager store entry's origin
-pub type FileOrigin = String;
-
-/// A token modulating access to a file for a blob URL.
-pub enum FileTokenCheck {
- /// Checking against a token not required,
- /// used for accessing a file
- /// that isn't linked to from a blob URL.
- NotRequired,
- /// Checking against token required.
- Required(Uuid),
- /// Request should always fail,
- /// used for cases when a check is required,
- /// but no token could be acquired.
- ShouldFail,
-}
-
-/// Relative slice positions of a sequence,
-/// whose semantic should be consistent with (start, end) parameters in
-/// <https://w3c.github.io/FileAPI/#dfn-slice>
-#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
-pub struct RelativePos {
- /// Relative to first byte if non-negative,
- /// relative to one past last byte if negative,
- pub start: i64,
- /// Relative offset from first byte if Some(non-negative),
- /// relative to one past last byte if Some(negative),
- /// None if one past last byte
- pub end: Option<i64>,
-}
-
-impl RelativePos {
- /// Full range from start to end
- pub fn full_range() -> RelativePos {
- RelativePos {
- start: 0,
- end: None,
- }
- }
-
- /// Instantiate optional slice position parameters
- pub fn from_opts(start: Option<i64>, end: Option<i64>) -> RelativePos {
- RelativePos {
- start: start.unwrap_or(0),
- end,
- }
- }
-
- /// Slice the inner sliced range by repositioning
- pub fn slice_inner(&self, rel_pos: &RelativePos) -> RelativePos {
- RelativePos {
- start: self.start + rel_pos.start,
- end: match (self.end, rel_pos.end) {
- (Some(old_end), Some(rel_end)) => Some(old_end + rel_end),
- (old, None) => old,
- (None, rel) => rel,
- },
- }
- }
-
- /// Compute absolute range by giving the total size
- /// <https://w3c.github.io/FileAPI/#slice-method-algo>
- pub fn to_abs_range(&self, size: usize) -> Range<usize> {
- let size = size as i64;
-
- let start = {
- if self.start < 0 {
- max(size + self.start, 0)
- } else {
- min(self.start, size)
- }
- };
-
- let end = match self.end {
- Some(rel_end) => {
- if rel_end < 0 {
- max(size + rel_end, 0)
- } else {
- min(rel_end, size)
- }
- },
- None => size,
- };
-
- let span: i64 = max(end - start, 0);
-
- Range {
- start: start.to_usize().unwrap(),
- end: (start + span).to_usize().unwrap(),
- }
- }
-}
-
-/// Response to file selection request
-#[derive(Debug, Deserialize, Serialize)]
-pub struct SelectedFile {
- pub id: Uuid,
- pub filename: PathBuf,
- pub modified: u64,
- pub size: u64,
- // https://w3c.github.io/FileAPI/#dfn-type
- pub type_string: String,
-}
-
-#[derive(Debug, Deserialize, Serialize)]
-pub enum FileManagerThreadMsg {
- /// Select a single file. Last field is pre-selected file path for testing
- SelectFile(
- Vec<FilterPattern>,
- IpcSender<FileManagerResult<SelectedFile>>,
- FileOrigin,
- Option<String>,
- ),
-
- /// Select multiple files. Last field is pre-selected file paths for testing
- SelectFiles(
- Vec<FilterPattern>,
- IpcSender<FileManagerResult<Vec<SelectedFile>>>,
- FileOrigin,
- Option<Vec<String>>,
- ),
-
- /// Read FileID-indexed file in chunks, optionally check URL validity based on boolean flag
- ReadFile(
- IpcSender<FileManagerResult<ReadFileProgress>>,
- Uuid,
- FileOrigin,
- ),
-
- /// Add an entry as promoted memory-based blob
- PromoteMemory(Uuid, BlobBuf, bool, FileOrigin),
-
- /// Add a sliced entry pointing to the parent FileID, and send back the associated FileID
- /// as part of a valid Blob URL
- AddSlicedURLEntry(
- Uuid,
- RelativePos,
- IpcSender<Result<Uuid, BlobURLStoreError>>,
- FileOrigin,
- ),
-
- /// Decrease reference count and send back the acknowledgement
- DecRef(Uuid, FileOrigin, IpcSender<Result<(), BlobURLStoreError>>),
-
- /// Activate an internal FileID so it becomes valid as part of a Blob URL
- ActivateBlobURL(Uuid, IpcSender<Result<(), BlobURLStoreError>>, FileOrigin),
-
- /// Revoke Blob URL and send back the acknowledgement
- RevokeBlobURL(Uuid, FileOrigin, IpcSender<Result<(), BlobURLStoreError>>),
-}
-
-#[derive(Debug, Deserialize, Serialize)]
-pub enum ReadFileProgress {
- Meta(BlobBuf),
- Partial(Vec<u8>),
- EOF,
-}
-
-pub type FileManagerResult<T> = Result<T, FileManagerThreadError>;
-
-#[derive(Debug, Deserialize, Serialize)]
-pub enum FileManagerThreadError {
- /// The selection action is invalid due to exceptional reason
- InvalidSelection,
- /// The selection action is cancelled by user
- UserCancelled,
- /// Errors returned from file system request
- FileSystemError(String),
- /// Blob URL Store error
- BlobURLStoreError(BlobURLStoreError),
-}
diff --git a/components/net_traits/image/base.rs b/components/net_traits/image/base.rs
deleted file mode 100644
index 74e2d8823dc..00000000000
--- a/components/net_traits/image/base.rs
+++ /dev/null
@@ -1,121 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-use std::fmt;
-
-use image::ImageFormat;
-use ipc_channel::ipc::IpcSharedMemory;
-use log::debug;
-use malloc_size_of_derive::MallocSizeOf;
-use pixels::PixelFormat;
-use serde::{Deserialize, Serialize};
-use webrender_api::ImageKey;
-
-use crate::image_cache::CorsStatus;
-
-#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
-pub struct Image {
- pub width: u32,
- pub height: u32,
- pub format: PixelFormat,
- #[ignore_malloc_size_of = "Defined in ipc-channel"]
- pub bytes: IpcSharedMemory,
- #[ignore_malloc_size_of = "Defined in webrender_api"]
- pub id: Option<ImageKey>,
- pub cors_status: CorsStatus,
-}
-
-impl fmt::Debug for Image {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(
- f,
- "Image {{ width: {}, height: {}, format: {:?}, ..., id: {:?} }}",
- self.width, self.height, self.format, self.id
- )
- }
-}
-
-#[derive(Clone, Debug, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)]
-pub struct ImageMetadata {
- pub width: u32,
- pub height: u32,
-}
-
-// FIXME: Images must not be copied every frame. Instead we should atomically
-// reference count them.
-
-pub fn load_from_memory(buffer: &[u8], cors_status: CorsStatus) -> Option<Image> {
- if buffer.is_empty() {
- return None;
- }
-
- let image_fmt_result = detect_image_format(buffer);
- match image_fmt_result {
- Err(msg) => {
- debug!("{}", msg);
- None
- },
- Ok(_) => match image::load_from_memory(buffer) {
- Ok(image) => {
- let mut rgba = image.into_rgba8();
- pixels::rgba8_byte_swap_colors_inplace(&mut *rgba);
- Some(Image {
- width: rgba.width(),
- height: rgba.height(),
- format: PixelFormat::BGRA8,
- bytes: IpcSharedMemory::from_bytes(&*rgba),
- id: None,
- cors_status,
- })
- },
- Err(e) => {
- debug!("Image decoding error: {:?}", e);
- None
- },
- },
- }
-}
-
-// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img
-pub fn detect_image_format(buffer: &[u8]) -> Result<ImageFormat, &str> {
- if is_gif(buffer) {
- Ok(ImageFormat::Gif)
- } else if is_jpeg(buffer) {
- Ok(ImageFormat::Jpeg)
- } else if is_png(buffer) {
- Ok(ImageFormat::Png)
- } else if is_webp(buffer) {
- Ok(ImageFormat::WebP)
- } else if is_bmp(buffer) {
- Ok(ImageFormat::Bmp)
- } else if is_ico(buffer) {
- Ok(ImageFormat::Ico)
- } else {
- Err("Image Format Not Supported")
- }
-}
-
-fn is_gif(buffer: &[u8]) -> bool {
- buffer.starts_with(b"GIF87a") || buffer.starts_with(b"GIF89a")
-}
-
-fn is_jpeg(buffer: &[u8]) -> bool {
- buffer.starts_with(&[0xff, 0xd8, 0xff])
-}
-
-fn is_png(buffer: &[u8]) -> bool {
- buffer.starts_with(&[0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A])
-}
-
-fn is_bmp(buffer: &[u8]) -> bool {
- buffer.starts_with(&[0x42, 0x4D])
-}
-
-fn is_ico(buffer: &[u8]) -> bool {
- buffer.starts_with(&[0x00, 0x00, 0x01, 0x00])
-}
-
-fn is_webp(buffer: &[u8]) -> bool {
- buffer.starts_with(b"RIFF") && buffer.len() >= 14 && &buffer[8..14] == b"WEBPVP"
-}
diff --git a/components/net_traits/image_cache.rs b/components/net_traits/image_cache.rs
deleted file mode 100644
index 81d34964db4..00000000000
--- a/components/net_traits/image_cache.rs
+++ /dev/null
@@ -1,156 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-use std::sync::Arc;
-
-use ipc_channel::ipc::IpcSender;
-use log::debug;
-use malloc_size_of_derive::MallocSizeOf;
-use serde::{Deserialize, Serialize};
-use servo_url::{ImmutableOrigin, ServoUrl};
-
-use crate::image::base::{Image, ImageMetadata};
-use crate::request::CorsSettings;
-use crate::{FetchResponseMsg, WebrenderIpcSender};
-
-// ======================================================================
-// Aux structs and enums.
-// ======================================================================
-
-/// Indicating either entire image or just metadata availability
-#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
-pub enum ImageOrMetadataAvailable {
- ImageAvailable {
- #[ignore_malloc_size_of = "Arc"]
- image: Arc<Image>,
- url: ServoUrl,
- is_placeholder: bool,
- },
- MetadataAvailable(ImageMetadata),
-}
-
-/// This is optionally passed to the image cache when requesting
-/// and image, and returned to the specified event loop when the
-/// image load completes. It is typically used to trigger a reflow
-/// and/or repaint.
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub struct ImageResponder {
- id: PendingImageId,
- sender: IpcSender<PendingImageResponse>,
-}
-
-impl ImageResponder {
- pub fn new(sender: IpcSender<PendingImageResponse>, id: PendingImageId) -> ImageResponder {
- ImageResponder {
- sender: sender,
- id: id,
- }
- }
-
- pub fn respond(&self, response: ImageResponse) {
- debug!("Notifying listener");
- // This send can fail if thread waiting for this notification has panicked.
- // That's not a case that's worth warning about.
- // TODO(#15501): are there cases in which we should perform cleanup?
- let _ = self.sender.send(PendingImageResponse {
- response: response,
- id: self.id,
- });
- }
-}
-
-/// The returned image.
-#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
-pub enum ImageResponse {
- /// The requested image was loaded.
- Loaded(#[ignore_malloc_size_of = "Arc"] Arc<Image>, ServoUrl),
- /// The request image metadata was loaded.
- MetadataLoaded(ImageMetadata),
- /// The requested image failed to load, so a placeholder was loaded instead.
- PlaceholderLoaded(#[ignore_malloc_size_of = "Arc"] Arc<Image>, ServoUrl),
- /// Neither the requested image nor the placeholder could be loaded.
- None,
-}
-
-/// The unique id for an image that has previously been requested.
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
-pub struct PendingImageId(pub u64);
-
-#[derive(Debug, Deserialize, Serialize)]
-pub struct PendingImageResponse {
- pub response: ImageResponse,
- pub id: PendingImageId,
-}
-
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
-pub enum UsePlaceholder {
- No,
- Yes,
-}
-
-// ======================================================================
-// ImageCache public API.
-// ======================================================================
-
-pub enum ImageCacheResult {
- Available(ImageOrMetadataAvailable),
- LoadError,
- Pending(PendingImageId),
- ReadyForRequest(PendingImageId),
-}
-
-pub trait ImageCache: Sync + Send {
- fn new(webrender_api: WebrenderIpcSender) -> Self
- where
- Self: Sized;
-
- /// Definitively check whether there is a cached, fully loaded image available.
- fn get_image(
- &self,
- url: ServoUrl,
- origin: ImmutableOrigin,
- cors_setting: Option<CorsSettings>,
- ) -> Option<Arc<Image>>;
-
- fn get_cached_image_status(
- &self,
- url: ServoUrl,
- origin: ImmutableOrigin,
- cors_setting: Option<CorsSettings>,
- use_placeholder: UsePlaceholder,
- ) -> ImageCacheResult;
-
- /// Add a listener for the provided pending image id, eventually called by
- /// ImageCacheStore::complete_load.
- /// If only metadata is available, Available(ImageOrMetadataAvailable) will
- /// be returned.
- /// If Available(ImageOrMetadataAvailable::Image) or LoadError is the final value,
- /// the provided listener will be dropped (consumed & not added to PendingLoad).
- fn track_image(
- &self,
- url: ServoUrl,
- origin: ImmutableOrigin,
- cors_setting: Option<CorsSettings>,
- sender: IpcSender<PendingImageResponse>,
- use_placeholder: UsePlaceholder,
- ) -> ImageCacheResult;
-
- /// Add a new listener for the given pending image id. If the image is already present,
- /// the responder will still receive the expected response.
- fn add_listener(&self, id: PendingImageId, listener: ImageResponder);
-
- /// Inform the image cache about a response for a pending request.
- fn notify_pending_response(&self, id: PendingImageId, action: FetchResponseMsg);
-}
-
-/// Whether this response passed any CORS checks, and is thus safe to read from
-/// in cross-origin environments.
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
-pub enum CorsStatus {
- /// The response is either same-origin or cross-origin but passed CORS checks.
- Safe,
- /// The response is cross-origin and did not pass CORS checks. It is unsafe
- /// to expose pixel data to the requesting environment.
- Unsafe,
-}
diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs
deleted file mode 100644
index b8b32725a25..00000000000
--- a/components/net_traits/lib.rs
+++ /dev/null
@@ -1,859 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-#![deny(unsafe_code)]
-
-use cookie::Cookie;
-use headers::{ContentType, HeaderMapExt, ReferrerPolicy as ReferrerPolicyHeader};
-use http::{Error as HttpError, HeaderMap, StatusCode};
-use hyper::Error as HyperError;
-use hyper_serde::Serde;
-use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
-use ipc_channel::router::ROUTER;
-use ipc_channel::Error as IpcError;
-use lazy_static::lazy_static;
-use log::warn;
-use malloc_size_of::malloc_size_of_is_0;
-use malloc_size_of_derive::MallocSizeOf;
-use mime::Mime;
-use msg::constellation_msg::HistoryStateId;
-use rustls::Certificate;
-use serde::{Deserialize, Serialize};
-use servo_rand::RngCore;
-use servo_url::{ImmutableOrigin, ServoUrl};
-use time::precise_time_ns;
-use webrender_api::{ImageData, ImageDescriptor, ImageKey};
-
-use crate::filemanager_thread::FileManagerThreadMsg;
-use crate::request::{Request, RequestBuilder};
-use crate::response::{HttpsState, Response, ResponseInit};
-use crate::storage_thread::StorageThreadMsg;
-
-pub mod blob_url_store;
-pub mod filemanager_thread;
-pub mod image_cache;
-pub mod pub_domains;
-pub mod quality;
-pub mod request;
-pub mod response;
-pub mod storage_thread;
-
-/// Image handling.
-///
-/// It may be surprising that this goes in the network crate as opposed to the graphics crate.
-/// However, image handling is generally very integrated with the network stack (especially where
-/// caching is involved) and as a result it must live in here.
-pub mod image {
- pub mod base;
-}
-
-/// An implementation of the [Fetch specification](https://fetch.spec.whatwg.org/)
-pub mod fetch {
- pub mod headers;
-}
-
-/// A loading context, for context-specific sniffing, as defined in
-/// <https://mimesniff.spec.whatwg.org/#context-specific-sniffing>
-#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
-pub enum LoadContext {
- Browsing,
- Image,
- AudioVideo,
- Plugin,
- Style,
- Script,
- Font,
- TextTrack,
- CacheManifest,
-}
-
-#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
-pub struct CustomResponse {
- #[ignore_malloc_size_of = "Defined in hyper"]
- #[serde(
- deserialize_with = "::hyper_serde::deserialize",
- serialize_with = "::hyper_serde::serialize"
- )]
- pub headers: HeaderMap,
- #[ignore_malloc_size_of = "Defined in hyper"]
- #[serde(
- deserialize_with = "::hyper_serde::deserialize",
- serialize_with = "::hyper_serde::serialize"
- )]
- pub raw_status: (StatusCode, String),
- pub body: Vec<u8>,
-}
-
-impl CustomResponse {
- pub fn new(
- headers: HeaderMap,
- raw_status: (StatusCode, String),
- body: Vec<u8>,
- ) -> CustomResponse {
- CustomResponse {
- headers: headers,
- raw_status: raw_status,
- body: body,
- }
- }
-}
-
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub struct CustomResponseMediator {
- pub response_chan: IpcSender<Option<CustomResponse>>,
- pub load_url: ServoUrl,
-}
-
-/// [Policies](https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-states)
-/// for providing a referrer header for a request
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, Serialize)]
-pub enum ReferrerPolicy {
- /// "no-referrer"
- NoReferrer,
- /// "no-referrer-when-downgrade"
- NoReferrerWhenDowngrade,
- /// "origin"
- Origin,
- /// "same-origin"
- SameOrigin,
- /// "origin-when-cross-origin"
- OriginWhenCrossOrigin,
- /// "unsafe-url"
- UnsafeUrl,
- /// "strict-origin"
- StrictOrigin,
- /// "strict-origin-when-cross-origin"
- StrictOriginWhenCrossOrigin,
-}
-
-impl ToString for ReferrerPolicy {
- fn to_string(&self) -> String {
- match self {
- ReferrerPolicy::NoReferrer => "no-referrer",
- ReferrerPolicy::NoReferrerWhenDowngrade => "no-referrer-when-downgrade",
- ReferrerPolicy::Origin => "origin",
- ReferrerPolicy::SameOrigin => "same-origin",
- ReferrerPolicy::OriginWhenCrossOrigin => "origin-when-cross-origin",
- ReferrerPolicy::UnsafeUrl => "unsafe-url",
- ReferrerPolicy::StrictOrigin => "strict-origin",
- ReferrerPolicy::StrictOriginWhenCrossOrigin => "strict-origin-when-cross-origin",
- }
- .to_string()
- }
-}
-
-impl From<ReferrerPolicyHeader> for ReferrerPolicy {
- fn from(policy: ReferrerPolicyHeader) -> Self {
- match policy {
- ReferrerPolicyHeader::NO_REFERRER => ReferrerPolicy::NoReferrer,
- ReferrerPolicyHeader::NO_REFERRER_WHEN_DOWNGRADE => {
- ReferrerPolicy::NoReferrerWhenDowngrade
- },
- ReferrerPolicyHeader::SAME_ORIGIN => ReferrerPolicy::SameOrigin,
- ReferrerPolicyHeader::ORIGIN => ReferrerPolicy::Origin,
- ReferrerPolicyHeader::ORIGIN_WHEN_CROSS_ORIGIN => ReferrerPolicy::OriginWhenCrossOrigin,
- ReferrerPolicyHeader::UNSAFE_URL => ReferrerPolicy::UnsafeUrl,
- ReferrerPolicyHeader::STRICT_ORIGIN => ReferrerPolicy::StrictOrigin,
- ReferrerPolicyHeader::STRICT_ORIGIN_WHEN_CROSS_ORIGIN => {
- ReferrerPolicy::StrictOriginWhenCrossOrigin
- },
- }
- }
-}
-
-impl From<ReferrerPolicy> for ReferrerPolicyHeader {
- fn from(referrer_policy: ReferrerPolicy) -> Self {
- match referrer_policy {
- ReferrerPolicy::NoReferrer => ReferrerPolicyHeader::NO_REFERRER,
- ReferrerPolicy::NoReferrerWhenDowngrade => {
- ReferrerPolicyHeader::NO_REFERRER_WHEN_DOWNGRADE
- },
- ReferrerPolicy::SameOrigin => ReferrerPolicyHeader::SAME_ORIGIN,
- ReferrerPolicy::Origin => ReferrerPolicyHeader::ORIGIN,
- ReferrerPolicy::OriginWhenCrossOrigin => ReferrerPolicyHeader::ORIGIN_WHEN_CROSS_ORIGIN,
- ReferrerPolicy::UnsafeUrl => ReferrerPolicyHeader::UNSAFE_URL,
- ReferrerPolicy::StrictOrigin => ReferrerPolicyHeader::STRICT_ORIGIN,
- ReferrerPolicy::StrictOriginWhenCrossOrigin => {
- ReferrerPolicyHeader::STRICT_ORIGIN_WHEN_CROSS_ORIGIN
- },
- }
- }
-}
-
-#[derive(Debug, Deserialize, Serialize)]
-pub enum FetchResponseMsg {
- // todo: should have fields for transmitted/total bytes
- ProcessRequestBody,
- ProcessRequestEOF,
- // todo: send more info about the response (or perhaps the entire Response)
- ProcessResponse(Result<FetchMetadata, NetworkError>),
- ProcessResponseChunk(Vec<u8>),
- ProcessResponseEOF(Result<ResourceFetchTiming, NetworkError>),
-}
-
-pub trait FetchTaskTarget {
- /// <https://fetch.spec.whatwg.org/#process-request-body>
- ///
- /// Fired when a chunk of the request body is transmitted
- fn process_request_body(&mut self, request: &Request);
-
- /// <https://fetch.spec.whatwg.org/#process-request-end-of-file>
- ///
- /// Fired when the entire request finishes being transmitted
- fn process_request_eof(&mut self, request: &Request);
-
- /// <https://fetch.spec.whatwg.org/#process-response>
- ///
- /// Fired when headers are received
- fn process_response(&mut self, response: &Response);
-
- /// Fired when a chunk of response content is received
- fn process_response_chunk(&mut self, chunk: Vec<u8>);
-
- /// <https://fetch.spec.whatwg.org/#process-response-end-of-file>
- ///
- /// Fired when the response is fully fetched
- fn process_response_eof(&mut self, response: &Response);
-}
-
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub enum FilteredMetadata {
- Basic(Metadata),
- Cors(Metadata),
- Opaque,
- OpaqueRedirect(ServoUrl),
-}
-
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub enum FetchMetadata {
- Unfiltered(Metadata),
- Filtered {
- filtered: FilteredMetadata,
- unsafe_: Metadata,
- },
-}
-
-pub trait FetchResponseListener {
- fn process_request_body(&mut self);
- fn process_request_eof(&mut self);
- fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>);
- fn process_response_chunk(&mut self, chunk: Vec<u8>);
- fn process_response_eof(&mut self, response: Result<ResourceFetchTiming, NetworkError>);
- fn resource_timing(&self) -> &ResourceFetchTiming;
- fn resource_timing_mut(&mut self) -> &mut ResourceFetchTiming;
- fn submit_resource_timing(&mut self);
-}
-
-impl FetchTaskTarget for IpcSender<FetchResponseMsg> {
- fn process_request_body(&mut self, _: &Request) {
- let _ = self.send(FetchResponseMsg::ProcessRequestBody);
- }
-
- fn process_request_eof(&mut self, _: &Request) {
- let _ = self.send(FetchResponseMsg::ProcessRequestEOF);
- }
-
- fn process_response(&mut self, response: &Response) {
- let _ = self.send(FetchResponseMsg::ProcessResponse(response.metadata()));
- }
-
- fn process_response_chunk(&mut self, chunk: Vec<u8>) {
- let _ = self.send(FetchResponseMsg::ProcessResponseChunk(chunk));
- }
-
- fn process_response_eof(&mut self, response: &Response) {
- if let Some(e) = response.get_network_error() {
- let _ = self.send(FetchResponseMsg::ProcessResponseEOF(Err(e.clone())));
- } else {
- let _ = self.send(FetchResponseMsg::ProcessResponseEOF(Ok(response
- .get_resource_timing()
- .lock()
- .unwrap()
- .clone())));
- }
- }
-}
-
-/// A fetch task that discards all data it's sent,
-/// useful when speculatively prefetching data that we don't need right
-/// now, but might need in the future.
-pub struct DiscardFetch;
-
-impl FetchTaskTarget for DiscardFetch {
- fn process_request_body(&mut self, _: &Request) {}
-
- fn process_request_eof(&mut self, _: &Request) {}
-
- fn process_response(&mut self, _: &Response) {}
-
- fn process_response_chunk(&mut self, _: Vec<u8>) {}
-
- fn process_response_eof(&mut self, _: &Response) {}
-}
-
-pub trait Action<Listener> {
- fn process(self, listener: &mut Listener);
-}
-
-impl<T: FetchResponseListener> Action<T> for FetchResponseMsg {
- /// Execute the default action on a provided listener.
- fn process(self, listener: &mut T) {
- match self {
- FetchResponseMsg::ProcessRequestBody => listener.process_request_body(),
- FetchResponseMsg::ProcessRequestEOF => listener.process_request_eof(),
- FetchResponseMsg::ProcessResponse(meta) => listener.process_response(meta),
- FetchResponseMsg::ProcessResponseChunk(data) => listener.process_response_chunk(data),
- FetchResponseMsg::ProcessResponseEOF(data) => {
- match data {
- Ok(ref response_resource_timing) => {
- // update listener with values from response
- *listener.resource_timing_mut() = response_resource_timing.clone();
- listener.process_response_eof(Ok(response_resource_timing.clone()));
- // TODO timing check https://w3c.github.io/resource-timing/#dfn-timing-allow-check
-
- listener.submit_resource_timing();
- },
- // TODO Resources for which the fetch was initiated, but was later aborted
- // (e.g. due to a network error) MAY be included as PerformanceResourceTiming
- // objects in the Performance Timeline and MUST contain initialized attribute
- // values for processed substeps of the processing model.
- Err(e) => listener.process_response_eof(Err(e)),
- }
- },
- }
- }
-}
-
-/// Handle to a resource thread
-pub type CoreResourceThread = IpcSender<CoreResourceMsg>;
-
-pub type IpcSendResult = Result<(), IpcError>;
-
-/// Abstraction of the ability to send a particular type of message,
-/// used by net_traits::ResourceThreads to ease the use its IpcSender sub-fields
-/// XXX: If this trait will be used more in future, some auto derive might be appealing
-pub trait IpcSend<T>
-where
- T: serde::Serialize + for<'de> serde::Deserialize<'de>,
-{
- /// send message T
- fn send(&self, _: T) -> IpcSendResult;
- /// get underlying sender
- fn sender(&self) -> IpcSender<T>;
-}
-
-// FIXME: Originally we will construct an Arc<ResourceThread> from ResourceThread
-// in script_thread to avoid some performance pitfall. Now we decide to deal with
-// the "Arc" hack implicitly in future.
-// See discussion: http://logs.glob.uno/?c=mozilla%23servo&s=16+May+2016&e=16+May+2016#c430412
-// See also: https://github.com/servo/servo/blob/735480/components/script/script_thread.rs#L313
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub struct ResourceThreads {
- core_thread: CoreResourceThread,
- storage_thread: IpcSender<StorageThreadMsg>,
-}
-
-impl ResourceThreads {
- pub fn new(c: CoreResourceThread, s: IpcSender<StorageThreadMsg>) -> ResourceThreads {
- ResourceThreads {
- core_thread: c,
- storage_thread: s,
- }
- }
-
- pub fn clear_cache(&self) {
- let _ = self.core_thread.send(CoreResourceMsg::ClearCache);
- }
-}
-
-impl IpcSend<CoreResourceMsg> for ResourceThreads {
- fn send(&self, msg: CoreResourceMsg) -> IpcSendResult {
- self.core_thread.send(msg)
- }
-
- fn sender(&self) -> IpcSender<CoreResourceMsg> {
- self.core_thread.clone()
- }
-}
-
-impl IpcSend<StorageThreadMsg> for ResourceThreads {
- fn send(&self, msg: StorageThreadMsg) -> IpcSendResult {
- self.storage_thread.send(msg)
- }
-
- fn sender(&self) -> IpcSender<StorageThreadMsg> {
- self.storage_thread.clone()
- }
-}
-
-// Ignore the sub-fields
-malloc_size_of_is_0!(ResourceThreads);
-
-#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
-pub enum IncludeSubdomains {
- Included,
- NotIncluded,
-}
-
-#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
-pub enum MessageData {
- Text(String),
- Binary(Vec<u8>),
-}
-
-#[derive(Debug, Deserialize, Serialize)]
-pub enum WebSocketDomAction {
- SendMessage(MessageData),
- Close(Option<u16>, Option<String>),
-}
-
-#[derive(Debug, Deserialize, Serialize)]
-pub enum WebSocketNetworkEvent {
- ConnectionEstablished { protocol_in_use: Option<String> },
- MessageReceived(MessageData),
- Close(Option<u16>, String),
- Fail,
-}
-
-#[derive(Debug, Deserialize, Serialize)]
-/// IPC channels to communicate with the script thread about network or DOM events.
-pub enum FetchChannels {
- ResponseMsg(
- IpcSender<FetchResponseMsg>,
- /* cancel_chan */ Option<IpcReceiver<()>>,
- ),
- WebSocket {
- event_sender: IpcSender<WebSocketNetworkEvent>,
- action_receiver: IpcReceiver<WebSocketDomAction>,
- },
- /// If the fetch is just being done to populate the cache,
- /// not because the data is needed now.
- Prefetch,
-}
-
-#[derive(Debug, Deserialize, Serialize)]
-pub enum CoreResourceMsg {
- Fetch(RequestBuilder, FetchChannels),
- /// Initiate a fetch in response to processing a redirection
- FetchRedirect(
- RequestBuilder,
- ResponseInit,
- IpcSender<FetchResponseMsg>,
- /* cancel_chan */ Option<IpcReceiver<()>>,
- ),
- /// Store a cookie for a given originating URL
- SetCookieForUrl(ServoUrl, Serde<Cookie<'static>>, CookieSource),
- /// Store a set of cookies for a given originating URL
- SetCookiesForUrl(ServoUrl, Vec<Serde<Cookie<'static>>>, CookieSource),
- /// Retrieve the stored cookies for a given URL
- GetCookiesForUrl(ServoUrl, IpcSender<Option<String>>, CookieSource),
- /// Get a cookie by name for a given originating URL
- GetCookiesDataForUrl(
- ServoUrl,
- IpcSender<Vec<Serde<Cookie<'static>>>>,
- CookieSource,
- ),
- DeleteCookies(ServoUrl),
- /// Get a history state by a given history state id
- GetHistoryState(HistoryStateId, IpcSender<Option<Vec<u8>>>),
- /// Set a history state for a given history state id
- SetHistoryState(HistoryStateId, Vec<u8>),
- /// Removes history states for the given ids
- RemoveHistoryStates(Vec<HistoryStateId>),
- /// Synchronization message solely for knowing the state of the ResourceChannelManager loop
- Synchronize(IpcSender<()>),
- /// Clear the network cache.
- ClearCache,
- /// Send the service worker network mediator for an origin to CoreResourceThread
- NetworkMediator(IpcSender<CustomResponseMediator>, ImmutableOrigin),
- /// Message forwarded to file manager's handler
- ToFileManager(FileManagerThreadMsg),
- /// Break the load handler loop, send a reply when done cleaning up local resources
- /// and exit
- Exit(IpcSender<()>),
-}
-
-/// Instruct the resource thread to make a new request.
-pub fn fetch_async<F>(request: RequestBuilder, core_resource_thread: &CoreResourceThread, f: F)
-where
- F: Fn(FetchResponseMsg) + Send + 'static,
-{
- let (action_sender, action_receiver) = ipc::channel().unwrap();
- ROUTER.add_route(
- action_receiver.to_opaque(),
- Box::new(move |message| f(message.to().unwrap())),
- );
- core_resource_thread
- .send(CoreResourceMsg::Fetch(
- request,
- FetchChannels::ResponseMsg(action_sender, None),
- ))
- .unwrap();
-}
-
-#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
-pub struct ResourceCorsData {
- /// CORS Preflight flag
- pub preflight: bool,
- /// Origin of CORS Request
- pub origin: ServoUrl,
-}
-
-#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
-pub struct ResourceFetchTiming {
- pub domain_lookup_start: u64,
- pub timing_check_passed: bool,
- pub timing_type: ResourceTimingType,
- /// Number of redirects until final resource (currently limited to 20)
- pub redirect_count: u16,
- pub request_start: u64,
- pub secure_connection_start: u64,
- pub response_start: u64,
- pub fetch_start: u64,
- pub response_end: u64,
- pub redirect_start: u64,
- pub redirect_end: u64,
- pub connect_start: u64,
- pub connect_end: u64,
- pub start_time: u64,
-}
-
-pub enum RedirectStartValue {
- #[allow(dead_code)]
- Zero,
- FetchStart,
-}
-
-pub enum RedirectEndValue {
- Zero,
- ResponseEnd,
-}
-
-// TODO: refactor existing code to use this enum for setting time attributes
-// suggest using this with all time attributes in the future
-pub enum ResourceTimeValue {
- Zero,
- Now,
- FetchStart,
- RedirectStart,
-}
-
-pub enum ResourceAttribute {
- RedirectCount(u16),
- DomainLookupStart,
- RequestStart,
- ResponseStart,
- RedirectStart(RedirectStartValue),
- RedirectEnd(RedirectEndValue),
- FetchStart,
- ConnectStart(u64),
- ConnectEnd(u64),
- SecureConnectionStart,
- ResponseEnd,
- StartTime(ResourceTimeValue),
-}
-
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
-pub enum ResourceTimingType {
- Resource,
- Navigation,
- Error,
- None,
-}
-
-impl ResourceFetchTiming {
- pub fn new(timing_type: ResourceTimingType) -> ResourceFetchTiming {
- ResourceFetchTiming {
- timing_type: timing_type,
- timing_check_passed: true,
- domain_lookup_start: 0,
- redirect_count: 0,
- secure_connection_start: 0,
- request_start: 0,
- response_start: 0,
- fetch_start: 0,
- redirect_start: 0,
- redirect_end: 0,
- connect_start: 0,
- connect_end: 0,
- response_end: 0,
- start_time: 0,
- }
- }
-
- // TODO currently this is being set with precise time ns when it should be time since
- // time origin (as described in Performance::now)
- pub fn set_attribute(&mut self, attribute: ResourceAttribute) {
- let should_attribute_always_be_updated = match attribute {
- ResourceAttribute::FetchStart |
- ResourceAttribute::ResponseEnd |
- ResourceAttribute::StartTime(_) => true,
- _ => false,
- };
- if !self.timing_check_passed && !should_attribute_always_be_updated {
- return;
- }
- match attribute {
- ResourceAttribute::DomainLookupStart => self.domain_lookup_start = precise_time_ns(),
- ResourceAttribute::RedirectCount(count) => self.redirect_count = count,
- ResourceAttribute::RequestStart => self.request_start = precise_time_ns(),
- ResourceAttribute::ResponseStart => self.response_start = precise_time_ns(),
- ResourceAttribute::RedirectStart(val) => match val {
- RedirectStartValue::Zero => self.redirect_start = 0,
- RedirectStartValue::FetchStart => {
- if self.redirect_start == 0 {
- self.redirect_start = self.fetch_start
- }
- },
- },
- ResourceAttribute::RedirectEnd(val) => match val {
- RedirectEndValue::Zero => self.redirect_end = 0,
- RedirectEndValue::ResponseEnd => self.redirect_end = self.response_end,
- },
- ResourceAttribute::FetchStart => self.fetch_start = precise_time_ns(),
- ResourceAttribute::ConnectStart(val) => self.connect_start = val,
- ResourceAttribute::ConnectEnd(val) => self.connect_end = val,
- ResourceAttribute::SecureConnectionStart => {
- self.secure_connection_start = precise_time_ns()
- },
- ResourceAttribute::ResponseEnd => self.response_end = precise_time_ns(),
- ResourceAttribute::StartTime(val) => match val {
- ResourceTimeValue::RedirectStart
- if self.redirect_start == 0 || !self.timing_check_passed => {},
- _ => self.start_time = self.get_time_value(val),
- },
- }
- }
-
- fn get_time_value(&self, time: ResourceTimeValue) -> u64 {
- match time {
- ResourceTimeValue::Zero => 0,
- ResourceTimeValue::Now => precise_time_ns(),
- ResourceTimeValue::FetchStart => self.fetch_start,
- ResourceTimeValue::RedirectStart => self.redirect_start,
- }
- }
-
- pub fn mark_timing_check_failed(&mut self) {
- self.timing_check_passed = false;
- self.domain_lookup_start = 0;
- self.redirect_count = 0;
- self.request_start = 0;
- self.response_start = 0;
- self.redirect_start = 0;
- self.connect_start = 0;
- self.connect_end = 0;
- }
-}
-
-/// Metadata about a loaded resource, such as is obtained from HTTP headers.
-#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
-pub struct Metadata {
- /// Final URL after redirects.
- pub final_url: ServoUrl,
-
- /// Location URL from the response headers.
- pub location_url: Option<Result<ServoUrl, String>>,
-
- #[ignore_malloc_size_of = "Defined in hyper"]
- /// MIME type / subtype.
- pub content_type: Option<Serde<ContentType>>,
-
- /// Character set.
- pub charset: Option<String>,
-
- #[ignore_malloc_size_of = "Defined in hyper"]
- /// Headers
- pub headers: Option<Serde<HeaderMap>>,
-
- /// HTTP Status
- pub status: Option<(u16, Vec<u8>)>,
-
- /// Is successful HTTPS connection
- pub https_state: HttpsState,
-
- /// Referrer Url
- pub referrer: Option<ServoUrl>,
-
- /// Referrer Policy of the Request used to obtain Response
- pub referrer_policy: Option<ReferrerPolicy>,
- /// Performance information for navigation events
- pub timing: Option<ResourceFetchTiming>,
- /// True if the request comes from a redirection
- pub redirected: bool,
-}
-
-impl Metadata {
- /// Metadata with defaults for everything optional.
- pub fn default(url: ServoUrl) -> Self {
- Metadata {
- final_url: url,
- location_url: None,
- content_type: None,
- charset: None,
- headers: None,
- // https://fetch.spec.whatwg.org/#concept-response-status-message
- status: Some((200, b"".to_vec())),
- https_state: HttpsState::None,
- referrer: None,
- referrer_policy: None,
- timing: None,
- redirected: false,
- }
- }
-
- /// Extract the parts of a Mime that we care about.
- pub fn set_content_type(&mut self, content_type: Option<&Mime>) {
- if self.headers.is_none() {
- self.headers = Some(Serde(HeaderMap::new()));
- }
-
- if let Some(mime) = content_type {
- self.headers
- .as_mut()
- .unwrap()
- .typed_insert(ContentType::from(mime.clone()));
- if let Some(charset) = mime.get_param(mime::CHARSET) {
- self.charset = Some(charset.to_string());
- }
- self.content_type = Some(Serde(ContentType::from(mime.clone())));
- }
- }
-
- /// Set the referrer policy associated with the loaded resource.
- pub fn set_referrer_policy(&mut self, referrer_policy: Option<ReferrerPolicy>) {
- if self.headers.is_none() {
- self.headers = Some(Serde(HeaderMap::new()));
- }
-
- self.referrer_policy = referrer_policy;
- if let Some(referrer_policy) = referrer_policy {
- self.headers
- .as_mut()
- .unwrap()
- .typed_insert::<ReferrerPolicyHeader>(referrer_policy.into());
- }
- }
-}
-
-/// The creator of a given cookie
-#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
-pub enum CookieSource {
- /// An HTTP API
- HTTP,
- /// A non-HTTP API
- NonHTTP,
-}
-
-/// Network errors that have to be exported out of the loaders
-#[derive(Clone, Debug, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)]
-pub enum NetworkError {
- /// Could be any of the internal errors, like unsupported scheme, connection errors, etc.
- Internal(String),
- LoadCancelled,
- /// SSL validation error, to be converted to Resource::BadCertHTML in the HTML parser.
- SslValidation(String, Vec<u8>),
- /// Crash error, to be converted to Resource::Crash in the HTML parser.
- Crash(String),
-}
-
-impl NetworkError {
- pub fn from_hyper_error(error: &HyperError, certificate: Option<Certificate>) -> Self {
- let error_string = error.to_string();
- match certificate {
- Some(certificate) => NetworkError::SslValidation(error_string, certificate.0),
- _ => NetworkError::Internal(error_string),
- }
- }
-
- pub fn from_http_error(error: &HttpError) -> Self {
- NetworkError::Internal(error.to_string())
- }
-}
-
-/// Normalize `slice`, as defined by
-/// [the Fetch Spec](https://fetch.spec.whatwg.org/#concept-header-value-normalize).
-pub fn trim_http_whitespace(mut slice: &[u8]) -> &[u8] {
- const HTTP_WS_BYTES: &'static [u8] = b"\x09\x0A\x0D\x20";
-
- loop {
- match slice.split_first() {
- Some((first, remainder)) if HTTP_WS_BYTES.contains(first) => slice = remainder,
- _ => break,
- }
- }
-
- loop {
- match slice.split_last() {
- Some((last, remainder)) if HTTP_WS_BYTES.contains(last) => slice = remainder,
- _ => break,
- }
- }
-
- slice
-}
-
-pub fn http_percent_encode(bytes: &[u8]) -> String {
- // This encode set is used for HTTP header values and is defined at
- // https://tools.ietf.org/html/rfc5987#section-3.2
- const HTTP_VALUE: &percent_encoding::AsciiSet = &percent_encoding::CONTROLS
- .add(b' ')
- .add(b'"')
- .add(b'%')
- .add(b'\'')
- .add(b'(')
- .add(b')')
- .add(b'*')
- .add(b',')
- .add(b'/')
- .add(b':')
- .add(b';')
- .add(b'<')
- .add(b'-')
- .add(b'>')
- .add(b'?')
- .add(b'[')
- .add(b'\\')
- .add(b']')
- .add(b'{')
- .add(b'}');
-
- percent_encoding::percent_encode(bytes, HTTP_VALUE).to_string()
-}
-
-#[derive(Deserialize, Serialize)]
-pub enum NetToCompositorMsg {
- AddImage(ImageKey, ImageDescriptor, ImageData),
- GenerateImageKey(IpcSender<ImageKey>),
-}
-
-#[derive(Clone, Deserialize, Serialize)]
-pub struct WebrenderIpcSender(IpcSender<NetToCompositorMsg>);
-
-impl WebrenderIpcSender {
- pub fn new(sender: IpcSender<NetToCompositorMsg>) -> Self {
- Self(sender)
- }
-
- pub fn generate_image_key(&self) -> ImageKey {
- let (sender, receiver) = ipc::channel().unwrap();
- self.0
- .send(NetToCompositorMsg::GenerateImageKey(sender))
- .expect("error sending image key generation");
- receiver.recv().expect("error receiving image key result")
- }
-
- pub fn add_image(&self, key: ImageKey, descriptor: ImageDescriptor, data: ImageData) {
- if let Err(e) = self
- .0
- .send(NetToCompositorMsg::AddImage(key, descriptor, data))
- {
- warn!("Error sending image update: {}", e);
- }
- }
-}
-
-lazy_static! {
- pub static ref PRIVILEGED_SECRET: u32 = servo_rand::ServoRng::new().next_u32();
-}
diff --git a/components/net_traits/pub_domains.rs b/components/net_traits/pub_domains.rs
deleted file mode 100644
index 1efb8faf56d..00000000000
--- a/components/net_traits/pub_domains.rs
+++ /dev/null
@@ -1,159 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-//! Implementation of public domain matching.
-//!
-//! The list is a file located on the `resources` folder and loaded once on first need.
-//!
-//! The list can be updated with `./mach update-pub-domains` from this source:
-//! <https://publicsuffix.org/list/>
-//!
-//! This implementation is not strictly following the specification of the list. Wildcards are not
-//! restricted to appear only in the leftmost position, but the current list has no such cases so
-//! we don't need to make the code more complex for it. The `mach` update command makes sure that
-//! those cases are not present.
-
-use std::collections::HashSet;
-use std::iter::FromIterator;
-
-use embedder_traits::resources::{self, Resource};
-use lazy_static::lazy_static;
-use servo_url::{Host, ImmutableOrigin, ServoUrl};
-
-#[derive(Clone, Debug)]
-pub struct PubDomainRules {
- rules: HashSet<String>,
- wildcards: HashSet<String>,
- exceptions: HashSet<String>,
-}
-
-lazy_static! {
- static ref PUB_DOMAINS: PubDomainRules = load_pub_domains();
-}
-
-impl<'a> FromIterator<&'a str> for PubDomainRules {
- fn from_iter<T>(iter: T) -> Self
- where
- T: IntoIterator<Item = &'a str>,
- {
- let mut result = PubDomainRules::new();
- for item in iter {
- if item.starts_with("!") {
- result.exceptions.insert(String::from(&item[1..]));
- } else if item.starts_with("*.") {
- result.wildcards.insert(String::from(&item[2..]));
- } else {
- result.rules.insert(String::from(item));
- }
- }
- result
- }
-}
-
-impl PubDomainRules {
- pub fn new() -> PubDomainRules {
- PubDomainRules {
- rules: HashSet::new(),
- wildcards: HashSet::new(),
- exceptions: HashSet::new(),
- }
- }
- pub fn parse(content: &str) -> PubDomainRules {
- content
- .lines()
- .map(str::trim)
- .filter(|s| !s.is_empty())
- .filter(|s| !s.starts_with("//"))
- .collect()
- }
- fn suffix_pair<'a>(&self, domain: &'a str) -> (&'a str, &'a str) {
- let domain = domain.trim_start_matches(".");
- let mut suffix = domain;
- let mut prev_suffix = domain;
- for (index, _) in domain.match_indices(".") {
- let next_suffix = &domain[index + 1..];
- if self.exceptions.contains(suffix) {
- return (next_suffix, suffix);
- } else if self.wildcards.contains(next_suffix) {
- return (suffix, prev_suffix);
- } else if self.rules.contains(suffix) {
- return (suffix, prev_suffix);
- } else {
- prev_suffix = suffix;
- suffix = next_suffix;
- }
- }
- return (suffix, prev_suffix);
- }
- pub fn public_suffix<'a>(&self, domain: &'a str) -> &'a str {
- let (public, _) = self.suffix_pair(domain);
- public
- }
- pub fn registrable_suffix<'a>(&self, domain: &'a str) -> &'a str {
- let (_, registrable) = self.suffix_pair(domain);
- registrable
- }
- pub fn is_public_suffix(&self, domain: &str) -> bool {
- // Speeded-up version of
- // domain != "" &&
- // self.public_suffix(domain) == domain.
- let domain = domain.trim_start_matches(".");
- match domain.find(".") {
- None => !domain.is_empty(),
- Some(index) => {
- !self.exceptions.contains(domain) && self.wildcards.contains(&domain[index + 1..]) ||
- self.rules.contains(domain)
- },
- }
- }
- pub fn is_registrable_suffix(&self, domain: &str) -> bool {
- // Speeded-up version of
- // self.public_suffix(domain) != domain &&
- // self.registrable_suffix(domain) == domain.
- let domain = domain.trim_start_matches(".");
- match domain.find(".") {
- None => false,
- Some(index) => {
- self.exceptions.contains(domain) ||
- !self.wildcards.contains(&domain[index + 1..]) &&
- !self.rules.contains(domain) &&
- self.is_public_suffix(&domain[index + 1..])
- },
- }
- }
-}
-
-fn load_pub_domains() -> PubDomainRules {
- PubDomainRules::parse(&resources::read_string(Resource::DomainList))
-}
-
-pub fn pub_suffix(domain: &str) -> &str {
- PUB_DOMAINS.public_suffix(domain)
-}
-
-pub fn reg_suffix(domain: &str) -> &str {
- PUB_DOMAINS.registrable_suffix(domain)
-}
-
-pub fn is_pub_domain(domain: &str) -> bool {
- PUB_DOMAINS.is_public_suffix(domain)
-}
-
-pub fn is_reg_domain(domain: &str) -> bool {
- PUB_DOMAINS.is_registrable_suffix(domain)
-}
-
-/// The registered domain name (aka eTLD+1) for a URL.
-/// Returns None if the URL has no host name.
-/// Returns the registered suffix for the host name if it is a domain.
-/// Leaves the host name alone if it is an IP address.
-pub fn reg_host(url: &ServoUrl) -> Option<Host> {
- match url.origin() {
- ImmutableOrigin::Tuple(_, Host::Domain(domain), _) => {
- Some(Host::Domain(String::from(reg_suffix(&*domain))))
- },
- ImmutableOrigin::Tuple(_, ip, _) => Some(ip),
- ImmutableOrigin::Opaque(_) => None,
- }
-}
diff --git a/components/net_traits/quality.rs b/components/net_traits/quality.rs
deleted file mode 100644
index 095cd121bad..00000000000
--- a/components/net_traits/quality.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-//TODO(eijebong): Remove this once typed headers figure out quality
-// This is copy pasted from the old hyper headers to avoid hardcoding everything
-// (I would probably also make some silly mistakes while migrating...)
-
-use std::{fmt, str};
-
-use http::header::HeaderValue;
-use mime::Mime;
-
-/// A quality value, as specified in [RFC7231].
-///
-/// Quality values are decimal numbers between 0 and 1 (inclusive) with up to 3 fractional digits of precision.
-///
-/// [RFC7231]: https://tools.ietf.org/html/rfc7231#section-5.3.1
-#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
-pub struct Quality(u16);
-
-impl Quality {
- /// Creates a quality value from a value between 0 and 1000 inclusive.
- ///
- /// This is semantically divided by 1000 to produce a value between 0 and 1.
- ///
- /// # Panics
- ///
- /// Panics if the value is greater than 1000.
- pub fn from_u16(quality: u16) -> Quality {
- assert!(quality <= 1000);
- Quality(quality)
- }
-}
-
-/// A value paired with its "quality" as defined in [RFC7231].
-///
-/// Quality items are used in content negotiation headers such as `Accept` and `Accept-Encoding`.
-///
-/// [RFC7231]: https://tools.ietf.org/html/rfc7231#section-5.3
-#[derive(Clone, Debug, PartialEq)]
-pub struct QualityItem<T> {
- pub item: T,
- pub quality: Quality,
-}
-
-impl<T> QualityItem<T> {
- /// Creates a new quality item.
- pub fn new(item: T, quality: Quality) -> QualityItem<T> {
- QualityItem { item, quality }
- }
-}
-
-impl<T> fmt::Display for QualityItem<T>
-where
- T: fmt::Display,
-{
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt::Display::fmt(&self.item, fmt)?;
- match self.quality.0 {
- 1000 => Ok(()),
- 0 => fmt.write_str("; q=0"),
- mut x => {
- fmt.write_str("; q=0.")?;
- let mut digits = *b"000";
- digits[2] = (x % 10) as u8 + b'0';
- x /= 10;
- digits[1] = (x % 10) as u8 + b'0';
- x /= 10;
- digits[0] = (x % 10) as u8 + b'0';
-
- let s = str::from_utf8(&digits[..]).unwrap();
- fmt.write_str(s.trim_end_matches('0'))
- },
- }
- }
-}
-
-pub fn quality_to_value(q: Vec<QualityItem<Mime>>) -> HeaderValue {
- HeaderValue::from_str(
- &q.iter()
- .map(|q| q.to_string())
- .collect::<Vec<String>>()
- .join(", "),
- )
- .unwrap()
-}
diff --git a/components/net_traits/request.rs b/components/net_traits/request.rs
deleted file mode 100644
index 1f9f0abf986..00000000000
--- a/components/net_traits/request.rs
+++ /dev/null
@@ -1,749 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-use std::sync::{Arc, Mutex};
-
-use content_security_policy::{self as csp, CspList};
-use http::header::{HeaderName, AUTHORIZATION};
-use http::{HeaderMap, Method};
-use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
-use malloc_size_of_derive::MallocSizeOf;
-use mime::Mime;
-use msg::constellation_msg::PipelineId;
-use serde::{Deserialize, Serialize};
-use servo_url::{ImmutableOrigin, ServoUrl};
-
-use crate::response::HttpsState;
-use crate::{ReferrerPolicy, ResourceTimingType};
-
-/// An [initiator](https://fetch.spec.whatwg.org/#concept-request-initiator)
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
-pub enum Initiator {
- None,
- Download,
- ImageSet,
- Manifest,
- XSLT,
-}
-
-/// A request [destination](https://fetch.spec.whatwg.org/#concept-request-destination)
-pub use csp::Destination;
-
-/// 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,
- /// Contains the url that "client" would be resolved to. See
- /// [https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer](https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer)
- ///
- /// If you are unsure you should probably use
- /// [`GlobalScope::get_referrer`](https://doc.servo.org/script/dom/globalscope/struct.GlobalScope.html#method.get_referrer)
- Client(ServoUrl),
- 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<String> },
-}
-
-/// 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,
- 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, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
-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, Eq, Hash, PartialEq, Serialize)]
-pub enum CorsSettings {
- Anonymous,
- UseCredentials,
-}
-
-/// [Parser Metadata](https://fetch.spec.whatwg.org/#concept-request-parser-metadata)
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
-pub enum ParserMetadata {
- Default,
- ParserInserted,
- NotParserInserted,
-}
-
-/// <https://fetch.spec.whatwg.org/#concept-body-source>
-#[derive(Clone, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
-pub enum BodySource {
- Null,
- Object,
-}
-
-/// Messages used to implement <https://fetch.spec.whatwg.org/#concept-request-transmit-body>
-/// which are sent from script to net.
-#[derive(Debug, Deserialize, Serialize)]
-pub enum BodyChunkResponse {
- /// A chunk of bytes.
- Chunk(Vec<u8>),
- /// The body is done.
- Done,
- /// There was an error streaming the body,
- /// terminate fetch.
- Error,
-}
-
-/// Messages used to implement <https://fetch.spec.whatwg.org/#concept-request-transmit-body>
-/// which are sent from net to script
-/// (with the exception of Done, which is sent from script to script).
-#[derive(Debug, Deserialize, Serialize)]
-pub enum BodyChunkRequest {
- /// Connect a fetch in `net`, with a stream of bytes from `script`.
- Connect(IpcSender<BodyChunkResponse>),
- /// Re-extract a new stream from the source, following a redirect.
- Extract(IpcReceiver<BodyChunkRequest>),
- /// Ask for another chunk.
- Chunk,
- /// Signal the stream is done(sent from script to script).
- Done,
- /// Signal the stream has errored(sent from script to script).
- Error,
-}
-
-/// The net component's view into <https://fetch.spec.whatwg.org/#bodies>
-#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
-pub struct RequestBody {
- /// Net's channel to communicate with script re this body.
- #[ignore_malloc_size_of = "Channels are hard"]
- chan: Arc<Mutex<IpcSender<BodyChunkRequest>>>,
- /// <https://fetch.spec.whatwg.org/#concept-body-source>
- source: BodySource,
- /// <https://fetch.spec.whatwg.org/#concept-body-total-bytes>
- total_bytes: Option<usize>,
-}
-
-impl RequestBody {
- pub fn new(
- chan: IpcSender<BodyChunkRequest>,
- source: BodySource,
- total_bytes: Option<usize>,
- ) -> Self {
- RequestBody {
- chan: Arc::new(Mutex::new(chan)),
- source,
- total_bytes,
- }
- }
-
- /// Step 12 of https://fetch.spec.whatwg.org/#concept-http-redirect-fetch
- pub fn extract_source(&mut self) {
- match self.source {
- BodySource::Null => panic!("Null sources should never be re-directed."),
- BodySource::Object => {
- let (chan, port) = ipc::channel().unwrap();
- let mut selfchan = self.chan.lock().unwrap();
- let _ = selfchan.send(BodyChunkRequest::Extract(port));
- *selfchan = chan;
- },
- }
- }
-
- pub fn take_stream(&self) -> Arc<Mutex<IpcSender<BodyChunkRequest>>> {
- self.chan.clone()
- }
-
- pub fn source_is_null(&self) -> bool {
- self.source == BodySource::Null
- }
-
- pub fn len(&self) -> Option<usize> {
- self.total_bytes.clone()
- }
-}
-
-#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
-pub struct RequestBuilder {
- #[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: HeaderMap,
- pub unsafe_request: bool,
- pub body: Option<RequestBody>,
- 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: Referrer,
- pub referrer_policy: Option<ReferrerPolicy>,
- pub pipeline_id: Option<PipelineId>,
- pub redirect_mode: RedirectMode,
- pub integrity_metadata: String,
- // This is nominally a part of the client's global object.
- // It is copied here to avoid having to reach across the thread
- // boundary every time a redirect occurs.
- #[ignore_malloc_size_of = "Defined in rust-content-security-policy"]
- pub csp_list: Option<CspList>,
- // to keep track of redirects
- pub url_list: Vec<ServoUrl>,
- pub parser_metadata: ParserMetadata,
- pub initiator: Initiator,
- pub https_state: HttpsState,
- pub response_tainting: ResponseTainting,
- /// Servo internal: if crash details are present, trigger a crash error page with these details.
- pub crash: Option<String>,
-}
-
-impl RequestBuilder {
- pub fn new(url: ServoUrl, referrer: Referrer) -> RequestBuilder {
- RequestBuilder {
- method: Method::GET,
- url: url,
- headers: HeaderMap::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::CredentialsSameOrigin,
- use_url_credentials: false,
- origin: ImmutableOrigin::new_opaque(),
- referrer: referrer,
- referrer_policy: None,
- pipeline_id: None,
- redirect_mode: RedirectMode::Follow,
- integrity_metadata: "".to_owned(),
- url_list: vec![],
- parser_metadata: ParserMetadata::Default,
- initiator: Initiator::None,
- csp_list: None,
- https_state: HttpsState::None,
- response_tainting: ResponseTainting::Basic,
- crash: None,
- }
- }
-
- pub fn initiator(mut self, initiator: Initiator) -> RequestBuilder {
- self.initiator = initiator;
- self
- }
-
- pub fn method(mut self, method: Method) -> RequestBuilder {
- self.method = method;
- self
- }
-
- pub fn headers(mut self, headers: HeaderMap) -> RequestBuilder {
- self.headers = headers;
- self
- }
-
- pub fn unsafe_request(mut self, unsafe_request: bool) -> RequestBuilder {
- self.unsafe_request = unsafe_request;
- self
- }
-
- pub fn body(mut self, body: Option<RequestBody>) -> RequestBuilder {
- self.body = body;
- self
- }
-
- pub fn destination(mut self, destination: Destination) -> RequestBuilder {
- self.destination = destination;
- self
- }
-
- pub fn synchronous(mut self, synchronous: bool) -> RequestBuilder {
- self.synchronous = synchronous;
- self
- }
-
- pub fn mode(mut self, mode: RequestMode) -> RequestBuilder {
- self.mode = mode;
- self
- }
-
- pub fn use_cors_preflight(mut self, use_cors_preflight: bool) -> RequestBuilder {
- self.use_cors_preflight = use_cors_preflight;
- self
- }
-
- pub fn credentials_mode(mut self, credentials_mode: CredentialsMode) -> RequestBuilder {
- self.credentials_mode = credentials_mode;
- self
- }
-
- pub fn use_url_credentials(mut self, use_url_credentials: bool) -> RequestBuilder {
- self.use_url_credentials = use_url_credentials;
- self
- }
-
- pub fn origin(mut self, origin: ImmutableOrigin) -> RequestBuilder {
- self.origin = origin;
- self
- }
-
- pub fn referrer_policy(mut self, referrer_policy: Option<ReferrerPolicy>) -> RequestBuilder {
- self.referrer_policy = referrer_policy;
- self
- }
-
- pub fn pipeline_id(mut self, pipeline_id: Option<PipelineId>) -> RequestBuilder {
- self.pipeline_id = pipeline_id;
- self
- }
-
- pub fn redirect_mode(mut self, redirect_mode: RedirectMode) -> RequestBuilder {
- self.redirect_mode = redirect_mode;
- self
- }
-
- pub fn integrity_metadata(mut self, integrity_metadata: String) -> RequestBuilder {
- self.integrity_metadata = integrity_metadata;
- self
- }
-
- pub fn parser_metadata(mut self, parser_metadata: ParserMetadata) -> RequestBuilder {
- self.parser_metadata = parser_metadata;
- self
- }
-
- pub fn https_state(mut self, https_state: HttpsState) -> RequestBuilder {
- self.https_state = https_state;
- self
- }
-
- pub fn response_tainting(mut self, response_tainting: ResponseTainting) -> RequestBuilder {
- self.response_tainting = response_tainting;
- self
- }
-
- pub fn crash(mut self, crash: Option<String>) -> Self {
- self.crash = crash;
- self
- }
-
- pub fn build(self) -> Request {
- let mut request = Request::new(
- self.url.clone(),
- Some(Origin::Origin(self.origin)),
- self.referrer,
- self.pipeline_id,
- self.https_state,
- );
- request.initiator = self.initiator;
- request.method = self.method;
- request.headers = self.headers;
- request.unsafe_request = self.unsafe_request;
- request.body = self.body;
- request.service_workers_mode = self.service_workers_mode;
- request.destination = self.destination;
- request.synchronous = self.synchronous;
- request.mode = self.mode;
- request.use_cors_preflight = self.use_cors_preflight;
- request.credentials_mode = self.credentials_mode;
- request.use_url_credentials = self.use_url_credentials;
- request.cache_mode = self.cache_mode;
- request.referrer_policy = self.referrer_policy;
- request.redirect_mode = self.redirect_mode;
- let mut url_list = self.url_list;
- if url_list.is_empty() {
- url_list.push(self.url);
- }
- request.redirect_count = url_list.len() as u32 - 1;
- request.url_list = url_list;
- request.integrity_metadata = self.integrity_metadata;
- request.parser_metadata = self.parser_metadata;
- request.csp_list = self.csp_list;
- request.response_tainting = self.response_tainting;
- request.crash = self.crash;
- request
- }
-}
-
-/// A [Request](https://fetch.spec.whatwg.org/#concept-request) as defined by
-/// the Fetch spec.
-#[derive(Clone, MallocSizeOf)]
-pub struct Request {
- /// <https://fetch.spec.whatwg.org/#concept-request-method>
- #[ignore_malloc_size_of = "Defined in hyper"]
- pub method: Method,
- /// <https://fetch.spec.whatwg.org/#local-urls-only-flag>
- pub local_urls_only: bool,
- /// <https://fetch.spec.whatwg.org/#sandboxed-storage-area-urls-flag>
- pub sandboxed_storage_area_urls: bool,
- /// <https://fetch.spec.whatwg.org/#concept-request-header-list>
- #[ignore_malloc_size_of = "Defined in hyper"]
- pub headers: HeaderMap,
- /// <https://fetch.spec.whatwg.org/#unsafe-request-flag>
- pub unsafe_request: bool,
- /// <https://fetch.spec.whatwg.org/#concept-request-body>
- pub body: Option<RequestBody>,
- // TODO: client object
- pub window: Window,
- // TODO: target browsing context
- /// <https://fetch.spec.whatwg.org/#request-keepalive-flag>
- pub keep_alive: bool,
- /// <https://fetch.spec.whatwg.org/#request-service-workers-mode>
- pub service_workers_mode: ServiceWorkersMode,
- /// <https://fetch.spec.whatwg.org/#concept-request-initiator>
- pub initiator: Initiator,
- /// <https://fetch.spec.whatwg.org/#concept-request-destination>
- pub destination: Destination,
- // TODO: priority object
- /// <https://fetch.spec.whatwg.org/#concept-request-origin>
- pub origin: Origin,
- /// <https://fetch.spec.whatwg.org/#concept-request-referrer>
- pub referrer: Referrer,
- /// <https://fetch.spec.whatwg.org/#concept-request-referrer-policy>
- pub referrer_policy: Option<ReferrerPolicy>,
- pub pipeline_id: Option<PipelineId>,
- /// <https://fetch.spec.whatwg.org/#synchronous-flag>
- pub synchronous: bool,
- /// <https://fetch.spec.whatwg.org/#concept-request-mode>
- pub mode: RequestMode,
- /// <https://fetch.spec.whatwg.org/#use-cors-preflight-flag>
- pub use_cors_preflight: bool,
- /// <https://fetch.spec.whatwg.org/#concept-request-credentials-mode>
- pub credentials_mode: CredentialsMode,
- /// <https://fetch.spec.whatwg.org/#concept-request-use-url-credentials-flag>
- pub use_url_credentials: bool,
- /// <https://fetch.spec.whatwg.org/#concept-request-cache-mode>
- pub cache_mode: CacheMode,
- /// <https://fetch.spec.whatwg.org/#concept-request-redirect-mode>
- pub redirect_mode: RedirectMode,
- /// <https://fetch.spec.whatwg.org/#concept-request-integrity-metadata>
- 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
- /// <https://fetch.spec.whatwg.org/#concept-request-url-list>
- pub url_list: Vec<ServoUrl>,
- /// <https://fetch.spec.whatwg.org/#concept-request-redirect-count>
- pub redirect_count: u32,
- /// <https://fetch.spec.whatwg.org/#concept-request-response-tainting>
- pub response_tainting: ResponseTainting,
- /// <https://fetch.spec.whatwg.org/#concept-request-parser-metadata>
- pub parser_metadata: ParserMetadata,
- // This is nominally a part of the client's global object.
- // It is copied here to avoid having to reach across the thread
- // boundary every time a redirect occurs.
- #[ignore_malloc_size_of = "Defined in rust-content-security-policy"]
- pub csp_list: Option<CspList>,
- pub https_state: HttpsState,
- /// Servo internal: if crash details are present, trigger a crash error page with these details.
- pub crash: Option<String>,
-}
-
-impl Request {
- pub fn new(
- url: ServoUrl,
- origin: Option<Origin>,
- referrer: Referrer,
- pipeline_id: Option<PipelineId>,
- https_state: HttpsState,
- ) -> Request {
- Request {
- method: Method::GET,
- local_urls_only: false,
- sandboxed_storage_area_urls: false,
- headers: HeaderMap::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,
- referrer_policy: None,
- pipeline_id: pipeline_id,
- synchronous: false,
- mode: RequestMode::NoCors,
- use_cors_preflight: false,
- credentials_mode: CredentialsMode::CredentialsSameOrigin,
- use_url_credentials: false,
- cache_mode: CacheMode::Default,
- redirect_mode: RedirectMode::Follow,
- integrity_metadata: String::new(),
- url_list: vec![url],
- parser_metadata: ParserMetadata::Default,
- redirect_count: 0,
- response_tainting: ResponseTainting::Basic,
- csp_list: None,
- https_state: https_state,
- crash: None,
- }
- }
-
- /// <https://fetch.spec.whatwg.org/#concept-request-url>
- pub fn url(&self) -> ServoUrl {
- self.url_list.first().unwrap().clone()
- }
-
- /// <https://fetch.spec.whatwg.org/#concept-request-current-url>
- pub fn current_url(&self) -> ServoUrl {
- self.url_list.last().unwrap().clone()
- }
-
- /// <https://fetch.spec.whatwg.org/#concept-request-current-url>
- pub fn current_url_mut(&mut self) -> &mut ServoUrl {
- self.url_list.last_mut().unwrap()
- }
-
- /// <https://fetch.spec.whatwg.org/#navigation-request>
- pub fn is_navigation_request(&self) -> bool {
- self.destination == Destination::Document
- }
-
- /// <https://fetch.spec.whatwg.org/#subresource-request>
- 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,
- }
- }
-
- pub fn timing_type(&self) -> ResourceTimingType {
- if self.is_navigation_request() {
- ResourceTimingType::Navigation
- } else {
- ResourceTimingType::Resource
- }
- }
-}
-
-impl Referrer {
- pub fn to_url(&self) -> Option<&ServoUrl> {
- match *self {
- Referrer::NoReferrer => None,
- Referrer::Client(ref url) => Some(url),
- Referrer::ReferrerUrl(ref url) => Some(url),
- }
- }
-}
-
-// https://fetch.spec.whatwg.org/#cors-unsafe-request-header-byte
-// TODO: values in the control-code range are being quietly stripped out by
-// HeaderMap and never reach this function to be loudly rejected!
-fn is_cors_unsafe_request_header_byte(value: &u8) -> bool {
- match value {
- 0x00..=0x08 |
- 0x10..=0x19 |
- 0x22 |
- 0x28 |
- 0x29 |
- 0x3A |
- 0x3C |
- 0x3E |
- 0x3F |
- 0x40 |
- 0x5B |
- 0x5C |
- 0x5D |
- 0x7B |
- 0x7D |
- 0x7F => true,
- _ => false,
- }
-}
-
-// https://fetch.spec.whatwg.org/#cors-safelisted-request-header
-// subclause `accept`
-fn is_cors_safelisted_request_accept(value: &[u8]) -> bool {
- !(value.iter().any(is_cors_unsafe_request_header_byte))
-}
-
-// https://fetch.spec.whatwg.org/#cors-safelisted-request-header
-// subclauses `accept-language`, `content-language`
-fn is_cors_safelisted_language(value: &[u8]) -> bool {
- value.iter().all(|&x| match x {
- 0x30..=0x39 |
- 0x41..=0x5A |
- 0x61..=0x7A |
- 0x20 |
- 0x2A |
- 0x2C |
- 0x2D |
- 0x2E |
- 0x3B |
- 0x3D => true,
- _ => false,
- })
-}
-
-// https://fetch.spec.whatwg.org/#cors-safelisted-request-header
-// subclause `content-type`
-fn is_cors_safelisted_request_content_type(value: &[u8]) -> bool {
- // step 1
- if value.iter().any(is_cors_unsafe_request_header_byte) {
- return false;
- }
- // step 2
- let value_string = if let Ok(s) = std::str::from_utf8(value) {
- s
- } else {
- return false;
- };
- let value_mime_result: Result<Mime, _> = value_string.parse();
- match value_mime_result {
- Err(_) => false, // step 3
- Ok(value_mime) => match (value_mime.type_(), value_mime.subtype()) {
- (mime::APPLICATION, mime::WWW_FORM_URLENCODED) |
- (mime::MULTIPART, mime::FORM_DATA) |
- (mime::TEXT, mime::PLAIN) => true,
- _ => false, // step 4
- },
- }
-}
-
-// TODO: "DPR", "Downlink", "Save-Data", "Viewport-Width", "Width":
-// ... once parsed, the value should not be failure.
-// https://fetch.spec.whatwg.org/#cors-safelisted-request-header
-pub fn is_cors_safelisted_request_header<N: AsRef<str>, V: AsRef<[u8]>>(
- name: &N,
- value: &V,
-) -> bool {
- let name: &str = name.as_ref();
- let value: &[u8] = value.as_ref();
- if value.len() > 128 {
- return false;
- }
- match name {
- "accept" => is_cors_safelisted_request_accept(value),
- "accept-language" | "content-language" => is_cors_safelisted_language(value),
- "content-type" => is_cors_safelisted_request_content_type(value),
- _ => false,
- }
-}
-
-/// <https://fetch.spec.whatwg.org/#cors-safelisted-method>
-pub fn is_cors_safelisted_method(m: &Method) -> bool {
- match *m {
- Method::GET | Method::HEAD | Method::POST => true,
- _ => false,
- }
-}
-
-/// <https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name>
-pub fn is_cors_non_wildcard_request_header_name(name: &HeaderName) -> bool {
- name == AUTHORIZATION
-}
-
-/// <https://fetch.spec.whatwg.org/#cors-unsafe-request-header-names>
-pub fn get_cors_unsafe_header_names(headers: &HeaderMap) -> Vec<HeaderName> {
- // Step 1
- let mut unsafe_names: Vec<&HeaderName> = vec![];
- // Step 2
- let mut potentillay_unsafe_names: Vec<&HeaderName> = vec![];
- // Step 3
- let mut safelist_value_size = 0;
-
- // Step 4
- for (name, value) in headers.iter() {
- if !is_cors_safelisted_request_header(&name, &value) {
- unsafe_names.push(name);
- } else {
- potentillay_unsafe_names.push(name);
- safelist_value_size += value.as_ref().len();
- }
- }
-
- // Step 5
- if safelist_value_size > 1024 {
- unsafe_names.extend_from_slice(&potentillay_unsafe_names);
- }
-
- // Step 6
- return convert_header_names_to_sorted_lowercase_set(unsafe_names);
-}
-
-/// <https://fetch.spec.whatwg.org/#ref-for-convert-header-names-to-a-sorted-lowercase-set>
-pub fn convert_header_names_to_sorted_lowercase_set(
- header_names: Vec<&HeaderName>,
-) -> Vec<HeaderName> {
- // HeaderName does not implement the needed traits to use a BTreeSet
- // So create a new Vec, sort, then dedup
- let mut ordered_set = header_names.to_vec();
- ordered_set.sort_by(|a, b| a.as_str().partial_cmp(b.as_str()).unwrap());
- ordered_set.dedup();
- return ordered_set.into_iter().cloned().collect();
-}
diff --git a/components/net_traits/response.rs b/components/net_traits/response.rs
deleted file mode 100644
index 552c0057c50..00000000000
--- a/components/net_traits/response.rs
+++ /dev/null
@@ -1,364 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-//! The [Response](https://fetch.spec.whatwg.org/#responses) object
-//! resulting from a [fetch operation](https://fetch.spec.whatwg.org/#concept-fetch)
-use std::sync::atomic::AtomicBool;
-use std::sync::Mutex;
-
-use headers::{ContentType, HeaderMapExt};
-use http::{HeaderMap, StatusCode};
-use hyper_serde::Serde;
-use malloc_size_of_derive::MallocSizeOf;
-use serde::{Deserialize, Serialize};
-use servo_arc::Arc;
-use servo_url::ServoUrl;
-
-use crate::{
- FetchMetadata, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy, ResourceFetchTiming,
- ResourceTimingType,
-};
-
-/// [Response type](https://fetch.spec.whatwg.org/#concept-response-type)
-#[derive(Clone, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
-pub enum ResponseType {
- Basic,
- Cors,
- Default,
- Error(NetworkError),
- Opaque,
- OpaqueRedirect,
-}
-
-/// [Response termination reason](https://fetch.spec.whatwg.org/#concept-response-termination-reason)
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, Serialize)]
-pub enum TerminationReason {
- EndUserAbort,
- Fatal,
- Timeout,
-}
-
-/// The response body can still be pushed to after fetch
-/// This provides a way to store unfinished response bodies
-#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
-pub enum ResponseBody {
- Empty, // XXXManishearth is this necessary, or is Done(vec![]) enough?
- Receiving(Vec<u8>),
- Done(Vec<u8>),
-}
-
-impl ResponseBody {
- pub fn is_done(&self) -> bool {
- match *self {
- ResponseBody::Done(..) => true,
- ResponseBody::Empty | ResponseBody::Receiving(..) => false,
- }
- }
-}
-
-/// [Cache state](https://fetch.spec.whatwg.org/#concept-response-cache-state)
-#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
-pub enum CacheState {
- None,
- Local,
- Validated,
- Partial,
-}
-
-/// [Https state](https://fetch.spec.whatwg.org/#concept-response-https-state)
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
-pub enum HttpsState {
- None,
- Deprecated,
- Modern,
-}
-
-#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
-pub struct ResponseInit {
- pub url: ServoUrl,
- #[serde(
- deserialize_with = "::hyper_serde::deserialize",
- serialize_with = "::hyper_serde::serialize"
- )]
- #[ignore_malloc_size_of = "Defined in hyper"]
- pub headers: HeaderMap,
- pub status_code: u16,
- pub referrer: Option<ServoUrl>,
- pub location_url: Option<Result<ServoUrl, String>>,
-}
-
-/// A [Response](https://fetch.spec.whatwg.org/#concept-response) as defined by the Fetch spec
-#[derive(Clone, Debug, MallocSizeOf)]
-pub struct Response {
- pub response_type: ResponseType,
- pub termination_reason: Option<TerminationReason>,
- url: Option<ServoUrl>,
- pub url_list: Vec<ServoUrl>,
- /// `None` can be considered a StatusCode of `0`.
- #[ignore_malloc_size_of = "Defined in hyper"]
- pub status: Option<(StatusCode, String)>,
- pub raw_status: Option<(u16, Vec<u8>)>,
- #[ignore_malloc_size_of = "Defined in hyper"]
- pub headers: HeaderMap,
- #[ignore_malloc_size_of = "Mutex heap size undefined"]
- pub body: Arc<Mutex<ResponseBody>>,
- pub cache_state: CacheState,
- pub https_state: HttpsState,
- pub referrer: Option<ServoUrl>,
- pub referrer_policy: Option<ReferrerPolicy>,
- /// [CORS-exposed header-name list](https://fetch.spec.whatwg.org/#concept-response-cors-exposed-header-name-list)
- pub cors_exposed_header_name_list: Vec<String>,
- /// [Location URL](https://fetch.spec.whatwg.org/#concept-response-location-url)
- pub location_url: Option<Result<ServoUrl, String>>,
- /// [Internal response](https://fetch.spec.whatwg.org/#concept-internal-response), only used if the Response
- /// is a filtered response
- pub internal_response: Option<Box<Response>>,
- /// whether or not to try to return the internal_response when asked for actual_response
- pub return_internal: bool,
- /// https://fetch.spec.whatwg.org/#concept-response-aborted
- #[ignore_malloc_size_of = "AtomicBool heap size undefined"]
- pub aborted: Arc<AtomicBool>,
- /// track network metrics
- #[ignore_malloc_size_of = "Mutex heap size undefined"]
- pub resource_timing: Arc<Mutex<ResourceFetchTiming>>,
-}
-
-impl Response {
- pub fn new(url: ServoUrl, resource_timing: ResourceFetchTiming) -> Response {
- Response {
- response_type: ResponseType::Default,
- termination_reason: None,
- url: Some(url),
- url_list: vec![],
- status: Some((StatusCode::OK, "".to_string())),
- raw_status: Some((200, b"".to_vec())),
- headers: HeaderMap::new(),
- body: Arc::new(Mutex::new(ResponseBody::Empty)),
- cache_state: CacheState::None,
- https_state: HttpsState::None,
- referrer: None,
- referrer_policy: None,
- cors_exposed_header_name_list: vec![],
- location_url: None,
- internal_response: None,
- return_internal: true,
- aborted: Arc::new(AtomicBool::new(false)),
- resource_timing: Arc::new(Mutex::new(resource_timing)),
- }
- }
-
- pub fn from_init(init: ResponseInit, resource_timing_type: ResourceTimingType) -> Response {
- let mut res = Response::new(init.url, ResourceFetchTiming::new(resource_timing_type));
- res.location_url = init.location_url;
- res.headers = init.headers;
- res.referrer = init.referrer;
- res.status = StatusCode::from_u16(init.status_code)
- .map(|s| (s, s.to_string()))
- .ok();
- res
- }
-
- pub fn network_error(e: NetworkError) -> Response {
- Response {
- response_type: ResponseType::Error(e),
- termination_reason: None,
- url: None,
- url_list: vec![],
- status: None,
- raw_status: None,
- headers: HeaderMap::new(),
- body: Arc::new(Mutex::new(ResponseBody::Empty)),
- cache_state: CacheState::None,
- https_state: HttpsState::None,
- referrer: None,
- referrer_policy: None,
- cors_exposed_header_name_list: vec![],
- location_url: None,
- internal_response: None,
- return_internal: true,
- aborted: Arc::new(AtomicBool::new(false)),
- resource_timing: Arc::new(Mutex::new(ResourceFetchTiming::new(
- ResourceTimingType::Error,
- ))),
- }
- }
-
- pub fn url(&self) -> Option<&ServoUrl> {
- self.url.as_ref()
- }
-
- pub fn is_network_error(&self) -> bool {
- match self.response_type {
- ResponseType::Error(..) => true,
- _ => false,
- }
- }
-
- pub fn get_network_error(&self) -> Option<&NetworkError> {
- match self.response_type {
- ResponseType::Error(ref e) => Some(e),
- _ => None,
- }
- }
-
- pub fn actual_response(&self) -> &Response {
- if self.return_internal && self.internal_response.is_some() {
- &**self.internal_response.as_ref().unwrap()
- } else {
- self
- }
- }
-
- pub fn actual_response_mut(&mut self) -> &mut Response {
- if self.return_internal && self.internal_response.is_some() {
- &mut **self.internal_response.as_mut().unwrap()
- } else {
- self
- }
- }
-
- pub fn to_actual(self) -> Response {
- if self.return_internal && self.internal_response.is_some() {
- *self.internal_response.unwrap()
- } else {
- self
- }
- }
-
- pub fn get_resource_timing(&self) -> Arc<Mutex<ResourceFetchTiming>> {
- Arc::clone(&self.resource_timing)
- }
-
- /// Convert to a filtered response, of type `filter_type`.
- /// Do not use with type Error or Default
- #[rustfmt::skip]
- pub fn to_filtered(self, filter_type: ResponseType) -> Response {
- match filter_type {
- ResponseType::Default |
- ResponseType::Error(..) => panic!(),
- _ => (),
- }
-
- let old_response = self.to_actual();
-
- if let ResponseType::Error(e) = old_response.response_type {
- return Response::network_error(e);
- }
-
- let old_headers = old_response.headers.clone();
- let exposed_headers = old_response.cors_exposed_header_name_list.clone();
- let mut response = old_response.clone();
- response.internal_response = Some(Box::new(old_response));
- response.response_type = filter_type;
-
- match response.response_type {
- ResponseType::Default |
- ResponseType::Error(..) => unreachable!(),
-
- ResponseType::Basic => {
- let headers = old_headers.iter().filter(|(name, _)| {
- match &*name.as_str().to_ascii_lowercase() {
- "set-cookie" | "set-cookie2" => false,
- _ => true
- }
- }).map(|(n, v)| (n.clone(), v.clone())).collect();
- response.headers = headers;
- },
-
- ResponseType::Cors => {
- let headers = old_headers.iter().filter(|(name, _)| {
- match &*name.as_str().to_ascii_lowercase() {
- "cache-control" | "content-language" | "content-type" |
- "expires" | "last-modified" | "pragma" => true,
- "set-cookie" | "set-cookie2" => false,
- header => {
- exposed_headers.iter().any(|h| *header == h.as_str().to_ascii_lowercase())
- }
- }
- }).map(|(n, v)| (n.clone(), v.clone())).collect();
- response.headers = headers;
- },
-
- ResponseType::Opaque => {
- response.url_list = vec![];
- response.url = None;
- response.headers = HeaderMap::new();
- response.status = None;
- response.body = Arc::new(Mutex::new(ResponseBody::Empty));
- response.cache_state = CacheState::None;
- },
-
- ResponseType::OpaqueRedirect => {
- response.headers = HeaderMap::new();
- response.status = None;
- response.body = Arc::new(Mutex::new(ResponseBody::Empty));
- response.cache_state = CacheState::None;
- },
- }
-
- response
- }
-
- pub fn metadata(&self) -> Result<FetchMetadata, NetworkError> {
- fn init_metadata(response: &Response, url: &ServoUrl) -> Metadata {
- let mut metadata = Metadata::default(url.clone());
- metadata.set_content_type(
- response
- .headers
- .typed_get::<ContentType>()
- .map(|v| v.into())
- .as_ref(),
- );
- metadata.location_url = response.location_url.clone();
- metadata.headers = Some(Serde(response.headers.clone()));
- metadata.status = response.raw_status.clone();
- metadata.https_state = response.https_state;
- metadata.referrer = response.referrer.clone();
- metadata.referrer_policy = response.referrer_policy.clone();
- metadata.redirected = response.actual_response().url_list.len() > 1;
- metadata
- }
-
- if let Some(error) = self.get_network_error() {
- return Err(error.clone());
- }
-
- let metadata = self.url.as_ref().map(|url| init_metadata(self, url));
-
- if let Some(ref response) = self.internal_response {
- match response.url {
- Some(ref url) => {
- let unsafe_metadata = init_metadata(response, url);
-
- match self.response_type {
- ResponseType::Basic => Ok(FetchMetadata::Filtered {
- filtered: FilteredMetadata::Basic(metadata.unwrap()),
- unsafe_: unsafe_metadata,
- }),
- ResponseType::Cors => Ok(FetchMetadata::Filtered {
- filtered: FilteredMetadata::Cors(metadata.unwrap()),
- unsafe_: unsafe_metadata,
- }),
- ResponseType::Default => unreachable!(),
- ResponseType::Error(ref network_err) => Err(network_err.clone()),
- ResponseType::Opaque => Ok(FetchMetadata::Filtered {
- filtered: FilteredMetadata::Opaque,
- unsafe_: unsafe_metadata,
- }),
- ResponseType::OpaqueRedirect => Ok(FetchMetadata::Filtered {
- filtered: FilteredMetadata::OpaqueRedirect(url.clone()),
- unsafe_: unsafe_metadata,
- }),
- }
- },
- None => Err(NetworkError::Internal(
- "No url found in unsafe response".to_owned(),
- )),
- }
- } else {
- assert_eq!(self.response_type, ResponseType::Default);
- Ok(FetchMetadata::Unfiltered(metadata.unwrap()))
- }
- }
-}
diff --git a/components/net_traits/storage_thread.rs b/components/net_traits/storage_thread.rs
deleted file mode 100644
index 0253603016e..00000000000
--- a/components/net_traits/storage_thread.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-use ipc_channel::ipc::IpcSender;
-use malloc_size_of_derive::MallocSizeOf;
-use serde::{Deserialize, Serialize};
-use servo_url::ServoUrl;
-
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, Serialize)]
-pub enum StorageType {
- Session,
- Local,
-}
-
-/// Request operations on the storage data associated with a particular url
-#[derive(Debug, Deserialize, Serialize)]
-pub enum StorageThreadMsg {
- /// gets the number of key/value pairs present in the associated storage data
- Length(IpcSender<usize>, ServoUrl, StorageType),
-
- /// gets the name of the key at the specified index in the associated storage data
- Key(IpcSender<Option<String>>, ServoUrl, StorageType, u32),
-
- /// Gets the available keys in the associated storage data
- Keys(IpcSender<Vec<String>>, ServoUrl, StorageType),
-
- /// gets the value associated with the given key in the associated storage data
- GetItem(IpcSender<Option<String>>, ServoUrl, StorageType, String),
-
- /// sets the value of the given key in the associated storage data
- SetItem(
- IpcSender<Result<(bool, Option<String>), ()>>,
- ServoUrl,
- StorageType,
- String,
- String,
- ),
-
- /// removes the key/value pair for the given key in the associated storage data
- RemoveItem(IpcSender<Option<String>>, ServoUrl, StorageType, String),
-
- /// clears the associated storage data by removing all the key/value pairs
- Clear(IpcSender<bool>, ServoUrl, StorageType),
-
- /// send a reply when done cleaning up thread resources and then shut it down
- Exit(IpcSender<()>),
-}
diff --git a/components/net_traits/tests/image.rs b/components/net_traits/tests/image.rs
deleted file mode 100644
index a4963702b57..00000000000
--- a/components/net_traits/tests/image.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-use net_traits::image::base::detect_image_format;
-
-#[test]
-fn test_supported_images() {
- let gif1 = [b'G', b'I', b'F', b'8', b'7', b'a'];
- let gif2 = [b'G', b'I', b'F', b'8', b'9', b'a'];
- let jpeg = [0xff, 0xd8, 0xff];
- let png = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A];
- let webp = [
- b'R', b'I', b'F', b'F', 0x01, 0x02, 0x03, 0x04, b'W', b'E', b'B', b'P', b'V', b'P',
- ];
- let bmp = [0x42, 0x4D];
- let ico = [0x00, 0x00, 0x01, 0x00];
- let junk_format = [0x01, 0x02, 0x03, 0x04, 0x05];
-
- assert!(detect_image_format(&gif1).is_ok());
- assert!(detect_image_format(&gif2).is_ok());
- assert!(detect_image_format(&jpeg).is_ok());
- assert!(detect_image_format(&png).is_ok());
- assert!(detect_image_format(&webp).is_ok());
- assert!(detect_image_format(&bmp).is_ok());
- assert!(detect_image_format(&ico).is_ok());
- assert!(detect_image_format(&junk_format).is_err());
-}
diff --git a/components/net_traits/tests/lib.rs b/components/net_traits/tests/lib.rs
deleted file mode 100644
index 290ca902935..00000000000
--- a/components/net_traits/tests/lib.rs
+++ /dev/null
@@ -1,212 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-use net_traits::{ResourceAttribute, ResourceFetchTiming, ResourceTimeValue, ResourceTimingType};
-
-#[test]
-fn test_set_start_time_to_fetch_start_if_nonzero_tao() {
- let mut resource_timing: ResourceFetchTiming =
- ResourceFetchTiming::new(ResourceTimingType::Resource);
- resource_timing.fetch_start = 1;
- assert_eq!(resource_timing.start_time, 0, "`start_time` should be zero");
- assert!(
- resource_timing.fetch_start > 0,
- "`fetch_start` should have a positive value"
- );
-
- // verify that setting `start_time` to `fetch_start` succeeds
- resource_timing.set_attribute(ResourceAttribute::StartTime(ResourceTimeValue::FetchStart));
- assert_eq!(
- resource_timing.start_time, resource_timing.fetch_start,
- "`start_time` should equal `fetch_start`"
- );
-}
-
-#[test]
-fn test_set_start_time_to_fetch_start_if_zero_tao() {
- let mut resource_timing: ResourceFetchTiming =
- ResourceFetchTiming::new(ResourceTimingType::Resource);
- resource_timing.start_time = 1;
- assert!(
- resource_timing.start_time > 0,
- "`start_time` should have a positive value"
- );
- assert_eq!(
- resource_timing.fetch_start, 0,
- "`fetch_start` should be zero"
- );
-
- // verify that setting `start_time` to `fetch_start` succeeds even when `fetch_start` == zero
- resource_timing.set_attribute(ResourceAttribute::StartTime(ResourceTimeValue::FetchStart));
- assert_eq!(
- resource_timing.start_time, resource_timing.fetch_start,
- "`start_time` should equal `fetch_start`"
- );
-}
-
-#[test]
-fn test_set_start_time_to_fetch_start_if_nonzero_no_tao() {
- let mut resource_timing: ResourceFetchTiming =
- ResourceFetchTiming::new(ResourceTimingType::Resource);
- resource_timing.mark_timing_check_failed();
- resource_timing.fetch_start = 1;
- assert_eq!(resource_timing.start_time, 0, "`start_time` should be zero");
- assert!(
- resource_timing.fetch_start > 0,
- "`fetch_start` should have a positive value"
- );
-
- // verify that setting `start_time` to `fetch_start` succeeds even when TAO check failed
- resource_timing.set_attribute(ResourceAttribute::StartTime(ResourceTimeValue::FetchStart));
- assert_eq!(
- resource_timing.start_time, resource_timing.fetch_start,
- "`start_time` should equal `fetch_start`"
- );
-}
-
-#[test]
-fn test_set_start_time_to_fetch_start_if_zero_no_tao() {
- let mut resource_timing: ResourceFetchTiming =
- ResourceFetchTiming::new(ResourceTimingType::Resource);
- resource_timing.mark_timing_check_failed();
- resource_timing.start_time = 1;
- assert!(
- resource_timing.start_time > 0,
- "`start_time` should have a positive value"
- );
- assert_eq!(
- resource_timing.fetch_start, 0,
- "`fetch_start` should be zero"
- );
-
- // verify that setting `start_time` to `fetch_start` succeeds even when `fetch_start`==0 and no TAO
- resource_timing.set_attribute(ResourceAttribute::StartTime(ResourceTimeValue::FetchStart));
- assert_eq!(
- resource_timing.start_time, resource_timing.fetch_start,
- "`start_time` should equal `fetch_start`"
- );
-}
-
-#[test]
-fn test_set_start_time_to_redirect_start_if_nonzero_tao() {
- let mut resource_timing: ResourceFetchTiming =
- ResourceFetchTiming::new(ResourceTimingType::Resource);
- resource_timing.redirect_start = 1;
- assert_eq!(resource_timing.start_time, 0, "`start_time` should be zero");
- assert!(
- resource_timing.redirect_start > 0,
- "`redirect_start` should have a positive value"
- );
-
- // verify that setting `start_time` to `redirect_start` succeeds for nonzero `redirect_start`, TAO pass
- resource_timing.set_attribute(ResourceAttribute::StartTime(
- ResourceTimeValue::RedirectStart,
- ));
- assert_eq!(
- resource_timing.start_time, resource_timing.redirect_start,
- "`start_time` should equal `redirect_start`"
- );
-}
-
-#[test]
-fn test_not_set_start_time_to_redirect_start_if_zero_tao() {
- let mut resource_timing: ResourceFetchTiming =
- ResourceFetchTiming::new(ResourceTimingType::Resource);
- resource_timing.start_time = 1;
- assert!(
- resource_timing.start_time > 0,
- "`start_time` should have a positive value"
- );
- assert_eq!(
- resource_timing.redirect_start, 0,
- "`redirect_start` should be zero"
- );
-
- // verify that setting `start_time` to `redirect_start` fails if `redirect_start` == 0
- resource_timing.set_attribute(ResourceAttribute::StartTime(
- ResourceTimeValue::RedirectStart,
- ));
- assert_ne!(
- resource_timing.start_time, resource_timing.redirect_start,
- "`start_time` should *not* equal `redirect_start`"
- );
-}
-
-#[test]
-fn test_not_set_start_time_to_redirect_start_if_nonzero_no_tao() {
- let mut resource_timing: ResourceFetchTiming =
- ResourceFetchTiming::new(ResourceTimingType::Resource);
- resource_timing.mark_timing_check_failed();
- // Note: properly-behaved redirect_start should never be nonzero once TAO check has failed
- resource_timing.redirect_start = 1;
- assert_eq!(resource_timing.start_time, 0, "`start_time` should be zero");
- assert!(
- resource_timing.redirect_start > 0,
- "`redirect_start` should have a positive value"
- );
-
- // verify that setting `start_time` to `redirect_start` fails if TAO check fails
- resource_timing.set_attribute(ResourceAttribute::StartTime(
- ResourceTimeValue::RedirectStart,
- ));
- assert_ne!(
- resource_timing.start_time, resource_timing.redirect_start,
- "`start_time` should *not* equal `redirect_start`"
- );
-}
-
-#[test]
-fn test_not_set_start_time_to_redirect_start_if_zero_no_tao() {
- let mut resource_timing: ResourceFetchTiming =
- ResourceFetchTiming::new(ResourceTimingType::Resource);
- resource_timing.mark_timing_check_failed();
- resource_timing.start_time = 1;
- assert!(
- resource_timing.start_time > 0,
- "`start_time` should have a positive value"
- );
- assert_eq!(
- resource_timing.redirect_start, 0,
- "`redirect_start` should be zero"
- );
-
- // verify that setting `start_time` to `redirect_start` fails if `redirect_start`==0 and no TAO
- resource_timing.set_attribute(ResourceAttribute::StartTime(
- ResourceTimeValue::RedirectStart,
- ));
- assert_ne!(
- resource_timing.start_time, resource_timing.redirect_start,
- "`start_time` should *not* equal `redirect_start`"
- );
-}
-
-#[test]
-fn test_set_start_time() {
- let mut resource_timing: ResourceFetchTiming =
- ResourceFetchTiming::new(ResourceTimingType::Resource);
- assert_eq!(resource_timing.start_time, 0, "`start_time` should be zero");
-
- // verify setting `start_time` to current time succeeds
- resource_timing.set_attribute(ResourceAttribute::StartTime(ResourceTimeValue::Now));
- assert!(resource_timing.start_time > 0, "failed to set `start_time`");
-}
-#[test]
-fn test_reset_start_time() {
- let mut resource_timing: ResourceFetchTiming =
- ResourceFetchTiming::new(ResourceTimingType::Resource);
- assert_eq!(resource_timing.start_time, 0, "`start_time` should be zero");
-
- resource_timing.start_time = 1;
- assert!(
- resource_timing.start_time > 0,
- "`start_time` should have a positive value"
- );
-
- // verify resetting `start_time` (to zero) succeeds
- resource_timing.set_attribute(ResourceAttribute::StartTime(ResourceTimeValue::Zero));
- assert_eq!(
- resource_timing.start_time, 0,
- "failed to reset `start_time`"
- );
-}
diff --git a/components/net_traits/tests/pub_domains.rs b/components/net_traits/tests/pub_domains.rs
deleted file mode 100644
index ea58e7650e3..00000000000
--- a/components/net_traits/tests/pub_domains.rs
+++ /dev/null
@@ -1,122 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-use net_traits::pub_domains::{is_pub_domain, is_reg_domain, pub_suffix, reg_suffix};
-
-// These tests may need to be updated if the PSL changes.
-
-#[test]
-fn test_is_pub_domain_plain() {
- assert!(is_pub_domain("com"));
- assert!(is_pub_domain(".org"));
- assert!(is_pub_domain("za.org"));
- assert!(is_pub_domain("xn--od0alg.hk"));
- assert!(is_pub_domain("xn--krdsherad-m8a.no"));
-}
-
-#[test]
-fn test_is_pub_domain_wildcard() {
- assert!(is_pub_domain("hello.bd"));
- assert!(is_pub_domain("world.jm"));
- assert!(is_pub_domain("toto.kobe.jp"));
-}
-
-#[test]
-fn test_is_pub_domain_exception() {
- assert_eq!(is_pub_domain("www.ck"), false);
- assert_eq!(is_pub_domain("city.kawasaki.jp"), false);
- assert_eq!(is_pub_domain("city.nagoya.jp"), false);
- assert_eq!(is_pub_domain("teledata.mz"), false);
-}
-
-#[test]
-fn test_is_pub_domain_not() {
- assert_eq!(is_pub_domain(""), false);
- assert_eq!(is_pub_domain("."), false);
- assert_eq!(is_pub_domain("..."), false);
- assert_eq!(is_pub_domain(".servo.org"), false);
- assert_eq!(is_pub_domain("www.mozilla.org"), false);
- assert_eq!(is_pub_domain("publicsuffix.org"), false);
- assert_eq!(is_pub_domain("hello.world.jm"), false);
- assert_eq!(is_pub_domain("toto.toto.kobe.jp"), false);
-}
-
-#[test]
-fn test_is_pub_domain() {
- assert!(!is_pub_domain("city.yokohama.jp"));
- assert!(!is_pub_domain("foo.bar.baz.yokohama.jp"));
- assert!(!is_pub_domain("foo.bar.city.yokohama.jp"));
- assert!(!is_pub_domain("foo.bar.com"));
- assert!(!is_pub_domain("foo.bar.tokyo.jp"));
- assert!(!is_pub_domain("foo.bar.yokohama.jp"));
- assert!(!is_pub_domain("foo.city.yokohama.jp"));
- assert!(!is_pub_domain("foo.com"));
- assert!(!is_pub_domain("foo.tokyo.jp"));
- assert!(!is_pub_domain("yokohama.jp"));
- assert!(is_pub_domain("com"));
- assert!(is_pub_domain("foo.yokohama.jp"));
- assert!(is_pub_domain("jp"));
- assert!(is_pub_domain("tokyo.jp"));
-}
-
-#[test]
-fn test_is_reg_domain() {
- assert!(!is_reg_domain("com"));
- assert!(!is_reg_domain("foo.bar.baz.yokohama.jp"));
- assert!(!is_reg_domain("foo.bar.com"));
- assert!(!is_reg_domain("foo.bar.tokyo.jp"));
- assert!(!is_reg_domain("foo.city.yokohama.jp"));
- assert!(!is_reg_domain("foo.yokohama.jp"));
- assert!(!is_reg_domain("jp"));
- assert!(!is_reg_domain("tokyo.jp"));
- assert!(is_reg_domain("city.yokohama.jp"));
- assert!(is_reg_domain("foo.bar.yokohama.jp"));
- assert!(is_reg_domain("foo.com"));
- assert!(is_reg_domain("foo.tokyo.jp"));
- assert!(is_reg_domain("yokohama.jp"));
-}
-
-#[test]
-fn test_pub_suffix() {
- assert_eq!(pub_suffix("city.yokohama.jp"), "yokohama.jp");
- assert_eq!(pub_suffix("com"), "com");
- assert_eq!(pub_suffix("foo.bar.baz.yokohama.jp"), "baz.yokohama.jp");
- assert_eq!(pub_suffix("foo.bar.com"), "com");
- assert_eq!(pub_suffix("foo.bar.tokyo.jp"), "tokyo.jp");
- assert_eq!(pub_suffix("foo.bar.yokohama.jp"), "bar.yokohama.jp");
- assert_eq!(pub_suffix("foo.city.yokohama.jp"), "yokohama.jp");
- assert_eq!(pub_suffix("foo.com"), "com");
- assert_eq!(pub_suffix("foo.tokyo.jp"), "tokyo.jp");
- assert_eq!(pub_suffix("foo.yokohama.jp"), "foo.yokohama.jp");
- assert_eq!(pub_suffix("jp"), "jp");
- assert_eq!(pub_suffix("tokyo.jp"), "tokyo.jp");
- assert_eq!(pub_suffix("yokohama.jp"), "jp");
-}
-
-#[test]
-fn test_reg_suffix() {
- assert_eq!(reg_suffix("city.yokohama.jp"), "city.yokohama.jp");
- assert_eq!(reg_suffix("com"), "com");
- assert_eq!(reg_suffix("foo.bar.baz.yokohama.jp"), "bar.baz.yokohama.jp");
- assert_eq!(reg_suffix("foo.bar.com"), "bar.com");
- assert_eq!(reg_suffix("foo.bar.tokyo.jp"), "bar.tokyo.jp");
- assert_eq!(reg_suffix("foo.bar.yokohama.jp"), "foo.bar.yokohama.jp");
- assert_eq!(reg_suffix("foo.city.yokohama.jp"), "city.yokohama.jp");
- assert_eq!(reg_suffix("foo.com"), "foo.com");
- assert_eq!(reg_suffix("foo.tokyo.jp"), "foo.tokyo.jp");
- assert_eq!(reg_suffix("foo.yokohama.jp"), "foo.yokohama.jp");
- assert_eq!(reg_suffix("jp"), "jp");
- assert_eq!(reg_suffix("tokyo.jp"), "tokyo.jp");
- assert_eq!(reg_suffix("yokohama.jp"), "yokohama.jp");
-}
-
-#[test]
-fn test_weirdness() {
- // These are weird results, but AFAICT they are spec-compliant.
- assert_ne!(
- pub_suffix("city.yokohama.jp"),
- pub_suffix(pub_suffix("city.yokohama.jp"))
- );
- assert!(!is_pub_domain(pub_suffix("city.yokohama.jp")));
-}
diff --git a/components/net_traits/tests/whitespace.rs b/components/net_traits/tests/whitespace.rs
deleted file mode 100644
index d1e6b7a2ac8..00000000000
--- a/components/net_traits/tests/whitespace.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-#[test]
-fn test_trim_http_whitespace() {
- fn test_trim(in_: &[u8], out: &[u8]) {
- let b = net_traits::trim_http_whitespace(in_);
- assert_eq!(b, out);
- }
-
- test_trim(b"", b"");
-
- test_trim(b" ", b"");
- test_trim(b"a", b"a");
- test_trim(b" a", b"a");
- test_trim(b"a ", b"a");
- test_trim(b" a ", b"a");
-
- test_trim(b"\t", b"");
- test_trim(b"a", b"a");
- test_trim(b"\ta", b"a");
- test_trim(b"a\t", b"a");
- test_trim(b"\ta\t", b"a");
-}