diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 66021ce6104..21dfde99f22 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -51,9 +51,11 @@ use dom::htmlimageelement::{HTMLImageElement, LayoutHTMLImageElementHelpers}; use dom::htmlinputelement::{HTMLInputElement, LayoutHTMLInputElementHelpers}; use dom::htmllabelelement::HTMLLabelElement; use dom::htmllegendelement::HTMLLegendElement; +use dom::htmllinkelement::HTMLLinkElement; use dom::htmlobjectelement::HTMLObjectElement; use dom::htmloptgroupelement::HTMLOptGroupElement; use dom::htmlselectelement::HTMLSelectElement; +use dom::htmlstyleelement::HTMLStyleElement; use dom::htmltablecellelement::{HTMLTableCellElement, HTMLTableCellElementLayoutHelpers}; use dom::htmltableelement::{HTMLTableElement, HTMLTableElementLayoutHelpers}; use dom::htmltablerowelement::{HTMLTableRowElement, HTMLTableRowElementLayoutHelpers}; @@ -109,6 +111,7 @@ use style::sink::Push; use style::stylist::ApplicableDeclarationBlock; use style::values::CSSFloat; use style::values::specified::{self, CSSColor, CSSRGBA, LengthOrPercentage}; +use stylesheet_loader::StylesheetOwner; // TODO: Update focus state when the top-level browsing context gains or loses system focus, // and when the element enters or leaves a browsing context container. @@ -2407,6 +2410,18 @@ impl Element { }) } + pub fn as_stylesheet_owner(&self) -> Option<&StylesheetOwner> { + if let Some(s) = self.downcast::() { + return Some(s as &StylesheetOwner) + } + + if let Some(l) = self.downcast::() { + return Some(l as &StylesheetOwner) + } + + None + } + // https://html.spec.whatwg.org/multipage/#category-submit pub fn as_maybe_validatable(&self) -> Option<&Validatable> { let element = match self.upcast::().type_id() { diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs index 298fb5a8c94..cc66a822d92 100644 --- a/components/script/dom/htmllinkelement.rs +++ b/components/script/dom/htmllinkelement.rs @@ -5,6 +5,7 @@ use cssparser::Parser as CssParser; use dom::attr::Attr; use dom::bindings::cell::DOMRefCell; +use dom::bindings::codegen::Bindings::DOMTokenListBinding::DOMTokenListBinding::DOMTokenListMethods; use dom::bindings::codegen::Bindings::HTMLLinkElementBinding; use dom::bindings::codegen::Bindings::HTMLLinkElementBinding::HTMLLinkElementMethods; use dom::bindings::inheritance::Castable; @@ -20,6 +21,7 @@ use dom::node::{Node, document_from_node, window_from_node}; use dom::stylesheet::StyleSheet as DOMStyleSheet; use dom::virtualmethods::VirtualMethods; use html5ever_atoms::LocalName; +use net_traits::ReferrerPolicy; use script_traits::{MozBrowserEvent, ScriptMsg as ConstellationMsg}; use std::ascii::AsciiExt; use std::borrow::ToOwned; @@ -30,7 +32,7 @@ use style::attr::AttrValue; use style::media_queries::parse_media_query_list; use style::str::HTML_SPACE_CHARACTERS; use style::stylesheets::Stylesheet; -use stylesheet_loader::{StylesheetLoader, StylesheetContextSource}; +use stylesheet_loader::{StylesheetLoader, StylesheetContextSource, StylesheetOwner}; unsafe_no_jsmanaged_fields!(Stylesheet); @@ -216,28 +218,6 @@ impl VirtualMethods for HTMLLinkElement { impl HTMLLinkElement { - pub fn increment_pending_loads_count(&self) { - self.pending_loads.set(self.pending_loads.get() + 1) - } - - /// Returns None if there are still pending loads, or whether any load has - /// failed since the loads started. - pub fn load_finished(&self, succeeded: bool) -> Option { - assert!(self.pending_loads.get() > 0, "What finished?"); - if !succeeded { - self.any_failed_load.set(true); - } - - self.pending_loads.set(self.pending_loads.get() - 1); - if self.pending_loads.get() != 0 { - return None; - } - - let any_failed = self.any_failed_load.get(); - self.any_failed_load.set(false); - Some(any_failed) - } - /// https://html.spec.whatwg.org/multipage/#concept-link-obtain fn handle_stylesheet_url(&self, href: &str) { let document = document_from_node(self); @@ -297,6 +277,40 @@ impl HTMLLinkElement { } } +impl StylesheetOwner for HTMLLinkElement { + fn increment_pending_loads_count(&self) { + self.pending_loads.set(self.pending_loads.get() + 1) + } + + fn load_finished(&self, succeeded: bool) -> Option { + assert!(self.pending_loads.get() > 0, "What finished?"); + if !succeeded { + self.any_failed_load.set(true); + } + + self.pending_loads.set(self.pending_loads.get() - 1); + if self.pending_loads.get() != 0 { + return None; + } + + let any_failed = self.any_failed_load.get(); + self.any_failed_load.set(false); + Some(any_failed) + } + + fn parser_inserted(&self) -> bool { + self.parser_inserted.get() + } + + fn referrer_policy(&self) -> Option { + if self.RelList().Contains("noreferrer".into()) { + return Some(ReferrerPolicy::NoReferrer) + } + + None + } +} + impl HTMLLinkElementMethods for HTMLLinkElement { // https://html.spec.whatwg.org/multipage/#dom-link-href make_url_getter!(Href, "href"); diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs index 4cf0575ed3d..2507f7bee35 100644 --- a/components/script/dom/htmlstyleelement.rs +++ b/components/script/dom/htmlstyleelement.rs @@ -19,13 +19,14 @@ use dom::node::{ChildrenMutation, Node, document_from_node, window_from_node}; use dom::stylesheet::StyleSheet as DOMStyleSheet; use dom::virtualmethods::VirtualMethods; use html5ever_atoms::LocalName; +use net_traits::ReferrerPolicy; use script_layout_interface::message::Msg; use std::cell::Cell; use std::sync::Arc; use style::media_queries::parse_media_query_list; use style::parser::ParserContextExtraData; use style::stylesheets::{Stylesheet, Origin}; -use stylesheet_loader::StylesheetLoader; +use stylesheet_loader::{StylesheetLoader, StylesheetOwner}; #[dom_struct] pub struct HTMLStyleElement { @@ -64,28 +65,6 @@ impl HTMLStyleElement { HTMLStyleElementBinding::Wrap) } - pub fn increment_pending_loads_count(&self) { - self.pending_loads.set(self.pending_loads.get() + 1) - } - - /// Returns None if there are still pending loads, or whether any load has - /// failed since the loads started. - pub fn load_finished(&self, succeeded: bool) -> Option { - assert!(self.pending_loads.get() > 0, "What finished?"); - if !succeeded { - self.any_failed_load.set(true); - } - - self.pending_loads.set(self.pending_loads.get() - 1); - if self.pending_loads.get() != 0 { - return None; - } - - let any_failed = self.any_failed_load.get(); - self.any_failed_load.set(false); - Some(any_failed) - } - pub fn parse_own_css(&self) { let node = self.upcast::(); let element = self.upcast::(); @@ -137,10 +116,6 @@ impl HTMLStyleElement { }) }) } - - pub fn parser_inserted(&self) -> bool { - self.parser_inserted.get() - } } impl VirtualMethods for HTMLStyleElement { @@ -168,6 +143,37 @@ impl VirtualMethods for HTMLStyleElement { } } +impl StylesheetOwner for HTMLStyleElement { + fn increment_pending_loads_count(&self) { + self.pending_loads.set(self.pending_loads.get() + 1) + } + + fn load_finished(&self, succeeded: bool) -> Option { + assert!(self.pending_loads.get() > 0, "What finished?"); + if !succeeded { + self.any_failed_load.set(true); + } + + self.pending_loads.set(self.pending_loads.get() - 1); + if self.pending_loads.get() != 0 { + return None; + } + + let any_failed = self.any_failed_load.get(); + self.any_failed_load.set(false); + Some(any_failed) + } + + fn parser_inserted(&self) -> bool { + self.parser_inserted.get() + } + + fn referrer_policy(&self) -> Option { + None + } +} + + impl HTMLStyleElementMethods for HTMLStyleElement { // https://drafts.csswg.org/cssom/#dom-linkstyle-sheet fn GetSheet(&self) -> Option> { diff --git a/components/script/stylesheet_loader.rs b/components/script/stylesheet_loader.rs index 38232e6c4bd..427593c8500 100644 --- a/components/script/stylesheet_loader.rs +++ b/components/script/stylesheet_loader.rs @@ -3,15 +3,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use document_loader::LoadType; -use dom::bindings::codegen::Bindings::DOMTokenListBinding::DOMTokenListBinding::DOMTokenListMethods; -use dom::bindings::codegen::Bindings::HTMLLinkElementBinding::HTMLLinkElementBinding::HTMLLinkElementMethods; use dom::bindings::inheritance::Castable; use dom::bindings::refcounted::Trusted; use dom::bindings::reflector::DomObject; +use dom::element::Element; use dom::eventtarget::EventTarget; use dom::htmlelement::HTMLElement; use dom::htmllinkelement::HTMLLinkElement; -use dom::htmlstyleelement::HTMLStyleElement; use dom::node::{document_from_node, window_from_node}; use encoding::EncodingRef; use encoding::all::UTF_8; @@ -33,6 +31,23 @@ use style::parser::ParserContextExtraData; use style::stylesheets::{ImportRule, Stylesheet, Origin}; use style::stylesheets::StylesheetLoader as StyleStylesheetLoader; +pub trait StylesheetOwner { + /// Returns whether this element was inserted by the parser (i.e., it should + /// trigger a document-load-blocking load). + fn parser_inserted(&self) -> bool; + + /// Which referrer policy should loads triggered by this owner follow, or + /// `None` for the default. + fn referrer_policy(&self) -> Option; + + /// Notes that a new load is pending to finish. + fn increment_pending_loads_count(&self); + + /// 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; +} + pub enum StylesheetContextSource { // NB: `media` is just an option so we avoid cloning it. LinkElement { media: Option, url: ServoUrl }, @@ -146,35 +161,18 @@ impl FetchResponseListener for StylesheetContext { successful = metadata.status.map_or(false, |(code, _)| code == 200); } - if let Some(ref link) = elem.downcast::() { - if link.parser_inserted() { - document.decrement_script_blocking_stylesheet_count(); - } - } else if let Some(ref style) = elem.downcast::() { - if style.parser_inserted() { - document.decrement_script_blocking_stylesheet_count(); - } - } else { - unreachable!( - "Stylesheet loads can only be triggered by or