diff -urpN webkitgtk-2.34.0.orig/Source/cmake/OptionsGTK.cmake webkitgtk.2.34.0/Source/cmake/OptionsGTK.cmake
--- webkitgtk-2.34.0.orig/Source/cmake/OptionsGTK.cmake	2021-09-22 03:21:23.000000000 -0500
+++ webkitgtk.2.34.0/Source/cmake/OptionsGTK.cmake	2021-09-29 11:16:12.679267678 -0500
@@ -156,7 +156,6 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_STREAM PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MHTML PRIVATE ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MOUSE_CURSOR_SCALE PRIVATE ON)
-WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NETSCAPE_PLUGIN_API PRIVATE OFF)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NETWORK_CACHE_SPECULATIVE_REVALIDATION PRIVATE ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NETWORK_CACHE_STALE_WHILE_REVALIDATE PRIVATE ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_OFFSCREEN_CANVAS PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
@@ -170,6 +169,10 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_API_STATISTICS PRIVATE ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_RTC PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES})
 
+if (USE_GTK4)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NETSCAPE_PLUGIN_API PRIVATE OFF)
+endif ()
+
 include(GStreamerDependencies)
 
 # Finalize the value for all options. Do not attempt to use an option before
@@ -250,7 +253,16 @@ SET_AND_EXPOSE_TO_BUILD(WTF_PLATFORM_QUA
 SET_AND_EXPOSE_TO_BUILD(WTF_PLATFORM_X11 ${ENABLE_X11_TARGET})
 SET_AND_EXPOSE_TO_BUILD(WTF_PLATFORM_WAYLAND ${ENABLE_WAYLAND_TARGET})
 
-SET_AND_EXPOSE_TO_BUILD(ENABLE_PLUGIN_PROCESS FALSE)
+if (ENABLE_NETSCAPE_PLUGIN_API)
+    # MOZ_X11 and XP_UNIX are required by npapi.h. Their value is not checked;
+    # only their definedness is. They should only be defined in the true case.
+    if (ENABLE_X11_TARGET)
+        SET_AND_EXPOSE_TO_BUILD(MOZ_X11 1)
+    endif ()
+    SET_AND_EXPOSE_TO_BUILD(XP_UNIX 1)
+endif ()
+
+SET_AND_EXPOSE_TO_BUILD(ENABLE_PLUGIN_PROCESS ${ENABLE_NETSCAPE_PLUGIN_API})
 
 add_definitions(-DBUILDING_GTK__=1)
 add_definitions(-DGETTEXT_PACKAGE="WebKit2GTK-${WEBKITGTK_API_VERSION}")
diff -urpN webkitgtk-2.34.0.orig/Source/WebCore/page/Frame.cpp webkitgtk.2.34.0/Source/WebCore/page/Frame.cpp
--- webkitgtk-2.34.0.orig/Source/WebCore/page/Frame.cpp	2021-09-01 04:16:50.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebCore/page/Frame.cpp	2021-09-29 11:16:12.679267678 -0500
@@ -1123,7 +1123,7 @@ TextStream& operator<<(TextStream& ts, c
     return ts;
 }
 
-bool Frame::arePluginsEnabled()
+bool Frame::arePluginsEnabled() const
 {
     return settings().arePluginsEnabled();
 }
diff -urpN webkitgtk-2.34.0.orig/Source/WebCore/page/Frame.h webkitgtk.2.34.0/Source/WebCore/page/Frame.h
--- webkitgtk-2.34.0.orig/Source/WebCore/page/Frame.h	2021-09-01 04:16:50.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebCore/page/Frame.h	2021-09-29 11:16:12.679267678 -0500
@@ -299,7 +299,7 @@ public:
     void selfOnlyRef();
     void selfOnlyDeref();
 
-    WEBCORE_EXPORT bool arePluginsEnabled();
+    WEBCORE_EXPORT bool arePluginsEnabled() const;
 
 private:
     friend class NavigationDisabler;
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/CMakeLists.txt webkitgtk.2.34.0/Source/WebKit/CMakeLists.txt
--- webkitgtk-2.34.0.orig/Source/WebKit/CMakeLists.txt	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/CMakeLists.txt	2021-09-29 11:16:12.679267678 -0500
@@ -611,7 +611,7 @@ else ()
 
     set_target_properties(WebKit PROPERTIES VERSION ${WEBKIT_VERSION} SOVERSION ${WEBKIT_VERSION_MAJOR})
 
-    install(TARGETS WebKit WebProcess NetworkProcess
+    install(TARGETS WebKit WebProcess NetworkProcess PluginProcess
         LIBRARY DESTINATION "${LIB_INSTALL_DIR}"
         RUNTIME DESTINATION "${LIBEXEC_INSTALL_DIR}"
     )
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/Platform/SharedMemory.h webkitgtk.2.34.0/Source/WebKit/Platform/SharedMemory.h
--- webkitgtk-2.34.0.orig/Source/WebKit/Platform/SharedMemory.h	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/Platform/SharedMemory.h	2021-09-29 11:16:12.679267678 -0500
@@ -55,6 +55,7 @@ class MachSendRight;
 
 namespace WebKit {
 
+#undef None
 enum class MemoryLedger { None, Default, Network, Media, Graphics, Neural };
 
 class SharedMemory : public ThreadSafeRefCounted<SharedMemory> {
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/PlatformGTK.cmake webkitgtk.2.34.0/Source/WebKit/PlatformGTK.cmake
--- webkitgtk-2.34.0.orig/Source/WebKit/PlatformGTK.cmake	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/PlatformGTK.cmake	2021-09-29 11:16:12.679267678 -0500
@@ -4,6 +4,7 @@ set(WebKit_OUTPUT_NAME webkit2gtk-${WEBK
 set(WebProcess_OUTPUT_NAME WebKitWebProcess)
 set(NetworkProcess_OUTPUT_NAME WebKitNetworkProcess)
 set(GPUProcess_OUTPUT_NAME WebKitGPUProcess)
+set(PluginProcess_OUTPUT_NAME WebKitPluginProcess)
 
 file(MAKE_DIRECTORY ${WebKit2Gtk_DERIVED_SOURCES_DIR}/webkit2)
 file(MAKE_DIRECTORY ${WebKit2Gtk_FRAMEWORK_HEADERS_DIR})
@@ -421,6 +422,7 @@ list(APPEND WebKit_INCLUDE_DIRECTORIES
     "${WEBKIT_DIR}/Shared/API/glib"
     "${WEBKIT_DIR}/Shared/CoordinatedGraphics"
     "${WEBKIT_DIR}/Shared/CoordinatedGraphics/threadedcompositor"
+    "${WEBKIT_DIR}/Shared/Plugins/unix"
     "${WEBKIT_DIR}/Shared/glib"
     "${WEBKIT_DIR}/Shared/gtk"
     "${WEBKIT_DIR}/Shared/linux"
@@ -433,6 +435,9 @@ list(APPEND WebKit_INCLUDE_DIRECTORIES
     "${WEBKIT_DIR}/UIProcess/CoordinatedGraphics"
     "${WEBKIT_DIR}/UIProcess/Inspector/glib"
     "${WEBKIT_DIR}/UIProcess/Inspector/gtk"
+    "${WEBKIT_DIR}/WebProcess/Plugins/Netscape/unix"
+    "${WEBKIT_DIR}/WebProcess/Plugins/Netscape/x11"
+    "${WEBKIT_DIR}/UIProcess/Plugins/gtk"
     "${WEBKIT_DIR}/UIProcess/geoclue"
     "${WEBKIT_DIR}/UIProcess/glib"
     "${WEBKIT_DIR}/UIProcess/gstreamer"
@@ -618,6 +623,11 @@ if (ENABLE_WAYLAND_TARGET)
     )
 endif ()
 
+# GTK3 PluginProcess
+list(APPEND PluginProcess_SOURCES
+    PluginProcess/EntryPoint/unix/PluginProcessMain.cpp
+)
+
 # Commands for building the built-in injected bundle.
 add_library(webkit2gtkinjectedbundle MODULE "${WEBKIT_DIR}/WebProcess/InjectedBundle/API/glib/WebKitInjectedBundleMain.cpp")
 ADD_WEBKIT_PREFIX_HEADER(webkit2gtkinjectedbundle)
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/PluginProcess/unix/PluginControllerProxyUnix.cpp webkitgtk.2.34.0/Source/WebKit/PluginProcess/unix/PluginControllerProxyUnix.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/PluginProcess/unix/PluginControllerProxyUnix.cpp	1969-12-31 18:00:00.000000000 -0600
+++ webkitgtk.2.34.0/Source/WebKit/PluginProcess/unix/PluginControllerProxyUnix.cpp	2021-09-29 11:16:12.679267678 -0500
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 Igalia S.L.
+ *
+ * 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "config.h"
+#include "PluginControllerProxy.h"
+
+#if ENABLE(NETSCAPE_PLUGIN_API)
+
+#include <WebCore/NotImplemented.h>
+
+namespace WebKit {
+using namespace WebCore;
+
+void PluginControllerProxy::platformInitialize(const PluginCreationParameters&)
+{
+    notImplemented();
+}
+
+void PluginControllerProxy::platformDestroy()
+{
+    notImplemented();
+}
+
+void PluginControllerProxy::platformGeometryDidChange()
+{
+    notImplemented();
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/PluginProcess/unix/PluginProcessMainUnix.cpp webkitgtk.2.34.0/Source/WebKit/PluginProcess/unix/PluginProcessMainUnix.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/PluginProcess/unix/PluginProcessMainUnix.cpp	1969-12-31 18:00:00.000000000 -0600
+++ webkitgtk.2.34.0/Source/WebKit/PluginProcess/unix/PluginProcessMainUnix.cpp	2021-09-29 11:16:12.679267678 -0500
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2011, 2014 Igalia S.L.
+ * Copyright (C) 2011 Apple Inc.
+ * Copyright (C) 2012 Samsung Electronics
+ *
+ * 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 OWNER 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 "config.h"
+#include "PluginProcessMain.h"
+
+#if ENABLE(PLUGIN_PROCESS)
+
+#include "AuxiliaryProcessMain.h"
+#include "Logging.h"
+#include "NetscapePlugin.h"
+#include "PluginProcess.h"
+#include <stdlib.h>
+#include <wtf/FileSystem.h>
+
+#if PLATFORM(GTK)
+#include <gtk/gtk.h>
+#endif
+
+#if PLATFORM(X11)
+#include <WebCore/PlatformDisplayX11.h>
+#include <WebCore/XErrorTrapper.h>
+#include <wtf/NeverDestroyed.h>
+#endif
+
+namespace WebKit {
+
+#if PLATFORM(X11)
+static LazyNeverDestroyed<WebCore::XErrorTrapper> xErrorTrapper;
+#endif
+
+class PluginProcessMainUnix final: public AuxiliaryProcessMainBase<PluginProcess> {
+public:
+    bool platformInitialize() override
+    {
+#if PLATFORM(GTK)
+        gtk_init(nullptr, nullptr);
+#endif
+
+        return true;
+    }
+
+    bool parseCommandLine(int argc, char** argv) override
+    {
+        ASSERT(argc > 2);
+        if (argc < 3)
+            return false;
+
+        if (!strcmp(argv[1], "-scanPlugin")) {
+            ASSERT(argc == 3);
+#if PLUGIN_ARCHITECTURE(UNIX)
+            InitializeWebKit2();
+            exit(NetscapePluginModule::scanPlugin(argv[2]) ? EXIT_SUCCESS : EXIT_FAILURE);
+#else
+            exit(EXIT_FAILURE);
+#endif
+        }
+
+        ASSERT(argc == 4);
+#if PLATFORM(X11)
+        if (WebCore::PlatformDisplay::sharedDisplay().type() == WebCore::PlatformDisplay::Type::X11) {
+            auto* display = downcast<WebCore::PlatformDisplayX11>(WebCore::PlatformDisplay::sharedDisplay()).native();
+            xErrorTrapper.construct(display, WebCore::XErrorTrapper::Policy::Warn);
+        }
+#endif
+
+        m_parameters.extraInitializationData.add("plugin-path", argv[3]);
+        return AuxiliaryProcessMainBase::parseCommandLine(argc, argv);
+    }
+};
+
+int PluginProcessMain(int argc, char** argv)
+{
+    return AuxiliaryProcessMain<PluginProcessMainUnix>(argc, argv);
+}
+
+} // namespace WebKit
+
+#endif
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/PluginProcess/unix/PluginProcessUnix.cpp webkitgtk.2.34.0/Source/WebKit/PluginProcess/unix/PluginProcessUnix.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/PluginProcess/unix/PluginProcessUnix.cpp	1969-12-31 18:00:00.000000000 -0600
+++ webkitgtk.2.34.0/Source/WebKit/PluginProcess/unix/PluginProcessUnix.cpp	2021-09-29 11:16:12.679267678 -0500
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 Igalia S.L.
+ *
+ * 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "config.h"
+#include "PluginProcess.h"
+
+#if ENABLE(PLUGIN_PROCESS)
+
+#include "PluginProcessCreationParameters.h"
+#include <WebCore/NotImplemented.h>
+
+namespace WebKit {
+
+void PluginProcess::platformInitializeProcess(const AuxiliaryProcessInitializationParameters&)
+{
+}
+
+void PluginProcess::platformInitializePluginProcess(PluginProcessCreationParameters&&)
+{
+    notImplemented();
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(PLUGIN_PROCESS)
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/Shared/AuxiliaryProcessMain.h webkitgtk.2.34.0/Source/WebKit/Shared/AuxiliaryProcessMain.h
--- webkitgtk-2.34.0.orig/Source/WebKit/Shared/AuxiliaryProcessMain.h	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/Shared/AuxiliaryProcessMain.h	2021-09-29 11:16:12.679267678 -0500
@@ -36,7 +36,7 @@ namespace WebKit {
 
 class AuxiliaryProcessMainCommon {
 public:
-    bool parseCommandLine(int argc, char** argv);
+    virtual bool parseCommandLine(int argc, char** argv);
 
 protected:
     AuxiliaryProcessInitializationParameters m_parameters;
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/Shared/Plugins/Netscape/unix/NetscapePluginModuleUnix.cpp webkitgtk.2.34.0/Source/WebKit/Shared/Plugins/Netscape/unix/NetscapePluginModuleUnix.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/Shared/Plugins/Netscape/unix/NetscapePluginModuleUnix.cpp	1969-12-31 18:00:00.000000000 -0600
+++ webkitgtk.2.34.0/Source/WebKit/Shared/Plugins/Netscape/unix/NetscapePluginModuleUnix.cpp	2021-09-29 11:16:12.679267678 -0500
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2010 Apple Inc. 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "config.h"
+#include "NetscapePluginModule.h"
+
+#if PLUGIN_ARCHITECTURE(UNIX) && ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "NetscapeBrowserFuncs.h"
+#include "PluginProcessProxy.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <wtf/FileSystem.h>
+#include <wtf/text/StringBuilder.h>
+
+namespace WebKit {
+using namespace WebCore;
+
+class StdoutDevNullRedirector {
+public:
+    StdoutDevNullRedirector();
+    ~StdoutDevNullRedirector();
+
+private:
+    int m_savedStdout;
+};
+
+StdoutDevNullRedirector::StdoutDevNullRedirector()
+    : m_savedStdout(-1)
+{
+    int newStdout = open("/dev/null", O_WRONLY);
+    if (newStdout == -1)
+        return;
+    m_savedStdout = dup(STDOUT_FILENO);
+    dup2(newStdout, STDOUT_FILENO);
+    close(newStdout);
+}
+
+StdoutDevNullRedirector::~StdoutDevNullRedirector()
+{
+    if (m_savedStdout != -1) {
+        dup2(m_savedStdout, STDOUT_FILENO);
+        close(m_savedStdout);
+    }
+}
+
+
+void NetscapePluginModule::parseMIMEDescription(const String& mimeDescription, Vector<MimeClassInfo>& result)
+{
+    ASSERT_ARG(result, result.isEmpty());
+
+    Vector<String> types = mimeDescription.convertToASCIILowercase().split(';');
+    result.reserveInitialCapacity(types.size());
+
+    size_t mimeInfoCount = 0;
+    for (size_t i = 0; i < types.size(); ++i) {
+        Vector<String> mimeTypeParts = types[i].splitAllowingEmptyEntries(':');
+        if (mimeTypeParts.size() <= 0)
+            continue;
+
+        result.uncheckedAppend(MimeClassInfo());
+        MimeClassInfo& mimeInfo = result[mimeInfoCount++];
+        mimeInfo.type = mimeTypeParts[0];
+
+        if (mimeTypeParts.size() > 1)
+            mimeInfo.extensions = mimeTypeParts[1].split(',');
+
+        if (mimeTypeParts.size() > 2)
+            mimeInfo.desc = mimeTypeParts[2];
+    }
+}
+
+String NetscapePluginModule::buildMIMEDescription(const Vector<MimeClassInfo>& mimeDescription)
+{
+    StringBuilder builder;
+
+    size_t mimeInfoCount = mimeDescription.size();
+    for (size_t i = 0; i < mimeInfoCount; ++i) {
+        const MimeClassInfo& mimeInfo = mimeDescription[i];
+        builder.append(mimeInfo.type);
+        builder.append(':');
+
+        size_t extensionsCount = mimeInfo.extensions.size();
+        for (size_t j = 0; j < extensionsCount; ++j) {
+            builder.append(mimeInfo.extensions[j]);
+            if (j != extensionsCount - 1)
+                builder.append(',');
+        }
+        builder.append(':');
+
+        builder.append(mimeInfo.desc);
+        if (i != mimeInfoCount - 1)
+            builder.append(';');
+    }
+
+    return builder.toString();
+}
+
+bool NetscapePluginModule::getPluginInfoForLoadedPlugin(RawPluginMetaData& metaData)
+{
+    ASSERT(m_isInitialized);
+
+    Module* module = m_module.get();
+    NPP_GetValueProcPtr NPP_GetValue = module->functionPointer<NPP_GetValueProcPtr>("NP_GetValue");
+    if (!NPP_GetValue)
+        return false;
+
+    NP_GetMIMEDescriptionFuncPtr NP_GetMIMEDescription = module->functionPointer<NP_GetMIMEDescriptionFuncPtr>("NP_GetMIMEDescription");
+    if (!NP_GetMIMEDescription)
+        return false;
+
+    char* buffer;
+    NPError error = NPP_GetValue(0, NPPVpluginNameString, &buffer);
+    if (error == NPERR_NO_ERROR)
+        metaData.name = String::fromUTF8(buffer);
+
+    error = NPP_GetValue(0, NPPVpluginDescriptionString, &buffer);
+    if (error == NPERR_NO_ERROR)
+        metaData.description = String::fromUTF8(buffer);
+
+    String mimeDescription = String::fromUTF8(NP_GetMIMEDescription());
+    if (mimeDescription.isNull())
+        return false;
+
+    metaData.mimeDescription = mimeDescription;
+
+    return true;
+}
+
+bool NetscapePluginModule::getPluginInfo(const String& pluginPath, PluginModuleInfo& plugin)
+{
+    RawPluginMetaData metaData;
+    if (!PluginProcessProxy::scanPlugin(pluginPath, metaData))
+        return false;
+
+    plugin.path = pluginPath;
+    plugin.info.file = FileSystem::pathFileName(pluginPath);
+    plugin.info.name = metaData.name;
+    plugin.info.desc = metaData.description;
+    parseMIMEDescription(metaData.mimeDescription, plugin.info.mimes);
+
+    return true;
+}
+
+void NetscapePluginModule::determineQuirks()
+{
+    RawPluginMetaData metaData;
+    if (!getPluginInfoForLoadedPlugin(metaData))
+        return;
+
+    Vector<MimeClassInfo> mimeTypes;
+    parseMIMEDescription(metaData.mimeDescription, mimeTypes);
+
+#if PLATFORM(X11)
+    for (size_t i = 0; i < mimeTypes.size(); ++i) {
+        if (mimeTypes[i].type == "application/x-shockwave-flash") {
+#if CPU(X86_64)
+            m_pluginQuirks.add(PluginQuirks::IgnoreRightClickInWindowlessMode);
+#endif
+            m_pluginQuirks.add(PluginQuirks::DoNotCancelSrcStreamInWindowedMode);
+            break;
+        }
+    }
+#endif // PLATFORM(X11)
+}
+
+static void writeCharacter(char byte)
+{
+    int result;
+    while ((result = fputc(byte, stdout)) == EOF && errno == EINTR) { }
+    ASSERT(result != EOF);
+}
+
+static void writeLine(const String& line)
+{
+    CString utf8String = line.utf8();
+    const char* utf8Data = utf8String.data();
+
+    for (unsigned i = 0; i < utf8String.length(); i++) {
+        char character = utf8Data[i];
+        if (character != '\n')
+            writeCharacter(character);
+    }
+    writeCharacter('\n');
+}
+
+bool NetscapePluginModule::scanPlugin(const String& pluginPath)
+{
+    RawPluginMetaData metaData;
+
+    {
+        // Don't allow the plugin to pollute the standard output.
+        StdoutDevNullRedirector stdOutRedirector;
+
+        // We are loading the plugin here since it does not seem to be a standardized way to
+        // get the needed informations from a UNIX plugin without loading it.
+        RefPtr<NetscapePluginModule> pluginModule = NetscapePluginModule::getOrCreate(pluginPath);
+        if (!pluginModule)
+            return false;
+
+        pluginModule->incrementLoadCount();
+        bool success = pluginModule->getPluginInfoForLoadedPlugin(metaData);
+        pluginModule->decrementLoadCount();
+
+        if (!success)
+            return false;
+    }
+
+    // Write data to standard output for the UI process.
+    writeLine(metaData.name);
+    writeLine(metaData.description);
+    writeLine(metaData.mimeDescription);
+
+    fflush(stdout);
+
+    return true;
+}
+
+} // namespace WebKit
+
+#endif // PLUGIN_ARCHITECTURE(UNIX) && ENABLE(NETSCAPE_PLUGIN_API)
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/Shared/Plugins/unix/PluginSearchPath.cpp webkitgtk.2.34.0/Source/WebKit/Shared/Plugins/unix/PluginSearchPath.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/Shared/Plugins/unix/PluginSearchPath.cpp	1969-12-31 18:00:00.000000000 -0600
+++ webkitgtk.2.34.0/Source/WebKit/Shared/Plugins/unix/PluginSearchPath.cpp	2021-09-29 14:21:13.073874803 -0500
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 Igalia S.L.
+ *
+ * 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "config.h"
+#include "PluginSearchPath.h"
+
+#include <wtf/FileSystem.h>
+
+namespace WebKit {
+
+Vector<String> pluginsDirectories()
+{
+    Vector<String> result;
+
+#if ENABLE(NETSCAPE_PLUGIN_API)
+    String mozillaPaths(getenv("MOZ_PLUGIN_PATH"));
+    if (!mozillaPaths.isEmpty()) {
+        Vector<String> paths = mozillaPaths.split(':');
+        result.appendVector(paths);
+    }
+
+    String mozillaHome(getenv("MOZILLA_HOME"));
+    if (!mozillaHome.isEmpty())
+        result.append(mozillaHome + "/plugins");
+
+    result.append("/usr/lib/browser/plugins");
+    result.append("/usr/local/lib/mozilla/plugins");
+    result.append("/usr/lib/firefox/plugins");
+    result.append("/usr/lib64/browser-plugins");
+    result.append("/usr/lib/browser-plugins");
+    result.append("/usr/lib/mozilla/plugins");
+    result.append("/usr/local/netscape/plugins");
+    result.append("/opt/mozilla/plugins");
+    result.append("/opt/mozilla/lib/plugins");
+    result.append("/opt/netscape/plugins");
+    result.append("/opt/netscape/communicator/plugins");
+    result.append("/usr/lib/netscape/plugins");
+    result.append("/usr/lib/netscape/plugins-libc5");
+    result.append("/usr/lib/netscape/plugins-libc6");
+    result.append("/usr/lib64/netscape/plugins");
+    result.append("/usr/lib64/mozilla/plugins");
+    result.append("/usr/lib/nsbrowser/plugins");
+    result.append("/usr/lib64/nsbrowser/plugins");
+#endif
+
+    return result;
+}
+
+} // namespace WebKit
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/Shared/Plugins/unix/PluginSearchPath.h webkitgtk.2.34.0/Source/WebKit/Shared/Plugins/unix/PluginSearchPath.h
--- webkitgtk-2.34.0.orig/Source/WebKit/Shared/Plugins/unix/PluginSearchPath.h	1969-12-31 18:00:00.000000000 -0600
+++ webkitgtk.2.34.0/Source/WebKit/Shared/Plugins/unix/PluginSearchPath.h	2021-09-29 11:16:12.679267678 -0500
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 Igalia S.L.
+ *
+ * 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+#ifndef PluginSearchPath_h
+#define PluginSearchPath_h
+
+#include <wtf/Forward.h>
+#include <wtf/Vector.h>
+
+namespace WebKit {
+
+Vector<String> pluginsDirectories();
+
+} // namespace WebKit
+
+#endif // PluginSandboxProfile_h
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/SourcesGTK.txt webkitgtk.2.34.0/Source/WebKit/SourcesGTK.txt
--- webkitgtk-2.34.0.orig/Source/WebKit/SourcesGTK.txt	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/SourcesGTK.txt	2021-09-29 11:16:12.679267678 -0500
@@ -61,6 +61,10 @@ Platform/glib/ModuleGlib.cpp
 Platform/unix/LoggingUnix.cpp
 Platform/unix/SharedMemoryUnix.cpp
 
+PluginProcess/unix/PluginControllerProxyUnix.cpp
+PluginProcess/unix/PluginProcessMainUnix.cpp
+PluginProcess/unix/PluginProcessUnix.cpp
+
 Shared/API/c/cairo/WKImageCairo.cpp
 
 Shared/API/glib/WebKitContextMenu.cpp @no-unify
@@ -78,6 +82,11 @@ Shared/CoordinatedGraphics/threadedcompo
 Shared/CoordinatedGraphics/threadedcompositor/ThreadedDisplayRefreshMonitor.cpp
 Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.cpp
 
+Shared/Plugins/Netscape/NetscapePluginModuleNone.cpp
+Shared/Plugins/Netscape/unix/NetscapePluginModuleUnix.cpp
+
+Shared/Plugins/unix/PluginSearchPath.cpp
+
 Shared/cairo/ShareableBitmapCairo.cpp
 
 Shared/glib/ArgumentCodersGLib.cpp
@@ -235,6 +244,11 @@ UIProcess/Launcher/glib/FlatpakLauncher.
 
 UIProcess/linux/MemoryPressureMonitor.cpp
 
+UIProcess/Plugins/gtk/PluginInfoCache.cpp
+
+UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp
+UIProcess/Plugins/unix/PluginProcessProxyUnix.cpp
+
 UIProcess/WebsiteData/soup/WebsiteDataStoreSoup.cpp
 UIProcess/WebsiteData/unix/WebsiteDataStoreUnix.cpp
 
@@ -411,6 +425,11 @@ WebProcess/Inspector/gtk/WebInspectorUIG
 
 WebProcess/MediaCache/WebMediaKeyStorageManager.cpp
 
+WebProcess/Plugins/Netscape/unix/NetscapePluginUnix.cpp @no-unify
+WebProcess/Plugins/Netscape/unix/PluginProxyUnix.cpp @no-unify
+
+WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp @no-unify
+
 WebProcess/WebCoreSupport/glib/WebEditorClientGLib.cpp
 
 WebProcess/WebCoreSupport/gtk/WebContextMenuClientGtk.cpp
@@ -445,3 +464,5 @@ WebProcess/glib/WebProcessGLib.cpp
 WebProcess/gtk/GtkSettingsManagerProxy.cpp
 WebProcess/gtk/WaylandCompositorDisplay.cpp
 WebProcess/gtk/WebProcessMainGtk.cpp
+
+WebProcess/Plugins/Netscape/NetscapePluginNone.cpp
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/SourcesWPE.txt webkitgtk.2.34.0/Source/WebKit/SourcesWPE.txt
--- webkitgtk-2.34.0.orig/Source/WebKit/SourcesWPE.txt	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/SourcesWPE.txt	2021-09-29 11:16:12.679267678 -0500
@@ -61,6 +61,10 @@ Platform/glib/ModuleGlib.cpp
 Platform/unix/LoggingUnix.cpp
 Platform/unix/SharedMemoryUnix.cpp
 
+PluginProcess/unix/PluginControllerProxyUnix.cpp
+PluginProcess/unix/PluginProcessMainUnix.cpp
+PluginProcess/unix/PluginProcessUnix.cpp
+
 Shared/API/c/cairo/WKImageCairo.cpp
 
 Shared/API/glib/WebKitContextMenu.cpp @no-unify
@@ -78,6 +82,9 @@ Shared/CoordinatedGraphics/threadedcompo
 Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.cpp
 Shared/CoordinatedGraphics/threadedcompositor/ThreadedDisplayRefreshMonitor.cpp
 
+Shared/Plugins/Netscape/NetscapePluginModuleNone.cpp
+Shared/Plugins/Netscape/unix/NetscapePluginModuleUnix.cpp
+
 Shared/cairo/ShareableBitmapCairo.cpp
 
 Shared/glib/ArgumentCodersGLib.cpp
@@ -208,6 +215,9 @@ UIProcess/Launcher/glib/ProcessLauncherG
 UIProcess/Launcher/glib/BubblewrapLauncher.cpp
 UIProcess/Launcher/glib/FlatpakLauncher.cpp
 
+UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp
+UIProcess/Plugins/unix/PluginProcessProxyUnix.cpp
+
 UIProcess/WebsiteData/soup/WebsiteDataStoreSoup.cpp
 UIProcess/WebsiteData/unix/WebsiteDataStoreUnix.cpp
 
@@ -245,6 +255,8 @@ WebProcess/InjectedBundle/glib/InjectedB
 
 WebProcess/MediaCache/WebMediaKeyStorageManager.cpp
 
+WebProcess/Plugins/Netscape/NetscapePluginNone.cpp @no-unify
+
 WebProcess/WebCoreSupport/glib/WebEditorClientGLib.cpp
 
 WebProcess/WebCoreSupport/soup/WebFrameNetworkingContext.cpp
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/glib/WebKitMimeInfo.cpp webkitgtk.2.34.0/Source/WebKit/UIProcess/API/glib/WebKitMimeInfo.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/glib/WebKitMimeInfo.cpp	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/API/glib/WebKitMimeInfo.cpp	2021-09-29 11:16:12.683267699 -0500
@@ -20,12 +20,32 @@
 #include "config.h"
 #include "WebKitMimeInfo.h"
 
+#include "WebKitMimeInfoPrivate.h"
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/text/CString.h>
+
 struct _WebKitMimeInfo {
+    _WebKitMimeInfo(const WebCore::MimeClassInfo& mimeInfo)
+        : mimeInfo(mimeInfo)
+    {
+    }
+
+    WebCore::MimeClassInfo mimeInfo;
+    CString mimeType;
+    CString description;
+    GRefPtr<GPtrArray> extensions;
+
+    int referenceCount { 0 };
 };
 
-ALLOW_DEPRECATED_DECLARATIONS_BEGIN
 G_DEFINE_BOXED_TYPE(WebKitMimeInfo, webkit_mime_info, webkit_mime_info_ref, webkit_mime_info_unref)
-ALLOW_DEPRECATED_DECLARATIONS_END
+
+WebKitMimeInfo* webkitMimeInfoCreate(const WebCore::MimeClassInfo& mimeInfo)
+{
+    WebKitMimeInfo* info = static_cast<WebKitMimeInfo*>(fastMalloc(sizeof(WebKitMimeInfo)));
+    new (info) WebKitMimeInfo(mimeInfo);
+    return info;
+}
 
 /**
  * webkit_mime_info_ref:
@@ -35,12 +55,11 @@ ALLOW_DEPRECATED_DECLARATIONS_END
  * function is MT-safe and may be called from any thread.
  *
  * Returns: The passed in #WebKitMimeInfo
- *
- * Deprecated: 2.32
  */
-WebKitMimeInfo* webkit_mime_info_ref(WebKitMimeInfo*)
+WebKitMimeInfo* webkit_mime_info_ref(WebKitMimeInfo* info)
 {
-    return nullptr;
+    g_atomic_int_inc(&info->referenceCount);
+    return info;
 }
 
 /**
@@ -51,11 +70,13 @@ WebKitMimeInfo* webkit_mime_info_ref(Web
  * reference count drops to 0, all memory allocated by the #WebKitMimeInfo is
  * released. This function is MT-safe and may be called from any
  * thread.
- *
- * Deprecated: 2.32
  */
-void webkit_mime_info_unref(WebKitMimeInfo*)
+void webkit_mime_info_unref(WebKitMimeInfo* info)
 {
+    if (g_atomic_int_dec_and_test(&info->referenceCount)) {
+        info->~WebKitMimeInfo();
+        fastFree(info);
+    }
 }
 
 /**
@@ -63,12 +84,17 @@ void webkit_mime_info_unref(WebKitMimeIn
  * @info: a #WebKitMimeInfo
  *
  * Returns: the MIME type of @info
- *
- * Deprecated: 2.32
  */
-const char* webkit_mime_info_get_mime_type(WebKitMimeInfo*)
+const char* webkit_mime_info_get_mime_type(WebKitMimeInfo* info)
 {
-    return nullptr;
+    if (!info->mimeType.isNull())
+        return info->mimeType.data();
+
+    if (info->mimeInfo.type.isEmpty())
+        return 0;
+
+    info->mimeType = info->mimeInfo.type.utf8();
+    return info->mimeType.data();
 }
 
 /**
@@ -76,12 +102,17 @@ const char* webkit_mime_info_get_mime_ty
  * @info: a #WebKitMimeInfo
  *
  * Returns: the description of the MIME type of @info
- *
- * Deprecated: 2.32
  */
-const char* webkit_mime_info_get_description(WebKitMimeInfo*)
+const char* webkit_mime_info_get_description(WebKitMimeInfo* info)
 {
-    return nullptr;
+    if (!info->description.isNull())
+        return info->description.data();
+
+    if (info->mimeInfo.desc.isEmpty())
+        return 0;
+
+    info->description = info->mimeInfo.desc.utf8();
+    return info->description.data();
 }
 
 /**
@@ -93,10 +124,22 @@ const char* webkit_mime_info_get_descrip
  *
  * Returns: (array zero-terminated=1) (transfer none): a
  *     %NULL-terminated array of strings
- *
- * Deprecated: 2.32
  */
-const char* const* webkit_mime_info_get_extensions(WebKitMimeInfo*)
+const char* const* webkit_mime_info_get_extensions(WebKitMimeInfo* info)
 {
-    return nullptr;
+    if (info->extensions)
+        return reinterpret_cast<gchar**>(info->extensions->pdata);
+
+    if (info->mimeInfo.extensions.isEmpty())
+        return 0;
+
+    info->extensions = adoptGRef(g_ptr_array_new_with_free_func(g_free));
+    for (size_t i = 0; i < info->mimeInfo.extensions.size(); ++i) {
+        if (info->mimeInfo.extensions[i].isEmpty())
+            continue;
+        g_ptr_array_add(info->extensions.get(), g_strdup(info->mimeInfo.extensions[i].utf8().data()));
+    }
+    g_ptr_array_add(info->extensions.get(), 0);
+
+    return reinterpret_cast<gchar**>(info->extensions->pdata);
 }
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/glib/WebKitMimeInfoPrivate.h webkitgtk.2.34.0/Source/WebKit/UIProcess/API/glib/WebKitMimeInfoPrivate.h
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/glib/WebKitMimeInfoPrivate.h	1969-12-31 18:00:00.000000000 -0600
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/API/glib/WebKitMimeInfoPrivate.h	2021-09-29 11:16:12.683267699 -0500
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+#include "WebKitMimeInfo.h"
+#include <WebCore/PluginData.h>
+
+WebKitMimeInfo* webkitMimeInfoCreate(const WebCore::MimeClassInfo&);
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/glib/WebKitPlugin.cpp webkitgtk.2.34.0/Source/WebKit/UIProcess/API/glib/WebKitPlugin.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/glib/WebKitPlugin.cpp	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/API/glib/WebKitPlugin.cpp	2021-09-29 11:16:12.683267699 -0500
@@ -20,7 +20,12 @@
 #include "config.h"
 #include "WebKitPlugin.h"
 
+#include "WebKitMimeInfoPrivate.h"
+#include "WebKitPluginPrivate.h"
 #include <wtf/glib/WTFGType.h>
+#include <wtf/text/CString.h>
+
+using namespace WebKit;
 
 /**
  * SECTION: WebKitPlugin
@@ -34,31 +39,52 @@
  * be obtained from the #WebKitWebContext, with
  * webkit_web_context_get_plugins().
  *
- * Deprecated: 2.32
  */
 
 struct _WebKitPluginPrivate {
+    ~_WebKitPluginPrivate()
+    {
+        g_list_free_full(mimeInfoList, reinterpret_cast<GDestroyNotify>(webkit_mime_info_unref));
+    }
+
+    PluginModuleInfo pluginInfo;
+    CString name;
+    CString description;
+    CString path;
+    GList* mimeInfoList;
 };
 
-ALLOW_DEPRECATED_DECLARATIONS_BEGIN
 WEBKIT_DEFINE_TYPE(WebKitPlugin, webkit_plugin, G_TYPE_OBJECT)
-ALLOW_DEPRECATED_DECLARATIONS_END
 
 static void webkit_plugin_class_init(WebKitPluginClass*)
 {
 }
 
+WebKitPlugin* webkitPluginCreate(const PluginModuleInfo& pluginInfo)
+{
+    WebKitPlugin* plugin = WEBKIT_PLUGIN(g_object_new(WEBKIT_TYPE_PLUGIN, NULL));
+    plugin->priv->pluginInfo = pluginInfo;
+    return plugin;
+}
+
 /**
  * webkit_plugin_get_name:
  * @plugin: a #WebKitPlugin
  *
  * Returns: the name of the plugin.
- *
- * Deprecated: 2.32
  */
-const char* webkit_plugin_get_name(WebKitPlugin*)
+const char* webkit_plugin_get_name(WebKitPlugin* plugin)
 {
-    return nullptr;
+    g_return_val_if_fail(WEBKIT_IS_PLUGIN(plugin), 0);
+
+    if (!plugin->priv->name.isNull())
+        return plugin->priv->name.data();
+
+    if (plugin->priv->pluginInfo.info.name.isEmpty())
+        return 0;
+
+    plugin->priv->name = plugin->priv->pluginInfo.info.name.utf8();
+    return plugin->priv->name.data();
 }
 
 /**
@@ -66,12 +92,19 @@ const char* webkit_plugin_get_name(WebKi
  * @plugin: a #WebKitPlugin
  *
  * Returns: the description of the plugin.
- *
- * Deprecated: 2.32
  */
-const char* webkit_plugin_get_description(WebKitPlugin*)
+const char* webkit_plugin_get_description(WebKitPlugin* plugin)
 {
-    return nullptr;
+    g_return_val_if_fail(WEBKIT_IS_PLUGIN(plugin), 0);
+
+    if (!plugin->priv->description.isNull())
+        return plugin->priv->description.data();
+
+    if (plugin->priv->pluginInfo.info.desc.isEmpty())
+        return 0;
+
+    plugin->priv->description = plugin->priv->pluginInfo.info.desc.utf8();
+    return plugin->priv->description.data();
 }
 
 /**
@@ -79,12 +112,19 @@ const char* webkit_plugin_get_descriptio
  * @plugin: a #WebKitPlugin
  *
  * Returns: the absolute path where the plugin is installed.
- *
- * Deprecated: 2.32
  */
-const char* webkit_plugin_get_path(WebKitPlugin*)
+const char* webkit_plugin_get_path(WebKitPlugin* plugin)
 {
-    return nullptr;
+    g_return_val_if_fail(WEBKIT_IS_PLUGIN(plugin), 0);
+
+    if (!plugin->priv->path.isNull())
+        return plugin->priv->path.data();
+
+    if (plugin->priv->pluginInfo.path.isEmpty())
+        return 0;
+
+    plugin->priv->path = plugin->priv->pluginInfo.path.utf8();
+    return plugin->priv->path.data();
 }
 
 /**
@@ -95,10 +135,18 @@ const char* webkit_plugin_get_path(WebKi
  * as a list of #WebKitMimeInfo.
  *
  * Returns: (element-type WebKitMimeInfo) (transfer none): a #GList of #WebKitMimeInfo.
- *
- * Deprecated: 2.32
  */
-GList* webkit_plugin_get_mime_info_list(WebKitPlugin*)
+GList* webkit_plugin_get_mime_info_list(WebKitPlugin* plugin)
 {
-    return nullptr;
+    g_return_val_if_fail(WEBKIT_IS_PLUGIN(plugin), 0);
+
+    if (plugin->priv->mimeInfoList)
+        return plugin->priv->mimeInfoList;
+
+    if (plugin->priv->pluginInfo.info.mimes.isEmpty())
+        return 0;
+
+    for (size_t i = 0; i < plugin->priv->pluginInfo.info.mimes.size(); ++i)
+        plugin->priv->mimeInfoList = g_list_prepend(plugin->priv->mimeInfoList, webkitMimeInfoCreate(plugin->priv->pluginInfo.info.mimes[i]));
+    return plugin->priv->mimeInfoList;
 }
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/glib/WebKitPluginPrivate.h webkitgtk.2.34.0/Source/WebKit/UIProcess/API/glib/WebKitPluginPrivate.h
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/glib/WebKitPluginPrivate.h	1969-12-31 18:00:00.000000000 -0600
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/API/glib/WebKitPluginPrivate.h	2021-09-29 11:16:12.683267699 -0500
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+#include "PluginModuleInfo.h"
+#include "WebKitPlugin.h"
+
+WebKitPlugin* webkitPluginCreate(const WebKit::PluginModuleInfo&);
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/glib/WebKitSettings.cpp webkitgtk.2.34.0/Source/WebKit/UIProcess/API/glib/WebKitSettings.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/glib/WebKitSettings.cpp	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/API/glib/WebKitSettings.cpp	2021-09-29 11:16:12.683267699 -0500
@@ -228,6 +228,7 @@ static void webKitSettingsSetProperty(GO
         webkit_settings_set_enable_frame_flattening(settings, g_value_get_boolean(value));
         break;
     case PROP_ENABLE_PLUGINS:
+        webkit_settings_set_enable_plugins(settings, g_value_get_boolean(value));
         break;
     case PROP_ENABLE_JAVA:
         webkit_settings_set_enable_java(settings, g_value_get_boolean(value));
@@ -430,7 +431,7 @@ static void webKitSettingsGetProperty(GO
         g_value_set_boolean(value, webkit_settings_get_enable_frame_flattening(settings));
         break;
     case PROP_ENABLE_PLUGINS:
-        g_value_set_boolean(value, FALSE);
+        g_value_set_boolean(value, webkit_settings_get_enable_plugins(settings));
         break;
     case PROP_ENABLE_JAVA:
         g_value_set_boolean(value, webkit_settings_get_enable_java(settings));
@@ -739,7 +740,7 @@ static void webkit_settings_class_init(W
             "enable-plugins",
             _("Enable plugins"),
             _("Enable embedded plugin objects."),
-            FALSE,
+            TRUE,
             readWriteConstructParamFlags);
 
     /**
@@ -1879,16 +1880,12 @@ void webkit_settings_set_enable_frame_fl
  * Get the #WebKitSettings:enable-plugins property.
  *
  * Returns: %TRUE If plugins are enabled or %FALSE otherwise.
- *
- * Deprecated: 2.32
  */
 gboolean webkit_settings_get_enable_plugins(WebKitSettings* settings)
 {
     g_return_val_if_fail(WEBKIT_IS_SETTINGS(settings), FALSE);
 
-    g_warning("webkit_settings_get_enable_plugins is deprecated and always returns FALSE. Plugins are no longer supported.");
-
-    return FALSE;
+    return settings->priv->preferences->pluginsEnabled();
 }
 
 /**
@@ -1897,15 +1894,18 @@ gboolean webkit_settings_get_enable_plug
  * @enabled: Value to be set
  *
  * Set the #WebKitSettings:enable-plugins property.
- *
- * Deprecated: 2.32
  */
 void webkit_settings_set_enable_plugins(WebKitSettings* settings, gboolean enabled)
 {
     g_return_if_fail(WEBKIT_IS_SETTINGS(settings));
 
-    if (enabled)
-        g_warning("webkit_settings_set_enable_plugins is deprecated and does nothing. Plugins are no longer supported.");
+    WebKitSettingsPrivate* priv = settings->priv;
+    bool currentValue = priv->preferences->pluginsEnabled();
+    if (currentValue == enabled)
+        return;
+
+    priv->preferences->setPluginsEnabled(enabled);
+    g_object_notify(G_OBJECT(settings), "enable-plugins");
 }
 
 /**
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp webkitgtk.2.34.0/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp	2021-09-29 11:16:12.683267699 -0500
@@ -42,6 +42,7 @@
 #include "WebKitMemoryPressureSettings.h"
 #include "WebKitMemoryPressureSettingsPrivate.h"
 #include "WebKitNotificationProvider.h"
+#include "WebKitPluginPrivate.h"
 #include "WebKitPrivate.h"
 #include "WebKitProtocolHandler.h"
 #include "WebKitSecurityManagerPrivate.h"
@@ -1147,12 +1148,31 @@ WebKitSecurityManager* webkit_web_contex
  * @directory: the directory to add
  *
  * Set an additional directory where WebKit will look for plugins.
- *
- * Deprecated: 2.32
  */
-void webkit_web_context_set_additional_plugins_directory(WebKitWebContext*, const char*)
+void webkit_web_context_set_additional_plugins_directory(WebKitWebContext* context, const char* directory)
+{
+    g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
+    g_return_if_fail(directory);
+
+#if ENABLE(NETSCAPE_PLUGIN_API)
+    context->priv->processPool->setAdditionalPluginsDirectory(FileSystem::stringFromFileSystemRepresentation(directory));
+#endif
+}
+
+static void destroyPluginList(GList* plugins)
+{
+    g_list_free_full(plugins, g_object_unref);
+}
+
+static void webkitWebContextGetPluginThread(GTask* task, gpointer object, gpointer /* taskData */, GCancellable*)
 {
-    g_warning("webkit_web_context_set_additional_plugins_directory is deprecated and does nothing. Netscape plugins are no longer supported.");
+    GList* returnValue = 0;
+#if ENABLE(NETSCAPE_PLUGIN_API)
+    Vector<PluginModuleInfo> plugins = WEBKIT_WEB_CONTEXT(object)->priv->processPool->pluginInfoStore().plugins();
+    for (size_t i = 0; i < plugins.size(); ++i)
+        returnValue = g_list_prepend(returnValue, webkitPluginCreate(plugins[i]));
+#endif
+    g_task_return_pointer(task, returnValue, reinterpret_cast<GDestroyNotify>(destroyPluginList));
 }
 
 /**
@@ -1166,17 +1186,13 @@ void webkit_web_context_set_additional_p
  *
  * When the operation is finished, @callback will be called. You can then call
  * webkit_web_context_get_plugins_finish() to get the result of the operation.
- *
- * Deprecated: 2.32
  */
 void webkit_web_context_get_plugins(WebKitWebContext* context, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
 {
     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
 
-    g_warning("webkit_web_context_get_plugins is deprecated and always returns an empty list. Netscape plugins are no longer supported.");
-
     GRefPtr<GTask> task = adoptGRef(g_task_new(context, cancellable, callback, userData));
-    g_task_return_pointer(task.get(), nullptr, nullptr);
+    g_task_run_in_thread(task.get(), webkitWebContextGetPluginThread);
 }
 
 /**
@@ -1189,13 +1205,11 @@ void webkit_web_context_get_plugins(WebK
  *
  * Returns: (element-type WebKitPlugin) (transfer full): a #GList of #WebKitPlugin. You must free the #GList with
  *    g_list_free() and unref the #WebKitPlugin<!-- -->s with g_object_unref() when you're done with them.
- *
- * Deprecated: 2.32
  */
 GList* webkit_web_context_get_plugins_finish(WebKitWebContext* context, GAsyncResult* result, GError** error)
 {
-    g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), nullptr);
-    g_return_val_if_fail(g_task_is_valid(result, context), nullptr);
+    g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0);
+    g_return_val_if_fail(g_task_is_valid(result, context), 0);
 
     return static_cast<GList*>(g_task_propagate_pointer(G_TASK(result), error));
 }
@@ -1226,7 +1240,9 @@ GList* webkit_web_context_get_plugins_fi
  *     const gchar  *path;
  *
  *     path = webkit_uri_scheme_request_get_path (request);
- *     if (!g_strcmp0 (path, "memory")) {
+ *     if (!g_strcmp0 (path, "plugins")) {
+ *         /<!-- -->* Create a GInputStream with the contents of plugins about page, and set its length to stream_length *<!-- -->/
+ *     } else if (!g_strcmp0 (path, "memory")) {
  *         /<!-- -->* Create a GInputStream with the contents of memory about page, and set its length to stream_length *<!-- -->/
  *     } else if (!g_strcmp0 (path, "applications")) {
  *         /<!-- -->* Create a GInputStream with the contents of applications about page, and set its length to stream_length *<!-- -->/
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/glib/WebKitWebsiteData.cpp webkitgtk.2.34.0/Source/WebKit/UIProcess/API/glib/WebKitWebsiteData.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/glib/WebKitWebsiteData.cpp	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/API/glib/WebKitWebsiteData.cpp	2021-09-29 11:16:12.683267699 -0500
@@ -74,6 +74,9 @@ static bool recordContainsSupportedDataT
         WebsiteDataType::WebSQLDatabases,
         WebsiteDataType::IndexedDBDatabases,
         WebsiteDataType::HSTSCache,
+#if ENABLE(NETSCAPE_PLUGIN_API)
+        WebsiteDataType::PlugInData,
+#endif
         WebsiteDataType::Cookies,
         WebsiteDataType::DeviceIdHashSalt,
         WebsiteDataType::ResourceLoadStatistics,
@@ -103,6 +106,10 @@ static WebKitWebsiteDataTypes toWebKitWe
         returnValue |= WEBKIT_WEBSITE_DATA_INDEXEDDB_DATABASES;
     if (types.contains(WebsiteDataType::HSTSCache))
         returnValue |= WEBKIT_WEBSITE_DATA_HSTS_CACHE;
+#if ENABLE(NETSCAPE_PLUGIN_API)
+    if (types.contains(WebsiteDataType::PlugInData))
+        returnValue |= WEBKIT_WEBSITE_DATA_PLUGIN_DATA;
+#endif
     if (types.contains(WebsiteDataType::Cookies))
         returnValue |= WEBKIT_WEBSITE_DATA_COOKIES;
     if (types.contains(WebsiteDataType::DeviceIdHashSalt))
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/glib/WebKitWebsiteDataManager.cpp webkitgtk.2.34.0/Source/WebKit/UIProcess/API/glib/WebKitWebsiteDataManager.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/glib/WebKitWebsiteDataManager.cpp	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/API/glib/WebKitWebsiteDataManager.cpp	2021-09-29 11:16:12.683267699 -0500
@@ -993,6 +993,10 @@ static OptionSet<WebsiteDataType> toWebs
         returnValue.add(WebsiteDataType::IndexedDBDatabases);
     if (types & WEBKIT_WEBSITE_DATA_HSTS_CACHE)
         returnValue.add(WebsiteDataType::HSTSCache);
+#if ENABLE(NETSCAPE_PLUGIN_API)
+    if (types & WEBKIT_WEBSITE_DATA_PLUGIN_DATA)
+        returnValue.add(WebsiteDataType::PlugInData);
+#endif
     if (types & WEBKIT_WEBSITE_DATA_COOKIES)
         returnValue.add(WebsiteDataType::Cookies);
     if (types & WEBKIT_WEBSITE_DATA_DEVICE_ID_HASH_SALT)
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp webkitgtk.2.34.0/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp	2021-09-29 11:16:12.683267699 -0500
@@ -501,7 +501,8 @@ static gboolean webkitWebViewLoadFail(We
 {
     if (g_error_matches(error, WEBKIT_NETWORK_ERROR, WEBKIT_NETWORK_ERROR_CANCELLED)
         || g_error_matches(error, WEBKIT_PLUGIN_ERROR, WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD)
-        || g_error_matches(error, WEBKIT_POLICY_ERROR, WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE))
+        || g_error_matches(error, WEBKIT_POLICY_ERROR, WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE)
+        || g_error_matches(error, WEBKIT_PLUGIN_ERROR, WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD))
         return FALSE;
 
     GUniquePtr<char> htmlString(g_strdup_printf("<html><body>%s</body></html>", error->message));
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/gtk/WebKitError.h webkitgtk.2.34.0/Source/WebKit/UIProcess/API/gtk/WebKitError.h
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/gtk/WebKitError.h	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/API/gtk/WebKitError.h	2021-09-29 11:16:12.683267699 -0500
@@ -41,6 +41,12 @@ G_BEGIN_DECLS
 /**
  * WebKitNetworkError:
  * @WEBKIT_NETWORK_ERROR_FAILED: Generic load failure
+ * @WEBKIT_PLUGIN_ERROR_FAILED: Generic plugin load failure
+ * @WEBKIT_PLUGIN_ERROR_CANNOT_FIND_PLUGIN: Load failure due to missing plugin
+ * @WEBKIT_PLUGIN_ERROR_CANNOT_LOAD_PLUGIN: Load failure due to inability to load plugin
+ * @WEBKIT_PLUGIN_ERROR_JAVA_UNAVAILABLE: Load failure due to missing Java support that is required to load plugin
+ * @WEBKIT_PLUGIN_ERROR_CONNECTION_CANCELLED: Load failure due to connection cancellation
+ * @WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD: Load failure since plugin handles the load
  * @WEBKIT_NETWORK_ERROR_TRANSPORT: Load failure due to transport error
  * @WEBKIT_NETWORK_ERROR_UNKNOWN_PROTOCOL: Load failure due to unknown protocol
  * @WEBKIT_NETWORK_ERROR_CANCELLED: Load failure due to cancellation
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/gtk/WebKitMimeInfo.h webkitgtk.2.34.0/Source/WebKit/UIProcess/API/gtk/WebKitMimeInfo.h
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/gtk/WebKitMimeInfo.h	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/API/gtk/WebKitMimeInfo.h	2021-09-29 11:16:12.683267699 -0500
@@ -34,22 +34,22 @@ G_BEGIN_DECLS
 typedef struct _WebKitMimeInfo WebKitMimeInfo;
 
 
-WEBKIT_DEPRECATED GType
+WEBKIT_API GType
 webkit_mime_info_get_type        (void);
 
-WEBKIT_DEPRECATED WebKitMimeInfo *
+WEBKIT_API WebKitMimeInfo *
 webkit_mime_info_ref             (WebKitMimeInfo *info);
 
-WEBKIT_DEPRECATED void
+WEBKIT_API void
 webkit_mime_info_unref           (WebKitMimeInfo *info);
 
-WEBKIT_DEPRECATED const gchar *
+WEBKIT_API const gchar *
 webkit_mime_info_get_mime_type   (WebKitMimeInfo *info);
 
-WEBKIT_DEPRECATED const gchar *
+WEBKIT_API const gchar *
 webkit_mime_info_get_description (WebKitMimeInfo *info);
 
-WEBKIT_DEPRECATED const gchar * const *
+WEBKIT_API const gchar * const *
 webkit_mime_info_get_extensions  (WebKitMimeInfo *info);
 
 G_END_DECLS
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/gtk/WebKitPlugin.h webkitgtk.2.34.0/Source/WebKit/UIProcess/API/gtk/WebKitPlugin.h
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/gtk/WebKitPlugin.h	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/API/gtk/WebKitPlugin.h	2021-09-29 11:16:12.683267699 -0500
@@ -55,19 +55,19 @@ struct _WebKitPluginClass {
     void (*_webkit_reserved3) (void);
 };
 
-WEBKIT_DEPRECATED GType
+WEBKIT_API GType
 webkit_plugin_get_type           (void);
 
-WEBKIT_DEPRECATED const gchar *
+WEBKIT_API const gchar *
 webkit_plugin_get_name           (WebKitPlugin *plugin);
 
-WEBKIT_DEPRECATED const gchar *
+WEBKIT_API const gchar *
 webkit_plugin_get_description    (WebKitPlugin *plugin);
 
-WEBKIT_DEPRECATED const gchar *
+WEBKIT_API const gchar *
 webkit_plugin_get_path           (WebKitPlugin *plugin);
 
-WEBKIT_DEPRECATED GList *
+WEBKIT_API GList *
 webkit_plugin_get_mime_info_list (WebKitPlugin *plugin);
 
 G_END_DECLS
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/gtk/WebKitSettings.h webkitgtk.2.34.0/Source/WebKit/UIProcess/API/gtk/WebKitSettings.h
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/gtk/WebKitSettings.h	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/API/gtk/WebKitSettings.h	2021-09-29 11:16:12.683267699 -0500
@@ -147,10 +147,10 @@ WEBKIT_API void
 webkit_settings_set_enable_frame_flattening                    (WebKitSettings *settings,
                                                                 gboolean        enabled);
 
-WEBKIT_DEPRECATED gboolean
+WEBKIT_API gboolean
 webkit_settings_get_enable_plugins                             (WebKitSettings *settings);
 
-WEBKIT_DEPRECATED void
+WEBKIT_API void
 webkit_settings_set_enable_plugins                             (WebKitSettings *settings,
                                                                 gboolean        enabled);
 
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/gtk/WebKitWebContext.h webkitgtk.2.34.0/Source/WebKit/UIProcess/API/gtk/WebKitWebContext.h
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/gtk/WebKitWebContext.h	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/API/gtk/WebKitWebContext.h	2021-09-29 11:16:12.683267699 -0500
@@ -197,17 +197,17 @@ webkit_web_context_get_favicon_database_
 WEBKIT_API WebKitSecurityManager *
 webkit_web_context_get_security_manager             (WebKitWebContext              *context);
 
-WEBKIT_DEPRECATED void
+WEBKIT_API void
 webkit_web_context_set_additional_plugins_directory (WebKitWebContext              *context,
                                                      const gchar                   *directory);
 
-WEBKIT_DEPRECATED void
+WEBKIT_API void
 webkit_web_context_get_plugins                      (WebKitWebContext              *context,
                                                      GCancellable                  *cancellable,
                                                      GAsyncReadyCallback            callback,
                                                      gpointer                       user_data);
 
-WEBKIT_DEPRECATED GList *
+WEBKIT_API GList *
 webkit_web_context_get_plugins_finish               (WebKitWebContext              *context,
                                                      GAsyncResult                  *result,
                                                      GError                       **error);
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/gtk/WebKitWebsiteData.h webkitgtk.2.34.0/Source/WebKit/UIProcess/API/gtk/WebKitWebsiteData.h
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/API/gtk/WebKitWebsiteData.h	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/API/gtk/WebKitWebsiteData.h	2021-09-29 11:16:12.683267699 -0500
@@ -42,7 +42,7 @@ typedef struct _WebKitWebsiteData WebKit
  * @WEBKIT_WEBSITE_DATA_LOCAL_STORAGE: Local storage data.
  * @WEBKIT_WEBSITE_DATA_WEBSQL_DATABASES: WebSQL databases. Deprecated 2.24
  * @WEBKIT_WEBSITE_DATA_INDEXEDDB_DATABASES: IndexedDB databases.
- * @WEBKIT_WEBSITE_DATA_PLUGIN_DATA: Plugins data. Deprecated 2.32
+ * @WEBKIT_WEBSITE_DATA_PLUGIN_DATA: Plugins data.
  * @WEBKIT_WEBSITE_DATA_COOKIES: Cookies.
  * @WEBKIT_WEBSITE_DATA_DEVICE_ID_HASH_SALT: Hash salt used to generate the device ids used by webpages. Since 2.24
  * @WEBKIT_WEBSITE_DATA_HSTS_CACHE: HSTS cache. Since 2.26
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/gtk/WebPageProxyGtk.cpp webkitgtk.2.34.0/Source/WebKit/UIProcess/gtk/WebPageProxyGtk.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/gtk/WebPageProxyGtk.cpp	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/gtk/WebPageProxyGtk.cpp	2021-09-29 11:16:12.687267721 -0500
@@ -38,6 +38,10 @@
 #include <WebCore/PlatformDisplay.h>
 #include <wtf/NeverDestroyed.h>
 
+#if PLATFORM(X11) && ENABLE(NETSCAPE_PLUGIN_API)
+#include <gtk/gtkx.h>
+#endif
+
 namespace WebKit {
 
 void WebPageProxy::platformInitialize()
@@ -67,6 +71,62 @@ void WebPageProxy::didUpdateEditorState(
     pageClient().selectionDidChange();
 }
 
+#if PLATFORM(X11) && ENABLE(NETSCAPE_PLUGIN_API)
+typedef HashMap<uint64_t, GtkWidget* > PluginWindowMap;
+static PluginWindowMap& pluginWindowMap()
+{
+    static NeverDestroyed<PluginWindowMap> map;
+    return map;
+}
+
+static gboolean pluginContainerPlugRemoved(GtkSocket* socket)
+{
+    uint64_t windowID = static_cast<uint64_t>(gtk_socket_get_id(socket));
+    pluginWindowMap().remove(windowID);
+    return FALSE;
+}
+
+void WebPageProxy::createPluginContainer(CompletionHandler<void(uint64_t)>&& completionHandler)
+{
+    RELEASE_ASSERT(WebCore::PlatformDisplay::sharedDisplay().type() == WebCore::PlatformDisplay::Type::X11);
+    GtkWidget* socket = gtk_socket_new();
+    g_signal_connect(socket, "plug-removed", G_CALLBACK(pluginContainerPlugRemoved), 0);
+    gtk_container_add(GTK_CONTAINER(viewWidget()), socket);
+
+    uint64_t windowID = static_cast<uint64_t>(gtk_socket_get_id(GTK_SOCKET(socket)));
+    pluginWindowMap().set(windowID, socket);
+    completionHandler(windowID);
+}
+
+void WebPageProxy::windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID)
+{
+    GtkWidget* plugin = pluginWindowMap().get(windowID);
+    if (!plugin)
+        return;
+
+    if (gtk_widget_get_realized(plugin)) {
+        GdkRectangle clip = clipRect;
+        cairo_region_t* clipRegion = cairo_region_create_rectangle(&clip);
+        gdk_window_shape_combine_region(gtk_widget_get_window(plugin), clipRegion, 0, 0);
+        cairo_region_destroy(clipRegion);
+    }
+
+    webkitWebViewBaseChildMoveResize(WEBKIT_WEB_VIEW_BASE(viewWidget()), plugin, frameRect);
+}
+
+void WebPageProxy::windowedPluginVisibilityDidChange(bool isVisible, uint64_t windowID)
+{
+    GtkWidget* plugin = pluginWindowMap().get(windowID);
+    if (!plugin)
+        return;
+
+    if (isVisible)
+        gtk_widget_show(plugin);
+    else
+        gtk_widget_hide(plugin);
+}
+#endif // PLATFORM(X11) && ENABLE(NETSCAPE_PLUGIN_API)
+
 void WebPageProxy::setInputMethodState(std::optional<InputMethodState>&& state)
 {
     webkitWebViewBaseSetInputMethodState(WEBKIT_WEB_VIEW_BASE(viewWidget()), WTFMove(state));
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/Launcher/glib/BubblewrapLauncher.cpp webkitgtk.2.34.0/Source/WebKit/UIProcess/Launcher/glib/BubblewrapLauncher.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/Launcher/glib/BubblewrapLauncher.cpp	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/Launcher/glib/BubblewrapLauncher.cpp	2021-09-29 11:16:12.687267721 -0500
@@ -746,6 +746,13 @@ GRefPtr<GSubprocess> bubblewrapSpawn(GSu
 {
     ASSERT(launcher);
 
+#if ENABLE(NETSCAPE_PLUGIN_API)
+    // It is impossible to know what access arbitrary plugins need and since it is for legacy
+    // reasons lets just leave it unsandboxed.
+    if (launchOptions.processType == ProcessLauncher::ProcessType::Plugin)
+        return adoptGRef(g_subprocess_launcher_spawnv(launcher, argv, error));
+#endif
+
     // For now we are just considering the network process trusted as it
     // requires a lot of access but doesn't execute arbitrary code like
     // the WebProcess where our focus lies.
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp webkitgtk.2.34.0/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp	2021-09-29 11:16:12.687267721 -0500
@@ -105,10 +105,21 @@ void ProcessLauncher::launchProcess()
 
     String executablePath;
     CString realExecutablePath;
+#if ENABLE(NETSCAPE_PLUGIN_API)
+    String pluginPath;
+    CString realPluginPath;
+#endif
     switch (m_launchOptions.processType) {
     case ProcessLauncher::ProcessType::Web:
         executablePath = executablePathOfWebProcess();
         break;
+#if ENABLE(NETSCAPE_PLUGIN_API)
+    case ProcessLauncher::ProcessType::Plugin:
+        executablePath = executablePathOfPluginProcess();
+        pluginPath = m_launchOptions.extraInitializationData.get("plugin-path");
+        realPluginPath = FileSystem::fileSystemRepresentation(pluginPath);
+        break;
+#endif
     case ProcessLauncher::ProcessType::Network:
         executablePath = executablePathOfNetworkProcess();
         break;
@@ -156,7 +167,11 @@ void ProcessLauncher::launchProcess()
     if (configureJSCForTesting)
         argv[i++] = const_cast<char*>("--configure-jsc-for-testing");
 #endif
+#if ENABLE(NETSCAPE_PLUGIN_API)
+    argv[i++] = const_cast<char*>(realPluginPath.data());
+#else
     argv[i++] = nullptr;
+#endif
 
     GRefPtr<GSubprocessLauncher> launcher = adoptGRef(g_subprocess_launcher_new(G_SUBPROCESS_FLAGS_INHERIT_FDS));
     g_subprocess_launcher_take_fd(launcher.get(), socketPair.client, socketPair.client);
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/Plugins/gtk/PluginInfoCache.cpp webkitgtk.2.34.0/Source/WebKit/UIProcess/Plugins/gtk/PluginInfoCache.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/Plugins/gtk/PluginInfoCache.cpp	1969-12-31 18:00:00.000000000 -0600
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/Plugins/gtk/PluginInfoCache.cpp	2021-09-30 15:24:36.223273899 -0500
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "config.h"
+#include "PluginInfoCache.h"
+
+#if ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "NetscapePluginModule.h"
+#include <WebCore/PlatformDisplay.h>
+#include <wtf/FileSystem.h>
+#include <wtf/text/CString.h>
+
+namespace WebKit {
+
+static const unsigned gSchemaVersion = 3;
+
+PluginInfoCache& PluginInfoCache::singleton()
+{
+    static NeverDestroyed<PluginInfoCache> pluginInfoCache;
+    return pluginInfoCache;
+}
+
+static inline const char* cacheFilenameForCurrentDisplay()
+{
+#if PLATFORM(X11)
+    if (WebCore::PlatformDisplay::sharedDisplay().type() == WebCore::PlatformDisplay::Type::X11)
+        return "plugins-x11";
+#endif
+#if PLATFORM(WAYLAND)
+    if (WebCore::PlatformDisplay::sharedDisplay().type() == WebCore::PlatformDisplay::Type::Wayland)
+        return "plugins-wayland";
+#endif
+
+    ASSERT_NOT_REACHED();
+    return "plugins";
+}
+
+PluginInfoCache::PluginInfoCache()
+    : m_cacheFile(g_key_file_new())
+    , m_saveToFileIdle(RunLoop::main(), this, &PluginInfoCache::saveToFile)
+    , m_readOnlyMode(false)
+{
+    m_saveToFileIdle.setPriority(G_PRIORITY_DEFAULT_IDLE);
+
+    GUniquePtr<char> cacheDirectory(g_build_filename(g_get_user_cache_dir(), "webkitgtk", nullptr));
+    if (FileSystem::makeAllDirectories(cacheDirectory.get())) {
+        // Delete old cache file.
+        GUniquePtr<char> oldCachePath(g_build_filename(cacheDirectory.get(), "plugins", nullptr));
+        FileSystem::deleteFile(FileSystem::stringFromFileSystemRepresentation(oldCachePath.get()));
+
+        m_cachePath.reset(g_build_filename(cacheDirectory.get(), cacheFilenameForCurrentDisplay(), nullptr));
+        g_key_file_load_from_file(m_cacheFile.get(), m_cachePath.get(), G_KEY_FILE_NONE, nullptr);
+    }
+
+    if (g_key_file_has_group(m_cacheFile.get(), "schema")) {
+        unsigned schemaVersion = static_cast<unsigned>(g_key_file_get_integer(m_cacheFile.get(), "schema", "version", nullptr));
+        if (schemaVersion < gSchemaVersion) {
+            // Cache file using an old schema, create a new empty file.
+            m_cacheFile.reset(g_key_file_new());
+        } else if (schemaVersion > gSchemaVersion) {
+            // Cache file using a newer schema, use the cache in read only mode.
+            m_readOnlyMode = true;
+        } else {
+            // Same schema version, we don't need to update it.
+            return;
+        }
+    }
+
+    g_key_file_set_integer(m_cacheFile.get(), "schema", "version", static_cast<unsigned>(gSchemaVersion));
+}
+
+PluginInfoCache::~PluginInfoCache()
+{
+}
+
+void PluginInfoCache::saveToFile()
+{
+    gsize dataLength;
+    GUniquePtr<char> data(g_key_file_to_data(m_cacheFile.get(), &dataLength, nullptr));
+    if (!data)
+        return;
+
+    g_file_set_contents(m_cachePath.get(), data.get(), dataLength, nullptr);
+}
+
+bool PluginInfoCache::getPluginInfo(const String& pluginPath, PluginModuleInfo& plugin)
+{
+    CString pluginGroup = pluginPath.utf8();
+    if (!g_key_file_has_group(m_cacheFile.get(), pluginGroup.data()))
+        return false;
+
+    auto lastModifiedTime = FileSystem::fileModificationTime(pluginPath);
+    if (!lastModifiedTime)
+        return false;
+    time_t cachedLastModified = static_cast<time_t>(g_key_file_get_uint64(m_cacheFile.get(), pluginGroup.data(), "mtime", nullptr));
+    if (lastModifiedTime->secondsSinceEpoch().secondsAs<time_t>() != cachedLastModified)
+        return false;
+
+    plugin.path = pluginPath;
+    plugin.info.file = FileSystem::pathFileName(pluginPath);
+
+    GUniquePtr<char> stringValue(g_key_file_get_string(m_cacheFile.get(), pluginGroup.data(), "name", nullptr));
+    plugin.info.name = String::fromUTF8(stringValue.get());
+
+    stringValue.reset(g_key_file_get_string(m_cacheFile.get(), pluginGroup.data(), "description", nullptr));
+    plugin.info.desc = String::fromUTF8(stringValue.get());
+
+#if PLUGIN_ARCHITECTURE(UNIX)
+    stringValue.reset(g_key_file_get_string(m_cacheFile.get(), pluginGroup.data(), "mime-description", nullptr));
+    NetscapePluginModule::parseMIMEDescription(String::fromUTF8(stringValue.get()), plugin.info.mimes);
+#endif
+
+    return true;
+}
+
+void PluginInfoCache::updatePluginInfo(const String& pluginPath, const PluginModuleInfo& plugin)
+{
+    auto lastModifiedTime = FileSystem::fileModificationTime(pluginPath);
+    if (!lastModifiedTime)
+        return;
+
+    CString pluginGroup = pluginPath.utf8();
+    g_key_file_set_uint64(m_cacheFile.get(), pluginGroup.data(), "mtime", lastModifiedTime->secondsSinceEpoch().secondsAs<guint64>());
+    g_key_file_set_string(m_cacheFile.get(), pluginGroup.data(), "name", plugin.info.name.utf8().data());
+    g_key_file_set_string(m_cacheFile.get(), pluginGroup.data(), "description", plugin.info.desc.utf8().data());
+
+#if PLUGIN_ARCHITECTURE(UNIX)
+    String mimeDescription = NetscapePluginModule::buildMIMEDescription(plugin.info.mimes);
+    g_key_file_set_string(m_cacheFile.get(), pluginGroup.data(), "mime-description", mimeDescription.utf8().data());
+#endif
+
+    if (m_cachePath && !m_readOnlyMode) {
+        // Save the cache file in an idle to make sure it happens in the main thread and
+        // it's done only once when this is called multiple times in a very short time.
+        if (m_saveToFileIdle.isActive())
+            return;
+
+        m_saveToFileIdle.startOneShot(0_s);
+    }
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/Plugins/gtk/PluginInfoCache.h webkitgtk.2.34.0/Source/WebKit/UIProcess/Plugins/gtk/PluginInfoCache.h
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/Plugins/gtk/PluginInfoCache.h	1969-12-31 18:00:00.000000000 -0600
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/Plugins/gtk/PluginInfoCache.h	2021-09-29 11:16:12.687267721 -0500
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+#ifndef PluginInfoCache_h
+#define PluginInfoCache_h
+
+#if ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "PluginModuleInfo.h"
+#include <wtf/NeverDestroyed.h>
+#include <wtf/RunLoop.h>
+#include <wtf/glib/GUniquePtr.h>
+
+namespace WebKit {
+
+class PluginInfoCache {
+    WTF_MAKE_NONCOPYABLE(PluginInfoCache);
+    friend NeverDestroyed<PluginInfoCache>;
+public:
+    static PluginInfoCache& singleton();
+
+    bool getPluginInfo(const String& pluginPath, PluginModuleInfo&);
+    void updatePluginInfo(const String& pluginPath, const PluginModuleInfo&);
+
+private:
+    PluginInfoCache();
+    ~PluginInfoCache();
+
+    void saveToFile();
+
+    GUniquePtr<GKeyFile> m_cacheFile;
+    GUniquePtr<char> m_cachePath;
+    RunLoop::Timer<PluginInfoCache> m_saveToFileIdle;
+    bool m_readOnlyMode;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
+
+#endif // PluginInfoCache_h
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp webkitgtk.2.34.0/Source/WebKit/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp	1969-12-31 18:00:00.000000000 -0600
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp	2021-09-30 13:40:07.078180095 -0500
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2010 Apple Inc. 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+// Note: this file is only for UNIX. On other platforms we can reuse the native implementation.
+
+#include "config.h"
+
+#if ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "PluginInfoStore.h"
+
+#include "NetscapePluginModule.h"
+#include "PluginSearchPath.h"
+#include "ProcessExecutablePath.h"
+#include <WebCore/PlatformDisplay.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <wtf/FileSystem.h>
+
+#if PLATFORM(GTK)
+#include "PluginInfoCache.h"
+#endif
+#include <fnmatch.h>
+
+namespace WebKit {
+using namespace WebCore;
+
+Vector<String> PluginInfoStore::pluginsDirectories()
+{
+    return WebKit::pluginsDirectories();
+}
+
+Vector<String> PluginInfoStore::pluginPathsInDirectory(const String& directory)
+{
+    Vector<String> result;
+    char normalizedPath[PATH_MAX];
+    CString cpath = FileSystem::fileSystemRepresentation(directory);
+    for (const auto& path : FileSystem::listDirectory(directory)) {
+        CString filename = FileSystem::fileSystemRepresentation(path);
+        if (fnmatch(filename.data(), "*.so", 0))
+            continue;
+        char filePath[PATH_MAX];
+        if (static_cast<int>(sizeof(filePath) - 1) < snprintf(filePath, sizeof(filePath), "%s/%s", cpath.data(), filename.data()))
+            continue; // buffer overflow
+        if (realpath(filePath, normalizedPath))
+            result.append(FileSystem::stringFromFileSystemRepresentation(normalizedPath));
+    }
+
+    return result;
+}
+
+Vector<String> PluginInfoStore::individualPluginPaths()
+{
+    return Vector<String>();
+}
+
+bool PluginInfoStore::getPluginInfo(const String& pluginPath, PluginModuleInfo& plugin)
+{
+#if PLATFORM(GTK)
+    if (PluginInfoCache::singleton().getPluginInfo(pluginPath, plugin))
+        return true;
+
+    if (NetscapePluginModule::getPluginInfo(pluginPath, plugin)) {
+        PluginInfoCache::singleton().updatePluginInfo(pluginPath, plugin);
+        return true;
+    }
+    return false;
+#else
+    return NetscapePluginModule::getPluginInfo(pluginPath, plugin);
+#endif
+}
+
+bool PluginInfoStore::shouldUsePlugin(Vector<PluginModuleInfo>& /*alreadyLoadedPlugins*/, const PluginModuleInfo& /*plugin*/)
+{
+    // We do not do any black-listing presently.
+    return true;
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/Plugins/unix/PluginProcessProxyUnix.cpp webkitgtk.2.34.0/Source/WebKit/UIProcess/Plugins/unix/PluginProcessProxyUnix.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/Plugins/unix/PluginProcessProxyUnix.cpp	1969-12-31 18:00:00.000000000 -0600
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/Plugins/unix/PluginProcessProxyUnix.cpp	2021-09-29 11:16:12.687267721 -0500
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2011, 2014 Igalia S.L.
+ * Copyright (C) 2011 Apple Inc.
+ * Copyright (C) 2012 Samsung Electronics
+ *
+ * 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 OWNER 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 "config.h"
+#include "PluginProcessProxy.h"
+
+#if ENABLE(PLUGIN_PROCESS)
+
+#include "PluginProcessCreationParameters.h"
+#include "ProcessExecutablePath.h"
+#include <WebCore/PlatformDisplay.h>
+#include <sys/wait.h>
+#include <wtf/FileSystem.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+#if PLATFORM(GTK)
+#include <glib.h>
+#include <wtf/glib/GUniquePtr.h>
+#endif
+
+#if PLATFORM(GTK)
+#include "Module.h"
+#endif
+
+namespace WebKit {
+using namespace WebCore;
+
+void PluginProcessProxy::platformGetLaunchOptionsWithAttributes(ProcessLauncher::LaunchOptions& launchOptions, const PluginProcessAttributes& pluginProcessAttributes)
+{
+    launchOptions.processType = ProcessLauncher::ProcessType::Plugin;
+    launchOptions.extraInitializationData.add("plugin-path", pluginProcessAttributes.moduleInfo.path);
+}
+
+void PluginProcessProxy::platformInitializePluginProcess(PluginProcessCreationParameters&)
+{
+}
+
+#if PLATFORM(GTK)
+static bool pluginRequiresGtk2(const String& pluginPath)
+{
+    std::unique_ptr<Module> module = makeUnique<Module>(pluginPath);
+    if (!module->load())
+        return false;
+    return module->functionPointer<gpointer>("gtk_object_get_type");
+}
+#endif
+
+#if PLUGIN_ARCHITECTURE(UNIX)
+bool PluginProcessProxy::scanPlugin(const String& pluginPath, RawPluginMetaData& result)
+{
+    String pluginProcessPath = executablePathOfPluginProcess();
+
+#if PLATFORM(GTK)
+    if (pluginRequiresGtk2(pluginPath))
+        return false;
+#endif
+
+    CString binaryPath = FileSystem::fileSystemRepresentation(pluginProcessPath);
+    CString pluginPathCString = FileSystem::fileSystemRepresentation(pluginPath);
+    char* argv[4];
+    argv[0] = const_cast<char*>(binaryPath.data());
+    argv[1] = const_cast<char*>("-scanPlugin");
+    argv[2] = const_cast<char*>(pluginPathCString.data());
+    argv[3] = nullptr;
+
+    // If the disposition of SIGCLD signal is set to SIG_IGN (default)
+    // then the signal will be ignored and g_spawn_sync() will not be
+    // able to return the status.
+    // As a consequence, we make sure that the disposition is set to
+    // SIG_DFL before calling g_spawn_sync().
+#if defined(SIGCLD)
+    struct sigaction action;
+    sigaction(SIGCLD, 0, &action);
+    if (action.sa_handler == SIG_IGN) {
+        action.sa_handler = SIG_DFL;
+        sigaction(SIGCLD, &action, 0);
+    }
+#endif
+
+    int status;
+    GUniqueOutPtr<char> stdOut;
+    GUniqueOutPtr<GError> error;
+    if (!g_spawn_sync(nullptr, argv, nullptr, G_SPAWN_STDERR_TO_DEV_NULL, nullptr, nullptr, &stdOut.outPtr(), nullptr, &status, &error.outPtr())) {
+        WTFLogAlways("Failed to launch %s: %s", argv[0], error->message);
+        return false;
+    }
+
+    if (!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SUCCESS) {
+        WTFLogAlways("Error scanning plugin %s, %s returned %d exit status", argv[2], argv[0], status);
+        return false;
+    }
+
+    if (!stdOut) {
+        WTFLogAlways("Error scanning plugin %s, %s didn't write any output to stdout", argv[2], argv[0]);
+        return false;
+    }
+
+    Vector<String> lines = String::fromUTF8(stdOut.get()).splitAllowingEmptyEntries('\n');
+
+    if (lines.size() < 3) {
+        WTFLogAlways("Error scanning plugin %s, too few lines of output provided", argv[2]);
+        return false;
+    }
+
+    result.name.swap(lines[0]);
+    result.description.swap(lines[1]);
+    result.mimeDescription.swap(lines[2]);
+    return !result.mimeDescription.isEmpty();
+}
+#endif // PLUGIN_ARCHITECTURE(UNIX)
+
+} // namespace WebKit
+
+#endif // ENABLE(PLUGIN_PROCESS)
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/WebPageProxy.h webkitgtk.2.34.0/Source/WebKit/UIProcess/WebPageProxy.h
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/WebPageProxy.h	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/WebPageProxy.h	2021-09-29 11:16:12.687267721 -0500
@@ -2376,6 +2376,12 @@ private:
 
     void setRenderTreeSize(uint64_t treeSize) { m_renderTreeSize = treeSize; }
 
+#if PLATFORM(X11) && ENABLE(NETSCAPE_PLUGIN_API)
+    void createPluginContainer(CompletionHandler<void(uint64_t)>&&);
+    void windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID);
+    void windowedPluginVisibilityDidChange(bool isVisible, uint64_t windowID);
+#endif
+
     void sendWheelEvent(const WebWheelEvent&);
 
     WebWheelEventCoalescer& wheelEventCoalescer();
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/WebPageProxy.messages.in webkitgtk.2.34.0/Source/WebKit/UIProcess/WebPageProxy.messages.in
--- webkitgtk-2.34.0.orig/Source/WebKit/UIProcess/WebPageProxy.messages.in	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/UIProcess/WebPageProxy.messages.in	2021-09-29 11:16:12.687267721 -0500
@@ -387,6 +387,13 @@ messages -> WebPageProxy {
     DictationAlternatives(WebCore::DictationContext dictationContext) -> (Vector<String> alternatives) Synchronous
 #endif
 
+#if PLATFORM(X11) && ENABLE(NETSCAPE_PLUGIN_API)
+    # X11 windowed plugin messages
+    CreatePluginContainer() -> (uint64_t windowID) Synchronous
+    WindowedPluginGeometryDidChange(WebCore::IntRect frameRect, WebCore::IntRect clipRect, uint64_t windowID)
+    WindowedPluginVisibilityDidChange(bool isVisible, uint64_t windowID)
+#endif
+
 #if PLATFORM(IOS_FAMILY)
     CouldNotRestorePageState()
     RestorePageState(std::optional<WebCore::FloatPoint> scrollPosition, WebCore::FloatPoint scrollOrigin, WebCore::RectEdges<float> obscuredInsetsOnSave, double scale)
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/webkitglib-symbols.map webkitgtk.2.34.0/Source/WebKit/webkitglib-symbols.map
--- webkitgtk-2.34.0.orig/Source/WebKit/webkitglib-symbols.map	2021-09-02 05:00:00.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/webkitglib-symbols.map	2021-09-29 11:16:12.687267721 -0500
@@ -7,6 +7,7 @@ global:
     "bmalloc::PerThreadStorage<bmalloc::PerHeapKind<bmalloc::Cache> >::s_key";
     "bmalloc::vmPageSize()::cached";
     "WebKit::NetworkProcessMain(int, char**)";
+    "WebKit::PluginProcessMain(int, char**)";
     "WebKit::WebKitExtensionManager::initialize(WebKit::InjectedBundle*, API::Object*)";
     "WebKit::WebKitExtensionManager::singleton()";
     "WebKit::WebProcessMain(int, char**)";
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/WebProcess/Plugins/Netscape/unix/NetscapePluginUnix.cpp webkitgtk.2.34.0/Source/WebKit/WebProcess/Plugins/Netscape/unix/NetscapePluginUnix.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/WebProcess/Plugins/Netscape/unix/NetscapePluginUnix.cpp	1969-12-31 18:00:00.000000000 -0600
+++ webkitgtk.2.34.0/Source/WebKit/WebProcess/Plugins/Netscape/unix/NetscapePluginUnix.cpp	2021-09-29 11:16:12.687267721 -0500
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2015 Igalia S.L.
+ *
+ * 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "config.h"
+#include "NetscapePluginUnix.h"
+
+#if PLUGIN_ARCHITECTURE(UNIX) && ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "NetscapePlugin.h"
+#include "WebEvent.h"
+#include "WebMouseEvent.h"
+#include "WebWheelEvent.h"
+#include <WebCore/NotImplemented.h>
+#include <WebCore/PlatformDisplay.h>
+
+#if PLATFORM(X11)
+#include "NetscapePluginX11.h"
+#endif
+
+namespace WebKit {
+using namespace WebCore;
+
+void NetscapePlugin::platformPreInitialize()
+{
+}
+
+bool NetscapePlugin::platformPostInitialize()
+{
+#if PLATFORM(X11)
+    if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::X11) {
+        m_impl = NetscapePluginX11::create(*this);
+        if (!m_impl)
+            return false;
+    }
+#endif
+
+    // Windowed plugins need a platform implementation.
+    if (!m_impl)
+        return !m_isWindowed;
+
+    m_npWindow.type = m_impl->windowType();
+    m_npWindow.window = m_impl->window();
+    m_npWindow.ws_info = m_impl->windowSystemInfo();
+    callSetWindow();
+    return true;
+}
+
+void NetscapePlugin::platformDestroy()
+{
+    m_impl = nullptr;
+}
+
+bool NetscapePlugin::platformInvalidate(const IntRect&)
+{
+    notImplemented();
+    return false;
+}
+
+void NetscapePlugin::platformGeometryDidChange()
+{
+    if (!m_impl)
+        return;
+    m_impl->geometryDidChange();
+}
+
+void NetscapePlugin::platformVisibilityDidChange()
+{
+    if (!m_isWindowed || !m_impl)
+        return;
+
+    m_impl->visibilityDidChange();
+}
+
+void NetscapePlugin::platformPaint(GraphicsContext& context, const IntRect& dirtyRect, bool /*isSnapshot*/)
+{
+    if (m_isWindowed || !m_impl)
+        return;
+
+    if (!m_isStarted) {
+        // FIXME: we should paint a missing plugin icon.
+        return;
+    }
+
+    m_impl->paint(context, dirtyRect);
+}
+
+bool NetscapePlugin::platformHandleMouseEvent(const WebMouseEvent& event)
+{
+    if (m_isWindowed || !m_impl)
+        return false;
+
+#if PLATFORM(X11)
+    if ((event.type() == WebEvent::MouseDown || event.type() == WebEvent::MouseUp)
+        && event.button() == WebMouseEvent::RightButton
+        && quirks().contains(PluginQuirks::IgnoreRightClickInWindowlessMode))
+        return false;
+#endif
+
+    return m_impl->handleMouseEvent(event);
+}
+
+bool NetscapePlugin::platformHandleWheelEvent(const WebWheelEvent& event)
+{
+    if (m_isWindowed || !m_impl)
+        return false;
+
+    return m_impl->handleWheelEvent(event);
+}
+
+void NetscapePlugin::platformSetFocus(bool focusIn)
+{
+    if (m_isWindowed || !m_impl)
+        return;
+
+    m_impl->setFocus(focusIn);
+}
+
+bool NetscapePlugin::wantsPluginRelativeNPWindowCoordinates()
+{
+    return true;
+}
+
+bool NetscapePlugin::platformHandleMouseEnterEvent(const WebMouseEvent& event)
+{
+    if (m_isWindowed || !m_impl)
+        return false;
+
+    return m_impl->handleMouseEnterEvent(event);
+}
+
+bool NetscapePlugin::platformHandleMouseLeaveEvent(const WebMouseEvent& event)
+{
+    if (m_isWindowed || !m_impl)
+        return false;
+
+    return m_impl->handleMouseLeaveEvent(event);
+}
+
+bool NetscapePlugin::platformHandleKeyboardEvent(const WebKeyboardEvent& event)
+{
+    // We don't generate other types of keyboard events via WebEventFactory.
+    ASSERT(event.type() == WebEvent::KeyDown || event.type() == WebEvent::KeyUp);
+
+    if (m_isWindowed || !m_impl)
+        return false;
+
+    return m_impl->handleKeyboardEvent(event);
+}
+
+} // namespace WebKit
+
+#endif // PLUGIN_ARCHITECTURE(UNIX) && ENABLE(NETSCAPE_PLUGIN_API)
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/WebProcess/Plugins/Netscape/unix/NetscapePluginUnix.h webkitgtk.2.34.0/Source/WebKit/WebProcess/Plugins/Netscape/unix/NetscapePluginUnix.h
--- webkitgtk-2.34.0.orig/Source/WebKit/WebProcess/Plugins/Netscape/unix/NetscapePluginUnix.h	1969-12-31 18:00:00.000000000 -0600
+++ webkitgtk.2.34.0/Source/WebKit/WebProcess/Plugins/Netscape/unix/NetscapePluginUnix.h	2021-09-29 11:16:12.687267721 -0500
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 Igalia S.L.
+ *
+ * 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+#ifndef NetscapePluginUnix_h
+#define NetscapePluginUnix_h
+
+#if PLUGIN_ARCHITECTURE(UNIX) && ENABLE(NETSCAPE_PLUGIN_API)
+
+#include <WebCore/npruntime_internal.h>
+
+namespace WebCore {
+class GraphicsContext;
+class IntRect;
+}
+
+namespace WebKit {
+
+class WebKeyboardEvent;
+class WebMouseEvent;
+class WebWheelEvent;
+
+class NetscapePluginUnix {
+public:
+    virtual ~NetscapePluginUnix() { }
+    virtual NPWindowType windowType() const = 0;
+    virtual void* window() const = 0;
+    virtual NPSetWindowCallbackStruct* windowSystemInfo() = 0;
+    virtual void geometryDidChange() = 0;
+    virtual void visibilityDidChange() = 0;
+    virtual void paint(WebCore::GraphicsContext&, const WebCore::IntRect&) = 0;
+    virtual bool handleMouseEvent(const WebMouseEvent&) = 0;
+    virtual bool handleWheelEvent(const WebWheelEvent&) = 0;
+    virtual bool handleMouseEnterEvent(const WebMouseEvent&) = 0;
+    virtual bool handleMouseLeaveEvent(const WebMouseEvent&) = 0;
+    virtual bool handleKeyboardEvent(const WebKeyboardEvent&) = 0;
+    virtual void setFocus(bool) = 0;
+};
+
+} // namespace WebKit
+
+#endif // PLUGIN_ARCHITECTURE(UNIX) && ENABLE(NETSCAPE_PLUGIN_API)
+
+#endif // NetscapePluginUnix_h
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/WebProcess/Plugins/Netscape/unix/PluginProxyUnix.cpp webkitgtk.2.34.0/Source/WebKit/WebProcess/Plugins/Netscape/unix/PluginProxyUnix.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/WebProcess/Plugins/Netscape/unix/PluginProxyUnix.cpp	1969-12-31 18:00:00.000000000 -0600
+++ webkitgtk.2.34.0/Source/WebKit/WebProcess/Plugins/Netscape/unix/PluginProxyUnix.cpp	2021-09-29 11:16:12.687267721 -0500
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011 Igalia S.L.
+ *
+ * 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "config.h"
+#include "PluginProxy.h"
+
+#if ENABLE(PLUGIN_PROCESS)
+
+#include <WebCore/NotImplemented.h>
+
+namespace WebKit {
+
+bool PluginProxy::needsBackingStore() const
+{
+    notImplemented();
+    return true;
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(PLUGIN_PROCESS)
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp webkitgtk.2.34.0/Source/WebKit/WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp	1969-12-31 18:00:00.000000000 -0600
+++ webkitgtk.2.34.0/Source/WebKit/WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp	2021-09-30 13:50:37.401507769 -0500
@@ -0,0 +1,542 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 University of Szeged
+ *
+ * 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "config.h"
+#include "NetscapePluginX11.h"
+
+#if PLATFORM(X11) && ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "NetscapePlugin.h"
+#include "PluginController.h"
+#include "WebEvent.h"
+#include "WebMouseEvent.h"
+#include "WebWheelEvent.h"
+#include "WebKeyboardEvent.h"
+#include <WebCore/GraphicsContext.h>
+#include <WebCore/NotImplemented.h>
+#include <WebCore/PlatformDisplayX11.h>
+#include <WebCore/XUniquePtr.h>
+
+#if PLATFORM(GTK)
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+#include <gtk/gtkx.h>
+#endif
+
+#if USE(CAIRO)
+#include <WebCore/GraphicsContextCairo.h>
+#include <WebCore/RefPtrCairo.h>
+#include <cairo/cairo-xlib.h>
+#endif
+
+namespace WebKit {
+using namespace WebCore;
+
+static inline Display* x11HostDisplay()
+{
+    return downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native();
+}
+
+static Display* getPluginDisplay()
+{
+#if PLATFORM(GTK)
+    // Since we're a gdk/gtk app, we'll (probably?) have the same X connection as any gdk-based
+    // plugins, so we can return that. We might want to add other implementations here later.
+    return gdk_x11_get_default_xdisplay();
+#else
+    return nullptr;
+#endif
+}
+
+static inline int x11Screen()
+{
+#if PLATFORM(GTK)
+    return gdk_x11_screen_get_screen_number(gdk_screen_get_default());
+#else
+    return 0;
+#endif
+}
+
+static inline int displayDepth()
+{
+#if PLATFORM(GTK)
+    return gdk_visual_get_depth(gdk_screen_get_system_visual(gdk_screen_get_default()));
+#else
+    return 0;
+#endif
+}
+
+static inline unsigned long rootWindowID()
+{
+#if PLATFORM(GTK)
+    return GDK_ROOT_WINDOW();
+#else
+    return 0;
+#endif
+}
+
+#if PLATFORM(GTK)
+static gboolean socketPlugRemovedCallback(GtkSocket*)
+{
+    // Default action is to destroy the GtkSocket, so we just return TRUE here
+    // to be able to reuse the socket. For some obscure reason, newer versions
+    // of flash plugin remove the plug from the socket, probably because the plug
+    // created by the plugin is re-parented.
+    return TRUE;
+}
+#endif
+
+std::unique_ptr<NetscapePluginX11> NetscapePluginX11::create(NetscapePlugin& plugin)
+{
+#if PLATFORM(GTK)
+    uint64_t windowID = 0;
+#endif
+    if (plugin.isWindowed()) {
+#if PLATFORM(GTK)
+        // NPPVplugiNeedsXEmbed is a boolean value, but at least the
+        // Flash player plugin is using an 'int' instead.
+        int needsXEmbed = 0;
+        plugin.NPP_GetValue(NPPVpluginNeedsXEmbed, &needsXEmbed);
+        if (needsXEmbed) {
+            windowID = plugin.controller()->createPluginContainer();
+            if (!windowID)
+                return nullptr;
+        } else {
+            notImplemented();
+            return nullptr;
+        }
+#else
+        notImplemented();
+        return nullptr;
+#endif
+    }
+
+    Display* display = getPluginDisplay();
+    if (!display)
+        return nullptr;
+
+#if PLATFORM(GTK)
+    if (plugin.isWindowed())
+        return makeUnique<NetscapePluginX11>(plugin, display, windowID);
+#endif
+
+    return makeUnique<NetscapePluginX11>(plugin, display);
+}
+
+NetscapePluginX11::NetscapePluginX11(NetscapePlugin& plugin, Display* display)
+    : m_plugin(plugin)
+    , m_pluginDisplay(display)
+{
+    Display* hostDisplay = x11HostDisplay();
+    int depth = displayDepth();
+    m_setWindowCallbackStruct.display = hostDisplay;
+    m_setWindowCallbackStruct.depth = depth;
+
+    XVisualInfo visualTemplate;
+    visualTemplate.screen = x11Screen();
+    visualTemplate.depth = depth;
+    visualTemplate.c_class = TrueColor;
+    int numMatching;
+    XUniquePtr<XVisualInfo> visualInfo(XGetVisualInfo(hostDisplay, VisualScreenMask | VisualDepthMask | VisualClassMask, &visualTemplate, &numMatching));
+    ASSERT(visualInfo);
+    Visual* visual = visualInfo.get()[0].visual;
+    ASSERT(visual);
+
+    m_setWindowCallbackStruct.type = NP_SETWINDOW;
+    m_setWindowCallbackStruct.visual = visual;
+    m_setWindowCallbackStruct.colormap = XCreateColormap(hostDisplay, rootWindowID(), visual, AllocNone);
+}
+
+#if PLATFORM(GTK)
+NetscapePluginX11::NetscapePluginX11(NetscapePlugin& plugin, Display* display, uint64_t windowID)
+    : m_plugin(plugin)
+    , m_pluginDisplay(display)
+{
+    // It seems flash needs the socket to be in the same process,
+    // I guess it uses gdk_window_lookup(), so we create a new socket here
+    // containing a plug with the UI process socket embedded.
+    m_platformPluginWidget = gtk_plug_new(static_cast<Window>(windowID));
+
+    // Hide the GtkPlug on delete-event since we assume the widget is valid while the plugin is active.
+    // platformDestroy() will be called anyway right after the delete-event.
+    g_signal_connect(m_platformPluginWidget, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), nullptr);
+
+    GtkWidget* socket = gtk_socket_new();
+    // Do not show the plug widget until the socket is connected.
+    g_signal_connect_swapped(socket, "plug-added", G_CALLBACK(gtk_widget_show), m_platformPluginWidget);
+    g_signal_connect(socket, "plug-removed", G_CALLBACK(socketPlugRemovedCallback), nullptr);
+    gtk_container_add(GTK_CONTAINER(m_platformPluginWidget), socket);
+    gtk_widget_show(socket);
+
+    Display* hostDisplay = x11HostDisplay();
+    m_npWindowID = gtk_socket_get_id(GTK_SOCKET(socket));
+    GdkWindow* window = gtk_widget_get_window(socket);
+    m_setWindowCallbackStruct.type = NP_SETWINDOW;
+    m_setWindowCallbackStruct.display = GDK_WINDOW_XDISPLAY(window);
+    m_setWindowCallbackStruct.visual = GDK_VISUAL_XVISUAL(gdk_window_get_visual(window));
+    m_setWindowCallbackStruct.depth = gdk_visual_get_depth(gdk_window_get_visual(window));
+    m_setWindowCallbackStruct.colormap = XCreateColormap(hostDisplay, GDK_ROOT_WINDOW(), m_setWindowCallbackStruct.visual, AllocNone);
+
+    XFlush(hostDisplay);
+}
+#endif
+
+NetscapePluginX11::~NetscapePluginX11()
+{
+    XFreeColormap(x11HostDisplay(), m_setWindowCallbackStruct.colormap);
+
+    m_drawable.reset();
+
+#if PLATFORM(GTK)
+    if (m_platformPluginWidget)
+        gtk_widget_destroy(m_platformPluginWidget);
+#endif
+}
+
+NPWindowType NetscapePluginX11::windowType() const
+{
+    return m_plugin.isWindowed() ? NPWindowTypeWindow : NPWindowTypeDrawable;
+}
+
+void* NetscapePluginX11::window() const
+{
+#if PLATFORM(GTK)
+    return m_plugin.isWindowed() ? GINT_TO_POINTER(m_npWindowID) : nullptr;
+#else
+    return nullptr;
+#endif
+}
+
+void NetscapePluginX11::geometryDidChange()
+{
+    if (m_plugin.isWindowed()) {
+        uint64_t windowID = 0;
+#if PLATFORM(GTK)
+        if (!gtk_plug_get_embedded(GTK_PLUG(m_platformPluginWidget)))
+            return;
+        windowID = static_cast<uint64_t>(GDK_WINDOW_XID(gtk_plug_get_socket_window(GTK_PLUG(m_platformPluginWidget))));
+#endif
+        m_plugin.controller()->windowedPluginGeometryDidChange(m_plugin.frameRectInWindowCoordinates(), m_plugin.clipRect(), windowID);
+        return;
+    }
+
+    m_drawable.reset();
+    if (m_plugin.size().isEmpty())
+        return;
+
+    m_drawable = XCreatePixmap(x11HostDisplay(), rootWindowID(), m_plugin.size().width(), m_plugin.size().height(), displayDepth());
+    XSync(x11HostDisplay(), false); // Make sure that the server knows about the Drawable.
+}
+
+void NetscapePluginX11::visibilityDidChange()
+{
+    ASSERT(m_plugin.isWindowed());
+    uint64_t windowID = 0;
+#if PLATFORM(GTK)
+    if (!gtk_plug_get_embedded(GTK_PLUG(m_platformPluginWidget)))
+        return;
+    windowID = static_cast<uint64_t>(GDK_WINDOW_XID(gtk_plug_get_socket_window(GTK_PLUG(m_platformPluginWidget))));
+#endif
+    m_plugin.controller()->windowedPluginVisibilityDidChange(m_plugin.isVisible(), windowID);
+    m_plugin.controller()->windowedPluginGeometryDidChange(m_plugin.frameRectInWindowCoordinates(), m_plugin.clipRect(), windowID);
+}
+
+void NetscapePluginX11::paint(GraphicsContext& context, const IntRect& dirtyRect)
+{
+    ASSERT(!m_plugin.isWindowed());
+
+    if (context.paintingDisabled() || !m_drawable)
+        return;
+
+    XEvent xevent;
+    memset(&xevent, 0, sizeof(XEvent));
+    XGraphicsExposeEvent& exposeEvent = xevent.xgraphicsexpose;
+    exposeEvent.type = GraphicsExpose;
+    exposeEvent.display = x11HostDisplay();
+    exposeEvent.drawable = m_drawable.get();
+
+    IntRect exposedRect(dirtyRect);
+    exposeEvent.x = exposedRect.x();
+    exposeEvent.y = exposedRect.y();
+
+    // Note: in transparent mode Flash thinks width is the right and height is the bottom.
+    // We should take it into account if we want to support transparency.
+    exposeEvent.width = exposedRect.width();
+    exposeEvent.height = exposedRect.height();
+
+    m_plugin.NPP_HandleEvent(&xevent);
+
+    if (m_pluginDisplay != x11HostDisplay())
+        XSync(m_pluginDisplay, false);
+
+#if PLATFORM(GTK)
+    RefPtr<cairo_surface_t> drawableSurface = adoptRef(cairo_xlib_surface_create(m_pluginDisplay, m_drawable.get(),
+        m_setWindowCallbackStruct.visual, m_plugin.size().width(), m_plugin.size().height()));
+    cairo_t* cr = context.platformContext()->cr();
+    cairo_save(cr);
+
+    cairo_set_source_surface(cr, drawableSurface.get(), 0, 0);
+
+    cairo_rectangle(cr, exposedRect.x(), exposedRect.y(), exposedRect.width(), exposedRect.height());
+    cairo_clip(cr);
+    cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+    cairo_paint(cr);
+
+    cairo_restore(cr);
+#else
+    notImplemented();
+#endif
+}
+
+static inline void initializeXEvent(XEvent& event)
+{
+    memset(&event, 0, sizeof(XEvent));
+    event.xany.serial = 0;
+    event.xany.send_event = false;
+    event.xany.display = x11HostDisplay();
+    event.xany.window = 0;
+}
+
+static inline uint64_t xTimeStamp(WallTime timestamp)
+{
+    return timestamp.secondsSinceEpoch().milliseconds();
+}
+
+static inline unsigned xKeyModifiers(const WebEvent& event)
+{
+    unsigned xModifiers = 0;
+    if (event.controlKey())
+        xModifiers |= ControlMask;
+    if (event.shiftKey())
+        xModifiers |= ShiftMask;
+    if (event.altKey())
+        xModifiers |= Mod1Mask;
+    if (event.metaKey())
+        xModifiers |= Mod4Mask;
+
+    return xModifiers;
+}
+
+template <typename XEventType, typename WebEventType>
+static inline void setCommonMouseEventFields(XEventType& xEvent, const WebEventType& webEvent, const WebCore::IntPoint& pluginLocation)
+{
+    xEvent.root = rootWindowID();
+    xEvent.subwindow = 0;
+    xEvent.time = xTimeStamp(webEvent.timestamp());
+    xEvent.x = webEvent.position().x() - pluginLocation.x();
+    xEvent.y = webEvent.position().y() - pluginLocation.y();
+    xEvent.x_root = webEvent.globalPosition().x();
+    xEvent.y_root = webEvent.globalPosition().y();
+    xEvent.state = xKeyModifiers(webEvent);
+    xEvent.same_screen = true;
+}
+
+static inline void setXMotionEventFields(XEvent& xEvent, const WebMouseEvent& webEvent, const WebCore::IntPoint& pluginLocation)
+{
+    XMotionEvent& xMotion = xEvent.xmotion;
+    setCommonMouseEventFields(xMotion, webEvent, pluginLocation);
+    xMotion.type = MotionNotify;
+}
+
+static inline void setXButtonEventFields(XEvent& xEvent, const WebMouseEvent& webEvent, const WebCore::IntPoint& pluginLocation)
+{
+    XButtonEvent& xButton = xEvent.xbutton;
+    setCommonMouseEventFields(xButton, webEvent, pluginLocation);
+
+    xButton.type = (webEvent.type() == WebEvent::MouseDown) ? ButtonPress : ButtonRelease;
+    switch (webEvent.button()) {
+    case WebMouseEvent::LeftButton:
+        xButton.button = Button1;
+        break;
+    case WebMouseEvent::MiddleButton:
+        xButton.button = Button2;
+        break;
+    case WebMouseEvent::RightButton:
+        xButton.button = Button3;
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+}
+
+static inline void setXButtonEventFieldsByWebWheelEvent(XEvent& xEvent, const WebWheelEvent& webEvent, const WebCore::IntPoint& pluginLocation)
+{
+    XButtonEvent& xButton = xEvent.xbutton;
+    setCommonMouseEventFields(xButton, webEvent, pluginLocation);
+
+    xButton.type = ButtonPress;
+    FloatSize ticks = webEvent.wheelTicks();
+    if (ticks.height()) {
+        if (ticks.height() > 0)
+            xButton.button = 4; // up
+        else
+            xButton.button = 5; // down
+    } else {
+        if (ticks.width() > 0)
+            xButton.button = 6; // left
+        else
+            xButton.button = 7; // right
+    }
+}
+
+static inline void setXCrossingEventFields(XEvent& xEvent, const WebMouseEvent& webEvent, const WebCore::IntPoint& pluginLocation, int type)
+{
+    XCrossingEvent& xCrossing = xEvent.xcrossing;
+    setCommonMouseEventFields(xCrossing, webEvent, pluginLocation);
+
+    xCrossing.type = type;
+    xCrossing.mode = NotifyNormal;
+    xCrossing.detail = NotifyDetailNone;
+    xCrossing.focus = false;
+}
+
+bool NetscapePluginX11::handleMouseEvent(const WebMouseEvent& event)
+{
+    ASSERT(!m_plugin.isWindowed());
+
+    XEvent xEvent;
+    initializeXEvent(xEvent);
+
+    switch (event.type()) {
+    case WebEvent::MouseDown:
+    case WebEvent::MouseUp:
+        setXButtonEventFields(xEvent, event, m_plugin.convertToRootView(IntPoint()));
+        break;
+    case WebEvent::MouseMove:
+        setXMotionEventFields(xEvent, event, m_plugin.convertToRootView(IntPoint()));
+        break;
+    case WebEvent::MouseForceChanged:
+    case WebEvent::MouseForceDown:
+    case WebEvent::MouseForceUp:
+    case WebEvent::NoType:
+    case WebEvent::Wheel:
+    case WebEvent::KeyDown:
+    case WebEvent::KeyUp:
+    case WebEvent::RawKeyDown:
+    case WebEvent::Char:
+#if ENABLE(TOUCH_EVENTS)
+    case WebEvent::TouchStart:
+    case WebEvent::TouchMove:
+    case WebEvent::TouchEnd:
+    case WebEvent::TouchCancel:
+#endif
+        return false;
+    }
+
+    return !m_plugin.NPP_HandleEvent(&xEvent);
+}
+
+// We undefine these constants in npruntime_internal.h to avoid collision
+// with WebKit and platform headers. Values are defined in X.h.
+const int kKeyPressType = 2;
+const int kKeyReleaseType = 3;
+const int kFocusInType = 9;
+const int kFocusOutType = 10;
+
+bool NetscapePluginX11::handleWheelEvent(const WebWheelEvent& event)
+{
+    ASSERT(!m_plugin.isWindowed());
+
+    XEvent xEvent;
+    initializeXEvent(xEvent);
+    setXButtonEventFieldsByWebWheelEvent(xEvent, event, m_plugin.convertToRootView(IntPoint()));
+
+    return !m_plugin.NPP_HandleEvent(&xEvent);
+}
+
+void NetscapePluginX11::setFocus(bool focusIn)
+{
+    ASSERT(!m_plugin.isWindowed());
+
+    XEvent xEvent;
+    initializeXEvent(xEvent);
+    XFocusChangeEvent& focusEvent = xEvent.xfocus;
+    focusEvent.type = focusIn ? kFocusInType : kFocusOutType;
+    focusEvent.mode = NotifyNormal;
+    focusEvent.detail = NotifyDetailNone;
+
+    m_plugin.NPP_HandleEvent(&xEvent);
+}
+
+bool NetscapePluginX11::handleMouseEnterEvent(const WebMouseEvent& event)
+{
+    ASSERT(!m_plugin.isWindowed());
+
+    XEvent xEvent;
+    initializeXEvent(xEvent);
+    setXCrossingEventFields(xEvent, event, m_plugin.convertToRootView(IntPoint()), EnterNotify);
+
+    return !m_plugin.NPP_HandleEvent(&xEvent);
+}
+
+bool NetscapePluginX11::handleMouseLeaveEvent(const WebMouseEvent& event)
+{
+    ASSERT(!m_plugin.isWindowed());
+
+    XEvent xEvent;
+    initializeXEvent(xEvent);
+    setXCrossingEventFields(xEvent, event, m_plugin.convertToRootView(IntPoint()), LeaveNotify);
+
+    return !m_plugin.NPP_HandleEvent(&xEvent);
+}
+
+static inline void setXKeyEventFields(XEvent& xEvent, const WebKeyboardEvent& webEvent)
+{
+    xEvent.xany.type = (webEvent.type() == WebEvent::KeyDown) ? kKeyPressType : kKeyReleaseType;
+    XKeyEvent& xKey = xEvent.xkey;
+    xKey.root = rootWindowID();
+    xKey.subwindow = 0;
+    xKey.time = xTimeStamp(webEvent.timestamp());
+    xKey.state = xKeyModifiers(webEvent);
+    xKey.keycode = webEvent.nativeVirtualKeyCode();
+
+    xKey.same_screen = true;
+
+    // Key events propagated to the plugin does not need to have position.
+    // source: https://developer.mozilla.org/en/NPEvent
+    xKey.x = 0;
+    xKey.y = 0;
+    xKey.x_root = 0;
+    xKey.y_root = 0;
+}
+
+bool NetscapePluginX11::handleKeyboardEvent(const WebKeyboardEvent& event)
+{
+    ASSERT(!m_plugin.isWindowed());
+    // We don't generate other types of keyboard events via WebEventFactory.
+    ASSERT(event.type() == WebEvent::KeyDown || event.type() == WebEvent::KeyUp);
+
+    XEvent xEvent;
+    initializeXEvent(xEvent);
+    setXKeyEventFields(xEvent, event);
+
+    return !m_plugin.NPP_HandleEvent(&xEvent);
+}
+
+} // namespace WebKit
+
+#endif // PLATFORM(X11) && ENABLE(NETSCAPE_PLUGIN_API)
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/WebProcess/Plugins/Netscape/x11/NetscapePluginX11.h webkitgtk.2.34.0/Source/WebKit/WebProcess/Plugins/Netscape/x11/NetscapePluginX11.h
--- webkitgtk-2.34.0.orig/Source/WebKit/WebProcess/Plugins/Netscape/x11/NetscapePluginX11.h	1969-12-31 18:00:00.000000000 -0600
+++ webkitgtk.2.34.0/Source/WebKit/WebProcess/Plugins/Netscape/x11/NetscapePluginX11.h	2021-09-29 11:16:12.687267721 -0500
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 University of Szeged
+ *
+ * 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+#ifndef NetscapePluginX11_h
+#define NetscapePluginX11_h
+
+#if PLATFORM(X11) && ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "NetscapePluginUnix.h"
+#include <WebCore/XUniqueResource.h>
+
+namespace WebKit {
+
+class NetscapePlugin;
+
+class NetscapePluginX11 final : public NetscapePluginUnix {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static std::unique_ptr<NetscapePluginX11> create(NetscapePlugin&);
+    NetscapePluginX11(NetscapePlugin&, Display*);
+#if PLATFORM(GTK)
+    NetscapePluginX11(NetscapePlugin&, Display*, uint64_t windowID);
+#endif
+    virtual ~NetscapePluginX11();
+
+private:
+    NPWindowType windowType() const override;
+    void* window() const override;
+    NPSetWindowCallbackStruct* windowSystemInfo() override { return &m_setWindowCallbackStruct; }
+    void geometryDidChange() override;
+    void visibilityDidChange() override;
+    void paint(WebCore::GraphicsContext&, const WebCore::IntRect&) override;
+    bool handleMouseEvent(const WebMouseEvent&) override;
+    bool handleWheelEvent(const WebWheelEvent&) override;
+    bool handleMouseEnterEvent(const WebMouseEvent&) override;
+    bool handleMouseLeaveEvent(const WebMouseEvent&) override;
+    bool handleKeyboardEvent(const WebKeyboardEvent&) override;
+    void setFocus(bool) override;
+
+    NetscapePlugin& m_plugin;
+    Display* m_pluginDisplay { nullptr };
+    WebCore::XUniquePixmap m_drawable;
+    NPSetWindowCallbackStruct m_setWindowCallbackStruct;
+#if PLATFORM(GTK)
+    unsigned long m_npWindowID { 0 };
+    GtkWidget* m_platformPluginWidget { nullptr };
+#endif
+};
+} // namespace WebKit
+
+#endif // PLATFORM(X11) && ENABLE(NETSCAPE_PLUGIN_API)
+
+#endif // NetscapePluginX11_h
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/WebProcess/Plugins/PluginController.h webkitgtk.2.34.0/Source/WebKit/WebProcess/Plugins/PluginController.h
--- webkitgtk-2.34.0.orig/Source/WebKit/WebProcess/Plugins/PluginController.h	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/WebProcess/Plugins/PluginController.h	2021-09-29 11:16:12.687267721 -0500
@@ -145,6 +145,13 @@ public:
     // Decrements a counter that, when it reaches 0, stops preventing the plug-in from being destroyed.
     virtual void unprotectPluginFromDestruction() = 0;
 
+#if PLATFORM(X11) && ENABLE(NETSCAPE_PLUGIN_API)
+    // Create a plugin container for windowed plugins
+    virtual uint64_t createPluginContainer() = 0;
+    virtual void windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID) = 0;
+    virtual void windowedPluginVisibilityDidChange(bool isVisible, uint64_t windowID) = 0;
+#endif
+
     // Called when the a plug-in instance is successfully initialized, either synchronously or asynchronously.
     virtual void didInitializePlugin() = 0;
     
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/WebProcess/Plugins/PluginView.cpp webkitgtk.2.34.0/Source/WebKit/WebProcess/Plugins/PluginView.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/WebProcess/Plugins/PluginView.cpp	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/WebProcess/Plugins/PluginView.cpp	2021-09-29 11:16:12.687267721 -0500
@@ -74,6 +74,10 @@
 #include <wtf/CompletionHandler.h>
 #include <wtf/text/StringBuilder.h>
 
+#if PLATFORM(X11) && ENABLE(NETSCAPE_PLUGIN_API)
+#include <WebCore/PlatformDisplay.h>
+#endif
+
 namespace WebKit {
 using namespace JSC;
 using namespace WebCore;
@@ -1492,6 +1496,26 @@ void PluginView::pluginProcessCrashed()
     Widget::invalidate();
 }
 
+#if PLATFORM(X11) && ENABLE(NETSCAPE_PLUGIN_API)
+uint64_t PluginView::createPluginContainer()
+{
+    uint64_t windowID = 0;
+    if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::X11)
+        m_webPage->sendSync(Messages::WebPageProxy::CreatePluginContainer(), Messages::WebPageProxy::CreatePluginContainer::Reply(windowID));
+    return windowID;
+}
+
+void PluginView::windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID)
+{
+    m_webPage->send(Messages::WebPageProxy::WindowedPluginGeometryDidChange(frameRect, clipRect, windowID));
+}
+
+void PluginView::windowedPluginVisibilityDidChange(bool isVisible, uint64_t windowID)
+{
+    m_webPage->send(Messages::WebPageProxy::WindowedPluginVisibilityDidChange(isVisible, windowID));
+}
+#endif
+
 #if PLATFORM(COCOA)
 void PluginView::pluginFocusOrWindowFocusChanged(bool pluginHasFocusAndWindowHasFocus)
 {
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/WebProcess/Plugins/PluginView.h webkitgtk.2.34.0/Source/WebKit/WebProcess/Plugins/PluginView.h
--- webkitgtk-2.34.0.orig/Source/WebKit/WebProcess/Plugins/PluginView.h	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/WebProcess/Plugins/PluginView.h	2021-09-29 11:16:12.687267721 -0500
@@ -221,6 +221,11 @@ private:
     bool artificialPluginInitializationDelayEnabled() const override;
     void protectPluginFromDestruction() override;
     void unprotectPluginFromDestruction() override;
+#if PLATFORM(X11) && ENABLE(NETSCAPE_PLUGIN_API)
+    uint64_t createPluginContainer() override;
+    void windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID) override;
+    void windowedPluginVisibilityDidChange(bool isVisible, uint64_t windowID) override;
+#endif
 
     void didInitializePlugin() override;
     void didFailToInitializePlugin() override;
diff -urpN webkitgtk-2.34.0.orig/Source/WebKit/WebProcess/Plugins/WebPluginInfoProvider.cpp webkitgtk.2.34.0/Source/WebKit/WebProcess/Plugins/WebPluginInfoProvider.cpp
--- webkitgtk-2.34.0.orig/Source/WebKit/WebProcess/Plugins/WebPluginInfoProvider.cpp	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Source/WebKit/WebProcess/Plugins/WebPluginInfoProvider.cpp	2021-09-29 11:16:12.687267721 -0500
@@ -114,7 +114,7 @@ Vector<WebCore::PluginInfo> WebPluginInf
 }
 
 #if ENABLE(NETSCAPE_PLUGIN_API)
-void WebPluginInfoProvider::populatePluginCache(const WebCore::Page&)
+void WebPluginInfoProvider::populatePluginCache(const WebCore::Page& page)
 {
     if (!m_pluginCacheIsPopulated) {
 #if PLATFORM(COCOA)
diff -urpN webkitgtk-2.34.0.orig/Tools/PlatformGTK.cmake webkitgtk.2.34.0/Tools/PlatformGTK.cmake
--- webkitgtk-2.34.0.orig/Tools/PlatformGTK.cmake	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Tools/PlatformGTK.cmake	2021-09-29 11:16:12.687267721 -0500
@@ -7,6 +7,10 @@ if (DEVELOPER_MODE)
     if (ENABLE_API_TESTS)
         add_subdirectory(TestWebKitAPI/glib)
     endif ()
+
+    if (ENABLE_NETSCAPE_PLUGIN_API)
+        add_subdirectory(DumpRenderTree/TestNetscapePlugIn)
+    endif ()
 endif ()
 
 if (ENABLE_MINIBROWSER)
diff -urpN webkitgtk-2.34.0.orig/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitSettings.cpp webkitgtk.2.34.0/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitSettings.cpp
--- webkitgtk-2.34.0.orig/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitSettings.cpp	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitSettings.cpp	2021-09-29 11:16:12.691267741 -0500
@@ -82,6 +82,11 @@ static void testWebKitSettings(Test*, gc
     webkit_settings_set_enable_frame_flattening(settings, TRUE);
     g_assert_true(webkit_settings_get_enable_frame_flattening(settings));
 
+    // Plugins are enabled by default.
+    g_assert_true(webkit_settings_get_enable_plugins(settings));
+    webkit_settings_set_enable_plugins(settings, FALSE);
+    g_assert_false(webkit_settings_get_enable_plugins(settings));
+
     // Java is enabled by default.
     g_assert_true(webkit_settings_get_enable_java(settings));
     webkit_settings_set_enable_java(settings, FALSE);
diff -urpN webkitgtk-2.34.0.orig/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebContext.cpp webkitgtk.2.34.0/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebContext.cpp
--- webkitgtk-2.34.0.orig/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebContext.cpp	2021-09-01 04:16:51.000000000 -0500
+++ webkitgtk.2.34.0/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebContext.cpp	2021-09-29 11:16:12.691267741 -0500
@@ -77,6 +77,84 @@ static void testWebContextEphemeral(Test
     g_assert_true(webkit_web_context_is_ephemeral(context.get()));
 }
 
+#if ENABLE(NETSCAPE_PLUGIN_API)
+class PluginsTest: public Test {
+public:
+    MAKE_GLIB_TEST_FIXTURE(PluginsTest);
+
+    PluginsTest()
+        : m_mainLoop(g_main_loop_new(nullptr, TRUE))
+        , m_plugins(nullptr)
+    {
+        webkit_web_context_set_additional_plugins_directory(m_webContext.get(), WEBKIT_TEST_PLUGIN_DIR);
+    }
+
+    ~PluginsTest()
+    {
+        g_main_loop_unref(m_mainLoop);
+        g_list_free_full(m_plugins, g_object_unref);
+    }
+
+    static void getPluginsAsyncReadyCallback(GObject*, GAsyncResult* result, PluginsTest* test)
+    {
+        test->m_plugins = webkit_web_context_get_plugins_finish(test->m_webContext.get(), result, nullptr);
+        g_main_loop_quit(test->m_mainLoop);
+    }
+
+    GList* getPlugins()
+    {
+        g_list_free_full(m_plugins, g_object_unref);
+        webkit_web_context_get_plugins(m_webContext.get(), nullptr, reinterpret_cast<GAsyncReadyCallback>(getPluginsAsyncReadyCallback), this);
+        g_main_loop_run(m_mainLoop);
+        return m_plugins;
+    }
+
+    GMainLoop* m_mainLoop;
+    GList* m_plugins;
+};
+
+static void testWebContextGetPlugins(PluginsTest* test, gconstpointer)
+{
+    GList* plugins = test->getPlugins();
+    g_assert_nonnull(plugins);
+
+    GRefPtr<WebKitPlugin> testPlugin;
+    for (GList* item = plugins; item; item = g_list_next(item)) {
+        WebKitPlugin* plugin = WEBKIT_PLUGIN(item->data);
+        test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(plugin));
+        if (!g_strcmp0(webkit_plugin_get_name(plugin), "WebKit Test PlugIn")) {
+            testPlugin = plugin;
+            break;
+        }
+    }
+    g_assert_true(WEBKIT_IS_PLUGIN(testPlugin.get()));
+
+    char normalizedPath[PATH_MAX];
+    g_assert_nonnull(realpath(WEBKIT_TEST_PLUGIN_DIR, normalizedPath));
+    GUniquePtr<char> pluginPath(g_build_filename(normalizedPath, "libTestNetscapePlugIn.so", nullptr));
+    g_assert_cmpstr(webkit_plugin_get_path(testPlugin.get()), ==, pluginPath.get());
+    g_assert_cmpstr(webkit_plugin_get_description(testPlugin.get()), ==, "Simple Netscape® plug-in that handles test content for WebKit");
+    GList* mimeInfoList = webkit_plugin_get_mime_info_list(testPlugin.get());
+    g_assert_nonnull(mimeInfoList);
+    g_assert_cmpuint(g_list_length(mimeInfoList), ==, 2);
+
+    WebKitMimeInfo* mimeInfo = static_cast<WebKitMimeInfo*>(mimeInfoList->data);
+    g_assert_cmpstr(webkit_mime_info_get_mime_type(mimeInfo), ==, "image/png");
+    g_assert_cmpstr(webkit_mime_info_get_description(mimeInfo), ==, "png image");
+    const gchar* const* extensions = webkit_mime_info_get_extensions(mimeInfo);
+    g_assert_nonnull(extensions);
+    g_assert_cmpstr(extensions[0], ==, "png");
+
+    mimeInfoList = g_list_next(mimeInfoList);
+    mimeInfo = static_cast<WebKitMimeInfo*>(mimeInfoList->data);
+    g_assert_cmpstr(webkit_mime_info_get_mime_type(mimeInfo), ==, "application/x-webkit-test-netscape");
+    g_assert_cmpstr(webkit_mime_info_get_description(mimeInfo), ==, "test netscape content");
+    extensions = webkit_mime_info_get_extensions(mimeInfo);
+    g_assert_nonnull(extensions);
+    g_assert_cmpstr(extensions[0], ==, "testnetscape");
+}
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
+
 static const char* kBarHTML = "<html><body>Bar</body></html>";
 static const char* kEchoHTMLFormat = "<html><body>%s</body></html>";
 static const char* errorDomain = "test";
@@ -877,6 +955,9 @@ void beforeAll()
 
     Test::add("WebKitWebContext", "default-context", testWebContextDefault);
     Test::add("WebKitWebContext", "ephemeral", testWebContextEphemeral);
+#if ENABLE(NETSCAPE_PLUGIN_API)
+    PluginsTest::add("WebKitWebContext", "get-plugins", testWebContextGetPlugins);
+#endif
     URISchemeTest::add("WebKitWebContext", "uri-scheme", testWebContextURIScheme);
     // FIXME: implement spellchecker in WPE.
 #if PLATFORM(GTK)
