diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index d60545e159b..2f0787ad6e4 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -23,6 +23,7 @@ use dom::bindings::codegen::InheritTypes::{HTMLAreaElementDerived, HTMLEmbedElem use dom::bindings::codegen::InheritTypes::{HTMLFormElementDerived, HTMLImageElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLScriptElementDerived, HTMLTitleElementDerived}; use dom::bindings::codegen::InheritTypes::ElementDerived; +use dom::bindings::codegen::InheritTypes::HTMLBaseElementCast; use dom::bindings::codegen::UnionTypes::NodeOrString; use dom::bindings::error::{ErrorResult, Fallible}; use dom::bindings::error::Error::{NotSupported, InvalidCharacter, Security}; @@ -45,6 +46,7 @@ use dom::element::{ElementTypeId, ActivationElementHelpers, FocusElementHelpers} use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers}; use dom::eventtarget::{EventTarget, EventTargetTypeId, EventTargetHelpers}; use dom::htmlanchorelement::HTMLAnchorElement; +use dom::htmlbaseelement::HTMLBaseElement; use dom::htmlcollection::{HTMLCollection, CollectionFilter}; use dom::htmlelement::{HTMLElement, HTMLElementTypeId}; use dom::htmlheadelement::HTMLHeadElement; @@ -231,7 +233,14 @@ pub trait DocumentHelpers<'a> { fn encoding_name(self) -> Ref<'a, DOMString>; fn is_html_document(self) -> bool; fn is_fully_active(self) -> bool; + /// https://dom.spec.whatwg.org/#concept-document-url fn url(self) -> Url; + /// https://html.spec.whatwg.org/multipage/#fallback-base-url + fn fallback_base_url(self) -> Url; + /// https://html.spec.whatwg.org/multipage/#document-base-url + fn base_url(self) -> Url; + /// Returns the first `base` element in the DOM that has an `href` attribute. + fn base_element(self) -> Option>; fn quirks_mode(self) -> QuirksMode; fn set_quirks_mode(self, mode: QuirksMode); fn set_encoding_name(self, name: DOMString); @@ -336,11 +345,38 @@ impl<'a> DocumentHelpers<'a> for &'a Document { true } - // https://dom.spec.whatwg.org/#dom-document-url + // https://dom.spec.whatwg.org/#concept-document-url fn url(self) -> Url { self.url.clone() } + // https://html.spec.whatwg.org/multipage/#fallback-base-url + fn fallback_base_url(self) -> Url { + // Step 1: iframe srcdoc (#4767). + // Step 2: about:blank with a creator browsing context. + // Step 3. + self.url() + } + + // https://html.spec.whatwg.org/multipage/#document-base-url + fn base_url(self) -> Url { + match self.base_element() { + // Step 1. + None => self.fallback_base_url(), + // Step 2. + Some(base) => base.frozen_base_url(), + } + } + + /// Returns the first `base` element in the DOM that has an `href` attribute. + fn base_element(self) -> Option> { + NodeCast::from_ref(self) + .traverse_preorder() + .filter_map(HTMLBaseElementCast::to_root) + .filter(|element| ElementCast::from_ref(&**element).has_attribute(&atom!("href"))) + .next() + } + fn quirks_mode(self) -> QuirksMode { self.quirks_mode.get() } diff --git a/components/script/dom/htmlbaseelement.rs b/components/script/dom/htmlbaseelement.rs index 6f4a585b113..42e7ffe6b5d 100644 --- a/components/script/dom/htmlbaseelement.rs +++ b/components/script/dom/htmlbaseelement.rs @@ -2,18 +2,22 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use dom::attr::AttrHelpers; use dom::bindings::codegen::Bindings::HTMLBaseElementBinding; +use dom::bindings::codegen::InheritTypes::ElementCast; use dom::bindings::codegen::InheritTypes::HTMLBaseElementDerived; use dom::bindings::codegen::InheritTypes::HTMLElementCast; use dom::bindings::js::Root; -use dom::document::Document; +use dom::document::{Document, DocumentHelpers}; use dom::eventtarget::{EventTarget, EventTargetTypeId}; -use dom::element::ElementTypeId; +use dom::element::{ElementTypeId, AttributeHandlers}; use dom::htmlelement::{HTMLElement, HTMLElementTypeId}; -use dom::node::{Node, NodeTypeId}; +use dom::node::{Node, NodeTypeId, document_from_node}; use dom::virtualmethods::VirtualMethods; use util::str::DOMString; +use url::{Url, UrlParser}; + #[dom_struct] pub struct HTMLBaseElement { htmlelement: HTMLElement @@ -41,6 +45,16 @@ impl HTMLBaseElement { let element = HTMLBaseElement::new_inherited(localName, prefix, document); Node::reflect_node(box element, document, HTMLBaseElementBinding::Wrap) } + + /// https://html.spec.whatwg.org/multipage/#frozen-base-url + pub fn frozen_base_url(&self) -> Url { + let href = ElementCast::from_ref(self).get_attribute(&ns!(""), &atom!("href")) + .expect("The frozen base url is only defined for base elements \ + that have a base url."); + let base = document_from_node(self).fallback_base_url(); + let parsed = UrlParser::new().base_url(&base).parse(&href.value()); + parsed.unwrap_or(base) + } } impl<'a> VirtualMethods for &'a HTMLBaseElement {