Move CSP code into one entrypoint (#37604)

This refactoring moves various CSP-related methods away from GlobalScope
and Document into a dedicated entrypoint. It also reduces the amount of
imports of the CSP crate, so that types are consolidated into this one
entrypoint. That way, we control how CSP code interacts with the script
crate.

For reviewing purposes, I split up the refactoring into separate
distinct commits that all move 1 method(group) into the new file.

Testing: no change in behavior, only a build improvement + code cleanup

---------

Signed-off-by: Tim van der Lippe <tvanderlippe@gmail.com>
Signed-off-by: Tim van der Lippe <TimvdLippe@users.noreply.github.com>
This commit is contained in:
Tim van der Lippe 2025-06-24 10:50:30 +02:00 committed by GitHub
parent 2265570c88
commit fc20d8b2e1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 424 additions and 289 deletions

View file

@ -0,0 +1,304 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::borrow::Cow;
use constellation_traits::{LoadData, LoadOrigin};
/// Used to determine which inline check to run
pub use content_security_policy::InlineCheckType;
/// Used to report CSP violations in Fetch handlers
pub use content_security_policy::Violation;
use content_security_policy::{
CheckResult, CspList, Destination, Element as CspElement, Initiator, NavigationCheckType,
Origin, ParserMetadata, PolicyDisposition, PolicySource, Request, ViolationResource,
};
use http::HeaderMap;
use hyper_serde::Serde;
use js::rust::describe_scripted_caller;
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::refcounted::Trusted;
use crate::dom::csppolicyviolationreport::CSPViolationReportBuilder;
use crate::dom::element::Element;
use crate::dom::globalscope::GlobalScope;
use crate::dom::node::{Node, NodeTraits};
use crate::dom::window::Window;
use crate::security_manager::CSPViolationReportTask;
pub(crate) trait CspReporting {
fn is_js_evaluation_allowed(&self, global: &GlobalScope, source: &str) -> bool;
fn is_wasm_evaluation_allowed(&self, global: &GlobalScope) -> bool;
fn should_navigation_request_be_blocked(
&self,
global: &GlobalScope,
load_data: &LoadData,
element: Option<&Element>,
) -> bool;
fn should_elements_inline_type_behavior_be_blocked(
&self,
global: &GlobalScope,
el: &Element,
type_: InlineCheckType,
source: &str,
) -> bool;
fn is_trusted_type_policy_creation_allowed(
&self,
global: &GlobalScope,
policy_name: String,
created_policy_names: Vec<String>,
) -> bool;
fn does_sink_type_require_trusted_types(
&self,
sink_group: &str,
include_report_only_policies: bool,
) -> bool;
fn should_sink_type_mismatch_violation_be_blocked_by_csp(
&self,
global: &GlobalScope,
sink: &str,
sink_group: &str,
source: &str,
) -> bool;
}
impl CspReporting for Option<CspList> {
/// <https://www.w3.org/TR/CSP/#can-compile-strings>
fn is_js_evaluation_allowed(&self, global: &GlobalScope, source: &str) -> bool {
let Some(csp_list) = self else {
return true;
};
let (is_js_evaluation_allowed, violations) = csp_list.is_js_evaluation_allowed(source);
global.report_csp_violations(violations, None);
is_js_evaluation_allowed == CheckResult::Allowed
}
/// <https://www.w3.org/TR/CSP/#can-compile-wasm-bytes>
fn is_wasm_evaluation_allowed(&self, global: &GlobalScope) -> bool {
let Some(csp_list) = self else {
return true;
};
let (is_wasm_evaluation_allowed, violations) = csp_list.is_wasm_evaluation_allowed();
global.report_csp_violations(violations, None);
is_wasm_evaluation_allowed == CheckResult::Allowed
}
/// <https://www.w3.org/TR/CSP/#should-block-navigation-request>
fn should_navigation_request_be_blocked(
&self,
global: &GlobalScope,
load_data: &LoadData,
element: Option<&Element>,
) -> bool {
let Some(csp_list) = self else {
return false;
};
let request = Request {
url: load_data.url.clone().into_url(),
origin: match &load_data.load_origin {
LoadOrigin::Script(immutable_origin) => immutable_origin.clone().into_url_origin(),
_ => Origin::new_opaque(),
},
// TODO: populate this field correctly
redirect_count: 0,
destination: Destination::None,
initiator: Initiator::None,
nonce: "".to_owned(),
integrity_metadata: "".to_owned(),
parser_metadata: ParserMetadata::None,
};
// TODO: set correct navigation check type for form submission if applicable
let (result, violations) =
csp_list.should_navigation_request_be_blocked(&request, NavigationCheckType::Other);
global.report_csp_violations(violations, element);
result == CheckResult::Blocked
}
/// <https://www.w3.org/TR/CSP/#should-block-inline>
fn should_elements_inline_type_behavior_be_blocked(
&self,
global: &GlobalScope,
el: &Element,
type_: InlineCheckType,
source: &str,
) -> bool {
let Some(csp_list) = self else {
return false;
};
let element = CspElement {
nonce: el.nonce_value_if_nonceable().map(Cow::Owned),
};
let (result, violations) =
csp_list.should_elements_inline_type_behavior_be_blocked(&element, type_, source);
global.report_csp_violations(violations, Some(el));
result == CheckResult::Blocked
}
/// <https://w3c.github.io/trusted-types/dist/spec/#should-block-create-policy>
fn is_trusted_type_policy_creation_allowed(
&self,
global: &GlobalScope,
policy_name: String,
created_policy_names: Vec<String>,
) -> bool {
let Some(csp_list) = self else {
return true;
};
let (allowed_by_csp, violations) =
csp_list.is_trusted_type_policy_creation_allowed(policy_name, created_policy_names);
global.report_csp_violations(violations, None);
allowed_by_csp == CheckResult::Allowed
}
/// <https://w3c.github.io/trusted-types/dist/spec/#abstract-opdef-does-sink-type-require-trusted-types>
fn does_sink_type_require_trusted_types(
&self,
sink_group: &str,
include_report_only_policies: bool,
) -> bool {
let Some(csp_list) = self else {
return false;
};
csp_list.does_sink_type_require_trusted_types(sink_group, include_report_only_policies)
}
/// <https://w3c.github.io/trusted-types/dist/spec/#should-block-sink-type-mismatch>
fn should_sink_type_mismatch_violation_be_blocked_by_csp(
&self,
global: &GlobalScope,
sink: &str,
sink_group: &str,
source: &str,
) -> bool {
let Some(csp_list) = self else {
return false;
};
let (allowed_by_csp, violations) = csp_list
.should_sink_type_mismatch_violation_be_blocked_by_csp(sink, sink_group, source);
global.report_csp_violations(violations, None);
allowed_by_csp == CheckResult::Blocked
}
}
pub(crate) trait GlobalCspReporting {
fn report_csp_violations(&self, violations: Vec<Violation>, element: Option<&Element>);
}
impl GlobalCspReporting for GlobalScope {
/// <https://www.w3.org/TR/CSP/#report-violation>
#[allow(unsafe_code)]
fn report_csp_violations(&self, violations: Vec<Violation>, element: Option<&Element>) {
let scripted_caller =
unsafe { describe_scripted_caller(*GlobalScope::get_cx()) }.unwrap_or_default();
for violation in violations {
let (sample, resource) = match violation.resource {
ViolationResource::Inline { sample } => (sample, "inline".to_owned()),
ViolationResource::Url(url) => (None, url.into()),
ViolationResource::TrustedTypePolicy { sample } => {
(Some(sample), "trusted-types-policy".to_owned())
},
ViolationResource::TrustedTypeSink { sample } => {
(Some(sample), "trusted-types-sink".to_owned())
},
ViolationResource::Eval { sample } => (sample, "eval".to_owned()),
ViolationResource::WasmEval => (None, "wasm-eval".to_owned()),
};
let report = CSPViolationReportBuilder::default()
.resource(resource)
.sample(sample)
.effective_directive(violation.directive.name)
.original_policy(violation.policy.to_string())
.report_only(violation.policy.disposition == PolicyDisposition::Report)
.source_file(scripted_caller.filename.clone())
.line_number(scripted_caller.line)
.column_number(scripted_caller.col + 1)
.build(self);
// Step 1: Let global be violations global object.
// We use `self` as `global`;
// Step 2: Let target be violations element.
let target = element.and_then(|event_target| {
// Step 3.1: If target is not null, and global is a Window,
// and targets shadow-including root is not globals associated Document, set target to null.
if let Some(window) = self.downcast::<Window>() {
// If a node is connected, its owner document is always the shadow-including root.
// If it isn't connected, then it also doesn't have a corresponding document, hence
// it can't be this document.
if event_target.upcast::<Node>().owner_document() != window.Document() {
return None;
}
}
Some(event_target)
});
let target = match target {
// Step 3.2: If target is null:
None => {
// Step 3.2.2: If target is a Window, set target to targets associated Document.
if let Some(window) = self.downcast::<Window>() {
Trusted::new(window.Document().upcast())
} else {
// Step 3.2.1: Set target to violations global object.
Trusted::new(self.upcast())
}
},
Some(event_target) => Trusted::new(event_target.upcast()),
};
// Step 3: Queue a task to run the following steps:
let task =
CSPViolationReportTask::new(Trusted::new(self), target, report, violation.policy);
self.task_manager()
.dom_manipulation_task_source()
.queue(task);
}
}
}
/// <https://www.w3.org/TR/CSP/#initialize-document-csp>
pub(crate) fn parse_csp_list_from_metadata(headers: &Option<Serde<HeaderMap>>) -> Option<CspList> {
// TODO: Implement step 1 (local scheme special case)
let headers = headers.as_ref()?;
let mut csp = headers.get_all("content-security-policy").iter();
// This silently ignores the CSP if it contains invalid Unicode.
// We should probably report an error somewhere.
let c = csp.next().and_then(|c| c.to_str().ok())?;
let mut csp_list = CspList::parse(c, PolicySource::Header, PolicyDisposition::Enforce);
for c in csp {
let c = c.to_str().ok()?;
csp_list.append(CspList::parse(
c,
PolicySource::Header,
PolicyDisposition::Enforce,
));
}
let csp_report = headers
.get_all("content-security-policy-report-only")
.iter();
// This silently ignores the CSP if it contains invalid Unicode.
// We should probably report an error somewhere.
for c in csp_report {
let c = c.to_str().ok()?;
csp_list.append(CspList::parse(
c,
PolicySource::Header,
PolicyDisposition::Report,
));
}
Some(csp_list)
}

View file

@ -43,6 +43,7 @@ use crate::dom::bindings::str::DOMString;
use crate::dom::bindings::structuredclone; use crate::dom::bindings::structuredclone;
use crate::dom::bindings::trace::{CustomTraceable, RootedTraceableBox}; use crate::dom::bindings::trace::{CustomTraceable, RootedTraceableBox};
use crate::dom::bindings::utils::define_all_exposed_interfaces; use crate::dom::bindings::utils::define_all_exposed_interfaces;
use crate::dom::csp::parse_csp_list_from_metadata;
use crate::dom::errorevent::ErrorEvent; use crate::dom::errorevent::ErrorEvent;
use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus}; use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
@ -479,7 +480,7 @@ impl DedicatedWorkerGlobalScope {
Ok((metadata, bytes)) => (metadata, bytes), Ok((metadata, bytes)) => (metadata, bytes),
}; };
scope.set_url(metadata.final_url.clone()); scope.set_url(metadata.final_url.clone());
scope.set_csp_list(GlobalScope::parse_csp_list_from_metadata(&metadata.headers)); scope.set_csp_list(parse_csp_list_from_metadata(&metadata.headers));
global_scope.set_https_state(metadata.https_state); global_scope.set_https_state(metadata.https_state);
let source = String::from_utf8_lossy(&bytes); let source = String::from_utf8_lossy(&bytes);
if let Some(chan) = global_scope.devtools_chan() { if let Some(chan) = global_scope.devtools_chan() {

View file

@ -2,7 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::borrow::Cow;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::hash_map::Entry::{Occupied, Vacant};
@ -22,7 +21,7 @@ use canvas_traits::canvas::CanvasId;
use canvas_traits::webgl::{self, WebGLContextId, WebGLMsg}; use canvas_traits::webgl::{self, WebGLContextId, WebGLMsg};
use chrono::Local; use chrono::Local;
use constellation_traits::{NavigationHistoryBehavior, ScriptToConstellationMessage}; use constellation_traits::{NavigationHistoryBehavior, ScriptToConstellationMessage};
use content_security_policy::{self as csp, CspList, PolicyDisposition}; use content_security_policy::{CspList, PolicyDisposition};
use cookie::Cookie; use cookie::Cookie;
use cssparser::match_ignore_ascii_case; use cssparser::match_ignore_ascii_case;
use data_url::mime::Mime; use data_url::mime::Mime;
@ -4306,30 +4305,6 @@ impl Document {
self.policy_container.borrow().csp_list.clone() self.policy_container.borrow().csp_list.clone()
} }
/// <https://www.w3.org/TR/CSP/#should-block-inline>
pub(crate) fn should_elements_inline_type_behavior_be_blocked(
&self,
el: &Element,
type_: csp::InlineCheckType,
source: &str,
) -> csp::CheckResult {
let (result, violations) = match self.get_csp_list() {
None => {
return csp::CheckResult::Allowed;
},
Some(csp_list) => {
let element = csp::Element {
nonce: el.nonce_value_if_nonceable().map(Cow::Owned),
};
csp_list.should_elements_inline_type_behavior_be_blocked(&element, type_, source)
},
};
self.global().report_csp_violations(violations, Some(el));
result
}
/// Prevent any JS or layout from running until the corresponding call to /// Prevent any JS or layout from running until the corresponding call to
/// `remove_script_and_layout_blocker`. Used to isolate periods in which /// `remove_script_and_layout_blocker`. Used to isolate periods in which
/// the DOM is in an unstable state and should not be exposed to arbitrary /// the DOM is in an unstable state and should not be exposed to arbitrary

View file

@ -12,7 +12,6 @@ use std::rc::Rc;
use std::str::FromStr; use std::str::FromStr;
use std::{fmt, mem}; use std::{fmt, mem};
use content_security_policy as csp;
use cssparser::{Parser as CssParser, ParserInput as CssParserInput, match_ignore_ascii_case}; use cssparser::{Parser as CssParser, ParserInput as CssParserInput, match_ignore_ascii_case};
use devtools_traits::AttrInfo; use devtools_traits::AttrInfo;
use dom_struct::dom_struct; use dom_struct::dom_struct;
@ -99,6 +98,7 @@ use crate::dom::bindings::xmlname::{
}; };
use crate::dom::characterdata::CharacterData; use crate::dom::characterdata::CharacterData;
use crate::dom::create::create_element; use crate::dom::create::create_element;
use crate::dom::csp::{CspReporting, InlineCheckType};
use crate::dom::customelementregistry::{ use crate::dom::customelementregistry::{
CallbackReaction, CustomElementDefinition, CustomElementReaction, CustomElementState, CallbackReaction, CustomElementDefinition, CustomElementReaction, CustomElementState,
is_valid_custom_element_name, is_valid_custom_element_name,
@ -2259,15 +2259,19 @@ impl Element {
} else { } else {
let win = self.owner_window(); let win = self.owner_window();
let source = &**attr.value(); let source = &**attr.value();
let global = &self.owner_global();
// However, if the Should element's inline behavior be blocked by // However, if the Should element's inline behavior be blocked by
// Content Security Policy? algorithm returns "Blocked" when executed // Content Security Policy? algorithm returns "Blocked" when executed
// upon the attribute's element, "style attribute", and the attribute's value, // upon the attribute's element, "style attribute", and the attribute's value,
// then the style rules defined in the attribute's value must not be applied to the element. [CSP] // then the style rules defined in the attribute's value must not be applied to the element. [CSP]
if doc.should_elements_inline_type_behavior_be_blocked( if global
self, .get_csp_list()
csp::InlineCheckType::StyleAttribute, .should_elements_inline_type_behavior_be_blocked(
source, global,
) == csp::CheckResult::Blocked self,
InlineCheckType::StyleAttribute,
source,
)
{ {
return; return;
} }

View file

@ -8,7 +8,6 @@ use std::str::{Chars, FromStr};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::Duration; use std::time::Duration;
use content_security_policy as csp;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use headers::ContentType; use headers::ContentType;
use http::StatusCode; use http::StatusCode;
@ -37,6 +36,7 @@ use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object_with_proto}; use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object_with_proto};
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::csp::{GlobalCspReporting, Violation};
use crate::dom::event::Event; use crate::dom::event::Event;
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
@ -474,7 +474,7 @@ impl FetchResponseListener for EventSourceContext {
network_listener::submit_timing(self, CanGc::note()) network_listener::submit_timing(self, CanGc::note())
} }
fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<Violation>) {
let global = &self.resource_timing_global(); let global = &self.resource_timing_global();
global.report_csp_violations(violations, None); global.report_csp_violations(violations, None);
} }

View file

@ -11,7 +11,6 @@ use std::mem;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::rc::Rc; use std::rc::Rc;
use content_security_policy as csp;
use deny_public_fields::DenyPublicFields; use deny_public_fields::DenyPublicFields;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use fnv::FnvHasher; use fnv::FnvHasher;
@ -56,6 +55,7 @@ use crate::dom::bindings::reflector::{
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::bindings::trace::HashMapTracedValues; use crate::dom::bindings::trace::HashMapTracedValues;
use crate::dom::csp::{CspReporting, InlineCheckType};
use crate::dom::document::Document; use crate::dom::document::Document;
use crate::dom::element::Element; use crate::dom::element::Element;
use crate::dom::errorevent::ErrorEvent; use crate::dom::errorevent::ErrorEvent;
@ -556,11 +556,15 @@ impl EventTarget {
) { ) {
if let Some(element) = self.downcast::<Element>() { if let Some(element) = self.downcast::<Element>() {
let doc = element.owner_document(); let doc = element.owner_document();
if doc.should_elements_inline_type_behavior_be_blocked( let global = &doc.global();
element.upcast(), if global
csp::InlineCheckType::ScriptAttribute, .get_csp_list()
source, .should_elements_inline_type_behavior_be_blocked(
) == csp::CheckResult::Blocked global,
element.upcast(),
InlineCheckType::ScriptAttribute,
source,
)
{ {
return; return;
} }

View file

@ -18,19 +18,14 @@ use base::id::{
ServiceWorkerId, ServiceWorkerRegistrationId, WebViewId, ServiceWorkerId, ServiceWorkerRegistrationId, WebViewId,
}; };
use constellation_traits::{ use constellation_traits::{
BlobData, BlobImpl, BroadcastMsg, FileBlob, LoadData, LoadOrigin, MessagePortImpl, BlobData, BlobImpl, BroadcastMsg, FileBlob, MessagePortImpl, MessagePortMsg, PortMessageTask,
MessagePortMsg, PortMessageTask, ScriptToConstellationChan, ScriptToConstellationMessage, ScriptToConstellationChan, ScriptToConstellationMessage,
};
use content_security_policy::{
CheckResult, CspList, Destination, Initiator, NavigationCheckType, ParserMetadata,
PolicyDisposition, PolicySource, Request, Violation, ViolationResource,
}; };
use content_security_policy::CspList;
use crossbeam_channel::Sender; use crossbeam_channel::Sender;
use devtools_traits::{PageError, ScriptToDevtoolsControlMsg}; use devtools_traits::{PageError, ScriptToDevtoolsControlMsg};
use dom_struct::dom_struct; use dom_struct::dom_struct;
use embedder_traits::EmbedderMsg; use embedder_traits::EmbedderMsg;
use http::HeaderMap;
use hyper_serde::Serde;
use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::ipc::{self, IpcSender};
use ipc_channel::router::ROUTER; use ipc_channel::router::ROUTER;
use js::glue::{IsWrapper, UnwrapObjectDynamic}; use js::glue::{IsWrapper, UnwrapObjectDynamic};
@ -43,8 +38,7 @@ use js::panic::maybe_resume_unwind;
use js::rust::wrappers::{JS_ExecuteScript, JS_GetScriptPrivate}; use js::rust::wrappers::{JS_ExecuteScript, JS_GetScriptPrivate};
use js::rust::{ use js::rust::{
CompileOptionsWrapper, CustomAutoRooter, CustomAutoRooterGuard, HandleValue, CompileOptionsWrapper, CustomAutoRooter, CustomAutoRooterGuard, HandleValue,
MutableHandleValue, ParentRuntime, Runtime, describe_scripted_caller, get_object_class, MutableHandleValue, ParentRuntime, Runtime, get_object_class, transform_str_to_source_text,
transform_str_to_source_text,
}; };
use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL}; use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
use net_traits::blob_url_store::{BlobBuf, get_blob_origin}; use net_traits::blob_url_store::{BlobBuf, get_blob_origin};
@ -63,7 +57,6 @@ use profile_traits::{ipc as profile_ipc, mem as profile_mem, time as profile_tim
use script_bindings::interfaces::GlobalScopeHelpers; use script_bindings::interfaces::GlobalScopeHelpers;
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
use timers::{TimerEventRequest, TimerId}; use timers::{TimerEventRequest, TimerId};
use url::Origin;
use uuid::Uuid; use uuid::Uuid;
#[cfg(feature = "webgpu")] #[cfg(feature = "webgpu")]
use webgpu_traits::{DeviceLostReason, WebGPUDevice}; use webgpu_traits::{DeviceLostReason, WebGPUDevice};
@ -101,11 +94,9 @@ use crate::dom::bindings::weakref::{DOMTracker, WeakRef};
use crate::dom::blob::Blob; use crate::dom::blob::Blob;
use crate::dom::broadcastchannel::BroadcastChannel; use crate::dom::broadcastchannel::BroadcastChannel;
use crate::dom::crypto::Crypto; use crate::dom::crypto::Crypto;
use crate::dom::csppolicyviolationreport::CSPViolationReportBuilder;
use crate::dom::dedicatedworkerglobalscope::{ use crate::dom::dedicatedworkerglobalscope::{
DedicatedWorkerControlMsg, DedicatedWorkerGlobalScope, DedicatedWorkerControlMsg, DedicatedWorkerGlobalScope,
}; };
use crate::dom::element::Element;
use crate::dom::errorevent::ErrorEvent; use crate::dom::errorevent::ErrorEvent;
use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus}; use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
use crate::dom::eventsource::EventSource; use crate::dom::eventsource::EventSource;
@ -113,7 +104,6 @@ use crate::dom::eventtarget::EventTarget;
use crate::dom::file::File; use crate::dom::file::File;
use crate::dom::htmlscriptelement::{ScriptId, SourceCode}; use crate::dom::htmlscriptelement::{ScriptId, SourceCode};
use crate::dom::messageport::MessagePort; use crate::dom::messageport::MessagePort;
use crate::dom::node::{Node, NodeTraits};
use crate::dom::paintworkletglobalscope::PaintWorkletGlobalScope; use crate::dom::paintworkletglobalscope::PaintWorkletGlobalScope;
use crate::dom::performance::Performance; use crate::dom::performance::Performance;
use crate::dom::performanceobserver::VALID_ENTRY_TYPES; use crate::dom::performanceobserver::VALID_ENTRY_TYPES;
@ -141,7 +131,6 @@ use crate::script_module::{
}; };
use crate::script_runtime::{CanGc, JSContext as SafeJSContext, ThreadSafeJSContext}; use crate::script_runtime::{CanGc, JSContext as SafeJSContext, ThreadSafeJSContext};
use crate::script_thread::{ScriptThread, with_script_thread}; use crate::script_thread::{ScriptThread, with_script_thread};
use crate::security_manager::CSPViolationReportTask;
use crate::task_manager::TaskManager; use crate::task_manager::TaskManager;
use crate::task_source::SendableTaskSource; use crate::task_source::SendableTaskSource;
use crate::timers::{ use crate::timers::{
@ -2520,41 +2509,6 @@ impl GlobalScope {
unreachable!(); unreachable!();
} }
/// <https://www.w3.org/TR/CSP/#initialize-document-csp>
pub(crate) fn parse_csp_list_from_metadata(
headers: &Option<Serde<HeaderMap>>,
) -> Option<CspList> {
// TODO: Implement step 1 (local scheme special case)
let headers = headers.as_ref()?;
let mut csp = headers.get_all("content-security-policy").iter();
// This silently ignores the CSP if it contains invalid Unicode.
// We should probably report an error somewhere.
let c = csp.next().and_then(|c| c.to_str().ok())?;
let mut csp_list = CspList::parse(c, PolicySource::Header, PolicyDisposition::Enforce);
for c in csp {
let c = c.to_str().ok()?;
csp_list.append(CspList::parse(
c,
PolicySource::Header,
PolicyDisposition::Enforce,
));
}
let csp_report = headers
.get_all("content-security-policy-report-only")
.iter();
// This silently ignores the CSP if it contains invalid Unicode.
// We should probably report an error somewhere.
for c in csp_report {
let c = c.to_str().ok()?;
csp_list.append(CspList::parse(
c,
PolicySource::Header,
PolicyDisposition::Report,
));
}
Some(csp_list)
}
/// Get the [base url](https://html.spec.whatwg.org/multipage/#api-base-url) /// Get the [base url](https://html.spec.whatwg.org/multipage/#api-base-url)
/// for this global scope. /// for this global scope.
pub(crate) fn api_base_url(&self) -> ServoUrl { pub(crate) fn api_base_url(&self) -> ServoUrl {
@ -2939,49 +2893,6 @@ impl GlobalScope {
})) }))
} }
pub(crate) fn is_js_evaluation_allowed(&self, source: &str) -> bool {
let Some(csp_list) = self.get_csp_list() else {
return true;
};
let (is_js_evaluation_allowed, violations) = csp_list.is_js_evaluation_allowed(source);
self.report_csp_violations(violations, None);
is_js_evaluation_allowed == CheckResult::Allowed
}
pub(crate) fn should_navigation_request_be_blocked(
&self,
load_data: &LoadData,
element: Option<&Element>,
) -> bool {
let Some(csp_list) = self.get_csp_list() else {
return false;
};
let request = Request {
url: load_data.url.clone().into_url(),
origin: match &load_data.load_origin {
LoadOrigin::Script(immutable_origin) => immutable_origin.clone().into_url_origin(),
_ => Origin::new_opaque(),
},
// TODO: populate this field correctly
redirect_count: 0,
destination: Destination::None,
initiator: Initiator::None,
nonce: "".to_owned(),
integrity_metadata: "".to_owned(),
parser_metadata: ParserMetadata::None,
};
// TODO: set correct navigation check type for form submission if applicable
let (result, violations) =
csp_list.should_navigation_request_be_blocked(&request, NavigationCheckType::Other);
self.report_csp_violations(violations, element);
result == CheckResult::Blocked
}
pub(crate) fn fire_timer(&self, handle: TimerEventId, can_gc: CanGc) { pub(crate) fn fire_timer(&self, handle: TimerEventId, can_gc: CanGc) {
self.timers().fire_timer(handle, self, can_gc); self.timers().fire_timer(handle, self, can_gc);
} }
@ -3421,76 +3332,6 @@ impl GlobalScope {
unreachable!(); unreachable!();
} }
/// <https://www.w3.org/TR/CSP/#report-violation>
#[allow(unsafe_code)]
pub(crate) fn report_csp_violations(
&self,
violations: Vec<Violation>,
element: Option<&Element>,
) {
let scripted_caller =
unsafe { describe_scripted_caller(*GlobalScope::get_cx()) }.unwrap_or_default();
for violation in violations {
let (sample, resource) = match violation.resource {
ViolationResource::Inline { sample } => (sample, "inline".to_owned()),
ViolationResource::Url(url) => (None, url.into()),
ViolationResource::TrustedTypePolicy { sample } => {
(Some(sample), "trusted-types-policy".to_owned())
},
ViolationResource::TrustedTypeSink { sample } => {
(Some(sample), "trusted-types-sink".to_owned())
},
ViolationResource::Eval { sample } => (sample, "eval".to_owned()),
ViolationResource::WasmEval => (None, "wasm-eval".to_owned()),
};
let report = CSPViolationReportBuilder::default()
.resource(resource)
.sample(sample)
.effective_directive(violation.directive.name)
.original_policy(violation.policy.to_string())
.report_only(violation.policy.disposition == PolicyDisposition::Report)
.source_file(scripted_caller.filename.clone())
.line_number(scripted_caller.line)
.column_number(scripted_caller.col + 1)
.build(self);
// Step 1: Let global be violations global object.
// We use `self` as `global`;
// Step 2: Let target be violations element.
let target = element.and_then(|event_target| {
// Step 3.1: If target is not null, and global is a Window,
// and targets shadow-including root is not globals associated Document, set target to null.
if let Some(window) = self.downcast::<Window>() {
// If a node is connected, its owner document is always the shadow-including root.
// If it isn't connected, then it also doesn't have a corresponding document, hence
// it can't be this document.
if event_target.upcast::<Node>().owner_document() != window.Document() {
return None;
}
}
Some(event_target)
});
let target = match target {
// Step 3.2: If target is null:
None => {
// Step 3.2.2: If target is a Window, set target to targets associated Document.
if let Some(window) = self.downcast::<Window>() {
Trusted::new(window.Document().upcast())
} else {
// Step 3.2.1: Set target to violations global object.
Trusted::new(self.upcast())
}
},
Some(event_target) => Trusted::new(event_target.upcast()),
};
// Step 3: Queue a task to run the following steps:
let task =
CSPViolationReportTask::new(Trusted::new(self), target, report, violation.policy);
self.task_manager()
.dom_manipulation_task_source()
.queue(task);
}
}
pub(crate) fn import_map(&self) -> Ref<'_, ImportMap> { pub(crate) fn import_map(&self) -> Ref<'_, ImportMap> {
self.import_map.borrow() self.import_map.borrow()
} }

View file

@ -34,6 +34,7 @@ use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::DomGlobal; use crate::dom::bindings::reflector::DomGlobal;
use crate::dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom}; use crate::dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom};
use crate::dom::bindings::str::{DOMString, USVString}; use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::csp::CspReporting;
use crate::dom::document::{Document, determine_policy_for_token}; use crate::dom::document::{Document, determine_policy_for_token};
use crate::dom::domtokenlist::DOMTokenList; use crate::dom::domtokenlist::DOMTokenList;
use crate::dom::element::{ use crate::dom::element::{
@ -166,10 +167,12 @@ impl HTMLIFrameElement {
if load_data.url.scheme() == "javascript" { if load_data.url.scheme() == "javascript" {
let window_proxy = self.GetContentWindow(); let window_proxy = self.GetContentWindow();
if let Some(window_proxy) = window_proxy { if let Some(window_proxy) = window_proxy {
if document let global = &document.global();
.global() if global.get_csp_list().should_navigation_request_be_blocked(
.should_navigation_request_be_blocked(&load_data, Some(self.upcast())) global,
{ &load_data,
Some(self.upcast()),
) {
return; return;
} }
// Important re security. See https://github.com/servo/servo/issues/23373 // Important re security. See https://github.com/servo/servo/issues/23373

View file

@ -10,7 +10,6 @@ use std::sync::Arc;
use std::{char, mem}; use std::{char, mem};
use app_units::{AU_PER_PX, Au}; use app_units::{AU_PER_PX, Au};
use content_security_policy as csp;
use cssparser::{Parser, ParserInput}; use cssparser::{Parser, ParserInput};
use dom_struct::dom_struct; use dom_struct::dom_struct;
use euclid::Point2D; use euclid::Point2D;
@ -60,6 +59,7 @@ use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::DomGlobal; use crate::dom::bindings::reflector::DomGlobal;
use crate::dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom}; use crate::dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom};
use crate::dom::bindings::str::{DOMString, USVString}; use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::csp::{GlobalCspReporting, Violation};
use crate::dom::document::{Document, determine_policy_for_token}; use crate::dom::document::{Document, determine_policy_for_token};
use crate::dom::element::{ use crate::dom::element::{
AttributeMutation, CustomElementCreationMode, Element, ElementCreator, LayoutElementHelpers, AttributeMutation, CustomElementCreationMode, Element, ElementCreator, LayoutElementHelpers,
@ -295,7 +295,7 @@ impl FetchResponseListener for ImageContext {
network_listener::submit_timing(self, CanGc::note()) network_listener::submit_timing(self, CanGc::note())
} }
fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<Violation>) {
let global = &self.resource_timing_global(); let global = &self.resource_timing_global();
global.report_csp_violations(violations, None); global.report_csp_violations(violations, None);
} }

View file

@ -8,7 +8,6 @@ use std::default::Default;
use std::str::FromStr; use std::str::FromStr;
use base::id::WebViewId; use base::id::WebViewId;
use content_security_policy as csp;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use embedder_traits::EmbedderMsg; use embedder_traits::EmbedderMsg;
use html5ever::{LocalName, Prefix, local_name, ns}; use html5ever::{LocalName, Prefix, local_name, ns};
@ -39,6 +38,7 @@ use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::DomGlobal; use crate::dom::bindings::reflector::DomGlobal;
use crate::dom::bindings::root::{DomRoot, MutNullableDom}; use crate::dom::bindings::root::{DomRoot, MutNullableDom};
use crate::dom::bindings::str::{DOMString, USVString}; use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::csp::{GlobalCspReporting, Violation};
use crate::dom::cssstylesheet::CSSStyleSheet; use crate::dom::cssstylesheet::CSSStyleSheet;
use crate::dom::document::Document; use crate::dom::document::Document;
use crate::dom::domtokenlist::DOMTokenList; use crate::dom::domtokenlist::DOMTokenList;
@ -1016,7 +1016,7 @@ impl FetchResponseListener for PrefetchContext {
submit_timing(self, CanGc::note()) submit_timing(self, CanGc::note())
} }
fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<Violation>) {
let global = &self.resource_timing_global(); let global = &self.resource_timing_global();
global.report_csp_violations(violations, None); global.report_csp_violations(violations, None);
} }
@ -1090,7 +1090,7 @@ impl FetchResponseListener for PreloadContext {
submit_timing(self, CanGc::note()) submit_timing(self, CanGc::note())
} }
fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<Violation>) {
let global = &self.resource_timing_global(); let global = &self.resource_timing_global();
global.report_csp_violations(violations, None); global.report_csp_violations(violations, None);
} }

View file

@ -10,7 +10,6 @@ use std::time::{Duration, Instant};
use std::{f64, mem}; use std::{f64, mem};
use compositing_traits::{CrossProcessCompositorApi, ImageUpdate, SerializableImageData}; use compositing_traits::{CrossProcessCompositorApi, ImageUpdate, SerializableImageData};
use content_security_policy as csp;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use embedder_traits::{MediaPositionState, MediaSessionEvent, MediaSessionPlaybackState}; use embedder_traits::{MediaPositionState, MediaSessionEvent, MediaSessionPlaybackState};
use euclid::default::Size2D; use euclid::default::Size2D;
@ -74,6 +73,7 @@ use crate::dom::bindings::reflector::DomGlobal;
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
use crate::dom::bindings::str::{DOMString, USVString}; use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::blob::Blob; use crate::dom::blob::Blob;
use crate::dom::csp::{GlobalCspReporting, Violation};
use crate::dom::document::Document; use crate::dom::document::Document;
use crate::dom::element::{ use crate::dom::element::{
AttributeMutation, Element, ElementCreator, cors_setting_for_element, AttributeMutation, Element, ElementCreator, cors_setting_for_element,
@ -3167,7 +3167,7 @@ impl FetchResponseListener for HTMLMediaElementFetchListener {
network_listener::submit_timing(self, CanGc::note()) network_listener::submit_timing(self, CanGc::note())
} }
fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<Violation>) {
let global = &self.resource_timing_global(); let global = &self.resource_timing_global();
global.report_csp_violations(violations, None); global.report_csp_violations(violations, None);
} }

View file

@ -12,7 +12,6 @@ use std::rc::Rc;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use base::id::{PipelineId, WebViewId}; use base::id::{PipelineId, WebViewId};
use content_security_policy as csp;
use devtools_traits::{ScriptToDevtoolsControlMsg, SourceInfo}; use devtools_traits::{ScriptToDevtoolsControlMsg, SourceInfo};
use dom_struct::dom_struct; use dom_struct::dom_struct;
use encoding_rs::Encoding; use encoding_rs::Encoding;
@ -58,6 +57,7 @@ use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
use crate::dom::bindings::settings_stack::AutoEntryScript; use crate::dom::bindings::settings_stack::AutoEntryScript;
use crate::dom::bindings::str::{DOMString, USVString}; use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::bindings::trace::NoTrace; use crate::dom::bindings::trace::NoTrace;
use crate::dom::csp::{CspReporting, GlobalCspReporting, InlineCheckType, Violation};
use crate::dom::document::Document; use crate::dom::document::Document;
use crate::dom::element::{ use crate::dom::element::{
AttributeMutation, Element, ElementCreator, cors_setting_for_element, AttributeMutation, Element, ElementCreator, cors_setting_for_element,
@ -557,7 +557,7 @@ impl FetchResponseListener for ClassicContext {
network_listener::submit_timing(self, CanGc::note()) network_listener::submit_timing(self, CanGc::note())
} }
fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<Violation>) {
let global = &self.resource_timing_global(); let global = &self.resource_timing_global();
let elem = self.elem.root(); let elem = self.elem.root();
global.report_csp_violations(violations, Some(elem.upcast::<Element>())); global.report_csp_violations(violations, Some(elem.upcast::<Element>()));
@ -763,13 +763,18 @@ impl HTMLScriptElement {
return; return;
} }
let global = &doc.global();
// Step 19. CSP. // Step 19. CSP.
if !element.has_attribute(&local_name!("src")) && if !element.has_attribute(&local_name!("src")) &&
doc.should_elements_inline_type_behavior_be_blocked( global
element, .get_csp_list()
csp::InlineCheckType::Script, .should_elements_inline_type_behavior_be_blocked(
&text, global,
) == csp::CheckResult::Blocked element,
InlineCheckType::Script,
&text,
)
{ {
warn!("Blocking inline script due to CSP"); warn!("Blocking inline script due to CSP");
return; return;

View file

@ -4,7 +4,6 @@
use std::cell::Cell; use std::cell::Cell;
use content_security_policy as csp;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use html5ever::{LocalName, Prefix}; use html5ever::{LocalName, Prefix};
use js::rust::HandleObject; use js::rust::HandleObject;
@ -20,6 +19,7 @@ use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::root::{DomRoot, MutNullableDom}; use crate::dom::bindings::root::{DomRoot, MutNullableDom};
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::csp::{CspReporting, InlineCheckType};
use crate::dom::cssstylesheet::CSSStyleSheet; use crate::dom::cssstylesheet::CSSStyleSheet;
use crate::dom::document::Document; use crate::dom::document::Document;
use crate::dom::element::{AttributeMutation, Element, ElementCreator}; use crate::dom::element::{AttributeMutation, Element, ElementCreator};
@ -99,15 +99,19 @@ impl HTMLStyleElement {
} }
let doc = self.owner_document(); let doc = self.owner_document();
let global = &self.owner_global();
// Step 5: If the Should element's inline behavior be blocked by Content Security Policy? algorithm // Step 5: If the Should element's inline behavior be blocked by Content Security Policy? algorithm
// returns "Blocked" when executed upon the style element, "style", // returns "Blocked" when executed upon the style element, "style",
// and the style element's child text content, then return. [CSP] // and the style element's child text content, then return. [CSP]
if doc.should_elements_inline_type_behavior_be_blocked( if global
self.upcast(), .get_csp_list()
csp::InlineCheckType::Style, .should_elements_inline_type_behavior_be_blocked(
&node.child_text_content(), global,
) == csp::CheckResult::Blocked self.upcast(),
InlineCheckType::Style,
&node.child_text_content(),
)
{ {
return; return;
} }

View file

@ -5,7 +5,6 @@
use std::cell::Cell; use std::cell::Cell;
use std::sync::Arc; use std::sync::Arc;
use content_security_policy as csp;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use euclid::default::Size2D; use euclid::default::Size2D;
use html5ever::{LocalName, Prefix, local_name, ns}; use html5ever::{LocalName, Prefix, local_name, ns};
@ -34,6 +33,7 @@ use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::DomGlobal; use crate::dom::bindings::reflector::DomGlobal;
use crate::dom::bindings::root::{DomRoot, LayoutDom}; use crate::dom::bindings::root::{DomRoot, LayoutDom};
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::csp::{GlobalCspReporting, Violation};
use crate::dom::document::Document; use crate::dom::document::Document;
use crate::dom::element::{AttributeMutation, Element, LayoutElementHelpers}; use crate::dom::element::{AttributeMutation, Element, LayoutElementHelpers};
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
@ -463,7 +463,7 @@ impl FetchResponseListener for PosterFrameFetchContext {
network_listener::submit_timing(self, CanGc::note()) network_listener::submit_timing(self, CanGc::note())
} }
fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<Violation>) {
let global = &self.resource_timing_global(); let global = &self.resource_timing_global();
global.report_csp_violations(violations, None); global.report_csp_violations(violations, None);
} }

View file

@ -263,6 +263,7 @@ pub(crate) mod countqueuingstrategy;
mod create; mod create;
pub(crate) mod crypto; pub(crate) mod crypto;
pub(crate) mod cryptokey; pub(crate) mod cryptokey;
pub(crate) mod csp;
pub(crate) mod csppolicyviolationreport; pub(crate) mod csppolicyviolationreport;
pub(crate) mod css; pub(crate) mod css;
pub(crate) mod cssconditionrule; pub(crate) mod cssconditionrule;

View file

@ -7,8 +7,6 @@ use std::rc::Rc;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use content_security_policy as csp;
use content_security_policy::Destination;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use embedder_traits::{ use embedder_traits::{
EmbedderMsg, Notification as EmbedderNotification, EmbedderMsg, Notification as EmbedderNotification,
@ -24,7 +22,7 @@ use net_traits::image_cache::{
ImageCache, ImageCacheResponseMessage, ImageCacheResult, ImageLoadListener, ImageCache, ImageCacheResponseMessage, ImageCacheResult, ImageLoadListener,
ImageOrMetadataAvailable, ImageResponse, PendingImageId, UsePlaceholder, ImageOrMetadataAvailable, ImageResponse, PendingImageId, UsePlaceholder,
}; };
use net_traits::request::{RequestBuilder, RequestId}; use net_traits::request::{Destination, RequestBuilder, RequestId};
use net_traits::{ use net_traits::{
FetchMetadata, FetchResponseListener, FetchResponseMsg, NetworkError, ResourceFetchTiming, FetchMetadata, FetchResponseListener, FetchResponseMsg, NetworkError, ResourceFetchTiming,
ResourceTimingType, ResourceTimingType,
@ -55,6 +53,7 @@ use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::{DOMString, USVString}; use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::bindings::trace::RootedTraceableBox; use crate::dom::bindings::trace::RootedTraceableBox;
use crate::dom::bindings::utils::to_frozen_array; use crate::dom::bindings::utils::to_frozen_array;
use crate::dom::csp::{GlobalCspReporting, Violation};
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::permissions::{PermissionAlgorithm, Permissions, descriptor_permission_state}; use crate::dom::permissions::{PermissionAlgorithm, Permissions, descriptor_permission_state};
@ -793,7 +792,7 @@ impl FetchResponseListener for ResourceFetchListener {
network_listener::submit_timing(self, CanGc::note()) network_listener::submit_timing(self, CanGc::note())
} }
fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<Violation>) {
let global = &self.resource_timing_global(); let global = &self.resource_timing_global();
global.report_csp_violations(violations, None); global.report_csp_violations(violations, None);
} }

View file

@ -9,7 +9,6 @@ use base::cross_process_instant::CrossProcessInstant;
use base::id::PipelineId; use base::id::PipelineId;
use base64::Engine as _; use base64::Engine as _;
use base64::engine::general_purpose; use base64::engine::general_purpose;
use content_security_policy as csp;
use devtools_traits::ScriptToDevtoolsControlMsg; use devtools_traits::ScriptToDevtoolsControlMsg;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use embedder_traits::resources::{self, Resource}; use embedder_traits::resources::{self, Resource};
@ -57,11 +56,11 @@ use crate::dom::bindings::settings_stack::is_execution_stack_empty;
use crate::dom::bindings::str::{DOMString, USVString}; use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::characterdata::CharacterData; use crate::dom::characterdata::CharacterData;
use crate::dom::comment::Comment; use crate::dom::comment::Comment;
use crate::dom::csp::{GlobalCspReporting, Violation, parse_csp_list_from_metadata};
use crate::dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument}; use crate::dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument};
use crate::dom::documentfragment::DocumentFragment; use crate::dom::documentfragment::DocumentFragment;
use crate::dom::documenttype::DocumentType; use crate::dom::documenttype::DocumentType;
use crate::dom::element::{CustomElementCreationMode, Element, ElementCreator}; use crate::dom::element::{CustomElementCreationMode, Element, ElementCreator};
use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlformelement::{FormControlElementHelpers, HTMLFormElement}; use crate::dom::htmlformelement::{FormControlElementHelpers, HTMLFormElement};
use crate::dom::htmlimageelement::HTMLImageElement; use crate::dom::htmlimageelement::HTMLImageElement;
use crate::dom::htmlinputelement::HTMLInputElement; use crate::dom::htmlinputelement::HTMLInputElement;
@ -908,7 +907,7 @@ impl FetchResponseListener for ParserContext {
let csp_list = metadata let csp_list = metadata
.as_ref() .as_ref()
.and_then(|m| GlobalScope::parse_csp_list_from_metadata(&m.headers)); .and_then(|m| parse_csp_list_from_metadata(&m.headers));
let parser = match ScriptThread::page_headers_available(&self.id, metadata, CanGc::note()) { let parser = match ScriptThread::page_headers_available(&self.id, metadata, CanGc::note()) {
Some(parser) => parser, Some(parser) => parser,
@ -1105,7 +1104,7 @@ impl FetchResponseListener for ParserContext {
); );
} }
fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<Violation>) {
let parser = match self.parser.as_ref() { let parser = match self.parser.as_ref() {
Some(parser) => parser.root(), Some(parser) => parser.root(),
None => return, None => return,

View file

@ -6,7 +6,6 @@ use std::cell::{Cell, RefCell};
use std::ops::Deref; use std::ops::Deref;
use base::id::{PipelineId, WebViewId}; use base::id::{PipelineId, WebViewId};
use content_security_policy::Destination;
use html5ever::buffer_queue::BufferQueue; use html5ever::buffer_queue::BufferQueue;
use html5ever::tokenizer::states::RawKind; use html5ever::tokenizer::states::RawKind;
use html5ever::tokenizer::{ use html5ever::tokenizer::{
@ -17,7 +16,7 @@ use js::jsapi::JSTracer;
use markup5ever::TokenizerResult; use markup5ever::TokenizerResult;
use net_traits::policy_container::PolicyContainer; use net_traits::policy_container::PolicyContainer;
use net_traits::request::{ use net_traits::request::{
CorsSettings, CredentialsMode, InsecureRequestsPolicy, ParserMetadata, Referrer, CorsSettings, CredentialsMode, Destination, InsecureRequestsPolicy, ParserMetadata, Referrer,
}; };
use net_traits::{CoreResourceMsg, FetchChannels, IpcSend, ReferrerPolicy, ResourceThreads}; use net_traits::{CoreResourceMsg, FetchChannels, IpcSend, ReferrerPolicy, ResourceThreads};
use servo_url::{ImmutableOrigin, ServoUrl}; use servo_url::{ImmutableOrigin, ServoUrl};

View file

@ -3,7 +3,6 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::cell::RefCell; use std::cell::RefCell;
use content_security_policy::CheckResult;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use html5ever::{LocalName, Namespace, QualName, local_name, ns}; use html5ever::{LocalName, Namespace, QualName, local_name, ns};
use js::jsval::NullValue; use js::jsval::NullValue;
@ -17,6 +16,7 @@ use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object}; use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
use crate::dom::bindings::root::{DomRoot, MutNullableDom}; use crate::dom::bindings::root::{DomRoot, MutNullableDom};
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::csp::CspReporting;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::trustedhtml::TrustedHTML; use crate::dom::trustedhtml::TrustedHTML;
use crate::dom::trustedscript::TrustedScript; use crate::dom::trustedscript::TrustedScript;
@ -57,19 +57,16 @@ impl TrustedTypePolicyFactory {
) -> Fallible<DomRoot<TrustedTypePolicy>> { ) -> Fallible<DomRoot<TrustedTypePolicy>> {
// Step 1: Let allowedByCSP be the result of executing Should Trusted Type policy creation be blocked by // Step 1: Let allowedByCSP be the result of executing Should Trusted Type policy creation be blocked by
// Content Security Policy? algorithm with global, policyName and factorys created policy names value. // Content Security Policy? algorithm with global, policyName and factorys created policy names value.
let (allowed_by_csp, violations) = if let Some(csp_list) = global.get_csp_list() { let allowed_by_csp = global
csp_list.is_trusted_type_policy_creation_allowed( .get_csp_list()
.is_trusted_type_policy_creation_allowed(
global,
policy_name.clone(), policy_name.clone(),
self.policy_names.borrow().clone(), self.policy_names.borrow().clone(),
) );
} else {
(CheckResult::Allowed, Vec::new())
};
global.report_csp_violations(violations, None);
// Step 2: If allowedByCSP is "Blocked", throw a TypeError and abort further steps. // Step 2: If allowedByCSP is "Blocked", throw a TypeError and abort further steps.
if allowed_by_csp == CheckResult::Blocked { if !allowed_by_csp {
return Err(Error::Type("Not allowed by CSP".to_string())); return Err(Error::Type("Not allowed by CSP".to_string()));
} }
@ -198,13 +195,11 @@ impl TrustedTypePolicyFactory {
sink_group: &str, sink_group: &str,
can_gc: CanGc, can_gc: CanGc,
) -> Fallible<DOMString> { ) -> Fallible<DOMString> {
let csp_list = match global.get_csp_list() {
None => return Ok(input),
Some(csp_list) => csp_list,
};
// Step 2: Let requireTrustedTypes be the result of executing Does sink type require trusted types? // Step 2: Let requireTrustedTypes be the result of executing Does sink type require trusted types?
// algorithm, passing global, sinkGroup, and true. // algorithm, passing global, sinkGroup, and true.
let require_trusted_types = csp_list.does_sink_type_require_trusted_types(sink_group, true); let require_trusted_types = global
.get_csp_list()
.does_sink_type_require_trusted_types(sink_group, true);
// Step 3: If requireTrustedTypes is false, return stringified input and abort these steps. // Step 3: If requireTrustedTypes is false, return stringified input and abort these steps.
if !require_trusted_types { if !require_trusted_types {
return Ok(input); return Ok(input);
@ -225,13 +220,13 @@ impl TrustedTypePolicyFactory {
// Step 6.1: Let disposition be the result of executing Should sink type mismatch violation // Step 6.1: Let disposition be the result of executing Should sink type mismatch violation
// be blocked by Content Security Policy? algorithm, passing global, // be blocked by Content Security Policy? algorithm, passing global,
// stringified input as source, sinkGroup and sink. // stringified input as source, sinkGroup and sink.
let (disposition, violations) = csp_list let is_blocked = global
.get_csp_list()
.should_sink_type_mismatch_violation_be_blocked_by_csp( .should_sink_type_mismatch_violation_be_blocked_by_csp(
sink, sink_group, &input, global, sink, sink_group, &input,
); );
global.report_csp_violations(violations, None);
// Step 6.2: If disposition is “Allowed”, return stringified input and abort further steps. // Step 6.2: If disposition is “Allowed”, return stringified input and abort further steps.
if disposition == CheckResult::Allowed { if !is_blocked {
Ok(input) Ok(input)
} else { } else {
// Step 6.3: Throw a TypeError and abort further steps. // Step 6.3: Throw a TypeError and abort further steps.

View file

@ -7,7 +7,6 @@ use std::cell::Cell;
use std::ptr; use std::ptr;
use constellation_traits::BlobImpl; use constellation_traits::BlobImpl;
use content_security_policy::Violation;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use ipc_channel::router::ROUTER; use ipc_channel::router::ROUTER;
@ -38,6 +37,7 @@ use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::{DOMString, USVString, is_token}; use crate::dom::bindings::str::{DOMString, USVString, is_token};
use crate::dom::blob::Blob; use crate::dom::blob::Blob;
use crate::dom::closeevent::CloseEvent; use crate::dom::closeevent::CloseEvent;
use crate::dom::csp::{GlobalCspReporting, Violation};
use crate::dom::event::{Event, EventBubbles, EventCancelable}; use crate::dom::event::{Event, EventBubbles, EventCancelable};
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;

View file

@ -11,7 +11,6 @@ use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use constellation_traits::BlobImpl; use constellation_traits::BlobImpl;
use content_security_policy as csp;
use data_url::mime::Mime; use data_url::mime::Mime;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use encoding_rs::{Encoding, UTF_8}; use encoding_rs::{Encoding, UTF_8};
@ -56,6 +55,7 @@ use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object_with_proto};
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
use crate::dom::bindings::str::{ByteString, DOMString, USVString, is_token}; use crate::dom::bindings::str::{ByteString, DOMString, USVString, is_token};
use crate::dom::blob::{Blob, normalize_type_string}; use crate::dom::blob::{Blob, normalize_type_string};
use crate::dom::csp::{GlobalCspReporting, Violation};
use crate::dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument}; use crate::dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument};
use crate::dom::event::{Event, EventBubbles, EventCancelable}; use crate::dom::event::{Event, EventBubbles, EventCancelable};
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
@ -147,7 +147,7 @@ impl FetchResponseListener for XHRContext {
network_listener::submit_timing(self, CanGc::note()) network_listener::submit_timing(self, CanGc::note())
} }
fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<Violation>) {
let global = &self.resource_timing_global(); let global = &self.resource_timing_global();
global.report_csp_violations(violations, None); global.report_csp_violations(violations, None);
} }

View file

@ -6,7 +6,6 @@ use std::rc::Rc;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use base::id::WebViewId; use base::id::WebViewId;
use content_security_policy as csp;
use ipc_channel::ipc; use ipc_channel::ipc;
use net_traits::policy_container::{PolicyContainer, RequestPolicyContainer}; use net_traits::policy_container::{PolicyContainer, RequestPolicyContainer};
use net_traits::request::{ use net_traits::request::{
@ -31,6 +30,7 @@ use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
use crate::dom::bindings::reflector::DomGlobal; use crate::dom::bindings::reflector::DomGlobal;
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::trace::RootedTraceableBox; use crate::dom::bindings::trace::RootedTraceableBox;
use crate::dom::csp::{GlobalCspReporting, Violation};
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::headers::Guard; use crate::dom::headers::Guard;
use crate::dom::performanceresourcetiming::InitiatorType; use crate::dom::performanceresourcetiming::InitiatorType;
@ -311,7 +311,7 @@ impl FetchResponseListener for FetchContext {
} }
} }
fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<Violation>) {
let global = &self.resource_timing_global(); let global = &self.resource_timing_global();
global.report_csp_violations(violations, None); global.report_csp_violations(violations, None);
} }

View file

@ -8,7 +8,6 @@
use std::sync::Arc; use std::sync::Arc;
use content_security_policy as csp;
use net_traits::image_cache::{ImageCache, PendingImageId}; use net_traits::image_cache::{ImageCache, PendingImageId};
use net_traits::request::{Destination, RequestBuilder as FetchRequestInit, RequestId}; use net_traits::request::{Destination, RequestBuilder as FetchRequestInit, RequestId};
use net_traits::{ use net_traits::{
@ -20,6 +19,7 @@ use servo_url::ServoUrl;
use crate::dom::bindings::refcounted::Trusted; use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::DomGlobal; use crate::dom::bindings::reflector::DomGlobal;
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::DomRoot;
use crate::dom::csp::{GlobalCspReporting, Violation};
use crate::dom::document::Document; use crate::dom::document::Document;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::node::{Node, NodeTraits}; use crate::dom::node::{Node, NodeTraits};
@ -79,7 +79,7 @@ impl FetchResponseListener for LayoutImageContext {
network_listener::submit_timing(self, CanGc::note()) network_listener::submit_timing(self, CanGc::note())
} }
fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<Violation>) {
let global = &self.resource_timing_global(); let global = &self.resource_timing_global();
global.report_csp_violations(violations, None); global.report_csp_violations(violations, None);
} }

View file

@ -11,7 +11,6 @@ use std::str::FromStr;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::{mem, ptr}; use std::{mem, ptr};
use content_security_policy as csp;
use encoding_rs::UTF_8; use encoding_rs::UTF_8;
use headers::{HeaderMapExt, ReferrerPolicy as ReferrerPolicyHeader}; use headers::{HeaderMapExt, ReferrerPolicy as ReferrerPolicyHeader};
use html5ever::local_name; use html5ever::local_name;
@ -61,6 +60,7 @@ use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::settings_stack::AutoIncumbentScript; use crate::dom::bindings::settings_stack::AutoIncumbentScript;
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::bindings::trace::RootedTraceableBox; use crate::dom::bindings::trace::RootedTraceableBox;
use crate::dom::csp::{GlobalCspReporting, Violation};
use crate::dom::document::Document; use crate::dom::document::Document;
use crate::dom::dynamicmoduleowner::{DynamicModuleId, DynamicModuleOwner}; use crate::dom::dynamicmoduleowner::{DynamicModuleId, DynamicModuleOwner};
use crate::dom::element::Element; use crate::dom::element::Element;
@ -1367,7 +1367,7 @@ impl FetchResponseListener for ModuleContext {
network_listener::submit_timing(self, CanGc::note()) network_listener::submit_timing(self, CanGc::note())
} }
fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<Violation>) {
let global = &self.resource_timing_global(); let global = &self.resource_timing_global();
global.report_csp_violations(violations, None); global.report_csp_violations(violations, None);
} }

View file

@ -19,7 +19,6 @@ use std::time::{Duration, Instant};
use std::{os, ptr, thread}; use std::{os, ptr, thread};
use background_hang_monitor_api::ScriptHangAnnotation; use background_hang_monitor_api::ScriptHangAnnotation;
use content_security_policy::CheckResult;
use js::conversions::jsstr_to_string; use js::conversions::jsstr_to_string;
use js::glue::{ use js::glue::{
CollectServoSizes, CreateJobQueue, DeleteJobQueue, DispatchableRun, JobQueueTraps, CollectServoSizes, CreateJobQueue, DeleteJobQueue, DispatchableRun, JobQueueTraps,
@ -72,6 +71,7 @@ use crate::dom::bindings::reflector::{DomGlobal, DomObject};
use crate::dom::bindings::root::trace_roots; use crate::dom::bindings::root::trace_roots;
use crate::dom::bindings::utils::DOM_CALLBACKS; use crate::dom::bindings::utils::DOM_CALLBACKS;
use crate::dom::bindings::{principals, settings_stack}; use crate::dom::bindings::{principals, settings_stack};
use crate::dom::csp::CspReporting;
use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus}; use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
@ -380,25 +380,20 @@ unsafe extern "C" fn content_security_policy_allows(
wrap_panic(&mut || { wrap_panic(&mut || {
// SpiderMonkey provides null pointer when executing webassembly. // SpiderMonkey provides null pointer when executing webassembly.
let in_realm_proof = AlreadyInRealm::assert_for_cx(cx); let in_realm_proof = AlreadyInRealm::assert_for_cx(cx);
let global = GlobalScope::from_context(*cx, InRealm::Already(&in_realm_proof)); let global = &GlobalScope::from_context(*cx, InRealm::Already(&in_realm_proof));
let Some(csp_list) = global.get_csp_list() else {
allowed = true;
return;
};
let (is_evaluation_allowed, violations) = match runtime_code { allowed = match runtime_code {
RuntimeCode::JS => { RuntimeCode::JS => {
let source = match sample { let source = match sample {
sample if !sample.is_null() => &jsstr_to_string(*cx, *sample), sample if !sample.is_null() => &jsstr_to_string(*cx, *sample),
_ => "", _ => "",
}; };
csp_list.is_js_evaluation_allowed(source) global
.get_csp_list()
.is_js_evaluation_allowed(global, source)
}, },
RuntimeCode::WASM => csp_list.is_wasm_evaluation_allowed(), RuntimeCode::WASM => global.get_csp_list().is_wasm_evaluation_allowed(global),
}; };
global.report_csp_violations(violations, None);
allowed = is_evaluation_allowed == CheckResult::Allowed;
}); });
allowed allowed
} }

View file

@ -41,7 +41,6 @@ use constellation_traits::{
JsEvalResult, LoadData, LoadOrigin, NavigationHistoryBehavior, ScriptToConstellationChan, JsEvalResult, LoadData, LoadOrigin, NavigationHistoryBehavior, ScriptToConstellationChan,
ScriptToConstellationMessage, StructuredSerializedData, WindowSizeType, ScriptToConstellationMessage, StructuredSerializedData, WindowSizeType,
}; };
use content_security_policy::{self as csp};
use crossbeam_channel::unbounded; use crossbeam_channel::unbounded;
use data_url::mime::Mime; use data_url::mime::Mime;
use devtools_traits::{ use devtools_traits::{
@ -119,6 +118,7 @@ use crate::dom::bindings::root::{
use crate::dom::bindings::settings_stack::AutoEntryScript; use crate::dom::bindings::settings_stack::AutoEntryScript;
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::bindings::trace::{HashMapTracedValues, JSTraceable}; use crate::dom::bindings::trace::{HashMapTracedValues, JSTraceable};
use crate::dom::csp::{CspReporting, GlobalCspReporting, Violation};
use crate::dom::customelementregistry::{ use crate::dom::customelementregistry::{
CallbackReaction, CustomElementDefinition, CustomElementReactionStack, CallbackReaction, CustomElementDefinition, CustomElementReactionStack,
}; };
@ -622,9 +622,10 @@ impl ScriptThread {
let task = task!(navigate_javascript: move || { let task = task!(navigate_javascript: move || {
// Important re security. See https://github.com/servo/servo/issues/23373 // Important re security. See https://github.com/servo/servo/issues/23373
if let Some(window) = trusted_global.root().downcast::<Window>() { if let Some(window) = trusted_global.root().downcast::<Window>() {
let global = &trusted_global.root();
// Step 5: If the result of should navigation request of type be blocked by // Step 5: If the result of should navigation request of type be blocked by
// Content Security Policy? given request and cspNavigationType is "Blocked", then return. [CSP] // Content Security Policy? given request and cspNavigationType is "Blocked", then return. [CSP]
if trusted_global.root().should_navigation_request_be_blocked(&load_data, None) { if global.get_csp_list().should_navigation_request_be_blocked(global, &load_data, None) {
return; return;
} }
if ScriptThread::check_load_origin(&load_data.load_origin, &window.get_url().origin()) { if ScriptThread::check_load_origin(&load_data.load_origin, &window.get_url().origin()) {
@ -3845,7 +3846,7 @@ impl ScriptThread {
} }
} }
fn handle_csp_violations(&self, id: PipelineId, _: RequestId, violations: Vec<csp::Violation>) { fn handle_csp_violations(&self, id: PipelineId, _: RequestId, violations: Vec<Violation>) {
if let Some(global) = self.documents.borrow().find_global(id) { if let Some(global) = self.documents.borrow().find_global(id) {
// TODO(https://github.com/w3c/webappsec-csp/issues/687): Update after spec is resolved // TODO(https://github.com/w3c/webappsec-csp/issues/687): Update after spec is resolved
global.report_csp_violations(violations, None); global.report_csp_violations(violations, None);

View file

@ -7,7 +7,7 @@ use std::sync::{Arc, Mutex};
use content_security_policy as csp; use content_security_policy as csp;
use headers::{ContentType, HeaderMap, HeaderMapExt}; use headers::{ContentType, HeaderMap, HeaderMapExt};
use net_traits::request::{ use net_traits::request::{
CredentialsMode, RequestBody, RequestId, create_request_body_with_content, CredentialsMode, Destination, RequestBody, RequestId, create_request_body_with_content,
}; };
use net_traits::{ use net_traits::{
FetchMetadata, FetchResponseListener, NetworkError, ResourceFetchTiming, ResourceTimingType, FetchMetadata, FetchResponseListener, NetworkError, ResourceFetchTiming, ResourceTimingType,
@ -19,6 +19,7 @@ use crate::conversions::Convert;
use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::refcounted::Trusted; use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::DomRoot;
use crate::dom::csp::{GlobalCspReporting, Violation};
use crate::dom::csppolicyviolationreport::{ use crate::dom::csppolicyviolationreport::{
CSPReportUriViolationReport, SecurityPolicyViolationReport, CSPReportUriViolationReport, SecurityPolicyViolationReport,
}; };
@ -110,7 +111,7 @@ impl CSPViolationReportTask {
let request = create_a_potential_cors_request( let request = create_a_potential_cors_request(
None, None,
endpoint.clone(), endpoint.clone(),
csp::Destination::Report, Destination::Report,
None, None,
None, None,
global.get_referrer(), global.get_referrer(),
@ -204,7 +205,7 @@ impl FetchResponseListener for CSPReportUriFetchListener {
submit_timing(self, CanGc::note()) submit_timing(self, CanGc::note())
} }
fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<Violation>) {
let global = &self.resource_timing_global(); let global = &self.resource_timing_global();
global.report_csp_violations(violations, None); global.report_csp_violations(violations, None);
} }

View file

@ -5,7 +5,6 @@
use std::io::{Read, Seek, Write}; use std::io::{Read, Seek, Write};
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use content_security_policy as csp;
use cssparser::SourceLocation; use cssparser::SourceLocation;
use encoding_rs::UTF_8; use encoding_rs::UTF_8;
use mime::{self, Mime}; use mime::{self, Mime};
@ -32,6 +31,7 @@ use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::refcounted::Trusted; use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::DomGlobal; use crate::dom::bindings::reflector::DomGlobal;
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::DomRoot;
use crate::dom::csp::{GlobalCspReporting, Violation};
use crate::dom::document::Document; use crate::dom::document::Document;
use crate::dom::element::Element; use crate::dom::element::Element;
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
@ -296,7 +296,7 @@ impl FetchResponseListener for StylesheetContext {
network_listener::submit_timing(self, CanGc::note()) network_listener::submit_timing(self, CanGc::note())
} }
fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<Violation>) {
let global = &self.resource_timing_global(); let global = &self.resource_timing_global();
global.report_csp_violations(violations, None); global.report_csp_violations(violations, None);
} }

View file

@ -26,6 +26,7 @@ use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::{DomGlobal, DomObject}; use crate::dom::bindings::reflector::{DomGlobal, DomObject};
use crate::dom::bindings::root::Dom; use crate::dom::bindings::root::Dom;
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::csp::CspReporting;
use crate::dom::document::{ImageAnimationUpdateCallback, RefreshRedirectDue}; use crate::dom::document::{ImageAnimationUpdateCallback, RefreshRedirectDue};
use crate::dom::eventsource::EventSourceTimeoutCallback; use crate::dom::eventsource::EventSourceTimeoutCallback;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
@ -426,7 +427,10 @@ impl JsTimers {
) -> i32 { ) -> i32 {
let callback = match callback { let callback = match callback {
TimerCallback::StringTimerCallback(code_str) => { TimerCallback::StringTimerCallback(code_str) => {
if global.is_js_evaluation_allowed(code_str.as_ref()) { if global
.get_csp_list()
.is_js_evaluation_allowed(global, code_str.as_ref())
{
InternalTimerCallback::StringTimerCallback(code_str) InternalTimerCallback::StringTimerCallback(code_str)
} else { } else {
return 0; return 0;