mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
enhance: Add support for unsafe-eval
and wasm-unsafe-eval
(#32893)
Signed-off-by: Chocolate Pie <106949016+chocolate-pie@users.noreply.github.com>
This commit is contained in:
parent
2cf207ddc8
commit
92866ab911
51 changed files with 755 additions and 73 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -976,9 +976,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "content-security-policy"
|
name = "content-security-policy"
|
||||||
version = "0.5.1"
|
version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "754c060c4a3342c5824d14caeba6c588716e9327f50558532685ef56718e0461"
|
checksum = "bf7225464dae1993d0045c023d0975f44d63337f35f85faddb998ff9abdfcd0f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
|
|
|
@ -474,6 +474,8 @@ pub struct Document {
|
||||||
fonts: MutNullableDom<FontFaceSet>,
|
fonts: MutNullableDom<FontFaceSet>,
|
||||||
/// <https://html.spec.whatwg.org/multipage/#visibility-state>
|
/// <https://html.spec.whatwg.org/multipage/#visibility-state>
|
||||||
visibility_state: Cell<DocumentVisibilityState>,
|
visibility_state: Cell<DocumentVisibilityState>,
|
||||||
|
/// <https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml>
|
||||||
|
status_code: Option<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(JSTraceable, MallocSizeOf)]
|
#[derive(JSTraceable, MallocSizeOf)]
|
||||||
|
@ -3001,6 +3003,10 @@ impl Document {
|
||||||
};
|
};
|
||||||
global_scope.report_an_error(error_info, HandleValue::null());
|
global_scope.report_an_error(error_info, HandleValue::null());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn status_code(&self) -> Option<u16> {
|
||||||
|
self.status_code
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_character_value_key(key: &Key) -> bool {
|
fn is_character_value_key(key: &Key) -> bool {
|
||||||
|
@ -3156,6 +3162,7 @@ impl Document {
|
||||||
doc_loader: DocumentLoader,
|
doc_loader: DocumentLoader,
|
||||||
referrer: Option<String>,
|
referrer: Option<String>,
|
||||||
referrer_policy: Option<ReferrerPolicy>,
|
referrer_policy: Option<ReferrerPolicy>,
|
||||||
|
status_code: Option<u16>,
|
||||||
canceller: FetchCanceller,
|
canceller: FetchCanceller,
|
||||||
) -> Document {
|
) -> Document {
|
||||||
let url = url.unwrap_or_else(|| ServoUrl::parse("about:blank").unwrap());
|
let url = url.unwrap_or_else(|| ServoUrl::parse("about:blank").unwrap());
|
||||||
|
@ -3306,6 +3313,7 @@ impl Document {
|
||||||
resize_observers: Default::default(),
|
resize_observers: Default::default(),
|
||||||
fonts: Default::default(),
|
fonts: Default::default(),
|
||||||
visibility_state: Cell::new(DocumentVisibilityState::Hidden),
|
visibility_state: Cell::new(DocumentVisibilityState::Hidden),
|
||||||
|
status_code,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3443,6 +3451,7 @@ impl Document {
|
||||||
docloader,
|
docloader,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -3461,6 +3470,7 @@ impl Document {
|
||||||
doc_loader: DocumentLoader,
|
doc_loader: DocumentLoader,
|
||||||
referrer: Option<String>,
|
referrer: Option<String>,
|
||||||
referrer_policy: Option<ReferrerPolicy>,
|
referrer_policy: Option<ReferrerPolicy>,
|
||||||
|
status_code: Option<u16>,
|
||||||
canceller: FetchCanceller,
|
canceller: FetchCanceller,
|
||||||
) -> DomRoot<Document> {
|
) -> DomRoot<Document> {
|
||||||
Self::new_with_proto(
|
Self::new_with_proto(
|
||||||
|
@ -3477,6 +3487,7 @@ impl Document {
|
||||||
doc_loader,
|
doc_loader,
|
||||||
referrer,
|
referrer,
|
||||||
referrer_policy,
|
referrer_policy,
|
||||||
|
status_code,
|
||||||
canceller,
|
canceller,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -3496,6 +3507,7 @@ impl Document {
|
||||||
doc_loader: DocumentLoader,
|
doc_loader: DocumentLoader,
|
||||||
referrer: Option<String>,
|
referrer: Option<String>,
|
||||||
referrer_policy: Option<ReferrerPolicy>,
|
referrer_policy: Option<ReferrerPolicy>,
|
||||||
|
status_code: Option<u16>,
|
||||||
canceller: FetchCanceller,
|
canceller: FetchCanceller,
|
||||||
) -> DomRoot<Document> {
|
) -> DomRoot<Document> {
|
||||||
let document = reflect_dom_object_with_proto(
|
let document = reflect_dom_object_with_proto(
|
||||||
|
@ -3512,6 +3524,7 @@ impl Document {
|
||||||
doc_loader,
|
doc_loader,
|
||||||
referrer,
|
referrer,
|
||||||
referrer_policy,
|
referrer_policy,
|
||||||
|
status_code,
|
||||||
canceller,
|
canceller,
|
||||||
)),
|
)),
|
||||||
window,
|
window,
|
||||||
|
@ -3634,6 +3647,7 @@ impl Document {
|
||||||
DocumentLoader::new(&self.loader()),
|
DocumentLoader::new(&self.loader()),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
);
|
);
|
||||||
new_doc
|
new_doc
|
||||||
|
|
|
@ -155,6 +155,7 @@ impl DOMImplementationMethods for DOMImplementation {
|
||||||
loader,
|
loader,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,7 @@ impl DOMParserMethods for DOMParser {
|
||||||
loader,
|
loader,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
);
|
);
|
||||||
ServoParser::parse_html_document(&document, Some(s), url);
|
ServoParser::parse_html_document(&document, Some(s), url);
|
||||||
|
@ -98,6 +99,7 @@ impl DOMParserMethods for DOMParser {
|
||||||
loader,
|
loader,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
);
|
);
|
||||||
ServoParser::parse_xml_document(&document, Some(s), url);
|
ServoParser::parse_xml_document(&document, Some(s), url);
|
||||||
|
|
|
@ -18,7 +18,7 @@ use base::id::{
|
||||||
BlobId, BroadcastChannelRouterId, MessagePortId, MessagePortRouterId, PipelineId,
|
BlobId, BroadcastChannelRouterId, MessagePortId, MessagePortRouterId, PipelineId,
|
||||||
ServiceWorkerId, ServiceWorkerRegistrationId,
|
ServiceWorkerId, ServiceWorkerRegistrationId,
|
||||||
};
|
};
|
||||||
use content_security_policy::CspList;
|
use content_security_policy::{CheckResult, CspList, PolicyDisposition};
|
||||||
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;
|
||||||
|
@ -28,14 +28,15 @@ use ipc_channel::router::ROUTER;
|
||||||
use js::glue::{IsWrapper, UnwrapObjectDynamic};
|
use js::glue::{IsWrapper, UnwrapObjectDynamic};
|
||||||
use js::jsapi::{
|
use js::jsapi::{
|
||||||
Compile1, CurrentGlobalOrNull, GetNonCCWObjectGlobal, HandleObject, Heap,
|
Compile1, CurrentGlobalOrNull, GetNonCCWObjectGlobal, HandleObject, Heap,
|
||||||
InstantiateGlobalStencil, InstantiateOptions, JSContext, JSObject, JSScript, SetScriptPrivate,
|
InstantiateGlobalStencil, InstantiateOptions, JSContext, JSObject, JSScript, RuntimeCode,
|
||||||
|
SetScriptPrivate,
|
||||||
};
|
};
|
||||||
use js::jsval::{JSVal, PrivateValue, UndefinedValue};
|
use js::jsval::{JSVal, PrivateValue, UndefinedValue};
|
||||||
use js::panic::maybe_resume_unwind;
|
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::{
|
||||||
get_object_class, transform_str_to_source_text, CompileOptionsWrapper, HandleValue,
|
describe_scripted_caller, get_object_class, transform_str_to_source_text,
|
||||||
MutableHandleValue, ParentRuntime, Runtime,
|
CompileOptionsWrapper, HandleValue, MutableHandleValue, ParentRuntime, Runtime,
|
||||||
};
|
};
|
||||||
use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
|
use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
|
||||||
use net_traits::blob_url_store::{get_blob_origin, BlobBuf};
|
use net_traits::blob_url_store::{get_blob_origin, BlobBuf};
|
||||||
|
@ -119,6 +120,7 @@ use crate::script_runtime::{
|
||||||
CommonScriptMsg, ContextForRequestInterrupt, JSContext as SafeJSContext, ScriptChan, ScriptPort,
|
CommonScriptMsg, ContextForRequestInterrupt, JSContext as SafeJSContext, ScriptChan, ScriptPort,
|
||||||
};
|
};
|
||||||
use crate::script_thread::{MainThreadScriptChan, ScriptThread};
|
use crate::script_thread::{MainThreadScriptChan, ScriptThread};
|
||||||
|
use crate::security_manager::CSPViolationReporter;
|
||||||
use crate::task::TaskCanceller;
|
use crate::task::TaskCanceller;
|
||||||
use crate::task_source::dom_manipulation::DOMManipulationTaskSource;
|
use crate::task_source::dom_manipulation::DOMManipulationTaskSource;
|
||||||
use crate::task_source::file_reading::FileReadingTaskSource;
|
use crate::task_source::file_reading::FileReadingTaskSource;
|
||||||
|
@ -2773,6 +2775,37 @@ impl GlobalScope {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
pub fn is_js_evaluation_allowed(&self, cx: SafeJSContext) -> bool {
|
||||||
|
let Some(csp_list) = self.get_csp_list() else {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
let scripted_caller = unsafe { describe_scripted_caller(*cx) }.unwrap_or_default();
|
||||||
|
let is_js_evaluation_allowed = csp_list.is_js_evaluation_allowed() == CheckResult::Allowed;
|
||||||
|
|
||||||
|
if !is_js_evaluation_allowed {
|
||||||
|
// FIXME: Don't fire event if `script-src` and `default-src`
|
||||||
|
// were not passed.
|
||||||
|
for policy in csp_list.0 {
|
||||||
|
let task = CSPViolationReporter::new(
|
||||||
|
self,
|
||||||
|
None,
|
||||||
|
policy.disposition == PolicyDisposition::Report,
|
||||||
|
RuntimeCode::JS,
|
||||||
|
scripted_caller.filename.clone(),
|
||||||
|
scripted_caller.line,
|
||||||
|
scripted_caller.col,
|
||||||
|
);
|
||||||
|
self.dom_manipulation_task_source()
|
||||||
|
.queue(task, self)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is_js_evaluation_allowed
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_image_bitmap(
|
pub fn create_image_bitmap(
|
||||||
&self,
|
&self,
|
||||||
image: ImageBitmapSource,
|
image: ImageBitmapSource,
|
||||||
|
@ -3090,6 +3123,13 @@ impl GlobalScope {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn status_code(&self) -> Option<u16> {
|
||||||
|
if let Some(window) = self.downcast::<Window>() {
|
||||||
|
return window.Document().status_code();
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
pub fn wgpu_id_hub(&self) -> Arc<Identities> {
|
pub fn wgpu_id_hub(&self) -> Arc<Identities> {
|
||||||
self.gpu_id_hub.clone()
|
self.gpu_id_hub.clone()
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* 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 content_security_policy::{CspList, PolicyDisposition, PolicySource};
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use html5ever::{local_name, namespace_url, ns, LocalName, Prefix};
|
use html5ever::{local_name, namespace_url, ns, LocalName, Prefix};
|
||||||
use js::rust::HandleObject;
|
use js::rust::HandleObject;
|
||||||
|
@ -80,6 +81,48 @@ impl HTMLHeadElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#attr-meta-http-equiv-content-security-policy>
|
||||||
|
pub fn set_content_security_policy(&self) {
|
||||||
|
let doc = document_from_node(self);
|
||||||
|
|
||||||
|
if doc.GetHead().as_deref() != Some(self) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut csp_list: Option<CspList> = None;
|
||||||
|
let node = self.upcast::<Node>();
|
||||||
|
let candinates = node
|
||||||
|
.traverse_preorder(ShadowIncluding::No)
|
||||||
|
.filter_map(DomRoot::downcast::<Element>)
|
||||||
|
.filter(|elem| elem.is::<HTMLMetaElement>())
|
||||||
|
.filter(|elem| {
|
||||||
|
elem.get_string_attribute(&local_name!("http-equiv"))
|
||||||
|
.to_ascii_lowercase() ==
|
||||||
|
"content-security-policy".to_owned()
|
||||||
|
})
|
||||||
|
.filter(|elem| {
|
||||||
|
elem.get_attribute(&ns!(), &local_name!("content"))
|
||||||
|
.is_some()
|
||||||
|
});
|
||||||
|
|
||||||
|
for meta in candinates {
|
||||||
|
if let Some(ref content) = meta.get_attribute(&ns!(), &local_name!("content")) {
|
||||||
|
let content = content.value();
|
||||||
|
let content_val = content.trim();
|
||||||
|
if !content_val.is_empty() {
|
||||||
|
let policies =
|
||||||
|
CspList::parse(content_val, PolicySource::Meta, PolicyDisposition::Enforce);
|
||||||
|
match csp_list {
|
||||||
|
Some(ref mut csp_list) => csp_list.append(policies),
|
||||||
|
None => csp_list = Some(policies),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
doc.set_csp_list(csp_list);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtualMethods for HTMLHeadElement {
|
impl VirtualMethods for HTMLHeadElement {
|
||||||
|
|
|
@ -88,8 +88,10 @@ impl HTMLMetaElement {
|
||||||
// https://html.spec.whatwg.org/multipage/#attr-meta-http-equiv
|
// https://html.spec.whatwg.org/multipage/#attr-meta-http-equiv
|
||||||
} else if !self.HttpEquiv().is_empty() {
|
} else if !self.HttpEquiv().is_empty() {
|
||||||
// TODO: Implement additional http-equiv candidates
|
// TODO: Implement additional http-equiv candidates
|
||||||
if self.HttpEquiv().to_ascii_lowercase().as_str() == "refresh" {
|
match self.HttpEquiv().to_ascii_lowercase().as_str() {
|
||||||
self.declarative_refresh();
|
"refresh" => self.declarative_refresh(),
|
||||||
|
"content-security-policy" => self.apply_csp_list(),
|
||||||
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,6 +117,15 @@ impl HTMLMetaElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#attr-meta-http-equiv-content-security-policy>
|
||||||
|
fn apply_csp_list(&self) {
|
||||||
|
if let Some(parent) = self.upcast::<Node>().GetParentElement() {
|
||||||
|
if let Some(head) = parent.downcast::<HTMLHeadElement>() {
|
||||||
|
head.set_content_security_policy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <https://html.spec.whatwg.org/multipage/#shared-declarative-refresh-steps>
|
/// <https://html.spec.whatwg.org/multipage/#shared-declarative-refresh-steps>
|
||||||
fn declarative_refresh(&self) {
|
fn declarative_refresh(&self) {
|
||||||
// 2
|
// 2
|
||||||
|
|
|
@ -471,6 +471,7 @@ macro_rules! global_event_handlers(
|
||||||
event_handler!(progress, GetOnprogress, SetOnprogress);
|
event_handler!(progress, GetOnprogress, SetOnprogress);
|
||||||
event_handler!(ratechange, GetOnratechange, SetOnratechange);
|
event_handler!(ratechange, GetOnratechange, SetOnratechange);
|
||||||
event_handler!(reset, GetOnreset, SetOnreset);
|
event_handler!(reset, GetOnreset, SetOnreset);
|
||||||
|
event_handler!(securitypolicyviolation, GetOnsecuritypolicyviolation, SetOnsecuritypolicyviolation);
|
||||||
event_handler!(seeked, GetOnseeked, SetOnseeked);
|
event_handler!(seeked, GetOnseeked, SetOnseeked);
|
||||||
event_handler!(seeking, GetOnseeking, SetOnseeking);
|
event_handler!(seeking, GetOnseeking, SetOnseeking);
|
||||||
event_handler!(select, GetOnselect, SetOnselect);
|
event_handler!(select, GetOnselect, SetOnselect);
|
||||||
|
|
|
@ -525,6 +525,7 @@ pub(crate) mod rtcrtptransceiver;
|
||||||
pub mod rtcsessiondescription;
|
pub mod rtcsessiondescription;
|
||||||
pub mod rtctrackevent;
|
pub mod rtctrackevent;
|
||||||
pub mod screen;
|
pub mod screen;
|
||||||
|
pub mod securitypolicyviolationevent;
|
||||||
pub mod selection;
|
pub mod selection;
|
||||||
pub mod serviceworker;
|
pub mod serviceworker;
|
||||||
pub mod serviceworkercontainer;
|
pub mod serviceworkercontainer;
|
||||||
|
|
|
@ -2296,6 +2296,7 @@ impl Node {
|
||||||
loader,
|
loader,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
document.status_code(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
);
|
);
|
||||||
DomRoot::upcast::<Node>(document)
|
DomRoot::upcast::<Node>(document)
|
||||||
|
|
|
@ -720,8 +720,11 @@ impl From<RequestDestination> for NetTraitsRequestDestination {
|
||||||
RequestDestination::Document => NetTraitsRequestDestination::Document,
|
RequestDestination::Document => NetTraitsRequestDestination::Document,
|
||||||
RequestDestination::Embed => NetTraitsRequestDestination::Embed,
|
RequestDestination::Embed => NetTraitsRequestDestination::Embed,
|
||||||
RequestDestination::Font => NetTraitsRequestDestination::Font,
|
RequestDestination::Font => NetTraitsRequestDestination::Font,
|
||||||
|
RequestDestination::Frame => NetTraitsRequestDestination::Frame,
|
||||||
|
RequestDestination::Iframe => NetTraitsRequestDestination::IFrame,
|
||||||
RequestDestination::Image => NetTraitsRequestDestination::Image,
|
RequestDestination::Image => NetTraitsRequestDestination::Image,
|
||||||
RequestDestination::Manifest => NetTraitsRequestDestination::Manifest,
|
RequestDestination::Manifest => NetTraitsRequestDestination::Manifest,
|
||||||
|
RequestDestination::Json => NetTraitsRequestDestination::Json,
|
||||||
RequestDestination::Object => NetTraitsRequestDestination::Object,
|
RequestDestination::Object => NetTraitsRequestDestination::Object,
|
||||||
RequestDestination::Report => NetTraitsRequestDestination::Report,
|
RequestDestination::Report => NetTraitsRequestDestination::Report,
|
||||||
RequestDestination::Script => NetTraitsRequestDestination::Script,
|
RequestDestination::Script => NetTraitsRequestDestination::Script,
|
||||||
|
@ -743,8 +746,11 @@ impl From<NetTraitsRequestDestination> for RequestDestination {
|
||||||
NetTraitsRequestDestination::Document => RequestDestination::Document,
|
NetTraitsRequestDestination::Document => RequestDestination::Document,
|
||||||
NetTraitsRequestDestination::Embed => RequestDestination::Embed,
|
NetTraitsRequestDestination::Embed => RequestDestination::Embed,
|
||||||
NetTraitsRequestDestination::Font => RequestDestination::Font,
|
NetTraitsRequestDestination::Font => RequestDestination::Font,
|
||||||
|
NetTraitsRequestDestination::Frame => RequestDestination::Frame,
|
||||||
|
NetTraitsRequestDestination::IFrame => RequestDestination::Iframe,
|
||||||
NetTraitsRequestDestination::Image => RequestDestination::Image,
|
NetTraitsRequestDestination::Image => RequestDestination::Image,
|
||||||
NetTraitsRequestDestination::Manifest => RequestDestination::Manifest,
|
NetTraitsRequestDestination::Manifest => RequestDestination::Manifest,
|
||||||
|
NetTraitsRequestDestination::Json => RequestDestination::Json,
|
||||||
NetTraitsRequestDestination::Object => RequestDestination::Object,
|
NetTraitsRequestDestination::Object => RequestDestination::Object,
|
||||||
NetTraitsRequestDestination::Report => RequestDestination::Report,
|
NetTraitsRequestDestination::Report => RequestDestination::Report,
|
||||||
NetTraitsRequestDestination::Script => RequestDestination::Script,
|
NetTraitsRequestDestination::Script => RequestDestination::Script,
|
||||||
|
@ -759,6 +765,7 @@ impl From<NetTraitsRequestDestination> for RequestDestination {
|
||||||
NetTraitsRequestDestination::Video => RequestDestination::Video,
|
NetTraitsRequestDestination::Video => RequestDestination::Video,
|
||||||
NetTraitsRequestDestination::Worker => RequestDestination::Worker,
|
NetTraitsRequestDestination::Worker => RequestDestination::Worker,
|
||||||
NetTraitsRequestDestination::Xslt => RequestDestination::Xslt,
|
NetTraitsRequestDestination::Xslt => RequestDestination::Xslt,
|
||||||
|
NetTraitsRequestDestination::WebIdentity => RequestDestination::_empty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
180
components/script/dom/securitypolicyviolationevent.rs
Normal file
180
components/script/dom/securitypolicyviolationevent.rs
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
/* 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 dom_struct::dom_struct;
|
||||||
|
use js::rust::HandleObject;
|
||||||
|
use servo_atoms::Atom;
|
||||||
|
|
||||||
|
use super::bindings::reflector::reflect_dom_object_with_proto;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::EventBinding::Event_Binding::EventMethods;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::SecurityPolicyViolationEventBinding::{
|
||||||
|
SecurityPolicyViolationEventDisposition, SecurityPolicyViolationEventInit,
|
||||||
|
SecurityPolicyViolationEventMethods,
|
||||||
|
};
|
||||||
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
|
use crate::dom::bindings::root::DomRoot;
|
||||||
|
use crate::dom::bindings::str::{DOMString, USVString};
|
||||||
|
use crate::dom::event::{Event, EventBubbles, EventCancelable};
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
|
||||||
|
// https://w3c.github.io/webappsec-csp/#securitypolicyviolationevent
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct SecurityPolicyViolationEvent {
|
||||||
|
event: Event,
|
||||||
|
document_uri: USVString,
|
||||||
|
referrer: USVString,
|
||||||
|
blocked_uri: USVString,
|
||||||
|
effective_directive: DOMString,
|
||||||
|
violated_directive: DOMString,
|
||||||
|
original_policy: DOMString,
|
||||||
|
source_file: USVString,
|
||||||
|
sample: DOMString,
|
||||||
|
disposition: SecurityPolicyViolationEventDisposition,
|
||||||
|
status_code: u16,
|
||||||
|
line_number: u32,
|
||||||
|
column_number: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SecurityPolicyViolationEvent {
|
||||||
|
fn new_inherited(init: &SecurityPolicyViolationEventInit) -> SecurityPolicyViolationEvent {
|
||||||
|
SecurityPolicyViolationEvent {
|
||||||
|
event: Event::new_inherited(),
|
||||||
|
document_uri: init.documentURI.clone(),
|
||||||
|
referrer: init.referrer.clone(),
|
||||||
|
blocked_uri: init.blockedURI.clone(),
|
||||||
|
effective_directive: init.effectiveDirective.clone(),
|
||||||
|
violated_directive: init.violatedDirective.clone(),
|
||||||
|
original_policy: init.originalPolicy.clone(),
|
||||||
|
source_file: init.sourceFile.clone(),
|
||||||
|
sample: init.sample.clone(),
|
||||||
|
disposition: init.disposition.clone(),
|
||||||
|
status_code: init.statusCode,
|
||||||
|
line_number: init.lineNumber,
|
||||||
|
column_number: init.columnNumber,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_initialized(
|
||||||
|
global: &GlobalScope,
|
||||||
|
init: &SecurityPolicyViolationEventInit,
|
||||||
|
proto: Option<HandleObject>,
|
||||||
|
) -> DomRoot<SecurityPolicyViolationEvent> {
|
||||||
|
reflect_dom_object_with_proto(
|
||||||
|
Box::new(SecurityPolicyViolationEvent::new_inherited(init)),
|
||||||
|
global,
|
||||||
|
proto,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_with_proto(
|
||||||
|
global: &GlobalScope,
|
||||||
|
proto: Option<HandleObject>,
|
||||||
|
type_: Atom,
|
||||||
|
bubbles: EventBubbles,
|
||||||
|
cancelable: EventCancelable,
|
||||||
|
init: &SecurityPolicyViolationEventInit,
|
||||||
|
) -> DomRoot<Self> {
|
||||||
|
let ev = SecurityPolicyViolationEvent::new_initialized(global, init, proto);
|
||||||
|
{
|
||||||
|
let event = ev.upcast::<Event>();
|
||||||
|
event.init_event(type_, bool::from(bubbles), bool::from(cancelable));
|
||||||
|
}
|
||||||
|
ev
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(
|
||||||
|
global: &GlobalScope,
|
||||||
|
type_: Atom,
|
||||||
|
bubbles: EventBubbles,
|
||||||
|
cancelable: EventCancelable,
|
||||||
|
init: &SecurityPolicyViolationEventInit,
|
||||||
|
) -> DomRoot<Self> {
|
||||||
|
Self::new_with_proto(global, None, type_, bubbles, cancelable, init)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn Constructor(
|
||||||
|
global: &GlobalScope,
|
||||||
|
proto: Option<HandleObject>,
|
||||||
|
type_: DOMString,
|
||||||
|
init: &SecurityPolicyViolationEventInit,
|
||||||
|
) -> DomRoot<Self> {
|
||||||
|
SecurityPolicyViolationEvent::new_with_proto(
|
||||||
|
global,
|
||||||
|
proto,
|
||||||
|
Atom::from(type_),
|
||||||
|
EventBubbles::from(init.parent.bubbles),
|
||||||
|
EventCancelable::from(init.parent.cancelable),
|
||||||
|
init,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
impl SecurityPolicyViolationEventMethods for SecurityPolicyViolationEvent {
|
||||||
|
/// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-documenturi>
|
||||||
|
fn DocumentURI(&self) -> USVString {
|
||||||
|
self.document_uri.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-referrer>
|
||||||
|
fn Referrer(&self) -> USVString {
|
||||||
|
self.referrer.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-blockeduri>
|
||||||
|
fn BlockedURI(&self) -> USVString {
|
||||||
|
self.blocked_uri.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-effectivedirective>
|
||||||
|
fn EffectiveDirective(&self) -> DOMString {
|
||||||
|
self.effective_directive.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-violateddirective>
|
||||||
|
fn ViolatedDirective(&self) -> DOMString {
|
||||||
|
self.violated_directive.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-originalpolicy>
|
||||||
|
fn OriginalPolicy(&self) -> DOMString {
|
||||||
|
self.original_policy.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-sourcefile>
|
||||||
|
fn SourceFile(&self) -> USVString {
|
||||||
|
self.source_file.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-sample>
|
||||||
|
fn Sample(&self) -> DOMString {
|
||||||
|
self.sample.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-disposition>
|
||||||
|
fn Disposition(&self) -> SecurityPolicyViolationEventDisposition {
|
||||||
|
self.disposition.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-statuscode>
|
||||||
|
fn StatusCode(&self) -> u16 {
|
||||||
|
self.status_code
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-linenumber>
|
||||||
|
fn LineNumber(&self) -> u32 {
|
||||||
|
self.line_number
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webappsec-csp/#dom-securitypolicyviolationevent-columnnumber>
|
||||||
|
fn ColumnNumber(&self) -> u32 {
|
||||||
|
self.column_number
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://dom.spec.whatwg.org/#dom-event-istrusted>
|
||||||
|
fn IsTrusted(&self) -> bool {
|
||||||
|
self.event.IsTrusted()
|
||||||
|
}
|
||||||
|
}
|
|
@ -214,6 +214,7 @@ impl ServoParser {
|
||||||
loader,
|
loader,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,7 @@ interface mixin GlobalEventHandlers {
|
||||||
attribute EventHandler onreset;
|
attribute EventHandler onreset;
|
||||||
attribute EventHandler onresize;
|
attribute EventHandler onresize;
|
||||||
attribute EventHandler onscroll;
|
attribute EventHandler onscroll;
|
||||||
|
attribute EventHandler onsecuritypolicyviolation;
|
||||||
attribute EventHandler onseeked;
|
attribute EventHandler onseeked;
|
||||||
attribute EventHandler onseeking;
|
attribute EventHandler onseeking;
|
||||||
attribute EventHandler onselect;
|
attribute EventHandler onselect;
|
||||||
|
|
|
@ -47,7 +47,10 @@ enum RequestDestination {
|
||||||
"document",
|
"document",
|
||||||
"embed",
|
"embed",
|
||||||
"font",
|
"font",
|
||||||
|
"frame",
|
||||||
|
"iframe",
|
||||||
"image",
|
"image",
|
||||||
|
"json",
|
||||||
"manifest",
|
"manifest",
|
||||||
"object",
|
"object",
|
||||||
"report",
|
"report",
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
// https://w3c.github.io/webappsec-csp/#securitypolicyviolationevent
|
||||||
|
|
||||||
|
enum SecurityPolicyViolationEventDisposition {
|
||||||
|
"enforce", "report"
|
||||||
|
};
|
||||||
|
|
||||||
|
[Exposed=(Window,Worker)]
|
||||||
|
interface SecurityPolicyViolationEvent : Event {
|
||||||
|
constructor(DOMString type, optional SecurityPolicyViolationEventInit eventInitDict = {});
|
||||||
|
readonly attribute USVString documentURI;
|
||||||
|
readonly attribute USVString referrer;
|
||||||
|
readonly attribute USVString blockedURI;
|
||||||
|
readonly attribute DOMString effectiveDirective;
|
||||||
|
readonly attribute DOMString violatedDirective; // historical alias of effectiveDirective
|
||||||
|
readonly attribute DOMString originalPolicy;
|
||||||
|
readonly attribute USVString sourceFile;
|
||||||
|
readonly attribute DOMString sample;
|
||||||
|
readonly attribute SecurityPolicyViolationEventDisposition disposition;
|
||||||
|
readonly attribute unsigned short statusCode;
|
||||||
|
readonly attribute unsigned long lineNumber;
|
||||||
|
readonly attribute unsigned long columnNumber;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary SecurityPolicyViolationEventInit : EventInit {
|
||||||
|
USVString documentURI = "";
|
||||||
|
USVString referrer = "";
|
||||||
|
USVString blockedURI = "";
|
||||||
|
DOMString violatedDirective = "";
|
||||||
|
DOMString effectiveDirective = "";
|
||||||
|
DOMString originalPolicy = "";
|
||||||
|
USVString sourceFile = "";
|
||||||
|
DOMString sample = "";
|
||||||
|
SecurityPolicyViolationEventDisposition disposition = "enforce";
|
||||||
|
unsigned short statusCode = 0;
|
||||||
|
unsigned long lineNumber = 0;
|
||||||
|
unsigned long columnNumber = 0;
|
||||||
|
};
|
|
@ -55,6 +55,7 @@ impl XMLDocument {
|
||||||
doc_loader,
|
doc_loader,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1527,6 +1527,7 @@ impl XMLHttpRequest {
|
||||||
docloader,
|
docloader,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,8 @@ pub mod script_runtime;
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub mod script_thread;
|
pub mod script_thread;
|
||||||
#[warn(deprecated)]
|
#[warn(deprecated)]
|
||||||
|
pub mod security_manager;
|
||||||
|
#[warn(deprecated)]
|
||||||
pub mod serviceworker_manager;
|
pub mod serviceworker_manager;
|
||||||
#[warn(deprecated)]
|
#[warn(deprecated)]
|
||||||
mod stylesheet_loader;
|
mod stylesheet_loader;
|
||||||
|
|
|
@ -19,6 +19,8 @@ use std::time::{Duration, Instant};
|
||||||
use std::{fmt, os, ptr, thread};
|
use std::{fmt, os, ptr, thread};
|
||||||
|
|
||||||
use base::id::PipelineId;
|
use base::id::PipelineId;
|
||||||
|
use content_security_policy::{CheckResult, PolicyDisposition};
|
||||||
|
use js::conversions::jsstr_to_string;
|
||||||
use js::glue::{
|
use js::glue::{
|
||||||
CollectServoSizes, CreateJobQueue, DeleteJobQueue, DispatchableRun, JobQueueTraps,
|
CollectServoSizes, CreateJobQueue, DeleteJobQueue, DispatchableRun, JobQueueTraps,
|
||||||
RUST_js_GetErrorMessage, SetBuildId, StreamConsumerConsumeChunk,
|
RUST_js_GetErrorMessage, SetBuildId, StreamConsumerConsumeChunk,
|
||||||
|
@ -27,23 +29,23 @@ use js::glue::{
|
||||||
use js::jsapi::{
|
use js::jsapi::{
|
||||||
AsmJSOption, BuildIdCharVector, ContextOptionsRef, DisableIncrementalGC,
|
AsmJSOption, BuildIdCharVector, ContextOptionsRef, DisableIncrementalGC,
|
||||||
Dispatchable as JSRunnable, Dispatchable_MaybeShuttingDown, GCDescription, GCOptions,
|
Dispatchable as JSRunnable, Dispatchable_MaybeShuttingDown, GCDescription, GCOptions,
|
||||||
GCProgress, GCReason, GetPromiseUserInputEventHandlingState, HandleObject, Heap,
|
GCProgress, GCReason, GetPromiseUserInputEventHandlingState, HandleObject, HandleString, Heap,
|
||||||
InitConsumeStreamCallback, InitDispatchToEventLoop, JSContext as RawJSContext, JSGCParamKey,
|
InitConsumeStreamCallback, InitDispatchToEventLoop, JSContext as RawJSContext, JSGCParamKey,
|
||||||
JSGCStatus, JSJitCompilerOption, JSObject, JSSecurityCallbacks, JSTracer,
|
JSGCStatus, JSJitCompilerOption, JSObject, JSSecurityCallbacks, JSTracer,
|
||||||
JS_AddExtraGCRootsTracer, JS_InitDestroyPrincipalsCallback, JS_InitReadPrincipalsCallback,
|
JS_AddExtraGCRootsTracer, JS_InitDestroyPrincipalsCallback, JS_InitReadPrincipalsCallback,
|
||||||
JS_RequestInterruptCallback, JS_SetGCCallback, JS_SetGCParameter,
|
JS_RequestInterruptCallback, JS_SetGCCallback, JS_SetGCParameter,
|
||||||
JS_SetGlobalJitCompilerOption, JS_SetOffthreadIonCompilationEnabled,
|
JS_SetGlobalJitCompilerOption, JS_SetOffthreadIonCompilationEnabled,
|
||||||
JS_SetParallelParsingEnabled, JS_SetSecurityCallbacks, JobQueue, MimeType,
|
JS_SetParallelParsingEnabled, JS_SetSecurityCallbacks, JobQueue, MimeType,
|
||||||
PromiseRejectionHandlingState, PromiseUserInputEventHandlingState, SetDOMCallbacks,
|
PromiseRejectionHandlingState, PromiseUserInputEventHandlingState, RuntimeCode,
|
||||||
SetGCSliceCallback, SetJobQueue, SetPreserveWrapperCallbacks, SetProcessBuildIdOp,
|
SetDOMCallbacks, SetGCSliceCallback, SetJobQueue, SetPreserveWrapperCallbacks,
|
||||||
SetPromiseRejectionTrackerCallback, StreamConsumer as JSStreamConsumer,
|
SetProcessBuildIdOp, SetPromiseRejectionTrackerCallback, StreamConsumer as JSStreamConsumer,
|
||||||
};
|
};
|
||||||
use js::jsval::UndefinedValue;
|
use js::jsval::UndefinedValue;
|
||||||
use js::panic::wrap_panic;
|
use js::panic::wrap_panic;
|
||||||
use js::rust::wrappers::{GetPromiseIsHandled, JS_GetPromiseResult};
|
use js::rust::wrappers::{GetPromiseIsHandled, JS_GetPromiseResult};
|
||||||
use js::rust::{
|
use js::rust::{
|
||||||
Handle, HandleObject as RustHandleObject, IntoHandle, JSEngine, JSEngineHandle, ParentRuntime,
|
describe_scripted_caller, Handle, HandleObject as RustHandleObject, IntoHandle, JSEngine,
|
||||||
Runtime as RustRuntime,
|
JSEngineHandle, ParentRuntime, Runtime as RustRuntime,
|
||||||
};
|
};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use malloc_size_of::MallocSizeOfOps;
|
use malloc_size_of::MallocSizeOfOps;
|
||||||
|
@ -79,6 +81,7 @@ use crate::microtask::{EnqueuedPromiseCallback, Microtask, MicrotaskQueue};
|
||||||
use crate::realms::{AlreadyInRealm, InRealm};
|
use crate::realms::{AlreadyInRealm, InRealm};
|
||||||
use crate::script_module::EnsureModuleHooksInitialized;
|
use crate::script_module::EnsureModuleHooksInitialized;
|
||||||
use crate::script_thread::trace_thread;
|
use crate::script_thread::trace_thread;
|
||||||
|
use crate::security_manager::CSPViolationReporter;
|
||||||
use crate::task::TaskBox;
|
use crate::task::TaskBox;
|
||||||
use crate::task_source::networking::NetworkingTaskSource;
|
use crate::task_source::networking::NetworkingTaskSource;
|
||||||
use crate::task_source::{TaskSource, TaskSourceName};
|
use crate::task_source::{TaskSource, TaskSourceName};
|
||||||
|
@ -90,8 +93,7 @@ static JOB_QUEUE_TRAPS: JobQueueTraps = JobQueueTraps {
|
||||||
};
|
};
|
||||||
|
|
||||||
static SECURITY_CALLBACKS: JSSecurityCallbacks = JSSecurityCallbacks {
|
static SECURITY_CALLBACKS: JSSecurityCallbacks = JSSecurityCallbacks {
|
||||||
// TODO: Content Security Policy <https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP>
|
contentSecurityPolicyAllows: Some(content_security_policy_allows),
|
||||||
contentSecurityPolicyAllows: None,
|
|
||||||
subsumes: Some(principals::subsumes),
|
subsumes: Some(principals::subsumes),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -311,6 +313,61 @@ unsafe extern "C" fn promise_rejection_tracker(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe extern "C" fn content_security_policy_allows(
|
||||||
|
cx: *mut RawJSContext,
|
||||||
|
runtime_code: RuntimeCode,
|
||||||
|
sample: HandleString,
|
||||||
|
) -> bool {
|
||||||
|
let mut allowed = false;
|
||||||
|
let cx = JSContext::from_ptr(cx);
|
||||||
|
wrap_panic(&mut || {
|
||||||
|
// SpiderMonkey provides null pointer when executing webassembly.
|
||||||
|
let sample = match sample {
|
||||||
|
sample if !sample.is_null() => Some(jsstr_to_string(*cx, *sample)),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
let in_realm_proof = AlreadyInRealm::assert_for_cx(cx);
|
||||||
|
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_js_evaluation_allowed = csp_list.is_js_evaluation_allowed() == CheckResult::Allowed;
|
||||||
|
let is_wasm_evaluation_allowed =
|
||||||
|
csp_list.is_wasm_evaluation_allowed() == CheckResult::Allowed;
|
||||||
|
let scripted_caller = describe_scripted_caller(*cx).unwrap_or_default();
|
||||||
|
|
||||||
|
allowed = match runtime_code {
|
||||||
|
RuntimeCode::JS if is_js_evaluation_allowed => true,
|
||||||
|
RuntimeCode::WASM if is_wasm_evaluation_allowed => true,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if !allowed {
|
||||||
|
// FIXME: Don't fire event if `script-src` and `default-src`
|
||||||
|
// were not passed.
|
||||||
|
for policy in csp_list.0 {
|
||||||
|
let task = CSPViolationReporter::new(
|
||||||
|
&global,
|
||||||
|
sample.clone(),
|
||||||
|
policy.disposition == PolicyDisposition::Report,
|
||||||
|
runtime_code,
|
||||||
|
scripted_caller.filename.clone(),
|
||||||
|
scripted_caller.line,
|
||||||
|
scripted_caller.col,
|
||||||
|
);
|
||||||
|
global
|
||||||
|
.dom_manipulation_task_source()
|
||||||
|
.queue(task, &global)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
allowed
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code, crown::unrooted_must_root)]
|
#[allow(unsafe_code, crown::unrooted_must_root)]
|
||||||
/// <https://html.spec.whatwg.org/multipage/#notify-about-rejected-promises>
|
/// <https://html.spec.whatwg.org/multipage/#notify-about-rejected-promises>
|
||||||
pub fn notify_about_rejected_promises(global: &GlobalScope) {
|
pub fn notify_about_rejected_promises(global: &GlobalScope) {
|
||||||
|
|
|
@ -3672,6 +3672,8 @@ impl ScriptThread {
|
||||||
.and_then(|h| h.typed_get::<ReferrerPolicyHeader>())
|
.and_then(|h| h.typed_get::<ReferrerPolicyHeader>())
|
||||||
.map(ReferrerPolicy::from);
|
.map(ReferrerPolicy::from);
|
||||||
|
|
||||||
|
let status_code = metadata.status.map(|status| status.0).unwrap_or(200);
|
||||||
|
|
||||||
let document = Document::new(
|
let document = Document::new(
|
||||||
&window,
|
&window,
|
||||||
HasBrowsingContext::Yes,
|
HasBrowsingContext::Yes,
|
||||||
|
@ -3685,6 +3687,7 @@ impl ScriptThread {
|
||||||
loader,
|
loader,
|
||||||
referrer,
|
referrer,
|
||||||
referrer_policy,
|
referrer_policy,
|
||||||
|
Some(status_code),
|
||||||
incomplete.canceller,
|
incomplete.canceller,
|
||||||
);
|
);
|
||||||
document.set_ready_state(DocumentReadyState::Loading);
|
document.set_ready_state(DocumentReadyState::Loading);
|
||||||
|
|
177
components/script/security_manager.rs
Normal file
177
components/script/security_manager.rs
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
/* 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 js::jsapi::RuntimeCode;
|
||||||
|
use net_traits::request::Referrer;
|
||||||
|
use serde::Serialize;
|
||||||
|
use servo_atoms::Atom;
|
||||||
|
use servo_url::ServoUrl;
|
||||||
|
|
||||||
|
use crate::dom::bindings::codegen::Bindings::EventBinding::EventInit;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::SecurityPolicyViolationEventBinding::{
|
||||||
|
SecurityPolicyViolationEventDisposition, SecurityPolicyViolationEventInit,
|
||||||
|
};
|
||||||
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
|
use crate::dom::bindings::refcounted::Trusted;
|
||||||
|
use crate::dom::bindings::reflector::DomObject;
|
||||||
|
use crate::dom::event::{Event, EventBubbles, EventCancelable};
|
||||||
|
use crate::dom::eventtarget::EventTarget;
|
||||||
|
use crate::dom::securitypolicyviolationevent::SecurityPolicyViolationEvent;
|
||||||
|
use crate::dom::types::GlobalScope;
|
||||||
|
use crate::task::TaskOnce;
|
||||||
|
|
||||||
|
pub struct CSPViolationReporter {
|
||||||
|
sample: Option<String>,
|
||||||
|
filename: String,
|
||||||
|
report_only: bool,
|
||||||
|
runtime_code: RuntimeCode,
|
||||||
|
line_number: u32,
|
||||||
|
column_number: u32,
|
||||||
|
target: Trusted<EventTarget>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct SecurityPolicyViolationReport {
|
||||||
|
sample: Option<String>,
|
||||||
|
#[serde(rename = "blockedURL")]
|
||||||
|
blocked_url: String,
|
||||||
|
referrer: String,
|
||||||
|
status_code: u16,
|
||||||
|
#[serde(rename = "documentURL")]
|
||||||
|
document_url: String,
|
||||||
|
source_file: String,
|
||||||
|
violated_directive: String,
|
||||||
|
effective_directive: String,
|
||||||
|
line_number: u32,
|
||||||
|
column_number: u32,
|
||||||
|
original_policy: String,
|
||||||
|
disposition: SecurityPolicyViolationEventDisposition,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CSPViolationReporter {
|
||||||
|
pub fn new(
|
||||||
|
global: &GlobalScope,
|
||||||
|
sample: Option<String>,
|
||||||
|
report_only: bool,
|
||||||
|
runtime_code: RuntimeCode,
|
||||||
|
filename: String,
|
||||||
|
line_number: u32,
|
||||||
|
column_number: u32,
|
||||||
|
) -> CSPViolationReporter {
|
||||||
|
CSPViolationReporter {
|
||||||
|
sample,
|
||||||
|
filename,
|
||||||
|
report_only,
|
||||||
|
runtime_code,
|
||||||
|
line_number,
|
||||||
|
column_number,
|
||||||
|
target: Trusted::new(global.upcast::<EventTarget>()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_report(&self, global: &GlobalScope) -> SecurityPolicyViolationReport {
|
||||||
|
SecurityPolicyViolationReport {
|
||||||
|
sample: self.sample.clone(),
|
||||||
|
disposition: match self.report_only {
|
||||||
|
true => SecurityPolicyViolationEventDisposition::Report,
|
||||||
|
false => SecurityPolicyViolationEventDisposition::Enforce,
|
||||||
|
},
|
||||||
|
// https://w3c.github.io/webappsec-csp/#violation-resource
|
||||||
|
blocked_url: match self.runtime_code {
|
||||||
|
RuntimeCode::JS => "eval".to_owned(),
|
||||||
|
RuntimeCode::WASM => "wasm-eval".to_owned(),
|
||||||
|
},
|
||||||
|
// https://w3c.github.io/webappsec-csp/#violation-referrer
|
||||||
|
referrer: match global.get_referrer() {
|
||||||
|
Referrer::Client(url) => self.strip_url_for_reports(url),
|
||||||
|
Referrer::ReferrerUrl(url) => self.strip_url_for_reports(url),
|
||||||
|
_ => "".to_owned(),
|
||||||
|
},
|
||||||
|
status_code: global.status_code().unwrap_or(200),
|
||||||
|
document_url: self.strip_url_for_reports(global.get_url()),
|
||||||
|
source_file: self.filename.clone(),
|
||||||
|
violated_directive: "script-src".to_owned(),
|
||||||
|
effective_directive: "script-src".to_owned(),
|
||||||
|
line_number: self.line_number,
|
||||||
|
column_number: self.column_number,
|
||||||
|
original_policy: String::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fire_violation_event(&self) {
|
||||||
|
let target = self.target.root();
|
||||||
|
let global = &target.global();
|
||||||
|
let report = self.get_report(global);
|
||||||
|
|
||||||
|
let event = SecurityPolicyViolationEvent::new(
|
||||||
|
global,
|
||||||
|
Atom::from("securitypolicyviolation"),
|
||||||
|
EventBubbles::Bubbles,
|
||||||
|
EventCancelable::Cancelable,
|
||||||
|
&report.into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
event.upcast::<Event>().fire(&target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://w3c.github.io/webappsec-csp/#strip-url-for-use-in-reports>
|
||||||
|
fn strip_url_for_reports(&self, mut url: ServoUrl) -> String {
|
||||||
|
let scheme = url.scheme();
|
||||||
|
// > Step 1: If url’s scheme is not an HTTP(S) scheme, then return url’s scheme.
|
||||||
|
if scheme != "https" && scheme != "http" {
|
||||||
|
return scheme.to_owned();
|
||||||
|
}
|
||||||
|
// > Step 2: Set url’s fragment to the empty string.
|
||||||
|
url.set_fragment(None);
|
||||||
|
// > Step 3: Set url’s username to the empty string.
|
||||||
|
let _ = url.set_username("");
|
||||||
|
// > Step 4: Set url’s password to the empty string.
|
||||||
|
let _ = url.set_password(None);
|
||||||
|
// > Step 5: Return the result of executing the URL serializer on url.
|
||||||
|
url.into_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Corresponds to the operation in 5.5 Report Violation
|
||||||
|
/// <https://w3c.github.io/webappsec-csp/#report-violation>
|
||||||
|
/// > Queue a task to run the following steps:
|
||||||
|
impl TaskOnce for CSPViolationReporter {
|
||||||
|
fn run_once(self) {
|
||||||
|
// > If target implements EventTarget, fire an event named securitypolicyviolation
|
||||||
|
// > that uses the SecurityPolicyViolationEvent interface
|
||||||
|
// > at target with its attributes initialized as follows:
|
||||||
|
self.fire_violation_event();
|
||||||
|
// TODO: Support `report-to` directive that corresponds to 5.5.3.5.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SecurityPolicyViolationReport> for SecurityPolicyViolationEventInit {
|
||||||
|
fn from(value: SecurityPolicyViolationReport) -> Self {
|
||||||
|
SecurityPolicyViolationEventInit {
|
||||||
|
sample: value.sample.unwrap_or_default().into(),
|
||||||
|
blockedURI: value.blocked_url.into(),
|
||||||
|
referrer: value.referrer.into(),
|
||||||
|
statusCode: value.status_code,
|
||||||
|
documentURI: value.document_url.into(),
|
||||||
|
sourceFile: value.source_file.into(),
|
||||||
|
violatedDirective: value.violated_directive.into(),
|
||||||
|
effectiveDirective: value.effective_directive.into(),
|
||||||
|
lineNumber: value.line_number,
|
||||||
|
columnNumber: value.column_number,
|
||||||
|
originalPolicy: value.original_policy.into(),
|
||||||
|
disposition: value.disposition.into(),
|
||||||
|
parent: EventInit::empty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for SecurityPolicyViolationEventDisposition {
|
||||||
|
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
|
match self {
|
||||||
|
Self::Report => serializer.serialize_str("report"),
|
||||||
|
Self::Enforce => serializer.serialize_str("enforce"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -442,7 +442,12 @@ impl JsTimers {
|
||||||
) -> i32 {
|
) -> i32 {
|
||||||
let callback = match callback {
|
let callback = match callback {
|
||||||
TimerCallback::StringTimerCallback(code_str) => {
|
TimerCallback::StringTimerCallback(code_str) => {
|
||||||
InternalTimerCallback::StringTimerCallback(code_str)
|
let cx = GlobalScope::get_cx();
|
||||||
|
if global.is_js_evaluation_allowed(cx) {
|
||||||
|
InternalTimerCallback::StringTimerCallback(code_str)
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
TimerCallback::FunctionTimerCallback(function) => {
|
TimerCallback::FunctionTimerCallback(function) => {
|
||||||
// This is a bit complicated, but this ensures that the vector's
|
// This is a bit complicated, but this ensures that the vector's
|
||||||
|
|
5
tests/wpt/include.ini
vendored
5
tests/wpt/include.ini
vendored
|
@ -9,6 +9,11 @@ skip: true
|
||||||
skip: false
|
skip: false
|
||||||
[samesite]
|
[samesite]
|
||||||
skip: true
|
skip: true
|
||||||
|
[content-security-policy]
|
||||||
|
[unsafe-eval]
|
||||||
|
skip: false
|
||||||
|
[wasm-unsafe-eval]
|
||||||
|
skip: false
|
||||||
[cors]
|
[cors]
|
||||||
skip: false
|
skip: false
|
||||||
[css]
|
[css]
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[eval-blocked-in-about-blank-iframe.html]
|
||||||
|
expected: ERROR
|
||||||
|
[eval-blocked-in-about-blank-iframe]
|
||||||
|
expected: TIMEOUT
|
12
tests/wpt/meta/content-security-policy/wasm-unsafe-eval/default-src-blocks-wasm.any.js.ini
vendored
Normal file
12
tests/wpt/meta/content-security-policy/wasm-unsafe-eval/default-src-blocks-wasm.any.js.ini
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[default-src-blocks-wasm.any.worker.html]
|
||||||
|
[default-src-blocks-wasm]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
||||||
|
[default-src-blocks-wasm.any.html]
|
||||||
|
|
||||||
|
[default-src-blocks-wasm.any.serviceworker.html]
|
||||||
|
expected: ERROR
|
||||||
|
|
||||||
|
[default-src-blocks-wasm.any.sharedworker.html]
|
||||||
|
expected: ERROR
|
|
@ -0,0 +1,9 @@
|
||||||
|
[default-src-unsafe-eval-allows-wasm.any.sharedworker.html]
|
||||||
|
expected: ERROR
|
||||||
|
|
||||||
|
[default-src-unsafe-eval-allows-wasm.any.worker.html]
|
||||||
|
|
||||||
|
[default-src-unsafe-eval-allows-wasm.any.html]
|
||||||
|
|
||||||
|
[default-src-unsafe-eval-allows-wasm.any.serviceworker.html]
|
||||||
|
expected: ERROR
|
|
@ -0,0 +1,9 @@
|
||||||
|
[default-src-wasm-unsafe-eval-allows-wasm.any.worker.html]
|
||||||
|
|
||||||
|
[default-src-wasm-unsafe-eval-allows-wasm.any.html]
|
||||||
|
|
||||||
|
[default-src-wasm-unsafe-eval-allows-wasm.any.sharedworker.html]
|
||||||
|
expected: ERROR
|
||||||
|
|
||||||
|
[default-src-wasm-unsafe-eval-allows-wasm.any.serviceworker.html]
|
||||||
|
expected: ERROR
|
4
tests/wpt/meta/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html.ini
vendored
Normal file
4
tests/wpt/meta/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html.ini
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
[postMessage-wasm-module.html]
|
||||||
|
expected: ERROR
|
||||||
|
[Got the expected securitypolicyviolation in the iframe]
|
||||||
|
expected: TIMEOUT
|
12
tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-blocks-wasm.any.js.ini
vendored
Normal file
12
tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-blocks-wasm.any.js.ini
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[script-src-blocks-wasm.any.sharedworker.html]
|
||||||
|
expected: ERROR
|
||||||
|
|
||||||
|
[script-src-blocks-wasm.any.worker.html]
|
||||||
|
[script-src-blocks-wasm]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
||||||
|
[script-src-blocks-wasm.any.html]
|
||||||
|
|
||||||
|
[script-src-blocks-wasm.any.serviceworker.html]
|
||||||
|
expected: ERROR
|
16
tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-spv-asynch.any.js.ini
vendored
Normal file
16
tests/wpt/meta/content-security-policy/wasm-unsafe-eval/script-src-spv-asynch.any.js.ini
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
[script-src-spv-asynch.any.sharedworker.html]
|
||||||
|
expected: ERROR
|
||||||
|
|
||||||
|
[script-src-spv-asynch.any.html]
|
||||||
|
[Securitypolicyviolation event looks like it should]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
||||||
|
[script-src-spv-asynch.any.worker.html]
|
||||||
|
expected: TIMEOUT
|
||||||
|
[Securitypolicyviolation event looks like it should]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
|
||||||
|
[script-src-spv-asynch.any.serviceworker.html]
|
||||||
|
expected: ERROR
|
|
@ -0,0 +1,9 @@
|
||||||
|
[script-src-unsafe-eval-allows-wasm.any.sharedworker.html]
|
||||||
|
expected: ERROR
|
||||||
|
|
||||||
|
[script-src-unsafe-eval-allows-wasm.any.html]
|
||||||
|
|
||||||
|
[script-src-unsafe-eval-allows-wasm.any.worker.html]
|
||||||
|
|
||||||
|
[script-src-unsafe-eval-allows-wasm.any.serviceworker.html]
|
||||||
|
expected: ERROR
|
|
@ -0,0 +1,9 @@
|
||||||
|
[script-src-wasm-unsafe-eval-allows-wasm.any.serviceworker.html]
|
||||||
|
expected: ERROR
|
||||||
|
|
||||||
|
[script-src-wasm-unsafe-eval-allows-wasm.any.html]
|
||||||
|
|
||||||
|
[script-src-wasm-unsafe-eval-allows-wasm.any.worker.html]
|
||||||
|
|
||||||
|
[script-src-wasm-unsafe-eval-allows-wasm.any.sharedworker.html]
|
||||||
|
expected: ERROR
|
|
@ -2002,9 +2002,6 @@
|
||||||
[Document interface: new Document() must inherit property "onwebkitanimationstart" with the proper type]
|
[Document interface: new Document() must inherit property "onwebkitanimationstart" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Document interface: new Document() must inherit property "onsecuritypolicyviolation" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Document interface: calling queryCommandIndeterm(DOMString) on documentWithHandlers with too few arguments must throw TypeError]
|
[Document interface: calling queryCommandIndeterm(DOMString) on documentWithHandlers with too few arguments must throw TypeError]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -2017,9 +2014,6 @@
|
||||||
[Window interface: window must inherit property "onwebkitanimationiteration" with the proper type]
|
[Window interface: window must inherit property "onwebkitanimationiteration" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Window interface: attribute onsecuritypolicyviolation]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Window interface: window must inherit property "applicationCache" with the proper type]
|
[Window interface: window must inherit property "applicationCache" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -2059,9 +2053,6 @@
|
||||||
[Document interface: documentWithHandlers must inherit property "execCommand(DOMString, optional boolean, optional DOMString)" with the proper type]
|
[Document interface: documentWithHandlers must inherit property "execCommand(DOMString, optional boolean, optional DOMString)" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Window interface: window must inherit property "onsecuritypolicyviolation" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Window interface: operation print()]
|
[Window interface: operation print()]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -2074,9 +2065,6 @@
|
||||||
[Document interface: attribute all]
|
[Document interface: attribute all]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Document interface: documentWithHandlers must inherit property "onsecuritypolicyviolation" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Window interface: operation focus()]
|
[Window interface: operation focus()]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -2215,9 +2203,6 @@
|
||||||
[Document interface: operation execCommand(DOMString, optional boolean, optional DOMString)]
|
[Document interface: operation execCommand(DOMString, optional boolean, optional DOMString)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Document interface: attribute onsecuritypolicyviolation]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Window interface: attribute menubar]
|
[Window interface: attribute menubar]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -2314,9 +2299,6 @@
|
||||||
[Window interface: internal [[SetPrototypeOf\]\] method of interface prototype object - setting to a new value via Object.setPrototypeOf should throw a TypeError]
|
[Window interface: internal [[SetPrototypeOf\]\] method of interface prototype object - setting to a new value via Object.setPrototypeOf should throw a TypeError]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Document interface: iframe.contentDocument must inherit property "onsecuritypolicyviolation" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Document interface: new Document() must inherit property "queryCommandValue(DOMString)" with the proper type]
|
[Document interface: new Document() must inherit property "queryCommandValue(DOMString)" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -2892,9 +2874,6 @@
|
||||||
[HTMLElement interface: document.createElement("noscript") must inherit property "autocapitalize" with the proper type]
|
[HTMLElement interface: document.createElement("noscript") must inherit property "autocapitalize" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLElement interface: attribute onsecuritypolicyviolation]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLTableColElement interface: document.createElement("col") must inherit property "align" with the proper type]
|
[HTMLTableColElement interface: document.createElement("col") must inherit property "align" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -4155,9 +4134,6 @@
|
||||||
[HTMLObjectElement interface: document.createElement("object") must inherit property "data" with the proper type]
|
[HTMLObjectElement interface: document.createElement("object") must inherit property "data" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLElement interface: document.createElement("noscript") must inherit property "onsecuritypolicyviolation" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLFrameElement interface: attribute contentDocument]
|
[HTMLFrameElement interface: attribute contentDocument]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
[http-equiv-enumerated-ascii-case-insensitive.html]
|
|
||||||
[keyword content-security-policy]
|
|
||||||
expected: FAIL
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
[code-cache-nonce.html]
|
||||||
|
expected: ERROR
|
||||||
|
[First dynamic import should use nonce=abc]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[Second dynamic import should use nonce=def]
|
||||||
|
expected: NOTRUN
|
||||||
|
|
||||||
|
[Third dynamic import should use nonce=ghi]
|
||||||
|
expected: NOTRUN
|
|
@ -1,4 +1,5 @@
|
||||||
[basic.any.html]
|
[basic.any.html]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
[basic.any.sharedworker.html]
|
[basic.any.sharedworker.html]
|
||||||
expected: ERROR
|
expected: ERROR
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
[propagate-nonce-external-classic.html]
|
||||||
|
expected: TIMEOUT
|
|
@ -0,0 +1,2 @@
|
||||||
|
[propagate-nonce-external-module.html]
|
||||||
|
expected: TIMEOUT
|
|
@ -0,0 +1,2 @@
|
||||||
|
[propagate-nonce-inline-classic.html]
|
||||||
|
expected: TIMEOUT
|
|
@ -0,0 +1,2 @@
|
||||||
|
[propagate-nonce-inline-module.html]
|
||||||
|
expected: TIMEOUT
|
|
@ -1,4 +1,5 @@
|
||||||
[string-compilation-nonce-classic.html]
|
[string-compilation-nonce-classic.html]
|
||||||
|
expected: TIMEOUT
|
||||||
[reflected inline event handlers must not inherit the nonce from the triggering script, thus fail]
|
[reflected inline event handlers must not inherit the nonce from the triggering script, thus fail]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
[string-compilation-nonce-module.html]
|
[string-compilation-nonce-module.html]
|
||||||
|
expected: TIMEOUT
|
||||||
[reflected inline event handlers must not inherit the nonce from the triggering script, thus fail]
|
[reflected inline event handlers must not inherit the nonce from the triggering script, thus fail]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
[v8-code-cache.html]
|
||||||
|
expected: ERROR
|
||||||
|
[text/javascript: Run #1]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[text/javascript: Run #2]
|
||||||
|
expected: NOTRUN
|
||||||
|
|
||||||
|
[text/javascript: Run #3]
|
||||||
|
expected: NOTRUN
|
||||||
|
|
||||||
|
[text/javascript: Run #4]
|
||||||
|
expected: NOTRUN
|
||||||
|
|
||||||
|
[text/javascript: Run #5]
|
||||||
|
expected: NOTRUN
|
||||||
|
|
||||||
|
[module: Run #1]
|
||||||
|
expected: NOTRUN
|
||||||
|
|
||||||
|
[module: Run #2]
|
||||||
|
expected: NOTRUN
|
||||||
|
|
||||||
|
[module: Run #3]
|
||||||
|
expected: NOTRUN
|
||||||
|
|
||||||
|
[module: Run #4]
|
||||||
|
expected: NOTRUN
|
||||||
|
|
||||||
|
[module: Run #5]
|
||||||
|
expected: NOTRUN
|
|
@ -314,9 +314,6 @@
|
||||||
[onsecuritypolicyviolation: the default value must be null]
|
[onsecuritypolicyviolation: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onsecuritypolicyviolation: the content attribute must be compiled into a function as the corresponding property]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[onseeked: must be on the appropriate locations for GlobalEventHandlers]
|
[onseeked: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,6 @@
|
||||||
[not shadowed contextrestored (document.body)]
|
[not shadowed contextrestored (document.body)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[not shadowed securitypolicyviolation (document.body)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[not shadowed slotchange (document.body)]
|
[not shadowed slotchange (document.body)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -44,9 +41,6 @@
|
||||||
[not shadowed contextrestored (document.createElement("body"))]
|
[not shadowed contextrestored (document.createElement("body"))]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[not shadowed securitypolicyviolation (document.createElement("body"))]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[not shadowed slotchange (document.createElement("body"))]
|
[not shadowed slotchange (document.createElement("body"))]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -80,9 +74,6 @@
|
||||||
[not shadowed contextrestored (window)]
|
[not shadowed contextrestored (window)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[not shadowed securitypolicyviolation (window)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[not shadowed slotchange (window)]
|
[not shadowed slotchange (window)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,6 @@
|
||||||
[not shadowed contextrestored (document.body)]
|
[not shadowed contextrestored (document.body)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[not shadowed securitypolicyviolation (document.body)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[not shadowed slotchange (document.body)]
|
[not shadowed slotchange (document.body)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -44,9 +41,6 @@
|
||||||
[not shadowed contextrestored (document.createElement("frameset"))]
|
[not shadowed contextrestored (document.createElement("frameset"))]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[not shadowed securitypolicyviolation (document.createElement("frameset"))]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[not shadowed slotchange (document.createElement("frameset"))]
|
[not shadowed slotchange (document.createElement("frameset"))]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -80,9 +74,6 @@
|
||||||
[not shadowed contextrestored (window)]
|
[not shadowed contextrestored (window)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[not shadowed securitypolicyviolation (window)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[not shadowed slotchange (window)]
|
[not shadowed slotchange (window)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,6 @@
|
||||||
[contextrestored is unaffected on a windowless body]
|
[contextrestored is unaffected on a windowless body]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[securitypolicyviolation is unaffected on a windowless body]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[slotchange is unaffected on a windowless body]
|
[slotchange is unaffected on a windowless body]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -35,9 +32,6 @@
|
||||||
[contextrestored is unaffected on a windowless frameset]
|
[contextrestored is unaffected on a windowless frameset]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[securitypolicyviolation is unaffected on a windowless frameset]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[slotchange is unaffected on a windowless frameset]
|
[slotchange is unaffected on a windowless frameset]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
4
tests/wpt/mozilla/meta/MANIFEST.json
vendored
4
tests/wpt/mozilla/meta/MANIFEST.json
vendored
|
@ -13434,14 +13434,14 @@
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"interfaces.html": [
|
"interfaces.html": [
|
||||||
"d4daa95cfe84f1ffd77d0b631e67deb778db5fc3",
|
"2ab9214e53c431e4a599254d4cb498fd75eef4ed",
|
||||||
[
|
[
|
||||||
null,
|
null,
|
||||||
{}
|
{}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"interfaces.worker.js": [
|
"interfaces.worker.js": [
|
||||||
"b1c7b7e9c5c2f21eafdcd27eafe589e654260628",
|
"2782a452ac10b97c4cd4418fb7ba516325a76fab",
|
||||||
[
|
[
|
||||||
"mozilla/interfaces.worker.html",
|
"mozilla/interfaces.worker.html",
|
||||||
{}
|
{}
|
||||||
|
|
|
@ -223,6 +223,7 @@ test_interfaces([
|
||||||
"Request",
|
"Request",
|
||||||
"Response",
|
"Response",
|
||||||
"Screen",
|
"Screen",
|
||||||
|
"SecurityPolicyViolationEvent",
|
||||||
"Selection",
|
"Selection",
|
||||||
"ShadowRoot",
|
"ShadowRoot",
|
||||||
"StaticRange",
|
"StaticRange",
|
||||||
|
|
|
@ -55,6 +55,7 @@ test_interfaces([
|
||||||
"ReadableStream",
|
"ReadableStream",
|
||||||
"Request",
|
"Request",
|
||||||
"Response",
|
"Response",
|
||||||
|
"SecurityPolicyViolationEvent",
|
||||||
"TextDecoder",
|
"TextDecoder",
|
||||||
"TextEncoder",
|
"TextEncoder",
|
||||||
"URL",
|
"URL",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue