/*
 * Copyright (C) 2006-2017 Apple Inc. All rights reserved.
 * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies)
 * Copyright (C) 2012, Samsung Electronics. 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 "Chrome.h"

#include "AppHighlight.h"
#include "ChromeClient.h"
#include "ContactInfo.h"
#include "ContactsRequestData.h"
#include "DOMWindow.h"
#include "Document.h"
#include "DocumentType.h"
#include "FileChooser.h"
#include "FileIconLoader.h"
#include "FileList.h"
#include "FloatRect.h"
#include "Frame.h"
#include "FrameLoaderClient.h"
#include "FrameTree.h"
#include "Geolocation.h"
#include "HTMLFormElement.h"
#include "HTMLInputElement.h"
#include "HTMLNames.h"
#include "HitTestResult.h"
#include "Icon.h"
#include "InspectorInstrumentation.h"
#include "Page.h"
#include "PageGroupLoadDeferrer.h"
#include "PopupOpeningObserver.h"
#include "RenderObject.h"
#include "ResourceHandle.h"
#include "Settings.h"
#include "ShareData.h"
#include "StorageNamespace.h"
#include "WindowFeatures.h"
#include <JavaScriptCore/VM.h>
#include <wtf/SetForScope.h>
#include <wtf/Vector.h>

#if ENABLE(INPUT_TYPE_COLOR)
#include "ColorChooser.h"
#endif

#if ENABLE(DATALIST_ELEMENT)
#include "DataListSuggestionPicker.h"
#endif

#if ENABLE(DATE_AND_TIME_INPUT_TYPES)
#include "DateTimeChooser.h"
#endif

namespace WebCore {

using namespace HTMLNames;

Chrome::Chrome(Page& page, ChromeClient& client)
    : m_page(page)
    , m_client(client)
{
}

Chrome::~Chrome()
{
    m_client.chromeDestroyed();
}

void Chrome::invalidateRootView(const IntRect& updateRect)
{
    m_client.invalidateRootView(updateRect);
}

void Chrome::invalidateContentsAndRootView(const IntRect& updateRect)
{
    m_client.invalidateContentsAndRootView(updateRect);
}

void Chrome::invalidateContentsForSlowScroll(const IntRect& updateRect)
{
    m_client.invalidateContentsForSlowScroll(updateRect);
}

void Chrome::scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
{
    m_client.scroll(scrollDelta, rectToScroll, clipRect);
    InspectorInstrumentation::didScroll(m_page);
}

IntPoint Chrome::screenToRootView(const IntPoint& point) const
{
    return m_client.screenToRootView(point);
}

IntRect Chrome::rootViewToScreen(const IntRect& rect) const
{
    return m_client.rootViewToScreen(rect);
}
    
IntPoint Chrome::accessibilityScreenToRootView(const IntPoint& point) const
{
    return m_client.accessibilityScreenToRootView(point);
}

IntRect Chrome::rootViewToAccessibilityScreen(const IntRect& rect) const
{
    return m_client.rootViewToAccessibilityScreen(rect);
}

PlatformPageClient Chrome::platformPageClient() const
{
    return m_client.platformPageClient();
}

void Chrome::contentsSizeChanged(Frame& frame, const IntSize& size) const
{
    m_client.contentsSizeChanged(frame, size);
}

void Chrome::scrollContainingScrollViewsToRevealRect(const IntRect& rect) const
{
    m_client.scrollContainingScrollViewsToRevealRect(rect);
}

void Chrome::scrollMainFrameToRevealRect(const IntRect& rect) const
{
    m_client.scrollMainFrameToRevealRect(rect);
}

void Chrome::setWindowRect(const FloatRect& rect) const
{
    m_client.setWindowRect(rect);
}

FloatRect Chrome::windowRect() const
{
    return m_client.windowRect();
}

FloatRect Chrome::pageRect() const
{
    return m_client.pageRect();
}

void Chrome::focus() const
{
    m_client.focus();
}

void Chrome::unfocus() const
{
    m_client.unfocus();
}

bool Chrome::canTakeFocus(FocusDirection direction) const
{
    return m_client.canTakeFocus(direction);
}

void Chrome::takeFocus(FocusDirection direction) const
{
    m_client.takeFocus(direction);
}

void Chrome::focusedElementChanged(Element* element) const
{
    m_client.focusedElementChanged(element);
}

void Chrome::focusedFrameChanged(Frame* frame) const
{
    m_client.focusedFrameChanged(frame);
}

Page* Chrome::createWindow(Frame& frame, const WindowFeatures& features, const NavigationAction& action) const
{
    Page* newPage = m_client.createWindow(frame, features, action);
    if (!newPage)
        return nullptr;

    if (!features.noopener && !features.noreferrer) {
        if (auto* oldSessionStorage = m_page.sessionStorage(false))
            newPage->setSessionStorage(oldSessionStorage->copy(*newPage));
    }

    return newPage;
}

void Chrome::show() const
{
    m_client.show();
}

bool Chrome::canRunModal() const
{
    return m_client.canRunModal();
}

void Chrome::runModal() const
{
    // Defer callbacks in all the other pages in this group, so we don't try to run JavaScript
    // in a way that could interact with this view.
    PageGroupLoadDeferrer deferrer(m_page, false);

    // JavaScript that runs within the nested event loop must not be run in the context of the
    // script that called showModalDialog. Null out entryScope to break the connection.
    SetForScope entryScopeNullifier { m_page.mainFrame().document()->vm().entryScope, nullptr };

    TimerBase::fireTimersInNestedEventLoop();
    m_client.runModal();
}

void Chrome::setToolbarsVisible(bool b) const
{
    m_client.setToolbarsVisible(b);
}

bool Chrome::toolbarsVisible() const
{
    return m_client.toolbarsVisible();
}

void Chrome::setStatusbarVisible(bool b) const
{
    m_client.setStatusbarVisible(b);
}

bool Chrome::statusbarVisible() const
{
    return m_client.statusbarVisible();
}

void Chrome::setScrollbarsVisible(bool b) const
{
    m_client.setScrollbarsVisible(b);
}

bool Chrome::scrollbarsVisible() const
{
    return m_client.scrollbarsVisible();
}

void Chrome::setMenubarVisible(bool b) const
{
    m_client.setMenubarVisible(b);
}

bool Chrome::menubarVisible() const
{
    return m_client.menubarVisible();
}

void Chrome::setResizable(bool b) const
{
    m_client.setResizable(b);
}

bool Chrome::canRunBeforeUnloadConfirmPanel()
{
    return m_client.canRunBeforeUnloadConfirmPanel();
}

bool Chrome::runBeforeUnloadConfirmPanel(const String& message, Frame& frame)
{
    // Defer loads in case the client method runs a new event loop that would
    // otherwise cause the load to continue while we're in the middle of executing JavaScript.
    PageGroupLoadDeferrer deferrer(m_page, true);

    return m_client.runBeforeUnloadConfirmPanel(message, frame);
}

void Chrome::closeWindow()
{
    m_client.closeWindow();
}

void Chrome::runJavaScriptAlert(Frame& frame, const String& message)
{
    // Defer loads in case the client method runs a new event loop that would
    // otherwise cause the load to continue while we're in the middle of executing JavaScript.
    PageGroupLoadDeferrer deferrer(m_page, true);

    notifyPopupOpeningObservers();
    String displayMessage = frame.displayStringModifiedByEncoding(message);

    m_client.runJavaScriptAlert(frame, displayMessage);
}

bool Chrome::runJavaScriptConfirm(Frame& frame, const String& message)
{
    // Defer loads in case the client method runs a new event loop that would
    // otherwise cause the load to continue while we're in the middle of executing JavaScript.
    PageGroupLoadDeferrer deferrer(m_page, true);

    notifyPopupOpeningObservers();
    return m_client.runJavaScriptConfirm(frame, frame.displayStringModifiedByEncoding(message));
}

bool Chrome::runJavaScriptPrompt(Frame& frame, const String& prompt, const String& defaultValue, String& result)
{
    // Defer loads in case the client method runs a new event loop that would
    // otherwise cause the load to continue while we're in the middle of executing JavaScript.
    PageGroupLoadDeferrer deferrer(m_page, true);

    notifyPopupOpeningObservers();
    String displayPrompt = frame.displayStringModifiedByEncoding(prompt);

    bool ok = m_client.runJavaScriptPrompt(frame, displayPrompt, frame.displayStringModifiedByEncoding(defaultValue), result);
    if (ok)
        result = frame.displayStringModifiedByEncoding(result);

    return ok;
}

void Chrome::setStatusbarText(Frame& frame, const String& status)
{
    m_client.setStatusbarText(frame.displayStringModifiedByEncoding(status));
}

void Chrome::mouseDidMoveOverElement(const HitTestResult& result, unsigned modifierFlags)
{
    if (result.innerNode() && result.innerNode()->document().isDNSPrefetchEnabled())
        m_page.mainFrame().loader().client().prefetchDNS(result.absoluteLinkURL().host().toString());

    String toolTip;
    TextDirection toolTipDirection;
    getToolTip(result, toolTip, toolTipDirection);
    m_client.mouseDidMoveOverElement(result, modifierFlags, toolTip, toolTipDirection);

    InspectorInstrumentation::mouseDidMoveOverElement(m_page, result, modifierFlags);
}

void Chrome::getToolTip(const HitTestResult& result, String& toolTip, TextDirection& toolTipDirection)
{
    // First priority is a potential toolTip representing a spelling or grammar error
    toolTip = result.spellingToolTip(toolTipDirection);

    // Next priority is a toolTip from a URL beneath the mouse (if preference is set to show those).
    if (toolTip.isEmpty() && m_page.settings().showsURLsInToolTips()) {
        if (Element* element = result.innerNonSharedElement()) {
            // Get tooltip representing form action, if relevant
            if (is<HTMLInputElement>(*element)) {
                HTMLInputElement& input = downcast<HTMLInputElement>(*element);
                if (input.isSubmitButton()) {
                    if (HTMLFormElement* form = input.form()) {
                        toolTip = form->action();
                        if (form->renderer())
                            toolTipDirection = form->renderer()->style().direction();
                        else
                            toolTipDirection = TextDirection::LTR;
                    }
                }
            }
        }

        // Get tooltip representing link's URL
        if (toolTip.isEmpty()) {
            // FIXME: Need to pass this URL through userVisibleString once that's in WebCore
            toolTip = result.absoluteLinkURL().string();
            // URL always display as LTR.
            toolTipDirection = TextDirection::LTR;
        }
    }

    // Next we'll consider a tooltip for element with "title" attribute
    if (toolTip.isEmpty())
        toolTip = result.title(toolTipDirection);

    if (toolTip.isEmpty() && m_page.settings().showsToolTipOverTruncatedText())
        toolTip = result.innerTextIfTruncated(toolTipDirection);

    // Lastly, for <input type="file"> that allow multiple files, we'll consider a tooltip for the selected filenames
    if (toolTip.isEmpty()) {
        if (Element* element = result.innerNonSharedElement()) {
            if (is<HTMLInputElement>(*element)) {
                toolTip = downcast<HTMLInputElement>(*element).defaultToolTip();

                // FIXME: We should obtain text direction of tooltip from
                // ChromeClient or platform. As of October 2011, all client
                // implementations don't use text direction information for
                // ChromeClient::mouseDidMoveOverElement. We'll work on tooltip text
                // direction during bidi cleanup in form inputs.
                toolTipDirection = TextDirection::LTR;
            }
        }
    }
}

bool Chrome::print(Frame& frame)
{
    // FIXME: This should have PageGroupLoadDeferrer, like runModal() or runJavaScriptAlert(), because it's no different from those.

    if (frame.document()->isSandboxed(SandboxModals)) {
        frame.document()->domWindow()->printErrorMessage("Use of window.print is not allowed in a sandboxed frame when the allow-modals flag is not set."_s);
        return false;
    }

    m_client.print(frame, frame.document()->titleWithDirection());
    return true;
}

void Chrome::enableSuddenTermination()
{
    m_client.enableSuddenTermination();
}

void Chrome::disableSuddenTermination()
{
    m_client.disableSuddenTermination();
}

#if ENABLE(INPUT_TYPE_COLOR)

std::unique_ptr<ColorChooser> Chrome::createColorChooser(ColorChooserClient& client, const Color& initialColor)
{
#if PLATFORM(IOS_FAMILY)
    UNUSED_PARAM(client);
    UNUSED_PARAM(initialColor);
    return nullptr;
#else
    notifyPopupOpeningObservers();
    return m_client.createColorChooser(client, initialColor);
#endif
}

#endif

#if ENABLE(DATALIST_ELEMENT)

std::unique_ptr<DataListSuggestionPicker> Chrome::createDataListSuggestionPicker(DataListSuggestionsClient& client)
{
    notifyPopupOpeningObservers();
    return m_client.createDataListSuggestionPicker(client);
}

#endif

#if ENABLE(DATE_AND_TIME_INPUT_TYPES)

std::unique_ptr<DateTimeChooser> Chrome::createDateTimeChooser(DateTimeChooserClient& client)
{
#if PLATFORM(IOS_FAMILY)
    UNUSED_PARAM(client);
    return nullptr;
#else
    notifyPopupOpeningObservers();
    return m_client.createDateTimeChooser(client);
#endif
}

#endif

void Chrome::runOpenPanel(Frame& frame, FileChooser& fileChooser)
{
    notifyPopupOpeningObservers();
    m_client.runOpenPanel(frame, fileChooser);
}

void Chrome::showShareSheet(ShareDataWithParsedURL& shareData, CompletionHandler<void(bool)>&& callback)
{
    m_client.showShareSheet(shareData, WTFMove(callback));
}

void Chrome::showContactPicker(const ContactsRequestData& requestData, CompletionHandler<void(std::optional<Vector<ContactInfo>>&&)>&& callback)
{
    m_client.showContactPicker(requestData, WTFMove(callback));
}

void Chrome::loadIconForFiles(const Vector<String>& filenames, FileIconLoader& loader)
{
    m_client.loadIconForFiles(filenames, loader);
}

FloatSize Chrome::screenSize() const
{
    return m_client.screenSize();
}

FloatSize Chrome::availableScreenSize() const
{
    return m_client.availableScreenSize();
}

FloatSize Chrome::overrideScreenSize() const
{
    return m_client.overrideScreenSize();
}

void Chrome::dispatchDisabledAdaptationsDidChange(const OptionSet<DisabledAdaptations>& disabledAdaptations) const
{
    m_client.dispatchDisabledAdaptationsDidChange(disabledAdaptations);
}

void Chrome::dispatchViewportPropertiesDidChange(const ViewportArguments& arguments) const
{
#if PLATFORM(IOS_FAMILY)
    if (m_isDispatchViewportDataDidChangeSuppressed)
        return;
#endif
    m_client.dispatchViewportPropertiesDidChange(arguments);
}

#if ENABLE(APP_HIGHLIGHTS)
void Chrome::storeAppHighlight(AppHighlight&& highlight) const
{
    m_client.storeAppHighlight(WTFMove(highlight));
}
#endif

void Chrome::setCursor(const Cursor& cursor)
{
    m_client.setCursor(cursor);
}

void Chrome::setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves)
{
    m_client.setCursorHiddenUntilMouseMoves(hiddenUntilMouseMoves);
}

RefPtr<ImageBuffer> Chrome::createImageBuffer(const FloatSize& size, RenderingMode renderingMode, RenderingPurpose purpose, float resolutionScale, const DestinationColorSpace& colorSpace, PixelFormat pixelFormat) const
{
    return m_client.createImageBuffer(size, renderingMode, purpose, resolutionScale, colorSpace, pixelFormat);
}

#if ENABLE(WEBGL)
RefPtr<GraphicsContextGL> Chrome::createGraphicsContextGL(const GraphicsContextGLAttributes& attributes) const
{
    return m_client.createGraphicsContextGL(attributes);
}
#endif

RefPtr<PAL::WebGPU::GPU> Chrome::createGPUForWebGPU() const
{
    return m_client.createGPUForWebGPU();
}

PlatformDisplayID Chrome::displayID() const
{
    return m_page.displayID();
}

void Chrome::windowScreenDidChange(PlatformDisplayID displayID, std::optional<FramesPerSecond> nominalFrameInterval)
{
    m_page.windowScreenDidChange(displayID, nominalFrameInterval);
}

bool Chrome::selectItemWritingDirectionIsNatural()
{
    return m_client.selectItemWritingDirectionIsNatural();
}

bool Chrome::selectItemAlignmentFollowsMenuWritingDirection()
{
    return m_client.selectItemAlignmentFollowsMenuWritingDirection();
}

RefPtr<PopupMenu> Chrome::createPopupMenu(PopupMenuClient& client) const
{
    notifyPopupOpeningObservers();
    return m_client.createPopupMenu(client);
}

RefPtr<SearchPopupMenu> Chrome::createSearchPopupMenu(PopupMenuClient& client) const
{
    notifyPopupOpeningObservers();
    return m_client.createSearchPopupMenu(client);
}

bool Chrome::requiresFullscreenForVideoPlayback()
{
    return m_client.requiresFullscreenForVideoPlayback();
}

void Chrome::didReceiveDocType(Frame& frame)
{
#if !PLATFORM(IOS_FAMILY)
    UNUSED_PARAM(frame);
#else
    if (!frame.isMainFrame())
        return;

    auto* doctype = frame.document()->doctype();
    m_client.didReceiveMobileDocType(doctype && doctype->publicId().containsIgnoringASCIICase("xhtml mobile"_s));
#endif
}

void Chrome::registerPopupOpeningObserver(PopupOpeningObserver& observer)
{
    m_popupOpeningObservers.append(&observer);
}

void Chrome::unregisterPopupOpeningObserver(PopupOpeningObserver& observer)
{
    bool removed = m_popupOpeningObservers.removeFirst(&observer);
    ASSERT_UNUSED(removed, removed);
}

void Chrome::notifyPopupOpeningObservers() const
{
    const Vector<PopupOpeningObserver*> observers(m_popupOpeningObservers);
    for (auto& observer : observers)
        observer->willOpenPopup();
}

} // namespace WebCore
