Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add referrer to navigation fetch request #23090

Merged
merged 2 commits into from Apr 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 5 additions & 2 deletions components/constellation/network_listener.rs
Expand Up @@ -12,7 +12,7 @@ use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use msg::constellation_msg::PipelineId;
use net::http_loader::{set_default_accept, set_default_accept_language};
use net_traits::request::{Destination, RequestBuilder};
use net_traits::request::{Destination, Referrer, RequestBuilder};
use net_traits::response::ResponseInit;
use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata, FetchResponseMsg};
use net_traits::{IpcSend, NetworkError, ResourceThreads};
Expand Down Expand Up @@ -109,7 +109,10 @@ impl NetworkListener {
.url_list
.push(metadata.final_url.clone());

self.request_builder.referrer_url = metadata.referrer.clone();
self.request_builder.referrer = metadata
.referrer
.clone()
.map(|referrer_url| Referrer::ReferrerUrl(referrer_url));
self.request_builder.referrer_policy = metadata.referrer_policy;

self.res_init = Some(ResponseInit {
Expand Down
72 changes: 42 additions & 30 deletions components/net/http_loader.rs
Expand Up @@ -783,21 +783,27 @@ fn http_network_or_cache_fetch(
done_chan: &mut DoneChannel,
context: &FetchContext,
) -> Response {
// Step 2
let mut response: Option<Response> = None;

// Step 4
let mut revalidating_flag = false;

// TODO: Implement Window enum for Request
let request_has_no_window = true;

// Step 2
// Step 5.1
let mut http_request;
let http_request = if request_has_no_window && request.redirect_mode == RedirectMode::Error {
request
} else {
// Step 3
// Step 5.2
// TODO Implement body source
http_request = request.clone();
&mut http_request
};

// Step 4
// Step 5.3
let credentials_flag = match http_request.credentials_mode {
CredentialsMode::Include => true,
CredentialsMode::CredentialsSameOrigin
Expand All @@ -810,26 +816,26 @@ fn http_network_or_cache_fetch(

let content_length_value = match http_request.body {
None => match http_request.method {
// Step 6
// Step 5.5
Method::POST | Method::PUT => Some(0),
// Step 5
// Step 5.4
_ => None,
},
// Step 7
// Step 5.6
Some(ref http_request_body) => Some(http_request_body.len() as u64),
};

// Step 8
// Step 5.7
if let Some(content_length_value) = content_length_value {
http_request
.headers
.typed_insert(ContentLength(content_length_value));
if http_request.keep_alive {
// Step 9 TODO: needs request's client object
// Step 5.8 TODO: needs request's client object
}
}

// Step 10
// Step 5.9
match http_request.referrer {
Referrer::NoReferrer => (),
Referrer::ReferrerUrl(ref http_request_referrer) => http_request
Expand All @@ -843,7 +849,7 @@ fn http_network_or_cache_fetch(
},
};

// Step 11
// Step 5.10
if cors_flag || (http_request.method != Method::GET && http_request.method != Method::HEAD) {
debug_assert_ne!(http_request.origin, Origin::Client);
if let Origin::Origin(ref url_origin) = http_request.origin {
Expand All @@ -853,7 +859,7 @@ fn http_network_or_cache_fetch(
}
}

// Step 12
// Step 5.11
if !http_request.headers.contains_key(header::USER_AGENT) {
let user_agent = context.user_agent.clone().into_owned();
http_request
Expand All @@ -862,19 +868,19 @@ fn http_network_or_cache_fetch(
}

match http_request.cache_mode {
// Step 13
// Step 5.12
CacheMode::Default if is_no_store_cache(&http_request.headers) => {
http_request.cache_mode = CacheMode::NoStore;
},

// Step 14
// Step 5.13
CacheMode::NoCache if !http_request.headers.contains_key(header::CACHE_CONTROL) => {
http_request
.headers
.typed_insert(CacheControl::new().with_max_age(Duration::from_secs(0)));
},

// Step 15
// Step 5.14
CacheMode::Reload | CacheMode::NoStore => {
// Substep 1
if !http_request.headers.contains_key(header::PRAGMA) {
Expand All @@ -892,7 +898,10 @@ fn http_network_or_cache_fetch(
_ => {},
}

// Step 16
// Step 5.15
// TODO: if necessary append `Accept-Encoding`/`identity` to headers

// Step 5.16
let current_url = http_request.current_url();
let host = Host::from(
format!(
Expand All @@ -912,7 +921,7 @@ fn http_network_or_cache_fetch(
// here, according to the fetch spec
set_default_accept_encoding(&mut http_request.headers);

// Step 17
// Step 5.17
// TODO some of this step can't be implemented yet
if credentials_flag {
// Substep 1
Expand Down Expand Up @@ -952,16 +961,10 @@ fn http_network_or_cache_fetch(
}
}

// Step 18
// Step 5.18
// TODO If there’s a proxy-authentication entry, use it as appropriate.

// Step 19
let mut response: Option<Response> = None;

// Step 20
let mut revalidating_flag = false;

// Step 21
// Step 5.19
if let Ok(http_cache) = context.state.http_cache.read() {
if let Some(response_from_cache) = http_cache.construct_response(&http_request, done_chan) {
let response_headers = response_from_cache.response.headers.clone();
Expand Down Expand Up @@ -1029,7 +1032,10 @@ fn http_network_or_cache_fetch(

wait_for_cached_response(done_chan, &mut response);

// Step 22
// Step 6
// TODO: https://infra.spec.whatwg.org/#if-aborted

// Step 7
if response.is_none() {
// Substep 1
if http_request.cache_mode == CacheMode::OnlyIfCached {
Expand All @@ -1038,7 +1044,7 @@ fn http_network_or_cache_fetch(
));
}
}
// More Step 22
// More Step 7
if response.is_none() {
// Substep 2
let forward_response =
Expand Down Expand Up @@ -1079,7 +1085,13 @@ fn http_network_or_cache_fetch(

let mut response = response.unwrap();

// Step 23
// Step 8
// TODO: if necessary set response's range-requested flag

// Step 9
// TODO: handle CORS not set and cross-origin blocked

// Step 10
// FIXME: Figure out what to do with request window objects
if let (Some((StatusCode::UNAUTHORIZED, _)), false, true) =
(response.status.as_ref(), cors_flag, credentials_flag)
Expand Down Expand Up @@ -1112,7 +1124,7 @@ fn http_network_or_cache_fetch(
);
}

// Step 24
// Step 11
if let Some((StatusCode::PROXY_AUTHENTICATION_REQUIRED, _)) = response.status.as_ref() {
// Step 1
if request_has_no_window {
Expand All @@ -1137,12 +1149,12 @@ fn http_network_or_cache_fetch(
// cors_flag, done_chan, context);
}

// Step 25
// Step 12
if authentication_fetch_flag {
// TODO Create the authentication entry for request and the given realm
}

// Step 26
// Step 13
response
}

Expand Down
14 changes: 5 additions & 9 deletions components/net_traits/request.rs
Expand Up @@ -162,7 +162,7 @@ pub struct RequestBuilder {
pub use_url_credentials: bool,
pub origin: ImmutableOrigin,
// XXXManishearth these should be part of the client object
pub referrer_url: Option<ServoUrl>,
pub referrer: Option<Referrer>,
pub referrer_policy: Option<ReferrerPolicy>,
pub pipeline_id: Option<PipelineId>,
pub redirect_mode: RedirectMode,
Expand All @@ -188,7 +188,7 @@ impl RequestBuilder {
credentials_mode: CredentialsMode::Omit,
use_url_credentials: false,
origin: ImmutableOrigin::new_opaque(),
referrer_url: None,
referrer: None,
referrer_policy: None,
pipeline_id: None,
redirect_mode: RedirectMode::Follow,
Expand Down Expand Up @@ -265,8 +265,8 @@ impl RequestBuilder {
self
}

pub fn referrer_url(mut self, referrer_url: Option<ServoUrl>) -> RequestBuilder {
self.referrer_url = referrer_url;
pub fn referrer(mut self, referrer: Option<Referrer>) -> RequestBuilder {
self.referrer = referrer;
self
}

Expand Down Expand Up @@ -313,11 +313,7 @@ impl RequestBuilder {
request.credentials_mode = self.credentials_mode;
request.use_url_credentials = self.use_url_credentials;
request.cache_mode = self.cache_mode;
request.referrer = if let Some(url) = self.referrer_url {
Referrer::ReferrerUrl(url)
} else {
Referrer::NoReferrer
};
request.referrer = self.referrer.unwrap_or(Referrer::Client);
request.referrer_policy = self.referrer_policy;
request.redirect_mode = self.redirect_mode;
let mut url_list = self.url_list;
Expand Down
6 changes: 4 additions & 2 deletions components/script/dom/dedicatedworkerglobalscope.rs
Expand Up @@ -36,7 +36,7 @@ use js::jsapi::{JSAutoCompartment, JSContext};
use js::jsval::UndefinedValue;
use js::rust::HandleValue;
use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId};
use net_traits::request::{CredentialsMode, Destination, RequestBuilder};
use net_traits::request::{CredentialsMode, Destination, Referrer, RequestBuilder};
use net_traits::{load_whole_resource, IpcSend};
use script_traits::{TimerEvent, TimerSource, WorkerGlobalScopeInit, WorkerScriptLoadOrigin};
use servo_rand::random;
Expand Down Expand Up @@ -305,12 +305,14 @@ impl DedicatedWorkerGlobalScope {
pipeline_id,
} = worker_load_origin;

let referrer = referrer_url.map(|referrer_url| Referrer::ReferrerUrl(referrer_url));

let request = RequestBuilder::new(worker_url.clone())
.destination(Destination::Worker)
.credentials_mode(CredentialsMode::Include)
.use_url_credentials(true)
.pipeline_id(pipeline_id)
.referrer_url(referrer_url)
.referrer(referrer)
.referrer_policy(referrer_policy)
.origin(origin);

Expand Down
15 changes: 12 additions & 3 deletions components/script/dom/htmlanchorelement.rs
Expand Up @@ -27,6 +27,7 @@ use crate::dom::urlhelper::UrlHelper;
use crate::dom::virtualmethods::VirtualMethods;
use dom_struct::dom_struct;
use html5ever::{LocalName, Prefix};
use net_traits::request::Referrer;
use num_traits::ToPrimitive;
use servo_url::ServoUrl;
use std::default::Default;
Expand Down Expand Up @@ -639,7 +640,7 @@ pub fn follow_hyperlink(subject: &Element, hyperlink_suffix: Option<String>) {
// will have been done as part of Step 7 above
// in choose_browsing_context/create_auxiliary_browsing_context.

// Step 10, 11, 12, 13. TODO: if parsing the URL failed, navigate to error page.
// Step 10, 11. TODO: if parsing the URL failed, navigate to error page.
let attribute = subject.get_attribute(&ns!(), &local_name!("href")).unwrap();
let mut href = attribute.Value();
// Step 11: append a hyperlink suffix.
Expand All @@ -657,8 +658,16 @@ pub fn follow_hyperlink(subject: &Element, hyperlink_suffix: Option<String>) {
.get_attribute_by_name(DOMString::from_string(String::from("referrerpolicy")))
.and_then(|attribute: DomRoot<Attr>| (determine_policy_for_token(&attribute.Value())));

// Step 13, 14.
// Step 13
let referrer = match subject.get_attribute(&ns!(), &local_name!("rel")) {
Some(ref link_types) if link_types.Value().contains("noreferrer") => {
Referrer::NoReferrer
},
_ => Referrer::Client,
};

// Step 14
debug!("following hyperlink to {}", url);
target_window.load_url(url, replace, false, referrer_policy);
target_window.load_url(url, replace, false, referrer, referrer_policy);
};
}
3 changes: 2 additions & 1 deletion components/script/dom/htmlformelement.rs
Expand Up @@ -55,6 +55,7 @@ use html5ever::{LocalName, Prefix};
use hyper::Method;
use mime::{self, Mime};
use net_traits::http_percent_encode;
use net_traits::request::Referrer;
use script_traits::LoadData;
use servo_rand::random;
use std::borrow::ToOwned;
Expand Down Expand Up @@ -400,8 +401,8 @@ impl HTMLFormElement {
let mut load_data = LoadData::new(
action_components,
None,
Some(Referrer::ReferrerUrl(target_document.url())),
target_document.get_referrer_policy(),
Some(target_document.url()),
);

// Step 22
Expand Down
5 changes: 3 additions & 2 deletions components/script/dom/htmliframeelement.rs
Expand Up @@ -30,6 +30,7 @@ use euclid::TypedSize2D;
use html5ever::{LocalName, Prefix};
use ipc_channel::ipc;
use msg::constellation_msg::{BrowsingContextId, PipelineId, TopLevelBrowsingContextId};
use net_traits::request::Referrer;
use profile_traits::ipc as ProfiledIpc;
use script_layout_interface::message::ReflowGoal;
use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
Expand Down Expand Up @@ -269,8 +270,8 @@ impl HTMLIFrameElement {
let load_data = LoadData::new(
url,
creator_pipeline_id,
Some(Referrer::ReferrerUrl(document.url())),
document.get_referrer_policy(),
Some(document.url()),
);

let pipeline_id = self.pipeline_id();
Expand All @@ -295,8 +296,8 @@ impl HTMLIFrameElement {
let load_data = LoadData::new(
url,
pipeline_id,
Some(Referrer::ReferrerUrl(document.url().clone())),
document.get_referrer_policy(),
Some(document.url().clone()),
);
let browsing_context_id = BrowsingContextId::new();
let top_level_browsing_context_id = window.window_proxy().top_level_browsing_context_id();
Expand Down
4 changes: 2 additions & 2 deletions components/script/dom/htmlmediaelement.rs
Expand Up @@ -64,7 +64,7 @@ use ipc_channel::router::ROUTER;
use mime::{self, Mime};
use net_traits::image::base::Image;
use net_traits::image_cache::ImageResponse;
use net_traits::request::{CredentialsMode, Destination, RequestBuilder};
use net_traits::request::{CredentialsMode, Destination, Referrer, RequestBuilder};
use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata, FetchResponseListener, Metadata};
use net_traits::{NetworkError, ResourceFetchTiming, ResourceTimingType};
use script_layout_interface::HTMLMediaData;
Expand Down Expand Up @@ -720,7 +720,7 @@ impl HTMLMediaElement {
.use_url_credentials(true)
.origin(document.origin().immutable().clone())
.pipeline_id(Some(self.global().pipeline_id()))
.referrer_url(Some(document.url()))
.referrer(Some(Referrer::ReferrerUrl(document.url())))
.referrer_policy(document.get_referrer_policy());

let mut current_fetch_context = self.current_fetch_context.borrow_mut();
Expand Down