Explorar el Código

LibWeb: Add basic <object> element support

This patch implements a simple <object> element with fallback content.
If the URL from the data attribute fails to load (including 404),
we render the DOM tree inside the <object> as fallback content.

This works by generating a different layout tree for the <object>
depending on the state and success of the data load. Since we cannot
currently do incremental layout tree updates, we have to force a
complete layout tree rebuild when the resource load finishes/fails.
Andreas Kling hace 5 años
padre
commit
3cc0c477db

+ 2 - 0
Libraries/LibWeb/CMakeLists.txt

@@ -52,6 +52,7 @@ set(SOURCES
     DOM/HTMLIFrameElement.cpp
     DOM/HTMLIFrameElement.cpp
     DOM/HTMLImageElement.cpp
     DOM/HTMLImageElement.cpp
     DOM/HTMLInputElement.cpp
     DOM/HTMLInputElement.cpp
+    DOM/HTMLObjectElement.cpp
     DOM/HTMLLinkElement.cpp
     DOM/HTMLLinkElement.cpp
     DOM/HTMLScriptElement.cpp
     DOM/HTMLScriptElement.cpp
     DOM/HTMLStyleElement.cpp
     DOM/HTMLStyleElement.cpp
@@ -95,6 +96,7 @@ set(SOURCES
     Layout/LineBoxFragment.cpp
     Layout/LineBoxFragment.cpp
     LayoutTreeModel.cpp
     LayoutTreeModel.cpp
     Loader/FrameLoader.cpp
     Loader/FrameLoader.cpp
+    Loader/ImageLoader.cpp
     Loader/ImageResource.cpp
     Loader/ImageResource.cpp
     Loader/Resource.cpp
     Loader/Resource.cpp
     Loader/ResourceLoader.cpp
     Loader/ResourceLoader.cpp

+ 2 - 1
Libraries/LibWeb/DOM/Element.h

@@ -79,9 +79,10 @@ public:
     String inner_html() const;
     String inner_html() const;
     void set_inner_html(StringView);
     void set_inner_html(StringView);
 
 
-private:
+protected:
     RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
     RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
 
 
+private:
     Attribute* find_attribute(const FlyString& name);
     Attribute* find_attribute(const FlyString& name);
     const Attribute* find_attribute(const FlyString& name) const;
     const Attribute* find_attribute(const FlyString& name) const;
 
 

+ 3 - 0
Libraries/LibWeb/DOM/ElementFactory.cpp

@@ -40,6 +40,7 @@
 #include <LibWeb/DOM/HTMLImageElement.h>
 #include <LibWeb/DOM/HTMLImageElement.h>
 #include <LibWeb/DOM/HTMLInputElement.h>
 #include <LibWeb/DOM/HTMLInputElement.h>
 #include <LibWeb/DOM/HTMLLinkElement.h>
 #include <LibWeb/DOM/HTMLLinkElement.h>
+#include <LibWeb/DOM/HTMLObjectElement.h>
 #include <LibWeb/DOM/HTMLScriptElement.h>
 #include <LibWeb/DOM/HTMLScriptElement.h>
 #include <LibWeb/DOM/HTMLStyleElement.h>
 #include <LibWeb/DOM/HTMLStyleElement.h>
 #include <LibWeb/DOM/HTMLTableCellElement.h>
 #include <LibWeb/DOM/HTMLTableCellElement.h>
@@ -94,6 +95,8 @@ NonnullRefPtr<Element> create_element(Document& document, const FlyString& tag_n
         return adopt(*new HTMLScriptElement(document, lowercase_tag_name));
         return adopt(*new HTMLScriptElement(document, lowercase_tag_name));
     if (lowercase_tag_name == HTML::TagNames::canvas)
     if (lowercase_tag_name == HTML::TagNames::canvas)
         return adopt(*new HTMLCanvasElement(document, lowercase_tag_name));
         return adopt(*new HTMLCanvasElement(document, lowercase_tag_name));
+    if (lowercase_tag_name == HTML::TagNames::object)
+        return adopt(*new HTMLObjectElement(document, lowercase_tag_name));
     return adopt(*new Element(document, lowercase_tag_name));
     return adopt(*new Element(document, lowercase_tag_name));
 }
 }
 
 

+ 78 - 0
Libraries/LibWeb/DOM/HTMLObjectElement.cpp

@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibGfx/Bitmap.h>
+#include <LibGfx/ImageDecoder.h>
+#include <LibWeb/CSS/StyleResolver.h>
+#include <LibWeb/DOM/Document.h>
+#include <LibWeb/DOM/Event.h>
+#include <LibWeb/DOM/HTMLObjectElement.h>
+#include <LibWeb/Layout/LayoutImage.h>
+#include <LibWeb/Loader/ResourceLoader.h>
+
+namespace Web {
+
+HTMLObjectElement::HTMLObjectElement(Document& document, const FlyString& tag_name)
+    : HTMLElement(document, tag_name)
+{
+    m_image_loader.on_load = [this] {
+        m_should_show_fallback_content = false;
+        this->document().force_layout();
+    };
+
+    m_image_loader.on_fail = [this] {
+        m_should_show_fallback_content = true;
+        this->document().force_layout();
+    };
+}
+
+HTMLObjectElement::~HTMLObjectElement()
+{
+}
+
+void HTMLObjectElement::parse_attribute(const FlyString& name, const String& value)
+{
+    HTMLElement::parse_attribute(name, value);
+
+    if (name == HTML::AttributeNames::data)
+        m_image_loader.load(document().complete_url(value));
+}
+
+RefPtr<LayoutNode> HTMLObjectElement::create_layout_node(const StyleProperties* parent_style) const
+{
+    if (m_should_show_fallback_content)
+        return HTMLElement::create_layout_node(parent_style);
+
+    auto style = document().style_resolver().resolve_style(*this, parent_style);
+    auto display = style->string_or_fallback(CSS::PropertyID::Display, "inline");
+    if (display == "none")
+        return nullptr;
+    if (m_image_loader.image_decoder())
+        return adopt(*new LayoutImage(*this, move(style), m_image_loader));
+    return nullptr;
+}
+
+}

+ 61 - 0
Libraries/LibWeb/DOM/HTMLObjectElement.h

@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibCore/Forward.h>
+#include <LibGfx/Forward.h>
+#include <LibWeb/DOM/HTMLElement.h>
+#include <LibWeb/Loader/ImageLoader.h>
+
+namespace Web {
+
+class LayoutDocument;
+
+class HTMLObjectElement final : public HTMLElement {
+public:
+    HTMLObjectElement(Document&, const FlyString& tag_name);
+    virtual ~HTMLObjectElement() override;
+
+    virtual void parse_attribute(const FlyString& name, const String& value) override;
+
+    String data() const { return attribute(HTML::AttributeNames::data); }
+    String type() const { return attribute(HTML::AttributeNames::type); }
+
+private:
+    virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
+
+    ImageLoader m_image_loader;
+    bool m_should_show_fallback_content { false };
+};
+
+template<>
+inline bool is<HTMLObjectElement>(const Node& node)
+{
+    return is<Element>(node) && to<Element>(node).tag_name() == HTML::TagNames::object;
+}
+
+}