Resolves #4183 - Implemementing context-based MIME type sniffing

The version of the standard is not finalized at the time of this writing.
Specifications may be found here: https://mimesniff.spec.whatwg.org/#context-specific-sniffing .
This commit is contained in:
David Rajchenbach-Teller 2015-09-30 12:22:00 +02:00 committed by Josh Matthews
parent 66c8aa8cda
commit 1e81b8c133
18 changed files with 226 additions and 93 deletions

View file

@ -5,7 +5,7 @@
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 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;
@ -156,7 +156,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();

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,13 +35,18 @@ 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 {
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;
@ -52,16 +59,81 @@ impl MIMEClassifier {
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
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![

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};
@ -65,14 +66,16 @@ 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 {
// TODO: should be calculated in the resource loader, from pull requeset #4094
@ -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

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