/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 * Copyright (C) 2000 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2004-2020 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 "RenderWidget.h"

#include "AXObjectCache.h"
#include "DocumentInlines.h"
#include "FloatRoundedRect.h"
#include "Frame.h"
#include "HTMLFrameOwnerElement.h"
#include "HitTestResult.h"
#include "RenderLayer.h"
#include "RenderLayerBacking.h"
#include "RenderLayerScrollableArea.h"
#include "RenderView.h"
#include "SecurityOrigin.h"
#include <wtf/IsoMallocInlines.h>
#include <wtf/StackStats.h>
#include <wtf/Ref.h>

namespace WebCore {

WTF_MAKE_ISO_ALLOCATED_IMPL(RenderWidget);

static HashMap<const Widget*, RenderWidget*>& widgetRendererMap()
{
    static HashMap<const Widget*, RenderWidget*>* staticWidgetRendererMap = new HashMap<const Widget*, RenderWidget*>;
    return *staticWidgetRendererMap;
}

unsigned WidgetHierarchyUpdatesSuspensionScope::s_widgetHierarchyUpdateSuspendCount = 0;
bool WidgetHierarchyUpdatesSuspensionScope::s_haveScheduledWidgetToMove = false;

WidgetHierarchyUpdatesSuspensionScope::WidgetToParentMap& WidgetHierarchyUpdatesSuspensionScope::widgetNewParentMap()
{
    static NeverDestroyed<WidgetToParentMap> map;
    return map;
}

void WidgetHierarchyUpdatesSuspensionScope::moveWidgets()
{
    ASSERT(s_haveScheduledWidgetToMove);
    while (!widgetNewParentMap().isEmpty()) {
        auto map = std::exchange(widgetNewParentMap(), { });
        for (auto& entry : map) {
            auto& child = *entry.key;
            auto* currentParent = child.parent();
            auto* newParent = entry.value;
            if (newParent != currentParent) {
                if (currentParent)
                    currentParent->removeChild(child);
                if (newParent)
                    newParent->addChild(child);
            }
        }
    }
    s_haveScheduledWidgetToMove = false;
}

static void moveWidgetToParentSoon(Widget& child, FrameView* parent)
{
    if (!WidgetHierarchyUpdatesSuspensionScope::isSuspended()) {
        if (parent)
            parent->addChild(child);
        else
            child.removeFromParent();
        return;
    }
    WidgetHierarchyUpdatesSuspensionScope::scheduleWidgetToMove(child, parent);
}

RenderWidget::RenderWidget(HTMLFrameOwnerElement& element, RenderStyle&& style)
    : RenderReplaced(element, WTFMove(style))
{
    setInline(false);
}

void RenderWidget::willBeDestroyed()
{
#if PLATFORM(IOS_FAMILY)
    if (hasLayer())
        layer()->willBeDestroyed();
#endif

    if (AXObjectCache* cache = document().existingAXObjectCache()) {
        cache->childrenChanged(this->parent());
        cache->remove(this);
    }

    if (renderTreeBeingDestroyed() && document().backForwardCacheState() == Document::NotInBackForwardCache && m_widget)
        m_widget->willBeDestroyed();

    setWidget(nullptr);

    RenderReplaced::willBeDestroyed();
}

RenderWidget::~RenderWidget()
{
    ASSERT(!m_refCount);
}

// Widgets are always placed on integer boundaries, so rounding the size is actually
// the desired behavior. This function is here because it's otherwise seldom what we
// want to do with a LayoutRect.
static inline IntRect roundedIntRect(const LayoutRect& rect)
{
    return IntRect(roundedIntPoint(rect.location()), roundedIntSize(rect.size()));
}

bool RenderWidget::setWidgetGeometry(const LayoutRect& frame)
{
    IntRect clipRect = roundedIntRect(enclosingLayer()->childrenClipRect());
    IntRect newFrameRect = roundedIntRect(frame);
    IntRect oldFrameRect = m_widget->frameRect();
    bool clipChanged = m_clipRect != clipRect;
    bool boundsChanged = oldFrameRect != newFrameRect;

    if (!boundsChanged && !clipChanged)
        return false;

    m_clipRect = clipRect;

    WeakPtr weakThis { *this };
    // These calls *may* cause this renderer to disappear from underneath...
    if (boundsChanged)
        m_widget->setFrameRect(newFrameRect);
    else if (clipChanged)
        m_widget->clipRectChanged();
    // ...so we follow up with a sanity check.
    if (!weakThis)
        return true;

    if (boundsChanged)
        view().compositor().widgetDidChangeSize(*this);

    return oldFrameRect.size() != newFrameRect.size();
}

bool RenderWidget::updateWidgetGeometry()
{
    if (!m_widget->transformsAffectFrameRect())
        return setWidgetGeometry(absoluteContentBox());

    LayoutRect contentBox = contentBoxRect();
    LayoutRect absoluteContentBox(localToAbsoluteQuad(FloatQuad(contentBox)).boundingBox());
    if (m_widget->isFrameView()) {
        contentBox.setLocation(absoluteContentBox.location());
        return setWidgetGeometry(contentBox);
    }

    return setWidgetGeometry(absoluteContentBox);
}

void RenderWidget::setWidget(RefPtr<Widget>&& widget)
{
    if (widget == m_widget)
        return;

    if (m_widget) {
        moveWidgetToParentSoon(*m_widget, nullptr);
        view().frameView().willRemoveWidgetFromRenderTree(*m_widget);
        widgetRendererMap().remove(m_widget.get());
        m_widget = nullptr;
    }
    m_widget = widget;
    if (m_widget) {
        widgetRendererMap().add(m_widget.get(), this);
        view().frameView().didAddWidgetToRenderTree(*m_widget);
        // If we've already received a layout, apply the calculated space to the
        // widget immediately, but we have to have really been fully constructed.
        if (hasInitializedStyle()) {
            if (!needsLayout()) {
                WeakPtr weakThis { *this };
                updateWidgetGeometry();
                if (!weakThis)
                    return;
            }

            if (style().visibility() != Visibility::Visible)
                m_widget->hide();
            else {
                m_widget->show();
                repaint();
            }
        }
        moveWidgetToParentSoon(*m_widget, &view().frameView());
    }
}

void RenderWidget::layout()
{
    StackStats::LayoutCheckPoint layoutCheckPoint;
    ASSERT(needsLayout());

    clearNeedsLayout();
}

void RenderWidget::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    RenderReplaced::styleDidChange(diff, oldStyle);
    if (m_widget) {
        if (style().visibility() != Visibility::Visible)
            m_widget->hide();
        else
            m_widget->show();
    }
}

void RenderWidget::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (paintInfo.requireSecurityOriginAccessForWidgets) {
        if (auto contentDocument = frameOwnerElement().contentDocument()) {
            if (!document().securityOrigin().isSameOriginDomain(contentDocument->securityOrigin()))
                return;
        }
    }

    IntPoint contentPaintOffset = roundedIntPoint(paintOffset + location() + contentBoxRect().location());
    // Tell the widget to paint now. This is the only time the widget is allowed
    // to paint itself. That way it will composite properly with z-indexed layers.
    LayoutRect paintRect = paintInfo.rect;

    OptionSet<PaintBehavior> oldBehavior = PaintBehavior::Normal;
    if (is<FrameView>(*m_widget) && (paintInfo.paintBehavior & PaintBehavior::TileFirstPaint)) {
        FrameView& frameView = downcast<FrameView>(*m_widget);
        oldBehavior = frameView.paintBehavior();
        frameView.setPaintBehavior(oldBehavior | PaintBehavior::TileFirstPaint);
    }

    IntPoint widgetLocation = m_widget->frameRect().location();
    IntSize widgetPaintOffset = contentPaintOffset - widgetLocation;
    // When painting widgets into compositing layers, tx and ty are relative to the enclosing compositing layer,
    // not the root. In this case, shift the CTM and adjust the paintRect to be root-relative to fix plug-in drawing.
    if (!widgetPaintOffset.isZero()) {
        paintInfo.context().translate(widgetPaintOffset);
        paintRect.move(-widgetPaintOffset);
    }

    if (paintInfo.eventRegionContext) {
        AffineTransform transform;
        transform.translate(contentPaintOffset);
        paintInfo.eventRegionContext->pushTransform(transform);
    }

    // FIXME: Remove repaintrect enclosing/integral snapping when RenderWidget becomes device pixel snapped.
    m_widget->paint(paintInfo.context(), snappedIntRect(paintRect), paintInfo.requireSecurityOriginAccessForWidgets ? Widget::SecurityOriginPaintPolicy::AccessibleOriginOnly : Widget::SecurityOriginPaintPolicy::AnyOrigin, paintInfo.eventRegionContext);

    if (paintInfo.eventRegionContext)
        paintInfo.eventRegionContext->popTransform();

    if (!widgetPaintOffset.isZero())
        paintInfo.context().translate(-widgetPaintOffset);

    if (is<FrameView>(*m_widget)) {
        FrameView& frameView = downcast<FrameView>(*m_widget);
        bool runOverlapTests = !frameView.useSlowRepaintsIfNotOverlapped();
        if (paintInfo.overlapTestRequests && runOverlapTests) {
            ASSERT(!paintInfo.overlapTestRequests->contains(this) || (paintInfo.overlapTestRequests->get(this) == m_widget->frameRect()));
            paintInfo.overlapTestRequests->set(this, m_widget->frameRect());
        }
        if (paintInfo.paintBehavior & PaintBehavior::TileFirstPaint)
            frameView.setPaintBehavior(oldBehavior);
    }
}

void RenderWidget::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (!shouldPaint(paintInfo, paintOffset))
        return;

    if (paintInfo.context().detectingContentfulPaint())
        return;

    LayoutPoint adjustedPaintOffset = paintOffset + location();

    if (hasVisibleBoxDecorations() && (paintInfo.phase == PaintPhase::Foreground || paintInfo.phase == PaintPhase::Selection))
        paintBoxDecorations(paintInfo, adjustedPaintOffset);

    if (paintInfo.phase == PaintPhase::Mask) {
        paintMask(paintInfo, adjustedPaintOffset);
        return;
    }

    if ((paintInfo.phase == PaintPhase::Outline || paintInfo.phase == PaintPhase::SelfOutline) && hasOutline())
        paintOutline(paintInfo, LayoutRect(adjustedPaintOffset, size()));

    // FIXME: Shouldn't check if the frame view needs layout during event region painting. This is a workaround
    // for the fact that non-composited frames depend on their enclosing compositing layer to perform an event
    // region update on their behalf. See <https://webkit.org/b/210311> for more details.
    bool needsEventRegionContentPaint = paintInfo.phase == PaintPhase::EventRegion && is<FrameView>(m_widget) && !downcast<FrameView>(*m_widget).needsLayout();
    if (paintInfo.phase != PaintPhase::Foreground && !needsEventRegionContentPaint)
        return;

    if (style().hasBorderRadius()) {
        LayoutRect borderRect = LayoutRect(adjustedPaintOffset, size());

        if (borderRect.isEmpty())
            return;

        // Push a clip if we have a border radius, since we want to round the foreground content that gets painted.
        paintInfo.context().save();
        FloatRoundedRect roundedInnerRect = FloatRoundedRect(style().getRoundedInnerBorderFor(borderRect,
            paddingTop() + borderTop(), paddingBottom() + borderBottom(), paddingLeft() + borderLeft(), paddingRight() + borderRight(), true, true));
        clipRoundedInnerRect(paintInfo.context(), borderRect, roundedInnerRect);
    }

    if (m_widget)
        paintContents(paintInfo, paintOffset);

    if (style().hasBorderRadius())
        paintInfo.context().restore();

    if (paintInfo.phase == PaintPhase::EventRegion)
        return;

    // Paint a partially transparent wash over selected widgets.
    if (isSelected() && !document().printing()) {
        // FIXME: selectionRect() is in absolute, not painting coordinates.
        paintInfo.context().fillRect(snappedIntRect(selectionRect()), selectionBackgroundColor());
    }

    if (hasLayer() && layer()->canResize()) {
        ASSERT(layer()->scrollableArea());
        layer()->scrollableArea()->paintResizer(paintInfo.context(), roundedIntPoint(adjustedPaintOffset), paintInfo.rect);
    }
}

void RenderWidget::setOverlapTestResult(bool isOverlapped)
{
    ASSERT(m_widget);
    downcast<FrameView>(*m_widget).setIsOverlapped(isOverlapped);
}

RenderWidget::ChildWidgetState RenderWidget::updateWidgetPosition()
{
    if (!m_widget)
        return ChildWidgetState::Destroyed;

    WeakPtr weakThis { *this };
    bool widgetSizeChanged = updateWidgetGeometry();
    if (!weakThis || !m_widget)
        return ChildWidgetState::Destroyed;

    // if the frame size got changed, or if view needs layout (possibly indicating
    // content size is wrong) we have to do a layout to set the right widget size.
    if (is<FrameView>(*m_widget)) {
        FrameView& frameView = downcast<FrameView>(*m_widget);
        // Check the frame's page to make sure that the frame isn't in the process of being destroyed.
        if ((widgetSizeChanged || frameView.needsLayout()) && frameView.frame().page() && frameView.frame().document())
            frameView.layoutContext().layout();
    }
    return ChildWidgetState::Valid;
}

IntRect RenderWidget::windowClipRect() const
{
    return intersection(view().frameView().contentsToWindow(m_clipRect), view().frameView().windowClipRect());
}

void RenderWidget::setSelectionState(HighlightState state)
{
    // The selection state for our containing block hierarchy is updated by the base class call.
    RenderReplaced::setSelectionState(state);

    if (m_widget)
        m_widget->setIsSelected(isSelected());
}

RenderWidget* RenderWidget::find(const Widget& widget)
{
    return widgetRendererMap().get(&widget);
}

bool RenderWidget::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
{
    auto shouldHitTestChildFrameContent = request.allowsChildFrameContent() || (request.allowsVisibleChildFrameContent() && visibleToHitTesting(request));
    auto hasRenderView = is<FrameView>(widget()) && downcast<FrameView>(*widget()).renderView();
    if (shouldHitTestChildFrameContent && hasRenderView) {
        FrameView& childFrameView = downcast<FrameView>(*widget());

        LayoutPoint adjustedLocation = accumulatedOffset + location();
        LayoutPoint contentOffset = LayoutPoint(borderLeft() + paddingLeft(), borderTop() + paddingTop()) - toIntSize(childFrameView.scrollPosition());
        HitTestLocation newHitTestLocation(locationInContainer, -adjustedLocation - contentOffset);
        HitTestRequest newHitTestRequest(request.type() | HitTestRequest::Type::ChildFrameHitTest);
        HitTestResult childFrameResult(newHitTestLocation);

        auto* document = childFrameView.frame().document();
        if (!document)
            return false;
        bool isInsideChildFrame = document->hitTest(newHitTestRequest, newHitTestLocation, childFrameResult);

        if (request.resultIsElementList())
            result.append(childFrameResult, request);
        else if (isInsideChildFrame)
            result = childFrameResult;

        if (isInsideChildFrame)
            return true;
    }

    bool hadResult = result.innerNode();
    bool inside = RenderReplaced::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action);

    // Check to see if we are really over the widget itself (and not just in the border/padding area).
    if ((inside || result.isRectBasedTest()) && !hadResult && result.innerNode() == &frameOwnerElement())
        result.setIsOverWidget(contentBoxRect().contains(result.localPoint()));
    return inside;
}

bool RenderWidget::requiresLayer() const
{
    return RenderReplaced::requiresLayer() || requiresAcceleratedCompositing();
}

bool RenderWidget::requiresAcceleratedCompositing() const
{
    // If this is a renderer with a contentDocument and that document needs a layer, then we need a layer.
    if (Document* contentDocument = frameOwnerElement().contentDocument()) {
        if (RenderView* view = contentDocument->renderView())
            return view->usesCompositing();
    }

    return false;
}

bool RenderWidget::needsPreferredWidthsRecalculation() const
{
    if (RenderReplaced::needsPreferredWidthsRecalculation())
        return true;
    return embeddedContentBox();
}

RenderBox* RenderWidget::embeddedContentBox() const
{
    if (!is<FrameView>(widget()))
        return nullptr;
    return downcast<FrameView>(*widget()).embeddedContentBox();
}

} // namespace WebCore
