summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Userland/Libraries/LibWeb/DOM/Document.cpp43
-rw-r--r--Userland/Libraries/LibWeb/DOM/Document.h4
-rw-r--r--Userland/Libraries/LibWeb/DOM/Node.cpp4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLBaseElement.cpp49
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLBaseElement.h12
-rw-r--r--Userland/Libraries/LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.cpp5
-rw-r--r--Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp2
7 files changed, 111 insertions, 8 deletions
diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp
index 34a964d9bd..5b2f9a7ca9 100644
--- a/Userland/Libraries/LibWeb/DOM/Document.cpp
+++ b/Userland/Libraries/LibWeb/DOM/Document.cpp
@@ -43,6 +43,7 @@
#include <LibWeb/HTML/EventNames.h>
#include <LibWeb/HTML/HTMLAnchorElement.h>
#include <LibWeb/HTML/HTMLAreaElement.h>
+#include <LibWeb/HTML/HTMLBaseElement.h>
#include <LibWeb/HTML/HTMLBodyElement.h>
#include <LibWeb/HTML/HTMLEmbedElement.h>
#include <LibWeb/HTML/HTMLFormElement.h>
@@ -523,11 +524,49 @@ Vector<CSS::BackgroundLayerData> const* Document::background_layers() const
return &body_layout_node->background_layers();
}
+RefPtr<HTML::HTMLBaseElement> Document::first_base_element_with_href_in_tree_order() const
+{
+ RefPtr<HTML::HTMLBaseElement> base_element;
+
+ for_each_in_subtree_of_type<HTML::HTMLBaseElement>([&base_element](HTML::HTMLBaseElement const& base_element_in_tree) {
+ if (base_element_in_tree.has_attribute(HTML::AttributeNames::href)) {
+ base_element = base_element_in_tree;
+ return IterationDecision::Break;
+ }
+
+ return IterationDecision::Continue;
+ });
+
+ return base_element;
+}
+
+// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#fallback-base-url
+AK::URL Document::fallback_base_url() const
+{
+ // FIXME: 1. If document is an iframe srcdoc document, then return the document base URL of document's browsing context's container document.
+ // FIXME: 2. If document's URL is about:blank, and document's browsing context's creator base URL is non-null, then return that creator base URL.
+
+ // 3. Return document's URL.
+ return m_url;
+}
+
+// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#document-base-url
+AK::URL Document::base_url() const
+{
+ // 1. If there is no base element that has an href attribute in the Document, then return the Document's fallback base URL.
+ auto base_element = first_base_element_with_href_in_tree_order();
+ if (!base_element)
+ return fallback_base_url();
+
+ // 2. Otherwise, return the frozen base URL of the first base element in the Document that has an href attribute, in tree order.
+ return base_element->frozen_base_url();
+}
+
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#parse-a-url
AK::URL Document::parse_url(String const& url) const
{
- // FIXME: Make sure we do this according to spec.
- return m_url.complete_url(url);
+ // FIXME: Pass in document's character encoding.
+ return base_url().complete_url(url);
}
void Document::set_needs_layout()
diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h
index ac646979f1..143ae6908d 100644
--- a/Userland/Libraries/LibWeb/DOM/Document.h
+++ b/Userland/Libraries/LibWeb/DOM/Document.h
@@ -66,6 +66,10 @@ public:
void set_url(const AK::URL& url) { m_url = url; }
AK::URL url() const { return m_url; }
+ AK::URL fallback_base_url() const;
+ AK::URL base_url() const;
+
+ RefPtr<HTML::HTMLBaseElement> first_base_element_with_href_in_tree_order() const;
String url_string() const { return m_url.to_string(); }
String document_uri() const { return m_url.to_string(); }
diff --git a/Userland/Libraries/LibWeb/DOM/Node.cpp b/Userland/Libraries/LibWeb/DOM/Node.cpp
index eced978f4c..7ca92dfe6f 100644
--- a/Userland/Libraries/LibWeb/DOM/Node.cpp
+++ b/Userland/Libraries/LibWeb/DOM/Node.cpp
@@ -81,8 +81,8 @@ Node::~Node()
// https://dom.spec.whatwg.org/#dom-node-baseuri
String Node::base_uri() const
{
- // FIXME: Return this’s node document’s document base URL, serialized.
- return document().url_string();
+ // Return this’s node document’s document base URL, serialized.
+ return document().base_url().to_string();
}
const HTML::HTMLAnchorElement* Node::enclosing_link_element() const
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBaseElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLBaseElement.cpp
index 19a73dfe84..b5008f41e6 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLBaseElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLBaseElement.cpp
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
+#include <LibWeb/DOM/Document.h>
#include <LibWeb/HTML/HTMLBaseElement.h>
namespace Web::HTML {
@@ -14,4 +15,52 @@ HTMLBaseElement::HTMLBaseElement(DOM::Document& document, DOM::QualifiedName qua
}
HTMLBaseElement::~HTMLBaseElement() = default;
+
+void HTMLBaseElement::inserted()
+{
+ HTMLElement::inserted();
+
+ // The frozen base URL must be immediately set for an element whenever any of the following situations occur:
+ // - The base element becomes the first base element in tree order with an href content attribute in its Document.
+
+ // NOTE: inserted() is called after this element has been inserted into the document.
+ auto first_base_element_with_href_in_document = document().first_base_element_with_href_in_tree_order();
+ if (first_base_element_with_href_in_document == this)
+ set_the_frozen_base_url();
+}
+
+void HTMLBaseElement::parse_attribute(FlyString const& name, String const& value)
+{
+ HTMLElement::parse_attribute(name, value);
+
+ // The frozen base URL must be immediately set for an element whenever any of the following situations occur:
+ // - The base element is the first base element in tree order with an href content attribute in its Document, and its href content attribute is changed.
+ if (name != AttributeNames::href)
+ return;
+
+ auto first_base_element_with_href_in_document = document().first_base_element_with_href_in_tree_order();
+ if (first_base_element_with_href_in_document == this)
+ set_the_frozen_base_url();
+}
+
+// https://html.spec.whatwg.org/multipage/semantics.html#set-the-frozen-base-url
+void HTMLBaseElement::set_the_frozen_base_url()
+{
+ // 1. Let document be element's node document.
+ auto& document = this->document();
+
+ // 2. Let urlRecord be the result of parsing the value of element's href content attribute with document's fallback base URL, and document's character encoding. (Thus, the base element isn't affected by itself.)
+ auto href = attribute(AttributeNames::href);
+ auto url_record = document.fallback_base_url().complete_url(href);
+
+ // 3. Set element's frozen base URL to document's fallback base URL, if urlRecord is failure or running Is base allowed for Document? on the resulting URL record and document returns "Blocked", and to urlRecord otherwise.
+ // FIXME: Apply "Is base allowed for Document?" CSP
+ if (!url_record.is_valid()) {
+ m_frozen_base_url = document.fallback_base_url();
+ return;
+ }
+
+ m_frozen_base_url = move(url_record);
+}
+
}
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBaseElement.h b/Userland/Libraries/LibWeb/HTML/HTMLBaseElement.h
index de620b86a9..40d7bd3525 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLBaseElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLBaseElement.h
@@ -16,6 +16,18 @@ public:
HTMLBaseElement(DOM::Document&, DOM::QualifiedName);
virtual ~HTMLBaseElement() override;
+
+ AK::URL const& frozen_base_url() const { return m_frozen_base_url; }
+
+ virtual void inserted() override;
+ virtual void parse_attribute(FlyString const& name, String const& value) override;
+
+private:
+ // https://html.spec.whatwg.org/multipage/semantics.html#frozen-base-url
+ // A base element that is the first base element with an href content attribute in a document tree has a frozen base URL.
+ AK::URL m_frozen_base_url;
+
+ void set_the_frozen_base_url();
};
}
diff --git a/Userland/Libraries/LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.cpp b/Userland/Libraries/LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.cpp
index 14a541e6bb..bc5183fce2 100644
--- a/Userland/Libraries/LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.cpp
+++ b/Userland/Libraries/LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.cpp
@@ -62,9 +62,8 @@ String WindowEnvironmentSettingsObject::api_url_character_encoding()
// https://html.spec.whatwg.org/multipage/window-object.html#script-settings-for-window-objects:api-base-url
AK::URL WindowEnvironmentSettingsObject::api_base_url()
{
- // FIXME: Return the current base URL of window's associated Document.
- // (This currently just returns the current document URL, not accounting for <base> elements and such)
- return m_window->associated_document().url();
+ // Return the current base URL of window's associated Document.
+ return m_window->associated_document().base_url();
}
// https://html.spec.whatwg.org/multipage/window-object.html#script-settings-for-window-objects:concept-settings-object-origin
diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp
index d4674251d7..7a145ee90a 100644
--- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp
+++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp
@@ -493,7 +493,7 @@ DOM::ExceptionOr<void> XMLHttpRequest::open(String const& method, String const&
auto normalized_method = normalize_method(method);
// 6. Let parsedURL be the result of parsing url with settingsObject’s API base URL and settingsObject’s API URL character encoding.
- auto parsed_url = settings_object.responsible_document()->parse_url(url);
+ auto parsed_url = settings_object.api_base_url().complete_url(url);
// 7. If parsedURL is failure, then throw a "SyntaxError" DOMException.
if (!parsed_url.is_valid())