summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Wilde <lukew@serenityos.org>2023-02-28 00:23:53 +0000
committerAndreas Kling <kling@serenityos.org>2023-02-28 12:36:14 +0100
commit4d0277cd9a338d8fe29db8521ce0e632cae1ae1d (patch)
treec4d4515cea3e17eb2c5d3c6d1e3f3cdba8f92042
parent5e422bdae03f1287e5ea3d7af80794e8aa25c919 (diff)
downloadserenity-4d0277cd9a338d8fe29db8521ce0e632cae1ae1d.zip
LibWeb: Implement navigator.{plugins,mimeTypes}
-rw-r--r--Userland/Libraries/LibWeb/CMakeLists.txt4
-rw-r--r--Userland/Libraries/LibWeb/Forward.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/MimeType.cpp65
-rw-r--r--Userland/Libraries/LibWeb/HTML/MimeType.h34
-rw-r--r--Userland/Libraries/LibWeb/HTML/MimeType.idl9
-rw-r--r--Userland/Libraries/LibWeb/HTML/MimeTypeArray.cpp112
-rw-r--r--Userland/Libraries/LibWeb/HTML/MimeTypeArray.h48
-rw-r--r--Userland/Libraries/LibWeb/HTML/MimeTypeArray.idl8
-rw-r--r--Userland/Libraries/LibWeb/HTML/Navigator.cpp23
-rw-r--r--Userland/Libraries/LibWeb/HTML/Navigator.h12
-rw-r--r--Userland/Libraries/LibWeb/HTML/Navigator.idl6
-rw-r--r--Userland/Libraries/LibWeb/HTML/Plugin.cpp135
-rw-r--r--Userland/Libraries/LibWeb/HTML/Plugin.h54
-rw-r--r--Userland/Libraries/LibWeb/HTML/Plugin.idl11
-rw-r--r--Userland/Libraries/LibWeb/HTML/PluginArray.cpp121
-rw-r--r--Userland/Libraries/LibWeb/HTML/PluginArray.h49
-rw-r--r--Userland/Libraries/LibWeb/HTML/PluginArray.idl9
-rw-r--r--Userland/Libraries/LibWeb/HTML/Window.cpp52
-rw-r--r--Userland/Libraries/LibWeb/HTML/Window.h11
-rw-r--r--Userland/Libraries/LibWeb/idl_files.cmake4
20 files changed, 767 insertions, 4 deletions
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt
index e2474811a0..105d2418e0 100644
--- a/Userland/Libraries/LibWeb/CMakeLists.txt
+++ b/Userland/Libraries/LibWeb/CMakeLists.txt
@@ -270,6 +270,8 @@ set(SOURCES
HTML/MessageChannel.cpp
HTML/MessageEvent.cpp
HTML/MessagePort.cpp
+ HTML/MimeType.cpp
+ HTML/MimeTypeArray.cpp
HTML/Navigator.cpp
HTML/NavigatorID.cpp
HTML/PageTransitionEvent.cpp
@@ -281,6 +283,8 @@ set(SOURCES
HTML/Parser/ListOfActiveFormattingElements.cpp
HTML/Parser/StackOfOpenElements.cpp
HTML/Path2D.cpp
+ HTML/Plugin.cpp
+ HTML/PluginArray.cpp
HTML/PromiseRejectionEvent.cpp
HTML/Scripting/ClassicScript.cpp
HTML/Scripting/Environments.cpp
diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h
index e9a9301129..243c34e27f 100644
--- a/Userland/Libraries/LibWeb/Forward.h
+++ b/Userland/Libraries/LibWeb/Forward.h
@@ -328,11 +328,15 @@ class Location;
class MessageChannel;
class MessageEvent;
class MessagePort;
+class MimeType;
+class MimeTypeArray;
struct NavigationParams;
class Navigator;
class Origin;
class PageTransitionEvent;
class Path2D;
+class Plugin;
+class PluginArray;
struct PolicyContainer;
class PromiseRejectionEvent;
class WorkerDebugConsoleClient;
diff --git a/Userland/Libraries/LibWeb/HTML/MimeType.cpp b/Userland/Libraries/LibWeb/HTML/MimeType.cpp
new file mode 100644
index 0000000000..30e20dfc36
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/MimeType.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibWeb/Bindings/Intrinsics.h>
+#include <LibWeb/HTML/MimeType.h>
+#include <LibWeb/HTML/Scripting/Environments.h>
+#include <LibWeb/HTML/Window.h>
+
+namespace Web::HTML {
+
+MimeType::MimeType(JS::Realm& realm, String const& type)
+ : Bindings::PlatformObject(realm)
+ , m_type(type)
+{
+}
+
+MimeType::~MimeType() = default;
+
+JS::ThrowCompletionOr<void> MimeType::initialize(JS::Realm& realm)
+{
+ MUST_OR_THROW_OOM(Base::initialize(realm));
+ set_prototype(&Bindings::ensure_web_prototype<Bindings::MimeTypePrototype>(realm, "MimeType"));
+
+ return {};
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#concept-mimetype-type
+String const& MimeType::type() const
+{
+ // The MimeType interface's type getter steps are to return this's type.
+ return m_type;
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#dom-mimetype-description
+JS::ThrowCompletionOr<String> MimeType::description() const
+{
+ // The MimeType interface's description getter steps are to return "Portable Document Format".
+ static String description_string = TRY_OR_THROW_OOM(vm(), String::from_utf8("Portable Document Format"sv));
+ return description_string;
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#dom-mimetype-suffixes
+String const& MimeType::suffixes() const
+{
+ // The MimeType interface's suffixes getter steps are to return "pdf".
+ static String suffixes_string = String::from_utf8_short_string("pdf"sv);
+ return suffixes_string;
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#dom-mimetype-enabledplugin
+JS::NonnullGCPtr<Plugin> MimeType::enabled_plugin() const
+{
+ // The MimeType interface's enabledPlugin getter steps are to return this's relevant global object's PDF viewer plugin objects[0] (i.e., the generic "PDF Viewer" one).
+ auto& window = verify_cast<HTML::Window>(HTML::relevant_global_object(*this));
+ auto plugin_objects = window.pdf_viewer_plugin_objects();
+
+ // NOTE: If a MimeType object was created, that means PDF viewer support is enabled, meaning there will be Plugin objects.
+ VERIFY(!plugin_objects.is_empty());
+ return plugin_objects.first();
+}
+
+}
diff --git a/Userland/Libraries/LibWeb/HTML/MimeType.h b/Userland/Libraries/LibWeb/HTML/MimeType.h
new file mode 100644
index 0000000000..859e15dbf6
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/MimeType.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibWeb/Bindings/LegacyPlatformObject.h>
+
+namespace Web::HTML {
+
+// https://html.spec.whatwg.org/multipage/system-state.html#mimetype
+class MimeType : public Bindings::PlatformObject {
+ WEB_PLATFORM_OBJECT(MimeType, Bindings::PlatformObject);
+
+public:
+ virtual ~MimeType() override;
+
+ String const& type() const;
+ JS::ThrowCompletionOr<String> description() const;
+ String const& suffixes() const;
+ JS::NonnullGCPtr<Plugin> enabled_plugin() const;
+
+private:
+ MimeType(JS::Realm&, String const& type);
+
+ virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
+
+ // https://html.spec.whatwg.org/multipage/system-state.html#concept-mimetype-type
+ String m_type;
+};
+
+}
diff --git a/Userland/Libraries/LibWeb/HTML/MimeType.idl b/Userland/Libraries/LibWeb/HTML/MimeType.idl
new file mode 100644
index 0000000000..f5c4b26ccc
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/MimeType.idl
@@ -0,0 +1,9 @@
+#import <HTML/Plugin.idl>
+
+[Exposed=Window, UseNewAKString]
+interface MimeType {
+ readonly attribute DOMString type;
+ readonly attribute DOMString description;
+ readonly attribute DOMString suffixes;
+ readonly attribute Plugin enabledPlugin;
+};
diff --git a/Userland/Libraries/LibWeb/HTML/MimeTypeArray.cpp b/Userland/Libraries/LibWeb/HTML/MimeTypeArray.cpp
new file mode 100644
index 0000000000..7e9a823d54
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/MimeTypeArray.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibWeb/Bindings/Intrinsics.h>
+#include <LibWeb/HTML/MimeTypeArray.h>
+#include <LibWeb/HTML/Scripting/Environments.h>
+#include <LibWeb/HTML/Window.h>
+#include <LibWeb/Page/Page.h>
+
+namespace Web::HTML {
+
+MimeTypeArray::MimeTypeArray(JS::Realm& realm)
+ : Bindings::LegacyPlatformObject(realm)
+{
+}
+
+MimeTypeArray::~MimeTypeArray() = default;
+
+JS::ThrowCompletionOr<void> MimeTypeArray::initialize(JS::Realm& realm)
+{
+ MUST_OR_THROW_OOM(Base::initialize(realm));
+ set_prototype(&Bindings::ensure_web_prototype<Bindings::MimeTypeArrayPrototype>(realm, "MimeTypeArray"));
+
+ return {};
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewing-support:support-named-properties-2
+Vector<DeprecatedString> MimeTypeArray::supported_property_names() const
+{
+ // The MimeTypeArray interface supports named properties. If the user agent's PDF viewer supported is true, then they are the PDF viewer mime types. Otherwise, they are the empty list.
+ auto const& window = verify_cast<HTML::Window>(HTML::relevant_global_object(*this));
+ VERIFY(window.page());
+ if (!window.page()->pdf_viewer_supported())
+ return {};
+
+ // https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewer-mime-types
+ static Vector<DeprecatedString> mime_types = {
+ "application/pdf"sv,
+ "text/pdf"sv,
+ };
+
+ return mime_types;
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewing-support:supports-indexed-properties-2
+bool MimeTypeArray::is_supported_property_index(u32 index) const
+{
+ // The MimeTypeArray interface supports indexed properties. The supported property indices are the indices of this's relevant global object's PDF viewer mime type objects.
+ auto& window = verify_cast<HTML::Window>(HTML::relevant_global_object(*this));
+ return index < window.pdf_viewer_mime_type_objects().size();
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#dom-mimetypearray-length
+size_t MimeTypeArray::length() const
+{
+ // The MimeTypeArray interface's length getter steps are to return this's relevant global object's PDF viewer mime type objects's size.
+ auto& window = verify_cast<HTML::Window>(HTML::relevant_global_object(*this));
+ return window.pdf_viewer_mime_type_objects().size();
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#dom-mimetypearray-item
+JS::GCPtr<MimeType> MimeTypeArray::item(u32 index) const
+{
+ // 1. Let mimeTypes be this's relevant global object's PDF viewer mime type objects.
+ auto& window = verify_cast<HTML::Window>(HTML::relevant_global_object(*this));
+ auto mime_types = window.pdf_viewer_mime_type_objects();
+
+ // 2. If index < mimeType's size, then return mimeTypes[index].
+ if (index < mime_types.size())
+ return mime_types[index];
+
+ // 3. Return null.
+ return nullptr;
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#dom-mimetypearray-nameditem
+JS::GCPtr<MimeType> MimeTypeArray::named_item(String const& name) const
+{
+ // 1. For each MimeType mimeType of this's relevant global object's PDF viewer mime type objects: if mimeType's type is name, then return mimeType.
+ auto& window = verify_cast<HTML::Window>(HTML::relevant_global_object(*this));
+ auto mime_types = window.pdf_viewer_mime_type_objects();
+
+ for (auto& mime_type : mime_types) {
+ if (mime_type->type() == name)
+ return mime_type;
+ }
+
+ // 2. Return null.
+ return nullptr;
+}
+
+WebIDL::ExceptionOr<JS::Value> MimeTypeArray::item_value(size_t index) const
+{
+ auto return_value = item(index);
+ if (!return_value)
+ return JS::js_null();
+ return return_value.ptr();
+}
+
+WebIDL::ExceptionOr<JS::Value> MimeTypeArray::named_item_value(DeprecatedFlyString const& name) const
+{
+ auto converted_name = TRY_OR_THROW_OOM(vm(), String::from_deprecated_string(name));
+ auto return_value = named_item(converted_name);
+ if (!return_value)
+ return JS::js_null();
+ return return_value.ptr();
+}
+
+}
diff --git a/Userland/Libraries/LibWeb/HTML/MimeTypeArray.h b/Userland/Libraries/LibWeb/HTML/MimeTypeArray.h
new file mode 100644
index 0000000000..368c13f46b
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/MimeTypeArray.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibWeb/Bindings/LegacyPlatformObject.h>
+
+namespace Web::HTML {
+
+// https://html.spec.whatwg.org/multipage/system-state.html#mimetypearray
+class MimeTypeArray : public Bindings::LegacyPlatformObject {
+ WEB_PLATFORM_OBJECT(MimeTypeArray, Bindings::LegacyPlatformObject);
+
+public:
+ virtual ~MimeTypeArray() override;
+
+ size_t length() const;
+ JS::GCPtr<MimeType> item(u32 index) const;
+ JS::GCPtr<MimeType> named_item(String const& name) const;
+
+private:
+ MimeTypeArray(JS::Realm&);
+
+ virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
+
+ // ^Bindings::LegacyPlatformObject
+ virtual Vector<DeprecatedString> supported_property_names() const override;
+ virtual WebIDL::ExceptionOr<JS::Value> item_value(size_t index) const override;
+ virtual WebIDL::ExceptionOr<JS::Value> named_item_value(DeprecatedFlyString const& name) const override;
+ virtual bool is_supported_property_index(u32) const override;
+
+ virtual bool supports_indexed_properties() const override { return true; }
+ virtual bool supports_named_properties() const override { return true; }
+ virtual bool has_indexed_property_setter() const override { return false; }
+ virtual bool has_named_property_setter() const override { return false; }
+ virtual bool has_named_property_deleter() const override { return false; }
+ virtual bool has_legacy_override_built_ins_interface_extended_attribute() const override { return false; }
+ virtual bool has_legacy_unenumerable_named_properties_interface_extended_attribute() const override { return true; }
+ virtual bool has_global_interface_extended_attribute() const override { return false; }
+ virtual bool indexed_property_setter_has_identifier() const override { return false; }
+ virtual bool named_property_setter_has_identifier() const override { return false; }
+ virtual bool named_property_deleter_has_identifier() const override { return false; }
+};
+
+}
diff --git a/Userland/Libraries/LibWeb/HTML/MimeTypeArray.idl b/Userland/Libraries/LibWeb/HTML/MimeTypeArray.idl
new file mode 100644
index 0000000000..80a5149ecb
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/MimeTypeArray.idl
@@ -0,0 +1,8 @@
+#import <HTML/MimeType.idl>
+
+[Exposed=Window, LegacyUnenumerableNamedProperties, UseNewAKString]
+interface MimeTypeArray {
+ readonly attribute unsigned long length;
+ getter MimeType? item(unsigned long index);
+ getter MimeType? namedItem(DOMString name);
+};
diff --git a/Userland/Libraries/LibWeb/HTML/Navigator.cpp b/Userland/Libraries/LibWeb/HTML/Navigator.cpp
index 67c8fb36af..4f538b5ed3 100644
--- a/Userland/Libraries/LibWeb/HTML/Navigator.cpp
+++ b/Userland/Libraries/LibWeb/HTML/Navigator.cpp
@@ -39,7 +39,7 @@ JS::ThrowCompletionOr<void> Navigator::initialize(JS::Realm& realm)
bool Navigator::pdf_viewer_enabled() const
{
// The NavigatorPlugins mixin's pdfViewerEnabled getter steps are to return the user agent's PDF viewer supported.
- // NOTE: THe NavigatorPlugins mixin should only be exposed on the Window object.
+ // NOTE: The NavigatorPlugins mixin should only be exposed on the Window object.
auto const& window = verify_cast<HTML::Window>(HTML::current_global_object());
return window.page()->pdf_viewer_supported();
}
@@ -54,4 +54,25 @@ bool Navigator::webdriver() const
return window.page()->is_webdriver_active();
}
+void Navigator::visit_edges(Cell::Visitor& visitor)
+{
+ Base::visit_edges(visitor);
+ visitor.visit(m_mime_type_array);
+ visitor.visit(m_plugin_array);
+}
+
+JS::ThrowCompletionOr<JS::NonnullGCPtr<MimeTypeArray>> Navigator::mime_types()
+{
+ if (!m_mime_type_array)
+ m_mime_type_array = TRY(heap().allocate<MimeTypeArray>(realm(), realm()));
+ return *m_mime_type_array;
+}
+
+JS::ThrowCompletionOr<JS::NonnullGCPtr<PluginArray>> Navigator::plugins()
+{
+ if (!m_plugin_array)
+ m_plugin_array = TRY(heap().allocate<PluginArray>(realm(), realm()));
+ return *m_plugin_array;
+}
+
}
diff --git a/Userland/Libraries/LibWeb/HTML/Navigator.h b/Userland/Libraries/LibWeb/HTML/Navigator.h
index 9d6123e5ff..0bb2332cf6 100644
--- a/Userland/Libraries/LibWeb/HTML/Navigator.h
+++ b/Userland/Libraries/LibWeb/HTML/Navigator.h
@@ -7,10 +7,12 @@
#pragma once
#include <LibWeb/Bindings/PlatformObject.h>
+#include <LibWeb/HTML/MimeTypeArray.h>
#include <LibWeb/HTML/NavigatorConcurrentHardware.h>
#include <LibWeb/HTML/NavigatorID.h>
#include <LibWeb/HTML/NavigatorLanguage.h>
#include <LibWeb/HTML/NavigatorOnLine.h>
+#include <LibWeb/HTML/PluginArray.h>
namespace Web::HTML {
@@ -35,17 +37,25 @@ public:
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-javaenabled
bool java_enabled() const { return false; }
- // https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-pdfviewerenabled
bool pdf_viewer_enabled() const;
bool webdriver() const;
+ JS::ThrowCompletionOr<JS::NonnullGCPtr<MimeTypeArray>> mime_types();
+ JS::ThrowCompletionOr<JS::NonnullGCPtr<PluginArray>> plugins();
+
virtual ~Navigator() override;
+protected:
+ virtual void visit_edges(Cell::Visitor&) override;
+
private:
explicit Navigator(JS::Realm&);
virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
+
+ JS::GCPtr<PluginArray> m_plugin_array;
+ JS::GCPtr<MimeTypeArray> m_mime_type_array;
};
}
diff --git a/Userland/Libraries/LibWeb/HTML/Navigator.idl b/Userland/Libraries/LibWeb/HTML/Navigator.idl
index 7d81a2cf40..4a96de9969 100644
--- a/Userland/Libraries/LibWeb/HTML/Navigator.idl
+++ b/Userland/Libraries/LibWeb/HTML/Navigator.idl
@@ -1,7 +1,9 @@
+#import <HTML/MimeTypeArray.idl>
#import <HTML/NavigatorID.idl>
#import <HTML/NavigatorLanguage.idl>
#import <HTML/NavigatorOnLine.idl>
#import <HTML/NavigatorConcurrentHardware.idl>
+#import <HTML/PluginArray.idl>
// https://html.spec.whatwg.org/multipage/system-state.html#navigator
[Exposed=Window]
@@ -25,8 +27,8 @@ interface mixin NavigatorCookies {
// https://html.spec.whatwg.org/multipage/system-state.html#navigatorplugins
interface mixin NavigatorPlugins {
- // FIXME: [SameObject] readonly attribute PluginArray plugins;
- // FIXME: [SameObject] readonly attribute MimeTypeArray mimeTypes;
+ [SameObject] readonly attribute PluginArray plugins;
+ [SameObject] readonly attribute MimeTypeArray mimeTypes;
boolean javaEnabled();
readonly attribute boolean pdfViewerEnabled;
};
diff --git a/Userland/Libraries/LibWeb/HTML/Plugin.cpp b/Userland/Libraries/LibWeb/HTML/Plugin.cpp
new file mode 100644
index 0000000000..4240a522c6
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/Plugin.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibWeb/Bindings/Intrinsics.h>
+#include <LibWeb/HTML/Plugin.h>
+#include <LibWeb/HTML/Scripting/Environments.h>
+#include <LibWeb/HTML/Window.h>
+#include <LibWeb/Page/Page.h>
+
+namespace Web::HTML {
+
+Plugin::Plugin(JS::Realm& realm, String const& name)
+ : Bindings::LegacyPlatformObject(realm)
+ , m_name(name)
+{
+}
+
+Plugin::~Plugin() = default;
+
+JS::ThrowCompletionOr<void> Plugin::initialize(JS::Realm& realm)
+{
+ MUST_OR_THROW_OOM(Base::initialize(realm));
+ set_prototype(&Bindings::ensure_web_prototype<Bindings::PluginPrototype>(realm, "Plugin"));
+
+ return {};
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#dom-plugin-name
+String const& Plugin::name() const
+{
+ // The Plugin interface's name getter steps are to return this's name.
+ return m_name;
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#dom-plugin-description
+JS::ThrowCompletionOr<String> Plugin::description() const
+{
+ // The Plugin interface's description getter steps are to return "Portable Document Format".
+ static String description_string = TRY_OR_THROW_OOM(vm(), String::from_utf8("Portable Document Format"sv));
+ return description_string;
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#dom-plugin-filename
+JS::ThrowCompletionOr<String> Plugin::filename() const
+{
+ // The Plugin interface's filename getter steps are to return "internal-pdf-viewer".
+ static String filename_string = TRY_OR_THROW_OOM(vm(), String::from_utf8("internal-pdf-viewer"sv));
+ return filename_string;
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewing-support:support-named-properties-3
+Vector<DeprecatedString> Plugin::supported_property_names() const
+{
+ // The Plugin interface supports named properties. If the user agent's PDF viewer supported is true, then they are the PDF viewer mime types. Otherwise, they are the empty list.
+ auto const& window = verify_cast<HTML::Window>(HTML::relevant_global_object(*this));
+ VERIFY(window.page());
+ if (!window.page()->pdf_viewer_supported())
+ return {};
+
+ // https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewer-mime-types
+ static Vector<DeprecatedString> mime_types = {
+ "application/pdf"sv,
+ "text/pdf"sv,
+ };
+
+ return mime_types;
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewing-support:supports-indexed-properties-3
+bool Plugin::is_supported_property_index(u32 index) const
+{
+ // The Plugin interface supports indexed properties. The supported property indices are the indices of this's relevant global object's PDF viewer mime type objects.
+ auto& window = verify_cast<HTML::Window>(HTML::relevant_global_object(*this));
+ return index < window.pdf_viewer_mime_type_objects().size();
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#dom-plugin-length
+size_t Plugin::length() const
+{
+ // The Plugin interface's length getter steps are to return this's relevant global object's PDF viewer mime type objects's size.
+ auto& window = verify_cast<HTML::Window>(HTML::relevant_global_object(*this));
+ return window.pdf_viewer_mime_type_objects().size();
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#dom-plugin-item
+JS::GCPtr<MimeType> Plugin::item(u32 index) const
+{
+ // 1. Let mimeTypes be this's relevant global object's PDF viewer mime type objects.
+ auto& window = verify_cast<HTML::Window>(HTML::relevant_global_object(*this));
+ auto mime_types = window.pdf_viewer_mime_type_objects();
+
+ // 2. If index < mimeType's size, then return mimeTypes[index].
+ if (index < mime_types.size())
+ return mime_types[index];
+
+ // 3. Return null.
+ return nullptr;
+}
+
+JS::GCPtr<MimeType> Plugin::named_item(String const& name) const
+{
+ // 1. For each MimeType mimeType of this's relevant global object's PDF viewer mime type objects: if mimeType's type is name, then return mimeType.
+ auto& window = verify_cast<HTML::Window>(HTML::relevant_global_object(*this));
+ auto mime_types = window.pdf_viewer_mime_type_objects();
+
+ for (auto& mime_type : mime_types) {
+ if (mime_type->type() == name)
+ return mime_type;
+ }
+
+ // 2. Return null.
+ return nullptr;
+}
+
+WebIDL::ExceptionOr<JS::Value> Plugin::item_value(size_t index) const
+{
+ auto return_value = item(index);
+ if (!return_value)
+ return JS::js_null();
+ return return_value.ptr();
+}
+
+WebIDL::ExceptionOr<JS::Value> Plugin::named_item_value(DeprecatedFlyString const& name) const
+{
+ auto converted_name = TRY_OR_THROW_OOM(vm(), String::from_deprecated_string(name));
+ auto return_value = named_item(converted_name);
+ if (!return_value)
+ return JS::js_null();
+ return return_value.ptr();
+}
+
+}
diff --git a/Userland/Libraries/LibWeb/HTML/Plugin.h b/Userland/Libraries/LibWeb/HTML/Plugin.h
new file mode 100644
index 0000000000..70bed1bae8
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/Plugin.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibWeb/Bindings/LegacyPlatformObject.h>
+
+namespace Web::HTML {
+
+// https://html.spec.whatwg.org/multipage/system-state.html#dom-plugin
+class Plugin : public Bindings::LegacyPlatformObject {
+ WEB_PLATFORM_OBJECT(Plugin, Bindings::LegacyPlatformObject);
+
+public:
+ virtual ~Plugin() override;
+
+ String const& name() const;
+ JS::ThrowCompletionOr<String> description() const;
+ JS::ThrowCompletionOr<String> filename() const;
+ size_t length() const;
+ JS::GCPtr<MimeType> item(u32 index) const;
+ JS::GCPtr<MimeType> named_item(String const& name) const;
+
+private:
+ Plugin(JS::Realm&, String const& name);
+
+ // https://html.spec.whatwg.org/multipage/system-state.html#concept-plugin-name
+ String m_name;
+
+ virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
+
+ // ^Bindings::LegacyPlatformObject
+ virtual Vector<DeprecatedString> supported_property_names() const override;
+ virtual WebIDL::ExceptionOr<JS::Value> item_value(size_t index) const override;
+ virtual WebIDL::ExceptionOr<JS::Value> named_item_value(DeprecatedFlyString const& name) const override;
+ virtual bool is_supported_property_index(u32) const override;
+
+ virtual bool supports_indexed_properties() const override { return true; }
+ virtual bool supports_named_properties() const override { return true; }
+ virtual bool has_indexed_property_setter() const override { return false; }
+ virtual bool has_named_property_setter() const override { return false; }
+ virtual bool has_named_property_deleter() const override { return false; }
+ virtual bool has_legacy_override_built_ins_interface_extended_attribute() const override { return false; }
+ virtual bool has_legacy_unenumerable_named_properties_interface_extended_attribute() const override { return true; }
+ virtual bool has_global_interface_extended_attribute() const override { return false; }
+ virtual bool indexed_property_setter_has_identifier() const override { return false; }
+ virtual bool named_property_setter_has_identifier() const override { return false; }
+ virtual bool named_property_deleter_has_identifier() const override { return false; }
+};
+
+}
diff --git a/Userland/Libraries/LibWeb/HTML/Plugin.idl b/Userland/Libraries/LibWeb/HTML/Plugin.idl
new file mode 100644
index 0000000000..b3d1591736
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/Plugin.idl
@@ -0,0 +1,11 @@
+#import <HTML/MimeType.idl>
+
+[Exposed=Window, LegacyUnenumerableNamedProperties, UseNewAKString]
+interface Plugin {
+ readonly attribute DOMString name;
+ readonly attribute DOMString description;
+ readonly attribute DOMString filename;
+ readonly attribute unsigned long length;
+ getter MimeType? item(unsigned long index);
+ getter MimeType? namedItem(DOMString name);
+};
diff --git a/Userland/Libraries/LibWeb/HTML/PluginArray.cpp b/Userland/Libraries/LibWeb/HTML/PluginArray.cpp
new file mode 100644
index 0000000000..c60699f47e
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/PluginArray.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibWeb/Bindings/Intrinsics.h>
+#include <LibWeb/HTML/PluginArray.h>
+#include <LibWeb/HTML/Scripting/Environments.h>
+#include <LibWeb/HTML/Window.h>
+#include <LibWeb/Page/Page.h>
+
+namespace Web::HTML {
+
+PluginArray::PluginArray(JS::Realm& realm)
+ : Bindings::LegacyPlatformObject(realm)
+{
+}
+
+PluginArray::~PluginArray() = default;
+
+JS::ThrowCompletionOr<void> PluginArray::initialize(JS::Realm& realm)
+{
+ MUST_OR_THROW_OOM(Base::initialize(realm));
+ set_prototype(&Bindings::ensure_web_prototype<Bindings::PluginArrayPrototype>(realm, "PluginArray"));
+
+ return {};
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#dom-pluginarray-refresh
+void PluginArray::refresh() const
+{
+ // The PluginArray interface's refresh() method steps are to do nothing.
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewing-support:support-named-properties
+Vector<DeprecatedString> PluginArray::supported_property_names() const
+{
+ // The PluginArray interface supports named properties. If the user agent's PDF viewer supported is true, then they are the PDF viewer plugin names. Otherwise, they are the empty list.
+ auto const& window = verify_cast<HTML::Window>(HTML::relevant_global_object(*this));
+ VERIFY(window.page());
+ if (!window.page()->pdf_viewer_supported())
+ return {};
+
+ // https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewer-plugin-names
+ static Vector<DeprecatedString> plugin_names = {
+ "PDF Viewer"sv,
+ "Chrome PDF Viewer"sv,
+ "Chromium PDF Viewer"sv,
+ "Microsoft Edge PDF Viewer"sv,
+ "WebKit built-in PDF"sv,
+ };
+
+ return plugin_names;
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewing-support:supports-indexed-properties
+bool PluginArray::is_supported_property_index(u32 index) const
+{
+ // The PluginArray interface supports indexed properties. The supported property indices are the indices of this's relevant global object's PDF viewer plugin objects.
+ auto& window = verify_cast<HTML::Window>(HTML::relevant_global_object(*this));
+ return index < window.pdf_viewer_plugin_objects().size();
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#dom-pluginarray-length
+size_t PluginArray::length() const
+{
+ // The PluginArray interface's length getter steps are to return this's relevant global object's PDF viewer plugin objects's size.
+ auto& window = verify_cast<HTML::Window>(HTML::relevant_global_object(*this));
+ return window.pdf_viewer_plugin_objects().size();
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#dom-pluginarray-item
+JS::GCPtr<Plugin> PluginArray::item(u32 index) const
+{
+ // 1. Let plugins be this's relevant global object's PDF viewer plugin objects.
+ auto& window = verify_cast<HTML::Window>(HTML::relevant_global_object(*this));
+ auto plugins = window.pdf_viewer_plugin_objects();
+
+ // 2. If index < plugins's size, then return plugins[index].
+ if (index < plugins.size())
+ return plugins[index];
+
+ // 3. Return null.
+ return nullptr;
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#dom-pluginarray-nameditem
+JS::GCPtr<Plugin> PluginArray::named_item(String const& name) const
+{
+ // 1. For each Plugin plugin of this's relevant global object's PDF viewer plugin objects: if plugin's name is name, then return plugin.
+ auto& window = verify_cast<HTML::Window>(HTML::relevant_global_object(*this));
+ auto plugins = window.pdf_viewer_plugin_objects();
+
+ for (auto& plugin : plugins) {
+ if (plugin->name() == name)
+ return plugin;
+ }
+
+ // 2. Return null.
+ return nullptr;
+}
+
+WebIDL::ExceptionOr<JS::Value> PluginArray::item_value(size_t index) const
+{
+ auto return_value = item(index);
+ if (!return_value)
+ return JS::js_null();
+ return return_value.ptr();
+}
+
+WebIDL::ExceptionOr<JS::Value> PluginArray::named_item_value(DeprecatedFlyString const& name) const
+{
+ auto converted_name = TRY_OR_THROW_OOM(vm(), String::from_deprecated_string(name));
+ auto return_value = named_item(converted_name);
+ if (!return_value)
+ return JS::js_null();
+ return return_value.ptr();
+}
+
+}
diff --git a/Userland/Libraries/LibWeb/HTML/PluginArray.h b/Userland/Libraries/LibWeb/HTML/PluginArray.h
new file mode 100644
index 0000000000..f9c447e363
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/PluginArray.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibWeb/Bindings/LegacyPlatformObject.h>
+
+namespace Web::HTML {
+
+// https://html.spec.whatwg.org/multipage/system-state.html#pluginarray
+class PluginArray : public Bindings::LegacyPlatformObject {
+ WEB_PLATFORM_OBJECT(PluginArray, Bindings::LegacyPlatformObject);
+
+public:
+ virtual ~PluginArray() override;
+
+ void refresh() const;
+ size_t length() const;
+ JS::GCPtr<Plugin> item(u32 index) const;
+ JS::GCPtr<Plugin> named_item(String const& name) const;
+
+private:
+ PluginArray(JS::Realm&);
+
+ virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
+
+ // ^Bindings::LegacyPlatformObject
+ virtual Vector<DeprecatedString> supported_property_names() const override;
+ virtual WebIDL::ExceptionOr<JS::Value> item_value(size_t index) const override;
+ virtual WebIDL::ExceptionOr<JS::Value> named_item_value(DeprecatedFlyString const& name) const override;
+ virtual bool is_supported_property_index(u32) const override;
+
+ virtual bool supports_indexed_properties() const override { return true; }
+ virtual bool supports_named_properties() const override { return true; }
+ virtual bool has_indexed_property_setter() const override { return false; }
+ virtual bool has_named_property_setter() const override { return false; }
+ virtual bool has_named_property_deleter() const override { return false; }
+ virtual bool has_legacy_override_built_ins_interface_extended_attribute() const override { return false; }
+ virtual bool has_legacy_unenumerable_named_properties_interface_extended_attribute() const override { return true; }
+ virtual bool has_global_interface_extended_attribute() const override { return false; }
+ virtual bool indexed_property_setter_has_identifier() const override { return false; }
+ virtual bool named_property_setter_has_identifier() const override { return false; }
+ virtual bool named_property_deleter_has_identifier() const override { return false; }
+};
+
+}
diff --git a/Userland/Libraries/LibWeb/HTML/PluginArray.idl b/Userland/Libraries/LibWeb/HTML/PluginArray.idl
new file mode 100644
index 0000000000..064ba80601
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/PluginArray.idl
@@ -0,0 +1,9 @@
+#import <HTML/Plugin.idl>
+
+[Exposed=Window, LegacyUnenumerableNamedProperties, UseNewAKString]
+interface PluginArray {
+ undefined refresh();
+ readonly attribute unsigned long length;
+ getter Plugin? item(unsigned long index);
+ getter Plugin? namedItem(DOMString name);
+};
diff --git a/Userland/Libraries/LibWeb/HTML/Window.cpp b/Userland/Libraries/LibWeb/HTML/Window.cpp
index acd0364e23..3507a81b3f 100644
--- a/Userland/Libraries/LibWeb/HTML/Window.cpp
+++ b/Userland/Libraries/LibWeb/HTML/Window.cpp
@@ -108,6 +108,10 @@ void Window::visit_edges(JS::Cell::Visitor& visitor)
visitor.visit(m_navigator);
for (auto& it : m_timers)
visitor.visit(it.value.ptr());
+ for (auto& plugin_object : m_pdf_viewer_plugin_objects)
+ visitor.visit(plugin_object);
+ for (auto& mime_type_object : m_pdf_viewer_mime_type_objects)
+ visitor.visit(mime_type_object);
}
Window::~Window() = default;
@@ -1060,6 +1064,54 @@ HTML::BrowsingContext* Window::browsing_context()
return m_associated_document->browsing_context();
}
+// https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewer-plugin-objects
+Vector<JS::NonnullGCPtr<Plugin>> Window::pdf_viewer_plugin_objects()
+{
+ // Each Window object has a PDF viewer plugin objects list. If the user agent's PDF viewer supported is false, then it is the empty list.
+ // Otherwise, it is a list containing five Plugin objects, whose names are, respectively:
+ // 0. "PDF Viewer"
+ // 1. "Chrome PDF Viewer"
+ // 2. "Chromium PDF Viewer"
+ // 3. "Microsoft Edge PDF Viewer"
+ // 4. "WebKit built-in PDF"
+ // The values of the above list form the PDF viewer plugin names list. https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewer-plugin-names
+ VERIFY(page());
+ if (!page()->pdf_viewer_supported())
+ return {};
+
+ if (m_pdf_viewer_plugin_objects.is_empty()) {
+ // FIXME: Remove the MUSTs and propagate the errors instead.
+ m_pdf_viewer_plugin_objects.append(realm().heap().allocate<Plugin>(realm(), realm(), MUST(String::from_utf8("PDF Viewer"sv))).release_allocated_value_but_fixme_should_propagate_errors());
+ m_pdf_viewer_plugin_objects.append(realm().heap().allocate<Plugin>(realm(), realm(), MUST(String::from_utf8("Chrome PDF Viewer"sv))).release_allocated_value_but_fixme_should_propagate_errors());
+ m_pdf_viewer_plugin_objects.append(realm().heap().allocate<Plugin>(realm(), realm(), MUST(String::from_utf8("Chromium PDF Viewer"sv))).release_allocated_value_but_fixme_should_propagate_errors());
+ m_pdf_viewer_plugin_objects.append(realm().heap().allocate<Plugin>(realm(), realm(), MUST(String::from_utf8("Microsoft Edge PDF Viewer"sv))).release_allocated_value_but_fixme_should_propagate_errors());
+ m_pdf_viewer_plugin_objects.append(realm().heap().allocate<Plugin>(realm(), realm(), MUST(String::from_utf8("WebKit built-in PDF"sv))).release_allocated_value_but_fixme_should_propagate_errors());
+ }
+
+ return m_pdf_viewer_plugin_objects;
+}
+
+// https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewer-mime-type-objects
+Vector<JS::NonnullGCPtr<MimeType>> Window::pdf_viewer_mime_type_objects()
+{
+ // Each Window object has a PDF viewer mime type objects list. If the user agent's PDF viewer supported is false, then it is the empty list.
+ // Otherwise, it is a list containing two MimeType objects, whose types are, respectively:
+ // 0. "application/pdf"
+ // 1. "text/pdf"
+ // The values of the above list form the PDF viewer mime types list. https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewer-mime-types
+ VERIFY(page());
+ if (!page()->pdf_viewer_supported())
+ return {};
+
+ if (m_pdf_viewer_mime_type_objects.is_empty()) {
+ // FIXME: Remove the MUSTs and propagate the errors instead.
+ m_pdf_viewer_mime_type_objects.append(realm().heap().allocate<MimeType>(realm(), realm(), MUST(String::from_utf8("application/pdf"sv))).release_allocated_value_but_fixme_should_propagate_errors());
+ m_pdf_viewer_mime_type_objects.append(realm().heap().allocate<MimeType>(realm(), realm(), MUST(String::from_utf8("text/pdf"sv))).release_allocated_value_but_fixme_should_propagate_errors());
+ }
+
+ return m_pdf_viewer_mime_type_objects;
+}
+
void Window::initialize_web_interfaces(Badge<WindowEnvironmentSettingsObject>)
{
auto& realm = this->realm();
diff --git a/Userland/Libraries/LibWeb/HTML/Window.h b/Userland/Libraries/LibWeb/HTML/Window.h
index 9a1d8c85da..42d88fb31b 100644
--- a/Userland/Libraries/LibWeb/HTML/Window.h
+++ b/Userland/Libraries/LibWeb/HTML/Window.h
@@ -20,6 +20,8 @@
#include <LibWeb/HTML/AnimationFrameCallbackDriver.h>
#include <LibWeb/HTML/CrossOrigin/CrossOriginPropertyDescriptorMap.h>
#include <LibWeb/HTML/GlobalEventHandlers.h>
+#include <LibWeb/HTML/MimeType.h>
+#include <LibWeb/HTML/Plugin.h>
#include <LibWeb/HTML/Scripting/ImportMap.h>
#include <LibWeb/HTML/WindowEventHandlers.h>
@@ -137,6 +139,9 @@ public:
void initialize_web_interfaces(Badge<WindowEnvironmentSettingsObject>);
+ Vector<JS::NonnullGCPtr<Plugin>> pdf_viewer_plugin_objects();
+ Vector<JS::NonnullGCPtr<MimeType>> pdf_viewer_mime_type_objects();
+
private:
explicit Window(JS::Realm&);
@@ -184,6 +189,12 @@ private:
// https://w3c.github.io/requestidlecallback/#dfn-idle-callback-identifier
u32 m_idle_callback_identifier = 0;
+ // https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewer-plugin-objects
+ Vector<JS::NonnullGCPtr<Plugin>> m_pdf_viewer_plugin_objects;
+
+ // https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewer-mime-type-objects
+ Vector<JS::NonnullGCPtr<MimeType>> m_pdf_viewer_mime_type_objects;
+
public:
HTML::Origin origin() const;
diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake
index fa1488d4b7..e394258a7d 100644
--- a/Userland/Libraries/LibWeb/idl_files.cmake
+++ b/Userland/Libraries/LibWeb/idl_files.cmake
@@ -152,9 +152,13 @@ libweb_js_bindings(HTML/Location)
libweb_js_bindings(HTML/MessageChannel)
libweb_js_bindings(HTML/MessageEvent)
libweb_js_bindings(HTML/MessagePort)
+libweb_js_bindings(HTML/MimeType)
+libweb_js_bindings(HTML/MimeTypeArray)
libweb_js_bindings(HTML/Navigator)
libweb_js_bindings(HTML/PageTransitionEvent)
libweb_js_bindings(HTML/Path2D)
+libweb_js_bindings(HTML/Plugin)
+libweb_js_bindings(HTML/PluginArray)
libweb_js_bindings(HTML/PromiseRejectionEvent)
libweb_js_bindings(HTML/Storage)
libweb_js_bindings(HTML/SubmitEvent)