mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Auto merge of #8190 - jdm:4138, r=eefriedman
Implemementing context-based MIME type sniffing This is a rebase of #7842 that also adds a test. Fixes #4183. @Yoric, how's this look to you? <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/8190) <!-- Reviewable:end -->
This commit is contained in:
commit
af1690f303
29 changed files with 387 additions and 122 deletions
|
@ -17,6 +17,7 @@ harfbuzz-sys = "0.1"
|
|||
lazy_static = "0.1"
|
||||
libc = "0.2"
|
||||
log = "0.3"
|
||||
mime = "0.1"
|
||||
rand = "0.3"
|
||||
rustc-serialize = "0.3"
|
||||
serde = "0.6"
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
use font_template::{FontTemplate, FontTemplateDescriptor};
|
||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||
use ipc_channel::router::ROUTER;
|
||||
use net_traits::{AsyncResponseTarget, PendingAsyncLoad, ResourceTask, ResponseAction};
|
||||
use mime::{TopLevel, SubLevel};
|
||||
use net_traits::{AsyncResponseTarget, LoadContext, PendingAsyncLoad, ResourceTask, ResponseAction};
|
||||
use platform::font_context::FontContextHandle;
|
||||
use platform::font_list::for_each_available_family;
|
||||
use platform::font_list::for_each_variation;
|
||||
|
@ -21,6 +22,7 @@ use string_cache::Atom;
|
|||
use style::font_face::Source;
|
||||
use style::properties::longhands::font_family::computed_value::FontFamily;
|
||||
use url::Url;
|
||||
use util::prefs;
|
||||
use util::str::LowercaseString;
|
||||
use util::task::spawn_named;
|
||||
|
||||
|
@ -156,7 +158,8 @@ impl FontCache {
|
|||
match src {
|
||||
Source::Url(ref url_source) => {
|
||||
let url = &url_source.url;
|
||||
let load = PendingAsyncLoad::new(self.resource_task.clone(),
|
||||
let load = PendingAsyncLoad::new(LoadContext::Font,
|
||||
self.resource_task.clone(),
|
||||
url.clone(),
|
||||
None);
|
||||
let (data_sender, data_receiver) = ipc::channel().unwrap();
|
||||
|
@ -167,15 +170,32 @@ impl FontCache {
|
|||
let channel_to_self = self.channel_to_self.clone();
|
||||
let url = (*url).clone();
|
||||
let bytes = Mutex::new(Vec::new());
|
||||
let response_valid = Mutex::new(false);
|
||||
ROUTER.add_route(data_receiver.to_opaque(), box move |message| {
|
||||
let response: ResponseAction = message.to().unwrap();
|
||||
match response {
|
||||
ResponseAction::HeadersAvailable(_) |
|
||||
ResponseAction::HeadersAvailable(metadata) => {
|
||||
let is_response_valid =
|
||||
metadata.content_type.as_ref().map_or(false, |content_type| {
|
||||
let mime = &content_type.0;
|
||||
is_supported_font_type(&mime.0, &mime.1)
|
||||
});
|
||||
info!("{} font with MIME type {:?}",
|
||||
if is_response_valid { "Loading" } else { "Ignoring" },
|
||||
metadata.content_type);
|
||||
*response_valid.lock().unwrap() = is_response_valid;
|
||||
}
|
||||
ResponseAction::ResponseComplete(Err(_)) => {}
|
||||
ResponseAction::DataAvailable(new_bytes) => {
|
||||
bytes.lock().unwrap().extend(new_bytes.into_iter())
|
||||
if *response_valid.lock().unwrap() {
|
||||
bytes.lock().unwrap().extend(new_bytes.into_iter())
|
||||
}
|
||||
}
|
||||
ResponseAction::ResponseComplete(Ok(_)) => {
|
||||
if !*response_valid.lock().unwrap() {
|
||||
drop(result.send(()));
|
||||
return;
|
||||
}
|
||||
let mut bytes = bytes.lock().unwrap();
|
||||
let bytes = mem::replace(&mut *bytes, Vec::new());
|
||||
let command =
|
||||
|
@ -368,3 +388,22 @@ impl FontCacheTask {
|
|||
response_port.recv().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
// derived from http://stackoverflow.com/a/10864297/3830
|
||||
fn is_supported_font_type(toplevel: &TopLevel, sublevel: &SubLevel) -> bool {
|
||||
if !prefs::get_pref("net.mime.sniff").as_boolean().unwrap_or(false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
match (toplevel, sublevel) {
|
||||
(&TopLevel::Application, &SubLevel::Ext(ref ext)) => {
|
||||
match &ext[..] {
|
||||
//FIXME: once sniffing is enabled by default, we shouldn't need nonstandard
|
||||
// MIME types here.
|
||||
"font-sfnt" | "x-font-ttf" | "x-font-truetype" | "x-font-opentype" => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ extern crate lazy_static;
|
|||
extern crate libc;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate mime;
|
||||
extern crate msg;
|
||||
extern crate net_traits;
|
||||
#[macro_use]
|
||||
|
|
|
@ -29,7 +29,11 @@ pub fn factory(mut load_data: LoadData,
|
|||
headers: None,
|
||||
status: Some(RawStatus(200, "OK".into())),
|
||||
};
|
||||
if let Ok(chan) = start_sending_sniffed_opt(start_chan, metadata, classifier, &[]) {
|
||||
if let Ok(chan) = start_sending_sniffed_opt(start_chan,
|
||||
metadata,
|
||||
classifier,
|
||||
&[],
|
||||
load_data.context) {
|
||||
let _ = chan.send(Done(Ok(())));
|
||||
}
|
||||
return
|
||||
|
|
|
@ -88,7 +88,11 @@ pub fn load(load_data: LoadData,
|
|||
|
||||
let mut metadata = Metadata::default(url);
|
||||
metadata.set_content_type(content_type.as_ref());
|
||||
if let Ok(chan) = start_sending_sniffed_opt(start_chan, metadata, classifier, &bytes) {
|
||||
if let Ok(chan) = start_sending_sniffed_opt(start_chan,
|
||||
metadata,
|
||||
classifier,
|
||||
&bytes,
|
||||
load_data.context) {
|
||||
let _ = chan.send(Payload(bytes));
|
||||
let _ = chan.send(Done(Ok(())));
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ pub fn factory(load_data: LoadData,
|
|||
classifier: Arc<MIMEClassifier>,
|
||||
cancel_listener: CancellationListener) {
|
||||
let url = load_data.url;
|
||||
let context = load_data.context;
|
||||
assert!(&*url.scheme == "file");
|
||||
spawn_named("file_loader".to_owned(), move || {
|
||||
let file_path: Result<PathBuf, ()> = url.to_file_path();
|
||||
|
@ -77,7 +78,7 @@ pub fn factory(load_data: LoadData,
|
|||
let mime_type = guess_mime_type(file_path.as_path());
|
||||
metadata.set_content_type(Some(&mime_type));
|
||||
let progress_chan = start_sending_sniffed(senders, metadata,
|
||||
classifier, &buf);
|
||||
classifier, &buf, context);
|
||||
progress_chan.send(Payload(buf)).unwrap();
|
||||
let read_result = read_all(reader, &progress_chan, &cancel_listener);
|
||||
if let Ok(load_result) = read_result {
|
||||
|
@ -94,7 +95,8 @@ pub fn factory(load_data: LoadData,
|
|||
if let Ok(chan) = start_sending_sniffed_opt(senders,
|
||||
metadata,
|
||||
classifier,
|
||||
&[]) {
|
||||
&[],
|
||||
context) {
|
||||
let _ = chan.send(Done(Ok(())));
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +110,7 @@ pub fn factory(load_data: LoadData,
|
|||
// http://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.open
|
||||
// but, we'll go for a "file not found!"
|
||||
let url = Url::parse("about:not-found").unwrap();
|
||||
let load_data_404 = LoadData::new(url, None);
|
||||
let load_data_404 = LoadData::new(context, url, None);
|
||||
about_loader::factory(load_data_404, senders, classifier, cancel_listener)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ use mime_classifier::MIMEClassifier;
|
|||
use msg::constellation_msg::{PipelineId};
|
||||
use net_traits::ProgressMsg::{Done, Payload};
|
||||
use net_traits::hosts::replace_hosts;
|
||||
use net_traits::{CookieSource, IncludeSubdomains, LoadConsumer, LoadData, Metadata};
|
||||
use net_traits::{CookieSource, IncludeSubdomains, LoadConsumer, LoadContext, LoadData, Metadata};
|
||||
use openssl::ssl::error::{SslError, OpensslError};
|
||||
use openssl::ssl::{SSL_OP_NO_SSLV2, SSL_OP_NO_SSLV3, SSL_VERIFY_PEER, SslContext, SslMethod};
|
||||
use resource_task::{CancellationListener, send_error, start_sending_sniffed_opt};
|
||||
|
@ -135,6 +135,7 @@ fn load_for_consumer(load_data: LoadData,
|
|||
let factory = NetworkHttpRequestFactory {
|
||||
connector: connector,
|
||||
};
|
||||
let context = load_data.context.clone();
|
||||
match load::<WrappedHttpRequest>(load_data, hsts_list,
|
||||
cookie_jar, devtools_chan,
|
||||
&factory, user_agent,
|
||||
|
@ -160,14 +161,14 @@ fn load_for_consumer(load_data: LoadData,
|
|||
|
||||
let mut image = resources_dir_path();
|
||||
image.push("badcert.html");
|
||||
let load_data = LoadData::new(Url::from_file_path(&*image).unwrap(), None);
|
||||
let load_data = LoadData::new(context, Url::from_file_path(&*image).unwrap(), None);
|
||||
|
||||
file_loader::factory(load_data, start_chan, classifier, cancel_listener)
|
||||
}
|
||||
Err(LoadError::ConnectionAborted(_)) => unreachable!(),
|
||||
Ok(mut load_response) => {
|
||||
let metadata = load_response.metadata.clone();
|
||||
send_data(&mut load_response, start_chan, metadata, classifier, &cancel_listener)
|
||||
send_data(context, &mut load_response, start_chan, metadata, classifier, &cancel_listener)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -765,7 +766,8 @@ pub fn load<A>(load_data: LoadData,
|
|||
}
|
||||
}
|
||||
|
||||
fn send_data<R: Read>(reader: &mut R,
|
||||
fn send_data<R: Read>(context: LoadContext,
|
||||
reader: &mut R,
|
||||
start_chan: LoadConsumer,
|
||||
metadata: Metadata,
|
||||
classifier: Arc<MIMEClassifier>,
|
||||
|
@ -775,7 +777,7 @@ fn send_data<R: Read>(reader: &mut R,
|
|||
Ok(ReadResult::Payload(buf)) => buf,
|
||||
_ => vec!(),
|
||||
};
|
||||
let p = match start_sending_sniffed_opt(start_chan, metadata, classifier, &buf) {
|
||||
let p = match start_sending_sniffed_opt(start_chan, metadata, classifier, &buf, context) {
|
||||
Ok(p) => p,
|
||||
_ => return
|
||||
};
|
||||
|
|
|
@ -8,7 +8,8 @@ use net_traits::image::base::{Image, load_from_memory};
|
|||
use net_traits::image_cache_task::ImageResponder;
|
||||
use net_traits::image_cache_task::{ImageCacheChan, ImageCacheCommand, ImageCacheTask, ImageState};
|
||||
use net_traits::image_cache_task::{ImageCacheResult, ImageResponse, UsePlaceholder};
|
||||
use net_traits::{AsyncResponseTarget, ControlMsg, LoadConsumer, LoadData, ResourceTask, ResponseAction};
|
||||
use net_traits::{AsyncResponseTarget, ControlMsg, LoadConsumer, LoadData, ResourceTask};
|
||||
use net_traits::{ResponseAction, LoadContext};
|
||||
use std::borrow::ToOwned;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
|
@ -423,7 +424,7 @@ impl ImageCache {
|
|||
CacheResult::Miss => {
|
||||
// A new load request! Request the load from
|
||||
// the resource task.
|
||||
let load_data = LoadData::new((*ref_url).clone(), None);
|
||||
let load_data = LoadData::new(LoadContext::Image, (*ref_url).clone(), None);
|
||||
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
||||
let response_target = AsyncResponseTarget {
|
||||
sender: action_sender,
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use net_traits::LoadContext;
|
||||
use std::borrow::ToOwned;
|
||||
|
||||
pub struct MIMEClassifier {
|
||||
|
@ -11,7 +12,8 @@ pub struct MIMEClassifier {
|
|||
plaintext_classifier: GroupedClassifier,
|
||||
archive_classifier: GroupedClassifier,
|
||||
binary_or_plaintext: BinaryOrPlaintextClassifier,
|
||||
feeds_classifier: FeedsClassifier
|
||||
feeds_classifier: FeedsClassifier,
|
||||
font_classifier: GroupedClassifier,
|
||||
}
|
||||
|
||||
pub enum MediaType {
|
||||
|
@ -33,35 +35,105 @@ pub enum NoSniffFlag {
|
|||
}
|
||||
|
||||
impl MIMEClassifier {
|
||||
//Performs MIME Type Sniffing Algorithm (section 7)
|
||||
//Performs MIME Type Sniffing Algorithm (sections 7 and 8)
|
||||
pub fn classify(&self,
|
||||
context: LoadContext,
|
||||
no_sniff_flag: NoSniffFlag,
|
||||
apache_bug_flag: ApacheBugFlag,
|
||||
supplied_type: &Option<(String, String)>,
|
||||
data: &[u8]) -> (String, String) {
|
||||
match *supplied_type {
|
||||
None => self.sniff_unknown_type(no_sniff_flag, data),
|
||||
Some(ref supplied_type) => {
|
||||
let &(ref media_type, ref media_subtype) = supplied_type;
|
||||
if MIMEClassifier::is_explicit_unknown(media_type, media_subtype) {
|
||||
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(media_type,
|
||||
media_subtype) {
|
||||
Some(MediaType::Xml) => None,
|
||||
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),
|
||||
None => None
|
||||
}.unwrap_or(supplied_type.clone())
|
||||
let supplied_type_or_octet_stream = supplied_type.clone()
|
||||
.unwrap_or(("application".to_owned(),
|
||||
"octet-stream".to_owned()));
|
||||
match context {
|
||||
LoadContext::Browsing => match *supplied_type {
|
||||
None => self.sniff_unknown_type(no_sniff_flag, data),
|
||||
Some(ref supplied_type) => {
|
||||
let &(ref media_type, ref media_subtype) = supplied_type;
|
||||
if MIMEClassifier::is_explicit_unknown(media_type, media_subtype) {
|
||||
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(media_type,
|
||||
media_subtype) {
|
||||
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::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 => ("application".to_owned(), "octet-stream".to_owned()),
|
||||
_ => 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 => ("text".to_owned(), "css".to_owned()),
|
||||
_ => 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 => ("text".to_owned(), "javascript".to_owned()),
|
||||
_ => 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".to_owned(), "vtt".to_owned())
|
||||
},
|
||||
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".to_owned(), "cache-manifest".to_owned())
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,7 +145,8 @@ impl MIMEClassifier {
|
|||
plaintext_classifier: GroupedClassifier::plaintext_classifier(),
|
||||
archive_classifier: GroupedClassifier::archive_classifier(),
|
||||
binary_or_plaintext: BinaryOrPlaintextClassifier,
|
||||
feeds_classifier: FeedsClassifier
|
||||
feeds_classifier: FeedsClassifier,
|
||||
font_classifier: GroupedClassifier::font_classifier()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,6 +216,12 @@ impl MIMEClassifier {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn maybe_get_media_type(supplied_type: &Option<(String, String)>) -> Option<MediaType> {
|
||||
supplied_type.as_ref().and_then(|&(ref media_type, ref media_subtype)| {
|
||||
MIMEClassifier::get_media_type(media_type, media_subtype)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_string_option(tup: Option<(&'static str, &'static str)>) -> Option<(String, String)> {
|
||||
|
@ -375,8 +454,6 @@ impl GroupedClassifier {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Use this in font context classifier
|
||||
#[allow(dead_code)]
|
||||
fn font_classifier() -> GroupedClassifier {
|
||||
GroupedClassifier {
|
||||
byte_matchers: vec![
|
||||
|
@ -873,8 +950,6 @@ impl ByteMatcher {
|
|||
}
|
||||
}
|
||||
//34 bytes followed by the string "LP", the Embedded OpenType signature.
|
||||
// TODO: Use this in font context classifier
|
||||
#[allow(dead_code)]
|
||||
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\
|
||||
|
@ -888,41 +963,33 @@ impl ByteMatcher {
|
|||
}
|
||||
}
|
||||
//4 bytes representing the version number 1.0, a TrueType signature.
|
||||
// TODO: Use this in font context classifier
|
||||
#[allow(dead_code)]
|
||||
fn true_type() -> ByteMatcher {
|
||||
ByteMatcher {
|
||||
pattern: b"\x00\x01\x00\x00",
|
||||
mask: b"\xFF\xFF\xFF\xFF",
|
||||
content_type: ("(TrueType)", ""),
|
||||
content_type: ("application", "font-sfnt"),
|
||||
leading_ignore: &[]
|
||||
}
|
||||
}
|
||||
//The string "OTTO", the OpenType signature.
|
||||
// TODO: Use this in font context classifier
|
||||
#[allow(dead_code)]
|
||||
fn open_type() -> ByteMatcher {
|
||||
ByteMatcher {
|
||||
pattern: b"OTTO",
|
||||
mask: b"\xFF\xFF\xFF\xFF",
|
||||
content_type: ("(OpenType)", ""),
|
||||
content_type: ("application", "font-sfnt"),
|
||||
leading_ignore: &[]
|
||||
}
|
||||
}
|
||||
// The string "ttcf", the TrueType Collection signature.
|
||||
// TODO: Use this in font context classifier
|
||||
#[allow(dead_code)]
|
||||
fn true_type_collection() -> ByteMatcher {
|
||||
ByteMatcher {
|
||||
pattern: b"ttcf",
|
||||
mask: b"\xFF\xFF\xFF\xFF",
|
||||
content_type: ("(TrueType Collection)", ""),
|
||||
content_type: ("application", "font-sfnt"),
|
||||
leading_ignore: &[]
|
||||
}
|
||||
}
|
||||
// The string "wOFF", the Web Open Font Format signature.
|
||||
// TODO: Use this in font context classifier
|
||||
#[allow(dead_code)]
|
||||
fn application_font_woff() -> ByteMatcher {
|
||||
ByteMatcher {
|
||||
pattern: b"wOFF",
|
||||
|
|
|
@ -17,6 +17,7 @@ use hyper::header::{ContentType, Header, SetCookie};
|
|||
use hyper::mime::{Mime, SubLevel, TopLevel};
|
||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||
use mime_classifier::{ApacheBugFlag, MIMEClassifier, NoSniffFlag};
|
||||
use net_traits::LoadContext;
|
||||
use net_traits::ProgressMsg::Done;
|
||||
use net_traits::{AsyncResponseTarget, Metadata, ProgressMsg, ResourceTask, ResponseAction};
|
||||
use net_traits::{ControlMsg, CookieSource, LoadConsumer, LoadData, LoadResponse, ResourceId};
|
||||
|
@ -28,7 +29,7 @@ use std::collections::HashMap;
|
|||
use std::sync::mpsc::{Receiver, Sender, channel};
|
||||
use std::sync::{Arc, RwLock};
|
||||
use url::Url;
|
||||
use util::opts;
|
||||
use util::prefs;
|
||||
use util::task::spawn_named;
|
||||
use websocket_loader;
|
||||
|
||||
|
@ -65,16 +66,18 @@ pub fn send_error(url: Url, err: String, start_chan: LoadConsumer) {
|
|||
|
||||
/// For use by loaders in responding to a Load message that allows content sniffing.
|
||||
pub fn start_sending_sniffed(start_chan: LoadConsumer, metadata: Metadata,
|
||||
classifier: Arc<MIMEClassifier>, partial_body: &[u8])
|
||||
classifier: Arc<MIMEClassifier>, partial_body: &[u8],
|
||||
context: LoadContext)
|
||||
-> ProgressSender {
|
||||
start_sending_sniffed_opt(start_chan, metadata, classifier, partial_body).ok().unwrap()
|
||||
start_sending_sniffed_opt(start_chan, metadata, classifier, partial_body, context).ok().unwrap()
|
||||
}
|
||||
|
||||
/// For use by loaders in responding to a Load message that allows content sniffing.
|
||||
pub fn start_sending_sniffed_opt(start_chan: LoadConsumer, mut metadata: Metadata,
|
||||
classifier: Arc<MIMEClassifier>, partial_body: &[u8])
|
||||
classifier: Arc<MIMEClassifier>, partial_body: &[u8],
|
||||
context: LoadContext)
|
||||
-> Result<ProgressSender, ()> {
|
||||
if opts::get().sniff_mime_types {
|
||||
if prefs::get_pref("net.mime.sniff").as_boolean().unwrap_or(false) {
|
||||
// TODO: should be calculated in the resource loader, from pull requeset #4094
|
||||
let mut no_sniff = NoSniffFlag::OFF;
|
||||
let mut check_for_apache_bug = ApacheBugFlag::OFF;
|
||||
|
@ -94,10 +97,11 @@ pub fn start_sending_sniffed_opt(start_chan: LoadConsumer, mut metadata: Metadat
|
|||
}
|
||||
|
||||
let supplied_type =
|
||||
metadata.content_type.map(|ContentType(Mime(toplevel, sublevel, _))| {
|
||||
metadata.content_type.as_ref().map(|&ContentType(Mime(ref toplevel, ref sublevel, _))| {
|
||||
(format!("{}", toplevel), format!("{}", sublevel))
|
||||
});
|
||||
let (toplevel, sublevel) = classifier.classify(no_sniff,
|
||||
let (toplevel, sublevel) = classifier.classify(context,
|
||||
no_sniff,
|
||||
check_for_apache_bug,
|
||||
&supplied_type,
|
||||
&partial_body);
|
||||
|
|
|
@ -136,6 +136,21 @@ pub mod image {
|
|||
pub mod base;
|
||||
}
|
||||
|
||||
/// A loading context, for context-specific sniffing, as defined in
|
||||
/// https://mimesniff.spec.whatwg.org/#context-specific-sniffing
|
||||
#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
|
||||
pub enum LoadContext {
|
||||
Browsing,
|
||||
Image,
|
||||
AudioVideo,
|
||||
Plugin,
|
||||
Style,
|
||||
Script,
|
||||
Font,
|
||||
TextTrack,
|
||||
CacheManifest,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
|
||||
pub struct LoadData {
|
||||
pub url: Url,
|
||||
|
@ -151,10 +166,11 @@ pub struct LoadData {
|
|||
pub pipeline_id: Option<PipelineId>,
|
||||
// https://fetch.spec.whatwg.org/#concept-http-fetch step 4.3
|
||||
pub credentials_flag: bool,
|
||||
pub context: LoadContext,
|
||||
}
|
||||
|
||||
impl LoadData {
|
||||
pub fn new(url: Url, id: Option<PipelineId>) -> LoadData {
|
||||
pub fn new(context: LoadContext, url: Url, id: Option<PipelineId>) -> LoadData {
|
||||
LoadData {
|
||||
url: url,
|
||||
method: Method::Get,
|
||||
|
@ -164,6 +180,7 @@ impl LoadData {
|
|||
cors: None,
|
||||
pipeline_id: id,
|
||||
credentials_flag: true,
|
||||
context: context
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -295,6 +312,7 @@ pub struct PendingAsyncLoad {
|
|||
url: Url,
|
||||
pipeline: Option<PipelineId>,
|
||||
guard: PendingLoadGuard,
|
||||
context: LoadContext,
|
||||
}
|
||||
|
||||
struct PendingLoadGuard {
|
||||
|
@ -316,20 +334,21 @@ impl Drop for PendingLoadGuard {
|
|||
}
|
||||
|
||||
impl PendingAsyncLoad {
|
||||
pub fn new(resource_task: ResourceTask, url: Url, pipeline: Option<PipelineId>)
|
||||
pub fn new(context: LoadContext, resource_task: ResourceTask, url: Url, pipeline: Option<PipelineId>)
|
||||
-> PendingAsyncLoad {
|
||||
PendingAsyncLoad {
|
||||
resource_task: resource_task,
|
||||
url: url,
|
||||
pipeline: pipeline,
|
||||
guard: PendingLoadGuard { loaded: false, },
|
||||
context: context
|
||||
}
|
||||
}
|
||||
|
||||
/// Initiate the network request associated with this pending load, using the provided target.
|
||||
pub fn load_async(mut self, listener: AsyncResponseTarget) {
|
||||
self.guard.neuter();
|
||||
let load_data = LoadData::new(self.url, self.pipeline);
|
||||
let load_data = LoadData::new(self.context, self.url, self.pipeline);
|
||||
let consumer = LoadConsumer::Listener(listener);
|
||||
self.resource_task.send(ControlMsg::Load(load_data, consumer, None)).unwrap();
|
||||
}
|
||||
|
@ -425,10 +444,13 @@ pub enum ProgressMsg {
|
|||
}
|
||||
|
||||
/// Convenience function for synchronously loading a whole resource.
|
||||
pub fn load_whole_resource(resource_task: &ResourceTask, url: Url, pipeline_id: Option<PipelineId>)
|
||||
pub fn load_whole_resource(context: LoadContext,
|
||||
resource_task: &ResourceTask,
|
||||
url: Url,
|
||||
pipeline_id: Option<PipelineId>)
|
||||
-> Result<(Metadata, Vec<u8>), String> {
|
||||
let (start_chan, start_port) = ipc::channel().unwrap();
|
||||
resource_task.send(ControlMsg::Load(LoadData::new(url, pipeline_id),
|
||||
resource_task.send(ControlMsg::Load(LoadData::new(context, url, pipeline_id),
|
||||
LoadConsumer::Channel(start_chan), None)).unwrap();
|
||||
let response = start_port.recv().unwrap();
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use net_traits::AsyncResponseTarget;
|
||||
use net_traits::{PendingAsyncLoad, ResourceTask};
|
||||
use net_traits::{PendingAsyncLoad, ResourceTask, LoadContext};
|
||||
use std::sync::Arc;
|
||||
use url::Url;
|
||||
|
||||
|
@ -30,6 +30,15 @@ impl LoadType {
|
|||
LoadType::PageSource(ref url) => url,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_load_context(&self) -> LoadContext {
|
||||
match *self {
|
||||
LoadType::Image(_) => LoadContext::Image,
|
||||
LoadType::Script(_) => LoadContext::Script,
|
||||
LoadType::Subframe(_) | LoadType::PageSource(_) => LoadContext::Browsing,
|
||||
LoadType::Stylesheet(_) => LoadContext::Style
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(JSTraceable, HeapSizeOf)]
|
||||
|
@ -67,9 +76,10 @@ impl DocumentLoader {
|
|||
/// Create a new pending network request, which can be initiated at some point in
|
||||
/// the future.
|
||||
pub fn prepare_async_load(&mut self, load: LoadType) -> PendingAsyncLoad {
|
||||
let context = load.to_load_context();
|
||||
let url = load.url().clone();
|
||||
self.blocking_loads.push(load);
|
||||
PendingAsyncLoad::new((*self.resource_task).clone(), url, self.pipeline)
|
||||
PendingAsyncLoad::new(context, (*self.resource_task).clone(), url, self.pipeline)
|
||||
}
|
||||
|
||||
/// Create and initiate a new network request.
|
||||
|
@ -78,7 +88,6 @@ impl DocumentLoader {
|
|||
pending.load_async(listener)
|
||||
}
|
||||
|
||||
|
||||
/// Mark an in-progress network request complete.
|
||||
pub fn finish_load(&mut self, load: LoadType) {
|
||||
let idx = self.blocking_loads.iter().position(|unfinished| *unfinished == load);
|
||||
|
|
|
@ -26,7 +26,7 @@ use js::jsapi::{JSAutoCompartment, JSAutoRequest};
|
|||
use js::jsval::UndefinedValue;
|
||||
use js::rust::Runtime;
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use net_traits::load_whole_resource;
|
||||
use net_traits::{LoadContext, load_whole_resource};
|
||||
use rand::random;
|
||||
use script_task::ScriptTaskEventCategory::WorkerEvent;
|
||||
use script_task::{ScriptTask, ScriptChan, ScriptPort, StackRootTLS, CommonScriptMsg};
|
||||
|
@ -220,7 +220,7 @@ impl DedicatedWorkerGlobalScope {
|
|||
let roots = RootCollection::new();
|
||||
let _stack_roots_tls = StackRootTLS::new(&roots);
|
||||
|
||||
let (url, source) = match load_whole_resource(&init.resource_task, worker_url, None) {
|
||||
let (url, source) = match load_whole_resource(LoadContext::Script, &init.resource_task, worker_url, None) {
|
||||
Err(_) => {
|
||||
println!("error loading script {}", serialized_worker_url);
|
||||
parent_sender.send(CommonScriptMsg::RunnableMsg(WorkerEvent,
|
||||
|
|
|
@ -21,7 +21,7 @@ use ipc_channel::ipc::IpcSender;
|
|||
use js::jsapi::{HandleValue, JSAutoRequest, JSContext};
|
||||
use js::rust::Runtime;
|
||||
use msg::constellation_msg::{ConstellationChan, PipelineId};
|
||||
use net_traits::{ResourceTask, load_whole_resource};
|
||||
use net_traits::{LoadContext, ResourceTask, load_whole_resource};
|
||||
use profile_traits::mem;
|
||||
use script_task::{CommonScriptMsg, ScriptChan, ScriptPort};
|
||||
use script_traits::ScriptMsg as ConstellationMsg;
|
||||
|
@ -203,7 +203,7 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
|
|||
}
|
||||
|
||||
for url in urls {
|
||||
let (url, source) = match load_whole_resource(&self.resource_task, url, None) {
|
||||
let (url, source) = match load_whole_resource(LoadContext::Script, &self.resource_task, url, None) {
|
||||
Err(_) => return Err(Error::Network),
|
||||
Ok((metadata, bytes)) => {
|
||||
(metadata.final_url, String::from_utf8(bytes).unwrap())
|
||||
|
|
|
@ -46,7 +46,7 @@ use js::jsapi::{JSContext, JS_ParseJSON, RootedValue};
|
|||
use js::jsval::{JSVal, NullValue, UndefinedValue};
|
||||
use net_traits::ControlMsg::Load;
|
||||
use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata};
|
||||
use net_traits::{LoadConsumer, LoadData, ResourceCORSData, ResourceTask};
|
||||
use net_traits::{LoadConsumer, LoadContext, LoadData, ResourceCORSData, ResourceTask};
|
||||
use network_listener::{NetworkListener, PreInvoke};
|
||||
use parse::html::{ParseContext, parse_html};
|
||||
use parse::xml::{self, parse_xml};
|
||||
|
@ -521,7 +521,10 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
|
|||
|
||||
let global = self.global.root();
|
||||
let pipeline_id = global.r().pipeline();
|
||||
let mut load_data = LoadData::new(self.request_url.borrow().clone().unwrap(), Some(pipeline_id));
|
||||
let mut load_data =
|
||||
LoadData::new(LoadContext::Browsing,
|
||||
self.request_url.borrow().clone().unwrap(),
|
||||
Some(pipeline_id));
|
||||
if load_data.url.origin().ne(&global.r().get_url().origin()) {
|
||||
load_data.credentials_flag = self.WithCredentials();
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ use msg::webdriver_msg::WebDriverScriptCommand;
|
|||
use net_traits::LoadData as NetLoadData;
|
||||
use net_traits::image_cache_task::{ImageCacheChan, ImageCacheResult, ImageCacheTask};
|
||||
use net_traits::storage_task::StorageTask;
|
||||
use net_traits::{AsyncResponseTarget, ControlMsg, LoadConsumer, Metadata, ResourceTask};
|
||||
use net_traits::{AsyncResponseTarget, ControlMsg, LoadConsumer, LoadContext, Metadata, ResourceTask};
|
||||
use network_listener::NetworkListener;
|
||||
use page::{Frame, IterablePage, Page};
|
||||
use parse::html::{ParseContext, parse_html};
|
||||
|
@ -2003,6 +2003,7 @@ impl ScriptTask {
|
|||
}
|
||||
|
||||
resource_task.send(ControlMsg::Load(NetLoadData {
|
||||
context: LoadContext::Browsing,
|
||||
url: load_data.url,
|
||||
method: load_data.method,
|
||||
headers: Headers::new(),
|
||||
|
|
5
components/servo/Cargo.lock
generated
5
components/servo/Cargo.lock
generated
|
@ -623,6 +623,7 @@ dependencies = [
|
|||
"lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
"plugins 0.0.1",
|
||||
|
@ -1080,7 +1081,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "mime_guess"
|
||||
version = "1.1.1"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"mime 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1147,7 +1148,7 @@ dependencies = [
|
|||
"hyper 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.1.0 (git+https://github.com/servo/ipc-channel)",
|
||||
"log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime_guess 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime_guess 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
"openssl 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -171,9 +171,6 @@ pub struct Opts {
|
|||
/// Whether to show an error when display list geometry escapes flow overflow regions.
|
||||
pub validate_display_list_geometry: bool,
|
||||
|
||||
/// Whether MIME sniffing should be used
|
||||
pub sniff_mime_types: bool,
|
||||
|
||||
/// Whether Style Sharing Cache is used
|
||||
pub disable_share_style_cache: bool,
|
||||
|
||||
|
@ -491,7 +488,6 @@ pub fn default_opts() -> Opts {
|
|||
profile_tasks: false,
|
||||
profile_script_events: false,
|
||||
profile_heartbeats: false,
|
||||
sniff_mime_types: false,
|
||||
disable_share_style_cache: false,
|
||||
parallel_display_list_building: false,
|
||||
convert_mouse_to_touch: false,
|
||||
|
@ -536,7 +532,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
|||
"A comma-separated string of debug options. Pass help to show available options.", "");
|
||||
opts.optflag("h", "help", "Print this message");
|
||||
opts.optopt("", "resources-path", "Path to find static resources", "/home/servo/resources");
|
||||
opts.optflag("", "sniff-mime-types" , "Enable MIME sniffing");
|
||||
opts.optopt("", "content-process" , "Run as a content process and connect to the given pipe",
|
||||
"servo-ipc-channel.abcdefg");
|
||||
opts.optmulti("", "pref",
|
||||
|
@ -726,7 +721,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
|||
dump_layer_tree: debug_options.dump_layer_tree,
|
||||
relayout_event: debug_options.relayout_event,
|
||||
validate_display_list_geometry: debug_options.validate_display_list_geometry,
|
||||
sniff_mime_types: opt_match.opt_present("sniff-mime-types"),
|
||||
disable_share_style_cache: debug_options.disable_share_style_cache,
|
||||
parallel_display_list_building: debug_options.parallel_display_list_building,
|
||||
convert_mouse_to_touch: debug_options.convert_mouse_to_touch,
|
||||
|
|
5
ports/cef/Cargo.lock
generated
5
ports/cef/Cargo.lock
generated
|
@ -590,6 +590,7 @@ dependencies = [
|
|||
"lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
"plugins 0.0.1",
|
||||
|
@ -1040,7 +1041,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "mime_guess"
|
||||
version = "1.1.1"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"mime 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1107,7 +1108,7 @@ dependencies = [
|
|||
"hyper 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.1.0 (git+https://github.com/servo/ipc-channel)",
|
||||
"log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime_guess 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime_guess 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
"openssl 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
5
ports/gonk/Cargo.lock
generated
5
ports/gonk/Cargo.lock
generated
|
@ -580,6 +580,7 @@ dependencies = [
|
|||
"lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
"plugins 0.0.1",
|
||||
|
@ -1008,7 +1009,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "mime_guess"
|
||||
version = "1.1.1"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"mime 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1075,7 +1076,7 @@ dependencies = [
|
|||
"hyper 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.1.0 (git+https://github.com/servo/ipc-channel)",
|
||||
"log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime_guess 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime_guess 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
"openssl 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -10,5 +10,6 @@
|
|||
"layout.text-orientation.enabled": false,
|
||||
"layout.viewport.enabled": false,
|
||||
"layout.writing-mode.enabled": false,
|
||||
"net.mime.sniff": false,
|
||||
"shell.homepage": "http://servo.org"
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ extern crate hyper;
|
|||
|
||||
use ipc_channel::ipc;
|
||||
use net_traits::LoadConsumer::Channel;
|
||||
use net_traits::LoadData;
|
||||
use net_traits::ProgressMsg::{Payload, Done};
|
||||
use net_traits::{LoadData, LoadContext};
|
||||
use self::hyper::header::ContentType;
|
||||
use self::hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
|
||||
|
||||
|
@ -25,7 +25,7 @@ fn assert_parse(url: &'static str,
|
|||
|
||||
let (start_chan, start_port) = ipc::channel().unwrap();
|
||||
let classifier = Arc::new(MIMEClassifier::new());
|
||||
load(LoadData::new(Url::parse(url).unwrap(), None),
|
||||
load(LoadData::new(LoadContext::Browsing, Url::parse(url).unwrap(), None),
|
||||
Channel(start_chan),
|
||||
classifier, CancellationListener::new(None));
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ use net::cookie_storage::CookieStorage;
|
|||
use net::hsts::{HSTSList};
|
||||
use net::http_loader::{load, LoadError, HttpRequestFactory, HttpRequest, HttpResponse};
|
||||
use net::resource_task::CancellationListener;
|
||||
use net_traits::{LoadData, CookieSource};
|
||||
use net_traits::{LoadData, CookieSource, LoadContext};
|
||||
use std::borrow::Cow;
|
||||
use std::io::{self, Write, Read, Cursor};
|
||||
use std::sync::mpsc::Receiver;
|
||||
|
@ -351,7 +351,7 @@ fn test_check_default_headers_loaded_in_every_request() {
|
|||
let hsts_list = Arc::new(RwLock::new(HSTSList::new()));
|
||||
let cookie_jar = Arc::new(RwLock::new(CookieStorage::new()));
|
||||
|
||||
let mut load_data = LoadData::new(url.clone(), None);
|
||||
let mut load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
load_data.data = None;
|
||||
load_data.method = Method::Get;
|
||||
|
||||
|
@ -395,7 +395,7 @@ fn test_load_when_request_is_not_get_or_head_and_there_is_no_body_content_length
|
|||
let hsts_list = Arc::new(RwLock::new(HSTSList::new()));
|
||||
let cookie_jar = Arc::new(RwLock::new(CookieStorage::new()));
|
||||
|
||||
let mut load_data = LoadData::new(url.clone(), None);
|
||||
let mut load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
load_data.data = None;
|
||||
load_data.method = Method::Post;
|
||||
|
||||
|
@ -433,7 +433,7 @@ fn test_request_and_response_data_with_network_messages() {
|
|||
let (devtools_chan, devtools_port) = mpsc::channel::<DevtoolsControlMsg>();
|
||||
// This will probably have to be changed as it uses fake_root_pipeline_id which is marked for removal.
|
||||
let pipeline_id = PipelineId::fake_root_pipeline_id();
|
||||
let mut load_data = LoadData::new(url.clone(), Some(pipeline_id));
|
||||
let mut load_data = LoadData::new(LoadContext::Browsing, url.clone(), Some(pipeline_id));
|
||||
let mut request_headers = Headers::new();
|
||||
request_headers.set(Host { hostname: "bar.foo".to_owned(), port: None });
|
||||
load_data.headers = request_headers.clone();
|
||||
|
@ -506,7 +506,7 @@ fn test_request_and_response_message_from_devtool_without_pipeline_id() {
|
|||
|
||||
let url = url!("https://mozilla.com");
|
||||
let (devtools_chan, devtools_port) = mpsc::channel::<DevtoolsControlMsg>();
|
||||
let load_data = LoadData::new(url.clone(), None);
|
||||
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
let _ = load::<MockRequest>(load_data, hsts_list, cookie_jar, Some(devtools_chan), &Factory,
|
||||
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None));
|
||||
|
||||
|
@ -535,7 +535,7 @@ fn test_load_when_redirecting_from_a_post_should_rewrite_next_request_as_get() {
|
|||
}
|
||||
|
||||
let url = url!("http://mozilla.com");
|
||||
let mut load_data = LoadData::new(url.clone(), None);
|
||||
let mut load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
load_data.method = Method::Post;
|
||||
|
||||
let hsts_list = Arc::new(RwLock::new(HSTSList::new()));
|
||||
|
@ -564,7 +564,7 @@ fn test_load_should_decode_the_response_as_deflate_when_response_headers_have_co
|
|||
}
|
||||
|
||||
let url = url!("http://mozilla.com");
|
||||
let load_data = LoadData::new(url.clone(), None);
|
||||
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
|
||||
let hsts_list = Arc::new(RwLock::new(HSTSList::new()));
|
||||
let cookie_jar = Arc::new(RwLock::new(CookieStorage::new()));
|
||||
|
@ -598,7 +598,7 @@ fn test_load_should_decode_the_response_as_gzip_when_response_headers_have_conte
|
|||
}
|
||||
|
||||
let url = url!("http://mozilla.com");
|
||||
let load_data = LoadData::new(url.clone(), None);
|
||||
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
let hsts_list = Arc::new(RwLock::new(HSTSList::new()));
|
||||
let cookie_jar = Arc::new(RwLock::new(CookieStorage::new()));
|
||||
|
||||
|
@ -641,7 +641,7 @@ fn test_load_doesnt_send_request_body_on_any_redirect() {
|
|||
}
|
||||
|
||||
let url = url!("http://mozilla.com");
|
||||
let mut load_data = LoadData::new(url.clone(), None);
|
||||
let mut load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
load_data.data = Some(<[_]>::to_vec("Body on POST!".as_bytes()));
|
||||
|
||||
let hsts_list = Arc::new(RwLock::new(HSTSList::new()));
|
||||
|
@ -672,7 +672,7 @@ fn test_load_doesnt_add_host_to_sts_list_when_url_is_http_even_if_sts_headers_ar
|
|||
|
||||
let url = url!("http://mozilla.com");
|
||||
|
||||
let load_data = LoadData::new(url.clone(), None);
|
||||
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
|
||||
let hsts_list = Arc::new(RwLock::new(HSTSList::new()));
|
||||
let cookie_jar = Arc::new(RwLock::new(CookieStorage::new()));
|
||||
|
@ -705,7 +705,7 @@ fn test_load_adds_host_to_sts_list_when_url_is_https_and_sts_headers_are_present
|
|||
|
||||
let url = url!("https://mozilla.com");
|
||||
|
||||
let load_data = LoadData::new(url.clone(), None);
|
||||
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
|
||||
let hsts_list = Arc::new(RwLock::new(HSTSList::new()));
|
||||
let cookie_jar = Arc::new(RwLock::new(CookieStorage::new()));
|
||||
|
@ -743,7 +743,7 @@ fn test_load_sets_cookies_in_the_resource_manager_when_it_get_set_cookie_header_
|
|||
|
||||
assert_cookie_for_domain(cookie_jar.clone(), "http://mozilla.com", "");
|
||||
|
||||
let load_data = LoadData::new(url.clone(), None);
|
||||
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
|
||||
let _ = load::<MockRequest>(load_data,
|
||||
hsts_list,
|
||||
|
@ -760,7 +760,7 @@ fn test_load_sets_cookies_in_the_resource_manager_when_it_get_set_cookie_header_
|
|||
fn test_load_sets_requests_cookies_header_for_url_by_getting_cookies_from_the_resource_manager() {
|
||||
let url = url!("http://mozilla.com");
|
||||
|
||||
let mut load_data = LoadData::new(url.clone(), None);
|
||||
let mut load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
load_data.data = Some(<[_]>::to_vec("Yay!".as_bytes()));
|
||||
|
||||
let hsts_list = Arc::new(RwLock::new(HSTSList::new()));
|
||||
|
@ -806,7 +806,7 @@ fn test_load_sends_cookie_if_nonhttp() {
|
|||
cookie_jar.push(cookie, CookieSource::HTTP);
|
||||
}
|
||||
|
||||
let mut load_data = LoadData::new(url, None);
|
||||
let mut load_data = LoadData::new(LoadContext::Browsing, url, None);
|
||||
load_data.data = Some(<[_]>::to_vec("Yay!".as_bytes()));
|
||||
|
||||
let mut headers = Headers::new();
|
||||
|
@ -840,7 +840,7 @@ fn test_cookie_set_with_httponly_should_not_be_available_using_getcookiesforurl(
|
|||
let hsts_list = Arc::new(RwLock::new(HSTSList::new()));
|
||||
let cookie_jar = Arc::new(RwLock::new(CookieStorage::new()));
|
||||
|
||||
let load_data = LoadData::new(url.clone(), None);
|
||||
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
let _ = load::<MockRequest>(load_data, hsts_list,
|
||||
cookie_jar.clone(),
|
||||
None,
|
||||
|
@ -870,7 +870,7 @@ fn test_when_cookie_received_marked_secure_is_ignored_for_http() {
|
|||
let hsts_list = Arc::new(RwLock::new(HSTSList::new()));
|
||||
let cookie_jar = Arc::new(RwLock::new(CookieStorage::new()));
|
||||
|
||||
let load_data = LoadData::new(url!("http://mozilla.com"), None);
|
||||
let load_data = LoadData::new(LoadContext::Browsing, url!("http://mozilla.com"), None);
|
||||
let _ = load::<MockRequest>(load_data, hsts_list,
|
||||
cookie_jar.clone(),
|
||||
None,
|
||||
|
@ -901,7 +901,7 @@ fn test_when_cookie_set_marked_httpsonly_secure_isnt_sent_on_http_request() {
|
|||
cookie_jar.push(cookie, CookieSource::HTTP);
|
||||
}
|
||||
|
||||
let mut load_data = LoadData::new(url, None);
|
||||
let mut load_data = LoadData::new(LoadContext::Browsing, url, None);
|
||||
load_data.data = Some(<[_]>::to_vec("Yay!".as_bytes()));
|
||||
|
||||
assert_cookie_for_domain(cookie_jar.clone(), "https://mozilla.com", "mozillaIs=theBest");
|
||||
|
@ -919,7 +919,7 @@ fn test_load_sets_content_length_to_length_of_request_body() {
|
|||
let content = "This is a request body";
|
||||
|
||||
let url = url!("http://mozilla.com");
|
||||
let mut load_data = LoadData::new(url.clone(), None);
|
||||
let mut load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
load_data.data = Some(<[_]>::to_vec(content.as_bytes()));
|
||||
|
||||
let mut content_len_headers = Headers::new();
|
||||
|
@ -944,7 +944,7 @@ fn test_load_uses_explicit_accept_from_headers_in_load_data() {
|
|||
accept_headers.set(Accept(vec![text_html.clone()]));
|
||||
|
||||
let url = url!("http://mozilla.com");
|
||||
let mut load_data = LoadData::new(url.clone(), None);
|
||||
let mut load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
load_data.data = Some(<[_]>::to_vec("Yay!".as_bytes()));
|
||||
load_data.headers.set(Accept(vec![text_html.clone()]));
|
||||
|
||||
|
@ -973,7 +973,7 @@ fn test_load_sets_default_accept_to_html_xhtml_xml_and_then_anything_else() {
|
|||
]));
|
||||
|
||||
let url = url!("http://mozilla.com");
|
||||
let mut load_data = LoadData::new(url.clone(), None);
|
||||
let mut load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
load_data.data = Some(<[_]>::to_vec("Yay!".as_bytes()));
|
||||
|
||||
let hsts_list = Arc::new(RwLock::new(HSTSList::new()));
|
||||
|
@ -996,7 +996,7 @@ fn test_load_uses_explicit_accept_encoding_from_load_data_headers() {
|
|||
accept_encoding_headers.set(AcceptEncoding(vec![qitem(Encoding::Chunked)]));
|
||||
|
||||
let url = url!("http://mozilla.com");
|
||||
let mut load_data = LoadData::new(url.clone(), None);
|
||||
let mut load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
load_data.data = Some(<[_]>::to_vec("Yay!".as_bytes()));
|
||||
load_data.headers.set(AcceptEncoding(vec![qitem(Encoding::Chunked)]));
|
||||
|
||||
|
@ -1022,7 +1022,7 @@ fn test_load_sets_default_accept_encoding_to_gzip_and_deflate() {
|
|||
qitem(Encoding::EncodingExt("br".to_owned()))]));
|
||||
|
||||
let url = url!("http://mozilla.com");
|
||||
let mut load_data = LoadData::new(url.clone(), None);
|
||||
let mut load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
load_data.data = Some(<[_]>::to_vec("Yay!".as_bytes()));
|
||||
|
||||
let hsts_list = Arc::new(RwLock::new(HSTSList::new()));
|
||||
|
@ -1058,7 +1058,7 @@ fn test_load_errors_when_there_a_redirect_loop() {
|
|||
}
|
||||
|
||||
let url = url!("http://mozilla.com");
|
||||
let load_data = LoadData::new(url.clone(), None);
|
||||
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
|
||||
let hsts_list = Arc::new(RwLock::new(HSTSList::new()));
|
||||
let cookie_jar = Arc::new(RwLock::new(CookieStorage::new()));
|
||||
|
@ -1089,7 +1089,7 @@ fn test_load_errors_when_there_is_too_many_redirects() {
|
|||
}
|
||||
|
||||
let url = url!("http://mozilla.com");
|
||||
let load_data = LoadData::new(url.clone(), None);
|
||||
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
|
||||
let hsts_list = Arc::new(RwLock::new(HSTSList::new()));
|
||||
let cookie_jar = Arc::new(RwLock::new(CookieStorage::new()));
|
||||
|
@ -1128,7 +1128,7 @@ fn test_load_follows_a_redirect() {
|
|||
}
|
||||
|
||||
let url = url!("http://mozilla.com");
|
||||
let load_data = LoadData::new(url.clone(), None);
|
||||
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
|
||||
let hsts_list = Arc::new(RwLock::new(HSTSList::new()));
|
||||
let cookie_jar = Arc::new(RwLock::new(CookieStorage::new()));
|
||||
|
@ -1156,7 +1156,7 @@ impl HttpRequestFactory for DontConnectFactory {
|
|||
#[test]
|
||||
fn test_load_errors_when_scheme_is_not_http_or_https() {
|
||||
let url = url!("ftp://not-supported");
|
||||
let load_data = LoadData::new(url.clone(), None);
|
||||
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
|
||||
let hsts_list = Arc::new(RwLock::new(HSTSList::new()));
|
||||
let cookie_jar = Arc::new(RwLock::new(CookieStorage::new()));
|
||||
|
@ -1176,7 +1176,7 @@ fn test_load_errors_when_scheme_is_not_http_or_https() {
|
|||
#[test]
|
||||
fn test_load_errors_when_viewing_source_and_inner_url_scheme_is_not_http_or_https() {
|
||||
let url = url!("view-source:ftp://not-supported");
|
||||
let load_data = LoadData::new(url.clone(), None);
|
||||
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
|
||||
let hsts_list = Arc::new(RwLock::new(HSTSList::new()));
|
||||
let cookie_jar = Arc::new(RwLock::new(CookieStorage::new()));
|
||||
|
@ -1220,7 +1220,7 @@ fn test_load_errors_when_cancelled() {
|
|||
cancel_sender.send(()).unwrap();
|
||||
|
||||
let url = url!("https://mozilla.com");
|
||||
let load_data = LoadData::new(url.clone(), None);
|
||||
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), None);
|
||||
let hsts_list = Arc::new(RwLock::new(HSTSList::new()));
|
||||
let cookie_jar = Arc::new(RwLock::new(CookieStorage::new()));
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
use net::mime_classifier::as_string_option;
|
||||
use net::mime_classifier::{Mp4Matcher, MIMEClassifier, ApacheBugFlag, NoSniffFlag};
|
||||
use net_traits::LoadContext;
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::{self, Read};
|
||||
|
@ -55,7 +56,8 @@ fn test_sniff_with_flags(filename_orig: &path::Path,
|
|||
|
||||
match read_result {
|
||||
Ok(data) => {
|
||||
let (parsed_type, parsed_subtp) = classifier.classify(no_sniff_flag,
|
||||
let (parsed_type, parsed_subtp) = classifier.classify(LoadContext::Browsing,
|
||||
no_sniff_flag,
|
||||
apache_bug_flag,
|
||||
&as_string_option(supplied_type),
|
||||
&data);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use ipc_channel::ipc;
|
||||
use net::resource_task::new_resource_task;
|
||||
use net_traits::hosts::{parse_hostsfile, host_replacement};
|
||||
use net_traits::{ControlMsg, LoadData, LoadConsumer, ProgressMsg};
|
||||
use net_traits::{ControlMsg, LoadData, LoadConsumer, ProgressMsg, LoadContext};
|
||||
use std::borrow::ToOwned;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::mpsc::channel;
|
||||
|
@ -22,7 +22,8 @@ fn test_bad_scheme() {
|
|||
let resource_task = new_resource_task("".to_owned(), None);
|
||||
let (start_chan, start) = ipc::channel().unwrap();
|
||||
let url = url!("bogus://whatever");
|
||||
resource_task.send(ControlMsg::Load(LoadData::new(url, None), LoadConsumer::Channel(start_chan), None)).unwrap();
|
||||
resource_task.send(ControlMsg::Load(LoadData::new(LoadContext::Browsing, url, None),
|
||||
LoadConsumer::Channel(start_chan), None)).unwrap();
|
||||
let response = start.recv().unwrap();
|
||||
match response.progress_port.recv().unwrap() {
|
||||
ProgressMsg::Done(result) => { assert!(result.is_err()) }
|
||||
|
@ -201,7 +202,7 @@ fn test_cancelled_listener() {
|
|||
let (sync_sender, sync_receiver) = ipc::channel().unwrap();
|
||||
let url = Url::parse(&format!("http://127.0.0.1:{}", port)).unwrap();
|
||||
|
||||
resource_task.send(ControlMsg::Load(LoadData::new(url, None),
|
||||
resource_task.send(ControlMsg::Load(LoadData::new(LoadContext::Browsing, url, None),
|
||||
LoadConsumer::Channel(sender),
|
||||
Some(id_sender))).unwrap();
|
||||
// get the `ResourceId` and send a cancel message, which should stop the loading loop
|
||||
|
|
|
@ -5685,6 +5685,12 @@
|
|||
"url": "/_mozilla/mozilla/load_event.html"
|
||||
}
|
||||
],
|
||||
"mozilla/mime_sniffing_font_context.html": [
|
||||
{
|
||||
"path": "mozilla/mime_sniffing_font_context.html",
|
||||
"url": "/_mozilla/mozilla/mime_sniffing_font_context.html"
|
||||
}
|
||||
],
|
||||
"mozilla/mozbrowser/iframe_goback.html": [
|
||||
{
|
||||
"path": "mozilla/mozbrowser/iframe_goback.html",
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
[mime_sniffing_font_context.html]
|
||||
prefs: ['net.mime.sniff:true']
|
|
@ -0,0 +1,85 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>Sniffed Content-Type for @font-face is different than XHR</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: MimelessAhem;
|
||||
src: url(resources/no_mime_type.py);
|
||||
}
|
||||
@font-face {
|
||||
font-family: XMLAhem;
|
||||
src: url(resources/no_mime_type.py?Content-Type=application/xml);
|
||||
}
|
||||
@font-face {
|
||||
font-family: XHTMLXMLAhem;
|
||||
src: url(resources/no_mime_type.py?Content-Type=application/xhtml%2Bxml);
|
||||
}
|
||||
#first {
|
||||
font-family: MimelessAhem, serif;
|
||||
}
|
||||
#second, #fourth, #sixth {
|
||||
font-family: serif;
|
||||
}
|
||||
#third {
|
||||
font-family: XMLAhem, serif;
|
||||
}
|
||||
#fifth {
|
||||
font-family: XHTMLXMLAhem, serif;
|
||||
}
|
||||
</style>
|
||||
<span id="first">w</span> <span id="second">w</span><br>
|
||||
<span id="third">w</span> <span id="fourth">w</span><br>
|
||||
<span id="fifth">w</span> <span id="sixth">w</span><br>
|
||||
<script>
|
||||
var t2 = async_test("Sniffed font is loaded and applied");
|
||||
var t3 = async_test("Sniffed font with xml is not loaded");
|
||||
var t4 = async_test("Sniffed font with xhtml+xml is not loaded");
|
||||
|
||||
async_test(function() {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', 'resources/no_mime_type.py', true);
|
||||
xhr.onload = this.step_func_done(function() {
|
||||
assert_equals(xhr.getResponseHeader('Content-Type'), null);
|
||||
t2.step_timeout(checkFontLoaded, 500);
|
||||
});
|
||||
xhr.send();
|
||||
}, "XHR Content-Type is empty");
|
||||
|
||||
async_test(function() {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', 'resources/no_mime_type.py?Content-Type=application/xhtml%2Bxml', true);
|
||||
xhr.onload = this.step_func_done(function() {
|
||||
t4.step_timeout(checkFontNotLoaded.bind(t4, 'fifth', 'sixth'), 500);
|
||||
assert_equals(xhr.getResponseHeader('Content-Type'), 'application/xhtml+xml');
|
||||
});
|
||||
xhr.send();
|
||||
}, "XHR Content-Type has xhtml+xml");
|
||||
|
||||
async_test(function() {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', 'resources/no_mime_type.py?Content-Type=application/xml', true);
|
||||
xhr.onload = this.step_func_done(function() {
|
||||
t3.step_timeout(checkFontNotLoaded.bind(t3, 'third', 'fourth'), 500);
|
||||
assert_equals(xhr.getResponseHeader('Content-Type'), 'application/xml');
|
||||
});
|
||||
xhr.send();
|
||||
}, "XHR Content-Type has xml");
|
||||
|
||||
function checkFontLoaded() {
|
||||
var first = document.getElementById('first');
|
||||
var second = document.getElementById('second');
|
||||
assert_not_equals(first.getBoundingClientRect().width, second.getBoundingClientRect().width);
|
||||
assert_not_equals(first.getBoundingClientRect().height, second.getBoundingClientRect().height);
|
||||
this.done();
|
||||
}
|
||||
|
||||
function checkFontNotLoaded(id1, id2) {
|
||||
var first = document.getElementById(id1);
|
||||
var second = document.getElementById(id2);
|
||||
assert_equals(first.getBoundingClientRect().width, second.getBoundingClientRect().width);
|
||||
assert_equals(first.getBoundingClientRect().height, second.getBoundingClientRect().height);
|
||||
this.done();
|
||||
}
|
||||
</script>
|
11
tests/wpt/mozilla/tests/mozilla/resources/no_mime_type.py
Normal file
11
tests/wpt/mozilla/tests/mozilla/resources/no_mime_type.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
|
||||
def main(request, response):
|
||||
headers = []
|
||||
if 'Content-Type' in request.GET:
|
||||
headers += [('Content-Type', request.GET['Content-Type'])]
|
||||
with open('./resources/ahem/AHEM____.TTF') as f:
|
||||
return 200, headers, f.read()
|
Loading…
Add table
Add a link
Reference in a new issue