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:
bors-servo 2015-12-31 21:13:10 +05:30
commit af1690f303
29 changed files with 387 additions and 122 deletions

View file

@ -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"

View file

@ -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,
}
}

View file

@ -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]

View file

@ -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

View file

@ -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(())));
}

View file

@ -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)
}
}

View file

@ -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
};

View file

@ -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,

View file

@ -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",

View file

@ -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);

View file

@ -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();

View file

@ -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);

View file

@ -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,

View file

@ -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())

View file

@ -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();
}

View file

@ -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(),

View file

@ -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)",

View file

@ -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
View file

@ -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
View file

@ -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)",

View file

@ -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"
}

View file

@ -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));

View file

@ -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()));

View file

@ -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);

View file

@ -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

View file

@ -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",

View file

@ -0,0 +1,2 @@
[mime_sniffing_font_context.html]
prefs: ['net.mime.sniff:true']

View file

@ -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>

View 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()