aboutsummaryrefslogtreecommitdiffstats
path: root/components/net/http_loader.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/net/http_loader.rs')
-rw-r--r--components/net/http_loader.rs593
1 files changed, 10 insertions, 583 deletions
diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs
index f40934d5e7c..69dcf1dddcd 100644
--- a/components/net/http_loader.rs
+++ b/components/net/http_loader.rs
@@ -4,90 +4,39 @@
use brotli::Decompressor;
use connector::Connector;
-use content_blocker_parser::{LoadType, Reaction, Request as CBRequest, ResourceType};
-use content_blocker_parser::{RuleList, process_rules_for_request};
+use content_blocker_parser::RuleList;
use cookie;
use cookie_storage::CookieStorage;
use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg, HttpRequest as DevtoolsHttpRequest};
use devtools_traits::{HttpResponse as DevtoolsHttpResponse, NetworkEvent};
use flate2::read::{DeflateDecoder, GzDecoder};
-use fnv::FnvHashSet;
-use hsts::{HstsEntry, HstsList, secure_url};
+use hsts::HstsList;
use hyper::Error as HttpError;
use hyper::LanguageTag;
use hyper::client::{Pool, Request, Response};
-use hyper::header::{Accept, AcceptEncoding, ContentEncoding, ContentLength, ContentType, Host, Referer};
-use hyper::header::{AcceptLanguage, Authorization, Basic};
-use hyper::header::{Encoding, Header, Headers, Quality, QualityItem};
-use hyper::header::{Location, SetCookie, StrictTransportSecurity, UserAgent, qitem};
+use hyper::header::{AcceptEncoding, AcceptLanguage, Basic, ContentEncoding, ContentLength};
+use hyper::header::{Encoding, Header, Headers, Quality, QualityItem, Referer};
+use hyper::header::{SetCookie, qitem};
use hyper::http::RawStatus;
use hyper::method::Method;
-use hyper::mime::{Mime, SubLevel, TopLevel};
use hyper::net::Fresh;
-use hyper::status::{StatusClass, StatusCode};
-use hyper_serde::Serde;
-use ipc_channel::ipc::{self, IpcSender};
+use hyper::status::StatusCode;
use log;
-use mime_classifier::MimeClassifier;
use msg::constellation_msg::PipelineId;
-use net_traits::{CookieSource, IncludeSubdomains, LoadConsumer, LoadContext, LoadData};
-use net_traits::{CustomResponse, CustomResponseMediator, Metadata, NetworkError, ReferrerPolicy};
-use net_traits::ProgressMsg::{Done, Payload};
+use net_traits::{CookieSource, Metadata, ReferrerPolicy};
use net_traits::hosts::replace_hosts;
-use net_traits::response::HttpsState;
use openssl;
use openssl::ssl::error::{OpensslError, SslError};
-use profile_traits::time::{ProfilerCategory, ProfilerChan, TimerMetadata, profile};
-use profile_traits::time::{TimerMetadataFrameType, TimerMetadataReflowType};
-use resource_thread::{AuthCache, AuthCacheEntry, CancellationListener, send_error, start_sending_sniffed_opt};
+use resource_thread::{AuthCache, CancellationListener};
use servo_url::ServoUrl;
-use std::borrow::{Cow, ToOwned};
-use std::boxed::FnBox;
use std::error::Error;
use std::fmt;
-use std::io::{self, Cursor, Read, Write};
-use std::ops::Deref;
+use std::io::{self, Read, Write};
use std::sync::{Arc, RwLock};
use std::sync::mpsc::Sender;
use time;
use time::Tm;
-#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
-use tinyfiledialogs;
-use url::{Position, Origin};
-use util::thread::spawn_named;
-use uuid;
-
-pub fn factory(user_agent: Cow<'static, str>,
- http_state: HttpState,
- devtools_chan: Option<Sender<DevtoolsControlMsg>>,
- profiler_chan: ProfilerChan,
- swmanager_chan: Option<IpcSender<CustomResponseMediator>>,
- connector: Arc<Pool<Connector>>)
- -> Box<FnBox(LoadData,
- LoadConsumer,
- Arc<MimeClassifier>,
- CancellationListener) + Send> {
- box move |load_data: LoadData, senders, classifier, cancel_listener| {
- spawn_named(format!("http_loader for {}", load_data.url), move || {
- let metadata = TimerMetadata {
- url: load_data.url.as_str().into(),
- iframe: TimerMetadataFrameType::RootWindow,
- incremental: TimerMetadataReflowType::FirstReflow,
- };
- profile(ProfilerCategory::NetHTTPRequestResponse, Some(metadata), profiler_chan, || {
- load_for_consumer(load_data,
- senders,
- classifier,
- connector,
- http_state,
- devtools_chan,
- swmanager_chan,
- cancel_listener,
- user_agent)
- })
- })
- }
-}
+use url::Origin;
pub enum ReadResult {
Payload(Vec<u8>),
@@ -129,40 +78,6 @@ fn precise_time_ms() -> u64 {
time::precise_time_ns() / (1000 * 1000)
}
-fn load_for_consumer(load_data: LoadData,
- start_chan: LoadConsumer,
- classifier: Arc<MimeClassifier>,
- connector: Arc<Pool<Connector>>,
- http_state: HttpState,
- devtools_chan: Option<Sender<DevtoolsControlMsg>>,
- swmanager_chan: Option<IpcSender<CustomResponseMediator>>,
- cancel_listener: CancellationListener,
- user_agent: Cow<'static, str>) {
- let factory = NetworkHttpRequestFactory {
- connector: connector,
- };
-
- let ui_provider = TFDProvider;
- match load(&load_data, &ui_provider, &http_state,
- devtools_chan, &factory,
- user_agent, &cancel_listener, swmanager_chan) {
- Err(error) => {
- match error.error {
- LoadErrorType::ConnectionAborted { .. } => unreachable!(),
- LoadErrorType::Ssl { reason } => send_error(error.url.clone(),
- NetworkError::SslValidation(error.url, reason),
- start_chan),
- LoadErrorType::Cancelled => send_error(error.url, NetworkError::LoadCancelled, start_chan),
- _ => send_error(error.url, NetworkError::Internal(error.error.description().to_owned()), start_chan)
- }
- }
- Ok(mut load_response) => {
- let metadata = load_response.metadata.clone();
- send_data(load_data.context, &mut load_response, start_chan, metadata, classifier, &cancel_listener)
- }
- }
-}
-
pub struct WrappedHttpResponse {
pub response: Response
}
@@ -216,34 +131,6 @@ impl HttpResponse for WrappedHttpResponse {
}
}
-pub struct ReadableCustomResponse {
- headers: Headers,
- raw_status: RawStatus,
- body: Cursor<Vec<u8>>
-}
-
-pub fn to_readable_response(custom_response: CustomResponse) -> ReadableCustomResponse {
- ReadableCustomResponse {
- headers: custom_response.headers,
- raw_status: custom_response.raw_status,
- body: Cursor::new(custom_response.body)
- }
-}
-
-impl HttpResponse for ReadableCustomResponse {
- fn headers(&self) -> &Headers { &self.headers }
- fn status(&self) -> StatusCode {
- StatusCode::Ok
- }
- fn status_raw(&self) -> &RawStatus { &self.raw_status }
-}
-
-impl Read for ReadableCustomResponse {
- fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
- self.body.read(buf)
- }
-}
-
pub trait HttpRequestFactory {
type R: HttpRequest;
@@ -356,15 +243,8 @@ pub enum LoadErrorType {
Cancelled,
Connection { reason: String },
ConnectionAborted { reason: String },
- ContentBlocked,
- // Preflight fetch inconsistent with main fetch
- CorsPreflightFetchInconsistent,
Decoding { reason: String },
- InvalidRedirect { reason: String },
- MaxRedirects(u32), // u32 indicates number of redirects that occurred
- RedirectLoop,
Ssl { reason: String },
- UnsupportedScheme { scheme: String },
}
impl fmt::Display for LoadErrorType {
@@ -379,14 +259,8 @@ impl Error for LoadErrorType {
LoadErrorType::Cancelled => "load cancelled",
LoadErrorType::Connection { ref reason } => reason,
LoadErrorType::ConnectionAborted { ref reason } => reason,
- LoadErrorType::ContentBlocked => "content blocked",
- LoadErrorType::CorsPreflightFetchInconsistent => "preflight fetch inconsistent with main fetch",
LoadErrorType::Decoding { ref reason } => reason,
- LoadErrorType::InvalidRedirect { ref reason } => reason,
- LoadErrorType::MaxRedirects(_) => "too many redirects",
- LoadErrorType::RedirectLoop => "redirect loop",
LoadErrorType::Ssl { ref reason } => reason,
- LoadErrorType::UnsupportedScheme { .. } => "unsupported url scheme",
}
}
}
@@ -403,18 +277,6 @@ pub fn set_default_accept_encoding(headers: &mut Headers) {
]));
}
-fn set_default_accept(headers: &mut Headers) {
- if !headers.has::<Accept>() {
- let accept = Accept(vec![
- qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])),
- qitem(Mime(TopLevel::Application, SubLevel::Ext("xhtml+xml".to_owned()), vec![])),
- QualityItem::new(Mime(TopLevel::Application, SubLevel::Xml, vec![]), Quality(900u16)),
- QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]), Quality(800u16)),
- ]);
- headers.set(accept);
- }
-}
-
pub fn set_default_accept_language(headers: &mut Headers) {
if headers.has::<AcceptLanguage>() {
return;
@@ -535,33 +397,6 @@ pub fn set_cookies_from_headers(url: &ServoUrl, headers: &Headers, cookie_jar: &
}
}
-fn update_sts_list_from_response(url: &ServoUrl, response: &HttpResponse, hsts_list: &Arc<RwLock<HstsList>>) {
- if url.scheme() != "https" {
- return;
- }
-
- if let Some(header) = response.headers().get::<StrictTransportSecurity>() {
- if let Some(host) = url.domain() {
- let mut hsts_list = hsts_list.write().unwrap();
- let include_subdomains = if header.include_subdomains {
- IncludeSubdomains::Included
- } else {
- IncludeSubdomains::NotIncluded
- };
-
- if let Some(entry) = HstsEntry::new(host.to_owned(), include_subdomains, Some(header.max_age)) {
- info!("adding host {} to the strict transport security list", host);
- info!("- max-age {}", header.max_age);
- if header.include_subdomains {
- info!("- includeSubdomains");
- }
-
- hsts_list.push(entry);
- }
- }
- }
-}
-
pub struct StreamedResponse {
decoder: Decoder,
pub metadata: Metadata
@@ -662,63 +497,6 @@ pub fn send_response_to_devtools(devtools_chan: &Sender<DevtoolsControlMsg>,
let _ = devtools_chan.send(DevtoolsControlMsg::FromChrome(msg));
}
-fn request_must_be_secured(url: &ServoUrl, hsts_list: &Arc<RwLock<HstsList>>) -> bool {
- match url.domain() {
- Some(domain) => hsts_list.read().unwrap().is_host_secure(domain),
- None => false
- }
-}
-
-pub fn modify_request_headers(headers: &mut Headers,
- url: &ServoUrl,
- user_agent: &str,
- referrer_policy: Option<ReferrerPolicy>,
- referrer_url: &mut Option<ServoUrl>) {
- // Ensure that the host header is set from the original url
- let host = Host {
- hostname: url.host_str().unwrap().to_owned(),
- port: url.port_or_known_default()
- };
- headers.set(host);
-
- // If the user-agent has not already been set, then use the
- // browser's default user-agent or the user-agent override
- // from the command line. If the user-agent is set, don't
- // modify it, as setting of the user-agent by the user is
- // allowed.
- // https://fetch.spec.whatwg.org/#concept-http-network-or-cache-fetch step 8
- if !headers.has::<UserAgent>() {
- headers.set(UserAgent(user_agent.to_owned()));
- }
-
- set_default_accept(headers);
- set_default_accept_language(headers);
- set_default_accept_encoding(headers);
-
- *referrer_url = determine_request_referrer(headers,
- referrer_policy.clone(),
- referrer_url.clone(),
- url.clone());
-
- if let Some(referrer_val) = referrer_url.clone() {
- headers.set(Referer(referrer_val.into_string()));
- }
-}
-
-fn set_auth_header(headers: &mut Headers,
- url: &ServoUrl,
- auth_cache: &Arc<RwLock<AuthCache>>) {
- if !headers.has::<Authorization<Basic>>() {
- if let Some(auth) = auth_from_url(url) {
- headers.set(auth);
- } else {
- if let Some(basic) = auth_from_cache(auth_cache, &url.origin()) {
- headers.set(Authorization(basic));
- }
- }
- }
-}
-
pub fn auth_from_cache(auth_cache: &Arc<RwLock<AuthCache>>, origin: &Origin) -> Option<Basic> {
if let Some(ref auth_entry) = auth_cache.read().unwrap().entries.get(&origin.ascii_serialization()) {
let user_name = auth_entry.user_name.clone();
@@ -729,37 +507,6 @@ pub fn auth_from_cache(auth_cache: &Arc<RwLock<AuthCache>>, origin: &Origin) ->
}
}
-fn auth_from_url(doc_url: &ServoUrl) -> Option<Authorization<Basic>> {
- let username = doc_url.username();
- if username != "" {
- Some(Authorization(Basic {
- username: username.to_owned(),
- password: Some(doc_url.password().unwrap_or("").to_owned())
- }))
- } else {
- None
- }
-}
-
-pub fn process_response_headers(response: &HttpResponse,
- url: &ServoUrl,
- cookie_jar: &Arc<RwLock<CookieStorage>>,
- hsts_list: &Arc<RwLock<HstsList>>,
- load_data: &LoadData) {
- info!("got HTTP response {}, headers:", response.status());
- if log_enabled!(log::LogLevel::Info) {
- for header in response.headers().iter() {
- info!(" - {}", header);
- }
- }
-
- // https://fetch.spec.whatwg.org/#concept-http-network-fetch step 9
- if load_data.credentials_flag {
- set_cookies_from_headers(url, response.headers(), cookie_jar);
- }
- update_sts_list_from_response(url, response, hsts_list);
-}
-
pub fn obtain_response<A>(request_factory: &HttpRequestFactory<R=A>,
url: &ServoUrl,
method: &Method,
@@ -871,312 +618,6 @@ pub trait UIProvider {
fn input_username_and_password(&self, prompt: &str) -> (Option<String>, Option<String>);
}
-impl UIProvider for TFDProvider {
- #[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
- fn input_username_and_password(&self, prompt: &str) -> (Option<String>, Option<String>) {
- (tinyfiledialogs::input_box(prompt, "Username:", ""),
- tinyfiledialogs::input_box(prompt, "Password:", ""))
- }
-
- #[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
- fn input_username_and_password(&self, _prompt: &str) -> (Option<String>, Option<String>) {
- (None, None)
- }
-}
-
-struct TFDProvider;
-
-pub fn load<A, B>(load_data: &LoadData,
- ui_provider: &B,
- http_state: &HttpState,
- devtools_chan: Option<Sender<DevtoolsControlMsg>>,
- request_factory: &HttpRequestFactory<R=A>,
- user_agent: Cow<'static, str>,
- cancel_listener: &CancellationListener,
- swmanager_chan: Option<IpcSender<CustomResponseMediator>>)
- -> Result<StreamedResponse, LoadError> where A: HttpRequest + 'static, B: UIProvider {
- let mut iters = 0;
- // URL of the document being loaded, as seen by all the higher-level code.
- let mut doc_url = load_data.url.clone();
- let mut redirected_to = FnvHashSet::with_hasher(Default::default());
- let mut method = load_data.method.clone();
- // URL of referrer - to be updated with redirects
- let mut referrer_url = load_data.referrer_url.clone();
-
- let mut new_auth_header: Option<Authorization<Basic>> = None;
-
- if cancel_listener.is_cancelled() {
- return Err(LoadError::new(doc_url, LoadErrorType::Cancelled));
- }
-
- let (msg_sender, msg_receiver) = ipc::channel().unwrap();
- let response_mediator = CustomResponseMediator {
- response_chan: msg_sender,
- load_url: doc_url.clone()
- };
- if let Some(sender) = swmanager_chan {
- let _ = sender.send(response_mediator);
- if let Ok(Some(custom_response)) = msg_receiver.recv() {
- let metadata = Metadata::default(doc_url.clone());
- let readable_response = to_readable_response(custom_response);
- return StreamedResponse::from_http_response(box readable_response, metadata);
- }
- } else {
- debug!("Did not receive a custom response");
- }
-
- // If the URL is a view-source scheme then the scheme data contains the
- // real URL that should be used for which the source is to be viewed.
- // Change our existing URL to that and keep note that we are viewing
- // the source rather than rendering the contents of the URL.
- let viewing_source = doc_url.scheme() == "view-source";
- if viewing_source {
- doc_url = ServoUrl::parse(&load_data.url[Position::BeforeUsername..]).unwrap();
- }
-
- // Loop to handle redirects.
- loop {
- iters = iters + 1;
-
- if doc_url.scheme() == "http" && request_must_be_secured(&doc_url, &http_state.hsts_list) {
- info!("{} is in the strict transport security list, requesting secure host", doc_url);
- doc_url = ServoUrl::from_url(secure_url(&doc_url.as_url().unwrap()));
- }
-
- if iters > 20 {
- return Err(LoadError::new(doc_url, LoadErrorType::MaxRedirects(iters - 1)));
- }
-
- if !matches!(doc_url.scheme(), "http" | "https") {
- let scheme = doc_url.scheme().to_owned();
- return Err(LoadError::new(doc_url, LoadErrorType::UnsupportedScheme { scheme: scheme }));
- }
-
- if cancel_listener.is_cancelled() {
- return Err(LoadError::new(doc_url, LoadErrorType::Cancelled));
- }
-
- let mut block_cookies = false;
- if let Some(ref rules) = *http_state.blocked_content {
- let same_origin =
- load_data.referrer_url.as_ref()
- .map(|url| url.origin() == doc_url.origin())
- .unwrap_or(false);
- let load_type = if same_origin { LoadType::FirstParty } else { LoadType::ThirdParty };
- let actions = process_rules_for_request(rules, &CBRequest {
- url: doc_url.as_url().unwrap(),
- resource_type: to_resource_type(&load_data.context),
- load_type: load_type,
- });
- for action in actions {
- match action {
- Reaction::Block => {
- return Err(LoadError::new(doc_url, LoadErrorType::ContentBlocked));
- },
- Reaction::BlockCookies => block_cookies = true,
- Reaction::HideMatchingElements(_) => (),
- }
- }
- }
-
- info!("requesting {}", doc_url);
-
- // Avoid automatically preserving request headers when redirects occur.
- // See https://bugzilla.mozilla.org/show_bug.cgi?id=401564 and
- // https://bugzilla.mozilla.org/show_bug.cgi?id=216828 .
- // Only preserve ones which have been explicitly marked as such.
- let mut request_headers = if iters == 1 {
- let mut combined_headers = load_data.headers.clone();
- combined_headers.extend(load_data.preserved_headers.iter());
- combined_headers
- } else {
- load_data.preserved_headers.clone()
- };
-
- let request_id = devtools_chan.as_ref().map(|_| {
- uuid::Uuid::new_v4().simple().to_string()
- });
-
- modify_request_headers(&mut request_headers, &doc_url,
- &user_agent, load_data.referrer_policy,
- &mut referrer_url);
-
- // https://fetch.spec.whatwg.org/#concept-http-network-or-cache-fetch step 11
- if load_data.credentials_flag {
- if !block_cookies {
- set_request_cookies(&doc_url, &mut request_headers, &http_state.cookie_jar);
- }
-
- // https://fetch.spec.whatwg.org/#http-network-or-cache-fetch step 12
- set_auth_header(&mut request_headers, &doc_url, &http_state.auth_cache);
- }
-
- //if there is a new auth header then set the request headers with it
- if let Some(ref auth_header) = new_auth_header {
- request_headers.set(auth_header.clone());
- }
-
- let (response, msg) =
- try!(obtain_response(request_factory, &doc_url, &method, &request_headers,
- &cancel_listener, &load_data.data, &load_data.method,
- &load_data.pipeline_id, iters,
- request_id.as_ref().map(Deref::deref), false));
-
- process_response_headers(&response, &doc_url, &http_state.cookie_jar, &http_state.hsts_list, &load_data);
-
- //if response status is unauthorized then prompt user for username and password
- if response.status() == StatusCode::Unauthorized &&
- response.headers().get_raw("WWW-Authenticate").is_some() {
- let (username_option, password_option) =
- ui_provider.input_username_and_password(doc_url.as_str());
-
- match username_option {
- Some(name) => {
- new_auth_header = Some(Authorization(Basic { username: name, password: password_option }));
- continue;
- },
- None => {},
- }
- }
-
- new_auth_header = None;
-
- if let Some(auth_header) = request_headers.get::<Authorization<Basic>>() {
- if response.status().class() == StatusClass::Success ||
- response.status().class() == StatusClass::Redirection {
- let auth_entry = AuthCacheEntry {
- user_name: auth_header.username.to_owned(),
- password: auth_header.password.to_owned().unwrap(),
- };
-
- let serialized_origin = doc_url.origin().ascii_serialization();
- http_state.auth_cache.write().unwrap().entries.insert(serialized_origin, auth_entry);
- }
- }
-
- // --- Loop if there's a redirect
- if response.status().class() == StatusClass::Redirection {
- if let Some(&Location(ref new_url)) = response.headers().get::<Location>() {
- // CORS (https://fetch.spec.whatwg.org/#http-fetch, status section, point 9, 10)
- if let Some(ref c) = load_data.cors {
- if c.preflight {
- return Err(LoadError::new(doc_url, LoadErrorType::CorsPreflightFetchInconsistent));
- } else {
- // XXXManishearth There are some CORS-related steps here,
- // but they don't seem necessary until credentials are implemented
- }
- }
-
- let new_doc_url = match doc_url.join(&new_url) {
- Ok(u) => u,
- Err(e) => return Err(
- LoadError::new(doc_url, LoadErrorType::InvalidRedirect { reason: e.to_string() })),
- };
-
- // According to https://tools.ietf.org/html/rfc7231#section-6.4.2,
- // historically UAs have rewritten POST->GET on 301 and 302 responses.
- if method == Method::Post &&
- (response.status() == StatusCode::MovedPermanently ||
- response.status() == StatusCode::Found) {
- method = Method::Get;
- }
-
- if redirected_to.contains(&new_doc_url) {
- return Err(LoadError::new(doc_url, LoadErrorType::RedirectLoop));
- }
-
- info!("redirecting to {}", new_doc_url);
- doc_url = new_doc_url;
-
- redirected_to.insert(doc_url.clone());
- }
- }
-
- // Only notify the devtools about the final request that received a response.
- if let Some(m) = msg {
- send_request_to_devtools(m, devtools_chan.as_ref().unwrap());
- }
- let mut adjusted_headers = response.headers().clone();
-
- if viewing_source {
- adjusted_headers.set(ContentType(Mime(TopLevel::Text, SubLevel::Plain, vec![])));
- }
-
- let mut metadata: Metadata = Metadata::default(doc_url.clone());
- metadata.set_content_type(match adjusted_headers.get() {
- Some(&ContentType(ref mime)) => Some(mime),
- None => None
- });
- metadata.headers = Some(Serde(adjusted_headers));
- metadata.status = Some((response.status_raw().0,
- response.status_raw().1.as_bytes().to_vec()));
- metadata.https_state = if doc_url.scheme() == "https" {
- HttpsState::Modern
- } else {
- HttpsState::None
- };
- metadata.referrer = referrer_url.clone();
-
- // --- Tell devtools that we got a response
- // Send an HttpResponse message to devtools with the corresponding request_id
- // TODO: Send this message even when the load fails?
- if let Some(pipeline_id) = load_data.pipeline_id {
- if let Some(ref chan) = devtools_chan {
- send_response_to_devtools(
- &chan, request_id.unwrap(),
- metadata.headers.clone().map(Serde::into_inner),
- metadata.status.clone(),
- pipeline_id);
- }
- }
- if response.status().class() == StatusClass::Redirection {
- continue;
- } else {
- return StreamedResponse::from_http_response(box response, metadata);
- }
- }
-}
-
-fn send_data<R: Read>(context: LoadContext,
- reader: &mut R,
- start_chan: LoadConsumer,
- metadata: Metadata,
- classifier: Arc<MimeClassifier>,
- cancel_listener: &CancellationListener) {
- let (progress_chan, mut chunk) = {
- let buf = match read_block(reader) {
- Ok(ReadResult::Payload(buf)) => buf,
- _ => vec!(),
- };
- let p = match start_sending_sniffed_opt(start_chan, metadata, classifier, &buf, context) {
- Ok(p) => p,
- _ => return
- };
- (p, buf)
- };
-
- loop {
- if cancel_listener.is_cancelled() {
- let _ = progress_chan.send(Done(Err(NetworkError::LoadCancelled)));
- return;
- }
-
- if progress_chan.send(Payload(chunk)).is_err() {
- // The send errors when the receiver is out of scope,
- // which will happen if the fetch has timed out (or has been aborted)
- // so we don't need to continue with the loading of the file here.
- return;
- }
-
- chunk = match read_block(reader) {
- Ok(ReadResult::Payload(buf)) => buf,
- Ok(ReadResult::EOF) | Err(_) => break,
- };
- }
-
- let _ = progress_chan.send(Done(Ok(())));
-}
-
// FIXME: This incredibly hacky. Make it more robust, and at least test it.
fn is_cert_verify_error(error: &OpensslError) -> bool {
match error {
@@ -1205,17 +646,3 @@ fn format_ssl_error(error: &OpensslError) -> String {
}
}
}
-
-fn to_resource_type(context: &LoadContext) -> ResourceType {
- match *context {
- LoadContext::Browsing => ResourceType::Document,
- LoadContext::Image => ResourceType::Image,
- LoadContext::AudioVideo => ResourceType::Media,
- LoadContext::Plugin => ResourceType::Raw,
- LoadContext::Style => ResourceType::StyleSheet,
- LoadContext::Script => ResourceType::Script,
- LoadContext::Font => ResourceType::Font,
- LoadContext::TextTrack => ResourceType::Media,
- LoadContext::CacheManifest => ResourceType::Raw,
- }
-}