aboutsummaryrefslogtreecommitdiffstats
path: root/components/net/fetch
diff options
context:
space:
mode:
authorshanehandley <1322294+shanehandley@users.noreply.github.com>2024-11-08 18:19:23 +1100
committerGitHub <noreply@github.com>2024-11-08 07:19:23 +0000
commit645176742813c423c3c5016eaba69a546b286339 (patch)
tree7b47b66bdeb596668681aa83f8cf3a64a8ff8408 /components/net/fetch
parent4f6283d7fead1b2489456651185e3a8bbbc725e8 (diff)
downloadservo-645176742813c423c3c5016eaba69a546b286339.tar.gz
servo-645176742813c423c3c5016eaba69a546b286339.zip
Implement PolicyContainer and update the default ReferrerPolicy (#33977)
* Implement PolicyContainer Signed-off-by: Shane Handley <shanehandley@fastmail.com> * implement small parts of fetch that interact with policy container Signed-off-by: Shane Handley <shanehandley@fastmail.com> * fix: allow policy container's csp list to be unset Signed-off-by: Shane Handley <shanehandley@fastmail.com> * fix: use the correct default policy when parsing from a token Signed-off-by: Shane Handley <shanehandley@fastmail.com> --------- Signed-off-by: Shane Handley <shanehandley@fastmail.com>
Diffstat (limited to 'components/net/fetch')
-rw-r--r--components/net/fetch/methods.rs82
1 files changed, 60 insertions, 22 deletions
diff --git a/components/net/fetch/methods.rs b/components/net/fetch/methods.rs
index 7d64b57436d..2e99f5f3314 100644
--- a/components/net/fetch/methods.rs
+++ b/components/net/fetch/methods.rs
@@ -20,6 +20,7 @@ use log::warn;
use mime::{self, Mime};
use net_traits::filemanager_thread::{FileTokenCheck, RelativePos};
use net_traits::http_status::HttpStatus;
+use net_traits::policy_container::{PolicyContainer, RequestPolicyContainer};
use net_traits::request::{
is_cors_safelisted_method, is_cors_safelisted_request_header, BodyChunkRequest,
BodyChunkResponse, CredentialsMode, Destination, Origin, RedirectMode, Referrer, Request,
@@ -27,8 +28,8 @@ use net_traits::request::{
};
use net_traits::response::{Response, ResponseBody, ResponseType};
use net_traits::{
- FetchTaskTarget, NetworkError, ReferrerPolicy, ResourceAttribute, ResourceFetchTiming,
- ResourceTimeValue, ResourceTimingType,
+ FetchTaskTarget, NetworkError, ResourceAttribute, ResourceFetchTiming, ResourceTimeValue,
+ ResourceTimingType,
};
use rustls::Certificate;
use serde::{Deserialize, Serialize};
@@ -114,52 +115,83 @@ pub async fn fetch(request: &mut Request, target: Target<'_>, context: &FetchCon
fetch_with_cors_cache(request, &mut CorsCache::default(), target, context).await;
}
+/// Continuation of fetch from step 9.
+///
+/// <https://fetch.spec.whatwg.org#concept-fetch>
pub async fn fetch_with_cors_cache(
request: &mut Request,
cache: &mut CorsCache,
target: Target<'_>,
context: &FetchContext,
) {
- // Step 1.
+ // Step 9: If request’s window is "client", then set request’s window to request’s client, if
+ // request’s client’s global object is a Window object; otherwise "no-window".
if request.window == Window::Client {
// TODO: Set window to request's client object if client is a Window object
} else {
request.window = Window::NoWindow;
}
- // Step 2.
+ // Step 10: If request’s origin is "client", then set request’s origin to request’s client’s
+ // origin.
if request.origin == Origin::Client {
// TODO: set request's origin to request's client's origin
unimplemented!()
}
- // Step 3.
+ // Step 11: If all of the following conditions are true:
+ // - request’s URL’s scheme is an HTTP(S) scheme
+ // - request’s mode is "same-origin", "cors", or "no-cors"
+ // - request’s window is an environment settings object
+ // - request’s method is `GET`
+ // - request’s unsafe-request flag is not set or request’s header list is empty
+ // TODO: evaluate these conditions when we have an an environment settings object
+
+ // Step 12: If request’s policy container is "client", then:
+ if let RequestPolicyContainer::Client = request.policy_container {
+ // Step 12.1: If request’s client is non-null, then set request’s policy container to a clone
+ // of request’s client’s policy container.
+ // TODO: Requires request's client to support PolicyContainer
+
+ // Step 12.2: Otherwise, set request’s policy container to a new policy container.
+ request.policy_container =
+ RequestPolicyContainer::PolicyContainer(PolicyContainer::default());
+ }
+
+ // Step 13: If request’s header list does not contain `Accept`:
set_default_accept(request);
- // Step 4.
+ // Step 14: If request’s header list does not contain `Accept-Language`, then user agents should
+ // append (`Accept-Language, an appropriate header value) to request’s header list.
set_default_accept_language(&mut request.headers);
- // Step 5.
+ // Step 15. If request’s internal priority is null, then use request’s priority, initiator,
+ // destination, and render-blocking in an implementation-defined manner to set request’s
+ // internal priority to an implementation-defined object.
// TODO: figure out what a Priority object is.
- // Step 6.
- // TODO: handle client hints headers.
-
- // Step 7.
+ // Step 16: If request is a subresource request, then:
if request.is_subresource_request() {
- // TODO: handle client hints headers.
+ // TODO: requires keepalive.
}
- // Step 8.
+ // Step 17: Run main fetch given fetchParams.
main_fetch(request, cache, false, false, target, &mut None, context).await;
+
+ // Step 18: Return fetchParams’s controller.
+ // TODO: We don't implement fetchParams as defined in the spec
}
/// <https://www.w3.org/TR/CSP/#should-block-request>
-pub fn should_request_be_blocked_by_csp(request: &Request) -> csp::CheckResult {
+pub fn should_request_be_blocked_by_csp(
+ request: &Request,
+ policy_container: &PolicyContainer,
+) -> csp::CheckResult {
let origin = match &request.origin {
Origin::Client => return csp::CheckResult::Allowed,
Origin::Origin(origin) => origin,
};
+
let csp_request = csp::Request {
url: request.url().into_url(),
origin: origin.clone().into_url_origin(),
@@ -170,8 +202,9 @@ pub fn should_request_be_blocked_by_csp(request: &Request) -> csp::CheckResult {
integrity_metadata: request.integrity_metadata.clone(),
parser_metadata: csp::ParserMetadata::None,
};
+
// TODO: Instead of ignoring violations, report them.
- request
+ policy_container
.csp_list
.as_ref()
.map(|c| c.should_request_be_blocked(&csp_request).0)
@@ -213,8 +246,15 @@ pub async fn main_fetch(
// Step 2.2.
// TODO: Report violations.
+ // The request should have a valid policy_container associated with it.
+ // TODO: This should not be `Client` here
+ let policy_container = match &request.policy_container {
+ RequestPolicyContainer::Client => PolicyContainer::default(),
+ RequestPolicyContainer::PolicyContainer(container) => container.to_owned(),
+ };
+
// Step 2.4.
- if should_request_be_blocked_by_csp(request) == csp::CheckResult::Blocked {
+ if should_request_be_blocked_by_csp(request, &policy_container) == csp::CheckResult::Blocked {
warn!("Request blocked by CSP");
response = Some(Response::network_error(NetworkError::Internal(
"Blocked by Content-Security-Policy".into(),
@@ -236,16 +276,14 @@ pub async fn main_fetch(
// TODO: handle blocking as mixed content.
// TODO: handle blocking by content security policy.
- // Step 6
- // TODO: handle request's client's referrer policy.
-
- // Step 7.
+ // Step 8: If request’s referrer policy is the empty string, then set request’s referrer policy
+ // to request’s policy container’s referrer policy.
request.referrer_policy = request
.referrer_policy
- .or(Some(ReferrerPolicy::NoReferrerWhenDowngrade));
+ .or(Some(policy_container.referrer_policy));
- // Step 8.
assert!(request.referrer_policy.is_some());
+
let referrer_url = match mem::replace(&mut request.referrer, Referrer::NoReferrer) {
Referrer::NoReferrer => None,
Referrer::ReferrerUrl(referrer_source) | Referrer::Client(referrer_source) => {