Auto merge of #23090 - miller-time:nav-fetch-referrer, r=gterzian

Add referrer to navigation fetch request

<!-- Please describe your changes on the following line: -->
Implement step 13 of [following hyperlinks](https://html.spec.whatwg.org/#following-hyperlinks-2) and step 14.3 of [window open](https://html.spec.whatwg.org/#window-open-steps), as well as other referrer- and fetch-related updates.

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix #22890 (GitHub issue number if applicable)

<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because ___

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23090)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2019-04-25 20:21:23 -04:00 committed by GitHub
commit b73956cc37
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 136 additions and 88 deletions

View file

@ -12,7 +12,7 @@ use ipc_channel::ipc;
use ipc_channel::router::ROUTER; use ipc_channel::router::ROUTER;
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use net::http_loader::{set_default_accept, set_default_accept_language}; 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::response::ResponseInit;
use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata, FetchResponseMsg}; use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata, FetchResponseMsg};
use net_traits::{IpcSend, NetworkError, ResourceThreads}; use net_traits::{IpcSend, NetworkError, ResourceThreads};
@ -109,7 +109,10 @@ impl NetworkListener {
.url_list .url_list
.push(metadata.final_url.clone()); .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.request_builder.referrer_policy = metadata.referrer_policy;
self.res_init = Some(ResponseInit { self.res_init = Some(ResponseInit {

View file

@ -781,21 +781,27 @@ fn http_network_or_cache_fetch(
done_chan: &mut DoneChannel, done_chan: &mut DoneChannel,
context: &FetchContext, context: &FetchContext,
) -> Response { ) -> Response {
// Step 2
let mut response: Option<Response> = None;
// Step 4
let mut revalidating_flag = false;
// TODO: Implement Window enum for Request // TODO: Implement Window enum for Request
let request_has_no_window = true; let request_has_no_window = true;
// Step 2 // Step 5.1
let mut http_request; let mut http_request;
let http_request = if request_has_no_window && request.redirect_mode == RedirectMode::Error { let http_request = if request_has_no_window && request.redirect_mode == RedirectMode::Error {
request request
} else { } else {
// Step 3 // Step 5.2
// TODO Implement body source // TODO Implement body source
http_request = request.clone(); http_request = request.clone();
&mut http_request &mut http_request
}; };
// Step 4 // Step 5.3
let credentials_flag = match http_request.credentials_mode { let credentials_flag = match http_request.credentials_mode {
CredentialsMode::Include => true, CredentialsMode::Include => true,
CredentialsMode::CredentialsSameOrigin CredentialsMode::CredentialsSameOrigin
@ -808,26 +814,26 @@ fn http_network_or_cache_fetch(
let content_length_value = match http_request.body { let content_length_value = match http_request.body {
None => match http_request.method { None => match http_request.method {
// Step 6 // Step 5.5
Method::POST | Method::PUT => Some(0), Method::POST | Method::PUT => Some(0),
// Step 5 // Step 5.4
_ => None, _ => None,
}, },
// Step 7 // Step 5.6
Some(ref http_request_body) => Some(http_request_body.len() as u64), 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 { if let Some(content_length_value) = content_length_value {
http_request http_request
.headers .headers
.typed_insert(ContentLength(content_length_value)); .typed_insert(ContentLength(content_length_value));
if http_request.keep_alive { 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 { match http_request.referrer {
Referrer::NoReferrer => (), Referrer::NoReferrer => (),
Referrer::ReferrerUrl(ref http_request_referrer) => http_request Referrer::ReferrerUrl(ref http_request_referrer) => http_request
@ -841,7 +847,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) { if cors_flag || (http_request.method != Method::GET && http_request.method != Method::HEAD) {
debug_assert_ne!(http_request.origin, Origin::Client); debug_assert_ne!(http_request.origin, Origin::Client);
if let Origin::Origin(ref url_origin) = http_request.origin { if let Origin::Origin(ref url_origin) = http_request.origin {
@ -851,7 +857,7 @@ fn http_network_or_cache_fetch(
} }
} }
// Step 12 // Step 5.11
if !http_request.headers.contains_key(header::USER_AGENT) { if !http_request.headers.contains_key(header::USER_AGENT) {
let user_agent = context.user_agent.clone().into_owned(); let user_agent = context.user_agent.clone().into_owned();
http_request http_request
@ -860,19 +866,19 @@ fn http_network_or_cache_fetch(
} }
match http_request.cache_mode { match http_request.cache_mode {
// Step 13 // Step 5.12
CacheMode::Default if is_no_store_cache(&http_request.headers) => { CacheMode::Default if is_no_store_cache(&http_request.headers) => {
http_request.cache_mode = CacheMode::NoStore; http_request.cache_mode = CacheMode::NoStore;
}, },
// Step 14 // Step 5.13
CacheMode::NoCache if !http_request.headers.contains_key(header::CACHE_CONTROL) => { CacheMode::NoCache if !http_request.headers.contains_key(header::CACHE_CONTROL) => {
http_request http_request
.headers .headers
.typed_insert(CacheControl::new().with_max_age(Duration::from_secs(0))); .typed_insert(CacheControl::new().with_max_age(Duration::from_secs(0)));
}, },
// Step 15 // Step 5.14
CacheMode::Reload | CacheMode::NoStore => { CacheMode::Reload | CacheMode::NoStore => {
// Substep 1 // Substep 1
if !http_request.headers.contains_key(header::PRAGMA) { if !http_request.headers.contains_key(header::PRAGMA) {
@ -890,7 +896,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 current_url = http_request.current_url();
let host = Host::from( let host = Host::from(
format!( format!(
@ -910,7 +919,7 @@ fn http_network_or_cache_fetch(
// here, according to the fetch spec // here, according to the fetch spec
set_default_accept_encoding(&mut http_request.headers); set_default_accept_encoding(&mut http_request.headers);
// Step 17 // Step 5.17
// TODO some of this step can't be implemented yet // TODO some of this step can't be implemented yet
if credentials_flag { if credentials_flag {
// Substep 1 // Substep 1
@ -950,16 +959,10 @@ fn http_network_or_cache_fetch(
} }
} }
// Step 18 // Step 5.18
// TODO If theres a proxy-authentication entry, use it as appropriate. // TODO If theres a proxy-authentication entry, use it as appropriate.
// Step 19 // Step 5.19
let mut response: Option<Response> = None;
// Step 20
let mut revalidating_flag = false;
// Step 21
if let Ok(http_cache) = context.state.http_cache.read() { if let Ok(http_cache) = context.state.http_cache.read() {
if let Some(response_from_cache) = http_cache.construct_response(&http_request, done_chan) { if let Some(response_from_cache) = http_cache.construct_response(&http_request, done_chan) {
let response_headers = response_from_cache.response.headers.clone(); let response_headers = response_from_cache.response.headers.clone();
@ -1027,7 +1030,10 @@ fn http_network_or_cache_fetch(
wait_for_cached_response(done_chan, &mut response); 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() { if response.is_none() {
// Substep 1 // Substep 1
if http_request.cache_mode == CacheMode::OnlyIfCached { if http_request.cache_mode == CacheMode::OnlyIfCached {
@ -1036,7 +1042,7 @@ fn http_network_or_cache_fetch(
)); ));
} }
} }
// More Step 22 // More Step 7
if response.is_none() { if response.is_none() {
// Substep 2 // Substep 2
let forward_response = let forward_response =
@ -1077,7 +1083,13 @@ fn http_network_or_cache_fetch(
let mut response = response.unwrap(); 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 // FIXME: Figure out what to do with request window objects
if let (Some((StatusCode::UNAUTHORIZED, _)), false, true) = if let (Some((StatusCode::UNAUTHORIZED, _)), false, true) =
(response.status.as_ref(), cors_flag, credentials_flag) (response.status.as_ref(), cors_flag, credentials_flag)
@ -1110,7 +1122,7 @@ fn http_network_or_cache_fetch(
); );
} }
// Step 24 // Step 11
if let Some((StatusCode::PROXY_AUTHENTICATION_REQUIRED, _)) = response.status.as_ref() { if let Some((StatusCode::PROXY_AUTHENTICATION_REQUIRED, _)) = response.status.as_ref() {
// Step 1 // Step 1
if request_has_no_window { if request_has_no_window {
@ -1135,12 +1147,12 @@ fn http_network_or_cache_fetch(
// cors_flag, done_chan, context); // cors_flag, done_chan, context);
} }
// Step 25 // Step 12
if authentication_fetch_flag { if authentication_fetch_flag {
// TODO Create the authentication entry for request and the given realm // TODO Create the authentication entry for request and the given realm
} }
// Step 26 // Step 13
response response
} }

View file

@ -162,7 +162,7 @@ pub struct RequestBuilder {
pub use_url_credentials: bool, pub use_url_credentials: bool,
pub origin: ImmutableOrigin, pub origin: ImmutableOrigin,
// XXXManishearth these should be part of the client object // XXXManishearth these should be part of the client object
pub referrer_url: Option<ServoUrl>, pub referrer: Option<Referrer>,
pub referrer_policy: Option<ReferrerPolicy>, pub referrer_policy: Option<ReferrerPolicy>,
pub pipeline_id: Option<PipelineId>, pub pipeline_id: Option<PipelineId>,
pub redirect_mode: RedirectMode, pub redirect_mode: RedirectMode,
@ -188,7 +188,7 @@ impl RequestBuilder {
credentials_mode: CredentialsMode::Omit, credentials_mode: CredentialsMode::Omit,
use_url_credentials: false, use_url_credentials: false,
origin: ImmutableOrigin::new_opaque(), origin: ImmutableOrigin::new_opaque(),
referrer_url: None, referrer: None,
referrer_policy: None, referrer_policy: None,
pipeline_id: None, pipeline_id: None,
redirect_mode: RedirectMode::Follow, redirect_mode: RedirectMode::Follow,
@ -265,8 +265,8 @@ impl RequestBuilder {
self self
} }
pub fn referrer_url(mut self, referrer_url: Option<ServoUrl>) -> RequestBuilder { pub fn referrer(mut self, referrer: Option<Referrer>) -> RequestBuilder {
self.referrer_url = referrer_url; self.referrer = referrer;
self self
} }
@ -313,11 +313,7 @@ impl RequestBuilder {
request.credentials_mode = self.credentials_mode; request.credentials_mode = self.credentials_mode;
request.use_url_credentials = self.use_url_credentials; request.use_url_credentials = self.use_url_credentials;
request.cache_mode = self.cache_mode; request.cache_mode = self.cache_mode;
request.referrer = if let Some(url) = self.referrer_url { request.referrer = self.referrer.unwrap_or(Referrer::Client);
Referrer::ReferrerUrl(url)
} else {
Referrer::NoReferrer
};
request.referrer_policy = self.referrer_policy; request.referrer_policy = self.referrer_policy;
request.redirect_mode = self.redirect_mode; request.redirect_mode = self.redirect_mode;
let mut url_list = self.url_list; let mut url_list = self.url_list;

View file

@ -36,7 +36,7 @@ use js::jsapi::{JSAutoCompartment, JSContext};
use js::jsval::UndefinedValue; use js::jsval::UndefinedValue;
use js::rust::HandleValue; use js::rust::HandleValue;
use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId}; 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 net_traits::{load_whole_resource, IpcSend};
use script_traits::{TimerEvent, TimerSource, WorkerGlobalScopeInit, WorkerScriptLoadOrigin}; use script_traits::{TimerEvent, TimerSource, WorkerGlobalScopeInit, WorkerScriptLoadOrigin};
use servo_rand::random; use servo_rand::random;
@ -305,12 +305,14 @@ impl DedicatedWorkerGlobalScope {
pipeline_id, pipeline_id,
} = worker_load_origin; } = worker_load_origin;
let referrer = referrer_url.map(|referrer_url| Referrer::ReferrerUrl(referrer_url));
let request = RequestBuilder::new(worker_url.clone()) let request = RequestBuilder::new(worker_url.clone())
.destination(Destination::Worker) .destination(Destination::Worker)
.credentials_mode(CredentialsMode::Include) .credentials_mode(CredentialsMode::Include)
.use_url_credentials(true) .use_url_credentials(true)
.pipeline_id(pipeline_id) .pipeline_id(pipeline_id)
.referrer_url(referrer_url) .referrer(referrer)
.referrer_policy(referrer_policy) .referrer_policy(referrer_policy)
.origin(origin); .origin(origin);

View file

@ -27,6 +27,7 @@ use crate::dom::urlhelper::UrlHelper;
use crate::dom::virtualmethods::VirtualMethods; use crate::dom::virtualmethods::VirtualMethods;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use html5ever::{LocalName, Prefix}; use html5ever::{LocalName, Prefix};
use net_traits::request::Referrer;
use num_traits::ToPrimitive; use num_traits::ToPrimitive;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use std::default::Default; use std::default::Default;
@ -639,7 +640,7 @@ pub fn follow_hyperlink(subject: &Element, hyperlink_suffix: Option<String>) {
// will have been done as part of Step 7 above // will have been done as part of Step 7 above
// in choose_browsing_context/create_auxiliary_browsing_context. // 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 attribute = subject.get_attribute(&ns!(), &local_name!("href")).unwrap();
let mut href = attribute.Value(); let mut href = attribute.Value();
// Step 11: append a hyperlink suffix. // Step 11: append a hyperlink suffix.
@ -657,8 +658,16 @@ pub fn follow_hyperlink(subject: &Element, hyperlink_suffix: Option<String>) {
.get_attribute_by_name(DOMString::from_string(String::from("referrerpolicy"))) .get_attribute_by_name(DOMString::from_string(String::from("referrerpolicy")))
.and_then(|attribute: DomRoot<Attr>| (determine_policy_for_token(&attribute.Value()))); .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); debug!("following hyperlink to {}", url);
target_window.load_url(url, replace, false, referrer_policy); target_window.load_url(url, replace, false, referrer, referrer_policy);
}; };
} }

View file

@ -55,6 +55,7 @@ use html5ever::{LocalName, Prefix};
use hyper::Method; use hyper::Method;
use mime::{self, Mime}; use mime::{self, Mime};
use net_traits::http_percent_encode; use net_traits::http_percent_encode;
use net_traits::request::Referrer;
use script_traits::LoadData; use script_traits::LoadData;
use servo_rand::random; use servo_rand::random;
use std::borrow::ToOwned; use std::borrow::ToOwned;
@ -400,8 +401,8 @@ impl HTMLFormElement {
let mut load_data = LoadData::new( let mut load_data = LoadData::new(
action_components, action_components,
None, None,
Some(Referrer::ReferrerUrl(target_document.url())),
target_document.get_referrer_policy(), target_document.get_referrer_policy(),
Some(target_document.url()),
); );
// Step 22 // Step 22

View file

@ -30,6 +30,7 @@ use euclid::TypedSize2D;
use html5ever::{LocalName, Prefix}; use html5ever::{LocalName, Prefix};
use ipc_channel::ipc; use ipc_channel::ipc;
use msg::constellation_msg::{BrowsingContextId, PipelineId, TopLevelBrowsingContextId}; use msg::constellation_msg::{BrowsingContextId, PipelineId, TopLevelBrowsingContextId};
use net_traits::request::Referrer;
use profile_traits::ipc as ProfiledIpc; use profile_traits::ipc as ProfiledIpc;
use script_layout_interface::message::ReflowGoal; use script_layout_interface::message::ReflowGoal;
use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed}; use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
@ -269,8 +270,8 @@ impl HTMLIFrameElement {
let load_data = LoadData::new( let load_data = LoadData::new(
url, url,
creator_pipeline_id, creator_pipeline_id,
Some(Referrer::ReferrerUrl(document.url())),
document.get_referrer_policy(), document.get_referrer_policy(),
Some(document.url()),
); );
let pipeline_id = self.pipeline_id(); let pipeline_id = self.pipeline_id();
@ -295,8 +296,8 @@ impl HTMLIFrameElement {
let load_data = LoadData::new( let load_data = LoadData::new(
url, url,
pipeline_id, pipeline_id,
Some(Referrer::ReferrerUrl(document.url().clone())),
document.get_referrer_policy(), document.get_referrer_policy(),
Some(document.url().clone()),
); );
let browsing_context_id = BrowsingContextId::new(); let browsing_context_id = BrowsingContextId::new();
let top_level_browsing_context_id = window.window_proxy().top_level_browsing_context_id(); let top_level_browsing_context_id = window.window_proxy().top_level_browsing_context_id();

View file

@ -64,7 +64,7 @@ use ipc_channel::router::ROUTER;
use mime::{self, Mime}; use mime::{self, Mime};
use net_traits::image::base::Image; use net_traits::image::base::Image;
use net_traits::image_cache::ImageResponse; 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::{CoreResourceMsg, FetchChannels, FetchMetadata, FetchResponseListener, Metadata};
use net_traits::{NetworkError, ResourceFetchTiming, ResourceTimingType}; use net_traits::{NetworkError, ResourceFetchTiming, ResourceTimingType};
use script_layout_interface::HTMLMediaData; use script_layout_interface::HTMLMediaData;
@ -720,7 +720,7 @@ impl HTMLMediaElement {
.use_url_credentials(true) .use_url_credentials(true)
.origin(document.origin().immutable().clone()) .origin(document.origin().immutable().clone())
.pipeline_id(Some(self.global().pipeline_id())) .pipeline_id(Some(self.global().pipeline_id()))
.referrer_url(Some(document.url())) .referrer(Some(Referrer::ReferrerUrl(document.url())))
.referrer_policy(document.get_referrer_policy()); .referrer_policy(document.get_referrer_policy());
let mut current_fetch_context = self.current_fetch_context.borrow_mut(); let mut current_fetch_context = self.current_fetch_context.borrow_mut();

View file

@ -33,7 +33,7 @@ use ipc_channel::ipc;
use ipc_channel::router::ROUTER; use ipc_channel::router::ROUTER;
use js::jsval::UndefinedValue; use js::jsval::UndefinedValue;
use net_traits::request::{ use net_traits::request::{
CorsSettings, CredentialsMode, Destination, RequestBuilder, RequestMode, CorsSettings, CredentialsMode, Destination, Referrer, RequestBuilder, RequestMode,
}; };
use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError}; use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError};
use net_traits::{ResourceFetchTiming, ResourceTimingType}; use net_traits::{ResourceFetchTiming, ResourceTimingType};
@ -308,7 +308,7 @@ fn fetch_a_classic_script(
}) })
.origin(doc.origin().immutable().clone()) .origin(doc.origin().immutable().clone())
.pipeline_id(Some(script.global().pipeline_id())) .pipeline_id(Some(script.global().pipeline_id()))
.referrer_url(Some(doc.url())) .referrer(Some(Referrer::ReferrerUrl(doc.url())))
.referrer_policy(doc.get_referrer_policy()) .referrer_policy(doc.get_referrer_policy())
.integrity_metadata(integrity_metadata); .integrity_metadata(integrity_metadata);

View file

@ -13,6 +13,7 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::urlhelper::UrlHelper; use crate::dom::urlhelper::UrlHelper;
use crate::dom::window::Window; use crate::dom::window::Window;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use net_traits::request::Referrer;
use servo_url::{MutableOrigin, ServoUrl}; use servo_url::{MutableOrigin, ServoUrl};
#[dom_struct] #[dom_struct]
@ -43,8 +44,9 @@ impl Location {
fn set_url_component(&self, value: USVString, setter: fn(&mut ServoUrl, USVString)) { fn set_url_component(&self, value: USVString, setter: fn(&mut ServoUrl, USVString)) {
let mut url = self.window.get_url(); let mut url = self.window.get_url();
let referrer = Referrer::ReferrerUrl(url.clone());
setter(&mut url, value); setter(&mut url, value);
self.window.load_url(url, false, false, None); self.window.load_url(url, false, false, referrer, None);
} }
fn check_same_origin_domain(&self) -> ErrorResult { fn check_same_origin_domain(&self) -> ErrorResult {
@ -62,7 +64,9 @@ impl Location {
// https://html.spec.whatwg.org/multipage/#dom-location-reload // https://html.spec.whatwg.org/multipage/#dom-location-reload
pub fn reload_without_origin_check(&self) { pub fn reload_without_origin_check(&self) {
self.window.load_url(self.get_url(), true, true, None); let url = self.get_url();
let referrer = Referrer::ReferrerUrl(url.clone());
self.window.load_url(url, true, true, referrer, None);
} }
#[allow(dead_code)] #[allow(dead_code)]
@ -79,7 +83,8 @@ impl LocationMethods for Location {
// _entry settings object_. // _entry settings object_.
let base_url = self.window.get_url(); let base_url = self.window.get_url();
if let Ok(url) = base_url.join(&url.0) { if let Ok(url) = base_url.join(&url.0) {
self.window.load_url(url, false, false, None); let referrer = Referrer::ReferrerUrl(base_url.clone());
self.window.load_url(url, false, false, referrer, None);
Ok(()) Ok(())
} else { } else {
Err(Error::Syntax) Err(Error::Syntax)
@ -89,7 +94,9 @@ impl LocationMethods for Location {
// https://html.spec.whatwg.org/multipage/#dom-location-reload // https://html.spec.whatwg.org/multipage/#dom-location-reload
fn Reload(&self) -> ErrorResult { fn Reload(&self) -> ErrorResult {
self.check_same_origin_domain()?; self.check_same_origin_domain()?;
self.window.load_url(self.get_url(), true, true, None); let url = self.get_url();
let referrer = Referrer::ReferrerUrl(url.clone());
self.window.load_url(url, true, true, referrer, None);
Ok(()) Ok(())
} }
@ -100,7 +107,8 @@ impl LocationMethods for Location {
// _entry settings object_. // _entry settings object_.
let base_url = self.window.get_url(); let base_url = self.window.get_url();
if let Ok(url) = base_url.join(&url.0) { if let Ok(url) = base_url.join(&url.0) {
self.window.load_url(url, true, false, None); let referrer = Referrer::ReferrerUrl(base_url.clone());
self.window.load_url(url, true, false, referrer, None);
Ok(()) Ok(())
} else { } else {
Err(Error::Syntax) Err(Error::Syntax)
@ -164,11 +172,13 @@ impl LocationMethods for Location {
// https://html.spec.whatwg.org/multipage/#dom-location-href // https://html.spec.whatwg.org/multipage/#dom-location-href
fn SetHref(&self, value: USVString) -> ErrorResult { fn SetHref(&self, value: USVString) -> ErrorResult {
// Note: no call to self.check_same_origin_domain() // Note: no call to self.check_same_origin_domain()
let url = match self.window.get_url().join(&value.0) { let current_url = self.window.get_url();
let url = match current_url.join(&value.0) {
Ok(url) => url, Ok(url) => url,
Err(e) => return Err(Error::Type(format!("Couldn't parse URL: {}", e))), Err(e) => return Err(Error::Type(format!("Couldn't parse URL: {}", e))),
}; };
self.window.load_url(url, false, false, None); let referrer = Referrer::ReferrerUrl(current_url.clone());
self.window.load_url(url, false, false, referrer, None);
Ok(()) Ok(())
} }

View file

@ -554,7 +554,7 @@ impl RequestMethods for Request {
fn Referrer(&self) -> USVString { fn Referrer(&self) -> USVString {
let r = self.request.borrow(); let r = self.request.borrow();
USVString(match r.referrer { USVString(match r.referrer {
NetTraitsRequestReferrer::NoReferrer => String::from("no-referrer"), NetTraitsRequestReferrer::NoReferrer => String::from(""),
NetTraitsRequestReferrer::Client => String::from("about:client"), NetTraitsRequestReferrer::Client => String::from("about:client"),
NetTraitsRequestReferrer::ReferrerUrl(ref u) => { NetTraitsRequestReferrer::ReferrerUrl(ref u) => {
let u_c = u.clone(); let u_c = u.clone();

View file

@ -30,7 +30,7 @@ use ipc_channel::router::ROUTER;
use js::jsapi::{JSAutoCompartment, JSContext, JS_AddInterruptCallback}; use js::jsapi::{JSAutoCompartment, JSContext, JS_AddInterruptCallback};
use js::jsval::UndefinedValue; use js::jsval::UndefinedValue;
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use net_traits::request::{CredentialsMode, Destination, RequestBuilder}; use net_traits::request::{CredentialsMode, Destination, Referrer, RequestBuilder};
use net_traits::{load_whole_resource, CustomResponseMediator, IpcSend}; use net_traits::{load_whole_resource, CustomResponseMediator, IpcSend};
use script_traits::{ use script_traits::{
ScopeThings, ServiceWorkerMsg, TimerEvent, WorkerGlobalScopeInit, WorkerScriptLoadOrigin, ScopeThings, ServiceWorkerMsg, TimerEvent, WorkerGlobalScopeInit, WorkerScriptLoadOrigin,
@ -281,12 +281,14 @@ impl ServiceWorkerGlobalScope {
pipeline_id, pipeline_id,
} = worker_load_origin; } = worker_load_origin;
let referrer = referrer_url.map(|referrer_url| Referrer::ReferrerUrl(referrer_url));
let request = RequestBuilder::new(script_url.clone()) let request = RequestBuilder::new(script_url.clone())
.destination(Destination::ServiceWorker) .destination(Destination::ServiceWorker)
.credentials_mode(CredentialsMode::Include) .credentials_mode(CredentialsMode::Include)
.use_url_credentials(true) .use_url_credentials(true)
.pipeline_id(pipeline_id) .pipeline_id(pipeline_id)
.referrer_url(referrer_url) .referrer(referrer)
.referrer_policy(referrer_policy) .referrer_policy(referrer_policy)
.origin(origin); .origin(origin);

View file

@ -31,7 +31,7 @@ use js::jsapi::{JSAutoCompartment, JSObject};
use js::jsval::UndefinedValue; use js::jsval::UndefinedValue;
use js::rust::CustomAutoRooterGuard; use js::rust::CustomAutoRooterGuard;
use js::typedarray::{ArrayBuffer, ArrayBufferView, CreateWith}; use js::typedarray::{ArrayBuffer, ArrayBufferView, CreateWith};
use net_traits::request::{RequestBuilder, RequestMode}; use net_traits::request::{Referrer, RequestBuilder, RequestMode};
use net_traits::MessageData; use net_traits::MessageData;
use net_traits::{CoreResourceMsg, FetchChannels}; use net_traits::{CoreResourceMsg, FetchChannels};
use net_traits::{WebSocketDomAction, WebSocketNetworkEvent}; use net_traits::{WebSocketDomAction, WebSocketNetworkEvent};
@ -203,7 +203,8 @@ impl WebSocket {
// Step 8. // Step 8.
let request = RequestBuilder::new(url_record) let request = RequestBuilder::new(url_record)
.origin(global.origin().immutable().clone()) .origin(global.origin().immutable().clone())
.mode(RequestMode::WebSocket { protocols }); .mode(RequestMode::WebSocket { protocols })
.referrer(Some(Referrer::NoReferrer));
let channels = FetchChannels::WebSocket { let channels = FetchChannels::WebSocket {
event_sender: resource_event_sender, event_sender: resource_event_sender,

View file

@ -87,6 +87,7 @@ use js::rust::HandleValue;
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use net_traits::image_cache::{ImageCache, ImageResponder, ImageResponse}; use net_traits::image_cache::{ImageCache, ImageResponder, ImageResponse};
use net_traits::image_cache::{PendingImageId, PendingImageResponse}; use net_traits::image_cache::{PendingImageId, PendingImageResponse};
use net_traits::request::Referrer;
use net_traits::storage_thread::StorageType; use net_traits::storage_thread::StorageType;
use net_traits::{ReferrerPolicy, ResourceThreads}; use net_traits::{ReferrerPolicy, ResourceThreads};
use num_traits::ToPrimitive; use num_traits::ToPrimitive;
@ -1726,6 +1727,7 @@ impl Window {
url: ServoUrl, url: ServoUrl,
replace: bool, replace: bool,
force_reload: bool, force_reload: bool,
referrer: Referrer,
referrer_policy: Option<ReferrerPolicy>, referrer_policy: Option<ReferrerPolicy>,
) { ) {
let doc = self.Document(); let doc = self.Document();
@ -1791,7 +1793,7 @@ impl Window {
self.main_thread_script_chan() self.main_thread_script_chan()
.send(MainThreadScriptMsg::Navigate( .send(MainThreadScriptMsg::Navigate(
pipeline_id, pipeline_id,
LoadData::new(url, Some(pipeline_id), referrer_policy, Some(doc.url())), LoadData::new(url, Some(pipeline_id), Some(referrer), referrer_policy),
replace, replace,
)) ))
.unwrap(); .unwrap();

View file

@ -45,6 +45,7 @@ use js::JSCLASS_IS_GLOBAL;
use msg::constellation_msg::BrowsingContextId; use msg::constellation_msg::BrowsingContextId;
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use msg::constellation_msg::TopLevelBrowsingContextId; use msg::constellation_msg::TopLevelBrowsingContextId;
use net_traits::request::Referrer;
use script_traits::{AuxiliaryBrowsingContextLoadInfo, LoadData, NewLayoutInfo, ScriptMsg}; use script_traits::{AuxiliaryBrowsingContextLoadInfo, LoadData, NewLayoutInfo, ScriptMsg};
use servo_url::ServoUrl; use servo_url::ServoUrl;
use std::cell::Cell; use std::cell::Cell;
@ -281,8 +282,8 @@ impl WindowProxy {
let load_data = LoadData::new( let load_data = LoadData::new(
blank_url, blank_url,
None, None,
Some(Referrer::ReferrerUrl(document.url().clone())),
document.get_referrer_policy(), document.get_referrer_policy(),
Some(document.url().clone()),
); );
let (pipeline_sender, pipeline_receiver) = ipc::channel().unwrap(); let (pipeline_sender, pipeline_receiver) = ipc::channel().unwrap();
let new_layout_info = NewLayoutInfo { let new_layout_info = NewLayoutInfo {
@ -428,9 +429,20 @@ impl WindowProxy {
Ok(url) => url, Ok(url) => url,
Err(_) => return None, // TODO: throw a "SyntaxError" DOMException. Err(_) => return None, // TODO: throw a "SyntaxError" DOMException.
}; };
// TODO Step 14.3, handle noreferrer flag // Step 14.3
let referrer = if noreferrer {
Referrer::NoReferrer
} else {
Referrer::Client
};
// Step 14.5 // Step 14.5
target_window.load_url(url, new, false, target_document.get_referrer_policy()); target_window.load_url(
url,
new,
false,
referrer,
target_document.get_referrer_policy(),
);
} }
if noopener { if noopener {
// Step 15 (Dis-owning has been done in create_auxiliary_browsing_context). // Step 15 (Dis-owning has been done in create_auxiliary_browsing_context).

View file

@ -213,9 +213,8 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
.use_url_credentials(true) .use_url_credentials(true)
.origin(global_scope.origin().immutable().clone()) .origin(global_scope.origin().immutable().clone())
.pipeline_id(Some(self.upcast::<GlobalScope>().pipeline_id())) .pipeline_id(Some(self.upcast::<GlobalScope>().pipeline_id()))
.referrer_url(None)
.referrer_policy(None); .referrer_policy(None);
;
let (url, source) = let (url, source) =
match load_whole_resource(request, &global_scope.resource_threads().sender()) { match load_whole_resource(request, &global_scope.resource_threads().sender()) {
Err(_) => return Err(Error::Network), Err(_) => return Err(Error::Network),

View file

@ -59,7 +59,7 @@ use js::jsval::{JSVal, NullValue, UndefinedValue};
use js::rust::wrappers::JS_ParseJSON; use js::rust::wrappers::JS_ParseJSON;
use js::typedarray::{ArrayBuffer, CreateWith}; use js::typedarray::{ArrayBuffer, CreateWith};
use mime::{self, Mime, Name}; use mime::{self, Mime, Name};
use net_traits::request::{CredentialsMode, Destination, RequestBuilder, RequestMode}; use net_traits::request::{CredentialsMode, Destination, Referrer, RequestBuilder, RequestMode};
use net_traits::trim_http_whitespace; use net_traits::trim_http_whitespace;
use net_traits::CoreResourceMsg::Fetch; use net_traits::CoreResourceMsg::Fetch;
use net_traits::{FetchChannels, FetchMetadata, FilteredMetadata}; use net_traits::{FetchChannels, FetchMetadata, FilteredMetadata};
@ -653,7 +653,11 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
.credentials_mode(credentials_mode) .credentials_mode(credentials_mode)
.use_url_credentials(use_url_credentials) .use_url_credentials(use_url_credentials)
.origin(self.global().origin().immutable().clone()) .origin(self.global().origin().immutable().clone())
.referrer_url(self.referrer_url.clone()) .referrer(
self.referrer_url
.clone()
.map(|referrer_url| Referrer::ReferrerUrl(referrer_url)),
)
.referrer_policy(self.referrer_policy.clone()) .referrer_policy(self.referrer_policy.clone())
.pipeline_id(Some(self.global().pipeline_id())); .pipeline_id(Some(self.global().pipeline_id()));

View file

@ -94,10 +94,6 @@ impl Drop for FetchCanceller {
} }
} }
fn from_referrer_to_referrer_url(request: &NetTraitsRequest) -> Option<ServoUrl> {
request.referrer.to_url().map(|url| url.clone())
}
fn request_init_from_request(request: NetTraitsRequest) -> RequestBuilder { fn request_init_from_request(request: NetTraitsRequest) -> RequestBuilder {
RequestBuilder { RequestBuilder {
method: request.method.clone(), method: request.method.clone(),
@ -118,7 +114,7 @@ fn request_init_from_request(request: NetTraitsRequest) -> RequestBuilder {
.origin() .origin()
.immutable() .immutable()
.clone(), .clone(),
referrer_url: from_referrer_to_referrer_url(&request), referrer: Some(request.referrer.clone()),
referrer_policy: request.referrer_policy, referrer_policy: request.referrer_policy,
pipeline_id: request.pipeline_id, pipeline_id: request.pipeline_id,
redirect_mode: request.redirect_mode, redirect_mode: request.redirect_mode,

View file

@ -3348,7 +3348,7 @@ impl ScriptThread {
.credentials_mode(CredentialsMode::Include) .credentials_mode(CredentialsMode::Include)
.use_url_credentials(true) .use_url_credentials(true)
.pipeline_id(Some(id)) .pipeline_id(Some(id))
.referrer_url(load_data.referrer_url) .referrer(load_data.referrer)
.referrer_policy(load_data.referrer_policy) .referrer_policy(load_data.referrer_policy)
.headers(load_data.headers) .headers(load_data.headers)
.body(load_data.data) .body(load_data.data)

View file

@ -22,7 +22,7 @@ use ipc_channel::ipc;
use ipc_channel::router::ROUTER; use ipc_channel::router::ROUTER;
use mime::{self, Mime}; use mime::{self, Mime};
use net_traits::request::{ use net_traits::request::{
CorsSettings, CredentialsMode, Destination, RequestBuilder, RequestMode, CorsSettings, CredentialsMode, Destination, Referrer, RequestBuilder, RequestMode,
}; };
use net_traits::{ use net_traits::{
FetchMetadata, FetchResponseListener, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy, FetchMetadata, FetchResponseListener, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy,
@ -326,7 +326,7 @@ impl<'a> StylesheetLoader<'a> {
}) })
.origin(document.origin().immutable().clone()) .origin(document.origin().immutable().clone())
.pipeline_id(Some(self.elem.global().pipeline_id())) .pipeline_id(Some(self.elem.global().pipeline_id()))
.referrer_url(Some(document.url())) .referrer(Some(Referrer::ReferrerUrl(document.url())))
.referrer_policy(referrer_policy) .referrer_policy(referrer_policy)
.integrity_metadata(integrity_metadata); .integrity_metadata(integrity_metadata);

View file

@ -39,6 +39,7 @@ use msg::constellation_msg::{BrowsingContextId, HistoryStateId, PipelineId};
use msg::constellation_msg::{PipelineNamespaceId, TopLevelBrowsingContextId, TraversalDirection}; use msg::constellation_msg::{PipelineNamespaceId, TopLevelBrowsingContextId, TraversalDirection};
use net_traits::image::base::Image; use net_traits::image::base::Image;
use net_traits::image_cache::ImageCache; use net_traits::image_cache::ImageCache;
use net_traits::request::Referrer;
use net_traits::storage_thread::StorageType; use net_traits::storage_thread::StorageType;
use net_traits::{FetchResponseMsg, ReferrerPolicy, ResourceThreads}; use net_traits::{FetchResponseMsg, ReferrerPolicy, ResourceThreads};
use pixels::PixelFormat; use pixels::PixelFormat;
@ -140,10 +141,10 @@ pub struct LoadData {
pub data: Option<Vec<u8>>, pub data: Option<Vec<u8>>,
/// The result of evaluating a javascript scheme url. /// The result of evaluating a javascript scheme url.
pub js_eval_result: Option<JsEvalResult>, pub js_eval_result: Option<JsEvalResult>,
/// The referrer.
pub referrer: Option<Referrer>,
/// The referrer policy. /// The referrer policy.
pub referrer_policy: Option<ReferrerPolicy>, pub referrer_policy: Option<ReferrerPolicy>,
/// The referrer URL.
pub referrer_url: Option<ServoUrl>,
} }
/// The result of evaluating a javascript scheme url. /// The result of evaluating a javascript scheme url.
@ -161,8 +162,8 @@ impl LoadData {
pub fn new( pub fn new(
url: ServoUrl, url: ServoUrl,
creator_pipeline_id: Option<PipelineId>, creator_pipeline_id: Option<PipelineId>,
referrer: Option<Referrer>,
referrer_policy: Option<ReferrerPolicy>, referrer_policy: Option<ReferrerPolicy>,
referrer_url: Option<ServoUrl>,
) -> LoadData { ) -> LoadData {
LoadData { LoadData {
url: url, url: url,
@ -171,8 +172,8 @@ impl LoadData {
headers: HeaderMap::new(), headers: HeaderMap::new(),
data: None, data: None,
js_eval_result: None, js_eval_result: None,
referrer: referrer,
referrer_policy: referrer_policy, referrer_policy: referrer_policy,
referrer_url: referrer_url,
} }
} }
} }

View file

@ -1,8 +1,5 @@
[request-init-001.sub.html] [request-init-001.sub.html]
type: testharness type: testharness
[Check referrer init value of and associated getter]
expected: FAIL
[Check referrerPolicy init value of and associated getter] [Check referrerPolicy init value of and associated getter]
expected: FAIL expected: FAIL