Urlmageddon: Use refcounted urls more often.

This commit is contained in:
Emilio Cobos Álvarez 2016-11-16 11:57:39 +01:00
parent f14e7339b5
commit 913c874cb5
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
161 changed files with 1044 additions and 718 deletions

View file

@ -39,6 +39,7 @@ 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 servo_url::ServoUrl;
use std::borrow::{Cow, ToOwned};
use std::boxed::FnBox;
use std::collections::HashSet;
@ -52,7 +53,7 @@ use time;
use time::Tm;
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
use tinyfiledialogs;
use url::{Position, Url, Origin};
use url::{Position, Origin};
use util::thread::spawn_named;
use uuid;
@ -246,7 +247,7 @@ impl Read for ReadableCustomResponse {
pub trait HttpRequestFactory {
type R: HttpRequest;
fn create(&self, url: Url, method: Method, headers: Headers) -> Result<Self::R, LoadError>;
fn create(&self, url: ServoUrl, method: Method, headers: Headers) -> Result<Self::R, LoadError>;
}
pub struct NetworkHttpRequestFactory {
@ -256,9 +257,11 @@ pub struct NetworkHttpRequestFactory {
impl HttpRequestFactory for NetworkHttpRequestFactory {
type R = WrappedHttpRequest;
fn create(&self, url: Url, method: Method, headers: Headers)
fn create(&self, url: ServoUrl, method: Method, headers: Headers)
-> Result<WrappedHttpRequest, LoadError> {
let connection = Request::with_connector(method, url.clone(), &*self.connector);
let connection = Request::with_connector(method,
url.clone().into_url().unwrap(),
&*self.connector);
if let Err(HttpError::Ssl(ref error)) = connection {
let error: &(Error + Send + 'static) = &**error;
@ -308,7 +311,7 @@ impl HttpRequest for WrappedHttpRequest {
type R = WrappedHttpResponse;
fn send(self, body: &Option<Vec<u8>>) -> Result<WrappedHttpResponse, LoadError> {
let url = self.request.url.clone();
let url = ServoUrl::from_url(self.request.url.clone());
let mut request_writer = match self.request.start() {
Ok(streaming) => streaming,
Err(e) => return Err(LoadError::new(url, LoadErrorType::Connection { reason: e.description().to_owned() })),
@ -335,12 +338,12 @@ impl HttpRequest for WrappedHttpRequest {
#[derive(Debug)]
pub struct LoadError {
pub url: Url,
pub url: ServoUrl,
pub error: LoadErrorType,
}
impl LoadError {
pub fn new(url: Url, error: LoadErrorType) -> LoadError {
pub fn new(url: ServoUrl, error: LoadErrorType) -> LoadError {
LoadError {
url: url,
error: error,
@ -429,7 +432,7 @@ pub fn set_default_accept_language(headers: &mut Headers) {
}
/// https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-state-no-referrer-when-downgrade
fn no_referrer_when_downgrade_header(referrer_url: Url, url: Url) -> Option<Url> {
fn no_referrer_when_downgrade_header(referrer_url: ServoUrl, url: ServoUrl) -> Option<ServoUrl> {
if referrer_url.scheme() == "https" && url.scheme() != "https" {
return None;
}
@ -437,7 +440,7 @@ fn no_referrer_when_downgrade_header(referrer_url: Url, url: Url) -> Option<Url>
}
/// https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-strict-origin
fn strict_origin(referrer_url: Url, url: Url) -> Option<Url> {
fn strict_origin(referrer_url: ServoUrl, url: ServoUrl) -> Option<ServoUrl> {
if referrer_url.scheme() == "https" && url.scheme() != "https" {
return None;
}
@ -445,7 +448,7 @@ fn strict_origin(referrer_url: Url, url: Url) -> Option<Url> {
}
/// https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-strict-origin-when-cross-origin
fn strict_origin_when_cross_origin(referrer_url: Url, url: Url) -> Option<Url> {
fn strict_origin_when_cross_origin(referrer_url: ServoUrl, url: ServoUrl) -> Option<ServoUrl> {
if referrer_url.scheme() == "https" && url.scheme() != "https" {
return None;
}
@ -454,14 +457,17 @@ fn strict_origin_when_cross_origin(referrer_url: Url, url: Url) -> Option<Url> {
}
/// https://w3c.github.io/webappsec-referrer-policy/#strip-url
fn strip_url(mut referrer_url: Url, origin_only: bool) -> Option<Url> {
fn strip_url(mut referrer_url: ServoUrl, origin_only: bool) -> Option<ServoUrl> {
if referrer_url.scheme() == "https" || referrer_url.scheme() == "http" {
referrer_url.set_username("").unwrap();
referrer_url.set_password(None).unwrap();
referrer_url.set_fragment(None);
if origin_only {
referrer_url.set_path("");
referrer_url.set_query(None);
{
let referrer = referrer_url.as_mut_url().unwrap();
referrer.set_username("").unwrap();
referrer.set_password(None).unwrap();
referrer.set_fragment(None);
if origin_only {
referrer.set_path("");
referrer.set_query(None);
}
}
return Some(referrer_url);
}
@ -471,8 +477,8 @@ fn strip_url(mut referrer_url: Url, origin_only: bool) -> Option<Url> {
/// https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer
pub fn determine_request_referrer(headers: &mut Headers,
referrer_policy: Option<ReferrerPolicy>,
referrer_url: Option<Url>,
url: Url) -> Option<Url> {
referrer_url: Option<ServoUrl>,
url: ServoUrl) -> Option<ServoUrl> {
//TODO - algorithm step 2 not addressed
assert!(!headers.has::<Referer>());
if let Some(ref_url) = referrer_url {
@ -492,7 +498,7 @@ pub fn determine_request_referrer(headers: &mut Headers,
return None;
}
pub fn set_request_cookies(url: &Url, headers: &mut Headers, cookie_jar: &Arc<RwLock<CookieStorage>>) {
pub fn set_request_cookies(url: &ServoUrl, headers: &mut Headers, cookie_jar: &Arc<RwLock<CookieStorage>>) {
let mut cookie_jar = cookie_jar.write().unwrap();
if let Some(cookie_list) = cookie_jar.cookies_for_url(url, CookieSource::HTTP) {
let mut v = Vec::new();
@ -502,7 +508,7 @@ pub fn set_request_cookies(url: &Url, headers: &mut Headers, cookie_jar: &Arc<Rw
}
fn set_cookie_for_url(cookie_jar: &Arc<RwLock<CookieStorage>>,
request: &Url,
request: &ServoUrl,
cookie_val: String) {
let mut cookie_jar = cookie_jar.write().unwrap();
let source = CookieSource::HTTP;
@ -517,7 +523,7 @@ fn set_cookie_for_url(cookie_jar: &Arc<RwLock<CookieStorage>>,
}
}
pub fn set_cookies_from_headers(url: &Url, headers: &Headers, cookie_jar: &Arc<RwLock<CookieStorage>>) {
pub fn set_cookies_from_headers(url: &ServoUrl, headers: &Headers, cookie_jar: &Arc<RwLock<CookieStorage>>) {
if let Some(cookies) = headers.get_raw("set-cookie") {
for cookie in cookies.iter() {
if let Ok(cookie_value) = String::from_utf8(cookie.clone()) {
@ -529,7 +535,7 @@ pub fn set_cookies_from_headers(url: &Url, headers: &Headers, cookie_jar: &Arc<R
}
}
fn update_sts_list_from_response(url: &Url, response: &HttpResponse, hsts_list: &Arc<RwLock<HstsList>>) {
fn update_sts_list_from_response(url: &ServoUrl, response: &HttpResponse, hsts_list: &Arc<RwLock<HstsList>>) {
if url.scheme() != "https" {
return;
}
@ -613,7 +619,7 @@ enum Decoder {
}
fn prepare_devtools_request(request_id: String,
url: Url,
url: ServoUrl,
method: Method,
headers: Headers,
body: Option<Vec<u8>>,
@ -656,7 +662,7 @@ pub fn send_response_to_devtools(devtools_chan: &Sender<DevtoolsControlMsg>,
let _ = devtools_chan.send(DevtoolsControlMsg::FromChrome(msg));
}
fn request_must_be_secured(url: &Url, hsts_list: &Arc<RwLock<HstsList>>) -> bool {
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
@ -664,10 +670,10 @@ fn request_must_be_secured(url: &Url, hsts_list: &Arc<RwLock<HstsList>>) -> bool
}
pub fn modify_request_headers(headers: &mut Headers,
url: &Url,
url: &ServoUrl,
user_agent: &str,
referrer_policy: Option<ReferrerPolicy>,
referrer_url: &mut Option<Url>) {
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(),
@ -700,7 +706,7 @@ pub fn modify_request_headers(headers: &mut Headers,
}
fn set_auth_header(headers: &mut Headers,
url: &Url,
url: &ServoUrl,
auth_cache: &Arc<RwLock<AuthCache>>) {
if !headers.has::<Authorization<Basic>>() {
if let Some(auth) = auth_from_url(url) {
@ -723,7 +729,7 @@ pub fn auth_from_cache(auth_cache: &Arc<RwLock<AuthCache>>, origin: &Origin) ->
}
}
fn auth_from_url(doc_url: &Url) -> Option<Authorization<Basic>> {
fn auth_from_url(doc_url: &ServoUrl) -> Option<Authorization<Basic>> {
let username = doc_url.username();
if username != "" {
Some(Authorization(Basic {
@ -736,7 +742,7 @@ fn auth_from_url(doc_url: &Url) -> Option<Authorization<Basic>> {
}
pub fn process_response_headers(response: &HttpResponse,
url: &Url,
url: &ServoUrl,
cookie_jar: &Arc<RwLock<CookieStorage>>,
hsts_list: &Arc<RwLock<HstsList>>,
load_data: &LoadData) {
@ -755,7 +761,7 @@ pub fn process_response_headers(response: &HttpResponse,
}
pub fn obtain_response<A>(request_factory: &HttpRequestFactory<R=A>,
url: &Url,
url: &ServoUrl,
method: &Method,
request_headers: &Headers,
cancel_listener: &CancellationListener,
@ -925,7 +931,7 @@ pub fn load<A, B>(load_data: &LoadData,
// the source rather than rendering the contents of the URL.
let viewing_source = doc_url.scheme() == "view-source";
if viewing_source {
doc_url = Url::parse(&load_data.url[Position::BeforeUsername..]).unwrap();
doc_url = ServoUrl::parse(&load_data.url.as_url().unwrap()[Position::BeforeUsername..]).unwrap();
}
// Loop to handle redirects.
@ -934,7 +940,7 @@ pub fn load<A, B>(load_data: &LoadData,
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 = secure_url(&doc_url);
doc_url = ServoUrl::from_url(secure_url(&doc_url.as_url().unwrap()));
}
if iters > 20 {
@ -958,7 +964,7 @@ pub fn load<A, B>(load_data: &LoadData,
.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,
url: doc_url.as_url().unwrap(),
resource_type: to_resource_type(&load_data.context),
load_type: load_type,
});