/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2000 Stefan Schimanski (1Stein@gmx.de)
 * Copyright (C) 2004-2019 Apple Inc. All rights reserved.
 *
 * 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.
 */

#include "config.h"
#include "HTMLPlugInElement.h"

#include "BridgeJSC.h"
#include "CSSPropertyNames.h"
#include "Document.h"
#include "Event.h"
#include "EventHandler.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "FrameTree.h"
#include "HTMLNames.h"
#include "HitTestResult.h"
#include "Logging.h"
#include "MIMETypeRegistry.h"
#include "Page.h"
#include "PluginData.h"
#include "PluginReplacement.h"
#include "PluginViewBase.h"
#include "RenderEmbeddedObject.h"
#include "RenderLayer.h"
#include "RenderView.h"
#include "RenderWidget.h"
#include "ScriptController.h"
#include "Settings.h"
#include "ShadowRoot.h"
#include "SubframeLoader.h"
#include "Widget.h"
#include <wtf/IsoMallocInlines.h>

#if ENABLE(NETSCAPE_PLUGIN_API)
#include "npruntime_impl.h"
#endif

#if PLATFORM(COCOA)
#include "QuickTimePluginReplacement.h"
#include "YouTubePluginReplacement.h"
#endif

namespace WebCore {

WTF_MAKE_ISO_ALLOCATED_IMPL(HTMLPlugInElement);

using namespace HTMLNames;

HTMLPlugInElement::HTMLPlugInElement(const QualifiedName& tagName, Document& document)
    : HTMLFrameOwnerElement(tagName, document)
    , m_swapRendererTimer(*this, &HTMLPlugInElement::swapRendererTimerFired)
{
    setHasCustomStyleResolveCallbacks();
}

HTMLPlugInElement::~HTMLPlugInElement()
{
    ASSERT(!m_instance); // cleared in detach()
}

bool HTMLPlugInElement::willRespondToMouseClickEvents()
{
    if (isDisabledFormControl())
        return false;
    auto renderer = this->renderer();
    return renderer && renderer->isWidget();
}

void HTMLPlugInElement::willDetachRenderers()
{
    m_instance = nullptr;

    if (m_isCapturingMouseEvents) {
        if (RefPtr<Frame> frame = document().frame())
            frame->eventHandler().setCapturingMouseEventsElement(nullptr);
        m_isCapturingMouseEvents = false;
    }
}

void HTMLPlugInElement::resetInstance()
{
    m_instance = nullptr;
}

JSC::Bindings::Instance* HTMLPlugInElement::bindingsInstance()
{
    RefPtr frame = document().frame();
    if (!frame)
        return nullptr;

    // If the host dynamically turns off JavaScript (or Java) we will still return
    // the cached allocated Bindings::Instance.  Not supporting this edge-case is OK.

    if (!m_instance) {
        if (RefPtr widget = pluginWidget())
            m_instance = frame->script().createScriptInstanceForWidget(widget.get());
    }
    return m_instance.get();
}

bool HTMLPlugInElement::guardedDispatchBeforeLoadEvent(const String& sourceURL)
{
    // FIXME: Our current plug-in loading design can't guarantee the following
    // assertion is true, since plug-in loading can be initiated during layout,
    // and synchronous layout can be initiated in a beforeload event handler!
    // See <http://webkit.org/b/71264>.
    // ASSERT(!m_inBeforeLoadEventHandler);
    m_inBeforeLoadEventHandler = true;
    // static_cast is used to avoid a compile error since dispatchBeforeLoadEvent
    // is intentionally undefined on this class.
    bool beforeLoadAllowedLoad = static_cast<HTMLFrameOwnerElement*>(this)->dispatchBeforeLoadEvent(sourceURL);
    m_inBeforeLoadEventHandler = false;
    return beforeLoadAllowedLoad;
}

Widget* HTMLPlugInElement::pluginWidget(PluginLoadingPolicy loadPolicy) const
{
    if (m_inBeforeLoadEventHandler) {
        // The plug-in hasn't loaded yet, and it makes no sense to try to load if beforeload handler happened to touch the plug-in element.
        // That would recursively call beforeload for the same element.
        return nullptr;
    }

    RenderWidget* renderWidget = loadPolicy == PluginLoadingPolicy::Load ? renderWidgetLoadingPlugin() : this->renderWidget();
    if (!renderWidget)
        return nullptr;

    return renderWidget->widget();
}

RenderWidget* HTMLPlugInElement::renderWidgetLoadingPlugin() const
{
    RefPtr<FrameView> view = document().view();
    if (!view || (!view->inUpdateEmbeddedObjects() && !view->layoutContext().isInLayout() && !view->isPainting())) {
        // Needs to load the plugin immediatedly because this function is called
        // when JavaScript code accesses the plugin.
        // FIXME: <rdar://16893708> Check if dispatching events here is safe.
        document().updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks::Synchronously);
    }
    return renderWidget(); // This will return nullptr if the renderer is not a RenderWidget.
}

bool HTMLPlugInElement::hasPresentationalHintsForAttribute(const QualifiedName& name) const
{
    if (name == widthAttr || name == heightAttr || name == vspaceAttr || name == hspaceAttr || name == alignAttr)
        return true;
    return HTMLFrameOwnerElement::hasPresentationalHintsForAttribute(name);
}

void HTMLPlugInElement::collectPresentationalHintsForAttribute(const QualifiedName& name, const AtomString& value, MutableStyleProperties& style)
{
    if (name == widthAttr)
        addHTMLLengthToStyle(style, CSSPropertyWidth, value);
    else if (name == heightAttr)
        addHTMLLengthToStyle(style, CSSPropertyHeight, value);
    else if (name == vspaceAttr) {
        addHTMLLengthToStyle(style, CSSPropertyMarginTop, value);
        addHTMLLengthToStyle(style, CSSPropertyMarginBottom, value);
    } else if (name == hspaceAttr) {
        addHTMLLengthToStyle(style, CSSPropertyMarginLeft, value);
        addHTMLLengthToStyle(style, CSSPropertyMarginRight, value);
    } else if (name == alignAttr)
        applyAlignmentAttributeToStyle(value, style);
    else
        HTMLFrameOwnerElement::collectPresentationalHintsForAttribute(name, value, style);
}

void HTMLPlugInElement::defaultEventHandler(Event& event)
{
    // Firefox seems to use a fake event listener to dispatch events to plug-in (tested with mouse events only).
    // This is observable via different order of events - in Firefox, event listeners specified in HTML attributes fires first, then an event
    // gets dispatched to plug-in, and only then other event listeners fire. Hopefully, this difference does not matter in practice.

    // FIXME: Mouse down and scroll events are passed down to plug-in via custom code in EventHandler; these code paths should be united.

    auto renderer = this->renderer();
    if (!is<RenderWidget>(renderer))
        return;

    if (is<RenderEmbeddedObject>(*renderer) && downcast<RenderEmbeddedObject>(*renderer).isPluginUnavailable())
        downcast<RenderEmbeddedObject>(*renderer).handleUnavailablePluginIndicatorEvent(&event);

    // Don't keep the widget alive over the defaultEventHandler call, since that can do things like navigate.
    {
        RefPtr<Widget> widget = downcast<RenderWidget>(*renderer).widget();
        if (!widget)
            return;
        widget->handleEvent(event);
        if (event.defaultHandled())
            return;
    }
    HTMLFrameOwnerElement::defaultEventHandler(event);
}

bool HTMLPlugInElement::isKeyboardFocusable(KeyboardEvent*) const
{
    // FIXME: Why is this check needed?
    if (!document().page())
        return false;

    RefPtr<Widget> widget = pluginWidget();
    if (!is<PluginViewBase>(widget))
        return false;

    return downcast<PluginViewBase>(*widget).supportsKeyboardFocus();
}

bool HTMLPlugInElement::isPluginElement() const
{
    return true;
}

bool HTMLPlugInElement::isUserObservable() const
{
    // No widget - can't be anything to see or hear here.
    RefPtr<Widget> widget = pluginWidget(PluginLoadingPolicy::DoNotLoad);
    if (!is<PluginViewBase>(widget))
        return false;

    PluginViewBase& pluginView = downcast<PluginViewBase>(*widget);

    // If audio is playing (or might be) then the plugin is detectable.
    if (pluginView.audioHardwareActivity() != AudioHardwareActivityType::IsInactive)
        return true;

    // If the plugin is visible and not vanishingly small in either dimension it is detectable.
    return pluginView.isVisible() && pluginView.width() > 2 && pluginView.height() > 2;
}

bool HTMLPlugInElement::supportsFocus() const
{
    if (HTMLFrameOwnerElement::supportsFocus())
        return true;

    if (useFallbackContent() || !is<RenderEmbeddedObject>(renderer()))
        return false;
    return !downcast<RenderEmbeddedObject>(*renderer()).isPluginUnavailable();
}

RenderPtr<RenderElement> HTMLPlugInElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition& insertionPosition)
{
    if (m_pluginReplacement && m_pluginReplacement->willCreateRenderer())
        return m_pluginReplacement->createElementRenderer(*this, WTFMove(style), insertionPosition);

    return createRenderer<RenderEmbeddedObject>(*this, WTFMove(style));
}

void HTMLPlugInElement::swapRendererTimerFired()
{
    ASSERT(displayState() == PreparingPluginReplacement);
    if (userAgentShadowRoot())
        return;
    
    // Create a shadow root, which will trigger the code to add a snapshot container
    // and reattach, thus making a new Renderer.
    Ref<HTMLPlugInElement> protectedThis(*this);
    ensureUserAgentShadowRoot();
}

void HTMLPlugInElement::setDisplayState(DisplayState state)
{
    if (state == m_displayState)
        return;

    m_displayState = state;

    m_swapRendererTimer.stop();
    if (displayState() == PreparingPluginReplacement)
        m_swapRendererTimer.startOneShot(0_s);
}

void HTMLPlugInElement::didAddUserAgentShadowRoot(ShadowRoot& root)
{
    if (!m_pluginReplacement || !document().page() || displayState() != PreparingPluginReplacement)
        return;
    
    root.setResetStyleInheritance(true);
    auto result = m_pluginReplacement->installReplacement(root);

#if PLATFORM(COCOA)
    RELEASE_ASSERT(result.success || !result.scriptObject);
    m_pluginReplacementScriptObject = result.scriptObject;
#endif

    if (result.success) {
        setDisplayState(DisplayingPluginReplacement);
        invalidateStyleAndRenderersForSubtree();
    }
}

#if PLATFORM(COCOA)
static void registrar(const ReplacementPlugin&);
#endif

static Vector<ReplacementPlugin*>& registeredPluginReplacements()
{
    static NeverDestroyed<Vector<ReplacementPlugin*>> registeredReplacements;
    static bool enginesQueried = false;
    
    if (enginesQueried)
        return registeredReplacements;
    enginesQueried = true;

#if PLATFORM(COCOA)
    QuickTimePluginReplacement::registerPluginReplacement(registrar);
    YouTubePluginReplacement::registerPluginReplacement(registrar);
#endif
    
    return registeredReplacements;
}

#if PLATFORM(COCOA)
static void registrar(const ReplacementPlugin& replacement)
{
    registeredPluginReplacements().append(new ReplacementPlugin(replacement));
}
#endif

static ReplacementPlugin* pluginReplacementForType(const URL& url, const String& mimeType)
{
    Vector<ReplacementPlugin*>& replacements = registeredPluginReplacements();
    if (replacements.isEmpty())
        return nullptr;

    String extension;
    auto lastPathComponent = url.lastPathComponent();
    size_t dotOffset = lastPathComponent.reverseFind('.');
    if (dotOffset != notFound)
        extension = lastPathComponent.substring(dotOffset + 1).toString();

    String type = mimeType;
    if (type.isEmpty() && url.protocolIsData())
        type = mimeTypeFromDataURL(url.string());
    
    if (type.isEmpty() && !extension.isEmpty()) {
        for (auto* replacement : replacements) {
            if (replacement->supportsFileExtension(extension) && replacement->supportsURL(url))
                return replacement;
        }
    }
    
    if (type.isEmpty()) {
        if (extension.isEmpty())
            return nullptr;
        type = MIMETypeRegistry::mediaMIMETypeForExtension(extension);
    }

    if (type.isEmpty())
        return nullptr;

    for (auto* replacement : replacements) {
        if (replacement->supportsType(type) && replacement->supportsURL(url))
            return replacement;
    }

    return nullptr;
}

bool HTMLPlugInElement::requestObject(const String& relativeURL, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues)
{
    if (m_pluginReplacement)
        return true;

    URL completedURL;
    if (!relativeURL.isEmpty())
        completedURL = document().completeURL(relativeURL);

    ReplacementPlugin* replacement = pluginReplacementForType(completedURL, mimeType);
    if (!replacement || !replacement->isEnabledBySettings(document().settings()))
        return false;

    LOG(Plugins, "%p - Found plug-in replacement for %s.", this, completedURL.string().utf8().data());

    m_pluginReplacement = replacement->create(*this, paramNames, paramValues);
    setDisplayState(PreparingPluginReplacement);
    return true;
}

JSC::JSObject* HTMLPlugInElement::scriptObjectForPluginReplacement()
{
#if PLATFORM(COCOA)
    JSC::JSValue value = m_pluginReplacementScriptObject;
    if (!value)
        return nullptr;
    return value.getObject();
#else
    return nullptr;
#endif
}

bool HTMLPlugInElement::isBelowSizeThreshold() const
{
    auto* renderObject = renderer();
    if (!is<RenderEmbeddedObject>(renderObject))
        return true;
    auto& renderEmbeddedObject = downcast<RenderEmbeddedObject>(*renderObject);
    return renderEmbeddedObject.isPluginUnavailable() && renderEmbeddedObject.pluginUnavailabilityReason() == RenderEmbeddedObject::PluginTooSmall;
}

bool HTMLPlugInElement::setReplacement(RenderEmbeddedObject::PluginUnavailabilityReason reason, const String& unavailabilityDescription)
{
    if (!is<RenderEmbeddedObject>(renderer()))
        return false;

    if (reason == RenderEmbeddedObject::UnsupportedPlugin)
        document().addConsoleMessage(MessageSource::JS, MessageLevel::Warning, "Tried to use an unsupported plug-in."_s);

    Ref<HTMLPlugInElement> protectedThis(*this);
    downcast<RenderEmbeddedObject>(*renderer()).setPluginUnavailabilityReasonWithDescription(reason, unavailabilityDescription);
    bool replacementIsObscured = isReplacementObscured();
    // hittest in isReplacementObscured() method could destroy the renderer. Let's refetch it.
    if (is<RenderEmbeddedObject>(renderer()))
        downcast<RenderEmbeddedObject>(*renderer()).setUnavailablePluginIndicatorIsHidden(replacementIsObscured);
    return replacementIsObscured;
}

bool HTMLPlugInElement::isReplacementObscured()
{
    Ref topDocument = document().topDocument();
    RefPtr topFrameView = topDocument->view();
    if (!topFrameView)
        return false;

    topFrameView->updateLayoutAndStyleIfNeededRecursive();

    // Updating the layout may have detached this document from the top document.
    auto* renderView = topDocument->renderView();
    if (!renderView || !document().view() || &document().topDocument() != topDocument.ptr())
        return false;

    if (!renderer() || !is<RenderEmbeddedObject>(*renderer()))
        return false;
    auto& pluginRenderer = downcast<RenderEmbeddedObject>(*renderer());
    // Check the opacity of each layer containing the element or its ancestors.
    float opacity = 1.0;
    for (auto* layer = pluginRenderer.enclosingLayer(); layer; layer = layer->parent()) {
        opacity *= layer->renderer().style().opacity();
        if (opacity < 0.1)
            return true;
    }
    // Calculate the absolute rect for the blocked plugin replacement text.
    LayoutPoint absoluteLocation(pluginRenderer.absoluteBoundingBoxRect().location());
    LayoutRect rect = pluginRenderer.unavailablePluginIndicatorBounds(absoluteLocation);
    if (rect.isEmpty())
        return true;
    auto viewRect = document().view()->convertToRootView(snappedIntRect(rect));
    auto x = viewRect.x();
    auto y = viewRect.y();
    auto width = viewRect.width();
    auto height = viewRect.height();
    // Hit test the center and near the corners of the replacement text to ensure
    // it is visible and is not masked by other elements.
    constexpr OptionSet<HitTestRequest::Type> hitType { HitTestRequest::Type::ReadOnly, HitTestRequest::Type::Active, HitTestRequest::Type::IgnoreClipping, HitTestRequest::Type::DisallowUserAgentShadowContent, HitTestRequest::Type::AllowChildFrameContent };
    HitTestResult result;
    HitTestLocation location { LayoutPoint { viewRect.center() } };
    ASSERT(!renderView->needsLayout());
    ASSERT(!renderView->document().needsStyleRecalc());
    bool hit = topDocument->hitTest(hitType, location, result);
    if (!hit || result.innerNode() != &pluginRenderer.frameOwnerElement())
        return true;

    location = LayoutPoint(x, y);
    hit = topDocument->hitTest(hitType, location, result);
    if (!hit || result.innerNode() != &pluginRenderer.frameOwnerElement())
        return true;

    location = LayoutPoint(x + width, y);
    hit = topDocument->hitTest(hitType, location, result);
    if (!hit || result.innerNode() != &pluginRenderer.frameOwnerElement())
        return true;

    location = LayoutPoint(x + width, y + height);
    hit = topDocument->hitTest(hitType, location, result);
    if (!hit || result.innerNode() != &pluginRenderer.frameOwnerElement())
        return true;

    location = LayoutPoint(x, y + height);
    hit = topDocument->hitTest(hitType, location, result);
    if (!hit || result.innerNode() != &pluginRenderer.frameOwnerElement())
        return true;
    return false;
}

bool HTMLPlugInElement::canLoadScriptURL(const URL&) const
{
    // FIXME: Probably want to at least check canAddSubframe.
    return true;
}

}
