/*
 * Copyright (C) 2015-2020 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.
 */

#import "config.h"
#import "UIScriptControllerIOS.h"

#if PLATFORM(IOS_FAMILY)

#import "HIDEventGenerator.h"
#import "PlatformViewHelpers.h"
#import "PlatformWebView.h"
#import "StringFunctions.h"
#import "TestController.h"
#import "TestRunnerWKWebView.h"
#import "UIKitSPI.h"
#import "UIScriptContext.h"
#import <JavaScriptCore/JavaScriptCore.h>
#import <JavaScriptCore/OpaqueJSString.h>
#import <UIKit/UIKit.h>
#import <WebCore/FloatPoint.h>
#import <WebCore/FloatRect.h>
#import <WebKit/WKWebViewPrivate.h>
#import <WebKit/WKWebViewPrivateForTesting.h>
#import <WebKit/WebKit.h>
#import <pal/spi/ios/GraphicsServicesSPI.h>
#import <wtf/BlockPtr.h>
#import <wtf/MonotonicTime.h>
#import <wtf/SoftLinking.h>
#import <wtf/Vector.h>
#import <wtf/cocoa/TypeCastsCocoa.h>

SOFT_LINK_FRAMEWORK(UIKit)
SOFT_LINK_CLASS(UIKit, UIPhysicalKeyboardEvent)

@interface UIPhysicalKeyboardEvent (UIPhysicalKeyboardEventHack)
@property (nonatomic, assign) NSInteger _modifierFlags;
@end

namespace WTR {

static BOOL returnYes()
{
    return YES;
}

static BOOL returnNo()
{
    return NO;
}

static NSDictionary *toNSDictionary(CGRect rect)
{
    return @{
        @"left": @(rect.origin.x),
        @"top": @(rect.origin.y),
        @"width": @(rect.size.width),
        @"height": @(rect.size.height)
    };
}

static Vector<String> parseModifierArray(JSContextRef context, JSValueRef arrayValue)
{
    if (!arrayValue)
        return { };

    // The value may either be a string with a single modifier or an array of modifiers.
    if (JSValueIsString(context, arrayValue))
        return { toWTFString(context, arrayValue) };

    if (!JSValueIsObject(context, arrayValue))
        return { };
    JSObjectRef array = const_cast<JSObjectRef>(arrayValue);
    unsigned length = arrayLength(context, array);
    Vector<String> modifiers;
    modifiers.reserveInitialCapacity(length);
    for (unsigned i = 0; i < length; ++i)
        modifiers.append(toWTFString(context, JSObjectGetPropertyAtIndex(context, array, i, nullptr)));
    return modifiers;
}

Ref<UIScriptController> UIScriptController::create(UIScriptContext& context)
{
    return adoptRef(*new UIScriptControllerIOS(context));
}

void UIScriptControllerIOS::waitForOutstandingCallbacks()
{
    HIDEventGenerator *eventGenerator = HIDEventGenerator.sharedHIDEventGenerator;
    NSDate *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:1];
    while (eventGenerator.hasOutstandingCallbacks) {
        [NSRunLoop.currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:timeoutDate];
        if ([timeoutDate compare:NSDate.date] == NSOrderedAscending)
            [NSException raise:@"WebKitTestRunnerTestProblem" format:@"The previous test completed before all synthesized events had been handled. Perhaps you're calling notifyDone() too early?"];
    }
}

void UIScriptControllerIOS::doAfterPresentationUpdate(JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
    [webView() _doAfterNextPresentationUpdate:makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get()];
}

void UIScriptControllerIOS::doAfterNextStablePresentationUpdate(JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
    [webView() _doAfterNextStablePresentationUpdate:makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get()];
}

void UIScriptControllerIOS::ensurePositionInformationIsUpToDateAt(long x, long y, JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
    [webView() _requestActivatedElementAtPosition:CGPointMake(x, y) completionBlock:makeBlockPtr([this, strongThis = Ref { *this }, callbackID] (_WKActivatedElementInfo *) {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get()];
}

void UIScriptControllerIOS::doAfterVisibleContentRectUpdate(JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
    [webView() _doAfterNextVisibleContentRectUpdate:makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get()];
}

void UIScriptControllerIOS::zoomToScale(double scale, JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);

    [webView() zoomToScale:scale animated:YES completionHandler:makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get()];
}

void UIScriptControllerIOS::retrieveSpeakSelectionContent(JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
    
    [webView() accessibilityRetrieveSpeakSelectionContentWithCompletionHandler:makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get()];
}

JSRetainPtr<JSStringRef> UIScriptControllerIOS::accessibilitySpeakSelectionContent() const
{
    return adopt(JSStringCreateWithCFString((CFStringRef)webView().accessibilitySpeakSelectionContent));
}

void UIScriptControllerIOS::simulateAccessibilitySettingsChangeNotification(JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);

    auto* webView = this->webView();
    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
    [center postNotificationName:UIAccessibilityInvertColorsStatusDidChangeNotification object:webView];

    [webView _doAfterNextPresentationUpdate:makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get()];
}

double UIScriptControllerIOS::zoomScale() const
{
    return webView().scrollView.zoomScale;
}

static CGPoint globalToContentCoordinates(TestRunnerWKWebView *webView, long x, long y)
{
    CGPoint point = CGPointMake(x, y);
    point = [webView _convertPointFromContentsToView:point];
    point = [webView convertPoint:point toView:nil];
    point = [webView.window convertPoint:point toWindow:nil];
    return point;
}

void UIScriptControllerIOS::touchDownAtPoint(long x, long y, long touchCount, JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);

    auto location = globalToContentCoordinates(webView(), x, y);
    [[HIDEventGenerator sharedHIDEventGenerator] touchDown:location touchCount:touchCount completionBlock:makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get()];
}

void UIScriptControllerIOS::liftUpAtPoint(long x, long y, long touchCount, JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
    
    auto location = globalToContentCoordinates(webView(), x, y);
    [[HIDEventGenerator sharedHIDEventGenerator] liftUp:location touchCount:touchCount completionBlock:makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get()];
}

void UIScriptControllerIOS::singleTapAtPoint(long x, long y, JSValueRef callback)
{
    singleTapAtPointWithModifiers(x, y, nullptr, callback);
}

void UIScriptControllerIOS::activateAtPoint(long x, long y, JSValueRef callback)
{
    singleTapAtPoint(x, y, callback);
}

void UIScriptControllerIOS::waitForModalTransitionToFinish() const
{
    while ([webView().window.rootViewController isPerformingModalTransition])
        [NSRunLoop.currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:NSDate.distantFuture];
}

void UIScriptControllerIOS::waitForSingleTapToReset() const
{
    auto allPendingSingleTapGesturesHaveBeenReset = [&]() -> bool {
        for (UIGestureRecognizer *gesture in [platformContentView() gestureRecognizers]) {
            if (!gesture.enabled || ![gesture isKindOfClass:UITapGestureRecognizer.class])
                continue;

            UITapGestureRecognizer *tapGesture = (UITapGestureRecognizer *)gesture;
            if (tapGesture.numberOfTapsRequired != 1 || tapGesture.numberOfTouches != 1 || tapGesture.state == UIGestureRecognizerStatePossible)
                continue;

            return false;
        }
        return true;
    };

    auto startTime = MonotonicTime::now();
    while (!allPendingSingleTapGesturesHaveBeenReset()) {
        [NSRunLoop.currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:NSDate.distantFuture];
        if (MonotonicTime::now() - startTime > 1_s)
            break;
    }
}

void UIScriptControllerIOS::twoFingerSingleTapAtPoint(long x, long y, JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);

    auto location = globalToContentCoordinates(webView(), x, y);
    [[HIDEventGenerator sharedHIDEventGenerator] twoFingerTap:location completionBlock:makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get()];
}

void UIScriptControllerIOS::singleTapAtPointWithModifiers(long x, long y, JSValueRef modifierArray, JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
    singleTapAtPointWithModifiers(WebCore::FloatPoint(x, y), parseModifierArray(m_context->jsContext(), modifierArray), makeBlockPtr([this, protectedThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }));
}

void UIScriptControllerIOS::singleTapAtPointWithModifiers(WebCore::FloatPoint location, Vector<String>&& modifierFlags, BlockPtr<void()>&& block)
{
    // Animations on the scroll view could be in progress to reveal a form control which may interfere with hit testing (see wkb.ug/205458).
    [webView().scrollView _removeAllAnimations:NO];

    // Necessary for popovers on iPad (used for elements such as <select>) to finish dismissing (see wkb.ug/206759).
    waitForModalTransitionToFinish();

    waitForSingleTapToReset();

    for (auto& modifierFlag : modifierFlags)
        [[HIDEventGenerator sharedHIDEventGenerator] keyDown:modifierFlag];

    [[HIDEventGenerator sharedHIDEventGenerator] tap:globalToContentCoordinates(webView(), location.x(), location.y()) completionBlock:[this, protectedThis = Ref { *this }, modifierFlags = WTFMove(modifierFlags), block = WTFMove(block)] () mutable {
        if (!m_context)
            return;

        for (size_t i = modifierFlags.size(); i; ) {
            --i;
            [[HIDEventGenerator sharedHIDEventGenerator] keyUp:modifierFlags[i]];
        }
        [[HIDEventGenerator sharedHIDEventGenerator] sendMarkerHIDEventWithCompletionBlock:block.get()];
    }];
}

void UIScriptControllerIOS::doubleTapAtPoint(long x, long y, float delay, JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);

    [[HIDEventGenerator sharedHIDEventGenerator] doubleTap:globalToContentCoordinates(webView(), x, y) delay:delay completionBlock:makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get()];
}

void UIScriptControllerIOS::stylusDownAtPoint(long x, long y, float azimuthAngle, float altitudeAngle, float pressure, JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);

    auto location = globalToContentCoordinates(webView(), x, y);
    [[HIDEventGenerator sharedHIDEventGenerator] stylusDownAtPoint:location azimuthAngle:azimuthAngle altitudeAngle:altitudeAngle pressure:pressure completionBlock:makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get()];
}

void UIScriptControllerIOS::stylusMoveToPoint(long x, long y, float azimuthAngle, float altitudeAngle, float pressure, JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);

    auto location = globalToContentCoordinates(webView(), x, y);
    [[HIDEventGenerator sharedHIDEventGenerator] stylusMoveToPoint:location azimuthAngle:azimuthAngle altitudeAngle:altitudeAngle pressure:pressure completionBlock:makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get()];
}

void UIScriptControllerIOS::stylusUpAtPoint(long x, long y, JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);

    auto location = globalToContentCoordinates(webView(), x, y);
    [[HIDEventGenerator sharedHIDEventGenerator] stylusUpAtPoint:location completionBlock:makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get()];
}

void UIScriptControllerIOS::stylusTapAtPoint(long x, long y, float azimuthAngle, float altitudeAngle, float pressure, JSValueRef callback)
{
    stylusTapAtPointWithModifiers(x, y, azimuthAngle, altitudeAngle, pressure, nullptr, callback);
}

void UIScriptControllerIOS::stylusTapAtPointWithModifiers(long x, long y, float azimuthAngle, float altitudeAngle, float pressure, JSValueRef modifierArray, JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);

    waitForSingleTapToReset();

    auto modifierFlags = parseModifierArray(m_context->jsContext(), modifierArray);
    for (auto& modifierFlag : modifierFlags)
        [[HIDEventGenerator sharedHIDEventGenerator] keyDown:modifierFlag];

    auto location = globalToContentCoordinates(webView(), x, y);
    [[HIDEventGenerator sharedHIDEventGenerator] stylusTapAtPoint:location azimuthAngle:azimuthAngle altitudeAngle:altitudeAngle pressure:pressure completionBlock:makeBlockPtr([this, strongThis = Ref { *this }, callbackID, modifierFlags = WTFMove(modifierFlags)] {
        if (!m_context)
            return;
        for (size_t i = modifierFlags.size(); i; ) {
            --i;
            [[HIDEventGenerator sharedHIDEventGenerator] keyUp:modifierFlags[i]];
        }
        [[HIDEventGenerator sharedHIDEventGenerator] sendMarkerHIDEventWithCompletionBlock:makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
            if (!m_context)
                return;
            m_context->asyncTaskComplete(callbackID);
        }).get()];
    }).get()];
}

void convertCoordinates(TestRunnerWKWebView *webView, NSMutableDictionary *event)
{
    if (event[HIDEventTouchesKey]) {
        for (NSMutableDictionary *touch in event[HIDEventTouchesKey]) {
            NSNumber *touchX = touch[HIDEventXKey] == [NSNull null] ? nil : touch[HIDEventXKey];
            NSNumber *touchY = touch[HIDEventYKey] == [NSNull null] ? nil : touch[HIDEventYKey];
            
            auto location = globalToContentCoordinates(webView, (long)[touchX doubleValue], (long)[touchY doubleValue]);
            touch[HIDEventXKey] = @(location.x);
            touch[HIDEventYKey] = @(location.y);
        }
    }
}

void UIScriptControllerIOS::sendEventStream(JSStringRef eventsJSON, JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);

    String jsonString = eventsJSON->string();
    auto eventInfo = dynamic_objc_cast<NSDictionary>([NSJSONSerialization JSONObjectWithData:[(NSString *)jsonString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves error:nil]);

    auto *webView = this->webView();
    
    for (NSMutableDictionary *event in eventInfo[TopLevelEventInfoKey]) {
        if (![event[HIDEventCoordinateSpaceKey] isEqualToString:HIDEventCoordinateSpaceTypeContent])
            continue;
        
        if (event[HIDEventStartEventKey])
            convertCoordinates(webView, event[HIDEventStartEventKey]);
        
        if (event[HIDEventEndEventKey])
            convertCoordinates(webView, event[HIDEventEndEventKey]);
        
        if (event[HIDEventTouchesKey])
            convertCoordinates(webView, event);
    }
    
    if (!eventInfo || ![eventInfo isKindOfClass:[NSDictionary class]]) {
        WTFLogAlways("JSON is not convertible to a dictionary");
        return;
    }

    auto completion = makeBlockPtr([this, protectedThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    });

    [[HIDEventGenerator sharedHIDEventGenerator] sendEventStream:eventInfo completionBlock:completion.get()];
}

static NSDictionary *dictionaryForFingerEventWithContentPoint(CGPoint point, NSString* phase, Seconds timeOffset)
{
    return @{
        HIDEventCoordinateSpaceKey : HIDEventCoordinateSpaceTypeContent,
        HIDEventTimeOffsetKey : @(timeOffset.seconds()),
        HIDEventInputType : HIDEventInputTypeHand,
        HIDEventTouchesKey : @[
            @{
                HIDEventTouchIDKey : @1,
                HIDEventInputType : HIDEventInputTypeFinger,
                HIDEventPhaseKey : phase,
                HIDEventXKey : @(point.x),
                HIDEventYKey : @(point.y),
            },
        ],
    };
}

void UIScriptControllerIOS::dragFromPointToPoint(long startX, long startY, long endX, long endY, double durationSeconds, JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
    
    CGPoint startPoint = globalToContentCoordinates(webView(), startX, startY);
    CGPoint endPoint = globalToContentCoordinates(webView(), endX, endY);

    NSDictionary *touchDownInfo = dictionaryForFingerEventWithContentPoint(startPoint, HIDEventPhaseBegan, 0_s);
    NSDictionary *interpolatedEvents = @{
        HIDEventInterpolateKey : HIDEventInterpolationTypeLinear,
        HIDEventCoordinateSpaceKey : HIDEventCoordinateSpaceTypeContent,
        HIDEventTimestepKey : @(0.016),
        HIDEventStartEventKey : dictionaryForFingerEventWithContentPoint(startPoint, HIDEventPhaseMoved, 0_s),
        HIDEventEndEventKey : dictionaryForFingerEventWithContentPoint(endPoint, HIDEventPhaseMoved, Seconds(durationSeconds)),
    };
    NSDictionary *liftUpInfo = dictionaryForFingerEventWithContentPoint(endPoint, HIDEventPhaseEnded, Seconds(durationSeconds));

    NSDictionary *eventStream = @{
        TopLevelEventInfoKey : @[
            touchDownInfo,
            interpolatedEvents,
            liftUpInfo,
        ],
    };

    auto completion = makeBlockPtr([this, protectedThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    });

    [[HIDEventGenerator sharedHIDEventGenerator] sendEventStream:eventStream completionBlock:completion.get()];
}
    
void UIScriptControllerIOS::longPressAtPoint(long x, long y, JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
    
    [[HIDEventGenerator sharedHIDEventGenerator] longPress:globalToContentCoordinates(webView(), x, y) completionBlock:makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get()];
}

void UIScriptControllerIOS::enterText(JSStringRef text)
{
    auto textAsCFString = adoptCF(JSStringCopyCFString(kCFAllocatorDefault, text));
    [webView() _simulateTextEntered:(NSString *)textAsCFString.get()];
}

void UIScriptControllerIOS::typeCharacterUsingHardwareKeyboard(JSStringRef character, JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);

    // Assumes that the keyboard is already shown.
    [[HIDEventGenerator sharedHIDEventGenerator] keyPress:toWTFString(character) completionBlock:makeBlockPtr([strongThis = Ref { *this }, callbackID] {
        if (strongThis->m_context)
            strongThis->m_context->asyncTaskComplete(callbackID);
    }).get()];
}

static UIPhysicalKeyboardEvent *createUIPhysicalKeyboardEvent(NSString *hidInputString, NSString *uiEventInputString, UIKeyModifierFlags modifierFlags, UIKeyboardInputFlags inputFlags, bool isKeyDown)
{
    auto* keyboardEvent = [getUIPhysicalKeyboardEventClass() _eventWithInput:uiEventInputString inputFlags:inputFlags];
    keyboardEvent._modifierFlags = modifierFlags;
    auto hidEvent = createHIDKeyEvent(hidInputString, keyboardEvent.timestamp, isKeyDown);
    [keyboardEvent _setHIDEvent:hidEvent.get() keyboard:nullptr];
    return keyboardEvent;
}

void UIScriptControllerIOS::rawKeyDown(JSStringRef key)
{
    // Key can be either a single Unicode code point or the name of a special key (e.g. "downArrow").
    // HIDEventGenerator knows how to map these special keys to the appropriate keycode.
    [[HIDEventGenerator sharedHIDEventGenerator] keyDown:toWTFString(key)];
    [[HIDEventGenerator sharedHIDEventGenerator] sendMarkerHIDEventWithCompletionBlock:^{ /* Do nothing */ }];
}

void UIScriptControllerIOS::rawKeyUp(JSStringRef key)
{
    // Key can be either a single Unicode code point or the name of a special key (e.g. "downArrow").
    // HIDEventGenerator knows how to map these special keys to the appropriate keycode.
    [[HIDEventGenerator sharedHIDEventGenerator] keyUp:toWTFString(key)];
    [[HIDEventGenerator sharedHIDEventGenerator] sendMarkerHIDEventWithCompletionBlock:^{ /* Do nothing */ }];
}

void UIScriptControllerIOS::keyDown(JSStringRef character, JSValueRef modifierArray)
{
    // Character can be either a single Unicode code point or the name of a special key (e.g. "downArrow").
    // HIDEventGenerator knows how to map these special keys to the appropriate keycode.
    auto inputString = toWTFString(character);
    auto modifierFlags = parseModifierArray(m_context->jsContext(), modifierArray);

    for (auto& modifierFlag : modifierFlags)
        [[HIDEventGenerator sharedHIDEventGenerator] keyDown:modifierFlag];

    [[HIDEventGenerator sharedHIDEventGenerator] keyDown:inputString];
    [[HIDEventGenerator sharedHIDEventGenerator] keyUp:inputString];

    for (size_t i = modifierFlags.size(); i; ) {
        --i;
        [[HIDEventGenerator sharedHIDEventGenerator] keyUp:modifierFlags[i]];
    }

    [[HIDEventGenerator sharedHIDEventGenerator] sendMarkerHIDEventWithCompletionBlock:^{ /* Do nothing */ }];
}

void UIScriptControllerIOS::dismissFormAccessoryView()
{
    [webView() dismissFormAccessoryView];
}

JSObjectRef UIScriptControllerIOS::filePickerAcceptedTypeIdentifiers()
{
    NSArray *acceptedTypeIdentifiers = [webView() _filePickerAcceptedTypeIdentifiers];
    return JSValueToObject(m_context->jsContext(), [JSValue valueWithObject:acceptedTypeIdentifiers inContext:[JSContext contextWithJSGlobalContextRef:m_context->jsContext()]].JSValueRef, nullptr);
}

void UIScriptControllerIOS::dismissFilePicker(JSValueRef callback)
{
    TestRunnerWKWebView *webView = this->webView();
    [webView _dismissFilePicker];

    // Round-trip with the WebProcess to make sure it has been notified of the dismissal.
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
    [webView evaluateJavaScript:@"" completionHandler:makeBlockPtr([this, strongThis = Ref { *this }, callbackID] (id result, NSError *error) {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get()];
}

JSRetainPtr<JSStringRef> UIScriptControllerIOS::selectFormPopoverTitle() const
{
    return adopt(JSStringCreateWithCFString((CFStringRef)webView().selectFormPopoverTitle));
}

JSRetainPtr<JSStringRef> UIScriptControllerIOS::textContentType() const
{
    return adopt(JSStringCreateWithCFString((CFStringRef)(webView().textContentTypeForTesting ?: @"")));
}

JSRetainPtr<JSStringRef> UIScriptControllerIOS::formInputLabel() const
{
    return adopt(JSStringCreateWithCFString((CFStringRef)webView().formInputLabel));
}

void UIScriptControllerIOS::selectFormAccessoryPickerRow(long rowIndex)
{
    [webView() selectFormAccessoryPickerRow:rowIndex];
}

bool UIScriptControllerIOS::selectFormAccessoryHasCheckedItemAtRow(long rowIndex) const
{
    return [webView() selectFormAccessoryHasCheckedItemAtRow:rowIndex];
}

void UIScriptControllerIOS::setTimePickerValue(long hour, long minute)
{
    [webView() setTimePickerValueToHour:hour minute:minute];
}

double UIScriptControllerIOS::timePickerValueHour() const
{
    return [webView() timePickerValueHour];
}

double UIScriptControllerIOS::timePickerValueMinute() const
{
    return [webView() timePickerValueMinute];
}

bool UIScriptControllerIOS::isPresentingModally() const
{
    return !!webView().window.rootViewController.presentedViewController;
}

static CGPoint contentOffsetBoundedIfNecessary(UIScrollView *scrollView, long x, long y, ScrollToOptions* options)
{
    auto contentOffset = CGPointMake(x, y);
    bool constrain = !options || !options->unconstrained;
    if (constrain) {
        UIEdgeInsets contentInsets = scrollView.contentInset;
        CGSize contentSize = scrollView.contentSize;
        CGSize scrollViewSize = scrollView.bounds.size;

        CGFloat maxHorizontalOffset = contentSize.width + contentInsets.right - scrollViewSize.width;
        contentOffset.x = std::min(maxHorizontalOffset, contentOffset.x);
        contentOffset.x = std::max(-contentInsets.left, contentOffset.x);

        CGFloat maxVerticalOffset = contentSize.height + contentInsets.bottom - scrollViewSize.height;
        contentOffset.y = std::min(maxVerticalOffset, contentOffset.y);
        contentOffset.y = std::max(-contentInsets.top, contentOffset.y);
    }

    return contentOffset;
}

double UIScriptControllerIOS::contentOffsetX() const
{
    return webView().scrollView.contentOffset.x;
}

double UIScriptControllerIOS::contentOffsetY() const
{
    return webView().scrollView.contentOffset.y;
}

bool UIScriptControllerIOS::scrollUpdatesDisabled() const
{
    return webView()._scrollingUpdatesDisabledForTesting;
}

void UIScriptControllerIOS::setScrollUpdatesDisabled(bool disabled)
{
    webView()._scrollingUpdatesDisabledForTesting = disabled;
}

void UIScriptControllerIOS::scrollToOffset(long x, long y, ScrollToOptions* options)
{
    TestRunnerWKWebView *webView = this->webView();
    auto offset = contentOffsetBoundedIfNecessary(webView.scrollView, x, y, options);
    [webView.scrollView setContentOffset:offset animated:YES];
}

void UIScriptControllerIOS::immediateScrollToOffset(long x, long y, ScrollToOptions* options)
{
    TestRunnerWKWebView *webView = this->webView();
    auto offset = contentOffsetBoundedIfNecessary(webView.scrollView, x, y, options);
    [webView.scrollView setContentOffset:offset animated:NO];
}

static UIScrollView *enclosingScrollViewIncludingSelf(UIView *view)
{
    do {
        if ([view isKindOfClass:[UIScrollView class]])
            return static_cast<UIScrollView *>(view);
    } while ((view = [view superview]));

    return nil;
}

void UIScriptControllerIOS::immediateScrollElementAtContentPointToOffset(long x, long y, long xScrollOffset, long yScrollOffset)
{
    UIView *contentView = platformContentView();
    UIView *hitView = [contentView hitTest:CGPointMake(x, y) withEvent:nil];
    UIScrollView *enclosingScrollView = enclosingScrollViewIncludingSelf(hitView);
    [enclosingScrollView setContentOffset:CGPointMake(xScrollOffset, yScrollOffset)];
}

void UIScriptControllerIOS::immediateZoomToScale(double scale)
{
    [webView().scrollView setZoomScale:scale animated:NO];
}

void UIScriptControllerIOS::keyboardAccessoryBarNext()
{
    [webView() keyboardAccessoryBarNext];
}

void UIScriptControllerIOS::keyboardAccessoryBarPrevious()
{
    [webView() keyboardAccessoryBarPrevious];
}

bool UIScriptControllerIOS::isShowingKeyboard() const
{
    return webView().showingKeyboard;
}

bool UIScriptControllerIOS::hasInputSession() const
{
    return webView().isInteractingWithFormControl;
}

void UIScriptControllerIOS::applyAutocorrection(JSStringRef newString, JSStringRef oldString, JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);

    TestRunnerWKWebView *webView = this->webView();
    [webView applyAutocorrection:toWTFString(newString) toString:toWTFString(oldString) withCompletionHandler:makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
        dispatch_async(dispatch_get_main_queue(), makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
            // applyAutocorrection can call its completion handler synchronously,
            // which makes UIScriptController unhappy (see bug 172884).
            if (!m_context)
                return;
            m_context->asyncTaskComplete(callbackID);
        }).get());
    }).get()];
}

double UIScriptControllerIOS::minimumZoomScale() const
{
    return webView().scrollView.minimumZoomScale;
}

double UIScriptControllerIOS::maximumZoomScale() const
{
    return webView().scrollView.maximumZoomScale;
}

std::optional<bool> UIScriptControllerIOS::stableStateOverride() const
{
    TestRunnerWKWebView *webView = this->webView();
    if (webView._stableStateOverride)
        return webView._stableStateOverride.boolValue;

    return std::nullopt;
}

void UIScriptControllerIOS::setStableStateOverride(std::optional<bool> overrideValue)
{
    TestRunnerWKWebView *webView = this->webView();
    if (overrideValue)
        webView._stableStateOverride = @(overrideValue.value());
    else
        webView._stableStateOverride = nil;
}

JSObjectRef UIScriptControllerIOS::contentVisibleRect() const
{
    CGRect contentVisibleRect = webView()._contentVisibleRect;
    
    WebCore::FloatRect rect(contentVisibleRect.origin.x, contentVisibleRect.origin.y, contentVisibleRect.size.width, contentVisibleRect.size.height);
    return m_context->objectFromRect(rect);
}

JSObjectRef UIScriptControllerIOS::textSelectionRangeRects() const
{
    auto selectionRects = adoptNS([[NSMutableArray alloc] init]);
    NSArray *rects = webView()._uiTextSelectionRects;
    for (NSValue *rect in rects)
        [selectionRects addObject:toNSDictionary(rect.CGRectValue)];

    return JSValueToObject(m_context->jsContext(), [JSValue valueWithObject:selectionRects.get() inContext:[JSContext contextWithJSGlobalContextRef:m_context->jsContext()]].JSValueRef, nullptr);
}

JSObjectRef UIScriptControllerIOS::textSelectionCaretRect() const
{
    return JSValueToObject(m_context->jsContext(), [JSValue valueWithObject:toNSDictionary(webView()._uiTextCaretRect) inContext:[JSContext contextWithJSGlobalContextRef:m_context->jsContext()]].JSValueRef, nullptr);
}

static void clipSelectionViewRectToContentView(CGRect& rect, UIView *contentView)
{
    rect = CGRectIntersection(contentView.bounds, rect);
    // The content view (a WKContentView in WebKit) is expected to implement the optional text input method -_selectionClipRect.
    ASSERT([contentView respondsToSelector:@selector(_selectionClipRect)]);
    auto selectionClipRect = [(UIView <UITextInputInternal> *)contentView _selectionClipRect];
    if (!CGRectIsNull(selectionClipRect))
        rect = CGRectIntersection(selectionClipRect, rect);
}

JSObjectRef UIScriptControllerIOS::selectionStartGrabberViewRect() const
{
    UIView *contentView = platformContentView();
    UIView *selectionRangeView = [contentView valueForKeyPath:@"interactionAssistant.selectionView.rangeView"];
    auto frameInContentViewCoordinates = [selectionRangeView convertRect:[[selectionRangeView valueForKeyPath:@"startGrabber"] frame] toView:contentView];
    clipSelectionViewRectToContentView(frameInContentViewCoordinates, contentView);
    auto jsContext = m_context->jsContext();
    return JSValueToObject(jsContext, [JSValue valueWithObject:toNSDictionary(frameInContentViewCoordinates) inContext:[JSContext contextWithJSGlobalContextRef:jsContext]].JSValueRef, nullptr);
}

JSObjectRef UIScriptControllerIOS::selectionEndGrabberViewRect() const
{
    UIView *contentView = platformContentView();
    UIView *selectionRangeView = [contentView valueForKeyPath:@"interactionAssistant.selectionView.rangeView"];
    auto frameInContentViewCoordinates = [selectionRangeView convertRect:[[selectionRangeView valueForKeyPath:@"endGrabber"] frame] toView:contentView];
    clipSelectionViewRectToContentView(frameInContentViewCoordinates, contentView);
    auto jsContext = m_context->jsContext();
    return JSValueToObject(jsContext, [JSValue valueWithObject:toNSDictionary(frameInContentViewCoordinates) inContext:[JSContext contextWithJSGlobalContextRef:jsContext]].JSValueRef, nullptr);
}

JSObjectRef UIScriptControllerIOS::selectionCaretViewRect() const
{
    UIView *contentView = platformContentView();
    UIView *caretView = [contentView valueForKeyPath:@"interactionAssistant.selectionView.caretView"];
    auto rectInContentViewCoordinates = CGRectIntersection([caretView convertRect:caretView.bounds toView:contentView], contentView.bounds);
    clipSelectionViewRectToContentView(rectInContentViewCoordinates, contentView);
    return JSValueToObject(m_context->jsContext(), [JSValue valueWithObject:toNSDictionary(rectInContentViewCoordinates) inContext:[JSContext contextWithJSGlobalContextRef:m_context->jsContext()]].JSValueRef, nullptr);
}

JSObjectRef UIScriptControllerIOS::selectionRangeViewRects() const
{
    UIView *contentView = platformContentView();
    UIView *rangeView = [contentView valueForKeyPath:@"interactionAssistant.selectionView.rangeView"];
    auto rectsAsDictionaries = adoptNS([[NSMutableArray alloc] init]);
    NSArray *textRectInfoArray = [rangeView valueForKeyPath:@"rects"];
    for (id textRectInfo in textRectInfoArray) {
        NSValue *rectValue = [textRectInfo valueForKeyPath:@"rect"];
        auto rangeRectInContentViewCoordinates = [rangeView convertRect:rectValue.CGRectValue toView:contentView];
        clipSelectionViewRectToContentView(rangeRectInContentViewCoordinates, contentView);
        [rectsAsDictionaries addObject:toNSDictionary(CGRectIntersection(rangeRectInContentViewCoordinates, contentView.bounds))];
    }
    return JSValueToObject(m_context->jsContext(), [JSValue valueWithObject:rectsAsDictionaries.get() inContext:[JSContext contextWithJSGlobalContextRef:m_context->jsContext()]].JSValueRef, nullptr);
}

JSObjectRef UIScriptControllerIOS::inputViewBounds() const
{
    return JSValueToObject(m_context->jsContext(), [JSValue valueWithObject:toNSDictionary(webView()._inputViewBoundsInWindow) inContext:[JSContext contextWithJSGlobalContextRef:m_context->jsContext()]].JSValueRef, nullptr);
}

JSRetainPtr<JSStringRef> UIScriptControllerIOS::scrollingTreeAsText() const
{
    return adopt(JSStringCreateWithCFString((CFStringRef)[webView() _scrollingTreeAsText]));
}

JSRetainPtr<JSStringRef> UIScriptControllerIOS::uiViewTreeAsText() const
{
    return adopt(JSStringCreateWithCFString((CFStringRef)[webView() _uiViewTreeAsText]));
}

JSObjectRef UIScriptControllerIOS::propertiesOfLayerWithID(uint64_t layerID) const
{
    return JSValueToObject(m_context->jsContext(), [JSValue valueWithObject:[webView() _propertiesOfLayerWithID:layerID] inContext:[JSContext contextWithJSGlobalContextRef:m_context->jsContext()]].JSValueRef, nullptr);
}

bool UIScriptControllerIOS::mayContainEditableElementsInRect(unsigned x, unsigned y, unsigned width, unsigned height)
{
    auto contentRect = CGRectMake(x, y, width, height);
    return [webView() _mayContainEditableElementsInRect:[webView() convertRect:contentRect fromView:platformContentView()]];
}

static UIDeviceOrientation toUIDeviceOrientation(DeviceOrientation* orientation)
{
    if (!orientation)
        return UIDeviceOrientationPortrait;
        
    switch (*orientation) {
    case DeviceOrientation::Portrait:
        return UIDeviceOrientationPortrait;
    case DeviceOrientation::PortraitUpsideDown:
        return UIDeviceOrientationPortraitUpsideDown;
    case DeviceOrientation::LandscapeLeft:
        return UIDeviceOrientationLandscapeLeft;
    case DeviceOrientation::LandscapeRight:
        return UIDeviceOrientationLandscapeRight;
    }
    
    return UIDeviceOrientationPortrait;
}

void UIScriptControllerIOS::simulateRotation(DeviceOrientation* orientation, JSValueRef callback)
{
    TestRunnerWKWebView *webView = this->webView();
    webView.usesSafariLikeRotation = NO;
    
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
    
    webView.rotationDidEndCallback = makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get();
    
    [[UIDevice currentDevice] setOrientation:toUIDeviceOrientation(orientation) animated:YES];
}

void UIScriptControllerIOS::simulateRotationLikeSafari(DeviceOrientation* orientation, JSValueRef callback)
{
    TestRunnerWKWebView *webView = this->webView();
    webView.usesSafariLikeRotation = YES;
    
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
    
    webView.rotationDidEndCallback = makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get();
    
    [[UIDevice currentDevice] setOrientation:toUIDeviceOrientation(orientation) animated:YES];
}

void UIScriptControllerIOS::setDidStartFormControlInteractionCallback(JSValueRef callback)
{
    UIScriptController::setDidStartFormControlInteractionCallback(callback);
    webView().didStartFormControlInteractionCallback = makeBlockPtr([this, strongThis = Ref { *this }] {
        if (!m_context)
            return;
        m_context->fireCallback(CallbackTypeDidStartFormControlInteraction);
    }).get();
}

void UIScriptControllerIOS::setDidEndFormControlInteractionCallback(JSValueRef callback)
{
    UIScriptController::setDidEndFormControlInteractionCallback(callback);
    webView().didEndFormControlInteractionCallback = makeBlockPtr([this, strongThis = Ref { *this }] {
        if (!m_context)
            return;
        m_context->fireCallback(CallbackTypeDidEndFormControlInteraction);
    }).get();
}

void UIScriptControllerIOS::setWillBeginZoomingCallback(JSValueRef callback)
{
    UIScriptController::setWillBeginZoomingCallback(callback);
    webView().willBeginZoomingCallback = makeBlockPtr([this, strongThis = Ref { *this }] {
        if (!m_context)
            return;
        m_context->fireCallback(CallbackTypeWillBeginZooming);
    }).get();
}

void UIScriptControllerIOS::setDidEndZoomingCallback(JSValueRef callback)
{
    UIScriptController::setDidEndZoomingCallback(callback);
    webView().didEndZoomingCallback = makeBlockPtr([this, strongThis = Ref { *this }] {
        if (!m_context)
            return;
        m_context->fireCallback(CallbackTypeDidEndZooming);
    }).get();
}

void UIScriptControllerIOS::setDidShowKeyboardCallback(JSValueRef callback)
{
    UIScriptController::setDidShowKeyboardCallback(callback);
    webView().didShowKeyboardCallback = makeBlockPtr([this, strongThis = Ref { *this }] {
        if (!m_context)
            return;
        m_context->fireCallback(CallbackTypeDidShowKeyboard);
    }).get();
}

void UIScriptControllerIOS::setDidHideKeyboardCallback(JSValueRef callback)
{
    UIScriptController::setDidHideKeyboardCallback(callback);
    webView().didHideKeyboardCallback = makeBlockPtr([this, strongThis = Ref { *this }] {
        if (!m_context)
            return;
        m_context->fireCallback(CallbackTypeDidHideKeyboard);
    }).get();
}

void UIScriptControllerIOS::setWillStartInputSessionCallback(JSValueRef callback)
{
    UIScriptController::setWillStartInputSessionCallback(callback);
    webView().willStartInputSessionCallback = makeBlockPtr([this, strongThis = Ref { *this }] {
        if (!m_context)
            return;
        m_context->fireCallback(CallbackTypeWillStartInputSession);
    }).get();
}

void UIScriptControllerIOS::chooseMenuAction(JSStringRef jsAction, JSValueRef callback)
{
    auto action = adoptCF(JSStringCopyCFString(kCFAllocatorDefault, jsAction));
    auto rect = rectForMenuAction(action.get());
    if (rect.isEmpty())
        return;

    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
    singleTapAtPointWithModifiers(rect.center(), { }, makeBlockPtr([this, protectedThis = Ref { *this }, callbackID] {
        if (m_context)
            m_context->asyncTaskComplete(callbackID);
    }));
}

bool UIScriptControllerIOS::isShowingPopover() const
{
    return webView().showingPopover;
}

void UIScriptControllerIOS::setWillPresentPopoverCallback(JSValueRef callback)
{
    UIScriptController::setWillPresentPopoverCallback(callback);
    webView().willPresentPopoverCallback = makeBlockPtr([this, strongThis = Ref { *this }] {
        if (!m_context)
            return;
        m_context->fireCallback(CallbackTypeWillPresentPopover);
    }).get();
}

void UIScriptControllerIOS::setDidDismissPopoverCallback(JSValueRef callback)
{
    UIScriptController::setDidDismissPopoverCallback(callback);
    webView().didDismissPopoverCallback = makeBlockPtr([this, strongThis = Ref { *this }] {
        if (!m_context)
            return;
        m_context->fireCallback(CallbackTypeDidDismissPopover);
    }).get();
}

JSObjectRef UIScriptControllerIOS::rectForMenuAction(JSStringRef jsAction) const
{
    auto action = adoptCF(JSStringCopyCFString(kCFAllocatorDefault, jsAction));
    auto rect = rectForMenuAction(action.get());
    if (rect.isEmpty())
        return nullptr;

    return m_context->objectFromRect(rect);
}

WebCore::FloatRect UIScriptControllerIOS::rectForMenuAction(CFStringRef action) const
{
    UIView *viewForAction = nil;
    UIWindow *window = webView().window;

    if (UIView *calloutBar = UICalloutBar.activeCalloutBar; calloutBar.window) {
        for (UIButton *button in findAllViewsInHierarchyOfType(calloutBar, UIButton.class)) {
            NSString *buttonTitle = [button titleForState:UIControlStateNormal];
            if (!buttonTitle.length)
                continue;

            if (![buttonTitle isEqualToString:(__bridge NSString *)action])
                continue;

            viewForAction = button;
            break;
        }
    }

    if (!viewForAction) {
        for (UILabel *label in findAllViewsInHierarchyOfType(window, UILabel.class)) {
            if (![label.text isEqualToString:(__bridge NSString *)action])
                continue;

            viewForAction = label;
            break;
        }
    }

    if (!viewForAction)
        return { };

    CGRect rectInRootViewCoordinates = [viewForAction convertRect:viewForAction.bounds toView:platformContentView()];
    return WebCore::FloatRect(rectInRootViewCoordinates.origin.x, rectInRootViewCoordinates.origin.y, rectInRootViewCoordinates.size.width, rectInRootViewCoordinates.size.height);
}

JSObjectRef UIScriptControllerIOS::menuRect() const
{
    UIView *calloutBar = UICalloutBar.activeCalloutBar;
    if (!calloutBar.window)
        return nullptr;

    CGRect rectInRootViewCoordinates = [calloutBar convertRect:calloutBar.bounds toView:platformContentView()];
    return m_context->objectFromRect(WebCore::FloatRect(rectInRootViewCoordinates.origin.x, rectInRootViewCoordinates.origin.y, rectInRootViewCoordinates.size.width, rectInRootViewCoordinates.size.height));
}

bool UIScriptControllerIOS::isDismissingMenu() const
{
    return webView().dismissingMenu;
}

void UIScriptControllerIOS::setDidEndScrollingCallback(JSValueRef callback)
{
    UIScriptController::setDidEndScrollingCallback(callback);
    webView().didEndScrollingCallback = makeBlockPtr([this, strongThis = Ref { *this }] {
        if (!m_context)
            return;
        m_context->fireCallback(CallbackTypeDidEndScrolling);
    }).get();
}

void UIScriptControllerIOS::clearAllCallbacks()
{
    [webView() resetInteractionCallbacks];
}

void UIScriptControllerIOS::setSafeAreaInsets(double top, double right, double bottom, double left)
{
    UIEdgeInsets insets = UIEdgeInsetsMake(top, left, bottom, right);
    webView().overrideSafeAreaInsets = insets;
}

void UIScriptControllerIOS::beginBackSwipe(JSValueRef callback)
{
    [webView() _beginBackSwipeForTesting];
}

void UIScriptControllerIOS::completeBackSwipe(JSValueRef callback)
{
    [webView() _completeBackSwipeForTesting];
}

void UIScriptControllerIOS::activateDataListSuggestion(unsigned index, JSValueRef callback)
{
    [webView() _selectDataListOption:index];

    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
    dispatch_async(dispatch_get_main_queue(), makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get());
}

bool UIScriptControllerIOS::isShowingDataListSuggestions() const
{
#if ENABLE(IOS_FORM_CONTROL_REFRESH)
    return [webView() _isShowingDataListSuggestions];
#else
    Class remoteKeyboardWindowClass = NSClassFromString(@"UIRemoteKeyboardWindow");
    Class suggestionsPickerViewClass = NSClassFromString(@"WKDataListSuggestionsPickerView");
    UIWindow *remoteInputHostingWindow = nil;
    for (UIWindow *window in UIApplication.sharedApplication.windows) {
        if ([window isKindOfClass:remoteKeyboardWindowClass])
            remoteInputHostingWindow = window;
    }

    if (!remoteInputHostingWindow)
        return false;

    __block bool foundDataListSuggestionsPickerView = false;
    forEachViewInHierarchy(remoteInputHostingWindow, ^(UIView *subview, BOOL *stop) {
        if (![subview isKindOfClass:suggestionsPickerViewClass])
            return;

        foundDataListSuggestionsPickerView = true;
        *stop = YES;
    });
    return foundDataListSuggestionsPickerView;
#endif
}

void UIScriptControllerIOS::setSelectedColorForColorPicker(double red, double green, double blue)
{
    UIColor *color = [UIColor colorWithRed:red green:green blue:blue alpha:1.0f];
    [webView() setSelectedColorForColorPicker:color];
}

void UIScriptControllerIOS::setKeyboardInputModeIdentifier(JSStringRef identifier)
{
    TestController::singleton().setKeyboardInputModeIdentifier(toWTFString(identifier));
}

// FIXME: Write this in terms of HIDEventGenerator once we know how to reset caps lock state
// on test completion to avoid it effecting subsequent tests.
void UIScriptControllerIOS::toggleCapsLock(JSValueRef callback)
{
    m_capsLockOn = !m_capsLockOn;
    auto *keyboardEvent = createUIPhysicalKeyboardEvent(@"capsLock", [NSString string], m_capsLockOn ? UIKeyModifierAlphaShift : 0,
        kUIKeyboardInputModifierFlagsChanged, m_capsLockOn);
    [[UIApplication sharedApplication] handleKeyUIEvent:keyboardEvent];
    doAsyncTask(callback);
}

bool UIScriptControllerIOS::keyboardIsAutomaticallyShifted() const
{
    return UIKeyboardImpl.activeInstance.isAutoShifted;
}

bool UIScriptControllerIOS::isAnimatingDragCancel() const
{
    return webView()._animatingDragCancel;
}

JSRetainPtr<JSStringRef> UIScriptControllerIOS::selectionCaretBackgroundColor() const
{
    NSString *serializedColor = webView()._serializedSelectionCaretBackgroundColorForTesting;
    if (!serializedColor)
        return { };

    return adopt(JSStringCreateWithCFString((__bridge CFStringRef)serializedColor));
}

JSObjectRef UIScriptControllerIOS::tapHighlightViewRect() const
{
    return JSValueToObject(m_context->jsContext(), [JSValue valueWithObject:toNSDictionary(webView()._tapHighlightViewRect) inContext:[JSContext contextWithJSGlobalContextRef:m_context->jsContext()]].JSValueRef, nullptr);
}

JSObjectRef UIScriptControllerIOS::attachmentInfo(JSStringRef jsAttachmentIdentifier)
{
    auto attachmentIdentifier = toWTFString(jsAttachmentIdentifier);
    _WKAttachment *attachment = [webView() _attachmentForIdentifier:attachmentIdentifier];
    _WKAttachmentInfo *attachmentInfo = attachment.info;

    NSDictionary *attachmentInfoDictionary = @{
        @"id": attachmentIdentifier,
        @"name": attachmentInfo.name,
        @"contentType": attachmentInfo.contentType,
        @"filePath": attachmentInfo.filePath,
        @"size": @(attachmentInfo.data.length),
    };

    return JSValueToObject(m_context->jsContext(), [JSValue valueWithObject:attachmentInfoDictionary inContext:[JSContext contextWithJSGlobalContextRef:m_context->jsContext()]].JSValueRef, nullptr);
}

UIView *UIScriptControllerIOS::platformContentView() const
{
    return webView().contentView;
}

JSObjectRef UIScriptControllerIOS::calendarType() const
{
    UIView *contentView = webView().contentView;
    NSString *calendarTypeString = [contentView valueForKeyPath:@"dateTimeInputControl.dateTimePickerCalendarType"];
    auto jsContext = m_context->jsContext();
    return JSValueToObject(jsContext, [JSValue valueWithObject:calendarTypeString inContext:[JSContext contextWithJSGlobalContextRef:jsContext]].JSValueRef, nullptr);
}

void UIScriptControllerIOS::setHardwareKeyboardAttached(bool attached)
{
    GSEventSetHardwareKeyboardAttached(attached, 0);
    method_setImplementation(class_getClassMethod([UIKeyboard class], @selector(isInHardwareKeyboardMode)), reinterpret_cast<IMP>(attached ? returnYes : returnNo));
}

void UIScriptControllerIOS::setAllowsViewportShrinkToFit(bool allows)
{
    webView()._allowsViewportShrinkToFit = allows;
}

void UIScriptControllerIOS::doAfterDoubleTapDelay(JSValueRef callback)
{
    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);

    NSTimeInterval maximumIntervalBetweenSuccessiveTaps = 0;
    for (UIGestureRecognizer *gesture in [platformContentView() gestureRecognizers]) {
        if (![gesture isKindOfClass:[UITapGestureRecognizer class]])
            continue;

        UITapGestureRecognizer *tapGesture = (UITapGestureRecognizer *)gesture;
        if (tapGesture.numberOfTapsRequired < 2)
            continue;

        if (tapGesture.maximumIntervalBetweenSuccessiveTaps > maximumIntervalBetweenSuccessiveTaps)
            maximumIntervalBetweenSuccessiveTaps = tapGesture.maximumIntervalBetweenSuccessiveTaps;
    }

    if (maximumIntervalBetweenSuccessiveTaps) {
        const NSTimeInterval additionalDelayBetweenSuccessiveTaps = 0.01;
        maximumIntervalBetweenSuccessiveTaps += additionalDelayBetweenSuccessiveTaps;
    }

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(maximumIntervalBetweenSuccessiveTaps * NSEC_PER_SEC)), dispatch_get_main_queue(), makeBlockPtr([this, strongThis = Ref { *this }, callbackID] {
        if (!m_context)
            return;
        m_context->asyncTaskComplete(callbackID);
    }).get());
}

void UIScriptControllerIOS::copyText(JSStringRef text)
{
    UIPasteboard.generalPasteboard.string = text->string();
}

void UIScriptControllerIOS::installTapGestureOnWindow(JSValueRef callback)
{
    m_context->registerCallback(callback, CallbackTypeWindowTapRecognized);
    webView().windowTapRecognizedCallback = makeBlockPtr([this, strongThis = Ref { *this }] {
        if (!m_context)
            return;
        m_context->fireCallback(CallbackTypeWindowTapRecognized);
    }).get();
}

bool UIScriptControllerIOS::suppressSoftwareKeyboard() const
{
    return webView()._suppressSoftwareKeyboard;
}

void UIScriptControllerIOS::setSuppressSoftwareKeyboard(bool suppressSoftwareKeyboard)
{
    webView()._suppressSoftwareKeyboard = suppressSoftwareKeyboard;
}

}

#endif // PLATFORM(IOS_FAMILY)
