aboutsummaryrefslogtreecommitdiffstats
path: root/components/shared
diff options
context:
space:
mode:
Diffstat (limited to 'components/shared')
-rw-r--r--components/shared/canvas/canvas.rs8
-rw-r--r--components/shared/canvas/lib.rs2
-rw-r--r--components/shared/compositing/lib.rs5
-rw-r--r--components/shared/compositing/viewport_description.rs175
-rw-r--r--components/shared/constellation/lib.rs3
-rw-r--r--components/shared/embedder/input_events.rs6
-rw-r--r--components/shared/embedder/webdriver.rs4
-rw-r--r--components/shared/net/lib.rs1
-rw-r--r--components/shared/net/mime_classifier.rs1229
-rw-r--r--components/shared/net/tests/mime_classifier.rs628
-rwxr-xr-xcomponents/shared/net/tests/parsable_mime/application/font-woff/test.wof1
-rw-r--r--components/shared/net/tests/parsable_mime/application/ogg/small.oggbin0 -> 105243 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/application/pdf/test.pdf157
-rwxr-xr-xcomponents/shared/net/tests/parsable_mime/application/postscript/test.ps1
-rwxr-xr-xcomponents/shared/net/tests/parsable_mime/application/vnd.ms-fontobject/vnd.ms-fontobjectbin0 -> 36 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/application/x-gzip/test.gzbin0 -> 1239 bytes
-rwxr-xr-xcomponents/shared/net/tests/parsable_mime/application/x-rar-compressed/test.rarbin0 -> 7 bytes
-rwxr-xr-xcomponents/shared/net/tests/parsable_mime/application/zip/test.zip1
-rw-r--r--components/shared/net/tests/parsable_mime/audio/aiff/test.aifbin0 -> 47122 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/audio/basic/test.aubin0 -> 47086 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/audio/midi/test.midbin0 -> 8444 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/audio/mpeg/test.mp3bin0 -> 33621 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/audio/wave/test.wavbin0 -> 47196 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/image/bmp/test.bmpbin0 -> 11914 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/image/gif/test87abin0 -> 1303 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/image/gif/test89a.gifbin0 -> 1303 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/image/jpeg/test.jpgbin0 -> 3744 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/image/png/test.pngbin0 -> 4293 bytes
-rwxr-xr-xcomponents/shared/net/tests/parsable_mime/image/webp/test.webpbin0 -> 14 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/image/x-icon/test.icobin0 -> 12206 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/image/x-icon/test_cursor.icobin0 -> 12206 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_a_20.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_a_20_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_a_3e.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_a_3e_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_b_20.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_b_20_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_b_3e.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_b_3e_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_body_20.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_body_20_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_body_3e.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_body_3e_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_br_20.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_br_20_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_br_3e.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_br_3e_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_comment_20.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_comment_20_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_comment_3e.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_comment_3e_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_div_20.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_div_20_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_div_3e.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_div_3e_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_doctype_20.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_doctype_20_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_doctype_3e.html4
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_doctype_3e_u.html4
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_font_20.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_font_20_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_font_3e.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_font_3e_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_h1_20.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_h1_20_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_h1_3e.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_h1_3e_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_head_20.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_head_20_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_head_3e.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_head_3e_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_iframe_20.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_iframe_20_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_iframe_3e.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_iframe_3e_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_p_20.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_p_20_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_p_3e.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_p_3e_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_page_20.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_page_20_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_page_3e.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_page_3e_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_script_20.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_script_20_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_script_3e.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_script_3e_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_style_20.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_style_20_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_style_3e.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_style_3e_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_table_20.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_table_20_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_table_3e.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_table_3e_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_title_20.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_title_20_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_title_3e.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/html/text_html_title_3e_u.html3
-rw-r--r--components/shared/net/tests/parsable_mime/text/plain/utf16bebom.txtbin0 -> 42 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/text/plain/utf16lebom.txtbin0 -> 40 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/text/plain/utf8bom.txt1
-rwxr-xr-xcomponents/shared/net/tests/parsable_mime/text/xml/feed.atom1
-rw-r--r--components/shared/net/tests/parsable_mime/text/xml/feed.rss151
-rw-r--r--components/shared/net/tests/parsable_mime/text/xml/rdf_rss.xml7
-rw-r--r--components/shared/net/tests/parsable_mime/text/xml/rdf_rss_ko_1.xml7
-rw-r--r--components/shared/net/tests/parsable_mime/text/xml/rdf_rss_ko_2.xml3
-rw-r--r--components/shared/net/tests/parsable_mime/text/xml/rdf_rss_ko_3.xml6
-rw-r--r--components/shared/net/tests/parsable_mime/text/xml/rdf_rss_ko_4.xml7
-rw-r--r--components/shared/net/tests/parsable_mime/text/xml/test.xml6
-rw-r--r--components/shared/net/tests/parsable_mime/unknown/binary_filebin0 -> 1024 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/unknown/open_type1
-rw-r--r--components/shared/net/tests/parsable_mime/unknown/true_type.ttfbin0 -> 333616 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/unknown/true_type_collection.ttc1
-rw-r--r--components/shared/net/tests/parsable_mime/video/avi/test.avibin0 -> 675840 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/video/mp4/test.mp4bin0 -> 383631 bytes
-rw-r--r--components/shared/net/tests/parsable_mime/video/webm/test.webmbin0 -> 229455 bytes
-rw-r--r--components/shared/snapshot/lib.rs12
118 files changed, 2615 insertions, 15 deletions
diff --git a/components/shared/canvas/canvas.rs b/components/shared/canvas/canvas.rs
index 850f5f9bd9a..283be0d458e 100644
--- a/components/shared/canvas/canvas.rs
+++ b/components/shared/canvas/canvas.rs
@@ -89,8 +89,8 @@ pub enum Canvas2dMsg {
Arc(Point2D<f32>, f32, f32, f32, bool),
ArcTo(Point2D<f32>, Point2D<f32>, f32),
DrawImage(IpcSnapshot, Rect<f64>, Rect<f64>, bool),
- DrawEmptyImage(Size2D<f64>, Rect<f64>, Rect<f64>),
- DrawImageInOther(CanvasId, Size2D<f64>, Rect<f64>, Rect<f64>, bool),
+ DrawEmptyImage(Size2D<u32>, Rect<f64>, Rect<f64>),
+ DrawImageInOther(CanvasId, Size2D<u32>, Rect<f64>, Rect<f64>, bool),
BeginPath,
BezierCurveTo(Point2D<f32>, Point2D<f32>, Point2D<f32>),
ClearRect(Rect<f32>),
@@ -102,14 +102,14 @@ pub enum Canvas2dMsg {
FillPath(FillOrStrokeStyle, Vec<PathSegment>),
FillText(String, f64, f64, Option<f64>, FillOrStrokeStyle, bool),
FillRect(Rect<f32>, FillOrStrokeStyle),
- GetImageData(Rect<u64>, Size2D<u64>, IpcSender<IpcSnapshot>),
+ GetImageData(Rect<u32>, Size2D<u32>, IpcSender<IpcSnapshot>),
GetTransform(IpcSender<Transform2D<f32>>),
IsPointInCurrentPath(f64, f64, FillRule, IpcSender<bool>),
IsPointInPath(Vec<PathSegment>, f64, f64, FillRule, IpcSender<bool>),
LineTo(Point2D<f32>),
MoveTo(Point2D<f32>),
MeasureText(String, IpcSender<TextMetrics>),
- PutImageData(Rect<u64>, IpcBytesReceiver),
+ PutImageData(Rect<u32>, IpcBytesReceiver),
QuadraticCurveTo(Point2D<f32>, Point2D<f32>),
Rect(Rect<f32>),
RestoreContext,
diff --git a/components/shared/canvas/lib.rs b/components/shared/canvas/lib.rs
index 826db54b0f6..df6b0854b9e 100644
--- a/components/shared/canvas/lib.rs
+++ b/components/shared/canvas/lib.rs
@@ -21,5 +21,5 @@ pub enum ConstellationCanvasMsg {
sender: Sender<(CanvasId, ImageKey)>,
size: Size2D<u64>,
},
- Exit,
+ Exit(Sender<()>),
}
diff --git a/components/shared/compositing/lib.rs b/components/shared/compositing/lib.rs
index 67ff0046885..8dadf93d628 100644
--- a/components/shared/compositing/lib.rs
+++ b/components/shared/compositing/lib.rs
@@ -23,6 +23,7 @@ use webrender_api::DocumentId;
pub mod display_list;
pub mod rendering_context;
+pub mod viewport_description;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
@@ -42,6 +43,8 @@ use webrender_api::{
ImageKey, NativeFontHandle, PipelineId as WebRenderPipelineId,
};
+use crate::viewport_description::ViewportDescription;
+
/// Sends messages to the compositor.
#[derive(Clone)]
pub struct CompositorProxy {
@@ -176,6 +179,8 @@ pub enum CompositorMsg {
/// Measure the current memory usage associated with the compositor.
/// The report must be sent on the provided channel once it's complete.
CollectMemoryReport(ReportsChan),
+ /// A top-level frame has parsed a viewport metatag and is sending the new constraints.
+ Viewport(WebViewId, ViewportDescription),
}
impl Debug for CompositorMsg {
diff --git a/components/shared/compositing/viewport_description.rs b/components/shared/compositing/viewport_description.rs
new file mode 100644
index 00000000000..83b29371f84
--- /dev/null
+++ b/components/shared/compositing/viewport_description.rs
@@ -0,0 +1,175 @@
+/* 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/. */
+
+//! This module contains helpers for Viewport
+
+use std::collections::HashMap;
+use std::str::FromStr;
+
+use euclid::default::Scale;
+use serde::{Deserialize, Serialize};
+
+/// Default viewport constraints
+///
+/// <https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag#initial-scale>
+pub const MIN_ZOOM: f32 = 0.1;
+/// <https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag#initial-scale>
+pub const MAX_ZOOM: f32 = 10.0;
+/// <https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag#initial-scale>
+pub const DEFAULT_ZOOM: f32 = 1.0;
+
+/// <https://drafts.csswg.org/css-viewport/#parsing-algorithm>
+const SEPARATORS: [char; 2] = [',', ';']; // Comma (0x2c) and Semicolon (0x3b)
+
+/// A set of viewport descriptors:
+///
+/// <https://www.w3.org/TR/css-viewport-1/#viewport-meta>
+#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
+pub struct ViewportDescription {
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag#width
+ // the (minimum width) size of the viewport
+ // TODO: width Needs to be implemented
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag#width
+ // the (minimum height) size of the viewport
+ // TODO: height Needs to be implemented
+ /// <https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag#initial-scale>
+ /// the zoom level when the page is first loaded
+ pub initial_scale: Scale<f32>,
+
+ /// <https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag#minimum_scale>
+ /// how much zoom out is allowed on the page.
+ pub minimum_scale: Scale<f32>,
+
+ /// <https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag#maximum_scale>
+ /// how much zoom in is allowed on the page
+ pub maximum_scale: Scale<f32>,
+
+ /// <https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag#user_scalable>
+ /// whether zoom in and zoom out actions are allowed on the page
+ pub user_scalable: UserScalable,
+}
+
+/// The errors that the viewport parsing can generate.
+#[derive(Debug)]
+pub enum ViewportDescriptionParseError {
+ /// When viewport attribute string is empty
+ Empty,
+}
+
+/// A set of User Zoom values:
+#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
+pub enum UserScalable {
+ /// Zoom is not allowed
+ No = 0,
+ /// Zoom is allowed
+ Yes = 1,
+}
+
+/// Parses a viewport user scalable value.
+impl TryFrom<&str> for UserScalable {
+ type Error = &'static str;
+ fn try_from(value: &str) -> Result<Self, Self::Error> {
+ match value.to_lowercase().as_str() {
+ "yes" => Ok(UserScalable::Yes),
+ "no" => Ok(UserScalable::No),
+ _ => match value.parse::<f32>() {
+ Ok(1.0) => Ok(UserScalable::Yes),
+ Ok(0.0) => Ok(UserScalable::No),
+ _ => Err("can't convert character to UserScalable"),
+ },
+ }
+ }
+}
+
+impl Default for ViewportDescription {
+ fn default() -> Self {
+ ViewportDescription {
+ initial_scale: Scale::new(DEFAULT_ZOOM),
+ minimum_scale: Scale::new(MIN_ZOOM),
+ maximum_scale: Scale::new(MAX_ZOOM),
+ user_scalable: UserScalable::Yes,
+ }
+ }
+}
+
+impl ViewportDescription {
+ /// Iterates over the key-value pairs generated from meta tag and returns a ViewportDescription
+ fn process_viewport_key_value_pairs(pairs: HashMap<String, String>) -> ViewportDescription {
+ let mut description = ViewportDescription::default();
+ for (key, value) in &pairs {
+ match key.as_str() {
+ "initial-scale" => {
+ if let Some(zoom) = Self::parse_viewport_value_as_zoom(value) {
+ description.initial_scale = zoom;
+ }
+ },
+ "minimum-scale" => {
+ if let Some(zoom) = Self::parse_viewport_value_as_zoom(value) {
+ description.minimum_scale = zoom;
+ }
+ },
+ "maximum-scale" => {
+ if let Some(zoom) = Self::parse_viewport_value_as_zoom(value) {
+ description.maximum_scale = zoom;
+ }
+ },
+ "user-scalable" => {
+ if let Ok(user_zoom_allowed) = value.as_str().try_into() {
+ description.user_scalable = user_zoom_allowed;
+ }
+ },
+ _ => (),
+ }
+ }
+ description
+ }
+
+ /// Parses a viewport zoom value.
+ fn parse_viewport_value_as_zoom(value: &str) -> Option<Scale<f32>> {
+ value
+ .to_lowercase()
+ .as_str()
+ .parse::<f32>()
+ .ok()
+ .filter(|&n| (0.0..=10.0).contains(&n))
+ .map(Scale::new)
+ }
+
+ /// Constrains a zoom value within the allowed scale range
+ pub fn clamp_zoom(&self, zoom: f32) -> f32 {
+ zoom.clamp(self.minimum_scale.get(), self.maximum_scale.get())
+ }
+}
+
+/// <https://drafts.csswg.org/css-viewport/#parsing-algorithm>
+///
+/// This implementation differs from the specified algorithm, but is equivalent because
+/// 1. It uses higher-level string operations to process string instead of character-by-character iteration.
+/// 2. Uses trim() operation to handle whitespace instead of explicitly handling throughout the parsing process.
+impl FromStr for ViewportDescription {
+ type Err = ViewportDescriptionParseError;
+ fn from_str(string: &str) -> Result<Self, Self::Err> {
+ if string.is_empty() {
+ return Err(ViewportDescriptionParseError::Empty);
+ }
+
+ // Parse key-value pairs from the content string
+ // 1. Split the content string using SEPARATORS
+ // 2. Split into key-value pair using "=" and trim whitespaces
+ // 3. Insert into HashMap
+ let parsed_values = string
+ .split(SEPARATORS)
+ .filter_map(|pair| {
+ let mut parts = pair.split('=').map(str::trim);
+ if let (Some(key), Some(value)) = (parts.next(), parts.next()) {
+ Some((key.to_string(), value.to_string()))
+ } else {
+ None
+ }
+ })
+ .collect::<HashMap<String, String>>();
+
+ Ok(Self::process_viewport_key_value_pairs(parsed_values))
+ }
+}
diff --git a/components/shared/constellation/lib.rs b/components/shared/constellation/lib.rs
index fb00d4afdbf..53e924c5ad5 100644
--- a/components/shared/constellation/lib.rs
+++ b/components/shared/constellation/lib.rs
@@ -26,6 +26,7 @@ use euclid::Vector2D;
pub use from_script_message::*;
use ipc_channel::ipc::IpcSender;
use malloc_size_of_derive::MallocSizeOf;
+use profile_traits::mem::MemoryReportResult;
use serde::{Deserialize, Serialize};
use servo_url::{ImmutableOrigin, ServoUrl};
pub use structured_data::*;
@@ -95,6 +96,8 @@ pub enum EmbedderToConstellationMessage {
/// Evaluate a JavaScript string in the context of a `WebView`. When execution is complete or an
/// error is encountered, a correpsonding message will be sent to the embedding layer.
EvaluateJavaScript(WebViewId, JavaScriptEvaluationId, String),
+ /// Create a memory report and return it via the ipc sender
+ CreateMemoryReport(IpcSender<MemoryReportResult>),
}
/// A description of a paint metric that is sent from the Servo renderer to the
diff --git a/components/shared/embedder/input_events.rs b/components/shared/embedder/input_events.rs
index 869c4eee004..ff48bd7b7d8 100644
--- a/components/shared/embedder/input_events.rs
+++ b/components/shared/embedder/input_events.rs
@@ -58,16 +58,16 @@ impl InputEvent {
}
}
- pub fn with_webdriver_message_id(self, webdriver_id: Option<WebDriverMessageId>) -> Self {
+ pub fn with_webdriver_message_id(mut self, webdriver_id: Option<WebDriverMessageId>) -> Self {
match self {
InputEvent::EditingAction(..) => {},
InputEvent::Gamepad(..) => {},
InputEvent::Ime(..) => {},
InputEvent::Keyboard(..) => {},
- InputEvent::MouseButton(mut event) => {
+ InputEvent::MouseButton(ref mut event) => {
event.webdriver_id = webdriver_id;
},
- InputEvent::MouseMove(mut event) => {
+ InputEvent::MouseMove(ref mut event) => {
event.webdriver_id = webdriver_id;
},
InputEvent::Touch(..) => {},
diff --git a/components/shared/embedder/webdriver.rs b/components/shared/embedder/webdriver.rs
index 7b0f02bc26a..d28bb6fc6c3 100644
--- a/components/shared/embedder/webdriver.rs
+++ b/components/shared/embedder/webdriver.rs
@@ -130,7 +130,7 @@ pub enum WebDriverScriptCommand {
IpcSender<Result<Vec<String>, ErrorStatus>>,
),
FindElementElementsTagName(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
- FocusElement(String, IpcSender<Result<(), ErrorStatus>>),
+ GetElementShadowRoot(String, IpcSender<Result<Option<String>, ErrorStatus>>),
ElementClick(String, IpcSender<Result<Option<String>, ErrorStatus>>),
GetActiveElement(IpcSender<Option<String>>),
GetComputedRole(String, IpcSender<Result<Option<String>, ErrorStatus>>),
@@ -161,6 +161,8 @@ pub enum WebDriverScriptCommand {
IsEnabled(String, IpcSender<Result<bool, ErrorStatus>>),
IsSelected(String, IpcSender<Result<bool, ErrorStatus>>),
GetTitle(IpcSender<String>),
+ /// Match the element type before sending the event for webdriver `element send keys`.
+ WillSendKeys(String, String, bool, IpcSender<Result<bool, ErrorStatus>>),
}
#[derive(Debug, Deserialize, Serialize)]
diff --git a/components/shared/net/lib.rs b/components/shared/net/lib.rs
index 0126bdbcd80..0a490fa3bcf 100644
--- a/components/shared/net/lib.rs
+++ b/components/shared/net/lib.rs
@@ -40,6 +40,7 @@ pub mod blob_url_store;
pub mod filemanager_thread;
pub mod http_status;
pub mod image_cache;
+pub mod mime_classifier;
pub mod policy_container;
pub mod pub_domains;
pub mod quality;
diff --git a/components/shared/net/mime_classifier.rs b/components/shared/net/mime_classifier.rs
new file mode 100644
index 00000000000..7e5408ba56e
--- /dev/null
+++ b/components/shared/net/mime_classifier.rs
@@ -0,0 +1,1229 @@
+/* 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 mime::{self, Mime};
+
+use crate::LoadContext;
+
+pub struct MimeClassifier {
+ image_classifier: GroupedClassifier,
+ audio_video_classifier: GroupedClassifier,
+ scriptable_classifier: GroupedClassifier,
+ plaintext_classifier: GroupedClassifier,
+ archive_classifier: GroupedClassifier,
+ binary_or_plaintext: BinaryOrPlaintextClassifier,
+ feeds_classifier: FeedsClassifier,
+ font_classifier: GroupedClassifier,
+}
+
+#[derive(PartialEq)]
+pub enum MediaType {
+ Xml,
+ Html,
+ AudioVideo,
+ Image,
+ JavaScript,
+ Json,
+ Font,
+}
+
+pub enum ApacheBugFlag {
+ On,
+ Off,
+}
+
+impl ApacheBugFlag {
+ /// <https://mimesniff.spec.whatwg.org/#supplied-mime-type-detection-algorithm>
+ pub fn from_content_type(last_raw_content_type: &[u8]) -> ApacheBugFlag {
+ if last_raw_content_type == b"text/plain" ||
+ last_raw_content_type == b"text/plain; charset=ISO-8859-1" ||
+ last_raw_content_type == b"text/plain; charset=iso-8859-1" ||
+ last_raw_content_type == b"text/plain; charset=UTF-8"
+ {
+ ApacheBugFlag::On
+ } else {
+ ApacheBugFlag::Off
+ }
+ }
+}
+
+#[derive(PartialEq)]
+pub enum NoSniffFlag {
+ On,
+ Off,
+}
+
+impl Default for MimeClassifier {
+ fn default() -> Self {
+ Self {
+ image_classifier: GroupedClassifier::image_classifer(),
+ audio_video_classifier: GroupedClassifier::audio_video_classifier(),
+ scriptable_classifier: GroupedClassifier::scriptable_classifier(),
+ plaintext_classifier: GroupedClassifier::plaintext_classifier(),
+ archive_classifier: GroupedClassifier::archive_classifier(),
+ binary_or_plaintext: BinaryOrPlaintextClassifier,
+ feeds_classifier: FeedsClassifier,
+ font_classifier: GroupedClassifier::font_classifier(),
+ }
+ }
+}
+
+impl MimeClassifier {
+ //Performs MIME Type Sniffing Algorithm (sections 7 and 8)
+ pub fn classify<'a>(
+ &'a self,
+ context: LoadContext,
+ no_sniff_flag: NoSniffFlag,
+ apache_bug_flag: ApacheBugFlag,
+ supplied_type: &Option<Mime>,
+ data: &'a [u8],
+ ) -> Mime {
+ let supplied_type_or_octet_stream = supplied_type
+ .clone()
+ .unwrap_or(mime::APPLICATION_OCTET_STREAM);
+ match context {
+ LoadContext::Browsing => match *supplied_type {
+ None => self.sniff_unknown_type(no_sniff_flag, data),
+ Some(ref supplied_type) => {
+ if MimeClassifier::is_explicit_unknown(supplied_type) {
+ self.sniff_unknown_type(no_sniff_flag, data)
+ } else {
+ match no_sniff_flag {
+ NoSniffFlag::On => supplied_type.clone(),
+ NoSniffFlag::Off => match apache_bug_flag {
+ ApacheBugFlag::On => self.sniff_text_or_data(data),
+ ApacheBugFlag::Off => {
+ match MimeClassifier::get_media_type(supplied_type) {
+ Some(MediaType::Html) => {
+ self.feeds_classifier.classify(data)
+ },
+ Some(MediaType::Image) => {
+ self.image_classifier.classify(data)
+ },
+ Some(MediaType::AudioVideo) => {
+ self.audio_video_classifier.classify(data)
+ },
+ Some(MediaType::JavaScript) |
+ Some(MediaType::Font) |
+ Some(MediaType::Json) |
+ Some(MediaType::Xml) |
+ None => None,
+ }
+ .unwrap_or(supplied_type.clone())
+ },
+ },
+ }
+ }
+ },
+ },
+ LoadContext::Image => {
+ // Section 8.2 Sniffing an image context
+ match MimeClassifier::maybe_get_media_type(supplied_type) {
+ Some(MediaType::Xml) => None,
+ _ => self.image_classifier.classify(data),
+ }
+ .unwrap_or(supplied_type_or_octet_stream)
+ },
+ LoadContext::AudioVideo => {
+ // Section 8.3 Sniffing an image context
+ match MimeClassifier::maybe_get_media_type(supplied_type) {
+ Some(MediaType::Xml) => None,
+ _ => self.audio_video_classifier.classify(data),
+ }
+ .unwrap_or(supplied_type_or_octet_stream)
+ },
+ LoadContext::Plugin => {
+ // 8.4 Sniffing in a plugin context
+ //
+ // This section was *not* finalized in the specs at the time
+ // of this implementation.
+ match *supplied_type {
+ None => mime::APPLICATION_OCTET_STREAM,
+ _ => supplied_type_or_octet_stream,
+ }
+ },
+ LoadContext::Style => {
+ // 8.5 Sniffing in a style context
+ //
+ // This section was *not* finalized in the specs at the time
+ // of this implementation.
+ match *supplied_type {
+ None => mime::TEXT_CSS,
+ _ => supplied_type_or_octet_stream,
+ }
+ },
+ LoadContext::Script => {
+ // 8.6 Sniffing in a script context
+ //
+ // This section was *not* finalized in the specs at the time
+ // of this implementation.
+ match *supplied_type {
+ None => mime::TEXT_JAVASCRIPT,
+ _ => supplied_type_or_octet_stream,
+ }
+ },
+ LoadContext::Font => {
+ // 8.7 Sniffing in a font context
+ match MimeClassifier::maybe_get_media_type(supplied_type) {
+ Some(MediaType::Xml) => None,
+ _ => self.font_classifier.classify(data),
+ }
+ .unwrap_or(supplied_type_or_octet_stream)
+ },
+ LoadContext::TextTrack => {
+ // 8.8 Sniffing in a text track context
+ //
+ // This section was *not* finalized in the specs at the time
+ // of this implementation.
+ "text/vtt".parse().unwrap()
+ },
+ LoadContext::CacheManifest => {
+ // 8.9 Sniffing in a cache manifest context
+ //
+ // This section was *not* finalized in the specs at the time
+ // of this implementation.
+ "text/cache-manifest".parse().unwrap()
+ },
+ }
+ }
+
+ pub fn validate(&self) -> Result<(), String> {
+ self.image_classifier.validate()?;
+ self.audio_video_classifier.validate()?;
+ self.scriptable_classifier.validate()?;
+ self.plaintext_classifier.validate()?;
+ self.archive_classifier.validate()?;
+ self.binary_or_plaintext.validate()?;
+ self.feeds_classifier.validate()?;
+ self.font_classifier.validate()?;
+ Ok(())
+ }
+
+ //some sort of iterator over the classifiers might be better?
+ fn sniff_unknown_type(&self, no_sniff_flag: NoSniffFlag, data: &[u8]) -> Mime {
+ let should_sniff_scriptable = no_sniff_flag == NoSniffFlag::Off;
+ let sniffed = if should_sniff_scriptable {
+ self.scriptable_classifier.classify(data)
+ } else {
+ None
+ };
+
+ sniffed
+ .or_else(|| self.plaintext_classifier.classify(data))
+ .or_else(|| self.image_classifier.classify(data))
+ .or_else(|| self.audio_video_classifier.classify(data))
+ .or_else(|| self.archive_classifier.classify(data))
+ .or_else(|| self.binary_or_plaintext.classify(data))
+ .expect("BinaryOrPlaintextClassifier always succeeds")
+ }
+
+ fn sniff_text_or_data<'a>(&'a self, data: &'a [u8]) -> Mime {
+ self.binary_or_plaintext
+ .classify(data)
+ .expect("BinaryOrPlaintextClassifier always succeeds")
+ }
+
+ /// <https://mimesniff.spec.whatwg.org/#xml-mime-type>
+ fn is_xml(mt: &Mime) -> bool {
+ mt.suffix() == Some(mime::XML) ||
+ *mt == mime::TEXT_XML ||
+ (mt.type_() == mime::APPLICATION && mt.subtype() == mime::XML)
+ }
+
+ /// <https://mimesniff.spec.whatwg.org/#html-mime-type>
+ fn is_html(mt: &Mime) -> bool {
+ *mt == mime::TEXT_HTML
+ }
+
+ /// <https://mimesniff.spec.whatwg.org/#image-mime-type>
+ fn is_image(mt: &Mime) -> bool {
+ mt.type_() == mime::IMAGE
+ }
+
+ /// <https://mimesniff.spec.whatwg.org/#audio-or-video-mime-type>
+ fn is_audio_video(mt: &Mime) -> bool {
+ mt.type_() == mime::AUDIO ||
+ mt.type_() == mime::VIDEO ||
+ mt.type_() == mime::APPLICATION && mt.subtype() == mime::OGG
+ }
+
+ fn is_explicit_unknown(mt: &Mime) -> bool {
+ mt.type_().as_str() == "unknown" && mt.subtype().as_str() == "unknown" ||
+ mt.type_() == mime::APPLICATION && mt.subtype().as_str() == "unknown" ||
+ mt.type_() == mime::STAR && mt.subtype() == mime::STAR
+ }
+
+ /// <https://mimesniff.spec.whatwg.org/#javascript-mime-type>
+ fn is_javascript(mt: &Mime) -> bool {
+ (mt.type_() == mime::APPLICATION &&
+ (["ecmascript", "javascript", "x-ecmascript", "x-javascript"]
+ .contains(&mt.subtype().as_str()))) ||
+ (mt.type_() == mime::TEXT &&
+ ([
+ "ecmascript",
+ "javascript",
+ "javascript1.0",
+ "javascript1.1",
+ "javascript1.2",
+ "javascript1.3",
+ "javascript1.4",
+ "javascript1.5",
+ "jscript",
+ "livescript",
+ "x-ecmascript",
+ "x-javascript",
+ ]
+ .contains(&mt.subtype().as_str())))
+ }
+
+ /// <https://mimesniff.spec.whatwg.org/#json-mime-type>
+ fn is_json(mt: &Mime) -> bool {
+ mt.suffix() == Some(mime::JSON) ||
+ (mt.subtype() == mime::JSON &&
+ (mt.type_() == mime::APPLICATION || mt.type_() == mime::TEXT))
+ }
+
+ /// <https://mimesniff.spec.whatwg.org/#font-mime-type>
+ fn is_font(mt: &Mime) -> bool {
+ mt.type_() == mime::FONT ||
+ (mt.type_() == mime::APPLICATION &&
+ ([
+ "font-cff",
+ "font-off",
+ "font-sfnt",
+ "font-ttf",
+ "font-woff",
+ "vnd.ms-fontobject",
+ "vnd.ms-opentype",
+ ]
+ .contains(&mt.subtype().as_str())))
+ }
+
+ pub fn get_media_type(mime: &Mime) -> Option<MediaType> {
+ if MimeClassifier::is_xml(mime) {
+ Some(MediaType::Xml)
+ } else if MimeClassifier::is_html(mime) {
+ Some(MediaType::Html)
+ } else if MimeClassifier::is_image(mime) {
+ Some(MediaType::Image)
+ } else if MimeClassifier::is_audio_video(mime) {
+ Some(MediaType::AudioVideo)
+ } else if MimeClassifier::is_javascript(mime) {
+ Some(MediaType::JavaScript)
+ } else if MimeClassifier::is_font(mime) {
+ Some(MediaType::Font)
+ } else if MimeClassifier::is_json(mime) {
+ Some(MediaType::Json)
+ } else {
+ None
+ }
+ }
+
+ fn maybe_get_media_type(supplied_type: &Option<Mime>) -> Option<MediaType> {
+ supplied_type
+ .as_ref()
+ .and_then(MimeClassifier::get_media_type)
+ }
+}
+
+//Interface used for composite types
+trait MIMEChecker {
+ fn classify(&self, data: &[u8]) -> Option<Mime>;
+ /// Validate the MIME checker configuration
+ fn validate(&self) -> Result<(), String>;
+}
+
+trait Matches {
+ fn matches(&mut self, matches: &[u8]) -> bool;
+}
+
+impl<'a, T: Iterator<Item = &'a u8> + Clone> Matches for T {
+ // Matching function that works on an iterator.
+ // see if the next matches.len() bytes in data_iterator equal matches
+ // move iterator and return true or just return false
+ //
+ // Params
+ // self: an iterator
+ // matches: a vector of bytes to match
+ //
+ // Return
+ // true if the next n elements of self match n elements of matches
+ // false otherwise
+ //
+ // Side effects
+ // moves the iterator when match is found
+ fn matches(&mut self, matches: &[u8]) -> bool {
+ if self.clone().nth(matches.len()).is_none() {
+ // there are less than matches.len() elements in self
+ return false;
+ }
+ let result = self.clone().zip(matches).all(|(s, m)| *s == *m);
+ if result {
+ self.nth(matches.len());
+ }
+ result
+ }
+}
+
+struct ByteMatcher {
+ pattern: &'static [u8],
+ mask: &'static [u8],
+ leading_ignore: &'static [u8],
+ content_type: Mime,
+}
+
+impl ByteMatcher {
+ fn matches(&self, data: &[u8]) -> Option<usize> {
+ if data.len() < self.pattern.len() {
+ None
+ } else if data == self.pattern {
+ Some(self.pattern.len())
+ } else {
+ data[..data.len() - self.pattern.len() + 1]
+ .iter()
+ .position(|x| !self.leading_ignore.contains(x))
+ .and_then(|start| {
+ if data[start..]
+ .iter()
+ .zip(self.pattern.iter())
+ .zip(self.mask.iter())
+ .all(|((&data, &pattern), &mask)| (data & mask) == pattern)
+ {
+ Some(start + self.pattern.len())
+ } else {
+ None
+ }
+ })
+ }
+ }
+}
+
+impl MIMEChecker for ByteMatcher {
+ fn classify(&self, data: &[u8]) -> Option<Mime> {
+ self.matches(data).map(|_| self.content_type.clone())
+ }
+
+ fn validate(&self) -> Result<(), String> {
+ if self.pattern.is_empty() {
+ return Err(format!("Zero length pattern for {:?}", self.content_type));
+ }
+ if self.pattern.len() != self.mask.len() {
+ return Err(format!(
+ "Unequal pattern and mask length for {:?}",
+ self.content_type
+ ));
+ }
+ if self
+ .pattern
+ .iter()
+ .zip(self.mask.iter())
+ .any(|(&pattern, &mask)| pattern & mask != pattern)
+ {
+ return Err(format!(
+ "Pattern not pre-masked for {:?}",
+ self.content_type
+ ));
+ }
+ Ok(())
+ }
+}
+
+struct TagTerminatedByteMatcher {
+ matcher: ByteMatcher,
+}
+
+impl MIMEChecker for TagTerminatedByteMatcher {
+ fn classify(&self, data: &[u8]) -> Option<Mime> {
+ self.matcher.matches(data).and_then(|j| {
+ if j < data.len() && (data[j] == b' ' || data[j] == b'>') {
+ Some(self.matcher.content_type.clone())
+ } else {
+ None
+ }
+ })
+ }
+
+ fn validate(&self) -> Result<(), String> {
+ self.matcher.validate()
+ }
+}
+
+pub struct Mp4Matcher;
+
+impl Mp4Matcher {
+ pub fn matches(&self, data: &[u8]) -> bool {
+ if data.len() < 12 {
+ return false;
+ }
+
+ let box_size = (((data[0] as u32) << 24) |
+ ((data[1] as u32) << 16) |
+ ((data[2] as u32) << 8) |
+ (data[3] as u32)) as usize;
+ if (data.len() < box_size) || (box_size % 4 != 0) {
+ return false;
+ }
+
+ let ftyp = [0x66, 0x74, 0x79, 0x70];
+ if !data[4..].starts_with(&ftyp) {
+ return false;
+ }
+
+ let mp4 = [0x6D, 0x70, 0x34];
+ data[8..].starts_with(&mp4) ||
+ data[16..box_size]
+ .chunks(4)
+ .any(|chunk| chunk.starts_with(&mp4))
+ }
+}
+impl MIMEChecker for Mp4Matcher {
+ fn classify(&self, data: &[u8]) -> Option<Mime> {
+ if self.matches(data) {
+ Some("video/mp4".parse().unwrap())
+ } else {
+ None
+ }
+ }
+
+ fn validate(&self) -> Result<(), String> {
+ Ok(())
+ }
+}
+
+struct BinaryOrPlaintextClassifier;
+
+impl BinaryOrPlaintextClassifier {
+ fn classify_impl(&self, data: &[u8]) -> Mime {
+ if data.starts_with(&[0xFFu8, 0xFEu8]) ||
+ data.starts_with(&[0xFEu8, 0xFFu8]) ||
+ data.starts_with(&[0xEFu8, 0xBBu8, 0xBFu8])
+ {
+ mime::TEXT_PLAIN
+ } else if data.iter().any(|&x| {
+ x <= 0x08u8 ||
+ x == 0x0Bu8 ||
+ (0x0Eu8..=0x1Au8).contains(&x) ||
+ (0x1Cu8..=0x1Fu8).contains(&x)
+ }) {
+ mime::APPLICATION_OCTET_STREAM
+ } else {
+ mime::TEXT_PLAIN
+ }
+ }
+}
+impl MIMEChecker for BinaryOrPlaintextClassifier {
+ fn classify(&self, data: &[u8]) -> Option<Mime> {
+ Some(self.classify_impl(data))
+ }
+
+ fn validate(&self) -> Result<(), String> {
+ Ok(())
+ }
+}
+struct GroupedClassifier {
+ byte_matchers: Vec<Box<dyn MIMEChecker + Send + Sync>>,
+}
+impl GroupedClassifier {
+ fn image_classifer() -> GroupedClassifier {
+ GroupedClassifier {
+ byte_matchers: vec![
+ // Keep this in sync with 'is_supported_mime_type' from
+ // components/style/servo/media_queries.rs
+ Box::new(ByteMatcher::image_x_icon()),
+ Box::new(ByteMatcher::image_x_icon_cursor()),
+ Box::new(ByteMatcher::image_bmp()),
+ Box::new(ByteMatcher::image_gif89a()),
+ Box::new(ByteMatcher::image_gif87a()),
+ Box::new(ByteMatcher::image_webp()),
+ Box::new(ByteMatcher::image_png()),
+ Box::new(ByteMatcher::image_jpeg()),
+ ],
+ }
+ }
+ fn audio_video_classifier() -> GroupedClassifier {
+ GroupedClassifier {
+ byte_matchers: vec![
+ Box::new(ByteMatcher::video_webm()),
+ Box::new(ByteMatcher::audio_basic()),
+ Box::new(ByteMatcher::audio_aiff()),
+ Box::new(ByteMatcher::audio_mpeg()),
+ Box::new(ByteMatcher::application_ogg()),
+ Box::new(ByteMatcher::audio_midi()),
+ Box::new(ByteMatcher::video_avi()),
+ Box::new(ByteMatcher::audio_wave()),
+ Box::new(Mp4Matcher),
+ ],
+ }
+ }
+ fn scriptable_classifier() -> GroupedClassifier {
+ GroupedClassifier {
+ byte_matchers: vec![
+ Box::new(ByteMatcher::text_html_doctype()),
+ Box::new(ByteMatcher::text_html_page()),
+ Box::new(ByteMatcher::text_html_head()),
+ Box::new(ByteMatcher::text_html_script()),
+ Box::new(ByteMatcher::text_html_iframe()),
+ Box::new(ByteMatcher::text_html_h1()),
+ Box::new(ByteMatcher::text_html_div()),
+ Box::new(ByteMatcher::text_html_font()),
+ Box::new(ByteMatcher::text_html_table()),
+ Box::new(ByteMatcher::text_html_a()),
+ Box::new(ByteMatcher::text_html_style()),
+ Box::new(ByteMatcher::text_html_title()),
+ Box::new(ByteMatcher::text_html_b()),
+ Box::new(ByteMatcher::text_html_body()),
+ Box::new(ByteMatcher::text_html_br()),
+ Box::new(ByteMatcher::text_html_p()),
+ Box::new(ByteMatcher::text_html_comment()),
+ Box::new(ByteMatcher::text_xml()),
+ Box::new(ByteMatcher::application_pdf()),
+ ],
+ }
+ }
+ fn plaintext_classifier() -> GroupedClassifier {
+ GroupedClassifier {
+ byte_matchers: vec![
+ Box::new(ByteMatcher::text_plain_utf_8_bom()),
+ Box::new(ByteMatcher::text_plain_utf_16le_bom()),
+ Box::new(ByteMatcher::text_plain_utf_16be_bom()),
+ Box::new(ByteMatcher::application_postscript()),
+ ],
+ }
+ }
+ fn archive_classifier() -> GroupedClassifier {
+ GroupedClassifier {
+ byte_matchers: vec![
+ Box::new(ByteMatcher::application_x_gzip()),
+ Box::new(ByteMatcher::application_zip()),
+ Box::new(ByteMatcher::application_x_rar_compressed()),
+ ],
+ }
+ }
+
+ fn font_classifier() -> GroupedClassifier {
+ GroupedClassifier {
+ byte_matchers: vec![
+ Box::new(ByteMatcher::application_font_woff()),
+ Box::new(ByteMatcher::true_type_collection()),
+ Box::new(ByteMatcher::open_type()),
+ Box::new(ByteMatcher::true_type()),
+ Box::new(ByteMatcher::application_vnd_ms_font_object()),
+ ],
+ }
+ }
+}
+impl MIMEChecker for GroupedClassifier {
+ fn classify(&self, data: &[u8]) -> Option<Mime> {
+ self.byte_matchers
+ .iter()
+ .filter_map(|matcher| matcher.classify(data))
+ .next()
+ }
+
+ fn validate(&self) -> Result<(), String> {
+ for byte_matcher in &self.byte_matchers {
+ byte_matcher.validate()?
+ }
+ Ok(())
+ }
+}
+
+enum Match {
+ None,
+ Start,
+ StartAndEnd,
+}
+
+impl Match {
+ fn chain<F: FnOnce() -> Match>(self, f: F) -> Match {
+ if let Match::None = self {
+ return f();
+ }
+ self
+ }
+}
+
+fn eats_until<'a, T>(matcher: &mut T, start: &[u8], end: &[u8]) -> Match
+where
+ T: Iterator<Item = &'a u8> + Clone,
+{
+ if !matcher.matches(start) {
+ Match::None
+ } else if end.len() == 1 {
+ if matcher.any(|&x| x == end[0]) {
+ Match::StartAndEnd
+ } else {
+ Match::Start
+ }
+ } else {
+ while !matcher.matches(end) {
+ if matcher.next().is_none() {
+ return Match::Start;
+ }
+ }
+ Match::StartAndEnd
+ }
+}
+
+struct FeedsClassifier;
+impl FeedsClassifier {
+ // Implements sniffing for mislabeled feeds (https://mimesniff.spec.whatwg.org/#sniffing-a-mislabeled-feed)
+ fn classify_impl(&self, data: &[u8]) -> Option<Mime> {
+ // Step 4: can not be feed unless length is > 3
+ if data.len() < 3 {
+ return None;
+ }
+
+ let mut matcher = data.iter();
+
+ // eat the first three acceptable byte sequences if they are equal to UTF-8 BOM
+ let utf8_bom = &[0xEFu8, 0xBBu8, 0xBFu8];
+ matcher.matches(utf8_bom);
+
+ // continuously search for next "<" until end of matcher
+ // TODO: need max_bytes to prevent inadvertently examining html document
+ // eg. an html page with a feed example
+ loop {
+ if !matcher.any(|x| *x == b'<') {
+ return None;
+ }
+
+ // Steps 5.2.1 to 5.2.4
+ match eats_until(&mut matcher, b"?", b"?>")
+ .chain(|| eats_until(&mut matcher, b"!--", b"-->"))
+ .chain(|| eats_until(&mut matcher, b"!", b">"))
+ {
+ Match::StartAndEnd => continue,
+ Match::None => {},
+ Match::Start => return None,
+ }
+
+ // Step 5.2.5
+ if matcher.matches(b"rss") {
+ return Some("application/rss+xml".parse().unwrap());
+ }
+ // Step 5.2.6
+ if matcher.matches(b"feed") {
+ return Some("application/atom+xml".parse().unwrap());
+ }
+ // Step 5.2.7
+ if matcher.matches(b"rdf:RDF") {
+ while matcher.next().is_some() {
+ match eats_until(
+ &mut matcher,
+ b"http://purl.org/rss/1.0/",
+ b"http://www.w3.org/1999/02/22-rdf-syntax-ns#",
+ )
+ .chain(|| {
+ eats_until(
+ &mut matcher,
+ b"http://www.w3.org/1999/02/22-rdf-syntax-ns#",
+ b"http://purl.org/rss/1.0/",
+ )
+ }) {
+ Match::StartAndEnd => return Some("application/rss+xml".parse().unwrap()),
+ Match::None => {},
+ Match::Start => return None,
+ }
+ }
+ return None;
+ }
+ }
+ }
+}
+
+impl MIMEChecker for FeedsClassifier {
+ fn classify(&self, data: &[u8]) -> Option<Mime> {
+ self.classify_impl(data)
+ }
+
+ fn validate(&self) -> Result<(), String> {
+ Ok(())
+ }
+}
+
+//Contains hard coded byte matchers
+//TODO: These should be configured and not hard coded
+impl ByteMatcher {
+ //A Windows Icon signature
+ fn image_x_icon() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"\x00\x00\x01\x00",
+ mask: b"\xFF\xFF\xFF\xFF",
+ content_type: "image/x-icon".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ //A Windows Cursor signature.
+ fn image_x_icon_cursor() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"\x00\x00\x02\x00",
+ mask: b"\xFF\xFF\xFF\xFF",
+ content_type: "image/x-icon".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ //The string "BM", a BMP signature.
+ fn image_bmp() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"BM",
+ mask: b"\xFF\xFF",
+ content_type: mime::IMAGE_BMP,
+ leading_ignore: &[],
+ }
+ }
+ //The string "GIF89a", a GIF signature.
+ fn image_gif89a() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"GIF89a",
+ mask: b"\xFF\xFF\xFF\xFF\xFF\xFF",
+ content_type: mime::IMAGE_GIF,
+ leading_ignore: &[],
+ }
+ }
+ //The string "GIF87a", a GIF signature.
+ fn image_gif87a() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"GIF87a",
+ mask: b"\xFF\xFF\xFF\xFF\xFF\xFF",
+ content_type: mime::IMAGE_GIF,
+ leading_ignore: &[],
+ }
+ }
+ //The string "RIFF" followed by four bytes followed by the string "WEBPVP".
+ fn image_webp() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"RIFF\x00\x00\x00\x00WEBPVP",
+ mask: b"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF",
+ content_type: "image/webp".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ //An error-checking byte followed by the string "PNG" followed by CR LF SUB LF, the PNG
+ //signature.
+ fn image_png() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"\x89PNG\r\n\x1A\n",
+ mask: b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
+ content_type: mime::IMAGE_PNG,
+ leading_ignore: &[],
+ }
+ }
+ // The JPEG Start of Image marker followed by the indicator byte of another marker.
+ fn image_jpeg() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"\xFF\xD8\xFF",
+ mask: b"\xFF\xFF\xFF",
+ content_type: mime::IMAGE_JPEG,
+ leading_ignore: &[],
+ }
+ }
+ //The WebM signature. [TODO: Use more bytes?]
+ fn video_webm() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"\x1A\x45\xDF\xA3",
+ mask: b"\xFF\xFF\xFF\xFF",
+ content_type: "video/webm".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ //The string ".snd", the basic audio signature.
+ fn audio_basic() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b".snd",
+ mask: b"\xFF\xFF\xFF\xFF",
+ content_type: "audio/basic".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ //The string "FORM" followed by four bytes followed by the string "AIFF", the AIFF signature.
+ fn audio_aiff() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"FORM\x00\x00\x00\x00AIFF",
+ mask: b"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF",
+ content_type: "audio/aiff".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ //The string "ID3", the ID3v2-tagged MP3 signature.
+ fn audio_mpeg() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"ID3",
+ mask: b"\xFF\xFF\xFF",
+ content_type: "audio/mpeg".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ //The string "OggS" followed by NUL, the Ogg container signature.
+ fn application_ogg() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"OggS\x00",
+ mask: b"\xFF\xFF\xFF\xFF\xFF",
+ content_type: "application/ogg".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ //The string "MThd" followed by four bytes representing the number 6 in 32 bits (big-endian),
+ //the MIDI signature.
+ fn audio_midi() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"MThd\x00\x00\x00\x06",
+ mask: b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
+ content_type: "audio/midi".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ //The string "RIFF" followed by four bytes followed by the string "AVI ", the AVI signature.
+ fn video_avi() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"RIFF\x00\x00\x00\x00AVI ",
+ mask: b"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF",
+ content_type: "video/avi".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ // The string "RIFF" followed by four bytes followed by the string "WAVE", the WAVE signature.
+ fn audio_wave() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"RIFF\x00\x00\x00\x00WAVE",
+ mask: b"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF",
+ content_type: "audio/wave".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ // doctype terminated with Tag terminating (TT) Byte
+ fn text_html_doctype() -> TagTerminatedByteMatcher {
+ TagTerminatedByteMatcher {
+ matcher: ByteMatcher {
+ pattern: b"<!DOCTYPE HTML",
+ mask: b"\xFF\xFF\xDF\xDF\xDF\xDF\xDF\xDF\xDF\xFF\xDF\xDF\xDF\xDF",
+ content_type: mime::TEXT_HTML,
+ leading_ignore: b"\t\n\x0C\r ",
+ },
+ }
+ }
+
+ // HTML terminated with Tag terminating (TT) Byte: 0x20 (SP)
+ fn text_html_page() -> TagTerminatedByteMatcher {
+ TagTerminatedByteMatcher {
+ matcher: ByteMatcher {
+ pattern: b"<HTML",
+ mask: b"\xFF\xDF\xDF\xDF\xDF",
+ content_type: mime::TEXT_HTML,
+ leading_ignore: b"\t\n\x0C\r ",
+ },
+ }
+ }
+
+ // head terminated with Tag Terminating (TT) Byte
+ fn text_html_head() -> TagTerminatedByteMatcher {
+ TagTerminatedByteMatcher {
+ matcher: ByteMatcher {
+ pattern: b"<HEAD",
+ mask: b"\xFF\xDF\xDF\xDF\xDF",
+ content_type: mime::TEXT_HTML,
+ leading_ignore: b"\t\n\x0C\r ",
+ },
+ }
+ }
+
+ // script terminated with Tag Terminating (TT) Byte
+ fn text_html_script() -> TagTerminatedByteMatcher {
+ TagTerminatedByteMatcher {
+ matcher: ByteMatcher {
+ pattern: b"<SCRIPT",
+ mask: b"\xFF\xDF\xDF\xDF\xDF\xDF\xDF",
+ content_type: mime::TEXT_HTML,
+ leading_ignore: b"\t\n\x0C\r ",
+ },
+ }
+ }
+
+ // iframe terminated with Tag Terminating (TT) Byte
+ fn text_html_iframe() -> TagTerminatedByteMatcher {
+ TagTerminatedByteMatcher {
+ matcher: ByteMatcher {
+ pattern: b"<IFRAME",
+ mask: b"\xFF\xDF\xDF\xDF\xDF\xDF\xDF",
+ content_type: mime::TEXT_HTML,
+ leading_ignore: b"\t\n\x0C\r ",
+ },
+ }
+ }
+
+ // h1 terminated with Tag Terminating (TT) Byte
+ fn text_html_h1() -> TagTerminatedByteMatcher {
+ TagTerminatedByteMatcher {
+ matcher: ByteMatcher {
+ pattern: b"<H1",
+ mask: b"\xFF\xDF\xFF",
+ content_type: mime::TEXT_HTML,
+ leading_ignore: b"\t\n\x0C\r ",
+ },
+ }
+ }
+
+ // div terminated with Tag Terminating (TT) Byte
+ fn text_html_div() -> TagTerminatedByteMatcher {
+ TagTerminatedByteMatcher {
+ matcher: ByteMatcher {
+ pattern: b"<DIV",
+ mask: b"\xFF\xDF\xDF\xDF",
+ content_type: mime::TEXT_HTML,
+ leading_ignore: b"\t\n\x0C\r ",
+ },
+ }
+ }
+
+ // font terminated with Tag Terminating (TT) Byte
+ fn text_html_font() -> TagTerminatedByteMatcher {
+ TagTerminatedByteMatcher {
+ matcher: ByteMatcher {
+ pattern: b"<FONT",
+ mask: b"\xFF\xDF\xDF\xDF\xDF",
+ content_type: mime::TEXT_HTML,
+ leading_ignore: b"\t\n\x0C\r ",
+ },
+ }
+ }
+
+ // table terminated with Tag Terminating (TT) Byte
+ fn text_html_table() -> TagTerminatedByteMatcher {
+ TagTerminatedByteMatcher {
+ matcher: ByteMatcher {
+ pattern: b"<TABLE",
+ mask: b"\xFF\xDF\xDF\xDF\xDF\xDF",
+ content_type: mime::TEXT_HTML,
+ leading_ignore: b"\t\n\x0C\r ",
+ },
+ }
+ }
+
+ // a terminated with Tag Terminating (TT) Byte
+ fn text_html_a() -> TagTerminatedByteMatcher {
+ TagTerminatedByteMatcher {
+ matcher: ByteMatcher {
+ pattern: b"<A",
+ mask: b"\xFF\xDF",
+ content_type: mime::TEXT_HTML,
+ leading_ignore: b"\t\n\x0C\r ",
+ },
+ }
+ }
+
+ // style terminated with Tag Terminating (TT) Byte
+ fn text_html_style() -> TagTerminatedByteMatcher {
+ TagTerminatedByteMatcher {
+ matcher: ByteMatcher {
+ pattern: b"<STYLE",
+ mask: b"\xFF\xDF\xDF\xDF\xDF\xDF",
+ content_type: mime::TEXT_HTML,
+ leading_ignore: b"\t\n\x0C\r ",
+ },
+ }
+ }
+
+ // title terminated with Tag Terminating (TT) Byte
+ fn text_html_title() -> TagTerminatedByteMatcher {
+ TagTerminatedByteMatcher {
+ matcher: ByteMatcher {
+ pattern: b"<TITLE",
+ mask: b"\xFF\xDF\xDF\xDF\xDF\xDF",
+ content_type: mime::TEXT_HTML,
+ leading_ignore: b"\t\n\x0C\r ",
+ },
+ }
+ }
+
+ // b terminated with Tag Terminating (TT) Byte
+ fn text_html_b() -> TagTerminatedByteMatcher {
+ TagTerminatedByteMatcher {
+ matcher: ByteMatcher {
+ pattern: b"<B",
+ mask: b"\xFF\xDF",
+ content_type: mime::TEXT_HTML,
+ leading_ignore: b"\t\n\x0C\r ",
+ },
+ }
+ }
+
+ // body terminated with Tag Terminating (TT) Byte
+ fn text_html_body() -> TagTerminatedByteMatcher {
+ TagTerminatedByteMatcher {
+ matcher: ByteMatcher {
+ pattern: b"<BODY",
+ mask: b"\xFF\xDF\xDF\xDF\xDF",
+ content_type: mime::TEXT_HTML,
+ leading_ignore: b"\t\n\x0C\r ",
+ },
+ }
+ }
+
+ // br terminated with Tag Terminating (TT) Byte
+ fn text_html_br() -> TagTerminatedByteMatcher {
+ TagTerminatedByteMatcher {
+ matcher: ByteMatcher {
+ pattern: b"<BR",
+ mask: b"\xFF\xDF\xDF",
+ content_type: mime::TEXT_HTML,
+ leading_ignore: b"\t\n\x0C\r ",
+ },
+ }
+ }
+
+ // p terminated with Tag Terminating (TT) Byte
+ fn text_html_p() -> TagTerminatedByteMatcher {
+ TagTerminatedByteMatcher {
+ matcher: ByteMatcher {
+ pattern: b"<P",
+ mask: b"\xFF\xDF",
+ content_type: mime::TEXT_HTML,
+ leading_ignore: b"\t\n\x0C\r ",
+ },
+ }
+ }
+
+ // comment terminated with Tag Terminating (TT) Byte
+ fn text_html_comment() -> TagTerminatedByteMatcher {
+ TagTerminatedByteMatcher {
+ matcher: ByteMatcher {
+ pattern: b"<!--",
+ mask: b"\xFF\xFF\xFF\xFF",
+ content_type: mime::TEXT_HTML,
+ leading_ignore: b"\t\n\x0C\r ",
+ },
+ }
+ }
+
+ //The string "<?xml".
+ fn text_xml() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"<?xml",
+ mask: b"\xFF\xFF\xFF\xFF\xFF",
+ content_type: mime::TEXT_XML,
+ leading_ignore: b"\t\n\x0C\r ",
+ }
+ }
+ //The string "%PDF-", the PDF signature.
+ fn application_pdf() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"%PDF-",
+ mask: b"\xFF\xFF\xFF\xFF\xFF",
+ content_type: mime::APPLICATION_PDF,
+ leading_ignore: &[],
+ }
+ }
+ //34 bytes followed by the string "LP", the Embedded OpenType signature.
+ fn application_vnd_ms_font_object() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+ \x00\x00LP",
+ mask: b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+ \x00\x00\xFF\xFF",
+ content_type: "application/vnd.ms-fontobject".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ //4 bytes representing the version number 1.0, a TrueType signature.
+ fn true_type() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"\x00\x01\x00\x00",
+ mask: b"\xFF\xFF\xFF\xFF",
+ content_type: "application/font-sfnt".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ //The string "OTTO", the OpenType signature.
+ fn open_type() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"OTTO",
+ mask: b"\xFF\xFF\xFF\xFF",
+ content_type: "application/font-sfnt".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ // The string "ttcf", the TrueType Collection signature.
+ fn true_type_collection() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"ttcf",
+ mask: b"\xFF\xFF\xFF\xFF",
+ content_type: "application/font-sfnt".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ // The string "wOFF", the Web Open Font Format signature.
+ fn application_font_woff() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"wOFF",
+ mask: b"\xFF\xFF\xFF\xFF",
+ content_type: "application/font-woff".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ //The GZIP archive signature.
+ fn application_x_gzip() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"\x1F\x8B\x08",
+ mask: b"\xFF\xFF\xFF",
+ content_type: "application/x-gzip".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ //The string "PK" followed by ETX EOT, the ZIP archive signature.
+ fn application_zip() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"PK\x03\x04",
+ mask: b"\xFF\xFF\xFF\xFF",
+ content_type: "application/zip".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ //The string "Rar " followed by SUB BEL NUL, the RAR archive signature.
+ fn application_x_rar_compressed() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"Rar \x1A\x07\x00",
+ mask: b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
+ content_type: "application/x-rar-compressed".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ // The string "%!PS-Adobe-", the PostScript signature.
+ fn application_postscript() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"%!PS-Adobe-",
+ mask: b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
+ content_type: "application/postscript".parse().unwrap(),
+ leading_ignore: &[],
+ }
+ }
+ // UTF-16BE BOM
+ fn text_plain_utf_16be_bom() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"\xFE\xFF\x00\x00",
+ mask: b"\xFF\xFF\x00\x00",
+ content_type: mime::TEXT_PLAIN,
+ leading_ignore: &[],
+ }
+ }
+ //UTF-16LE BOM
+ fn text_plain_utf_16le_bom() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"\xFF\xFE\x00\x00",
+ mask: b"\xFF\xFF\x00\x00",
+ content_type: mime::TEXT_PLAIN,
+ leading_ignore: &[],
+ }
+ }
+ //UTF-8 BOM
+ fn text_plain_utf_8_bom() -> ByteMatcher {
+ ByteMatcher {
+ pattern: b"\xEF\xBB\xBF\x00",
+ mask: b"\xFF\xFF\xFF\x00",
+ content_type: mime::TEXT_PLAIN,
+ leading_ignore: &[],
+ }
+ }
+}
diff --git a/components/shared/net/tests/mime_classifier.rs b/components/shared/net/tests/mime_classifier.rs
new file mode 100644
index 00000000000..79a122ac8bf
--- /dev/null
+++ b/components/shared/net/tests/mime_classifier.rs
@@ -0,0 +1,628 @@
+/* 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::env;
+use std::fs::File;
+use std::io::{self, Read};
+use std::path::{self, PathBuf};
+
+use mime::{self, Mime};
+use net_traits::LoadContext;
+use net_traits::mime_classifier::{ApacheBugFlag, MimeClassifier, Mp4Matcher, NoSniffFlag};
+
+fn read_file(path: &path::Path) -> io::Result<Vec<u8>> {
+ let mut file = File::open(path)?;
+ let mut buffer = Vec::new();
+
+ file.read_to_end(&mut buffer)?;
+
+ Ok(buffer)
+}
+
+#[test]
+fn test_sniff_mp4_matcher() {
+ let matcher = Mp4Matcher;
+
+ let p = PathBuf::from("tests/parsable_mime/video/mp4/test.mp4");
+ let read_result = read_file(&p);
+
+ match read_result {
+ Ok(data) => {
+ println!("Data Length {:?}", data.len());
+ if !matcher.matches(&data) {
+ panic!("Didn't read mime type")
+ }
+ },
+ Err(e) => panic!("Couldn't read from file with error {}", e),
+ }
+}
+
+#[test]
+fn test_sniff_mp4_matcher_long() {
+ // Check that a multi-byte length is calculated correctly
+ let matcher = Mp4Matcher;
+
+ let mut data: [u8; 260] = [0; 260];
+ let _ = &data[..11].clone_from_slice(&[
+ 0x00, 0x00, 0x01, 0x04, 0x66, 0x74, 0x79, 0x70, 0x6D, 0x70, 0x34,
+ ]);
+
+ assert!(matcher.matches(&data));
+}
+
+#[test]
+fn test_validate_classifier() {
+ let classifier = MimeClassifier::default();
+ classifier.validate().expect("Validation error")
+}
+
+#[cfg(test)]
+fn test_sniff_with_flags(
+ filename_orig: &path::Path,
+ expected_mime: Mime,
+ supplied_type: Option<Mime>,
+ no_sniff_flag: NoSniffFlag,
+ apache_bug_flag: ApacheBugFlag,
+) {
+ let current_working_directory = env::current_dir().unwrap();
+ println!(
+ "The current directory is {}",
+ current_working_directory.display()
+ );
+
+ let mut filename = PathBuf::from("tests/parsable_mime/");
+ filename.push(filename_orig);
+
+ let classifier = MimeClassifier::default();
+
+ let read_result = read_file(&filename);
+
+ match read_result {
+ Ok(data) => {
+ let parsed_mime = classifier.classify(
+ LoadContext::Browsing,
+ no_sniff_flag,
+ apache_bug_flag,
+ &supplied_type,
+ &data,
+ );
+ if (parsed_mime.type_() != expected_mime.type_()) ||
+ (parsed_mime.subtype() != expected_mime.subtype())
+ {
+ panic!(
+ "File {:?} parsed incorrectly should be {:?}, parsed as {:?}",
+ filename, expected_mime, parsed_mime
+ );
+ }
+ },
+ Err(e) => panic!("Couldn't read from file {:?} with error {}", filename, e),
+ }
+}
+
+#[cfg(test)]
+fn test_sniff_full(filename_orig: &path::Path, expected_mime: Mime, supplied_type: Option<Mime>) {
+ test_sniff_with_flags(
+ filename_orig,
+ expected_mime,
+ supplied_type,
+ NoSniffFlag::Off,
+ ApacheBugFlag::Off,
+ )
+}
+
+#[cfg(test)]
+fn test_sniff_classification(file: &str, expected_mime: Mime, supplied_type: Option<Mime>) {
+ let mut x = PathBuf::from("./");
+ x.push(expected_mime.type_().as_str());
+ x.push(expected_mime.subtype().as_str());
+ x.push(file);
+ test_sniff_full(&x, expected_mime, supplied_type);
+}
+#[cfg(test)]
+fn test_sniff_classification_sup(file: &str, expected_mime: Mime) {
+ test_sniff_classification(file, expected_mime.clone(), None);
+ let no_sub = format!("{}/", expected_mime.type_()).parse().unwrap();
+ test_sniff_classification(file, expected_mime, Some(no_sub));
+}
+
+#[test]
+fn test_sniff_x_icon() {
+ test_sniff_classification_sup("test.ico", "image/x-icon".parse().unwrap());
+}
+
+#[test]
+fn test_sniff_x_icon_cursor() {
+ test_sniff_classification_sup("test_cursor.ico", "image/x-icon".parse().unwrap());
+}
+
+#[test]
+fn test_sniff_bmp() {
+ test_sniff_classification_sup("test.bmp", mime::IMAGE_BMP);
+}
+
+#[test]
+fn test_sniff_gif87a() {
+ test_sniff_classification_sup("test87a", mime::IMAGE_GIF);
+}
+
+#[test]
+fn test_sniff_gif89a() {
+ test_sniff_classification_sup("test89a.gif", mime::IMAGE_GIF);
+}
+
+#[test]
+fn test_sniff_webp() {
+ test_sniff_classification_sup("test.webp", "image/webp".parse().unwrap());
+}
+
+#[test]
+fn test_sniff_png() {
+ test_sniff_classification_sup("test.png", mime::IMAGE_PNG);
+}
+
+#[test]
+fn test_sniff_jpg() {
+ test_sniff_classification_sup("test.jpg", mime::IMAGE_JPEG);
+}
+
+#[test]
+fn test_sniff_webm() {
+ test_sniff_classification_sup("test.webm", "video/webm".parse().unwrap());
+}
+
+#[test]
+fn test_sniff_mp4() {
+ test_sniff_classification_sup("test.mp4", "video/mp4".parse().unwrap());
+}
+
+#[test]
+fn test_sniff_avi() {
+ test_sniff_classification_sup("test.avi", "video/avi".parse().unwrap());
+}
+
+#[test]
+fn test_sniff_basic() {
+ test_sniff_classification_sup("test.au", "audio/basic".parse().unwrap());
+}
+
+#[test]
+fn test_sniff_aiff() {
+ test_sniff_classification_sup("test.aif", "audio/aiff".parse().unwrap());
+}
+
+#[test]
+fn test_sniff_mpeg() {
+ test_sniff_classification_sup("test.mp3", "audio/mpeg".parse().unwrap());
+}
+
+#[test]
+fn test_sniff_midi() {
+ test_sniff_classification_sup("test.mid", "audio/midi".parse().unwrap());
+}
+
+#[test]
+fn test_sniff_wave() {
+ test_sniff_classification_sup("test.wav", "audio/wave".parse().unwrap());
+}
+
+#[test]
+fn test_sniff_ogg() {
+ test_sniff_classification("small.ogg", "application/ogg".parse().unwrap(), None);
+ test_sniff_classification(
+ "small.ogg",
+ "application/ogg".parse().unwrap(),
+ Some("audio/".parse().unwrap()),
+ );
+}
+
+#[test]
+#[should_panic]
+fn test_sniff_vsn_ms_fontobject() {
+ test_sniff_classification_sup(
+ "vnd.ms-fontobject",
+ "application/vnd.ms-fontobject".parse().unwrap(),
+ );
+}
+
+#[test]
+#[should_panic]
+fn test_sniff_true_type() {
+ test_sniff_full(
+ &PathBuf::from("unknown/true_type.ttf"),
+ "(TrueType)/".parse().unwrap(),
+ None,
+ );
+}
+
+#[test]
+#[should_panic]
+fn test_sniff_open_type() {
+ test_sniff_full(
+ &PathBuf::from("unknown/open_type"),
+ "(OpenType)/".parse().unwrap(),
+ None,
+ );
+}
+
+#[test]
+#[should_panic]
+fn test_sniff_true_type_collection() {
+ test_sniff_full(
+ &PathBuf::from("unknown/true_type_collection.ttc"),
+ "(TrueType Collection)/".parse().unwrap(),
+ None,
+ );
+}
+
+#[test]
+#[should_panic]
+fn test_sniff_woff() {
+ test_sniff_classification_sup("test.wof", "application/font-woff".parse().unwrap());
+}
+
+#[test]
+fn test_sniff_gzip() {
+ test_sniff_classification("test.gz", "application/x-gzip".parse().unwrap(), None);
+}
+
+#[test]
+fn test_sniff_zip() {
+ test_sniff_classification("test.zip", "application/zip".parse().unwrap(), None);
+}
+
+#[test]
+fn test_sniff_rar() {
+ test_sniff_classification(
+ "test.rar",
+ "application/x-rar-compressed".parse().unwrap(),
+ None,
+ );
+}
+
+#[test]
+fn test_sniff_text_html_doctype_20() {
+ test_sniff_classification("text_html_doctype_20.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_doctype_20_u.html", mime::TEXT_HTML, None);
+}
+#[test]
+fn test_sniff_text_html_doctype_3e() {
+ test_sniff_classification("text_html_doctype_3e.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_doctype_3e_u.html", mime::TEXT_HTML, None);
+}
+
+#[test]
+fn test_sniff_text_html_page_20() {
+ test_sniff_classification("text_html_page_20.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_page_20_u.html", mime::TEXT_HTML, None);
+}
+
+#[test]
+fn test_sniff_text_html_page_3e() {
+ test_sniff_classification("text_html_page_3e.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_page_3e_u.html", mime::TEXT_HTML, None);
+}
+#[test]
+fn test_sniff_text_html_head_20() {
+ test_sniff_classification("text_html_head_20.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_head_20_u.html", mime::TEXT_HTML, None);
+}
+
+#[test]
+fn test_sniff_text_html_head_3e() {
+ test_sniff_classification("text_html_head_3e.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_head_3e_u.html", mime::TEXT_HTML, None);
+}
+#[test]
+fn test_sniff_text_html_script_20() {
+ test_sniff_classification("text_html_script_20.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_script_20_u.html", mime::TEXT_HTML, None);
+}
+
+#[test]
+fn test_sniff_text_html_script_3e() {
+ test_sniff_classification("text_html_script_3e.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_script_3e_u.html", mime::TEXT_HTML, None);
+}
+#[test]
+fn test_sniff_text_html_iframe_20() {
+ test_sniff_classification("text_html_iframe_20.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_iframe_20_u.html", mime::TEXT_HTML, None);
+}
+
+#[test]
+fn test_sniff_text_html_iframe_3e() {
+ test_sniff_classification("text_html_iframe_3e.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_iframe_3e_u.html", mime::TEXT_HTML, None);
+}
+#[test]
+fn test_sniff_text_html_h1_20() {
+ test_sniff_classification("text_html_h1_20.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_h1_20_u.html", mime::TEXT_HTML, None);
+}
+
+#[test]
+fn test_sniff_text_html_h1_3e() {
+ test_sniff_classification("text_html_h1_3e.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_h1_3e_u.html", mime::TEXT_HTML, None);
+}
+#[test]
+fn test_sniff_text_html_div_20() {
+ test_sniff_classification("text_html_div_20.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_div_20_u.html", mime::TEXT_HTML, None);
+}
+
+#[test]
+fn test_sniff_text_html_div_3e() {
+ test_sniff_classification("text_html_div_3e.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_div_3e_u.html", mime::TEXT_HTML, None);
+}
+#[test]
+fn test_sniff_text_html_font_20() {
+ test_sniff_classification("text_html_font_20.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_font_20_u.html", mime::TEXT_HTML, None);
+}
+
+#[test]
+fn test_sniff_text_html_font_3e() {
+ test_sniff_classification("text_html_font_3e.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_font_3e_u.html", mime::TEXT_HTML, None);
+}
+#[test]
+fn test_sniff_text_html_table_20() {
+ test_sniff_classification("text_html_table_20.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_table_20_u.html", mime::TEXT_HTML, None);
+}
+
+#[test]
+fn test_sniff_text_html_table_3e() {
+ test_sniff_classification("text_html_table_3e.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_table_3e_u.html", mime::TEXT_HTML, None);
+}
+#[test]
+fn test_sniff_text_html_a_20() {
+ test_sniff_classification("text_html_a_20.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_a_20_u.html", mime::TEXT_HTML, None);
+}
+
+#[test]
+fn test_sniff_text_html_a_3e() {
+ test_sniff_classification("text_html_a_3e.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_a_3e_u.html", mime::TEXT_HTML, None);
+}
+#[test]
+fn test_sniff_text_html_style_20() {
+ test_sniff_classification("text_html_style_20.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_style_20_u.html", mime::TEXT_HTML, None);
+}
+
+#[test]
+fn test_sniff_text_html_style_3e() {
+ test_sniff_classification("text_html_style_3e.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_style_3e_u.html", mime::TEXT_HTML, None);
+}
+#[test]
+fn test_sniff_text_html_title_20() {
+ test_sniff_classification("text_html_title_20.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_title_20_u.html", mime::TEXT_HTML, None);
+}
+
+#[test]
+fn test_sniff_text_html_title_3e() {
+ test_sniff_classification("text_html_title_3e.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_title_3e_u.html", mime::TEXT_HTML, None);
+}
+#[test]
+fn test_sniff_text_html_b_20() {
+ test_sniff_classification("text_html_b_20.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_b_20_u.html", mime::TEXT_HTML, None);
+}
+
+#[test]
+fn test_sniff_text_html_b_3e() {
+ test_sniff_classification("text_html_b_3e.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_b_3e_u.html", mime::TEXT_HTML, None);
+}
+#[test]
+fn test_sniff_text_html_body_20() {
+ test_sniff_classification("text_html_body_20.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_body_20_u.html", mime::TEXT_HTML, None);
+}
+
+#[test]
+fn test_sniff_text_html_body_3e() {
+ test_sniff_classification("text_html_body_3e.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_body_3e_u.html", mime::TEXT_HTML, None);
+}
+#[test]
+fn test_sniff_text_html_br_20() {
+ test_sniff_classification("text_html_br_20.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_br_20_u.html", mime::TEXT_HTML, None);
+}
+
+#[test]
+fn test_sniff_text_html_br_3e() {
+ test_sniff_classification("text_html_br_3e.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_br_3e_u.html", mime::TEXT_HTML, None);
+}
+#[test]
+fn test_sniff_text_html_p_20() {
+ test_sniff_classification("text_html_p_20.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_p_20_u.html", mime::TEXT_HTML, None);
+}
+#[test]
+fn test_sniff_text_html_p_3e() {
+ test_sniff_classification("text_html_p_3e.html", mime::TEXT_HTML, None);
+ test_sniff_classification("text_html_p_3e_u.html", mime::TEXT_HTML, None);
+}
+
+#[test]
+fn test_sniff_text_html_comment_20() {
+ test_sniff_classification("text_html_comment_20.html", mime::TEXT_HTML, None);
+}
+
+#[test]
+fn test_sniff_text_html_comment_3e() {
+ test_sniff_classification("text_html_comment_3e.html", mime::TEXT_HTML, None);
+}
+
+#[test]
+fn test_sniff_xml() {
+ test_sniff_classification("test.xml", mime::TEXT_XML, None);
+}
+
+#[test]
+fn test_sniff_pdf() {
+ test_sniff_classification("test.pdf", mime::APPLICATION_PDF, None);
+}
+
+#[test]
+fn test_sniff_postscript() {
+ test_sniff_classification("test.ps", "application/postscript".parse().unwrap(), None);
+}
+
+#[test]
+fn test_sniff_utf_16be_bom() {
+ test_sniff_classification("utf16bebom.txt", mime::TEXT_PLAIN, None);
+}
+
+#[test]
+fn test_sniff_utf_16le_bom() {
+ test_sniff_classification("utf16lebom.txt", mime::TEXT_PLAIN, None);
+}
+
+#[test]
+fn test_sniff_utf_8_bom() {
+ test_sniff_classification("utf8bom.txt", mime::TEXT_PLAIN, None);
+}
+
+#[test]
+fn test_sniff_rss_feed() {
+ // RSS feeds
+ test_sniff_full(
+ &PathBuf::from("text/xml/feed.rss"),
+ "application/rss+xml".parse().unwrap(),
+ Some(mime::TEXT_HTML),
+ );
+ test_sniff_full(
+ &PathBuf::from("text/xml/rdf_rss.xml"),
+ "application/rss+xml".parse().unwrap(),
+ Some(mime::TEXT_HTML),
+ );
+ // Not RSS feeds
+ test_sniff_full(
+ &PathBuf::from("text/xml/rdf_rss_ko_1.xml"),
+ mime::TEXT_HTML,
+ Some(mime::TEXT_HTML),
+ );
+ test_sniff_full(
+ &PathBuf::from("text/xml/rdf_rss_ko_2.xml"),
+ mime::TEXT_HTML,
+ Some(mime::TEXT_HTML),
+ );
+ test_sniff_full(
+ &PathBuf::from("text/xml/rdf_rss_ko_3.xml"),
+ mime::TEXT_HTML,
+ Some(mime::TEXT_HTML),
+ );
+ test_sniff_full(
+ &PathBuf::from("text/xml/rdf_rss_ko_4.xml"),
+ mime::TEXT_HTML,
+ Some(mime::TEXT_HTML),
+ );
+}
+
+#[test]
+fn test_sniff_atom_feed() {
+ test_sniff_full(
+ &PathBuf::from("text/xml/feed.atom"),
+ "application/atom+xml".parse().unwrap(),
+ Some(mime::TEXT_HTML),
+ );
+}
+
+#[test]
+fn test_sniff_binary_file() {
+ test_sniff_full(
+ &PathBuf::from("unknown/binary_file"),
+ mime::APPLICATION_OCTET_STREAM,
+ None,
+ );
+}
+
+#[test]
+fn test_sniff_atom_feed_with_no_sniff_flag_on() {
+ test_sniff_with_flags(
+ &PathBuf::from("text/xml/feed.atom"),
+ mime::TEXT_HTML,
+ Some(mime::TEXT_HTML),
+ NoSniffFlag::On,
+ ApacheBugFlag::Off,
+ );
+}
+
+#[test]
+fn test_sniff_with_no_sniff_flag_on_and_apache_flag_on() {
+ test_sniff_with_flags(
+ &PathBuf::from("text/xml/feed.atom"),
+ mime::TEXT_HTML,
+ Some(mime::TEXT_HTML),
+ NoSniffFlag::On,
+ ApacheBugFlag::On,
+ );
+}
+
+#[test]
+fn test_sniff_utf_8_bom_with_apache_flag_on() {
+ test_sniff_with_flags(
+ &PathBuf::from("text/plain/utf8bom.txt"),
+ mime::TEXT_PLAIN,
+ Some("dummy/text".parse().unwrap()),
+ NoSniffFlag::Off,
+ ApacheBugFlag::On,
+ );
+}
+
+#[test]
+fn test_sniff_utf_16be_bom_with_apache_flag_on() {
+ test_sniff_with_flags(
+ &PathBuf::from("text/plain/utf16bebom.txt"),
+ mime::TEXT_PLAIN,
+ Some("dummy/text".parse().unwrap()),
+ NoSniffFlag::Off,
+ ApacheBugFlag::On,
+ );
+}
+
+#[test]
+fn test_sniff_utf_16le_bom_with_apache_flag_on() {
+ test_sniff_with_flags(
+ &PathBuf::from("text/plain/utf16lebom.txt"),
+ mime::TEXT_PLAIN,
+ Some("dummy/text".parse().unwrap()),
+ NoSniffFlag::Off,
+ ApacheBugFlag::On,
+ );
+}
+
+#[test]
+fn test_sniff_octet_stream_apache_flag_on() {
+ test_sniff_with_flags(
+ &PathBuf::from("unknown/binary_file"),
+ mime::APPLICATION_OCTET_STREAM,
+ Some("dummy/binary".parse().unwrap()),
+ NoSniffFlag::Off,
+ ApacheBugFlag::On,
+ );
+}
+
+#[test]
+fn test_sniff_mp4_video_apache_flag_on() {
+ test_sniff_with_flags(
+ &PathBuf::from("video/mp4/test.mp4"),
+ mime::APPLICATION_OCTET_STREAM,
+ Some("video/mp4".parse().unwrap()),
+ NoSniffFlag::Off,
+ ApacheBugFlag::On,
+ );
+}
diff --git a/components/shared/net/tests/parsable_mime/application/font-woff/test.wof b/components/shared/net/tests/parsable_mime/application/font-woff/test.wof
new file mode 100755
index 00000000000..a1393ebee1d
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/application/font-woff/test.wof
@@ -0,0 +1 @@
+wOFF \ No newline at end of file
diff --git a/components/shared/net/tests/parsable_mime/application/ogg/small.ogg b/components/shared/net/tests/parsable_mime/application/ogg/small.ogg
new file mode 100644
index 00000000000..0d7f43eb795
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/application/ogg/small.ogg
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/application/pdf/test.pdf b/components/shared/net/tests/parsable_mime/application/pdf/test.pdf
new file mode 100644
index 00000000000..055169fe34b
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/application/pdf/test.pdf
@@ -0,0 +1,157 @@
+%PDF-1.2
+%
+
+9 0 obj
+<<
+/Length 10 0 R
+/Filter /FlateDecode
+>>
+stream
+H͐J0 {f$Mn-[&jeۤ ~$}ɅIjs~X-],$Y)'Nu1!V??
+b1Rbb҉H[TD:#&حXi$qnf]a{أq|JLs]QIj%9`঺Uitez$OeBĒүR@zܗg<
+endstream
+endobj
+10 0 obj
+246
+endobj
+4 0 obj
+<<
+/Type /Page
+/Parent 5 0 R
+/Resources <<
+/Font <<
+/F0 6 0 R
+/F1 7 0 R
+>>
+/ProcSet 2 0 R
+>>
+/Contents 9 0 R
+>>
+endobj
+6 0 obj
+<<
+/Type /Font
+/Subtype /TrueType
+/Name /F0
+/BaseFont /Arial
+/Encoding /WinAnsiEncoding
+>>
+endobj
+7 0 obj
+<<
+/Type /Font
+/Subtype /TrueType
+/Name /F1
+/BaseFont /BookAntiqua,Bold
+/FirstChar 31
+/LastChar 255
+/Widths [ 750 250 278 402 606 500 889 833 227 333 333 444 606 250 333 250
+296 500 500 500 500 500 500 500 500 500 500 250 250 606 606 606
+444 747 778 667 722 833 611 556 833 833 389 389 778 611 1000 833
+833 611 833 722 611 667 778 778 1000 667 667 667 333 606 333 606
+500 333 500 611 444 611 500 389 556 611 333 333 611 333 889 611
+556 611 611 389 444 333 611 556 833 500 556 500 310 606 310 606
+750 500 750 333 500 500 1000 500 500 333 1000 611 389 1000 750 750
+750 750 278 278 500 500 606 500 1000 333 998 444 389 833 750 750
+667 250 278 500 500 606 500 606 500 333 747 438 500 606 333 747
+500 400 549 361 361 333 576 641 250 333 361 488 500 889 890 889
+444 778 778 778 778 778 778 1000 722 611 611 611 611 389 389 389
+389 833 833 833 833 833 833 833 606 833 778 778 778 778 667 611
+611 500 500 500 500 500 500 778 444 500 500 500 500 333 333 333
+333 556 611 556 556 556 556 556 549 556 611 611 611 611 556 611
+556 ]
+/Encoding /WinAnsiEncoding
+/FontDescriptor 8 0 R
+>>
+endobj
+8 0 obj
+<<
+/Type /FontDescriptor
+/FontName /BookAntiqua,Bold
+/Flags 16418
+/FontBBox [ -250 -260 1236 930 ]
+/MissingWidth 750
+/StemV 146
+/StemH 146
+/ItalicAngle 0
+/CapHeight 930
+/XHeight 651
+/Ascent 930
+/Descent 260
+/Leading 210
+/MaxWidth 1030
+/AvgWidth 460
+>>
+endobj
+2 0 obj
+[ /PDF /Text ]
+endobj
+5 0 obj
+<<
+/Kids [4 0 R ]
+/Count 1
+/Type /Pages
+/MediaBox [ 0 0 612 792 ]
+>>
+endobj
+1 0 obj
+<<
+/Creator (1725.fm)
+/CreationDate (1-Jan-3 18:15PM)
+/Title (1725.PDF)
+/Author (Unknown)
+/Producer (Acrobat PDFWriter 3.02 for Windows)
+/Keywords ()
+/Subject ()
+>>
+endobj
+3 0 obj
+<<
+/Pages 5 0 R
+/Type /Catalog
+/DefaultGray 11 0 R
+/DefaultRGB 12 0 R
+>>
+endobj
+11 0 obj
+[/CalGray
+<<
+/WhitePoint [0.9505 1 1.0891 ]
+/Gamma 0.2468
+>>
+]
+endobj
+12 0 obj
+[/CalRGB
+<<
+/WhitePoint [0.9505 1 1.0891 ]
+/Gamma [0.2468 0.2468 0.2468 ]
+/Matrix [0.4361 0.2225 0.0139 0.3851 0.7169 0.0971 0.1431 0.0606 0.7141 ]
+>>
+]
+endobj
+xref
+0 13
+0000000000 65535 f
+0000002172 00000 n
+0000002046 00000 n
+0000002363 00000 n
+0000000375 00000 n
+0000002080 00000 n
+0000000518 00000 n
+0000000633 00000 n
+0000001760 00000 n
+0000000021 00000 n
+0000000352 00000 n
+0000002460 00000 n
+0000002548 00000 n
+trailer
+<<
+/Size 13
+/Root 3 0 R
+/Info 1 0 R
+/ID [<47149510433dd4882f05f8c124223734><47149510433dd4882f05f8c124223734>]
+>>
+startxref
+2726
+%%EOF
diff --git a/components/shared/net/tests/parsable_mime/application/postscript/test.ps b/components/shared/net/tests/parsable_mime/application/postscript/test.ps
new file mode 100755
index 00000000000..c273ffa3f0f
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/application/postscript/test.ps
@@ -0,0 +1 @@
+%!PS-Adobe- \ No newline at end of file
diff --git a/components/shared/net/tests/parsable_mime/application/vnd.ms-fontobject/vnd.ms-fontobject b/components/shared/net/tests/parsable_mime/application/vnd.ms-fontobject/vnd.ms-fontobject
new file mode 100755
index 00000000000..1b84f4c37c1
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/application/vnd.ms-fontobject/vnd.ms-fontobject
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/application/x-gzip/test.gz b/components/shared/net/tests/parsable_mime/application/x-gzip/test.gz
new file mode 100644
index 00000000000..3b99b73e6f0
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/application/x-gzip/test.gz
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/application/x-rar-compressed/test.rar b/components/shared/net/tests/parsable_mime/application/x-rar-compressed/test.rar
new file mode 100755
index 00000000000..920bd4d8a8c
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/application/x-rar-compressed/test.rar
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/application/zip/test.zip b/components/shared/net/tests/parsable_mime/application/zip/test.zip
new file mode 100755
index 00000000000..5c74c9658c6
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/application/zip/test.zip
@@ -0,0 +1 @@
+PK \ No newline at end of file
diff --git a/components/shared/net/tests/parsable_mime/audio/aiff/test.aif b/components/shared/net/tests/parsable_mime/audio/aiff/test.aif
new file mode 100644
index 00000000000..ad2e35df40b
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/audio/aiff/test.aif
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/audio/basic/test.au b/components/shared/net/tests/parsable_mime/audio/basic/test.au
new file mode 100644
index 00000000000..d4e53deb74a
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/audio/basic/test.au
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/audio/midi/test.mid b/components/shared/net/tests/parsable_mime/audio/midi/test.mid
new file mode 100644
index 00000000000..a52838c62bc
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/audio/midi/test.mid
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/audio/mpeg/test.mp3 b/components/shared/net/tests/parsable_mime/audio/mpeg/test.mp3
new file mode 100644
index 00000000000..50786790311
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/audio/mpeg/test.mp3
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/audio/wave/test.wav b/components/shared/net/tests/parsable_mime/audio/wave/test.wav
new file mode 100644
index 00000000000..f96276c063c
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/audio/wave/test.wav
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/image/bmp/test.bmp b/components/shared/net/tests/parsable_mime/image/bmp/test.bmp
new file mode 100644
index 00000000000..8a1b10bae5e
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/image/bmp/test.bmp
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/image/gif/test87a b/components/shared/net/tests/parsable_mime/image/gif/test87a
new file mode 100644
index 00000000000..8d49c776420
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/image/gif/test87a
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/image/gif/test89a.gif b/components/shared/net/tests/parsable_mime/image/gif/test89a.gif
new file mode 100644
index 00000000000..0e2995e0821
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/image/gif/test89a.gif
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/image/jpeg/test.jpg b/components/shared/net/tests/parsable_mime/image/jpeg/test.jpg
new file mode 100644
index 00000000000..7f758f65d13
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/image/jpeg/test.jpg
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/image/png/test.png b/components/shared/net/tests/parsable_mime/image/png/test.png
new file mode 100644
index 00000000000..cc81374d4f5
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/image/png/test.png
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/image/webp/test.webp b/components/shared/net/tests/parsable_mime/image/webp/test.webp
new file mode 100755
index 00000000000..ad88e62f94c
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/image/webp/test.webp
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/image/x-icon/test.ico b/components/shared/net/tests/parsable_mime/image/x-icon/test.ico
new file mode 100644
index 00000000000..a2d0ee49098
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/image/x-icon/test.ico
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/image/x-icon/test_cursor.ico b/components/shared/net/tests/parsable_mime/image/x-icon/test_cursor.ico
new file mode 100644
index 00000000000..6029d6684d5
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/image/x-icon/test_cursor.ico
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_a_20.html b/components/shared/net/tests/parsable_mime/text/html/text_html_a_20.html
new file mode 100644
index 00000000000..1b9619279a7
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_a_20.html
@@ -0,0 +1,3 @@
+
+
+ <A
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_a_20_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_a_20_u.html
new file mode 100644
index 00000000000..887a1280650
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_a_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <a
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_a_3e.html b/components/shared/net/tests/parsable_mime/text/html/text_html_a_3e.html
new file mode 100644
index 00000000000..610cd08fea4
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_a_3e.html
@@ -0,0 +1,3 @@
+
+
+ <A>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_a_3e_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_a_3e_u.html
new file mode 100644
index 00000000000..48528fdf341
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_a_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <a>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_b_20.html b/components/shared/net/tests/parsable_mime/text/html/text_html_b_20.html
new file mode 100644
index 00000000000..5977d2eeaab
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_b_20.html
@@ -0,0 +1,3 @@
+
+
+ <B
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_b_20_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_b_20_u.html
new file mode 100644
index 00000000000..a8a963b95f0
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_b_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <b
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_b_3e.html b/components/shared/net/tests/parsable_mime/text/html/text_html_b_3e.html
new file mode 100644
index 00000000000..dc79cd5d568
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_b_3e.html
@@ -0,0 +1,3 @@
+
+
+ <B>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_b_3e_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_b_3e_u.html
new file mode 100644
index 00000000000..0d72d281aec
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_b_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <b>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_body_20.html b/components/shared/net/tests/parsable_mime/text/html/text_html_body_20.html
new file mode 100644
index 00000000000..c72b1ad3bec
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_body_20.html
@@ -0,0 +1,3 @@
+
+
+ <BODY
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_body_20_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_body_20_u.html
new file mode 100644
index 00000000000..1d76ebb0f47
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_body_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <body
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_body_3e.html b/components/shared/net/tests/parsable_mime/text/html/text_html_body_3e.html
new file mode 100644
index 00000000000..4a66f59ef95
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_body_3e.html
@@ -0,0 +1,3 @@
+
+
+ <BODY>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_body_3e_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_body_3e_u.html
new file mode 100644
index 00000000000..b431695f3ab
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_body_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <body>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_br_20.html b/components/shared/net/tests/parsable_mime/text/html/text_html_br_20.html
new file mode 100644
index 00000000000..d04df680012
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_br_20.html
@@ -0,0 +1,3 @@
+
+
+ <BR
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_br_20_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_br_20_u.html
new file mode 100644
index 00000000000..1c0f0ce13ba
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_br_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <br
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_br_3e.html b/components/shared/net/tests/parsable_mime/text/html/text_html_br_3e.html
new file mode 100644
index 00000000000..1d40ef06566
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_br_3e.html
@@ -0,0 +1,3 @@
+
+
+ <BR>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_br_3e_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_br_3e_u.html
new file mode 100644
index 00000000000..c4eae116f03
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_br_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <br>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_comment_20.html b/components/shared/net/tests/parsable_mime/text/html/text_html_comment_20.html
new file mode 100644
index 00000000000..e9612efc73c
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_comment_20.html
@@ -0,0 +1,3 @@
+
+
+ <!--
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_comment_20_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_comment_20_u.html
new file mode 100644
index 00000000000..e9612efc73c
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_comment_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <!--
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_comment_3e.html b/components/shared/net/tests/parsable_mime/text/html/text_html_comment_3e.html
new file mode 100644
index 00000000000..44a94ca5a7a
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_comment_3e.html
@@ -0,0 +1,3 @@
+
+
+ <!-->
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_comment_3e_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_comment_3e_u.html
new file mode 100644
index 00000000000..44a94ca5a7a
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_comment_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <!-->
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_div_20.html b/components/shared/net/tests/parsable_mime/text/html/text_html_div_20.html
new file mode 100644
index 00000000000..2ed34363b2f
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_div_20.html
@@ -0,0 +1,3 @@
+
+
+ <DIV
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_div_20_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_div_20_u.html
new file mode 100644
index 00000000000..b98886efd83
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_div_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <div
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_div_3e.html b/components/shared/net/tests/parsable_mime/text/html/text_html_div_3e.html
new file mode 100644
index 00000000000..ccf4ca8d70a
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_div_3e.html
@@ -0,0 +1,3 @@
+
+
+ <DIV>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_div_3e_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_div_3e_u.html
new file mode 100644
index 00000000000..c117f0f4cdd
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_div_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <div>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_doctype_20.html b/components/shared/net/tests/parsable_mime/text/html/text_html_doctype_20.html
new file mode 100644
index 00000000000..dbeb5a41c2a
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_doctype_20.html
@@ -0,0 +1,3 @@
+
+
+ <!DOCTYPE HTML
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_doctype_20_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_doctype_20_u.html
new file mode 100644
index 00000000000..acede44dffb
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_doctype_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <!doctype html
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_doctype_3e.html b/components/shared/net/tests/parsable_mime/text/html/text_html_doctype_3e.html
new file mode 100644
index 00000000000..6a22ea8b978
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_doctype_3e.html
@@ -0,0 +1,4 @@
+
+
+ <!DOCTYPE HTML>
+
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_doctype_3e_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_doctype_3e_u.html
new file mode 100644
index 00000000000..8b16e40458e
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_doctype_3e_u.html
@@ -0,0 +1,4 @@
+
+
+ <!doctype html>
+
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_font_20.html b/components/shared/net/tests/parsable_mime/text/html/text_html_font_20.html
new file mode 100644
index 00000000000..a18fa850617
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_font_20.html
@@ -0,0 +1,3 @@
+
+
+ <FONT
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_font_20_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_font_20_u.html
new file mode 100644
index 00000000000..6a31d2a8aba
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_font_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <font
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_font_3e.html b/components/shared/net/tests/parsable_mime/text/html/text_html_font_3e.html
new file mode 100644
index 00000000000..3605840fc5a
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_font_3e.html
@@ -0,0 +1,3 @@
+
+
+ <FONT>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_font_3e_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_font_3e_u.html
new file mode 100644
index 00000000000..1181517947b
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_font_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <font>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_h1_20.html b/components/shared/net/tests/parsable_mime/text/html/text_html_h1_20.html
new file mode 100644
index 00000000000..3ed0eb125ff
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_h1_20.html
@@ -0,0 +1,3 @@
+
+
+ <H1
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_h1_20_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_h1_20_u.html
new file mode 100644
index 00000000000..f517b61487e
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_h1_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <h1
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_h1_3e.html b/components/shared/net/tests/parsable_mime/text/html/text_html_h1_3e.html
new file mode 100644
index 00000000000..af0bf8c56b9
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_h1_3e.html
@@ -0,0 +1,3 @@
+
+
+ <H1>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_h1_3e_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_h1_3e_u.html
new file mode 100644
index 00000000000..bae85229fcf
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_h1_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <h1>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_head_20.html b/components/shared/net/tests/parsable_mime/text/html/text_html_head_20.html
new file mode 100644
index 00000000000..eb322c946e0
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_head_20.html
@@ -0,0 +1,3 @@
+
+
+ <HEAD
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_head_20_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_head_20_u.html
new file mode 100644
index 00000000000..899655a5a2c
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_head_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <head
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_head_3e.html b/components/shared/net/tests/parsable_mime/text/html/text_html_head_3e.html
new file mode 100644
index 00000000000..058c7dce4a9
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_head_3e.html
@@ -0,0 +1,3 @@
+
+
+ <HEAD>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_head_3e_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_head_3e_u.html
new file mode 100644
index 00000000000..8a33d623daa
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_head_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <head>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_iframe_20.html b/components/shared/net/tests/parsable_mime/text/html/text_html_iframe_20.html
new file mode 100644
index 00000000000..e632915590a
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_iframe_20.html
@@ -0,0 +1,3 @@
+
+
+ <IFRAME
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_iframe_20_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_iframe_20_u.html
new file mode 100644
index 00000000000..527a06e415c
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_iframe_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <iframe
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_iframe_3e.html b/components/shared/net/tests/parsable_mime/text/html/text_html_iframe_3e.html
new file mode 100644
index 00000000000..9db0efd47d4
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_iframe_3e.html
@@ -0,0 +1,3 @@
+
+
+ <IFRAME>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_iframe_3e_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_iframe_3e_u.html
new file mode 100644
index 00000000000..e3512c8a5c2
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_iframe_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <iframe>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_p_20.html b/components/shared/net/tests/parsable_mime/text/html/text_html_p_20.html
new file mode 100644
index 00000000000..a099441be2b
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_p_20.html
@@ -0,0 +1,3 @@
+
+
+ <P
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_p_20_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_p_20_u.html
new file mode 100644
index 00000000000..ff4befbde7b
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_p_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <p
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_p_3e.html b/components/shared/net/tests/parsable_mime/text/html/text_html_p_3e.html
new file mode 100644
index 00000000000..98db18913d0
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_p_3e.html
@@ -0,0 +1,3 @@
+
+
+ <P>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_p_3e_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_p_3e_u.html
new file mode 100644
index 00000000000..9d99a59ed08
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_p_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <p>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_page_20.html b/components/shared/net/tests/parsable_mime/text/html/text_html_page_20.html
new file mode 100644
index 00000000000..bb1c4572b25
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_page_20.html
@@ -0,0 +1,3 @@
+
+
+ <HTML
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_page_20_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_page_20_u.html
new file mode 100644
index 00000000000..b3300d9f4e4
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_page_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <html
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_page_3e.html b/components/shared/net/tests/parsable_mime/text/html/text_html_page_3e.html
new file mode 100644
index 00000000000..e6a49c51924
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_page_3e.html
@@ -0,0 +1,3 @@
+
+
+ <HTML>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_page_3e_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_page_3e_u.html
new file mode 100644
index 00000000000..2b8ee203d25
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_page_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <html>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_script_20.html b/components/shared/net/tests/parsable_mime/text/html/text_html_script_20.html
new file mode 100644
index 00000000000..620c629266c
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_script_20.html
@@ -0,0 +1,3 @@
+
+
+ <SCRIPT
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_script_20_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_script_20_u.html
new file mode 100644
index 00000000000..bd2c58e676c
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_script_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <script
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_script_3e.html b/components/shared/net/tests/parsable_mime/text/html/text_html_script_3e.html
new file mode 100644
index 00000000000..d59535f70cd
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_script_3e.html
@@ -0,0 +1,3 @@
+
+
+ <SCRIPT>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_script_3e_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_script_3e_u.html
new file mode 100644
index 00000000000..625c13820f4
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_script_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <script>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_style_20.html b/components/shared/net/tests/parsable_mime/text/html/text_html_style_20.html
new file mode 100644
index 00000000000..57bc2a1ecd7
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_style_20.html
@@ -0,0 +1,3 @@
+
+
+ <STYLE
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_style_20_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_style_20_u.html
new file mode 100644
index 00000000000..8163eca3c60
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_style_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <style
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_style_3e.html b/components/shared/net/tests/parsable_mime/text/html/text_html_style_3e.html
new file mode 100644
index 00000000000..229d5f951bd
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_style_3e.html
@@ -0,0 +1,3 @@
+
+
+ <STYLE>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_style_3e_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_style_3e_u.html
new file mode 100644
index 00000000000..12d686e4953
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_style_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <style>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_table_20.html b/components/shared/net/tests/parsable_mime/text/html/text_html_table_20.html
new file mode 100644
index 00000000000..27cccc6acd6
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_table_20.html
@@ -0,0 +1,3 @@
+
+
+ <TABLE
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_table_20_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_table_20_u.html
new file mode 100644
index 00000000000..556b46e7fc4
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_table_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <table
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_table_3e.html b/components/shared/net/tests/parsable_mime/text/html/text_html_table_3e.html
new file mode 100644
index 00000000000..351ee543af8
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_table_3e.html
@@ -0,0 +1,3 @@
+
+
+ <TABLE>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_table_3e_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_table_3e_u.html
new file mode 100644
index 00000000000..6259870bfcf
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_table_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <table>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_title_20.html b/components/shared/net/tests/parsable_mime/text/html/text_html_title_20.html
new file mode 100644
index 00000000000..f7d151658d9
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_title_20.html
@@ -0,0 +1,3 @@
+
+
+ <TITLE
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_title_20_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_title_20_u.html
new file mode 100644
index 00000000000..03a072d8ac0
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_title_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <title
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_title_3e.html b/components/shared/net/tests/parsable_mime/text/html/text_html_title_3e.html
new file mode 100644
index 00000000000..fedf57b9e4f
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_title_3e.html
@@ -0,0 +1,3 @@
+
+
+ <TITLE>
diff --git a/components/shared/net/tests/parsable_mime/text/html/text_html_title_3e_u.html b/components/shared/net/tests/parsable_mime/text/html/text_html_title_3e_u.html
new file mode 100644
index 00000000000..5fbf8a75c47
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/html/text_html_title_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <title>
diff --git a/components/shared/net/tests/parsable_mime/text/plain/utf16bebom.txt b/components/shared/net/tests/parsable_mime/text/plain/utf16bebom.txt
new file mode 100644
index 00000000000..9fb50d49fb8
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/plain/utf16bebom.txt
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/text/plain/utf16lebom.txt b/components/shared/net/tests/parsable_mime/text/plain/utf16lebom.txt
new file mode 100644
index 00000000000..d79d81725ec
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/plain/utf16lebom.txt
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/text/plain/utf8bom.txt b/components/shared/net/tests/parsable_mime/text/plain/utf8bom.txt
new file mode 100644
index 00000000000..56ad8a265ef
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/plain/utf8bom.txt
@@ -0,0 +1 @@
+ test_file
diff --git a/components/shared/net/tests/parsable_mime/text/xml/feed.atom b/components/shared/net/tests/parsable_mime/text/xml/feed.atom
new file mode 100755
index 00000000000..893c3f27a8e
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/xml/feed.atom
@@ -0,0 +1 @@
+<feed>
diff --git a/components/shared/net/tests/parsable_mime/text/xml/feed.rss b/components/shared/net/tests/parsable_mime/text/xml/feed.rss
new file mode 100644
index 00000000000..57ea10d5b4e
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/xml/feed.rss
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="windows-1252"?>
+<rss version="2.0">
+ <channel>
+ <title>FeedForAll Sample Feed</title>
+ <description>RSS is a fascinating technology. The uses for RSS are expanding daily. Take a closer look at how various industries are using the benefits of RSS in their businesses.</description>
+ <link>http://www.feedforall.com/industry-solutions.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <copyright>Copyright 2004 NotePage, Inc.</copyright>
+ <docs>http://blogs.law.harvard.edu/tech/rss</docs>
+ <language>en-us</language>
+ <lastBuildDate>Tue, 19 Oct 2004 13:39:14 -0400</lastBuildDate>
+ <managingEditor>marketing@feedforall.com</managingEditor>
+ <pubDate>Tue, 19 Oct 2004 13:38:55 -0400</pubDate>
+ <webMaster>webmaster@feedforall.com</webMaster>
+ <generator>FeedForAll Beta1 (0.0.1.8)</generator>
+ <image>
+ <url>http://www.feedforall.com/ffalogo48x48.gif</url>
+ <title>FeedForAll Sample Feed</title>
+ <link>http://www.feedforall.com/industry-solutions.htm</link>
+ <description>FeedForAll Sample Feed</description>
+ <width>48</width>
+ <height>48</height>
+ </image>
+ <item>
+ <title>RSS Solutions for Restaurants</title>
+ <description>&lt;b&gt;FeedForAll &lt;/b&gt;helps Restaurant&apos;s communicate with customers. Let your customers know the latest specials or events.&lt;br&gt;
+&lt;br&gt;
+RSS feed uses include:&lt;br&gt;
+&lt;i&gt;&lt;font color=&quot;#FF0000&quot;&gt;Daily Specials &lt;br&gt;
+Entertainment &lt;br&gt;
+Calendar of Events &lt;/i&gt;&lt;/font&gt;</description>
+ <link>http://www.feedforall.com/restaurant.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <comments>http://www.feedforall.com/forum</comments>
+ <pubDate>Tue, 19 Oct 2004 11:09:11 -0400</pubDate>
+ </item>
+ <item>
+ <title>RSS Solutions for Schools and Colleges</title>
+ <description>FeedForAll helps Educational Institutions communicate with students about school wide activities, events, and schedules.&lt;br&gt;
+&lt;br&gt;
+RSS feed uses include:&lt;br&gt;
+&lt;i&gt;&lt;font color=&quot;#0000FF&quot;&gt;Homework Assignments &lt;br&gt;
+School Cancellations &lt;br&gt;
+Calendar of Events &lt;br&gt;
+Sports Scores &lt;br&gt;
+Clubs/Organization Meetings &lt;br&gt;
+Lunches Menus &lt;/i&gt;&lt;/font&gt;</description>
+ <link>http://www.feedforall.com/schools.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <comments>http://www.feedforall.com/forum</comments>
+ <pubDate>Tue, 19 Oct 2004 11:09:09 -0400</pubDate>
+ </item>
+ <item>
+ <title>RSS Solutions for Computer Service Companies</title>
+ <description>FeedForAll helps Computer Service Companies communicate with clients about cyber security and related issues. &lt;br&gt;
+&lt;br&gt;
+Uses include:&lt;br&gt;
+&lt;i&gt;&lt;font color=&quot;#0000FF&quot;&gt;Cyber Security Alerts &lt;br&gt;
+Specials&lt;br&gt;
+Job Postings &lt;/i&gt;&lt;/font&gt;</description>
+ <link>http://www.feedforall.com/computer-service.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <comments>http://www.feedforall.com/forum</comments>
+ <pubDate>Tue, 19 Oct 2004 11:09:07 -0400</pubDate>
+ </item>
+ <item>
+ <title>RSS Solutions for Governments</title>
+ <description>FeedForAll helps Governments communicate with the general public about positions on various issues, and keep the community aware of changes in important legislative issues. &lt;b&gt;&lt;i&gt;&lt;br&gt;
+&lt;/b&gt;&lt;/i&gt;&lt;br&gt;
+RSS uses Include:&lt;br&gt;
+&lt;i&gt;&lt;font color=&quot;#00FF00&quot;&gt;Legislative Calendar&lt;br&gt;
+Votes&lt;br&gt;
+Bulletins&lt;/i&gt;&lt;/font&gt;</description>
+ <link>http://www.feedforall.com/government.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <comments>http://www.feedforall.com/forum</comments>
+ <pubDate>Tue, 19 Oct 2004 11:09:05 -0400</pubDate>
+ </item>
+ <item>
+ <title>RSS Solutions for Politicians</title>
+ <description>FeedForAll helps Politicians communicate with the general public about positions on various issues, and keep the community notified of their schedule. &lt;br&gt;
+&lt;br&gt;
+Uses Include:&lt;br&gt;
+&lt;i&gt;&lt;font color=&quot;#FF0000&quot;&gt;Blogs&lt;br&gt;
+Speaking Engagements &lt;br&gt;
+Statements&lt;br&gt;
+ &lt;/i&gt;&lt;/font&gt;</description>
+ <link>http://www.feedforall.com/politics.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <comments>http://www.feedforall.com/forum</comments>
+ <pubDate>Tue, 19 Oct 2004 11:09:03 -0400</pubDate>
+ </item>
+ <item>
+ <title>RSS Solutions for Meteorologists</title>
+ <description>FeedForAll helps Meteorologists communicate with the general public about storm warnings and weather alerts, in specific regions. Using RSS meteorologists are able to quickly disseminate urgent and life threatening weather warnings. &lt;br&gt;
+&lt;br&gt;
+Uses Include:&lt;br&gt;
+&lt;i&gt;&lt;font color=&quot;#0000FF&quot;&gt;Weather Alerts&lt;br&gt;
+Plotting Storms&lt;br&gt;
+School Cancellations &lt;/i&gt;&lt;/font&gt;</description>
+ <link>http://www.feedforall.com/weather.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <comments>http://www.feedforall.com/forum</comments>
+ <pubDate>Tue, 19 Oct 2004 11:09:01 -0400</pubDate>
+ </item>
+ <item>
+ <title>RSS Solutions for Realtors &amp; Real Estate Firms</title>
+ <description>FeedForAll helps Realtors and Real Estate companies communicate with clients informing them of newly available properties, and open house announcements. RSS helps to reach a targeted audience and spread the word in an inexpensive, professional manner. &lt;font color=&quot;#0000FF&quot;&gt;&lt;br&gt;
+&lt;/font&gt;&lt;br&gt;
+Feeds can be used for:&lt;br&gt;
+&lt;i&gt;&lt;font color=&quot;#FF0000&quot;&gt;Open House Dates&lt;br&gt;
+New Properties For Sale&lt;br&gt;
+Mortgage Rates&lt;/i&gt;&lt;/font&gt;</description>
+ <link>http://www.feedforall.com/real-estate.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <comments>http://www.feedforall.com/forum</comments>
+ <pubDate>Tue, 19 Oct 2004 11:08:59 -0400</pubDate>
+ </item>
+ <item>
+ <title>RSS Solutions for Banks / Mortgage Companies</title>
+ <description>FeedForAll helps &lt;b&gt;Banks, Credit Unions and Mortgage companies&lt;/b&gt; communicate with the general public about rate changes in a prompt and professional manner. &lt;br&gt;
+&lt;br&gt;
+Uses include:&lt;br&gt;
+&lt;i&gt;&lt;font color=&quot;#0000FF&quot;&gt;Mortgage Rates&lt;br&gt;
+Foreign Exchange Rates &lt;br&gt;
+Bank Rates&lt;br&gt;
+Specials&lt;/i&gt;&lt;/font&gt;</description>
+ <link>http://www.feedforall.com/banks.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <comments>http://www.feedforall.com/forum</comments>
+ <pubDate>Tue, 19 Oct 2004 11:08:57 -0400</pubDate>
+ </item>
+ <item>
+ <title>RSS Solutions for Law Enforcement</title>
+ <description>&lt;b&gt;FeedForAll&lt;/b&gt; helps Law Enforcement Professionals communicate with the general public and other agencies in a prompt and efficient manner. Using RSS police are able to quickly disseminate urgent and life threatening information. &lt;br&gt;
+&lt;br&gt;
+Uses include:&lt;br&gt;
+&lt;i&gt;&lt;font color=&quot;#0000FF&quot;&gt;Amber Alerts&lt;br&gt;
+Sex Offender Community Notification &lt;br&gt;
+Weather Alerts &lt;br&gt;
+Scheduling &lt;br&gt;
+Security Alerts &lt;br&gt;
+Police Report &lt;br&gt;
+Meetings&lt;/i&gt;&lt;/font&gt;</description>
+ <link>http://www.feedforall.com/law-enforcement.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <comments>http://www.feedforall.com/forum</comments>
+ <pubDate>Tue, 19 Oct 2004 11:08:56 -0400</pubDate>
+ </item>
+ </channel>
+</rss> \ No newline at end of file
diff --git a/components/shared/net/tests/parsable_mime/text/xml/rdf_rss.xml b/components/shared/net/tests/parsable_mime/text/xml/rdf_rss.xml
new file mode 100644
index 00000000000..4c58f82974e
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/xml/rdf_rss.xml
@@ -0,0 +1,7 @@
+<!-- Good format for a "RDF feed" -->
+<?xml version="1.0"?>
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+>
+</rdf:RDF> \ No newline at end of file
diff --git a/components/shared/net/tests/parsable_mime/text/xml/rdf_rss_ko_1.xml b/components/shared/net/tests/parsable_mime/text/xml/rdf_rss_ko_1.xml
new file mode 100644
index 00000000000..f6e486c5960
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/xml/rdf_rss_ko_1.xml
@@ -0,0 +1,7 @@
+<!-- Bad format for a "RDF feed" (space between "rdf:" and "RDF") -->
+<?xml version="1.0"?>
+<rdf: RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+>
+</rdf:RDF> \ No newline at end of file
diff --git a/components/shared/net/tests/parsable_mime/text/xml/rdf_rss_ko_2.xml b/components/shared/net/tests/parsable_mime/text/xml/rdf_rss_ko_2.xml
new file mode 100644
index 00000000000..be8414382e5
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/xml/rdf_rss_ko_2.xml
@@ -0,0 +1,3 @@
+<!-- Bad format for a "RDF feed" (2 missing URLs) -->
+<?xml version="1.0"?>
+<rdf:RDF/> \ No newline at end of file
diff --git a/components/shared/net/tests/parsable_mime/text/xml/rdf_rss_ko_3.xml b/components/shared/net/tests/parsable_mime/text/xml/rdf_rss_ko_3.xml
new file mode 100644
index 00000000000..5f0f03f1e2d
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/xml/rdf_rss_ko_3.xml
@@ -0,0 +1,6 @@
+<!-- Bad format for a "RDF feed" (one missing URL) -->
+<?xml version="1.0"?>
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+>
+</rdf:RDF> \ No newline at end of file
diff --git a/components/shared/net/tests/parsable_mime/text/xml/rdf_rss_ko_4.xml b/components/shared/net/tests/parsable_mime/text/xml/rdf_rss_ko_4.xml
new file mode 100644
index 00000000000..c06a80cf1f8
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/xml/rdf_rss_ko_4.xml
@@ -0,0 +1,7 @@
+<!-- Bad format for a "RDF feed" (unexpected space in first URL) -->
+<?xml version="1.0"?>
+<rdf:RDF
+ xmlns:rdf="http: //www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+>
+</rdf:RDF> \ No newline at end of file
diff --git a/components/shared/net/tests/parsable_mime/text/xml/test.xml b/components/shared/net/tests/parsable_mime/text/xml/test.xml
new file mode 100644
index 00000000000..8fe8c0e91cf
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/text/xml/test.xml
@@ -0,0 +1,6 @@
+
+<?xml version="1.0" encoding="UTF-8"?>
+<foo>
+ <bar>
+ </bar>
+</foo>
diff --git a/components/shared/net/tests/parsable_mime/unknown/binary_file b/components/shared/net/tests/parsable_mime/unknown/binary_file
new file mode 100644
index 00000000000..ecf3bbcdf3e
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/unknown/binary_file
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/unknown/open_type b/components/shared/net/tests/parsable_mime/unknown/open_type
new file mode 100644
index 00000000000..9117b12600f
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/unknown/open_type
@@ -0,0 +1 @@
+OTTO \ No newline at end of file
diff --git a/components/shared/net/tests/parsable_mime/unknown/true_type.ttf b/components/shared/net/tests/parsable_mime/unknown/true_type.ttf
new file mode 100644
index 00000000000..c0142fea093
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/unknown/true_type.ttf
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/unknown/true_type_collection.ttc b/components/shared/net/tests/parsable_mime/unknown/true_type_collection.ttc
new file mode 100644
index 00000000000..42d3cef1e6d
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/unknown/true_type_collection.ttc
@@ -0,0 +1 @@
+ttcf \ No newline at end of file
diff --git a/components/shared/net/tests/parsable_mime/video/avi/test.avi b/components/shared/net/tests/parsable_mime/video/avi/test.avi
new file mode 100644
index 00000000000..f6cd837a924
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/video/avi/test.avi
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/video/mp4/test.mp4 b/components/shared/net/tests/parsable_mime/video/mp4/test.mp4
new file mode 100644
index 00000000000..1fc478842f5
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/video/mp4/test.mp4
Binary files differ
diff --git a/components/shared/net/tests/parsable_mime/video/webm/test.webm b/components/shared/net/tests/parsable_mime/video/webm/test.webm
new file mode 100644
index 00000000000..da946da5290
--- /dev/null
+++ b/components/shared/net/tests/parsable_mime/video/webm/test.webm
Binary files differ
diff --git a/components/shared/snapshot/lib.rs b/components/shared/snapshot/lib.rs
index 7f0111f7a79..590de3666ad 100644
--- a/components/shared/snapshot/lib.rs
+++ b/components/shared/snapshot/lib.rs
@@ -87,7 +87,7 @@ pub type IpcSnapshot = Snapshot<IpcSharedMemory>;
/// <https://gpuweb.github.io/gpuweb/#abstract-opdef-get-a-copy-of-the-image-contents-of-a-context>
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
pub struct Snapshot<T = Data> {
- size: Size2D<u64>,
+ size: Size2D<u32>,
/// internal data (can be any format it will be converted on use if needed)
data: T,
/// RGBA/BGRA (reflect internal data)
@@ -97,7 +97,7 @@ pub struct Snapshot<T = Data> {
}
impl<T> Snapshot<T> {
- pub const fn size(&self) -> Size2D<u64> {
+ pub const fn size(&self) -> Size2D<u32> {
self.size
}
@@ -131,7 +131,7 @@ impl Snapshot<Data> {
}
/// Returns snapshot with provided size that is black transparent alpha
- pub fn cleared(size: Size2D<u64>) -> Self {
+ pub fn cleared(size: Size2D<u32>) -> Self {
Self {
size,
data: Data::Owned(vec![0; size.area() as usize * 4]),
@@ -143,7 +143,7 @@ impl Snapshot<Data> {
}
pub fn from_vec(
- size: Size2D<u64>,
+ size: Size2D<u32>,
format: PixelFormat,
alpha_mode: AlphaMode,
data: Vec<u8>,
@@ -157,7 +157,7 @@ impl Snapshot<Data> {
}
pub fn from_shared_memory(
- size: Size2D<u64>,
+ size: Size2D<u32>,
format: PixelFormat,
alpha_mode: AlphaMode,
ism: IpcSharedMemory,
@@ -177,7 +177,7 @@ impl Snapshot<Data> {
/// This is safe if data is owned by this process only
/// (ownership is transferred on send)
pub unsafe fn from_shared_memory(
- size: Size2D<u64>,
+ size: Size2D<u32>,
format: PixelFormat,
alpha_mode: AlphaMode,
ism: IpcSharedMemory,