diff --git a/components/gfx/font_cache_thread.rs b/components/gfx/font_cache_thread.rs index e921f41fcf90..474eef7df15c 100644 --- a/components/gfx/font_cache_thread.rs +++ b/components/gfx/font_cache_thread.rs @@ -5,9 +5,8 @@ use font_template::{FontTemplate, FontTemplateDescriptor}; use fontsan; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; -use ipc_channel::router::ROUTER; -use mime::{TopLevel, SubLevel}; -use net_traits::{AsyncResponseTarget, LoadContext, CoreResourceThread, ResponseAction, load_async}; +use net_traits::{CoreResourceThread, FetchResponseMsg, fetch_async, FetchMetadata}; +use net_traits::request::{Destination, RequestInit, Type as RequestType}; use platform::font_context::FontContextHandle; use platform::font_list::SANS_SERIF_FONT_FAMILY; use platform::font_list::for_each_available_family; @@ -25,7 +24,6 @@ use string_cache::Atom; use style::font_face::{EffectiveSources, Source}; use style::properties::longhands::font_family::computed_value::FontFamily; use url::Url; -use util::prefs::PREFS; use util::thread::spawn_named; use webrender_traits; @@ -206,49 +204,33 @@ impl FontCache { } match src { - Source::Url(ref url_source) => { - let url = &url_source.url; - let (data_sender, data_receiver) = ipc::channel().unwrap(); - let data_target = AsyncResponseTarget { - sender: data_sender, + Source::Url(url_source) => { + // https://drafts.csswg.org/css-fonts/#font-fetching-requirements + let url = url_source.url; + let request = RequestInit { + url: url.clone(), + type_: RequestType::Font, + destination: Destination::Font, + origin: url.clone(), + .. RequestInit::default() }; - load_async(LoadContext::Font, - self.core_resource_thread.clone(), - url.clone(), - None, - None, - None, - data_target); + 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(); + fetch_async(request, &self.core_resource_thread, move |response| { match response { - ResponseAction::HeadersAvailable(meta_result) => { - let is_response_valid = match meta_result { - Ok(ref metadata) => { - metadata.content_type.as_ref().map_or(false, |content_type| { - let mime = &content_type.0; - is_supported_font_type(&(mime.0).0, &mime.1) - }) - } - Err(_) => false, - }; - - info!("{} font with MIME type {}", - if is_response_valid { "Loading" } else { "Ignoring" }, - meta_result.map(|ref meta| format!("{:?}", meta.content_type)) - .unwrap_or(format!(""))); - *response_valid.lock().unwrap() = is_response_valid; + FetchResponseMsg::ProcessRequestBody | + FetchResponseMsg::ProcessRequestEOF => (), + FetchResponseMsg::ProcessResponse(meta_result) => { + *response_valid.lock().unwrap() = meta_result.is_ok(); } - ResponseAction::DataAvailable(new_bytes) => { + FetchResponseMsg::ProcessResponseChunk(new_bytes) => { if *response_valid.lock().unwrap() { bytes.lock().unwrap().extend(new_bytes.into_iter()) } } - ResponseAction::ResponseComplete(response) => { + FetchResponseMsg::ProcessResponseEOF(response) => { if response.is_err() || !*response_valid.lock().unwrap() { let msg = Command::AddWebFont(family_name.clone(), sources.clone(), sender.clone()); channel_to_self.send(msg).unwrap(); @@ -480,25 +462,6 @@ impl FontCacheThread { } } -// derived from http://stackoverflow.com/a/10864297/3830 -fn is_supported_font_type(toplevel: &TopLevel, sublevel: &SubLevel) -> bool { - if !PREFS.get("network.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, - } -} - #[derive(Clone, Eq, PartialEq, Hash, Debug, Deserialize, Serialize)] pub struct LowercaseString { diff --git a/components/net/image_cache_thread.rs b/components/net/image_cache_thread.rs index 8925e6198ca2..440ebd321002 100644 --- a/components/net/image_cache_thread.rs +++ b/components/net/image_cache_thread.rs @@ -5,13 +5,12 @@ use immeta::load_from_buf; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use ipc_channel::router::ROUTER; -use msg::constellation_msg::{PipelineId, ReferrerPolicy}; -use net_traits::{AsyncResponseTarget, CoreResourceMsg, CoreResourceThread, LoadConsumer, LoadData, LoadOrigin}; -use net_traits::{LoadContext, NetworkError, ResponseAction}; +use net_traits::{CoreResourceThread, NetworkError, fetch_async, FetchResponseMsg, FetchMetadata, Metadata}; use net_traits::image::base::{Image, ImageMetadata, PixelFormat, load_from_memory}; use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheCommand, ImageCacheThread, ImageState}; use net_traits::image_cache_thread::{ImageCacheResult, ImageOrMetadataAvailable, ImageResponse, UsePlaceholder}; use net_traits::image_cache_thread::ImageResponder; +use net_traits::request::{Destination, RequestInit, Type as RequestType}; use std::borrow::ToOwned; use std::collections::HashMap; use std::collections::hash_map::Entry::{Occupied, Vacant}; @@ -226,6 +225,15 @@ impl ImageListener { } } +/// A legacy type that's mostly redundant with FetchResponseMsg. +// FIXME(#13717): remove this type. +#[derive(Deserialize, Serialize)] +enum ResponseAction { + HeadersAvailable(Result), + DataAvailable(Vec), + ResponseComplete(Result<(), NetworkError>) +} + struct ResourceLoadInfo { action: ResponseAction, key: LoadKey, @@ -305,19 +313,6 @@ fn convert_format(format: PixelFormat) -> webrender_traits::ImageFormat { } } -struct ImageCacheOrigin; -impl LoadOrigin for ImageCacheOrigin { - fn referrer_url(&self) -> Option { - None - } - fn referrer_policy(&self) -> Option { - None - } - fn pipeline_id(&self) -> Option { - None - } -} - fn get_placeholder_image(webrender_api: &webrender_traits::RenderApi) -> io::Result> { let mut placeholder_path = try!(resources_dir_path()); placeholder_path.push("rippy.png"); @@ -530,25 +525,41 @@ impl ImageCache { CacheResult::Miss => { // A new load request! Request the load from // the resource thread. - let load_data = LoadData::new(LoadContext::Image, - (*ref_url).clone(), - &ImageCacheOrigin); - let (action_sender, action_receiver) = ipc::channel().unwrap(); - let response_target = AsyncResponseTarget { - sender: action_sender, + // https://html.spec.whatwg.org/multipage/#update-the-image-data + // step 12. + let request = RequestInit { + url: (*ref_url).clone(), + type_: RequestType::Image, + destination: Destination::Image, + origin: (*ref_url).clone(), + .. RequestInit::default() }; - let msg = CoreResourceMsg::Load(load_data, - LoadConsumer::Listener(response_target), - None); + let progress_sender = self.progress_sender.clone(); - ROUTER.add_route(action_receiver.to_opaque(), box move |message| { - let action: ResponseAction = message.to().unwrap(); + fetch_async(request, &self.core_resource_thread, move |action| { + let action = match action { + FetchResponseMsg::ProcessRequestBody | + FetchResponseMsg::ProcessRequestEOF => return, + FetchResponseMsg::ProcessResponse(meta_result) => { + ResponseAction::HeadersAvailable(meta_result.map(|m| { + match m { + FetchMetadata::Unfiltered(m) => m, + FetchMetadata::Filtered { unsafe_, .. } => unsafe_ + } + })) + } + FetchResponseMsg::ProcessResponseChunk(new_bytes) => { + ResponseAction::DataAvailable(new_bytes) + } + FetchResponseMsg::ProcessResponseEOF(response) => { + ResponseAction::ResponseComplete(response) + } + }; progress_sender.send(ResourceLoadInfo { action: action, key: load_key, }).unwrap(); }); - self.core_resource_thread.send(msg).unwrap(); } CacheResult::Hit => { // Request is already on its way. diff --git a/components/net/resource_thread.rs b/components/net/resource_thread.rs index e6606b87b8c5..3724641c5bf9 100644 --- a/components/net/resource_thread.rs +++ b/components/net/resource_thread.rs @@ -24,8 +24,8 @@ use hyper::mime::{Mime, SubLevel, TopLevel}; use hyper_serde::Serde; use ipc_channel::ipc::{self, IpcReceiver, IpcReceiverSet, IpcSender}; use mime_classifier::{ApacheBugFlag, MimeClassifier, NoSniffFlag}; -use net_traits::{AsyncResponseTarget, CoreResourceThread, Metadata, ProgressMsg, ResponseAction}; -use net_traits::{CookieSource, CoreResourceMsg, FetchResponseMsg, FetchTaskTarget, LoadConsumer}; +use net_traits::{CookieSource, CoreResourceThread, Metadata, ProgressMsg}; +use net_traits::{CoreResourceMsg, FetchResponseMsg, FetchTaskTarget, LoadConsumer}; use net_traits::{CustomResponseMediator, LoadData, LoadResponse, NetworkError, ResourceId}; use net_traits::{ResourceThreads, WebSocketCommunicate, WebSocketConnectData}; use net_traits::LoadContext; @@ -57,7 +57,6 @@ const TFD_PROVIDER: &'static TFDProvider = &TFDProvider; pub enum ProgressSender { Channel(IpcSender), - Listener(AsyncResponseTarget), } #[derive(Clone)] @@ -73,14 +72,6 @@ impl ProgressSender { pub fn send(&self, msg: ProgressMsg) -> Result<(), ()> { match *self { ProgressSender::Channel(ref c) => c.send(msg).map_err(|_| ()), - ProgressSender::Listener(ref b) => { - let action = match msg { - ProgressMsg::Payload(buf) => ResponseAction::DataAvailable(buf), - ProgressMsg::Done(status) => ResponseAction::ResponseComplete(status), - }; - b.invoke_with_listener(action); - Ok(()) - } } } } @@ -89,7 +80,7 @@ pub fn send_error(url: Url, err: NetworkError, start_chan: LoadConsumer) { let mut metadata: Metadata = Metadata::default(url); metadata.status = None; - if let Ok(p) = start_sending_opt(start_chan, metadata, Some(err.clone())) { + if let Ok(p) = start_sending_opt(start_chan, metadata) { p.send(Done(Err(err))).unwrap(); } } @@ -130,14 +121,13 @@ pub fn start_sending_sniffed_opt(start_chan: LoadConsumer, mut metadata: Metadat Some(Serde(ContentType(Mime(mime_tp, mime_sb, vec![])))); } - start_sending_opt(start_chan, metadata, None) + start_sending_opt(start_chan, metadata) } /// For use by loaders in responding to a Load message. /// It takes an optional NetworkError, so that we can extract the SSL Validation errors /// and take it to the HTML parser -fn start_sending_opt(start_chan: LoadConsumer, metadata: Metadata, - network_error: Option) -> Result { +fn start_sending_opt(start_chan: LoadConsumer, metadata: Metadata) -> Result { match start_chan { LoadConsumer::Channel(start_chan) => { let (progress_chan, progress_port) = ipc::channel().unwrap(); @@ -150,16 +140,6 @@ fn start_sending_opt(start_chan: LoadConsumer, metadata: Metadata, Err(_) => Err(()) } } - LoadConsumer::Listener(target) => { - match network_error { - Some(NetworkError::SslValidation(url, reason)) => { - let error = NetworkError::SslValidation(url, reason); - target.invoke_with_listener(ResponseAction::HeadersAvailable(Err(error))); - } - _ => target.invoke_with_listener(ResponseAction::HeadersAvailable(Ok(metadata))), - } - Ok(ProgressSender::Listener(target)) - } } } diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs index aad61971fd79..39c5d0f87769 100644 --- a/components/net_traits/lib.rs +++ b/components/net_traits/lib.rs @@ -46,6 +46,7 @@ use hyper::method::Method; use hyper::mime::{Attr, Mime}; use hyper_serde::Serde; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; +use ipc_channel::router::ROUTER; use msg::constellation_msg::{PipelineId, ReferrerPolicy}; use request::{Request, RequestInit}; use response::{HttpsState, Response}; @@ -262,18 +263,6 @@ pub trait Action { fn process(self, listener: &mut Listener); } -/// Data for passing between threads/processes to indicate a particular action to -/// take on a provided network listener. -#[derive(Deserialize, Serialize)] -pub enum ResponseAction { - /// Invoke headers_available - HeadersAvailable(Result), - /// Invoke data_available - DataAvailable(Vec), - /// Invoke response_complete - ResponseComplete(Result<(), NetworkError>) -} - impl Action for FetchResponseMsg { /// Execute the default action on a provided listener. fn process(self, listener: &mut T) { @@ -287,24 +276,10 @@ impl Action for FetchResponseMsg { } } -/// A target for async networking events. Commonly used to dispatch a runnable event to another -/// thread storing the wrapped closure for later execution. -#[derive(Deserialize, Serialize)] -pub struct AsyncResponseTarget { - pub sender: IpcSender, -} - -impl AsyncResponseTarget { - pub fn invoke_with_listener(&self, action: ResponseAction) { - self.sender.send(action).unwrap() - } -} - /// A wrapper for a network load that can either be channel or event-based. #[derive(Deserialize, Serialize)] pub enum LoadConsumer { Channel(IpcSender), - Listener(AsyncResponseTarget), } /// Handle to a resource thread @@ -446,40 +421,17 @@ pub enum CoreResourceMsg { Exit(IpcSender<()>), } -struct LoadOriginData { - pipeline: Option, - referrer_policy: Option, - referrer_url: Option -} - -impl LoadOrigin for LoadOriginData { - fn referrer_url(&self) -> Option { - self.referrer_url.clone() - } - fn referrer_policy(&self) -> Option { - self.referrer_policy.clone() - } - fn pipeline_id(&self) -> Option { - self.pipeline - } -} - /// Instruct the resource thread to make a new request. -pub fn load_async(context: LoadContext, - core_resource_thread: CoreResourceThread, - url: Url, - pipeline: Option, - referrer_policy: Option, - referrer_url: Option, - listener: AsyncResponseTarget) { - let load = LoadOriginData { - pipeline: pipeline, - referrer_policy: referrer_policy, - referrer_url: referrer_url - }; - let load_data = LoadData::new(context, url, &load); - let consumer = LoadConsumer::Listener(listener); - core_resource_thread.send(CoreResourceMsg::Load(load_data, consumer, None)).unwrap(); +pub fn fetch_async(request: RequestInit, + core_resource_thread: &CoreResourceThread, + f: F) + where F: Fn(FetchResponseMsg) + Send + 'static +{ + let (action_sender, action_receiver) = ipc::channel().unwrap(); + ROUTER.add_route(action_receiver.to_opaque(), box move |message| { + f(message.to().unwrap()); + }); + core_resource_thread.send(CoreResourceMsg::Fetch(request, action_sender)).unwrap(); } /// Message sent in response to `Load`. Contains metadata, and a port diff --git a/tests/wpt/mozilla/meta/mozilla/mime_sniffing_font_context.html.ini b/tests/wpt/mozilla/meta/mozilla/mime_sniffing_font_context.html.ini index 567ecfaa9cf1..f58ef7e15c72 100644 --- a/tests/wpt/mozilla/meta/mozilla/mime_sniffing_font_context.html.ini +++ b/tests/wpt/mozilla/meta/mozilla/mime_sniffing_font_context.html.ini @@ -1,3 +1,2 @@ [mime_sniffing_font_context.html] type: testharness - prefs: [network.mime.sniff:true] diff --git a/tests/wpt/mozilla/tests/mozilla/mime_sniffing_font_context.html b/tests/wpt/mozilla/tests/mozilla/mime_sniffing_font_context.html index 8112a99f4314..2182b7fcbd80 100644 --- a/tests/wpt/mozilla/tests/mozilla/mime_sniffing_font_context.html +++ b/tests/wpt/mozilla/tests/mozilla/mime_sniffing_font_context.html @@ -51,8 +51,8 @@ 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'); + t4.step_timeout(checkFontLoaded, 500); }); xhr.send(); }, "XHR Content-Type has xhtml+xml"); @@ -61,8 +61,8 @@ 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'); + t3.step_timeout(checkFontLoaded, 500); }); xhr.send(); }, "XHR Content-Type has xml");