From fd950a730961dcf71eccd1e244776897c5f945c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naz=C4=B1m=20Can=20Alt=C4=B1nova?= Date: Tue, 20 Dec 2016 11:37:28 +0300 Subject: [PATCH] Support origins in CSSOM stylesheets --- components/script/dom/cssstylesheet.rs | 26 ++++++++--- components/script/dom/htmllinkelement.rs | 6 +++ components/script/dom/htmlstyleelement.rs | 6 +++ .../script/dom/webidls/CSSStyleSheet.webidl | 2 +- components/script/stylesheet_loader.rs | 18 +++++++- tests/wpt/metadata/MANIFEST.json | 6 +++ .../cssom/stylesheet-same-origin.css | 3 ++ .../cssom/stylesheet-same-origin.sub.html | 45 +++++++++++++++++++ 8 files changed, 103 insertions(+), 9 deletions(-) create mode 100644 tests/wpt/web-platform-tests/cssom/stylesheet-same-origin.css create mode 100644 tests/wpt/web-platform-tests/cssom/stylesheet-same-origin.sub.html diff --git a/components/script/dom/cssstylesheet.rs b/components/script/dom/cssstylesheet.rs index 908cfad2cd5..d0f6ed869c3 100644 --- a/components/script/dom/cssstylesheet.rs +++ b/components/script/dom/cssstylesheet.rs @@ -5,7 +5,7 @@ use dom::bindings::codegen::Bindings::CSSStyleSheetBinding; use dom::bindings::codegen::Bindings::CSSStyleSheetBinding::CSSStyleSheetMethods; use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods; -use dom::bindings::error::{ErrorResult, Fallible}; +use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::js::{JS, MutNullableJS, Root}; use dom::bindings::reflector::{reflect_dom_object, DomObject}; use dom::bindings::str::DOMString; @@ -13,6 +13,7 @@ use dom::cssrulelist::{CSSRuleList, RulesSource}; use dom::element::Element; use dom::stylesheet::StyleSheet; use dom::window::Window; +use std::cell::Cell; use std::sync::Arc; use style::stylesheets::Stylesheet as StyleStyleSheet; @@ -23,6 +24,7 @@ pub struct CSSStyleSheet { rulelist: MutNullableJS, #[ignore_heap_size_of = "Arc"] style_stylesheet: Arc, + origin_clean: Cell, } impl CSSStyleSheet { @@ -36,6 +38,7 @@ impl CSSStyleSheet { owner: JS::from_ref(owner), rulelist: MutNullableJS::new(None), style_stylesheet: stylesheet, + origin_clean: Cell::new(true), } } @@ -71,25 +74,34 @@ impl CSSStyleSheet { pub fn style_stylesheet(&self) -> &StyleStyleSheet { &self.style_stylesheet } + + pub fn set_origin_clean(&self, origin_clean: bool) { + self.origin_clean.set(origin_clean); + } } impl CSSStyleSheetMethods for CSSStyleSheet { // https://drafts.csswg.org/cssom/#dom-cssstylesheet-cssrules - fn CssRules(&self) -> Root { - // XXXManishearth check origin clean flag - // https://github.com/servo/servo/issues/14327 - self.rulelist() + fn GetCssRules(&self) -> Fallible> { + if !self.origin_clean.get() { + return Err(Error::Security); + } + Ok(self.rulelist()) } // https://drafts.csswg.org/cssom/#dom-cssstylesheet-insertrule fn InsertRule(&self, rule: DOMString, index: u32) -> Fallible { - // XXXManishearth check origin clean flag + if !self.origin_clean.get() { + return Err(Error::Security); + } self.rulelist().insert_rule(&rule, index, /* nested */ false) } // https://drafts.csswg.org/cssom/#dom-cssstylesheet-deleterule fn DeleteRule(&self, index: u32) -> ErrorResult { - // XXXManishearth check origin clean flag + if !self.origin_clean.get() { + return Err(Error::Security); + } self.rulelist().remove_rule(index) } } diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs index 674db5c8a0c..7b26fb8bbee 100644 --- a/components/script/dom/htmllinkelement.rs +++ b/components/script/dom/htmllinkelement.rs @@ -319,6 +319,12 @@ impl StylesheetOwner for HTMLLinkElement { None } + + fn set_origin_clean(&self, origin_clean: bool) { + if let Some(stylesheet) = self.get_cssom_stylesheet() { + stylesheet.set_origin_clean(origin_clean); + } + } } impl HTMLLinkElementMethods for HTMLLinkElement { diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs index 35da9bb6368..7401c67aa95 100644 --- a/components/script/dom/htmlstyleelement.rs +++ b/components/script/dom/htmlstyleelement.rs @@ -191,6 +191,12 @@ impl StylesheetOwner for HTMLStyleElement { fn referrer_policy(&self) -> Option { None } + + fn set_origin_clean(&self, origin_clean: bool) { + if let Some(stylesheet) = self.get_cssom_stylesheet() { + stylesheet.set_origin_clean(origin_clean); + } + } } diff --git a/components/script/dom/webidls/CSSStyleSheet.webidl b/components/script/dom/webidls/CSSStyleSheet.webidl index 6fba0cf983a..c616c9d2a10 100644 --- a/components/script/dom/webidls/CSSStyleSheet.webidl +++ b/components/script/dom/webidls/CSSStyleSheet.webidl @@ -6,7 +6,7 @@ [Exposed=Window] interface CSSStyleSheet : StyleSheet { // readonly attribute CSSRule? ownerRule; - [SameObject] readonly attribute CSSRuleList cssRules; + [Throws, SameObject] readonly attribute CSSRuleList cssRules; [Throws] unsigned long insertRule(DOMString rule, unsigned long index); [Throws] void deleteRule(unsigned long index); }; diff --git a/components/script/stylesheet_loader.rs b/components/script/stylesheet_loader.rs index 25b06e31de9..8e5481df8aa 100644 --- a/components/script/stylesheet_loader.rs +++ b/components/script/stylesheet_loader.rs @@ -19,7 +19,7 @@ use hyper::mime::{Mime, TopLevel, SubLevel}; use hyper_serde::Serde; use ipc_channel::ipc; use ipc_channel::router::ROUTER; -use net_traits::{FetchResponseListener, FetchMetadata, Metadata, NetworkError, ReferrerPolicy}; +use net_traits::{FetchResponseListener, FetchMetadata, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy}; use net_traits::request::{CorsSettings, CredentialsMode, Destination, RequestInit, RequestMode, Type as RequestType}; use network_listener::{NetworkListener, PreInvoke}; use parking_lot::RwLock; @@ -47,6 +47,9 @@ pub trait StylesheetOwner { /// Returns None if there are still pending loads, or whether any load has /// failed since the loads started. fn load_finished(&self, successful: bool) -> Option; + + /// Sets origin_clean flag. + fn set_origin_clean(&self, origin_clean: bool); } pub enum StylesheetContextSource { @@ -81,6 +84,7 @@ pub struct StylesheetContext { data: Vec, /// The node document for elem when the load was initiated. document: Trusted, + origin_clean: bool, } impl PreInvoke for StylesheetContext {} @@ -92,6 +96,16 @@ impl FetchResponseListener for StylesheetContext { fn process_response(&mut self, metadata: Result) { + if let Ok(FetchMetadata::Filtered { ref filtered, .. }) = metadata { + match *filtered { + FilteredMetadata::Opaque | + FilteredMetadata::OpaqueRedirect => { + self.origin_clean = false; + }, + _ => {}, + } + } + self.metadata = metadata.ok().map(|m| { match m { FetchMetadata::Unfiltered(m) => m, @@ -169,6 +183,7 @@ impl FetchResponseListener for StylesheetContext { let owner = elem.upcast::().as_stylesheet_owner() .expect("Stylesheet not loaded by