From c1931ee2cbeb16710388ee7c88e0c209ef1df801 Mon Sep 17 00:00:00 2001 From: webbeef Date: Fri, 27 Sep 2024 17:19:30 -0700 Subject: [PATCH] Simplify the data: protocol handler (#33500) Signed-off-by: webbeef --- components/net/protocols/data.rs | 94 ++---- .../fetch/api/basic/scheme-data.any.js.ini | 34 --- .../fetch/data-urls/processing.any.js.ini | 287 ------------------ tests/wpt/meta/fetch/range/data.any.js.ini | 14 - .../resource-timing/opaque-origin.html.ini | 3 +- .../importscripts_mime_local.any.js.ini | 3 - tests/wpt/meta/xhr/data-uri.htm.ini | 3 - 7 files changed, 29 insertions(+), 409 deletions(-) delete mode 100644 tests/wpt/meta/fetch/range/data.any.js.ini delete mode 100644 tests/wpt/meta/xhr/data-uri.htm.ini diff --git a/components/net/protocols/data.rs b/components/net/protocols/data.rs index 3835525d100..0f548683373 100644 --- a/components/net/protocols/data.rs +++ b/components/net/protocols/data.rs @@ -5,16 +5,12 @@ use std::future::Future; use std::pin::Pin; -use data_url::forgiving_base64; -use headers::{ContentType, HeaderMapExt}; +use data_url::DataUrl; +use headers::HeaderValue; use http::StatusCode; -use mime::Mime; use net_traits::request::Request; use net_traits::response::{Response, ResponseBody}; use net_traits::{NetworkError, ResourceFetchTiming}; -use percent_encoding::percent_decode; -use servo_url::ServoUrl; -use url::Position; use crate::fetch::methods::{DoneChannel, FetchContext}; use crate::protocols::ProtocolHandler; @@ -22,54 +18,6 @@ use crate::protocols::ProtocolHandler; #[derive(Default)] pub struct DataProtocolHander {} -enum DecodeError { - InvalidDataUri, - NonBase64DataUri, -} - -type DecodeData = (Mime, Vec); - -fn decode(url: &ServoUrl) -> Result { - // data_url could do all of this work for us, - // except that it currently (Nov 2019) parses mime types into a - // different Mime class than other code expects - - assert_eq!(url.scheme(), "data"); - // Split out content type and data. - let parts: Vec<&str> = url[Position::BeforePath..Position::AfterQuery] - .splitn(2, ',') - .collect(); - if parts.len() != 2 { - return Err(DecodeError::InvalidDataUri); - } - - // ";base64" must come at the end of the content type, per RFC 2397. - // rust-http will fail to parse it because there's no =value part. - let mut ct_str = parts[0]; - let is_base64 = ct_str.ends_with(";base64"); - if is_base64 { - ct_str = &ct_str[..ct_str.len() - ";base64".len()]; - } - let ct_str = if ct_str.starts_with(";charset=") { - format!("text/plain{}", ct_str) - } else { - ct_str.to_owned() - }; - - let content_type = ct_str - .parse() - .unwrap_or_else(|_| "text/plain; charset=US-ASCII".parse().unwrap()); - - let mut bytes = percent_decode(parts[1].as_bytes()).collect::>(); - if is_base64 { - match forgiving_base64::decode_to_vec(&bytes) { - Err(..) => return Err(DecodeError::NonBase64DataUri), - Ok(data) => bytes = data, - } - } - Ok((content_type, bytes)) -} - impl ProtocolHandler for DataProtocolHander { fn load( &self, @@ -78,20 +26,32 @@ impl ProtocolHandler for DataProtocolHander { _context: &FetchContext, ) -> Pin + Send>> { let url = request.current_url(); - let response = match decode(&url) { - Ok((mime, bytes)) => { - let mut response = - Response::new(url, ResourceFetchTiming::new(request.timing_type())); - *response.body.lock().unwrap() = ResponseBody::Done(bytes); - response.headers.typed_insert(ContentType::from(mime)); - response.status = Some((StatusCode::OK, "OK".to_string())); - response.raw_status = Some((StatusCode::OK.as_u16(), b"OK".to_vec())); - response + + assert_eq!(url.scheme(), "data"); + + let response = match DataUrl::process(url.clone().as_str()) { + Ok(data_url) => match data_url.decode_to_vec() { + Ok((bytes, _fragment_id)) => { + let mut response = + Response::new(url, ResourceFetchTiming::new(request.timing_type())); + *response.body.lock().unwrap() = ResponseBody::Done(bytes); + let mime = data_url.mime_type(); + response.headers.insert( + http::header::CONTENT_TYPE, + HeaderValue::from_str(&mime.to_string()).unwrap(), + ); + response.status = Some((StatusCode::OK, "OK".to_string())); + response.raw_status = Some((StatusCode::OK.as_u16(), b"OK".to_vec())); + Some(response) + }, + Err(_) => None, }, - Err(_) => { - Response::network_error(NetworkError::Internal("Decoding data URL failed".into())) - }, - }; + Err(_) => None, + } + .unwrap_or_else(|| { + Response::network_error(NetworkError::Internal("Decoding data URL failed".into())) + }); + Box::pin(std::future::ready(response)) } } diff --git a/tests/wpt/meta/fetch/api/basic/scheme-data.any.js.ini b/tests/wpt/meta/fetch/api/basic/scheme-data.any.js.ini index 1ccad87dc7d..9a2ae70f1b7 100644 --- a/tests/wpt/meta/fetch/api/basic/scheme-data.any.js.ini +++ b/tests/wpt/meta/fetch/api/basic/scheme-data.any.js.ini @@ -1,37 +1,3 @@ -[scheme-data.any.html] - [Fetching data:,response%27s%20body is OK (cors)] - expected: FAIL - - [Fetching [HEAD\] data:,response%27s%20body is OK] - expected: FAIL - - [Fetching [POST\] data:,response%27s%20body is OK] - expected: FAIL - - [Fetching data:,response%27s%20body is OK (same-origin)] - expected: FAIL - - [Fetching data:,response%27s%20body is OK] - expected: FAIL - - -[scheme-data.any.worker.html] - [Fetching data:,response%27s%20body is OK (cors)] - expected: FAIL - - [Fetching [HEAD\] data:,response%27s%20body is OK] - expected: FAIL - - [Fetching [POST\] data:,response%27s%20body is OK] - expected: FAIL - - [Fetching data:,response%27s%20body is OK (same-origin)] - expected: FAIL - - [Fetching data:,response%27s%20body is OK] - expected: FAIL - - [scheme-data.any.sharedworker.html] expected: ERROR diff --git a/tests/wpt/meta/fetch/data-urls/processing.any.js.ini b/tests/wpt/meta/fetch/data-urls/processing.any.js.ini index d1d8ddd7f64..0765d0eaed9 100644 --- a/tests/wpt/meta/fetch/data-urls/processing.any.js.ini +++ b/tests/wpt/meta/fetch/data-urls/processing.any.js.ini @@ -5,292 +5,5 @@ expected: ERROR [processing.any.html] - ["data:%00,%FF"] - expected: FAIL - - ["data:,"] - expected: FAIL - - ["data:text / html,X"] - expected: FAIL - - ["data:†,X"] - expected: FAIL - - ["data: ,%FF"] - expected: FAIL - - ["data:text/plain;Charset=UTF-8,%C2%B1"] - expected: FAIL - - ["data:;x=x;charset=x,X"] - expected: FAIL - - ["data:;base 64,WA"] - expected: FAIL - - ["data:text/html ,X"] - expected: FAIL - - ["data:text/plain;a=\\",\\",X"] - expected: FAIL - - ["data:;charset=,X"] - expected: FAIL - - ["data:;CHARSET=\\"X\\",X"] - expected: FAIL - - ["data:;%62ase64,WA"] - expected: FAIL - - ["data:x/x;base64;charset=x;base64,WA"] - expected: FAIL - - ["data://test/,X"] - expected: FAIL - - ["data:X,X"] - expected: FAIL - - ["data:%3Bbase64,WA"] - expected: FAIL - - ["data:\\f,%FF"] - expected: FAIL - - ["data:x/x;base64;base64x,WA"] - expected: FAIL - - ["data:;charset= x,X"] - expected: FAIL - - ["data:text/plain ,X"] - expected: FAIL - - ["data:;charset,X"] - expected: FAIL - - ["data:;base64,W%0CA"] - expected: FAIL - - ["data:;x=x,X"] - expected: FAIL - - ["data:,%FF"] - expected: FAIL - - ["data:;base64 ,WA"] - expected: FAIL - - ["data:;base64,W%20A"] - expected: FAIL - - ["data:\\0,%FF"] - expected: FAIL - - ["data:x;base64;x,WA"] - expected: FAIL - - ["data:;BASe64,WA"] - expected: FAIL - - ["data:; charset=x,X"] - expected: FAIL - - ["data:x;base64x,WA"] - expected: FAIL - - ["data:; base64,WA"] - expected: FAIL - - ["data:,X#X"] - expected: FAIL - - ["data:x/x;base64;charset=x,WA"] - expected: FAIL - - ["data: ;charset=x ; base64,WA"] - expected: FAIL - - ["data:;base64;,WA"] - expected: FAIL - - ["data:;base64;base64,WA"] - expected: FAIL - - ["data:; base64,WA"] - expected: FAIL - - ["data:;charset =x,X"] - expected: FAIL - - ["data:x/x;base64;base64,WA"] - expected: FAIL - - ["data:%20,%FF"] - expected: FAIL - - ["data:%1F,%FF"] - expected: FAIL - - ["data:,X"] - expected: FAIL - - ["data:x;base64=x,WA"] - expected: FAIL - - ["data:;base64 ,WA"] - expected: FAIL - - ["data:;charset=\\"x\\",X"] - expected: FAIL - - ["data:text/plain;charset=UTF-8,áñçə💩"] - expected: FAIL - [processing.any.worker.html] - ["data:%00,%FF"] - expected: FAIL - - ["data:,"] - expected: FAIL - - ["data:text / html,X"] - expected: FAIL - - ["data:†,X"] - expected: FAIL - - ["data: ,%FF"] - expected: FAIL - - ["data:text/plain;Charset=UTF-8,%C2%B1"] - expected: FAIL - - ["data:;x=x;charset=x,X"] - expected: FAIL - - ["data:;base 64,WA"] - expected: FAIL - - ["data:text/html ,X"] - expected: FAIL - - ["data:text/plain;a=\\",\\",X"] - expected: FAIL - - ["data:;charset=,X"] - expected: FAIL - - ["data:;CHARSET=\\"X\\",X"] - expected: FAIL - - ["data:;%62ase64,WA"] - expected: FAIL - - ["data:x/x;base64;charset=x;base64,WA"] - expected: FAIL - - ["data://test/,X"] - expected: FAIL - - ["data:X,X"] - expected: FAIL - - ["data:%3Bbase64,WA"] - expected: FAIL - - ["data:\\f,%FF"] - expected: FAIL - - ["data:x/x;base64;base64x,WA"] - expected: FAIL - - ["data:;charset= x,X"] - expected: FAIL - - ["data:text/plain ,X"] - expected: FAIL - - ["data:;charset,X"] - expected: FAIL - - ["data:;base64,W%0CA"] - expected: FAIL - - ["data:;x=x,X"] - expected: FAIL - - ["data:,%FF"] - expected: FAIL - - ["data:;base64 ,WA"] - expected: FAIL - - ["data:;base64,W%20A"] - expected: FAIL - - ["data:\\0,%FF"] - expected: FAIL - - ["data:x;base64;x,WA"] - expected: FAIL - - ["data:;BASe64,WA"] - expected: FAIL - - ["data:; charset=x,X"] - expected: FAIL - - ["data:x;base64x,WA"] - expected: FAIL - - ["data:; base64,WA"] - expected: FAIL - - ["data:,X#X"] - expected: FAIL - - ["data:x/x;base64;charset=x,WA"] - expected: FAIL - - ["data: ;charset=x ; base64,WA"] - expected: FAIL - - ["data:;base64;,WA"] - expected: FAIL - - ["data:;base64;base64,WA"] - expected: FAIL - - ["data:; base64,WA"] - expected: FAIL - - ["data:;charset =x,X"] - expected: FAIL - - ["data:x/x;base64;base64,WA"] - expected: FAIL - - ["data:%20,%FF"] - expected: FAIL - - ["data:%1F,%FF"] - expected: FAIL - - ["data:,X"] - expected: FAIL - - ["data:x;base64=x,WA"] - expected: FAIL - - ["data:;base64 ,WA"] - expected: FAIL - - ["data:;charset=\\"x\\",X"] - expected: FAIL - - ["data:text/plain;charset=UTF-8,áñçə💩"] - expected: FAIL diff --git a/tests/wpt/meta/fetch/range/data.any.js.ini b/tests/wpt/meta/fetch/range/data.any.js.ini deleted file mode 100644 index eb6c50aef47..00000000000 --- a/tests/wpt/meta/fetch/range/data.any.js.ini +++ /dev/null @@ -1,14 +0,0 @@ -[data.any.html] - [data: URL and Range header] - expected: FAIL - - [data: URL and Range header with multiple ranges] - expected: FAIL - - -[data.any.worker.html] - [data: URL and Range header] - expected: FAIL - - [data: URL and Range header with multiple ranges] - expected: FAIL diff --git a/tests/wpt/meta/resource-timing/opaque-origin.html.ini b/tests/wpt/meta/resource-timing/opaque-origin.html.ini index 39bef618ce0..55e7b264830 100644 --- a/tests/wpt/meta/resource-timing/opaque-origin.html.ini +++ b/tests/wpt/meta/resource-timing/opaque-origin.html.ini @@ -1,2 +1,3 @@ [opaque-origin.html] - expected: TIMEOUT + [An opaque origin should be authorized to see resource timings when theTAO header is the string 'null'] + expected: FAIL diff --git a/tests/wpt/meta/workers/importscripts_mime_local.any.js.ini b/tests/wpt/meta/workers/importscripts_mime_local.any.js.ini index ad86615abd2..9f5d3813049 100644 --- a/tests/wpt/meta/workers/importscripts_mime_local.any.js.ini +++ b/tests/wpt/meta/workers/importscripts_mime_local.any.js.ini @@ -26,9 +26,6 @@ [importScripts() requires scripty MIME types for data: URLs: zzz/zzz is blocked.] expected: FAIL - [importScripts() requires scripty MIME types for data: URLs: text/csv;bla;bla is blocked.] - expected: FAIL - [importScripts() requires scripty MIME types for data: URLs: Text/html is blocked.] expected: FAIL diff --git a/tests/wpt/meta/xhr/data-uri.htm.ini b/tests/wpt/meta/xhr/data-uri.htm.ini deleted file mode 100644 index 0cd8c771e22..00000000000 --- a/tests/wpt/meta/xhr/data-uri.htm.ini +++ /dev/null @@ -1,3 +0,0 @@ -[data-uri.htm] - [XHR method GET with MIME type text/html;charset=UTF-8] - expected: FAIL