1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-23 04:47:36 +00:00

LibWeb: Implement navigator.{plugins,mimeTypes}

This commit is contained in:
Luke Wilde 2023-02-28 00:23:53 +00:00 committed by Andreas Kling
parent 5e422bdae0
commit 4d0277cd9a
20 changed files with 767 additions and 4 deletions

View file

@ -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

View file

@ -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;

View file

@ -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();
}
}

View file

@ -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;
};
}

View file

@ -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;
};

View file

@ -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();
}
}

View file

@ -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; }
};
}

View file

@ -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);
};

View file

@ -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;
}
}

View file

@ -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;
};
}

View file

@ -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;
};

View file

@ -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();
}
}

View file

@ -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; }
};
}

View file

@ -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);
};

View file

@ -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();
}
}

View file

@ -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; }
};
}

View file

@ -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);
};

View file

@ -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();

View file

@ -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;

View file

@ -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)