aboutsummaryrefslogtreecommitdiffstats
path: root/components/shared
diff options
context:
space:
mode:
Diffstat (limited to 'components/shared')
-rw-r--r--components/shared/net/Cargo.toml1
-rw-r--r--components/shared/net/fetch/headers.rs93
-rw-r--r--components/shared/net/pub_domains.rs8
-rw-r--r--components/shared/net/response.rs10
4 files changed, 102 insertions, 10 deletions
diff --git a/components/shared/net/Cargo.toml b/components/shared/net/Cargo.toml
index 79ea936a688..0dfad486455 100644
--- a/components/shared/net/Cargo.toml
+++ b/components/shared/net/Cargo.toml
@@ -19,6 +19,7 @@ compositing_traits = { workspace = true }
content-security-policy = { workspace = true }
cookie = { workspace = true }
crossbeam-channel = { workspace = true }
+data-url = { workspace = true }
embedder_traits = { workspace = true }
headers = { workspace = true }
http = { workspace = true }
diff --git a/components/shared/net/fetch/headers.rs b/components/shared/net/fetch/headers.rs
index 11bb68d5d0a..5ffd537adf8 100644
--- a/components/shared/net/fetch/headers.rs
+++ b/components/shared/net/fetch/headers.rs
@@ -3,8 +3,9 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::iter::Peekable;
-use std::str::Chars;
+use std::str::{Chars, FromStr};
+use data_url::mime::Mime as DataUrlMime;
use headers::HeaderMap;
/// <https://fetch.spec.whatwg.org/#http-tab-or-space>
@@ -184,3 +185,93 @@ fn collect_http_quoted_string(position: &mut Peekable<Chars>, extract_value: boo
// Step 6, 7
value
}
+
+/// <https://fetch.spec.whatwg.org/#concept-header-extract-mime-type>
+/// This function uses data_url::Mime to parse the MIME Type because
+/// mime::Mime does not provide a parser following the Fetch spec
+/// see <https://github.com/hyperium/mime/issues/106>
+pub fn extract_mime_type_as_dataurl_mime(headers: &HeaderMap) -> Option<DataUrlMime> {
+ // > 1: Let charset be null.
+ let mut charset = None;
+ // > 2: Let essence be null.
+ let mut essence = String::new();
+ // > 3: Let mimeType be null.
+ let mut mime_type = None;
+
+ // > 4: Let values be the result of getting, decoding, and splitting `Content-Type`
+ // from headers.
+ // > 5: If values is null, then return failure.
+ let headers_values = get_decode_and_split_header_name("content-type", headers)?;
+
+ // > 6: For each value of values:
+ for header_value in headers_values.iter() {
+ // > 6.1: Let temporaryMimeType be the result of parsing value.
+ match DataUrlMime::from_str(header_value) {
+ // > 6.2: If temporaryMimeType is failure or its essence is "*/*", then continue.
+ Err(_) => continue,
+ Ok(temp_mime) => {
+ let temp_essence = format!("{}/{}", temp_mime.type_, temp_mime.subtype);
+
+ // > 6.2: If temporaryMimeType is failure or its essence is "*/*", then
+ // continue.
+ if temp_essence == "*/*" {
+ continue;
+ }
+
+ // > 6.3: Set mimeType to temporaryMimeType.
+ mime_type = Some(DataUrlMime {
+ type_: temp_mime.type_.to_string(),
+ subtype: temp_mime.subtype.to_string(),
+ parameters: temp_mime.parameters.clone(),
+ });
+
+ // > 6.4: If mimeType’s essence is not essence, then:
+ let temp_charset = &temp_mime.get_parameter("charset");
+ if temp_essence != essence {
+ // > 6.4.1: Set charset to null.
+ // > 6.4.2: If mimeType’s parameters["charset"] exists, then set
+ // charset to mimeType’s parameters["charset"].
+ charset = temp_charset.map(|c| c.to_string());
+ // > 6.4.3: Set essence to mimeType’s essence.
+ essence = temp_essence.to_owned();
+ } else {
+ // > 6.5: Otherwise, if mimeType’s parameters["charset"] does not exist,
+ // and charset is non-null, set mimeType’s parameters["charset"] to charset.
+ if temp_charset.is_none() && charset.is_some() {
+ let DataUrlMime {
+ type_: t,
+ subtype: st,
+ parameters: p,
+ } = mime_type.unwrap();
+ let mut params = p;
+ params.push(("charset".to_string(), charset.clone().unwrap()));
+ mime_type = Some(DataUrlMime {
+ type_: t.to_string(),
+ subtype: st.to_string(),
+ parameters: params,
+ })
+ }
+ }
+ },
+ }
+ }
+
+ // > 7: If mimeType is null, then return failure.
+ // > 8: Return mimeType.
+ mime_type
+}
+
+pub fn extract_mime_type(headers: &HeaderMap) -> Option<Vec<u8>> {
+ extract_mime_type_as_dataurl_mime(headers).map(|m| format!("{}", m).into_bytes())
+}
+
+pub fn extract_mime_type_as_mime(headers: &HeaderMap) -> Option<mime::Mime> {
+ extract_mime_type_as_dataurl_mime(headers).and_then(|mime: DataUrlMime| {
+ // Try to transform a data-url::mime::Mime into a mime::Mime
+ let mut mime_as_str = format!("{}/{}", mime.type_, mime.subtype);
+ for p in mime.parameters {
+ mime_as_str.push_str(format!("; {}={}", p.0, p.1).as_str());
+ }
+ mime_as_str.parse().ok()
+ })
+}
diff --git a/components/shared/net/pub_domains.rs b/components/shared/net/pub_domains.rs
index cbbb2b465b2..6e6f883cd2f 100644
--- a/components/shared/net/pub_domains.rs
+++ b/components/shared/net/pub_domains.rs
@@ -19,9 +19,11 @@ use std::iter::FromIterator;
use std::sync::LazyLock;
use embedder_traits::resources::{self, Resource};
+use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
+use malloc_size_of_derive::MallocSizeOf;
use servo_url::{Host, ImmutableOrigin, ServoUrl};
-#[derive(Clone, Debug, Default)]
+#[derive(Clone, Debug, Default, MallocSizeOf)]
pub struct PubDomainRules {
rules: HashSet<String>,
wildcards: HashSet<String>,
@@ -30,6 +32,10 @@ pub struct PubDomainRules {
static PUB_DOMAINS: LazyLock<PubDomainRules> = LazyLock::new(load_pub_domains);
+pub fn public_suffix_list_size_of(ops: &mut MallocSizeOfOps) -> usize {
+ PUB_DOMAINS.size_of(ops)
+}
+
impl<'a> FromIterator<&'a str> for PubDomainRules {
fn from_iter<T>(iter: T) -> Self
where
diff --git a/components/shared/net/response.rs b/components/shared/net/response.rs
index f91993ddccb..9a01fbbf965 100644
--- a/components/shared/net/response.rs
+++ b/components/shared/net/response.rs
@@ -7,7 +7,6 @@
use std::sync::Mutex;
use std::sync::atomic::AtomicBool;
-use headers::{ContentType, HeaderMapExt};
use http::HeaderMap;
use hyper_serde::Serde;
use malloc_size_of_derive::MallocSizeOf;
@@ -15,6 +14,7 @@ use serde::{Deserialize, Serialize};
use servo_arc::Arc;
use servo_url::ServoUrl;
+use crate::fetch::headers::extract_mime_type_as_mime;
use crate::http_status::HttpStatus;
use crate::{
FetchMetadata, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy, ResourceFetchTiming,
@@ -300,13 +300,7 @@ impl 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.set_content_type(extract_mime_type_as_mime(&response.headers).as_ref());
metadata.location_url.clone_from(&response.location_url);
metadata.headers = Some(Serde(response.headers.clone()));
metadata.status.clone_from(&response.status);