/*
 * Copyright (C) 2016 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 "WebAutomationSessionProxy.h"

#include "AutomationProtocolObjects.h"
#include "CoordinateSystem.h"
#include "WebAutomationSessionMessages.h"
#include "WebAutomationSessionProxyMessages.h"
#include "WebAutomationSessionProxyScriptSource.h"
#include "WebCoreArgumentCoders.h"
#include "WebFrame.h"
#include "WebImage.h"
#include "WebPage.h"
#include "WebProcess.h"
#include <JavaScriptCore/APICast.h>
#include <JavaScriptCore/JSObject.h>
#include <JavaScriptCore/JSStringRefPrivate.h>
#include <JavaScriptCore/OpaqueJSString.h>
#include <WebCore/CookieJar.h>
#include <WebCore/DOMRect.h>
#include <WebCore/DOMRectList.h>
#include <WebCore/DOMWindow.h>
#include <WebCore/File.h>
#include <WebCore/FileList.h>
#include <WebCore/Frame.h>
#include <WebCore/FrameTree.h>
#include <WebCore/FrameView.h>
#include <WebCore/HTMLFrameElement.h>
#include <WebCore/HTMLIFrameElement.h>
#include <WebCore/HTMLInputElement.h>
#include <WebCore/HTMLOptGroupElement.h>
#include <WebCore/HTMLOptionElement.h>
#include <WebCore/HTMLSelectElement.h>
#include <WebCore/JSElement.h>
#include <WebCore/RenderElement.h>
#include <wtf/UUID.h>

#if ENABLE(DATALIST_ELEMENT)
#include <WebCore/HTMLDataListElement.h>
#endif

namespace WebKit {

template <typename T>
static JSObjectRef toJSArray(JSContextRef context, const Vector<T>& data, JSValueRef (*converter)(JSContextRef, const T&), JSValueRef* exception)
{
    ASSERT_ARG(converter, converter);

    if (data.isEmpty())
        return JSObjectMakeArray(context, 0, nullptr, exception);

    Vector<JSValueRef, 8> convertedData;
    convertedData.reserveCapacity(data.size());

    for (auto& originalValue : data) {
        JSValueRef convertedValue = converter(context, originalValue);
        JSValueProtect(context, convertedValue);
        convertedData.uncheckedAppend(convertedValue);
    }

    JSObjectRef array = JSObjectMakeArray(context, convertedData.size(), convertedData.data(), exception);

    for (auto& convertedValue : convertedData)
        JSValueUnprotect(context, convertedValue);

    return array;
}

static inline JSValueRef toJSValue(JSContextRef context, const String& string)
{
    return JSValueMakeString(context, OpaqueJSString::tryCreate(string).get());
}

static inline JSValueRef callPropertyFunction(JSContextRef context, JSObjectRef object, const String& propertyName, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
    ASSERT_ARG(object, object);
    ASSERT_ARG(object, JSValueIsObject(context, object));

    JSObjectRef function = const_cast<JSObjectRef>(JSObjectGetProperty(context, object, OpaqueJSString::tryCreate(propertyName).get(), exception));
    ASSERT(JSObjectIsFunction(context, function));

    return JSObjectCallAsFunction(context, function, object, argumentCount, arguments, exception);
}

WebAutomationSessionProxy::WebAutomationSessionProxy(const String& sessionIdentifier)
    : m_sessionIdentifier(sessionIdentifier)
{
    WebProcess::singleton().addMessageReceiver(Messages::WebAutomationSessionProxy::messageReceiverName(), *this);
}

WebAutomationSessionProxy::~WebAutomationSessionProxy()
{
    WebProcess::singleton().removeMessageReceiver(Messages::WebAutomationSessionProxy::messageReceiverName());
}

static JSValueRef evaluate(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
    ASSERT_ARG(argumentCount, argumentCount == 1);
    ASSERT_ARG(arguments, JSValueIsString(context, arguments[0]));

    if (argumentCount != 1)
        return JSValueMakeUndefined(context);

    auto script = adoptRef(JSValueToStringCopy(context, arguments[0], exception));
    return JSEvaluateScript(context, script.get(), nullptr, nullptr, 0, exception);
}

static JSValueRef createUUID(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
    return toJSValue(context, createCanonicalUUIDString().convertToASCIIUppercase());
}

static JSValueRef evaluateJavaScriptCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
    ASSERT_ARG(argumentCount, argumentCount == 4);
    ASSERT_ARG(arguments, JSValueIsNumber(context, arguments[0]));
    ASSERT_ARG(arguments, JSValueIsNumber(context, arguments[1]));
    ASSERT_ARG(arguments, JSValueIsString(context, arguments[2]));
    ASSERT_ARG(arguments, JSValueIsBoolean(context, arguments[3]));

    auto automationSessionProxy = WebProcess::singleton().automationSessionProxy();
    if (!automationSessionProxy)
        return JSValueMakeUndefined(context);

    WebCore::FrameIdentifier frameID = WebCore::frameIdentifierFromID(JSValueToNumber(context, arguments[0], exception));
    uint64_t callbackID = JSValueToNumber(context, arguments[1], exception);
    auto result = adoptRef(JSValueToStringCopy(context, arguments[2], exception));

    bool resultIsErrorName = JSValueToBoolean(context, arguments[3]);

    if (resultIsErrorName) {
        if (result->string() == "JavaScriptTimeout") {
            String errorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::JavaScriptTimeout);
            automationSessionProxy->didEvaluateJavaScriptFunction(frameID, callbackID, String(), errorType);
        } else {
            ASSERT_NOT_REACHED();
            String errorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::InternalError);
            automationSessionProxy->didEvaluateJavaScriptFunction(frameID, callbackID, String(), errorType);
        }
    } else
        automationSessionProxy->didEvaluateJavaScriptFunction(frameID, callbackID, result->string(), String());

    return JSValueMakeUndefined(context);
}

JSObjectRef WebAutomationSessionProxy::scriptObjectForFrame(WebFrame& frame)
{
    if (JSObjectRef scriptObject = m_webFrameScriptObjectMap.get(frame.frameID()))
        return scriptObject;

    JSValueRef exception = nullptr;
    JSGlobalContextRef context = frame.jsContext();

    JSValueRef sessionIdentifier = toJSValue(context, m_sessionIdentifier);
    JSObjectRef evaluateFunction = JSObjectMakeFunctionWithCallback(context, nullptr, evaluate);
    JSObjectRef createUUIDFunction = JSObjectMakeFunctionWithCallback(context, nullptr, createUUID);

    String script = StringImpl::createWithoutCopying(WebAutomationSessionProxyScriptSource, sizeof(WebAutomationSessionProxyScriptSource));

    JSObjectRef scriptObjectFunction = const_cast<JSObjectRef>(JSEvaluateScript(context, OpaqueJSString::tryCreate(script).get(), nullptr, nullptr, 0, &exception));
    ASSERT(JSValueIsObject(context, scriptObjectFunction));

    JSValueRef arguments[] = { sessionIdentifier, evaluateFunction, createUUIDFunction };
    JSObjectRef scriptObject = const_cast<JSObjectRef>(JSObjectCallAsFunction(context, scriptObjectFunction, nullptr, WTF_ARRAY_LENGTH(arguments), arguments, &exception));
    ASSERT(JSValueIsObject(context, scriptObject));

    JSValueProtect(context, scriptObject);
    m_webFrameScriptObjectMap.add(frame.frameID(), scriptObject);

    return scriptObject;
}

WebCore::Element* WebAutomationSessionProxy::elementForNodeHandle(WebFrame& frame, const String& nodeHandle)
{
    // Don't use scriptObjectForFrame() since we can assume if the script object
    // does not exist, there are no nodes mapped to handles. Using scriptObjectForFrame()
    // will make a new script object if it can't find one, preventing us from returning fast.
    JSObjectRef scriptObject = m_webFrameScriptObjectMap.get(frame.frameID());
    if (!scriptObject)
        return nullptr;

    JSGlobalContextRef context = frame.jsContext();

    JSValueRef functionArguments[] = {
        toJSValue(context, nodeHandle)
    };

    JSValueRef result = callPropertyFunction(context, scriptObject, "nodeForIdentifier"_s, WTF_ARRAY_LENGTH(functionArguments), functionArguments, nullptr);
    JSObjectRef element = JSValueToObject(context, result, nullptr);
    if (!element)
        return nullptr;

    auto elementWrapper = JSC::jsDynamicCast<WebCore::JSElement*>(toJS(context)->vm(), toJS(element));
    if (!elementWrapper)
        return nullptr;

    return &elementWrapper->wrapped();
}

void WebAutomationSessionProxy::didClearWindowObjectForFrame(WebFrame& frame)
{
    WebCore::FrameIdentifier frameID = frame.frameID();
    if (JSObjectRef scriptObject = m_webFrameScriptObjectMap.take(frameID))
        JSValueUnprotect(frame.jsContext(), scriptObject);

    String errorMessage = "Callback was not called before the unload event."_s;
    String errorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::JavaScriptError);

    auto pendingFrameCallbacks = m_webFramePendingEvaluateJavaScriptCallbacksMap.take(frameID);
    for (uint64_t callbackID : pendingFrameCallbacks)
        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidEvaluateJavaScriptFunction(callbackID, errorMessage, errorType), 0);
}

void WebAutomationSessionProxy::evaluateJavaScriptFunction(WebCore::PageIdentifier pageID, Optional<WebCore::FrameIdentifier> optionalFrameID, const String& function, Vector<String> arguments, bool expectsImplicitCallbackArgument, int callbackTimeout, uint64_t callbackID)
{
    WebPage* page = WebProcess::singleton().webPage(pageID);
    if (!page) {
        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidEvaluateJavaScriptFunction(callbackID, { },
            Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::WindowNotFound)), 0);
        return;
    }
    WebFrame* frame = optionalFrameID ? WebProcess::singleton().webFrame(*optionalFrameID) : page->mainWebFrame();
    if (!frame) {
        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidEvaluateJavaScriptFunction(callbackID, { },
            Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound)), 0);
        return;
    }

    JSObjectRef scriptObject = scriptObjectForFrame(*frame);
    ASSERT(scriptObject);

    auto frameID = frame->frameID();
    JSValueRef exception = nullptr;
    JSGlobalContextRef context = frame->jsContext();

    if (expectsImplicitCallbackArgument) {
        auto result = m_webFramePendingEvaluateJavaScriptCallbacksMap.add(frameID, Vector<uint64_t>());
        result.iterator->value.append(callbackID);
    }

    JSValueRef functionArguments[] = {
        toJSValue(context, function),
        toJSArray(context, arguments, toJSValue, &exception),
        JSValueMakeBoolean(context, expectsImplicitCallbackArgument),
        JSValueMakeNumber(context, frameID.toUInt64()),
        JSValueMakeNumber(context, callbackID),
        JSObjectMakeFunctionWithCallback(context, nullptr, evaluateJavaScriptCallback),
        JSValueMakeNumber(context, callbackTimeout)
    };

    {
        WebCore::UserGestureIndicator gestureIndicator(WebCore::ProcessingUserGesture, frame->coreFrame()->document());
        callPropertyFunction(context, scriptObject, "evaluateJavaScriptFunction"_s, WTF_ARRAY_LENGTH(functionArguments), functionArguments, &exception);
    }

    if (!exception)
        return;

    String errorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::JavaScriptError);

    String exceptionMessage;
    if (JSValueIsObject(context, exception)) {
        JSValueRef nameValue = JSObjectGetProperty(context, const_cast<JSObjectRef>(exception), OpaqueJSString::tryCreate("name"_s).get(), nullptr);
        auto exceptionName = adoptRef(JSValueToStringCopy(context, nameValue, nullptr))->string();
        if (exceptionName == "NodeNotFound")
            errorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::NodeNotFound);
        else if (exceptionName == "InvalidElementState")
            errorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::InvalidElementState);
        else if (exceptionName == "InvalidParameter")
            errorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::InvalidParameter);
        else if (exceptionName == "InvalidSelector")
            errorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::InvalidSelector);
        else if (exceptionName == "ElementNotInteractable")
            errorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::ElementNotInteractable);

        JSValueRef messageValue = JSObjectGetProperty(context, const_cast<JSObjectRef>(exception), OpaqueJSString::tryCreate("message"_s).get(), nullptr);
        exceptionMessage = adoptRef(JSValueToStringCopy(context, messageValue, nullptr))->string();
    } else
        exceptionMessage = adoptRef(JSValueToStringCopy(context, exception, nullptr))->string();

    didEvaluateJavaScriptFunction(frameID, callbackID, exceptionMessage, errorType);
}

void WebAutomationSessionProxy::didEvaluateJavaScriptFunction(WebCore::FrameIdentifier frameID, uint64_t callbackID, const String& result, const String& errorType)
{
    auto findResult = m_webFramePendingEvaluateJavaScriptCallbacksMap.find(frameID);
    if (findResult != m_webFramePendingEvaluateJavaScriptCallbacksMap.end()) {
        findResult->value.removeFirst(callbackID);
        ASSERT(!findResult->value.contains(callbackID));
        if (findResult->value.isEmpty())
            m_webFramePendingEvaluateJavaScriptCallbacksMap.remove(findResult);
    }

    WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidEvaluateJavaScriptFunction(callbackID, result, errorType), 0);
}

void WebAutomationSessionProxy::resolveChildFrameWithOrdinal(WebCore::PageIdentifier pageID, Optional<WebCore::FrameIdentifier> frameID, uint32_t ordinal, CompletionHandler<void(Optional<String>, Optional<WebCore::FrameIdentifier>)>&& completionHandler)
{
    WebPage* page = WebProcess::singleton().webPage(pageID);
    if (!page) {
        String windowNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::WindowNotFound);
        completionHandler(windowNotFoundErrorType, WTF::nullopt);
        return;
    }

    String frameNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);

    WebFrame* frame = frameID ? WebProcess::singleton().webFrame(*frameID) : page->mainWebFrame();
    if (!frame) {
        completionHandler(frameNotFoundErrorType, WTF::nullopt);
        return;
    }

    WebCore::Frame* coreFrame = frame->coreFrame();
    if (!coreFrame) {
        completionHandler(frameNotFoundErrorType, WTF::nullopt);
        return;
    }

    WebCore::Frame* coreChildFrame = coreFrame->tree().scopedChild(ordinal);
    if (!coreChildFrame) {
        completionHandler(frameNotFoundErrorType, WTF::nullopt);
        return;
    }

    WebFrame* childFrame = WebFrame::fromCoreFrame(*coreChildFrame);
    if (!childFrame) {
        completionHandler(frameNotFoundErrorType, WTF::nullopt);
        return;
    }

    completionHandler(WTF::nullopt, childFrame->frameID());
}

void WebAutomationSessionProxy::resolveChildFrameWithNodeHandle(WebCore::PageIdentifier pageID, Optional<WebCore::FrameIdentifier> frameID, const String& nodeHandle, CompletionHandler<void(Optional<String>, Optional<WebCore::FrameIdentifier>)>&& completionHandler)
{
    WebPage* page = WebProcess::singleton().webPage(pageID);
    if (!page) {
        String windowNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::WindowNotFound);
        completionHandler(windowNotFoundErrorType, WTF::nullopt);
        return;
    }

    String frameNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);

    WebFrame* frame = frameID ? WebProcess::singleton().webFrame(*frameID) : page->mainWebFrame();
    if (!frame) {
        completionHandler(frameNotFoundErrorType, WTF::nullopt);
        return;
    }

    WebCore::Element* coreElement = elementForNodeHandle(*frame, nodeHandle);
    if (!is<WebCore::HTMLFrameElementBase>(coreElement)) {
        completionHandler(frameNotFoundErrorType, WTF::nullopt);
        return;
    }

    WebCore::Frame* coreFrameFromElement = downcast<WebCore::HTMLFrameElementBase>(*coreElement).contentFrame();
    if (!coreFrameFromElement) {
        completionHandler(frameNotFoundErrorType, WTF::nullopt);
        return;
    }

    WebFrame* frameFromElement = WebFrame::fromCoreFrame(*coreFrameFromElement);
    if (!frameFromElement) {
        completionHandler(frameNotFoundErrorType, WTF::nullopt);
        return;
    }

    completionHandler(WTF::nullopt, frameFromElement->frameID());
}

void WebAutomationSessionProxy::resolveChildFrameWithName(WebCore::PageIdentifier pageID, Optional<WebCore::FrameIdentifier> frameID, const String& name, CompletionHandler<void(Optional<String>, Optional<WebCore::FrameIdentifier>)>&& completionHandler)
{
    WebPage* page = WebProcess::singleton().webPage(pageID);
    if (!page) {
        String windowNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::WindowNotFound);
        completionHandler(windowNotFoundErrorType, WTF::nullopt);
        return;
    }

    String frameNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);

    WebFrame* frame = frameID ? WebProcess::singleton().webFrame(*frameID) : page->mainWebFrame();
    if (!frame) {
        completionHandler(frameNotFoundErrorType, WTF::nullopt);
        return;
    }

    WebCore::Frame* coreFrame = frame->coreFrame();
    if (!coreFrame) {
        completionHandler(frameNotFoundErrorType, WTF::nullopt);
        return;
    }

    WebCore::Frame* coreChildFrame = coreFrame->tree().scopedChild(name);
    if (!coreChildFrame) {
        completionHandler(frameNotFoundErrorType, WTF::nullopt);
        return;
    }

    WebFrame* childFrame = WebFrame::fromCoreFrame(*coreChildFrame);
    if (!childFrame) {
        completionHandler(frameNotFoundErrorType, WTF::nullopt);
        return;
    }

    completionHandler(WTF::nullopt, childFrame->frameID());
}

void WebAutomationSessionProxy::resolveParentFrame(WebCore::PageIdentifier pageID, Optional<WebCore::FrameIdentifier> frameID, CompletionHandler<void(Optional<String>, Optional<WebCore::FrameIdentifier>)>&& completionHandler)
{
    WebPage* page = WebProcess::singleton().webPage(pageID);
    if (!page) {
        String windowNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::WindowNotFound);
        completionHandler(windowNotFoundErrorType, WTF::nullopt);
        return;
    }

    String frameNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);

    WebFrame* frame = frameID ? WebProcess::singleton().webFrame(*frameID) : page->mainWebFrame();
    if (!frame) {
        completionHandler(frameNotFoundErrorType, WTF::nullopt);
        return;
    }

    WebFrame* parentFrame = frame->parentFrame();
    if (!parentFrame) {
        completionHandler(frameNotFoundErrorType, WTF::nullopt);
        return;
    }

    completionHandler(WTF::nullopt, parentFrame->frameID());
}

void WebAutomationSessionProxy::focusFrame(WebCore::PageIdentifier pageID, Optional<WebCore::FrameIdentifier> frameID)
{
    WebPage* page = WebProcess::singleton().webPage(pageID);
    if (!page)
        return;

    WebFrame* frame = frameID ? WebProcess::singleton().webFrame(*frameID) : page->mainWebFrame();
    if (!frame)
        return;

    WebCore::Frame* coreFrame = frame->coreFrame();
    if (!coreFrame)
        return;

    WebCore::Document* coreDocument = coreFrame->document();
    if (!coreDocument)
        return;

    WebCore::DOMWindow* coreDOMWindow = coreDocument->domWindow();
    if (!coreDOMWindow)
        return;

    coreDOMWindow->focus(true);
}

static WebCore::Element* containerElementForElement(WebCore::Element& element)
{
    // §13. Element State.
    // https://w3c.github.io/webdriver/webdriver-spec.html#dfn-container.
    if (is<WebCore::HTMLOptionElement>(element)) {
        auto& optionElement = downcast<WebCore::HTMLOptionElement>(element);
#if ENABLE(DATALIST_ELEMENT)
        if (auto* parentElement = optionElement.ownerDataListElement())
            return parentElement;
#endif
        if (auto* parentElement = optionElement.ownerSelectElement())
            return parentElement;

        return nullptr;
    }

    if (is<WebCore::HTMLOptGroupElement>(element)) {
        if (auto* parentElement = downcast<WebCore::HTMLOptGroupElement>(element).ownerSelectElement())
            return parentElement;

        return nullptr;
    }

    return &element;
}

static WebCore::FloatRect convertRectFromFrameClientToRootView(WebCore::FrameView* frameView, WebCore::FloatRect clientRect)
{
    if (!frameView->delegatesScrolling())
        return frameView->contentsToRootView(frameView->clientToDocumentRect(clientRect));

    // If the frame delegates scrolling, contentsToRootView doesn't take into account scroll/zoom/scale.
    auto& frame = frameView->frame();
    clientRect.scale(frame.pageZoomFactor() * frame.frameScaleFactor());
    clientRect.moveBy(frameView->contentsScrollPosition());
    return clientRect;
}

static WebCore::FloatPoint convertPointFromFrameClientToRootView(WebCore::FrameView* frameView, WebCore::FloatPoint clientPoint)
{
    if (!frameView->delegatesScrolling())
        return frameView->contentsToRootView(frameView->clientToDocumentPoint(clientPoint));

    // If the frame delegates scrolling, contentsToRootView doesn't take into account scroll/zoom/scale.
    auto& frame = frameView->frame();
    clientPoint.scale(frame.pageZoomFactor() * frame.frameScaleFactor());
    clientPoint.moveBy(frameView->contentsScrollPosition());
    return clientPoint;
}

void WebAutomationSessionProxy::computeElementLayout(WebCore::PageIdentifier pageID, Optional<WebCore::FrameIdentifier> frameID, String nodeHandle, bool scrollIntoViewIfNeeded, CoordinateSystem coordinateSystem, CompletionHandler<void(Optional<String>, WebCore::IntRect, Optional<WebCore::IntPoint>, bool)>&& completionHandler)
{
    WebPage* page = WebProcess::singleton().webPage(pageID);
    if (!page) {
        String windowNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::WindowNotFound);
        completionHandler(windowNotFoundErrorType, { }, WTF::nullopt, false);
        return;
    }

    WebFrame* frame = frameID ? WebProcess::singleton().webFrame(*frameID) : page->mainWebFrame();
    if (!frame || !frame->coreFrame() || !frame->coreFrame()->view()) {
        String frameNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);
        completionHandler(frameNotFoundErrorType, { }, WTF::nullopt, false);
        return;
    }

    WebCore::Element* coreElement = elementForNodeHandle(*frame, nodeHandle);
    if (!coreElement) {
        String nodeNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::NodeNotFound);
        completionHandler(nodeNotFoundErrorType, { }, WTF::nullopt, false);
        return;
    }

    auto* containerElement = containerElementForElement(*coreElement);
    if (scrollIntoViewIfNeeded && containerElement) {
        // §14.1 Element Click. Step 4. Scroll into view the element’s container.
        // https://w3c.github.io/webdriver/webdriver-spec.html#element-click
        containerElement->scrollIntoViewIfNotVisible(false);
        // FIXME: Wait in an implementation-specific way up to the session implicit wait timeout for the element to become in view.
    }

    WebCore::FrameView* frameView = frame->coreFrame()->view();
    WebCore::FrameView* mainView = frame->coreFrame()->mainFrame().view();

    WebCore::IntRect resultElementBounds;
    Optional<WebCore::IntPoint> resultInViewCenterPoint;
    bool isObscured = false;

    auto elementBoundsInRootCoordinates = convertRectFromFrameClientToRootView(frameView, coreElement->boundingClientRect());
    switch (coordinateSystem) {
    case CoordinateSystem::Page:
        resultElementBounds = enclosingIntRect(mainView->absoluteToDocumentRect(mainView->rootViewToContents(elementBoundsInRootCoordinates)));
        break;
    case CoordinateSystem::LayoutViewport:
        resultElementBounds = enclosingIntRect(mainView->absoluteToLayoutViewportRect(elementBoundsInRootCoordinates));
        break;
    }

    // If an <option> or <optgroup> does not have an associated <select> or <datalist> element, then give up.
    if (!containerElement) {
        String elementNotInteractableErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::ElementNotInteractable);
        completionHandler(elementNotInteractableErrorType, resultElementBounds, resultInViewCenterPoint, isObscured);
        return;
    }

    // §12.1 Element Interactability.
    // https://www.w3.org/TR/webdriver/#dfn-in-view-center-point
    auto* firstElementRect = containerElement->getClientRects()->item(0);
    if (!firstElementRect) {
        String elementNotInteractableErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::ElementNotInteractable);
        completionHandler(elementNotInteractableErrorType, resultElementBounds, resultInViewCenterPoint, isObscured);
        return;
    }

    // The W3C WebDriver specification does not explicitly intersect the element with the visual viewport.
    // Do that here so that the IVCP for an element larger than the viewport is within the viewport.
    // See spec bug here: https://github.com/w3c/webdriver/issues/1402
    auto viewportRect = frameView->documentToClientRect(frameView->visualViewportRect());
    auto elementRect = WebCore::FloatRect(firstElementRect->x(), firstElementRect->y(), firstElementRect->width(), firstElementRect->height());
    auto visiblePortionOfElementRect = intersection(viewportRect, elementRect);

    // If the element is entirely outside the viewport, still calculate it's bounds.
    if (visiblePortionOfElementRect.isEmpty()) {
        completionHandler(WTF::nullopt, resultElementBounds, resultInViewCenterPoint, isObscured);
        return;
    }

    auto elementInViewCenterPoint = visiblePortionOfElementRect.center();
    auto elementList = containerElement->treeScope().elementsFromPoint(elementInViewCenterPoint);
    auto index = elementList.findMatching([containerElement] (auto& item) { return item.get() == containerElement; });
    if (elementList.isEmpty() || index == notFound) {
        // We hit this case if the element is visibility:hidden or opacity:0, in which case it will not hit test
        // at the calculated IVCP. An element is technically not "in view" if it is not within its own paint/hit test tree,
        // so it cannot have an in-view center point either. And without an IVCP, the definition of 'obscured' makes no sense.
        // See <https://w3c.github.io/webdriver/webdriver-spec.html#dfn-in-view>.
        String elementNotInteractableErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::ElementNotInteractable);
        completionHandler(elementNotInteractableErrorType, resultElementBounds, resultInViewCenterPoint, isObscured);
        return;
    }

    // Check the case where a non-descendant element hit tests before the target element. For example, a child <option>
    // of a <select> does not obscure the <select>, but two sibling <div> that overlap at the IVCP will obscure each other.
    // Node::isDescendantOf() is not self-inclusive, so that is explicitly checked here.
    isObscured = elementList[0] != containerElement && !elementList[0]->isDescendantOf(containerElement);

    auto inViewCenterPointInRootCoordinates = convertPointFromFrameClientToRootView(frameView, elementInViewCenterPoint);
    switch (coordinateSystem) {
    case CoordinateSystem::Page:
        resultInViewCenterPoint = roundedIntPoint(mainView->absoluteToDocumentPoint(inViewCenterPointInRootCoordinates));
        break;
    case CoordinateSystem::LayoutViewport:
        resultInViewCenterPoint = roundedIntPoint(mainView->absoluteToLayoutViewportPoint(inViewCenterPointInRootCoordinates));
        break;
    }

    completionHandler(WTF::nullopt, resultElementBounds, resultInViewCenterPoint, isObscured);
}

void WebAutomationSessionProxy::selectOptionElement(WebCore::PageIdentifier pageID, Optional<WebCore::FrameIdentifier> frameID, String nodeHandle, CompletionHandler<void(Optional<String>)>&& completionHandler)
{
    WebPage* page = WebProcess::singleton().webPage(pageID);
    if (!page) {
        String windowNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::WindowNotFound);
        completionHandler(windowNotFoundErrorType);
        return;
    }

    WebFrame* frame = frameID ? WebProcess::singleton().webFrame(*frameID) : page->mainWebFrame();
    if (!frame || !frame->coreFrame() || !frame->coreFrame()->view()) {
        String frameNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);
        completionHandler(frameNotFoundErrorType);
        return;
    }

    WebCore::Element* coreElement = elementForNodeHandle(*frame, nodeHandle);
    if (!coreElement || (!is<WebCore::HTMLOptionElement>(coreElement) && !is<WebCore::HTMLOptGroupElement>(coreElement))) {
        String nodeNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::NodeNotFound);
        completionHandler(nodeNotFoundErrorType);
        return;
    }

    String elementNotInteractableErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::ElementNotInteractable);
    if (is<WebCore::HTMLOptGroupElement>(coreElement)) {
        completionHandler(elementNotInteractableErrorType);
        return;
    }

    auto& optionElement = downcast<WebCore::HTMLOptionElement>(*coreElement);
    auto* selectElement = optionElement.ownerSelectElement();
    if (!selectElement) {
        completionHandler(elementNotInteractableErrorType);
        return;
    }

    if (!selectElement->isDisabledFormControl() && !optionElement.isDisabledFormControl()) {
        // FIXME: According to the spec we should fire mouse over, move and down events, then input and change, and finally mouse up and click.
        // optionSelectedByUser() will fire input and change events if needed, but all other events should be fired manually here.
        selectElement->optionSelectedByUser(optionElement.index(), true, selectElement->multiple());
    }
    completionHandler(WTF::nullopt);
}

void WebAutomationSessionProxy::setFilesForInputFileUpload(WebCore::PageIdentifier pageID, Optional<WebCore::FrameIdentifier> frameID, String nodeHandle, Vector<String>&& filenames, CompletionHandler<void(Optional<String>)>&& completionHandler)
{
    WebPage* page = WebProcess::singleton().webPage(pageID);
    if (!page) {
        String windowNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::WindowNotFound);
        completionHandler(windowNotFoundErrorType);
        return;
    }

    WebFrame* frame = frameID ? WebProcess::singleton().webFrame(*frameID) : page->mainWebFrame();
    if (!frame || !frame->coreFrame() || !frame->coreFrame()->view()) {
        String frameNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);
        completionHandler(frameNotFoundErrorType);
        return;
    }

    WebCore::Element* coreElement = elementForNodeHandle(*frame, nodeHandle);
    if (!coreElement || !is<WebCore::HTMLInputElement>(coreElement) || !downcast<WebCore::HTMLInputElement>(*coreElement).isFileUpload()) {
        String nodeNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::NodeNotFound);
        completionHandler(nodeNotFoundErrorType);
        return;
    }

    auto& inputElement = downcast<WebCore::HTMLInputElement>(*coreElement);
    Vector<Ref<WebCore::File>> fileObjects;
    if (inputElement.multiple()) {
        if (auto* files = inputElement.files()) {
            for (auto& file : files->files())
                fileObjects.append(file.copyRef());
        }
    }
    for (const auto& path : filenames)
        fileObjects.append(File::create(path));
    inputElement.setFiles(FileList::create(WTFMove(fileObjects)));

    completionHandler(WTF::nullopt);
}

static WebCore::IntRect snapshotRectForScreenshot(WebPage& page, WebCore::Element* element, bool clipToViewport)
{
    auto* frameView = page.mainFrameView();
    if (!frameView)
        return { };

    if (element) {
        if (!element->renderer())
            return { };

        WebCore::LayoutRect topLevelRect;
        WebCore::IntRect elementRect = WebCore::snappedIntRect(element->renderer()->paintingRootRect(topLevelRect));
        if (clipToViewport)
            elementRect.intersect(frameView->visibleContentRect());

        return elementRect;
    }

    if (auto* frameView = page.mainFrameView())
        return clipToViewport ? frameView->visibleContentRect() : WebCore::IntRect(WebCore::IntPoint(0, 0), frameView->contentsSize());

    return { };
}

void WebAutomationSessionProxy::takeScreenshot(WebCore::PageIdentifier pageID, Optional<WebCore::FrameIdentifier> frameID, String nodeHandle, bool scrollIntoViewIfNeeded, bool clipToViewport, uint64_t callbackID)
{
    ShareableBitmap::Handle handle;

    WebPage* page = WebProcess::singleton().webPage(pageID);
    if (!page) {
        String windowNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::WindowNotFound);
        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidTakeScreenshot(callbackID, handle, windowNotFoundErrorType), 0);
        return;
    }

    WebFrame* frame = frameID ? WebProcess::singleton().webFrame(*frameID) : page->mainWebFrame();
    if (!frame || !frame->coreFrame()) {
        String frameNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);
        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidTakeScreenshot(callbackID, handle, frameNotFoundErrorType), 0);
        return;
    }

    WebCore::Element* coreElement = nullptr;
    if (!nodeHandle.isEmpty()) {
        coreElement = elementForNodeHandle(*frame, nodeHandle);
        if (!coreElement) {
            String nodeNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::NodeNotFound);
            WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidTakeScreenshot(callbackID, handle, nodeNotFoundErrorType), 0);
            return;
        }
    }

    if (coreElement && scrollIntoViewIfNeeded)
        coreElement->scrollIntoViewIfNeeded(false);

    String screenshotErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::ScreenshotError);
    WebCore::IntRect snapshotRect = snapshotRectForScreenshot(*page, coreElement, clipToViewport);
    if (snapshotRect.isEmpty()) {
        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidTakeScreenshot(callbackID, handle, screenshotErrorType), 0);
        return;
    }

    RefPtr<WebImage> image = page->scaledSnapshotWithOptions(snapshotRect, 1, SnapshotOptionsShareable);
    if (!image) {
        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidTakeScreenshot(callbackID, handle, screenshotErrorType), 0);
        return;
    }

    image->bitmap().createHandle(handle, SharedMemory::Protection::ReadOnly);
    WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidTakeScreenshot(callbackID, handle, { }), 0);
}

void WebAutomationSessionProxy::getCookiesForFrame(WebCore::PageIdentifier pageID, Optional<WebCore::FrameIdentifier> frameID, CompletionHandler<void(Optional<String>, Vector<WebCore::Cookie>)>&& completionHandler)
{
    WebPage* page = WebProcess::singleton().webPage(pageID);
    if (!page) {
        String windowNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::WindowNotFound);
        completionHandler(windowNotFoundErrorType, Vector<WebCore::Cookie>());
        return;
    }

    WebFrame* frame = frameID ? WebProcess::singleton().webFrame(*frameID) : page->mainWebFrame();
    if (!frame || !frame->coreFrame() || !frame->coreFrame()->document()) {
        String frameNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);
        completionHandler(frameNotFoundErrorType, Vector<WebCore::Cookie>());
        return;
    }

    // This returns the same list of cookies as when evaluating `document.cookies` in JavaScript.
    auto& document = *frame->coreFrame()->document();
    Vector<WebCore::Cookie> foundCookies;
    if (!document.cookieURL().isEmpty())
        page->corePage()->cookieJar().getRawCookies(document, document.cookieURL(), foundCookies);

    completionHandler(WTF::nullopt, foundCookies);
}

void WebAutomationSessionProxy::deleteCookie(WebCore::PageIdentifier pageID, Optional<WebCore::FrameIdentifier> frameID, String cookieName, CompletionHandler<void(Optional<String>)>&& completionHandler)
{
    WebPage* page = WebProcess::singleton().webPage(pageID);
    if (!page) {
        String windowNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::WindowNotFound);
        completionHandler(windowNotFoundErrorType);
        return;
    }

    WebFrame* frame = frameID ? WebProcess::singleton().webFrame(*frameID) : page->mainWebFrame();
    if (!frame || !frame->coreFrame() || !frame->coreFrame()->document()) {
        String frameNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);
        completionHandler(frameNotFoundErrorType);
        return;
    }

    auto& document = *frame->coreFrame()->document();
    page->corePage()->cookieJar().deleteCookie(document, document.cookieURL(), cookieName);

    completionHandler(WTF::nullopt);
}

} // namespace WebKit
