/*
 * Copyright (C) 2010-2026 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 "TestController.h"

#include "DataFunctions.h"
#include "DictionaryFunctions.h"
#include "EventSenderProxy.h"
#include "ExternalURLBlockingHelpers.h"
#include "Options.h"
#include "PlatformWebView.h"
#include "StringFunctions.h"
#include "TestCommand.h"
#include "TestInvocation.h"
#include "WebCoreTestSupport.h"
#include <JavaScriptCore/InitializeThreading.h>
#include <WebCore/NotificationData.h>
#include <WebKit/WKArray.h>
#include <WebKit/WKAuthenticationChallenge.h>
#include <WebKit/WKAuthenticationDecisionListener.h>
#include <WebKit/WKBase.h>
#include <WebKit/WKCast.h>
#include <WebKit/WKContextConfigurationRef.h>
#include <WebKit/WKContextPrivate.h>
#include <WebKit/WKCredential.h>
#include <WebKit/WKDownloadClient.h>
#include <WebKit/WKDownloadRef.h>
#include <WebKit/WKEvent.h>
#include <WebKit/WKFrameHandleRef.h>
#include <WebKit/WKFrameInfoRef.h>
#include <WebKit/WKHTTPCookieStoreRef.h>
#include <WebKit/WKIconDatabase.h>
#include <WebKit/WKJSHandleRef.h>
#include <WebKit/WKMediaKeySystemPermissionCallback.h>
#include <WebKit/WKMessageListener.h>
#include <WebKit/WKMockMediaDevice.h>
#include <WebKit/WKNavigationActionRef.h>
#include <WebKit/WKNavigationResponseRef.h>
#include <WebKit/WKNotification.h>
#include <WebKit/WKNotificationManager.h>
#include <WebKit/WKNotificationPermissionRequest.h>
#include <WebKit/WKNumber.h>
#include <WebKit/WKOpenPanelResultListener.h>
#include <WebKit/WKPageConfigurationRef.h>
#include <WebKit/WKPageInjectedBundleClient.h>
#include <WebKit/WKPagePrivate.h>
#include <WebKit/WKPluginInformation.h>
#include <WebKit/WKPreferencesRefPrivate.h>
#include <WebKit/WKProtectionSpace.h>
#include <WebKit/WKQueryPermissionResultCallback.h>
#include <WebKit/WKRetainPtr.h>
#include <WebKit/WKScriptMessageRef.h>
#include <WebKit/WKSecurityOriginRef.h>
#include <WebKit/WKTextChecker.h>
#include <WebKit/WKURL.h>
#include <WebKit/WKUserContentControllerRef.h>
#include <WebKit/WKUserContentExtensionStoreRef.h>
#include <WebKit/WKUserScriptInjectionTime.h>
#include <WebKit/WKUserScriptRef.h>
#include <WebKit/WKWebsiteDataStoreConfigurationRef.h>
#include <WebKit/WKWebsiteDataStoreRef.h>
#include <WebKit/WKWebsitePolicies.h>
#include <algorithm>
#include <cstdio>
#include <ctype.h>
#include <fstream>
#include <stdlib.h>
#include <string>
#include <wtf/AutodrainedPool.h>
#include <wtf/Compiler.h>
#include <wtf/CompletionHandler.h>
#include <wtf/CryptographicallyRandomNumber.h>
#include <wtf/FileSystem.h>
#include <wtf/Logging.h>
#include <wtf/MainThread.h>
#include <wtf/MallocSpan.h>
#include <wtf/ProcessPrivilege.h>
#include <wtf/RefCounted.h>
#include <wtf/RunLoop.h>
#include <wtf/SetForScope.h>
#include <wtf/StdLibExtras.h>
#include <wtf/UUID.h>
#include <wtf/UniqueArray.h>
#include <wtf/UniqueRef.h>
#include <wtf/WTFProcess.h>
#include <wtf/text/CString.h>
#include <wtf/text/MakeString.h>
#include <wtf/text/TextStream.h>
#include <wtf/text/WTFString.h>
#include <wtf/unicode/CharacterNames.h>

#if PLATFORM(COCOA)
#include <WebKit/WKContextPrivateMac.h>
#include <WebKit/WKPagePrivateMac.h>
#endif

#if PLATFORM(MAC)
#import <ApplicationServices/ApplicationServices.h>
#import <wtf/RetainPtr.h>
#import <wtf/RuntimeApplicationChecks.h>
#endif

#if PLATFORM(GTK) || PLATFORM(WPE)
#include <WebKit/WKContextConfigurationGlib.h>
#endif

#if PLATFORM(WIN)
#include <direct.h>
#include <shlwapi.h>
#include <wininet.h>
#define getcwd _getcwd
#define PATH_MAX _MAX_PATH
#else
#include <unistd.h>
#endif

namespace WTR {

#if OS(WINDOWS)
static constexpr auto pathSeparator = '\\';
#else
static constexpr auto pathSeparator = '/';
#endif

const WTF::Seconds TestController::defaultShortTimeout = 5_s;
const WTF::Seconds TestController::noTimeout = -1_s;

static const double ZoomMultiplierRatio = 1.2;

static WKURLRef blankURL()
{
    static WKURLRef staticBlankURL = WKURLCreateWithUTF8CString("about:blank");
    return staticBlankURL;
}

static WKDataRef copyWebCryptoMasterKey(WKPageRef, const void*)
{
    // Any 128 bit key would do, all we need for testing is to implement the callback.
    return WKDataCreate((const uint8_t*)"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", 16);
}

static std::string testPath(WKURLRef url)
{
    auto scheme = adoptWK(WKURLCopyScheme(url));
    if (WKStringIsEqualToUTF8CStringIgnoringCase(scheme.get(), "file")) {
        auto path = adoptWK(WKURLCopyPath(url));
        auto buffer = std::vector<char>(WKStringGetMaximumUTF8CStringSize(path.get()));
        auto length = WKStringGetUTF8CString(path.get(), buffer.data(), buffer.size());
        RELEASE_ASSERT(length > 0);
#if OS(WINDOWS)
        // Remove the first '/' if it starts with something like "/C:/".
        if (length >= 4 && buffer[0] == '/' && buffer[2] == ':' && buffer[3] == '/')
            return std::string(buffer.data() + 1, length - 1);
#endif
        return std::string(buffer.data(), length - 1);
    }
    return std::string();
}

void TestController::navigationDidBecomeDownloadShared(WKDownloadRef download, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->downloadDidStart(download);

    WKDownloadClientV0 client {
        { 0, clientInfo },
        TestController::downloadDidReceiveServerRedirectToURL,
        TestController::downloadDidReceiveAuthenticationChallenge,
        TestController::decideDestinationWithSuggestedFilename,
        TestController::downloadDidWriteData,
        TestController::downloadDidFinish,
        TestController::downloadDidFail
    };

    WKDownloadSetClient(download, &client.base);
}

void TestController::navigationActionDidBecomeDownload(WKPageRef, WKNavigationActionRef, WKDownloadRef download, const void* clientInfo)
{
    navigationDidBecomeDownloadShared(download, clientInfo);
}

void TestController::navigationResponseDidBecomeDownload(WKPageRef, WKNavigationResponseRef, WKDownloadRef download, const void* clientInfo)
{
    navigationDidBecomeDownloadShared(download, clientInfo);
}

AsyncTask* AsyncTask::m_currentTask;

bool AsyncTask::run()
{
    m_currentTask = this;
    m_task();
    TestController::singleton().runUntil(m_taskDone, m_timeout);
    m_currentTask = nullptr;
    return m_taskDone;
}

AsyncTask* AsyncTask::currentTask()
{
    return m_currentTask;
}

static TestController* controller;

TestController& TestController::singleton()
{
    ASSERT(controller);
    return *controller;
}

TestController::TestController(int argc, const char* argv[])
{
    initialize(argc, argv);
    controller = this;
    run();
    controller = nullptr;
}

TestController::~TestController()
{
    // The context will be null if WebKitTestRunner was in server mode, but ran no tests.
    if (m_context)
        WKIconDatabaseClose(WKContextGetIconDatabase(m_context.get()));

    platformDestroy();
}

static WKRect getWindowFrame(WKPageRef page, const void* clientInfo)
{
    PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
    return view->windowFrame();
}

#if !PLATFORM(COCOA)
static unsigned long long exceededDatabaseQuota(WKPageRef, WKFrameRef, WKSecurityOriginRef, WKStringRef, WKStringRef, unsigned long long currentQuota, unsigned long long, unsigned long long currentDatabaseUsage, unsigned long long expectedUsage, const void*)
{
    return TestController::singleton().decideStorageQuota(currentQuota, currentDatabaseUsage, expectedUsage);
}
#endif

static void setWindowFrame(WKPageRef page, WKRect frame, const void* clientInfo)
{
    PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
    view->setWindowFrame(frame);
}

static bool runBeforeUnloadConfirmPanel(WKPageRef page, WKStringRef message, WKFrameRef frame, const void*)
{
    printf("CONFIRM NAVIGATION: %s\n", toSTD(message).c_str());
    return TestController::singleton().beforeUnloadReturnValue();
}

static void runOpenPanel(WKPageRef page, WKFrameRef frame, WKOpenPanelParametersRef parameters, WKOpenPanelResultListenerRef resultListenerRef, const void*)
{
    printf("OPEN FILE PANEL\n");
    if (WKOpenPanelParametersGetAllowsDirectories(parameters))
        printf("-> DIRECTORIES ARE ALLOWED\n");
    WKArrayRef fileURLs = TestController::singleton().openPanelFileURLs();
    if (!fileURLs || !WKArrayGetSize(fileURLs)) {
        WKOpenPanelResultListenerCancel(resultListenerRef);
        return;
    }
    
    WKTypeRef firstItem = WKArrayGetItemAtIndex(fileURLs, 0);
    
#if PLATFORM(IOS_FAMILY)
    auto displayString = adoptWK(WKURLCopyLastPathComponent(static_cast<WKURLRef>(firstItem)));
    WKDataRef mediaIcon = TestController::singleton().openPanelFileURLsMediaIcon();
    
    if (mediaIcon) {
        if (WKOpenPanelParametersGetAllowsMultipleFiles(parameters)) {
            WKOpenPanelResultListenerChooseMediaFiles(resultListenerRef, fileURLs, displayString.get(), mediaIcon);
            return;
        }
        
        WKOpenPanelResultListenerChooseMediaFiles(resultListenerRef, adoptWK(WKArrayCreate(&firstItem, 1)).get(), displayString.get(), mediaIcon);
        return;
    }
#endif

    auto allowedMIMETypes = adoptWK(WKOpenPanelParametersCopyAllowedMIMETypes(parameters));

    if (WKOpenPanelParametersGetAllowsMultipleFiles(parameters)) {
        WKOpenPanelResultListenerChooseFiles(resultListenerRef, fileURLs, allowedMIMETypes.get());
        return;
    }

    WKOpenPanelResultListenerChooseFiles(resultListenerRef, adoptWK(WKArrayCreate(&firstItem, 1)).get(), allowedMIMETypes.get());
}

void TestController::runModal(WKPageRef page, const void* clientInfo)
{
    PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
    TestController::singleton().mainWebView()->setWindowIsKey(false);
    runModal(view);
    TestController::singleton().mainWebView()->setWindowIsKey(true);
}

void TestController::closeOtherPage(WKPageRef page, const void* clientInfo)
{
    PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
    TestController::singleton().closeOtherPage(page, view);
}

static void focus(WKPageRef page, const void* clientInfo)
{
    PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
    view->focus();
    view->setWindowIsKey(true);
}

static void unfocus(WKPageRef page, const void* clientInfo)
{
    PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
    view->setWindowIsKey(false);
}

static void decidePolicyForGeolocationPermissionRequest(WKPageRef, WKFrameRef, WKSecurityOriginRef, WKGeolocationPermissionRequestRef permissionRequest, const void* clientInfo)
{
    TestController::singleton().handleGeolocationPermissionRequest(permissionRequest);
}

static void decidePolicyForUserMediaPermissionRequest(WKPageRef, WKFrameRef frame, WKSecurityOriginRef userMediaDocumentOrigin, WKSecurityOriginRef topLevelDocumentOrigin, WKUserMediaPermissionRequestRef permissionRequest, const void* clientInfo)
{
    TestController::singleton().handleUserMediaPermissionRequest(frame, userMediaDocumentOrigin, topLevelDocumentOrigin, permissionRequest);
}

static void runJavaScriptAlert(WKPageRef page, WKStringRef alertText, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptAlertResultListenerRef listener, const void *clientInfo)
{
    TestController::singleton().handleJavaScriptAlert(alertText, listener);
}

static void runJavaScriptPrompt(WKPageRef page, WKStringRef message, WKStringRef defaultValue, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptPromptResultListenerRef listener, const void *clientInfo)
{
    TestController::singleton().handleJavaScriptPrompt(message, defaultValue, listener);
}

static void runJavaScriptConfirm(WKPageRef page, WKStringRef message, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptConfirmResultListenerRef listener, const void *clientInfo)
{
    TestController::singleton().handleJavaScriptConfirm(message, listener);
}

static void requestPointerLock(WKPageRef page, WKCompletionListenerRef listener, const void*)
{
    WKCompletionListenerComplete(listener, nullptr);
}

static void printFrame(WKPageRef page, WKFrameRef frame, const void*)
{
    WKPageBeginPrinting(page, frame, WKPrintInfo { 1, 21, 29.7f });
}

static bool shouldAllowDeviceOrientationAndMotionAccess(WKPageRef, WKSecurityOriginRef origin, WKFrameInfoRef frame, const void*)
{
    return TestController::singleton().handleDeviceOrientationAndMotionAccessRequest(origin, frame);
}

// A placeholder to tell WebKit the client is WebKitTestRunner.
static void runWebAuthenticationPanel()
{
}

void TestController::setIsSpeechRecognitionPermissionGranted(bool granted)
{
    m_isSpeechRecognitionPermissionGranted = granted;
}

static void decidePolicyForMediaKeySystemPermissionRequest(WKPageRef, WKSecurityOriginRef, WKStringRef, WKMediaKeySystemPermissionCallbackRef callback)
{
    TestController::singleton().completeMediaKeySystemPermissionCheck(callback);
}

void TestController::completeMediaKeySystemPermissionCheck(WKMediaKeySystemPermissionCallbackRef callback)
{
    WKMediaKeySystemPermissionCallbackComplete(callback, m_isMediaKeySystemPermissionGranted);
}

void TestController::setIsMediaKeySystemPermissionGranted(bool granted)
{
    m_isMediaKeySystemPermissionGranted = granted;
}

static void queryPermission(WKStringRef string, WKSecurityOriginRef securityOrigin, WKQueryPermissionResultCallbackRef callback)
{
    TestController::singleton().handleQueryPermission(string, securityOrigin, callback);
}

void TestController::handleQueryPermission(WKStringRef string, WKSecurityOriginRef securityOrigin, WKQueryPermissionResultCallbackRef callback)
{
    if (toWTFString(string) == "camera"_s) {
        if (!m_isCameraPermissionAllowed) {
            WKQueryPermissionResultCallbackCompleteWithPrompt(callback);
            return;
        }
        if (!*m_isCameraPermissionAllowed) {
            WKQueryPermissionResultCallbackCompleteWithDenied(callback);
            return;
        }
        WKQueryPermissionResultCallbackCompleteWithGranted(callback);
        return;
    }

    if (toWTFString(string) == "microphone"_s) {
        if (!m_isMicrophonePermissionAllowed) {
            WKQueryPermissionResultCallbackCompleteWithPrompt(callback);
            return;
        }
        if (!*m_isMicrophonePermissionAllowed) {
            WKQueryPermissionResultCallbackCompleteWithDenied(callback);
            return;
        }
        WKQueryPermissionResultCallbackCompleteWithGranted(callback);
        return;
    }

    if (toWTFString(string) == "notifications"_s) {
        auto permissionState = m_webNotificationProvider.permissionState(securityOrigin);
        if (permissionState) {
            if (permissionState.value())
                WKQueryPermissionResultCallbackCompleteWithGranted(callback);
            else
                WKQueryPermissionResultCallbackCompleteWithDenied(callback);
            return;
        }
    }

    if (toWTFString(string) == "geolocation"_s) {
        m_geolocationPermissionQueryOrigins.add(toWTFString(adoptWK(WKSecurityOriginCopyToString(securityOrigin))));

        if (m_isGeolocationPermissionSet) {
            if (m_isGeolocationPermissionAllowed)
                WKQueryPermissionResultCallbackCompleteWithGranted(callback);
            else
                WKQueryPermissionResultCallbackCompleteWithDenied(callback);
            return;
        }
    }

    if (toWTFString(string) == "screen-wake-lock"_s) {
        if (m_screenWakeLockPermission) {
            if (*m_screenWakeLockPermission)
                WKQueryPermissionResultCallbackCompleteWithGranted(callback);
            else
                WKQueryPermissionResultCallbackCompleteWithDenied(callback);
            return;
        }
    }

    WKQueryPermissionResultCallbackCompleteWithPrompt(callback);
}

#if PLATFORM(IOS) || PLATFORM(VISION)
static void lockScreenOrientationCallback(WKPageRef, WKScreenOrientationType orientation)
{
    TestController::singleton().lockScreenOrientation(orientation);
}

static void unlockScreenOrientationCallback(WKPageRef)
{
    TestController::singleton().unlockScreenOrientation();
}
#endif

static StringView lastFileURLPathComponent(StringView path)
{
    auto pos = path.find("file://"_s);
    ASSERT(WTF::notFound != pos);

    auto tmpPath = path.substring(pos + 7);
    if (tmpPath.length() < 2) // Keep the lone slash to avoid empty output.
        return tmpPath;

    // Remove the trailing delimiter
    if (tmpPath[tmpPath.length() - 1] == '/')
        tmpPath = tmpPath.left(tmpPath.length() - 1);

    pos = tmpPath.reverseFind('/');
    if (WTF::notFound != pos)
        return tmpPath.substring(pos + 1);

    return tmpPath;
}

static void addMessageToConsole(WKPageRef, WKStringRef message, const void*)
{
    auto messageString = toWTFString(message);
    messageString = messageString.left(messageString.find(nullCharacter));

    size_t fileProtocolStart = messageString.find("file://"_s);
    if (fileProtocolStart != WTF::notFound) {
        StringView messageStringView { messageString };
        // FIXME: The code below does not handle additional text after url nor multiple urls. This matches DumpRenderTree implementation.
        messageString = makeString(messageStringView.left(fileProtocolStart), lastFileURLPathComponent(messageStringView.substring(fileProtocolStart)));
    }
    messageString = makeString("CONSOLE MESSAGE:"_s, addLeadingSpaceStripTrailingSpacesAddNewline(messageString));

    RefPtr invocation = TestController::singleton().currentInvocation();
    if (!invocation || invocation->gotFinalMessage())
        return;
    if (invocation->shouldDumpJSConsoleLogInStdErr()) {
        if (auto string = messageString.tryGetUTF8())
            SAFE_FPRINTF(stderr, "%s", *string);
        else
            SAFE_FPRINTF(stderr, "Out of memory\n");
    } else
        invocation->outputText(messageString);
}

void TestController::tooltipDidChange(WKPageRef, WKStringRef tooltip, const void*)
{
    TestController::singleton().tooltipDidChange(tooltip);
}

void TestController::tooltipDidChange(WKStringRef tooltip)
{
    m_tooltipCallbacks.notifyListeners(tooltip);
}

static void cursorDidChangeForTesting(WKStringRef cursorInfo, const void*)
{
    TestController::singleton().cursorDidChange(cursorInfo);
}

void TestController::cursorDidChange(WKStringRef cursorInfo)
{
    m_cursorCallbacks.notifyListeners(cursorInfo);
#if PLATFORM(MAC)
    if (m_mainWebView)
        m_mainWebView->updateCursorOverlayImage();
#endif
}

void TestController::Callbacks::append(WKJSHandleRef handle)
{
    if (!handle)
        return;
    m_callbacks.append(handle);
}

void TestController::Callbacks::notifyListeners(WKStringRef parameter)
{
    if (TestController::singleton().m_state != RunningTest)
        return;

    for (auto& callback : m_callbacks) {
        WKRetainPtr arguments = adoptWK(WKMutableDictionaryCreate());
        setValue(arguments, "callback", callback);
        setValue(arguments, "parameter", parameter);
        WKRetainPtr frame = adoptWK(WKJSHandleCopyFrameInfo(callback.get()));
        WKPageCallAsyncJavaScriptWithoutUserGesture(WKFrameInfoGetPage(frame.get()), toWK("return callback(parameter)").get(), arguments.get(), frame.get(), nullptr, nullptr);
    }
}

void TestController::Callbacks::notifyListeners()
{
    if (TestController::singleton().m_state != RunningTest)
        return;

    for (auto& callback : m_callbacks) {
        WKRetainPtr arguments = adoptWK(WKMutableDictionaryCreate());
        setValue(arguments, "callback", callback);
        WKRetainPtr frame = adoptWK(WKJSHandleCopyFrameInfo(callback.get()));
        WKPageCallAsyncJavaScriptWithoutUserGesture(WKFrameInfoGetPage(frame.get()), toWK("return callback()").get(), arguments.get(), frame.get(), nullptr, nullptr);
    }
}

void TestController::closeOtherPage(WKPageRef page, PlatformWebView* view)
{
    WKPageClose(page);
    auto index = m_auxiliaryWebViews.findIf([view](auto& auxiliaryWebView) { return auxiliaryWebView.ptr() == view; });
    if (index != notFound)
        m_auxiliaryWebViews.removeAt(index);
}

PlatformWebView* TestController::viewForPage(WKPageRef page)
{
    if (mainWebView() && mainWebView()->page() == page)
        return mainWebView();
    for (auto& auxiliaryWebView : m_auxiliaryWebViews) {
        if (auxiliaryWebView->page() == page)
            return auxiliaryWebView.ptr();
    }
    return mainWebView();
}

void TestController::setTargetViewFromMessage(WKScriptMessageRef message)
{
    auto* frameInfo = WKScriptMessageGetFrameInfo(message);
    auto* sourcePage = frameInfo ? WKFrameInfoGetPage(frameInfo) : nullptr;
    setTargetView(sourcePage ? viewForPage(sourcePage) : mainWebView());
}

WKPageRef TestController::createOtherPage(WKPageRef, WKPageConfigurationRef configuration, WKNavigationActionRef navigationAction, WKWindowFeaturesRef windowFeatures, const void *clientInfo)
{
    PlatformWebView* parentView = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
    return TestController::singleton().createOtherPage(parentView, configuration, navigationAction, windowFeatures);
}

WKPageRef TestController::createOtherPage(PlatformWebView* parentView, WKPageConfigurationRef configuration, WKNavigationActionRef navigationAction, WKWindowFeaturesRef windowFeatures)
{
    auto* platformWebView = createOtherPlatformWebView(parentView, configuration, navigationAction, windowFeatures);
    if (!platformWebView)
        return nullptr;
    auto preferences = WKPageConfigurationGetPreferences(configuration);
    if (WKPreferencesGetVerifyUserGestureInUIProcessEnabled(preferences) && !WKNavigationActionHasUnconsumedUserGesture(navigationAction))
        return nullptr;

    auto* page = platformWebView->page();
    WKRetain(page);
    return page;
}

void TestController::willEnterFullScreen(WKPageRef page, WKCompletionListenerRef listener, const void* clientInfo)
{
    return static_cast<TestController*>(const_cast<void*>(clientInfo))->willEnterFullScreen(page, listener);
}

void TestController::willEnterFullScreen(WKPageRef page, WKCompletionListenerRef listener)
{
    if (m_dumpFullScreenCallbacks)
        protectedCurrentInvocation()->outputText("supportsFullScreen() == true\nenterFullScreenForElement()\n"_s);
    if (!m_scrollDuringEnterFullscreen)
        return WKCompletionListenerComplete(listener, nullptr);

    // The amount we scroll isn't important, but it should be nonzero to verify it is gone after restoring scroll position.
    WKPageEvaluateJavaScriptInMainFrame(page, toWK("scrollBy(5,7)").get(), (void*)WKRetain(listener), [] (WKTypeRef, WKErrorRef, void* context) {
        auto listener = (WKCompletionListenerRef)context;
        WKCompletionListenerComplete(listener, nullptr);
        WKRelease(listener);
    });
}

void TestController::beganEnterFullScreen(WKPageRef page, WKRect initialFrame, WKRect finalFrame, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->beganEnterFullScreen(page, initialFrame, finalFrame);
}

void TestController::beganEnterFullScreen(WKPageRef page, WKRect initialFrame, WKRect finalFrame)
{
    if (m_dumpFullScreenCallbacks) {
        protectedCurrentInvocation()->outputText(makeString(
            "beganEnterFullScreen() - initialRect.size: {"_s,
            initialFrame.size.width,
            ", "_s,
            initialFrame.size.height,
            "}, finalRect.size: {"_s,
            finalFrame.size.width,
            ", "_s,
            finalFrame.size.height,
            "}\n"_s
        ));
    }

    if (m_dumpFullScreenOrigin) {
        protectedCurrentInvocation()->outputText(makeString(
            "beganEnterFullScreen() - initialRect.origin: {"_s,
            (initialFrame.origin.x - finalFrame.origin.x),
            ", "_s,
            (initialFrame.origin.y - finalFrame.origin.y),
            "}, finalRect.origin: {"_s,
            (finalFrame.origin.x - initialFrame.origin.x),
            ", "_s,
            (finalFrame.origin.y - initialFrame.origin.y),
            "}\n"_s
        ));
    }
}

void TestController::exitFullScreen(WKPageRef page, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->exitFullScreen(page);
}

void TestController::exitFullScreen(WKPageRef page)
{
    if (m_dumpFullScreenCallbacks)
        protectedCurrentInvocation()->outputText("exitFullScreenForElement()\n"_s);
}

void TestController::beganExitFullScreen(WKPageRef page, WKRect initialFrame, WKRect finalFrame, WKCompletionListenerRef listener, const void* clientInfo)
{
    return static_cast<TestController*>(const_cast<void*>(clientInfo))->beganExitFullScreen(page, initialFrame, finalFrame, listener);
}

void TestController::beganExitFullScreen(WKPageRef, WKRect initialFrame, WKRect finalFrame, WKCompletionListenerRef listener)
{
    if (m_dumpFullScreenCallbacks) {
        protectedCurrentInvocation()->outputText(makeString(
        "beganExitFullScreen() - initialRect.size: {"_s,
        initialFrame.size.width,
        ", "_s,
        initialFrame.size.height,
        "}, finalRect.size: {"_s,
        finalFrame.size.width,
        ", "_s,
        finalFrame.size.height,
        "}\n"_s
        ));
    }

    if (m_dumpFullScreenOrigin) {
        protectedCurrentInvocation()->outputText(makeString(
        "beganExitFullScreen() - initialRect.origin: {"_s,
        (initialFrame.origin.x - finalFrame.origin.x),
        ", "_s,
        (initialFrame.origin.y - finalFrame.origin.y),
        "}, finalRect.origin: {"_s,
        (finalFrame.origin.x - initialFrame.origin.x),
        ", "_s,
        (finalFrame.origin.y - initialFrame.origin.y),
        "}\n"_s
        ));
    }

    m_finishExitFullscreenHandler = [listener = WKRetainPtr { listener }] {
        WKCompletionListenerComplete(listener.get(), nullptr);
    };
    if (!m_waitBeforeFinishingFullscreenExit)
        finishFullscreenExit();
}

void TestController::finishFullscreenExit()
{
    m_finishExitFullscreenHandler();
}

void TestController::requestExitFullscreenFromUIProcess()
{
    WKPageRequestExitFullScreen(mainWebView()->page());
}

PlatformWebView* TestController::createOtherPlatformWebView(PlatformWebView* parentView, WKPageConfigurationRef configuration, WKNavigationActionRef, WKWindowFeaturesRef)
{
    RefPtr currentInvocation = m_currentInvocation;
    currentInvocation->willCreateNewPage();

    // The test called testRunner.preventPopupWindows() to prevent opening new windows.
    if (!currentInvocation->canOpenWindows())
        return nullptr;

    m_createdOtherPage = true;

    auto options = parentView ? parentView->options() : m_mainWebView->options();
    auto view = platformCreateOtherPage(parentView, configuration, options);
    WKPageRef newPage = view->page();

    view->resizeTo(800, 600);

    WKPageUIClientV19 otherPageUIClient = {
        { 19, view.ptr() },
        nullptr, // createNewPage_deprecatedForUseWithV0
        nullptr, // showPage
        closeOtherPage,
        nullptr, // takeFocus
        focus,
        unfocus,
        nullptr, // runJavaScriptAlert_deprecatedForUseWithV0
        nullptr, // runJavaScriptAlert_deprecatedForUseWithV0
        nullptr, // runJavaScriptAlert_deprecatedForUseWithV0
        nullptr, // setStatusText
        nullptr, // mouseDidMoveOverElement_deprecatedForUseWithV0
        nullptr, // missingPluginButtonClicked
        nullptr, // didNotHandleKeyEvent
        nullptr, // didNotHandleWheelEvent
        nullptr, // toolbarsAreVisible
        nullptr, // setToolbarsAreVisible
        nullptr, // menuBarIsVisible
        nullptr, // setMenuBarIsVisible
        nullptr, // statusBarIsVisible
        nullptr, // setStatusBarIsVisible
        nullptr, // isResizable
        nullptr, // setIsResizable
        getWindowFrame,
        setWindowFrame,
        runBeforeUnloadConfirmPanel,
        nullptr, // didDraw
        nullptr, // pageDidScroll
#if PLATFORM(COCOA)
        nullptr, // exceededDatabaseQuota
#else
        exceededDatabaseQuota,
#endif
        runOpenPanel,
        decidePolicyForGeolocationPermissionRequest,
        nullptr, // headerHeight
        nullptr, // footerHeight
        nullptr, // drawHeader
        nullptr, // drawFooter
        printFrame,
        runModal,
        nullptr, // didCompleteRubberBandForMainFrame
        nullptr, // saveDataToFileInDownloadsFolder
        nullptr, // shouldInterruptJavaScript
        nullptr, // createNewPage_deprecatedForUseWithV1
        nullptr, // mouseDidMoveOverElement
        nullptr, // decidePolicyForNotificationPermissionRequest
        nullptr, // unavailablePluginButtonClicked_deprecatedForUseWithV1
        nullptr, // showColorPicker
        nullptr, // hideColorPicker
        nullptr, // unavailablePluginButtonClicked
        nullptr, // pinnedStateDidChange
        nullptr, // didBeginTrackingPotentialLongMousePress
        nullptr, // didRecognizeLongMousePress
        nullptr, // didCancelTrackingPotentialLongMousePress
        nullptr, // isPlayingAudioDidChange
        decidePolicyForUserMediaPermissionRequest,
        nullptr, // didClickAutofillButton
        nullptr, // runJavaScriptAlert_deprecatedForUseWithV5
        nullptr, // runJavaScriptConfirm_deprecatedForUseWithV5
        nullptr, // runJavaScriptPrompt_deprecatedForUseWithV5
        nullptr, // unused5
        createOtherPage,
        runJavaScriptAlert,
        runJavaScriptConfirm,
        runJavaScriptPrompt,
        nullptr, // checkUserMediaPermissionForOrigin,
        nullptr, // runBeforeUnloadConfirmPanel
        nullptr, // fullscreenMayReturnToInline
        requestPointerLock,
        nullptr, // didLosePointerLock
        nullptr, // handleAutoplayEvent
        nullptr, // hasVideoInPictureInPictureDidChange
        nullptr, // didExceedBackgroundResourceLimitWhileInForeground
        nullptr, // didResignInputElementStrongPasswordAppearance
        nullptr, // requestStorageAccessConfirm
        nullptr, // shouldAllowDeviceOrientationAndMotionAccess
        nullptr, // runWebAuthenticationPanel
        nullptr, // decidePolicyForSpeechRecognitionPermissionRequest
        nullptr, // decidePolicyForMediaKeySystemPermissionRequest
        nullptr, // queryPermission
        nullptr, // lockScreenOrientationCallback,
        nullptr, // unlockScreenOrientationCallback,
        addMessageToConsole,
        tooltipDidChange
    };
    WKPageSetPageUIClient(newPage, &otherPageUIClient.base);

    WKPageFullScreenClientV0 fullscreenClient = {
        { 0, this },
        willEnterFullScreen,
        beganEnterFullScreen,
        exitFullScreen,
        beganExitFullScreen
    };
    WKPageSetFullScreenClientForTesting(newPage, &fullscreenClient.base);

    WKPageNavigationClientV3 pageNavigationClient = {
        { 3, &TestController::singleton() },
        decidePolicyForNavigationAction,
        decidePolicyForNavigationResponse,
        decidePolicyForPluginLoad,
        nullptr, // didStartProvisionalNavigation
        didReceiveServerRedirectForProvisionalNavigation,
        didFailProvisionalNavigation,
        nullptr, // didCommitNavigation
        nullptr, // didFinishNavigation
        nullptr, // didFailNavigation
        nullptr, // didFailProvisionalLoadInSubframe
        nullptr, // didFinishDocumentLoad
        nullptr, // didSameDocumentNavigation
        nullptr, // renderingProgressDidChange
        canAuthenticateAgainstProtectionSpace,
        didReceiveAuthenticationChallenge,
        nullptr, // webProcessDidCrash
        copyWebCryptoMasterKey,
        didBeginNavigationGesture,
        willEndNavigationGesture,
        didEndNavigationGesture,
        didRemoveNavigationGestureSnapshot,
        webProcessDidTerminate, // webProcessDidTerminate
        nullptr, // contentRuleListNotification
        nullptr, // copySignedPublicKeyAndChallengeString
        navigationActionDidBecomeDownload,
        navigationResponseDidBecomeDownload,
        nullptr // contextMenuDidCreateDownload
    };
    WKPageSetPageNavigationClient(newPage, &pageNavigationClient.base);

    WKPageInjectedBundleClientV2 injectedBundleClient = {
        { 2, this },
        didReceivePageMessageFromInjectedBundle,
        nullptr,
        nullptr,
        didReceiveSynchronousPageMessageFromInjectedBundleWithListenerFromMainFrameProcess,
    };
    WKPageSetPageInjectedBundleClient(newPage, &injectedBundleClient.base);

    view->didInitializeClients();

    TestController::singleton().updateWindowScaleForTest(view.ptr(), *TestController::singleton().protectedCurrentInvocation());

    PlatformWebView* viewToReturn = view.ptr();
    m_auxiliaryWebViews.append(WTF::move(view));
    return viewToReturn;
}

const char* TestController::libraryPathForTesting()
{
    // FIXME: This may not be sufficient to prevent interactions/crashes
    // when running more than one copy of DumpRenderTree.
    // See https://bugs.webkit.org/show_bug.cgi?id=10906
    char* dumpRenderTreeTemp = getenv("DUMPRENDERTREE_TEMP");
    if (dumpRenderTreeTemp)
        return dumpRenderTreeTemp;
    return platformLibraryPathForTesting();
}

void TestController::initialize(int argc, const char* argv[])
{
    AutodrainedPool pool;

    JSC::initialize();
    WTF::initializeMainThread();
    WTF::setProcessPrivileges(allPrivileges());
    WebCoreTestSupport::initializeNames();
    WebCoreTestSupport::populateJITOperations();

    Options options;
    OptionsHandler optionsHandler(options);

    if (argc < 2) {
        optionsHandler.printHelp();
        exitProcess(1);
    }
    if (!optionsHandler.parse(argc, argv))
        exitProcess(1);

    platformInitialize(options);

    m_useWaitToDumpWatchdogTimer = options.useWaitToDumpWatchdogTimer;
    m_forceNoTimeout = options.forceNoTimeout;
    m_verbose = options.verbose;
    m_gcBetweenTests = options.gcBetweenTests;
    m_shouldDumpPixelsForAllTests = options.shouldDumpPixelsForAllTests;
    m_forceComplexText = options.forceComplexText;
    m_paths = options.paths;
    m_allowedHosts = options.allowedHosts;
    m_localhostAliases = options.localhostAliases;
    m_checkForWorldLeaks = options.checkForWorldLeaks;
    m_allowAnyHTTPSCertificateForAllowedHosts = options.allowAnyHTTPSCertificateForAllowedHosts;
    m_enableAllExperimentalFeatures = options.enableAllExperimentalFeatures;
    m_globalFeatures = std::move(options.features);
    if (options.siteIsolationEnabledByDefault)
        m_globalFeatures.boolWebPreferenceFeatures.insert_or_assign("SiteIsolationEnabled", true);
#if ENABLE(WPE_PLATFORM)
    m_useWPELegacyAPI = options.useWPELegacyAPI;
#endif

    /* localhost is implicitly allowed and so should aliases to it. */
    for (const auto& alias : m_localhostAliases)
        m_allowedHosts.insert(alias);

    m_usingServerMode = (m_paths.size() == 1 && m_paths[0] == "-");
    if (m_usingServerMode)
        m_printSeparators = true;
    else
        m_printSeparators = m_paths.size() > 1;

    initializeInjectedBundlePath();
    initializeTestPluginDirectory();

#if ENABLE(GAMEPAD)
    WebCoreTestSupport::installMockGamepadProvider();
#endif

    m_eventSenderProxy = makeUnique<EventSenderProxy>(this);
}

WKRetainPtr<WKContextConfigurationRef> TestController::generateContextConfiguration(const TestOptions& options) const
{
    auto configuration = adoptWK(WKContextConfigurationCreate());
    WKContextConfigurationSetInjectedBundlePath(configuration.get(), injectedBundlePath());
    WKContextConfigurationSetFullySynchronousModeIsAllowedForTesting(configuration.get(), true);
    WKContextConfigurationSetIgnoreSynchronousMessagingTimeoutsForTesting(configuration.get(), options.ignoreSynchronousMessagingTimeouts());

    auto overrideLanguages = adoptWK(WKMutableArrayCreate());
    for (auto& language : options.overrideLanguages())
        WKArrayAppendItem(overrideLanguages.get(), toWK(language).get());
    WKContextConfigurationSetOverrideLanguages(configuration.get(), overrideLanguages.get());

    if (options.shouldEnableProcessSwapOnNavigation())
        WKContextConfigurationSetProcessSwapsOnNavigation(configuration.get(), true);

    WKContextConfigurationSetShouldConfigureJSCForTesting(configuration.get(), true);

#if PLATFORM(GTK) || PLATFORM(WPE)
    WKContextConfigurationSetDisableFontHintingForTesting(configuration.get(), true);
#endif

    return configuration;
}

void TestController::configureWebsiteDataStoreTemporaryDirectories(WKWebsiteDataStoreConfigurationRef configuration)
{
    if (const char* dumpRenderTreeTemp = libraryPathForTesting()) {
        String temporaryFolder = String::fromUTF8(dumpRenderTreeTemp);
        auto randomNumber = cryptographicallyRandomNumber<uint32_t>();

        WKWebsiteDataStoreConfigurationSetNetworkCacheDirectory(configuration, toWK(makeString(temporaryFolder, pathSeparator, "Cache"_s, pathSeparator, randomNumber)).get());
        WKWebsiteDataStoreConfigurationSetCacheStorageDirectory(configuration, toWK(makeString(temporaryFolder, pathSeparator, "CacheStorage"_s, pathSeparator, randomNumber)).get());
        WKWebsiteDataStoreConfigurationSetIndexedDBDatabaseDirectory(configuration, toWK(makeString(temporaryFolder, pathSeparator, "Databases"_s, pathSeparator, "IndexedDB"_s, pathSeparator, randomNumber)).get());
        WKWebsiteDataStoreConfigurationSetLocalStorageDirectory(configuration, toWK(makeString(temporaryFolder, pathSeparator, "LocalStorage"_s, pathSeparator, randomNumber)).get());
        WKWebsiteDataStoreConfigurationSetMediaKeysStorageDirectory(configuration, toWK(makeString(temporaryFolder, pathSeparator, "MediaKeys"_s, pathSeparator, randomNumber)).get());
        WKWebsiteDataStoreConfigurationSetResourceLoadStatisticsDirectory(configuration, toWK(makeString(temporaryFolder, pathSeparator, "ResourceLoadStatistics"_s, pathSeparator, randomNumber)).get());
        WKWebsiteDataStoreConfigurationSetServiceWorkerRegistrationDirectory(configuration, toWK(makeString(temporaryFolder, pathSeparator, "ServiceWorkers"_s, pathSeparator, randomNumber)).get());
        WKWebsiteDataStoreConfigurationSetIsolatedSitesDirectory(configuration, toWK(makeString(temporaryFolder, pathSeparator, "IsolatedSites"_s, pathSeparator, randomNumber)).get());
        WKWebsiteDataStoreConfigurationSetGeneralStorageDirectory(configuration, toWK(makeString(temporaryFolder, pathSeparator, "Default"_s, pathSeparator, randomNumber)).get());
        WKWebsiteDataStoreConfigurationSetResourceMonitorThrottlerDirectory(configuration, toWK(makeString(temporaryFolder, pathSeparator, "ResourceMonitorThrottler"_s, pathSeparator, randomNumber)).get());
#if PLATFORM(WIN)
        WKWebsiteDataStoreConfigurationSetCookieStorageFile(configuration, toWK(makeString(temporaryFolder, pathSeparator, "cookies"_s, pathSeparator, randomNumber, pathSeparator, "cookiejar.db"_s)).get());
#endif
        WKWebsiteDataStoreConfigurationSetPerOriginStorageQuota(configuration, 400 * 1024);
        WKWebsiteDataStoreConfigurationSetOriginQuotaRatio(configuration, 0.6);
        WKWebsiteDataStoreConfigurationSetNetworkCacheSpeculativeValidationEnabled(configuration, true);
        WKWebsiteDataStoreConfigurationSetStaleWhileRevalidateEnabled(configuration, true);
        WKWebsiteDataStoreConfigurationSetTestingSessionEnabled(configuration, true);
        WKWebsiteDataStoreConfigurationSetPCMMachServiceName(configuration, nullptr);
    }
}

WKWebsiteDataStoreRef TestController::defaultWebsiteDataStore()
{
    static WKWebsiteDataStoreRef dataStore = nullptr;
    if (!dataStore) {
        auto configuration = adoptWK(WKWebsiteDataStoreConfigurationCreate());
        configureWebsiteDataStoreTemporaryDirectories(configuration.get());

        // Including any non-trivial value of "persistent notifications have a minimum timeout before being closeable"
        // is counterproductive for layout tests - especially WPT tests. We cover the behavior in API tests.
        // So let's just set it to a tiny value for no behavior change in layout tests.
        WKWebsiteDataStoreConfigurationSetOverridePersistentNotificationMinimumLifetimeForTesting(configuration.get(), std::numeric_limits<float>::min());
        dataStore = WKWebsiteDataStoreCreateWithConfiguration(configuration.get());
    }
    return dataStore;
}

WKWebsiteDataStoreRef TestController::websiteDataStore()
{
    return m_websiteDataStore.get();
}

WKRetainPtr<WKPageConfigurationRef> TestController::generatePageConfiguration(const TestOptions& options)
{
    if (!m_context || !m_mainWebView || !m_mainWebView->viewSupportsOptions(options)) {
        auto contextConfiguration = generateContextConfiguration(options);
        if (options.siteIsolationEnabled())
            WKContextConfigurationSetPrewarmsProcessesAutomatically(contextConfiguration.get(), false);
        m_preferences = adoptWK(WKPreferencesCreate());
        m_context = adoptWK(WKContextCreateWithConfiguration(contextConfiguration.get()));

        auto localhostAliases = adoptWK(WKMutableArrayCreate());
        for (const auto& alias : m_localhostAliases)
            WKArrayAppendItem(localhostAliases.get(), toWK(alias.c_str()).get());
        WKContextSetLocalhostAliases(m_context.get(), localhostAliases.get());

        m_geolocationProvider = makeUnique<GeolocationProviderMock>(m_context.get());

        if (const char* dumpRenderTreeTemp = libraryPathForTesting()) {
            String temporaryFolder = String::fromUTF8(dumpRenderTreeTemp);

            // FIXME: This should be migrated to WKContextConfigurationRef.
            // Disable icon database to avoid fetching <http://127.0.0.1:8000/favicon.ico> and making tests flaky.
            // Invividual tests can enable it using testRunner.setIconDatabaseEnabled, although it's not currently supported in WebKitTestRunner.
            WKContextSetIconDatabasePath(m_context.get(), toWK(emptyString()).get());
        }

        WKContextSetCacheModel(m_context.get(), kWKCacheModelDocumentBrowser);
        WKContextSetDisableFontSubpixelAntialiasingForTesting(TestController::singleton().context(), true);

        platformInitializeContext();
    }

    WKContextInjectedBundleClientV2 injectedBundleClient = {
        { 2, this },
        didReceiveMessageFromInjectedBundle,
        nullptr,
        getInjectedBundleInitializationUserData,
        didReceiveSynchronousMessageFromInjectedBundleWithListener,
    };
    WKContextSetInjectedBundleClient(m_context.get(), &injectedBundleClient.base);

    WKContextClientV4 contextClient = {
        { 4, this },
        0, // plugInAutoStartOriginHashesChanged
        0, // networkProcessDidCrash,
        0, // plugInInformationBecameAvailable
        0, // copyWebCryptoMasterKey
        0, // serviceWorkerProcessDidCrash,
        0, // gpuProcessDidCrash
        networkProcessDidCrashWithDetails,
        serviceWorkerProcessDidCrashWithDetails,
        gpuProcessDidCrashWithDetails,
    };
    WKContextSetClient(m_context.get(), &contextClient.base);

    WKContextHistoryClientV0 historyClient = {
        { 0, this },
        didNavigateWithNavigationData,
        didPerformClientRedirect,
        didPerformServerRedirect,
        didUpdateHistoryTitle,
        0, // populateVisitedLinks
    };
    WKContextSetHistoryClient(m_context.get(), &historyClient.base);

    WKNotificationManagerRef notificationManager = WKContextGetNotificationManager(m_context.get());
    WKNotificationProviderV0 notificationKit = m_webNotificationProvider.provider();
    WKNotificationManagerSetProvider(notificationManager, &notificationKit.base);
    WKNotificationManagerSetProvider(WKNotificationManagerGetSharedServiceWorkerNotificationManager(), &notificationKit.base);

    if (testPluginDirectory())
        WKContextSetAdditionalPluginsDirectory(m_context.get(), testPluginDirectory());

    if (m_forceComplexText)
        WKContextSetAlwaysUsesComplexTextCodePath(m_context.get(), true);

    if (options.usesBackForwardCache())
        WKPreferencesSetBoolValueForKeyForTesting(m_preferences.get(), true, toWK("UsesBackForwardCache").get());

    auto pageConfiguration = adoptWK(WKPageConfigurationCreate());
    WKPageConfigurationSetContext(pageConfiguration.get(), m_context.get());
    WKPageConfigurationSetPreferences(pageConfiguration.get(), m_preferences.get());
    
    if (options.useEphemeralSession()) {
        auto ephemeralDataStore = adoptWK(WKWebsiteDataStoreCreateNonPersistentDataStore());
        WKPageConfigurationSetWebsiteDataStore(pageConfiguration.get(), ephemeralDataStore.get());
    }

    if (options.allowTestOnlyIPC())
        WKPageConfigurationSetAllowTestOnlyIPC(pageConfiguration.get(), true);
    WKPageConfigurationSetShouldSendConsoleLogsToUIProcessForTesting(pageConfiguration.get(), true);

    m_userContentController = adoptWK(WKUserContentControllerCreate());
    WKPageConfigurationSetUserContentController(pageConfiguration.get(), userContentController());
    WKPageConfigurationSetPortsForUpgradingInsecureSchemeForTesting(pageConfiguration.get(), options.insecureUpgradePort(), options.secureUpgradePort());
    return pageConfiguration;
}

static String originUserVisibleName(WKSecurityOriginRef origin)
{
    if (!origin)
        return emptyString();

    auto host = toWTFString(adoptWK(WKSecurityOriginCopyHost(origin)));
    auto protocol = toWTFString(adoptWK(WKSecurityOriginCopyProtocol(origin)));

    if (host.isEmpty() || protocol.isEmpty())
        return emptyString();

    if (int port = WKSecurityOriginGetPort(origin))
        return makeString(protocol, "://"_s, host, ':', port);

    return makeString(protocol, "://"_s, host);
}

bool TestController::grantNotificationPermission(WKStringRef originString)
{
    auto origin = adoptWK(WKSecurityOriginCreateFromString(originString));
    auto previousPermissionState = m_webNotificationProvider.permissionState(origin.get());

    m_webNotificationProvider.setPermission(toWTFString(originString), true);

    WKNotificationManagerProviderDidUpdateNotificationPolicy(WKNotificationManagerGetSharedServiceWorkerNotificationManager(), origin.get(), true);
    WKNotificationManagerProviderDidUpdateNotificationPolicy(WKContextGetNotificationManager(m_context.get()), origin.get(), true);

    if (!previousPermissionState || !*previousPermissionState)
        WKPagePermissionChanged(toWK("notifications").get(), originString);

    return true;
}

bool TestController::denyNotificationPermission(WKStringRef originString)
{
    auto origin = adoptWK(WKSecurityOriginCreateFromString(originString));
    auto previousPermissionState = m_webNotificationProvider.permissionState(origin.get());

    m_webNotificationProvider.setPermission(toWTFString(originString), false);
    WKNotificationManagerProviderDidUpdateNotificationPolicy(WKNotificationManagerGetSharedServiceWorkerNotificationManager(), origin.get(), false);

    if (!previousPermissionState || *previousPermissionState)
        WKPagePermissionChanged(toWK("notifications").get(), originString);

    return true;
}

bool TestController::denyNotificationPermissionOnPrompt(WKStringRef originString)
{
    auto origin = adoptWK(WKSecurityOriginCreateFromString(originString));
    auto originName = originUserVisibleName(origin.get());
    m_notificationOriginsToDenyOnPrompt.add(originName);
    return true;
}

#if !PLATFORM(COCOA)
void TestController::updatePresentation(CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    completionHandler(nullptr);
}

WKRetainPtr<WKStringRef> TestController::getBackgroundFetchIdentifier()
{
    return { };
}

void TestController::abortBackgroundFetch(WKStringRef)
{
}

void TestController::pauseBackgroundFetch(WKStringRef)
{
}

void TestController::resumeBackgroundFetch(WKStringRef)
{
}

void TestController::simulateClickBackgroundFetch(WKStringRef)
{
}
#endif

void TestController::createWebViewWithOptions(const TestOptions& options)
{
    auto applicationBundleIdentifier = options.applicationBundleIdentifier();
#if PLATFORM(COCOA)
    if (!applicationBundleIdentifier.empty()) {
        // The bundle identifier can only be set once per test, and is cleared between tests.
        RELEASE_ASSERT(!m_hasSetApplicationBundleIdentifier);
        setApplicationBundleIdentifier(applicationBundleIdentifier);
        m_hasSetApplicationBundleIdentifier = true;
    }
#endif

    auto configuration = generatePageConfiguration(options);
    platformInitializeDataStore(configuration.get(), options);

    // Some preferences (notably mock scroll bars setting) currently cannot be re-applied to an existing view, so we need to set them now.
    // FIXME: Migrate these preferences to WKContextConfigurationRef.
    resetPreferencesToConsistentValues(options);

    WKHTTPCookieStoreDeleteAllCookies(WKWebsiteDataStoreGetHTTPCookieStore(websiteDataStore()), nullptr, nullptr);

    platformCreateWebView(configuration.get(), options);
    WKPageUIClientV19 pageUIClient = {
        { 19, m_mainWebView.get() },
        nullptr, // createNewPage_deprecatedForUseWithV0
        nullptr, // showPage
        nullptr, // close
        nullptr, // takeFocus
        focus,
        unfocus,
        nullptr, // runJavaScriptAlert_deprecatedForUseWithV0
        nullptr, // runJavaScriptAlert_deprecatedForUseWithV0
        nullptr, // runJavaScriptAlert_deprecatedForUseWithV0
        nullptr, // setStatusText
        nullptr, // mouseDidMoveOverElement_deprecatedForUseWithV0
        nullptr, // missingPluginButtonClicked
        nullptr, // didNotHandleKeyEvent
        nullptr, // didNotHandleWheelEvent
        nullptr, // toolbarsAreVisible
        nullptr, // setToolbarsAreVisible
        nullptr, // menuBarIsVisible
        nullptr, // setMenuBarIsVisible
        nullptr, // statusBarIsVisible
        nullptr, // setStatusBarIsVisible
        nullptr, // isResizable
        nullptr, // setIsResizable
        getWindowFrame,
        setWindowFrame,
        runBeforeUnloadConfirmPanel,
        nullptr, // didDraw
        nullptr, // pageDidScroll
#if PLATFORM(COCOA)
        nullptr, // exceededDatabaseQuota,
#else
        exceededDatabaseQuota,
#endif
        options.shouldHandleRunOpenPanel() ? runOpenPanel : nullptr,
        decidePolicyForGeolocationPermissionRequest,
        nullptr, // headerHeight
        nullptr, // footerHeight
        nullptr, // drawHeader
        nullptr, // drawFooter
        printFrame,
        runModal,
        nullptr, // didCompleteRubberBandForMainFrame
        nullptr, // saveDataToFileInDownloadsFolder
        nullptr, // shouldInterruptJavaScript
        nullptr, // createNewPage_deprecatedForUseWithV1
        nullptr, // mouseDidMoveOverElement
        decidePolicyForNotificationPermissionRequest, // decidePolicyForNotificationPermissionRequest
        nullptr, // unavailablePluginButtonClicked_deprecatedForUseWithV1
        nullptr, // showColorPicker
        nullptr, // hideColorPicker
        unavailablePluginButtonClicked,
        nullptr, // pinnedStateDidChange
        nullptr, // didBeginTrackingPotentialLongMousePress
        nullptr, // didRecognizeLongMousePress
        nullptr, // didCancelTrackingPotentialLongMousePress
        nullptr, // isPlayingAudioDidChange
        decidePolicyForUserMediaPermissionRequest,
        nullptr, // didClickAutofillButton
        nullptr, // runJavaScriptAlert_deprecatedForUseWithV5
        nullptr, // runJavaScriptConfirm_deprecatedForUseWithV5
        nullptr, // runJavaScriptPrompt_deprecatedForUseWithV5
        nullptr, // unused5
        createOtherPage,
        runJavaScriptAlert,
        runJavaScriptConfirm,
        runJavaScriptPrompt,
        nullptr, // checkUserMediaPermissionForOrigin,
        nullptr, // runBeforeUnloadConfirmPanel
        nullptr, // fullscreenMayReturnToInline
        requestPointerLock,
        nullptr, // didLosePointerLock
        nullptr, // handleAutoplayEvent
        nullptr, // hasVideoInPictureInPictureDidChange
        nullptr, // didExceedBackgroundResourceLimitWhileInForeground
        nullptr, // didResignInputElementStrongPasswordAppearance
        nullptr, // requestStorageAccessConfirm
        shouldAllowDeviceOrientationAndMotionAccess,
        runWebAuthenticationPanel,
        nullptr, // decidePolicyForSpeechRecognitionPermissionRequest
        decidePolicyForMediaKeySystemPermissionRequest,
        queryPermission,
#if PLATFORM(IOS) || PLATFORM(VISION)
        lockScreenOrientationCallback,
        unlockScreenOrientationCallback,
#else
        nullptr, // lockScreenOrientation
        nullptr, // unlockScreenOrientation
#endif
        addMessageToConsole,
        tooltipDidChange
    };
    WKPageSetPageUIClient(m_mainWebView->page(), &pageUIClient.base);

    WKPageFullScreenClientV0 fullscreenClient = {
        { 0, this },
        willEnterFullScreen,
        beganEnterFullScreen,
        exitFullScreen,
        beganExitFullScreen
    };
    WKPageSetFullScreenClientForTesting(m_mainWebView->page(), &fullscreenClient.base);

    WKPageNavigationClientV3 pageNavigationClient = {
        { 3, this },
        decidePolicyForNavigationAction,
        decidePolicyForNavigationResponse,
        decidePolicyForPluginLoad,
        nullptr, // didStartProvisionalNavigation
        didReceiveServerRedirectForProvisionalNavigation,
        didFailProvisionalNavigation,
        didCommitNavigation,
        didFinishNavigation,
        nullptr, // didFailNavigation
        nullptr, // didFailProvisionalLoadInSubframe
        nullptr, // didFinishDocumentLoad
        nullptr, // didSameDocumentNavigation
        nullptr, // renderingProgressDidChange
        canAuthenticateAgainstProtectionSpace,
        didReceiveAuthenticationChallenge,
        nullptr,
        copyWebCryptoMasterKey,
        didBeginNavigationGesture,
        willEndNavigationGesture,
        didEndNavigationGesture,
        didRemoveNavigationGestureSnapshot,
        webProcessDidTerminate, // webProcessDidTerminate
        nullptr, // contentRuleListNotification
        nullptr, // copySignedPublicKeyAndChallengeString
        navigationActionDidBecomeDownload,
        navigationResponseDidBecomeDownload,
        nullptr // contextMenuDidCreateDownload
    };
    WKPageSetPageNavigationClient(m_mainWebView->page(), &pageNavigationClient.base);
    
    // this should just be done on the page?
    WKPageInjectedBundleClientV2 injectedBundleClient = {
        { 2, this },
        didReceivePageMessageFromInjectedBundle,
        nullptr,
        nullptr,
        didReceiveSynchronousPageMessageFromInjectedBundleWithListenerFromMainFrameProcess,
    };
    WKPageSetPageInjectedBundleClient(m_mainWebView->page(), &injectedBundleClient.base);

    m_mainWebView->didInitializeClients();

    // Generally, the tests should default to running at 1x. updateWindowScaleForTest() will adjust the scale to
    // something else for specific tests that need to run at a different window scale.
    m_mainWebView->changeWindowScaleIfNeeded(1);
    
    if (!applicationBundleIdentifier.empty()) {
        reinitializeAppBoundDomains();
        updateBundleIdentifierInNetworkProcess(applicationBundleIdentifier);
    }
}

void TestController::ensureViewSupportsOptionsForTest(const TestInvocation& test)
{
    auto options = test.options();

    if (m_mainWebView) {
        // Having created another page (via window.open()) prevents process swapping on navigation and it may therefore
        // cause flakiness to reuse the view. We should also always make a new view if the test is marked as app-bound, because
        // the view configuration must change.
        if (!m_createdOtherPage && m_mainWebView->viewSupportsOptions(options) && !options.isAppBoundWebView())
            return;

        willDestroyWebView();

        WKPageSetPageUIClient(m_mainWebView->page(), nullptr);
        WKPageSetFullScreenClientForTesting(m_mainWebView->page(), nullptr);
        WKPageSetPageNavigationClient(m_mainWebView->page(), nullptr);
        WKPageClose(m_mainWebView->page());

        m_mainWebView = nullptr;
        m_createdOtherPage = false;
    }

    platformEnsureGPUProcessConfiguredForOptions(options);
    createWebViewWithOptions(options);

    if (!resetStateToConsistentValues(options, ResetStage::BeforeTest))
        TestInvocation::dumpWebProcessUnresponsiveness("<unknown> - TestController::run - Failed to reset state to consistent values\n");
}

template<typename F> static void batchUpdatePreferences(WKPreferencesRef preferences, F&& functor)
{
    WKPreferencesStartBatchingUpdates(preferences);
    functor(preferences);
    WKPreferencesEndBatchingUpdates(preferences);
}

void TestController::resetPreferencesToConsistentValues(const TestOptions& options)
{
    batchUpdatePreferences(platformPreferences(), [options, enableAllExperimentalFeatures = m_enableAllExperimentalFeatures] (auto preferences) {
        WKPreferencesResetTestRunnerOverrides(preferences);

        if (enableAllExperimentalFeatures) {
            WKPreferencesEnableAllExperimentalFeatures(preferences);
            WKPreferencesSetExperimentalFeatureForKey(preferences, false, toWK("SiteIsolationEnabled").get());
            WKPreferencesSetExperimentalFeatureForKey(preferences, false, toWK("VerifyWindowOpenUserGestureFromUIProcess").get());
            WKPreferencesSetExperimentalFeatureForKey(preferences, true, toWK("WebGPUEnabled").get());
            WKPreferencesSetExperimentalFeatureForKey(preferences, true, toWK("ModelElementEnabled").get());
            WKPreferencesSetExperimentalFeatureForKey(preferences, false, toWK("HTTPSByDefaultEnabled").get());
            WKPreferencesSetExperimentalFeatureForKey(preferences, false, toWK("WebRTCL4SEnabled").get()); // FIXME: Remove this once L4S SDP negotation is supported.
        }

        WKPreferencesResetAllInternalDebugFeatures(preferences);

        WKPreferencesSetProcessSwapOnNavigationEnabled(preferences, options.shouldEnableProcessSwapOnNavigation());
        WKPreferencesSetStorageBlockingPolicy(preferences, options.blockThirdPartyStorage() ? kWKBlockThirdPartyStorage : kWKAllowAllStorage); // FIXME: We should be testing the default.
        WKPreferencesSetMinimumFontSize(preferences, 0);
        WKPreferencesSetAllowsPictureInPictureMediaPlayback(preferences, true);

        WKPreferencesSetBoolValueForKeyForTesting(preferences, options.allowTestOnlyIPC(), toWK("AllowTestOnlyIPC").get());
        WKPreferencesSetBoolValueForKeyForTesting(preferences, options.allowTestOnlyMockContentFilterIPC(), toWK("AllowTestOnlyMockContentFilterIPC").get());
        WKPreferencesSetBoolValueForKeyForTesting(preferences, options.allowTestOnlyOriginAccessAllowListIPC(), toWK("AllowTestOnlyOriginAccessAllowListIPC").get());

        for (const auto& [key, value] : options.boolWebPreferenceFeatures())
            WKPreferencesSetBoolValueForKeyForTesting(preferences, value, toWK(key).get());

        for (const auto& [key, value] : options.doubleWebPreferenceFeatures())
            WKPreferencesSetDoubleValueForKeyForTesting(preferences, value, toWK(key).get());

        for (const auto& [key, value] : options.uint32WebPreferenceFeatures())
            WKPreferencesSetUInt32ValueForKeyForTesting(preferences, value, toWK(key).get());

        for (const auto& [key, value] : options.stringWebPreferenceFeatures())
            WKPreferencesSetStringValueForKeyForTesting(preferences, toWK(value).get(), toWK(key).get());
    });
}

bool TestController::resetStateToConsistentValues(const TestOptions& options, ResetStage resetStage)
{
    SetForScope changeState(m_state, Resetting);
    m_beforeUnloadReturnValue = true;

    m_globalPrivacyControlEnabled = std::nullopt;

    for (auto& auxiliaryWebView : std::exchange(m_auxiliaryWebViews, { }))
        WKPageClose(auxiliaryWebView->page());

    WKPageSetCustomUserAgent(m_mainWebView->page(), nullptr);

    auto resetMessageBody = adoptWK(WKMutableDictionaryCreate());

    if (resetStage == ResetStage::AfterTest)
        WKPageStopLoading(m_mainWebView->page());
    setValue(resetMessageBody, "ResetStage", resetStage == ResetStage::AfterTest ? "AfterTest" : "BeforeTest");

    setValue(resetMessageBody, "ShouldGC", m_gcBetweenTests);

    auto allowedHostsValue = adoptWK(WKMutableArrayCreate());
    for (auto& host : m_allowedHosts)
        WKArrayAppendItem(allowedHostsValue.get(), toWK(host.c_str()).get());
    setValue(resetMessageBody, "AllowedHosts", allowedHostsValue);

    auto jscOptions = options.jscOptions();
    if (!jscOptions.empty())
        setValue(resetMessageBody, "JSCOptions", jscOptions.c_str());

    WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), toWK("Reset").get(), resetMessageBody.get());

    WKContextSetCacheModel(TestController::singleton().context(), kWKCacheModelDocumentBrowser);

    WKWebsiteDataStoreResetServiceWorkerFetchTimeoutForTesting(websiteDataStore());
    WKWebsiteDataStoreClearCrossOriginPreflightResultCacheForTesting(websiteDataStore());

    WKWebsiteDataStoreSetResourceLoadStatisticsEnabled(websiteDataStore(), true);
    WKWebsiteDataStoreClearAllDeviceOrientationPermissions(websiteDataStore());

    WKHTTPCookieStoreDeleteAllCookies(WKWebsiteDataStoreGetHTTPCookieStore(websiteDataStore()), nullptr, nullptr);

    clearStorage();
    resetQuota();
    resetStoragePersistedState();

    WKContextClearCurrentModifierStateForTesting(TestController::singleton().context());
    WKContextResetAccessibilityModeForTesting(TestController::singleton().context());
    WKContextSetUseSeparateServiceWorkerProcess(TestController::singleton().context(), false);
    WKContextClearMockGamepadsForTesting(TestController::singleton().context());

    WKPageSetMockCameraOrientationForTesting(m_mainWebView->page(), 0, nullptr);
    resetMockMediaDevices();
    WKPageSetMediaCaptureReportingDelayForTesting(m_mainWebView->page(), 0);

    WKWebsiteDataStoreResetResourceMonitorThrottler(websiteDataStore(), nullptr, nullptr);

    WKURLRequestSetDefaultTimeoutInterval((60_s).value());

    // FIXME: This function should also ensure that there is only one page open.

    // Reset the EventSender for each test.
    m_eventSenderProxy = makeUnique<EventSenderProxy>(this);

    // FIXME: Is this needed? Nothing in TestController changes preferences during tests, and if there is
    // some other code doing this, it should probably be responsible for cleanup too.
    resetPreferencesToConsistentValues(options);

    // Make sure the view is in the window (a test can unparent it).
    m_mainWebView->addToWindow();

    // In the case that a test using the chrome input field failed, be sure to clean up for the next test.
    m_mainWebView->removeChromeInputField();
    m_mainWebView->focus();

    // Re-set to the default backing scale factor by setting the custom scale factor to 0.
    WKPageSetCustomBackingScaleFactor(m_mainWebView->page(), 0);

    WKPageClearWheelEventTestMonitor(m_mainWebView->page());

    // GStreamer uses fakesink to avoid sound output during testing and doing this creates trouble with volume events.
#if !USE(GSTREAMER)
    WKPageSetMediaVolume(m_mainWebView->page(), 0);
#endif

    WKPageClearUserMediaState(m_mainWebView->page());

    setTracksRepaints(false);

    // Reset notification permissions
    m_webNotificationProvider.reset();
    m_notificationOriginsToDenyOnPrompt.clear();
    WKPageClearNotificationPermissionState(m_mainWebView->page());

    // Reset Geolocation permissions.
    m_geolocationPermissionRequests.clear();
    m_isGeolocationPermissionSet = false;
    m_isGeolocationPermissionAllowed = false;
    m_geolocationPermissionQueryOrigins.clear();

    // Reset Screen Wake Lock permission.
    m_screenWakeLockPermission = std::nullopt;

    // Reset UserMedia permissions.
    m_userMediaPermissionRequests.clear();
    resetUserMediaPermission();

    // Reset Custom Policy Delegate.
    setCustomPolicyDelegate(false, false);
    m_skipPolicyDelegateNotifyDone = false;

    // Reset Content Extensions.
    resetContentExtensions();

    m_shouldDownloadUndisplayableMIMETypes = false;

    m_shouldAllowDeviceOrientationAndMotionAccess = false;

    m_workQueueManager.clearWorkQueue();

    m_rejectsProtectionSpaceAndContinueForAuthenticationChallenges = false;
    m_handlesAuthenticationChallenges = false;
    m_authenticationUsername = String();
    m_authenticationPassword = String();

    setBlockAllPlugins(false);
    setPluginSupportedMode({ });

    m_shouldLogDownloadSize = false;
    m_shouldLogDownloadExpectedSize = false;
    m_shouldLogDownloadCallbacks = false;
    m_shouldLogHistoryClientCallbacks = false;
    m_shouldLogCanAuthenticateAgainstProtectionSpace = false;

    setHidden(false);
    setAllowStorageQuotaIncrease(true);
    setQuota(40 * KB);
    setOriginQuotaRatioEnabled(true);

    if (!platformResetStateToConsistentValues(options))
        return false;

    m_shouldDecideNavigationPolicyAfterDelay = false;
    m_shouldDecideResponsePolicyAfterDelay = false;

    setNavigationGesturesEnabled(false);
    
    setIgnoresViewportScaleLimits(options.ignoresViewportScaleLimits());
    m_mainWebView->setEditable(options.editable());

    m_openPanelFileURLs = nullptr;
#if PLATFORM(IOS_FAMILY)
    m_openPanelFileURLsMediaIcon = nullptr;
#endif

    setAllowsAnySSLCertificate(true);
    setBackgroundFetchPermission(true);

    statisticsResetToConsistentState();
    clearLoadedSubresourceDomains();
    clearAppBoundSession();
    clearPrivateClickMeasurement();

    WKPageDispatchActivityStateUpdateForTesting(m_mainWebView->page());

    m_didReceiveServerRedirectForProvisionalNavigation = false;
    m_lastProvisionalNavigationFailureURL = nullptr;
    m_serverTrustEvaluationCallbackCallsCount = 0;
    m_shouldDismissJavaScriptAlertsAsynchronously = false;

    setIsSpeechRecognitionPermissionGranted(true);

    auto loadAboutBlank = [this] {
        m_doneResetting = false;
        WKPageLoadURL(m_mainWebView->page(), blankURL());
        runUntil(m_doneResetting, protectedCurrentInvocation()->shortTimeout());
        return m_doneResetting;
    };

    // Reset main page back to about:blank
    if (!loadAboutBlank()) {
        WTFLogAlways("Failed to load 'about:blank', terminating process and trying again.");
        WKPageTerminate(m_mainWebView->page());
        if (!loadAboutBlank()) {
            WTFLogAlways("Failed to load 'about:blank' again after termination.");
            return false;
        }
    }

    WKPageResetStateBetweenTests(m_mainWebView->page());

    {
        bool done { false };
        WKWebsiteDataStoreRemoveNetworkCache(websiteDataStore(), &done, [] (void* context) {
            *(bool*)context = true;
        });
        runUntil(done, noTimeout);
    }

    WKPageClearBackForwardListForTesting(m_mainWebView->page(), nullptr, [](void*) { });
    WKPageClearBackForwardCache(m_mainWebView->page());

    if (resetStage == ResetStage::AfterTest) {
        updateLiveDocumentsAfterTest();
#if PLATFORM(COCOA)
        clearApplicationBundleIdentifierTestingOverride();
        clearAppPrivacyReportTestingData();
#endif
        clearBundleIdentifierInNetworkProcess();
    }

    m_downloadTotalBytesWritten = { };
    m_downloadIndex = 0;
    m_shouldDownloadContentDispositionAttachments = true;
    m_dumpPolicyDelegateCallbacks = false;
    m_resourceResponseMIMETypesToDump = String();
    m_dumpFullScreenCallbacks = false;

    WKPageSetResourceLoadClient(m_mainWebView->page(), nullptr);
    m_dumpAllHTTPRedirectedResponseHeaders = false;
    m_hasResourceLoadClient = false;
    m_dumpResourceLoadCallbacks = false;

    m_dumpFullScreenOrigin = false;
    m_waitBeforeFinishingFullscreenExit = false;
    m_scrollDuringEnterFullscreen = false;
    if (m_finishExitFullscreenHandler)
        m_finishExitFullscreenHandler();

    m_tooltipCallbacks.clear();
    m_cursorCallbacks.clear();
    if (m_mainWebView && m_mainWebView->options().shouldShowCursor())
        WKPageSetCursorDidChangeCallbackForTesting(mainWebView()->page(), cursorDidChangeForTesting, nullptr);
    else
        WKPageSetCursorDidChangeCallbackForTesting(mainWebView()->page(), nullptr, nullptr);
    m_beginSwipeCallbacks.clear();
    m_willEndSwipeCallbacks.clear();
    m_didEndSwipeCallbacks.clear();
    m_didRemoveSwipeSnapshotCallbacks.clear();
    m_uiScriptCallbacks.clear();

    return m_doneResetting;
}

#if !PLATFORM(COCOA)
uint64_t TestController::responseHeaderCount(WKURLResponseRef)
{
    return 0;
}
#endif

static inline bool isLocalFileScheme(WKStringRef scheme)
{
    return WKStringIsEqualToUTF8CStringIgnoringCase(scheme, "file");
}

static WTF::String pathSuitableForTestResult(WKURLRef fileURL, WKPageRef page)
{
    if (!fileURL)
        return "(null)"_s;

    auto schemeString = adoptWK(WKURLCopyScheme(fileURL));
    if (!isLocalFileScheme(schemeString.get()))
        return toWTFString(adoptWK(WKURLCopyString(fileURL)));

    WKFrameRef mainFrame = WKPageGetMainFrame(page);
    auto mainFrameURL = adoptWK(WKFrameCopyURL(mainFrame));
    if (!mainFrameURL)
        mainFrameURL = adoptWK(WKFrameCopyProvisionalURL(mainFrame));

    String pathString = toWTFString(adoptWK(WKURLCopyPath(fileURL)));
    String mainFrameURLPathString = mainFrameURL ? toWTFString(adoptWK(WKURLCopyPath(mainFrameURL.get()))) : ""_s;
    auto basePath = StringView(mainFrameURLPathString).left(mainFrameURLPathString.reverseFind('/') + 1);

    if (!basePath.isEmpty() && pathString.startsWith(basePath))
        return pathString.substring(basePath.length());
    return toWTFString(adoptWK(WKURLCopyLastPathComponent(fileURL))); // We lose some information here, but it's better than exposing a full path, which is always machine specific.
}

static String string(WKURLRequestRef request, WKPageRef page)
{
    auto url = adoptWK(WKURLRequestCopyURL(request));
    auto firstParty = adoptWK(WKURLRequestCopyFirstPartyForCookies(request));
    auto httpMethod = adoptWK(WKURLRequestCopyHTTPMethod(request));
    return makeString("<NSURLRequest URL "_s, pathSuitableForTestResult(url.get(), page),
        ", main document URL "_s, pathSuitableForTestResult(firstParty.get(), page),
        ", http method "_s, WKStringIsEmpty(httpMethod.get()) ? "(none)"_s : ""_s, toWTFString(httpMethod.get()), '>');
}

static String string(WKURLResponseRef response, WKPageRef page, bool shouldDumpResponseHeaders = false)
{
    auto url = adoptWK(WKURLResponseCopyURL(response));
    if (!url)
        return "(null)"_s;
    if (!shouldDumpResponseHeaders) {
        return makeString("<NSURLResponse "_s, pathSuitableForTestResult(url.get(), page),
            ", http status code "_s, WKURLResponseHTTPStatusCode(response), '>');
    }
    return makeString("<NSURLResponse "_s, pathSuitableForTestResult(url.get(), page),
        ", http status code "_s, WKURLResponseHTTPStatusCode(response),
        ", "_s, TestController::responseHeaderCount(response), " headers>"_s);
}

static inline void dumpErrorDescriptionSuitableForTestResult(WKErrorRef error, StringBuilder& stringBuilder)
{
    auto errorDomain = toWTFString(adoptWK(WKErrorCopyDomain(error)));
    auto errorCode = WKErrorGetErrorCode(error);

    // We need to do some error mapping here to match the test expectations (Mac error names are expected).
    if (errorDomain == "WebKitNetworkError"_s) {
        errorDomain = "NSURLErrorDomain"_s;
        errorCode = -999;
    }
    if (errorDomain == "WebKitPolicyError"_s)
        errorDomain = "WebKitErrorDomain"_s;

    stringBuilder.append("<NSError domain "_s, errorDomain, ", code "_s, errorCode);
    if (auto url = adoptWK(WKErrorCopyFailingURL(error)))
        stringBuilder.append(", failing URL \""_s, adoptWK(WKURLCopyString(url.get())).get(), '"');
    stringBuilder.append('>');
}

void TestController::dumpResourceResponseMIMETypes(String&& types)
{
    m_resourceResponseMIMETypesToDump = WTF::move(types);
    installResourceLoadClient();
}

void TestController::dumpResourceLoadCallbacks()
{
    m_dumpResourceLoadCallbacks = true;
    installResourceLoadClient();
}

void TestController::didSendRequest(WKPageRef page, WKURLRequestRef request)
{
    if (m_state != RunningTest)
        return;

    if (m_dumpResourceLoadCallbacks) {
        WKRetainPtr url = adoptWK(WKURLRequestCopyURL(request));
        StringBuilder stringBuilder;
        stringBuilder.append(pathSuitableForTestResult(url.get(), page));
        stringBuilder.append(" - willSendRequest "_s, string(request, page), " redirectResponse (null)\n"_s);
        currentInvocation()->outputResourceLoadCallback(stringBuilder.toString());
    }
}

#if !PLATFORM(COCOA)
String TestController::platformResponseMIMEType(WKURLResponseRef response)
{
    return { };
}
#endif

void TestController::didPerformRedirect(WKPageRef page, WKURLResponseRef response, WKURLRequestRef request)
{
    if (m_dumpResourceLoadCallbacks) {
        WKRetainPtr url = adoptWK(WKURLRequestCopyURL(request));
        StringBuilder stringBuilder;
        stringBuilder.append(pathSuitableForTestResult(url.get(), page));
        stringBuilder.append(" - willSendRequest "_s, string(request, page), " redirectResponse "_s, string(response, page, m_dumpAllHTTPRedirectedResponseHeaders), "\n"_s);
        currentInvocation()->outputResourceLoadCallback(stringBuilder.toString());
    }
}

void TestController::didReceiveResponse(WKPageRef page, WKURLRef originalURL, WKURLResponseRef response)
{
    if (m_dumpResourceLoadCallbacks) {
        StringBuilder stringBuilder;
        stringBuilder.append(pathSuitableForTestResult(originalURL, page));
        stringBuilder.append(" - didReceiveResponse "_s, string(response, page), '\n');
        currentInvocation()->outputResourceLoadCallback(stringBuilder.toString());
    }

    if (!m_resourceResponseMIMETypesToDump.isEmpty()) {
        WKRetainPtr url = adoptWK(WKURLResponseCopyURL(response));
        WKRetainPtr urlString = adoptWK(WKURLCopyLastPathComponent(url.get()));
        WKRetainPtr mimeTypeString = adoptWK(WKURLResponseCopyMIMEType(response));
        if (m_resourceResponseMIMETypesToDump == "*" || m_resourceResponseMIMETypesToDump.contains(toWTFString(urlString))) {
            StringBuilder stringBuilder;
            stringBuilder.append(urlString.get(), " has MIME type "_s, mimeTypeString.get());

            String platformMIMEType = platformResponseMIMEType(response);
            if (!platformMIMEType.isEmpty() && platformMIMEType != toWTFString(mimeTypeString))
                stringBuilder.append(" but platform response has "_s, platformMIMEType);

            stringBuilder.append('\n');
            currentInvocation()->outputResourceLoadCallback(stringBuilder.toString());
        }
    }
}

void TestController::didCompleteWithError(WKPageRef page, WKURLRef originalURL, WKURLResponseRef response, WKErrorRef error)
{
    if (m_dumpResourceLoadCallbacks) {
        StringBuilder stringBuilder;
        stringBuilder.append(pathSuitableForTestResult(originalURL, page));
        if (error) {
            stringBuilder.append(" - didFailLoadingWithError: "_s);
            dumpErrorDescriptionSuitableForTestResult(error, stringBuilder);
            stringBuilder.append('\n');
        } else
            stringBuilder.append(" - didFinishLoading\n"_s);
        currentInvocation()->outputResourceLoadCallback(stringBuilder.toString());
    }
}

void TestController::installResourceLoadClient()
{
    if (m_hasResourceLoadClient)
        return;

    WKPageResourceLoadClientV0 client {
        { 0, nullptr },
        [] (const void*, WKPageRef page, WKURLRequestRef request) {
            TestController::singleton().didSendRequest(page, request);
        }, [] (const void*, WKPageRef page, WKURLResponseRef response, WKURLRequestRef request) {
            TestController::singleton().didPerformRedirect(page, response, request);
        }, [] (const void*, WKPageRef page, WKURLRef originalURL, WKURLResponseRef response) {
            TestController::singleton().didReceiveResponse(page, originalURL, response);
        }, [] (const void*, WKPageRef page, WKURLRef originalURL, WKURLResponseRef response, WKErrorRef error) {
            TestController::singleton().didCompleteWithError(page, originalURL, response, error);
        }
    };

    WKPageSetResourceLoadClient(m_mainWebView->page(), &client.base);
    m_hasResourceLoadClient = true;
}

void TestController::updateLiveDocumentsAfterTest()
{
    if (!m_checkForWorldLeaks)
        return;

    AsyncTask([]() {
        // After each test, we update the list of live documents so that we can detect when an abandoned document first showed up.
    WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), toWK("GetLiveDocuments").get(), nullptr);
    }, 5_s).run();
}

void TestController::checkForWorldLeaks()
{
    if (!m_checkForWorldLeaks || !TestController::singleton().mainWebView())
        return;

    AsyncTask([]() {
        // This runs at the end of a series of tests. It clears caches, runs a GC and then fetches the list of documents.
        WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), toWK("CheckForWorldLeaks").get(), nullptr);
    }, 20_s).run();
}

void TestController::dumpResponse(const String& result)
{
    unsigned resultLength = result.length();
    printf("Content-Type: text/plain\n");
    printf("Content-Length: %u\n", resultLength);
    fwrite(result.utf8().data(), 1, resultLength, stdout);
    printf("#EOF\n");
    fprintf(stderr, "#EOF\n");
    fflush(stdout);
    fflush(stderr);
}

void TestController::findAndDumpWebKitProcessIdentifiers()
{
#if PLATFORM(COCOA)
    auto page = TestController::singleton().mainWebView()->page();
    dumpResponse(makeString(
        TestController::webProcessName(), ": "_s
        , WKPageGetProcessIdentifier(page), '\n'
        , TestController::networkProcessName(), ": "_s
        , WKWebsiteDataStoreGetNetworkProcessIdentifier(websiteDataStore()), '\n'
#if ENABLE(GPU_PROCESS)
        , TestController::gpuProcessName(), ": "_s
        , WKPageGetGPUProcessIdentifier(page), '\n'
#endif
    ));
#else
    dumpResponse("\n"_s);
#endif
}

void TestController::findAndDumpWorldLeaks()
{
    if (!m_checkForWorldLeaks)
        return;

    checkForWorldLeaks();

    StringBuilder builder;
    
    if (m_abandonedDocumentInfo.size()) {
        for (const auto& it : m_abandonedDocumentInfo) {
            auto documentURL = it.value.abandonedDocumentURL;
            if (documentURL.isEmpty())
                documentURL = "(no url)"_s;
            builder.append("TEST: "_s);
            builder.append(it.value.testURL);
            builder.append('\n');
            builder.append("ABANDONED DOCUMENT: "_s);
            builder.append(documentURL);
            builder.append('\n');
        }
    } else
        builder.append("no abandoned documents\n"_s);

    dumpResponse(builder.toString());
}

void TestController::willDestroyWebView()
{
    // Before we kill the web view, look for abandoned documents before that web process goes away.
    checkForWorldLeaks();
}

void TestController::terminateWebContentProcess()
{
    WKPageTerminate(m_mainWebView->page());
}

void TestController::reattachPageToWebProcess()
{
    // Loading a web page is the only way to reattach an existing page to a process.
    SetForScope changeState(m_state, Resetting);
    m_doneResetting = false;
    WKPageLoadURL(m_mainWebView->page(), blankURL());
    runUntil(m_doneResetting, noTimeout);
}

ASCIILiteral TestController::webProcessName()
{
    // FIXME: Find a way to not hardcode the process name.
#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR)
    return "com.apple.WebKit.WebContent"_s;
#elif PLATFORM(COCOA)
    return "com.apple.WebKit.WebContent.Development"_s;
#elif PLATFORM(GTK)
    return "WebKitWebProcess"_s;
#elif PLATFORM(WPE)
    return "WPEWebProcess"_s;
#else
    return "WebProcess"_s;
#endif
}

ASCIILiteral TestController::networkProcessName()
{
    // FIXME: Find a way to not hardcode the process name.
#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR)
    return "com.apple.WebKit.Networking"_s;
#elif PLATFORM(COCOA)
    return "com.apple.WebKit.Networking.Development"_s;
#elif PLATFORM(GTK)
    return "WebKitNetworkProcess"_s;
#elif PLATFORM(WPE)
    return "WPENetworkProcess"_s;
#else
    return "NetworkProcess"_s;
#endif
}

ASCIILiteral TestController::gpuProcessName()
{
    // FIXME: Find a way to not hardcode the process name.
#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR)
    return "com.apple.WebKit.GPU"_s;
#elif PLATFORM(COCOA)
    return "com.apple.WebKit.GPU.Development"_s;
#elif PLATFORM(GTK)
    return "WebKitGPUProcess"_s;
#elif PLATFORM(WPE)
    return "WPEGPUProcess"_s;
#else
    return "GPUProcess"_s;
#endif
}

ASCIILiteral TestController::serviceWorkerProcessName()
{
#if PLATFORM(GTK) || PLATFORM(WPE)
    return webProcessName();
#else
    return "ServiceWorkerProcess"_s;
#endif
}

void TestController::setVirtualWalletBehavior(WKStringRef action, WKStringRef protocol, WKStringRef responseJSON)
{
    if (auto* webView = mainWebView())
        WKPageSetVirtualWalletBehaviorForTesting(webView->page(), action, protocol, responseJSON);
}

#if !PLATFORM(COCOA)

void TestController::setAllowsAnySSLCertificate(bool allows)
{
    m_allowsAnySSLCertificate = allows;
}

void TestController::setBackgroundFetchPermission(bool)
{
    // FIXME: Add support.
}

WKRetainPtr<WKStringRef> TestController::lastAddedBackgroundFetchIdentifier() const
{
    return adoptWK(WKStringCreateWithUTF8CString("not implemented"));
}

WKRetainPtr<WKStringRef> TestController::lastRemovedBackgroundFetchIdentifier() const
{
    return adoptWK(WKStringCreateWithUTF8CString("not implemented"));
}

WKRetainPtr<WKStringRef> TestController::lastUpdatedBackgroundFetchIdentifier() const
{
    return adoptWK(WKStringCreateWithUTF8CString("not implemented"));
}

WKRetainPtr<WKStringRef> TestController::backgroundFetchState(WKStringRef)
{
    return { };
}
#endif

WKURLRef TestController::createTestURL(std::span<const char> pathOrURL)
{
    if (pathOrURL.empty())
        return nullptr;

    if (spanHasPrefix(pathOrURL, "http://"_span) || spanHasPrefix(pathOrURL, "https://"_span))
        return WKURLCreateWithUTF8String(pathOrURL.data(), pathOrURL.size());

    if (spanHasPrefix(pathOrURL, "file://"_span)) {
        auto url = adoptWK(WKURLCreateWithUTF8String(pathOrURL.data(), pathOrURL.size()));
        auto path = testPath(url.get());
        auto pathString = String::fromUTF8(std::span { path });
        if (!m_usingServerMode && !WTF::FileSystemImpl::fileExists(pathString)) {
            printf("Failed: File for URL ‘%s’ was not found or is inaccessible\n", pathString.utf8().data());
            return nullptr;
        }
        return url.leakRef();
    }

    // Creating from filesytem path.
    auto urlString = makeString("file://"_s, FileSystem::realPath(String::fromUTF8(pathOrURL))).utf8();
    auto url = adoptWK(WKURLCreateWithUTF8String(urlString.data(), urlString.length()));
    auto path = testPath(url.get());
    auto pathString = String::fromUTF8(std::span { path });
    if (!m_usingServerMode && !FileSystem::fileExists(pathString)) {
        printf("Failed: File ‘%s’ was not found or is inaccessible\n", pathString.utf8().data());
        return nullptr;
    }
    return url.leakRef();
}

TestOptions TestController::testOptionsForTest(const TestCommand& command) const
{
    TestFeatures features = TestOptions::defaults();
    merge(features, m_globalFeatures);
    merge(features, hardcodedFeaturesBasedOnPathForTest(command));
    merge(features, platformSpecificFeatureDefaultsForTest(command));
    merge(features, featureDefaultsFromSelfComparisonHeader(command, TestOptions::keyTypeMapping()));
    merge(features, featureDefaultsFromTestHeaderForTest(command, TestOptions::keyTypeMapping()));
    merge(features, featureFromAdditionalHeaderOption(command, TestOptions::keyTypeMapping()));
    merge(features, platformSpecificFeatureOverridesDefaultsForTest(command));
    return TestOptions { features };
}

void TestController::updateWebViewSizeForTest(const TestInvocation& test)
{
    mainWebView()->resizeTo(test.options().viewWidth(), test.options().viewHeight());
}

void TestController::updateWindowScaleForTest(PlatformWebView* view, const TestInvocation& test)
{
    view->changeWindowScaleIfNeeded(test.options().deviceScaleFactor());
}

void TestController::configureViewForTest(const TestInvocation& test)
{
    ensureViewSupportsOptionsForTest(test);
    updateWebViewSizeForTest(test);
    updateWindowScaleForTest(mainWebView(), test);
    configureContentExtensionForTest(test);
    platformConfigureViewForTest(test);
    installUserScript(test);
}

static WKFindOptions findOptionsFromArray(WKArrayRef array)
{
    auto length = WKArrayGetSize(array);
    WKFindOptions options { };
    for (unsigned i = 0; i < length; ++i) {
        WKStringRef optionName = dynamic_wk_cast<WKStringRef>(WKArrayGetItemAtIndex(array, i));
        if (WKStringIsEqualToUTF8CString(optionName, "CaseInsensitive"))
            options |= kWKFindOptionsCaseInsensitive;
        else if (WKStringIsEqualToUTF8CString(optionName, "AtWordStarts"))
            options |= kWKFindOptionsAtWordStarts;
        else if (WKStringIsEqualToUTF8CString(optionName, "TreatMedialCapitalAsWordStart"))
            options |= kWKFindOptionsTreatMedialCapitalAsWordStart;
        else if (WKStringIsEqualToUTF8CString(optionName, "Backwards"))
            options |= kWKFindOptionsBackwards;
        else if (WKStringIsEqualToUTF8CString(optionName, "WrapAround"))
            options |= kWKFindOptionsWrapAround;
        // FIXME: No kWKFindOptionsStartInSelection.
    }
    return options;
}

static void adoptAndCallCompletionHandler(void* context)
{
    auto completionHandler = WTF::adopt(static_cast<CompletionHandler<void(WKTypeRef)>::Impl*>(context));
    completionHandler(nullptr);
}

struct UIScriptInvocationData {
    UIScriptInvocationData(unsigned callbackID, WebKit::WKRetainPtr<WKStringRef>&& scriptString, WeakPtr<TestInvocation>&& testInvocation)
        : callbackID(callbackID)
        , scriptString(WTF::move(scriptString))
        , testInvocation(WTF::move(testInvocation)) { }

    unsigned callbackID;
    WebKit::WKRetainPtr<WKStringRef> scriptString;
    WeakPtr<TestInvocation> testInvocation;

    static unsigned nextCallbackID;
};

unsigned UIScriptInvocationData::nextCallbackID { 1 };

static void runUISideScriptImmediately(void* context)
{
    UIScriptInvocationData* data = static_cast<UIScriptInvocationData*>(context);
    if (TestInvocation* invocation = data->testInvocation.get()) {
        RELEASE_ASSERT(TestController::singleton().isCurrentInvocation(invocation));
        invocation->runUISideScript(data->scriptString.get(), data->callbackID);
    }
    delete data;
};

void TestController::uiScriptDidComplete(const String& result, unsigned scriptCallbackID)
{
    m_uiScriptCallbacks.get(scriptCallbackID).notifyListeners(toWK(result).get());
}

constexpr auto eventSenderJS = R"eventSenderJS(
if (window.eventSender) {
    let post = window.webkit.messageHandlers.webkitTestRunner.postMessage.bind(window.webkit.messageHandlers.webkitTestRunner);

    eventSender.asyncMouseDown = async (button, modifierArray, pointerType) => { // NOLINT
        await post(['AsyncMouseDown', button, modifierArray, pointerType]);
    };
    eventSender.asyncMouseUp = async (button, modifierArray, pointerType) => { // NOLINT
        await post(['AsyncMouseUp', button, modifierArray, pointerType]);
    };
    eventSender.asyncMouseMoveTo = async (x, y, pointerType) => { // NOLINT
        await post(['AsyncMouseMoveTo', x, y, pointerType]);
    };
    eventSender.asyncKeyDown = async (key, modifiers) => { // NOLINT
        await post(['AsyncKeyDown', key, modifiers]);
    };
    eventSender.asyncTouchStart = async () => { // NOLINT
        await post(['AsyncTouchStart']);
    };
    eventSender.asyncTouchMove = async () => { // NOLINT
        await post(['AsyncTouchMove']);
    };
    eventSender.asyncTouchEnd = async () => { // NOLINT
        await post(['AsyncTouchEnd']);
    };
    eventSender.asyncTouchCancel = async () => { // NOLINT
        await post(['AsyncTouchCancel']);
    };
}
)eventSenderJS";

constexpr auto testRunnerJS = R"testRunnerJS(
if (window.testRunner) {
    let post = window.webkit.messageHandlers.webkitTestRunner.postMessage.bind(window.webkit.messageHandlers.webkitTestRunner);
    let createHandle = (object) => object ? window.webkit.createJSHandle(object) : undefined;

    testRunner.installTooltipDidChangeCallback = callback => post(['InstallTooltipCallback', createHandle(callback)]);
    testRunner.installCursorDidChangeCallback = callback => post(['InstallCursorCallback', createHandle(callback)]);
    testRunner.installDidBeginSwipeCallback = callback => post(['InstallBeginSwipeCallback', createHandle(callback)]);
    testRunner.installWillEndSwipeCallback = callback => post(['InstallWillEndSwipeCallback', createHandle(callback)]);
    testRunner.installDidEndSwipeCallback = callback => post(['InstallDidEndSwipeCallback', createHandle(callback)]);
    testRunner.installDidRemoveSwipeSnapshotCallback = callback => post(['InstallDidRemoveSwipeSnapshotCallback', createHandle(callback)]);
    testRunner.findString = (target, options) => post(['FindString', target, options]);
    testRunner.runUIScript = (script, callback) => post(['RunUIScript', script, createHandle(callback)]);
    testRunner.runUIScriptImmediately = (script, callback) => post(['RunUIScriptImmediately', script, createHandle(callback)]);
    testRunner.getApplicationManifest = () => post(['GetApplicationManifest']);
    testRunner.scrollDuringEnterFullscreen = () => post(['ScrollDuringEnterFullscreen']);
    testRunner.waitBeforeFinishingFullscreenExit = () => post(['WaitBeforeFinishingFullscreenExit']);
    testRunner.finishFullscreenExit = () => post(['FinishFullscreenExit']);
    testRunner.requestExitFullscreenFromUIProcess = () => post(['RequestExitFullscreenFromUIProcess']);
    testRunner.keyExistsInKeychain = (attrLabel, applicationLabelBase64) => post(['KeyExistsInKeychain', attrLabel, applicationLabelBase64]);
    testRunner.indicateFindMatch = index => post(['IndicateFindMatch', index]);
    testRunner.setShouldLogDownloadCallbacks = value => post(['SetShouldLogDownloadCallbacks', value]);
    testRunner.setShouldLogDownloadSize = value => post(['SetShouldLogDownloadSize', value]);
    testRunner.setShouldLogDownloadExpectedSize = value => post(['SetShouldLogDownloadExpectedSize', value]);
    testRunner.setShouldDownloadContentDispositionAttachments = value => post(['SetShouldDownloadContentDispositionAttachments', value]);
    testRunner.setShouldDecideNavigationPolicyAfterDelay = value => post(['SetShouldDecideNavigationPolicyAfterDelay', value]);
    testRunner.setShouldDecideResponsePolicyAfterDelay = value => post(['SetShouldDecideResponsePolicyAfterDelay', value]);
    testRunner.setNavigationGesturesEnabled = value => post(['SetNavigationGesturesEnabled', value]);
    testRunner.setIgnoresViewportScaleLimits = value => post(['SetIgnoresViewportScaleLimits', value]);
    testRunner.setUseDarkAppearanceForTesting = value => post(['SetUseDarkAppearanceForTesting', value]);
    testRunner.setShouldDownloadUndisplayableMIMETypes = value => post(['SetShouldDownloadUndisplayableMIMETypes', value]);
    testRunner.setShouldAllowDeviceOrientationAndMotionAccess = value => post(['SetShouldAllowDeviceOrientationAndMotionAccess', value]);
    testRunner.dumpAllHTTPRedirectedResponseHeaders = () => post(['DumpAllHTTPRedirectedResponseHeaders']);
    testRunner.setRejectsProtectionSpaceAndContinueForAuthenticationChallenges = value => post(['SetRejectsProtectionSpaceAndContinueForAuthenticationChallenges', value]);
    testRunner.setHandlesAuthenticationChallenges = value => post(['SetHandlesAuthenticationChallenges', value]);
    testRunner.setShouldLogCanAuthenticateAgainstProtectionSpace = value => post(['SetShouldLogCanAuthenticateAgainstProtectionSpace', value]);
    testRunner.setBlockAllPlugins = value => post(['SetBlockAllPlugins', value]);
    testRunner.stopLoading = () => post(['StopLoading']);
    testRunner.dumpFullScreenCallbacks = () => post(['DumpFullScreenCallbacks']);
    testRunner.dumpFullScreenOrigin = () => post(['DumpFullScreenOrigin']);
    testRunner.displayAndTrackRepaints = () => post(['DisplayAndTrackRepaints']);
    testRunner.clearBackForwardList = () => post(['ClearBackForwardList']);
    testRunner.addChromeInputField = async (callback) => { await post(['AddChromeInputField']); callback?.(); }; // NOLINT
    testRunner.removeChromeInputField = async (callback) => { await post(['RemoveChromeInputField']); callback?.(); }; // NOLINT
    testRunner.setTextInChromeInputField = async (text, callback) => { await post(['SetTextInChromeInputField', text]); callback?.(); }; // NOLINT
    testRunner.selectChromeInputField = async (callback) => { await post(['SelectChromeInputField']); callback?.(); }; // NOLINT
    testRunner.getSelectedTextInChromeInputField = async (callback) => { const result = await post(['GetSelectedTextInChromeInputField']); callback?.(result); }; // NOLINT
    testRunner.focusWebView = async (callback) => { await post(['FocusWebView']); callback?.(); }; // NOLINT
    testRunner.setBackingScaleFactor = async (value, callback) => { await post(['SetBackingScaleFactor', value]); callback?.(); }; // NOLINT
    testRunner.removeAllCookies = async (callback) => { await post(['RemoveAllCookies']); callback?.(); }; // NOLINT
    testRunner.setStatisticsDebugMode = async (value, callback) => { // NOLINT
        await post(['SetStatisticsDebugMode', value]);
        callback?.();
    };
    testRunner.setStatisticsPrevalentResourceForDebugMode = async (hostName, callback) => { // NOLINT
        await post(['SetStatisticsPrevalentResourceForDebugMode', hostName]);
        callback?.();
    };
    testRunner.setStatisticsLastSeen = (hostName, seconds) => post(['SetStatisticsLastSeen', { HostName: hostName, Value: seconds }]);
    testRunner.setStatisticsMergeStatistic = async (hostName, topFrameDomain1, topFrameDomain2, lastSeen, hadUserInteraction, mostRecentUserInteraction, isGrandfathered, isPrevalent, isVeryPrevalent, dataRecordsRemoved, callback) => { // NOLINT
        await post(['SetStatisticsMergeStatistic', {
            HostName: hostName,
            TopFrameDomain1: topFrameDomain1,
            TopFrameDomain2: topFrameDomain2,
            LastSeen: lastSeen,
            HadUserInteraction: hadUserInteraction,
            MostRecentUserInteraction: mostRecentUserInteraction,
            IsGrandfathered: isGrandfathered,
            IsPrevalent: isPrevalent,
            IsVeryPrevalent: isVeryPrevalent,
            DataRecordsRemoved: dataRecordsRemoved
        }]);
        callback?.();
    };
    testRunner.setStatisticsExpiredStatistic = async (hostName, numberOfOperatingDaysPassed, hadUserInteraction, isScheduledForAllButCookieDataRemoval, isPrevalent, callback) => { // NOLINT
        await post(['SetStatisticsExpiredStatistic', {
            HostName: hostName,
            NumberOfOperatingDaysPassed: numberOfOperatingDaysPassed,
            HadUserInteraction: hadUserInteraction,
            IsScheduledForAllButCookieDataRemoval: isScheduledForAllButCookieDataRemoval,
            IsPrevalent: isPrevalent
        }]);
        callback?.();
    };
    testRunner.setStatisticsPrevalentResource = async (hostName, value, callback) => { // NOLINT
        await post(['SetStatisticsPrevalentResource', {
            HostName: hostName,
            Value: value
        }]);
        callback?.();
    };
    testRunner.setStatisticsVeryPrevalentResource = async (hostName, value, callback) => { // NOLINT
        await post(['SetStatisticsVeryPrevalentResource', {
            HostName: hostName,
            Value: value
        }]);
        callback?.();
    };
    testRunner.setStatisticsHasHadUserInteraction = async (hostName, value, callback) => { // NOLINT
        await post(['SetStatisticsHasHadUserInteraction', {
            HostName: hostName,
            Value: value
        }]);
        callback?.();
    };
    testRunner.statisticsProcessStatisticsAndDataRecords = async () => { // NOLINT
        await post(['StatisticsProcessStatisticsAndDataRecords']);
    };
    testRunner.statisticsUpdateCookieBlocking = async (callback) => { // NOLINT
        await post(['StatisticsUpdateCookieBlocking']);
        callback?.();
    };
    testRunner.statisticsClearInMemoryAndPersistentStoreModifiedSinceHours = async (hours, callback) => { // NOLINT
        await post(['StatisticsClearInMemoryAndPersistentStore', hours]);
        callback?.();
    };
    testRunner.statisticsClearInMemoryAndPersistentStore = async (callback) => { // NOLINT
        await post(['StatisticsClearInMemoryAndPersistentStore']);
        callback?.();
    };
    testRunner.statisticsClearThroughWebsiteDataRemoval = async (callback) => { // NOLINT
        await post(['StatisticsClearThroughWebsiteDataRemoval']);
        callback?.();
    };
    testRunner.statisticsDeleteCookiesForHost = async (hostName, includeHttpOnlyCookies, callback) => { // NOLINT
        await post(['StatisticsDeleteCookiesForHost', { HostName: hostName, IncludeHttpOnlyCookies: includeHttpOnlyCookies }]);
        callback?.();
    };
    testRunner.setStatisticsShouldDowngradeReferrer = async (value, callback) => { // NOLINT
        await post(['SetStatisticsShouldDowngradeReferrer', value]);
        callback?.();
    };
    testRunner.setStatisticsShouldBlockThirdPartyCookies = async (value, callback, onlyOnSitesWithoutUserInteraction, onlyUnpartitionedCookies) => { // NOLINT
        let message = 'SetStatisticsShouldBlockThirdPartyCookies';
        if (onlyOnSitesWithoutUserInteraction)
            message = 'SetStatisticsShouldBlockThirdPartyCookiesOnSitesWithoutUserInteraction';
        else if (onlyUnpartitionedCookies)
            message = 'SetStatisticsShouldBlockThirdPartyCookiesExceptPartitioned';
        await post([message, value]);
        callback?.();
    };
    testRunner.setStatisticsFirstPartyWebsiteDataRemovalMode = async (value, callback) => { // NOLINT
        await post(['SetStatisticsFirstPartyWebsiteDataRemovalMode', value]);
        callback?.();
    };
    testRunner.statisticsSetToSameSiteStrictCookies = async (hostName, callback) => { // NOLINT
        await post(['StatisticsSetToSameSiteStrictCookies', hostName]);
        callback?.();
    };
    testRunner.statisticsSetFirstPartyHostCNAMEDomain = async (firstPartURL, cnameURLString, callback) => { // NOLINT
        await post(['StatisticsSetFirstPartyHostCNAMEDomain', { FirstPartyURL: firstPartURL, CNAME: cnameURLString }]);
        callback?.();
    };
    testRunner.statisticsSetThirdPartyCNAMEDomain = async (cnameURLString, callback) => { // NOLINT
        await post(['StatisticsSetThirdPartyCNAMEDomain', cnameURLString]);
        callback?.();
    };
    testRunner.statisticsResetToConsistentState = async (callback) => { // NOLINT
        await post(['StatisticsResetToConsistentState']);
        callback?.();
    };
    testRunner.getAllStorageAccessEntries = async (callback) => { // NOLINT
        const entries = await post(['GetAllStorageAccessEntries']);
        callback?.(entries);
    };
    testRunner.setStorageAccessPermission = async (granted, subFrameURL, callback) => { // NOLINT
        await post(['SetStorageAccessPermission', { Value: granted, SubFrameURL: subFrameURL }]);
        callback?.();
    };
    testRunner.setStorageAccess = async (blocked, callback) => { // NOLINT
        await post(['SetStorageAccess', blocked]);
        callback?.();
    };
    testRunner.setStorageAccessAPIPerPageScopeEnabled = (enabled) => post(['SetStorageAccessAPIPerPageScopeEnabled', enabled]);
    testRunner.loadedSubresourceDomains = async (callback) => { // NOLINT
        const arrays = await post(['LoadedSubresourceDomains']);
        callback?.(arrays);
    };
    testRunner.removeAllSessionCredentials = async (callback) => { // NOLINT
        await post(['RemoveAllSessionCredentials']);
        callback?.();
    };
    testRunner.takeViewPortSnapshot = async (callback) => { // NOLINT
        const snapshot = await post(['TakeViewPortSnapshot']);
        callback?.(snapshot);
    };
    testRunner.flushConsoleLogs = () => post(['FlushConsoleLogs']);
    testRunner.updatePresentation = () => post(['UpdatePresentation']);
    testRunner.setPageScaleFactor = (scaleFactor, x, y) => post(['SetPageScaleFactor', { scaleFactor: scaleFactor, x: x, y: y }]);
    testRunner.setObscuredContentInsets = (top, right, bottom, left) => post(['SetObscuredContentInsets', [top, right, bottom, left]]);
    testRunner.setResourceMonitorList = (rulesText) => post(['SetResourceMonitorList', rulesText]);
    testRunner.findStringMatchesInPage = (target, options) => post(['FindStringMatches', { String: target, FindOptions: options }]);
    testRunner.setAuthenticationUsername = username => post(['SetAuthenticationUsername', username]);
    testRunner.setAuthenticationPassword = password => post(['SetAuthenticationPassword', password]);
    testRunner.setPluginSupportedMode = mode => post(['SetPluginSupportedMode', mode]);
    testRunner.setAllowedMenuActions = actions => post(['SetAllowedMenuActions', actions]);
    testRunner.setOpenPanelFiles = files => post(['SetOpenPanelFileURLs', files]);
    testRunner.setOpenPanelFilesMediaIcon = iconBytes => post(['SetOpenPanelFileURLsMediaIcon', iconBytes]);
    testRunner.setAppBoundDomains = async (domains, callback) => { // NOLINT
        await post(['SetAppBoundDomains', domains]);
        callback?.();
    }
    testRunner.setManagedDomains = async (domains, callback) => { // NOLINT
        await post(['SetManagedDomains', domains]);
        callback?.();
    }
}
)testRunnerJS";

static WKRetainPtr<WKArrayRef> WKURLArrayFromWKStringArray(const WKTypeRef array)
{
    const auto stringArray = arrayValue(array);
    auto urlArray = adoptWK(WKMutableArrayCreate());
    const auto length = WKArrayGetSize(stringArray);
    for (size_t i = 0; i < length; i++) {
        auto str = WKArrayGetItemAtIndex(stringArray, i);
        auto cstr = toWTFString(stringValue(str)).utf8();
        WKArrayAppendItem(urlArray.get(), adoptWK(WKURLCreateWithUTF8CString(cstr.data())).get());
    }

    return urlArray;
}

static WKEventModifiers parseModifier(WKStringRef modifier)
{
    if (WKStringIsEqualToUTF8CString(modifier, "ctrlKey"))
        return kWKEventModifiersControlKey;
    if (WKStringIsEqualToUTF8CString(modifier, "shiftKey") || WKStringIsEqualToUTF8CString(modifier, "rangeSelectionKey"))
        return kWKEventModifiersShiftKey;
    if (WKStringIsEqualToUTF8CString(modifier, "altKey"))
        return kWKEventModifiersAltKey;
    if (WKStringIsEqualToUTF8CString(modifier, "metaKey"))
        return kWKEventModifiersMetaKey;
    if (WKStringIsEqualToUTF8CString(modifier, "capsLockKey"))
        return kWKEventModifiersCapsLockKey;
    if (WKStringIsEqualToUTF8CString(modifier, "addSelectionKey")) {
#if OS(MACOS)
        return kWKEventModifiersMetaKey;
#else
        return kWKEventModifiersControlKey;
#endif
    }
    return 0;
}

static WKEventModifiers parseModifierArray(WKArrayRef array)
{
    if (!array)
        return 0;

    if (const auto str = dynamic_wk_cast<WKStringRef>(array))
        return parseModifier(str);

    WKEventModifiers modifiers = 0;
    const auto length = WKArrayGetSize(array);
    for (size_t i = 0; i < length; i++) {
        const auto modifierStr = WKArrayGetItemAtIndex(array, i);
        modifiers |= parseModifier(stringValue(modifierStr));
    }

    return modifiers;
}

void TestController::didReceiveScriptMessage(WKScriptMessageRef message, WKCompletionListenerRef listener, const void *)
{
    TestController::singleton().didReceiveScriptMessage(message, [listener = WKRetainPtr { listener }] (WKTypeRef result) {
        WKCompletionListenerComplete(listener.get(), result);
    });
}

static WKRetainPtr<WKURLRef> makeOpenPanelURL(WKURLRef baseURL, const String& filePath)
{
#if OS(WINDOWS)
    auto cFilePath = FileSystem::fileSystemRepresentation(filePath);
    if (!PathIsRelativeA(cFilePath.data())) {
        char fileURI[INTERNET_MAX_PATH_LENGTH];
        DWORD fileURILength = INTERNET_MAX_PATH_LENGTH;
        UrlCreateFromPathA(cFilePath.data(), fileURI, &fileURILength, 0);
        return adoptWK(WKURLCreateWithUTF8CString(fileURI));
    }
#else
    WKRetainPtr<WKURLRef> fileURL;
    if (!filePath.isEmpty() && filePath[0] == '/') {
        fileURL = adoptWK(WKURLCreateWithUTF8CString("file://"));
        baseURL = fileURL.get();
    }
#endif
    return adoptWK(WKURLCreateWithBaseURL(baseURL, filePath.utf8().data()));
}

void TestController::didReceiveScriptMessage(WKScriptMessageRef message, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    if (m_state != RunningTest)
        return completionHandler(nullptr);

    WKTypeRef messageBody = WKScriptMessageGetBody(message);
    WKArrayRef array = dynamic_wk_cast<WKArrayRef>(messageBody);
    WKStringRef command = (WKStringRef)WKArrayGetItemAtIndex(array, 0);
    WKTypeRef argument = WKArrayGetSize(array) > 1 ? WKArrayGetItemAtIndex(array, 1) : nullptr;
    WKTypeRef argument2 = WKArrayGetSize(array) > 2 ? WKArrayGetItemAtIndex(array, 2) : nullptr;
    WKTypeRef argument3 = WKArrayGetSize(array) > 3 ? WKArrayGetItemAtIndex(array, 3) : nullptr;

    if (WKStringIsEqualToUTF8CString(command, "FindString")) {
        WKStringRef target = dynamic_wk_cast<WKStringRef>(argument);
        WKArrayRef optionsArray = dynamic_wk_cast<WKArrayRef>(WKArrayGetItemAtIndex(array, 2));
        WKFindOptions options = findOptionsFromArray(optionsArray);
        return WKPageFindStringForTesting(mainWebView()->page(), completionHandler.leak(), target, options, 0, [] (bool found, void* context) {
            auto completionHandler = WTF::adopt(static_cast<CompletionHandler<void(WKTypeRef)>::Impl*>(context));
            completionHandler(adoptWK(WKBooleanCreate(found)).get());
        });
    }

    if (WKStringIsEqualToUTF8CString(command, "RemoveAllCookies"))
        return removeAllCookies(WTF::move(completionHandler));

    if (WKStringIsEqualToUTF8CString(command, "AddChromeInputField")) {
        mainWebView()->addChromeInputField();
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "RemoveChromeInputField")) {
        mainWebView()->removeChromeInputField();
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "SetTextInChromeInputField")) {
        mainWebView()->setTextInChromeInputField(toWTFString(stringValue(argument)));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "SelectChromeInputField")) {
        mainWebView()->selectChromeInputField();
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "GetSelectedTextInChromeInputField")) {
        auto selectedText = mainWebView()->getSelectedTextInChromeInputField();
        return completionHandler(toWK(selectedText).get());
    }

    if (WKStringIsEqualToUTF8CString(command, "FocusWebView")) {
        mainWebView()->makeWebViewFirstResponder();
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "SetBackingScaleFactor")) {
        WKPageSetCustomBackingScaleFactorWithCallback(TestController::singleton().mainWebView()->page(), doubleValue(argument), completionHandler.leak(), adoptAndCallCompletionHandler);
        return;
    }

    if (WKStringIsEqualToUTF8CString(command, "ClearBackForwardList"))
        return WKPageClearBackForwardListForTesting(TestController::singleton().mainWebView()->page(), completionHandler.leak(), adoptAndCallCompletionHandler);

    if (WKStringIsEqualToUTF8CString(command, "DisplayAndTrackRepaints"))
        return WKPageDisplayAndTrackRepaintsForTesting(TestController::singleton().mainWebView()->page(), completionHandler.leak(), adoptAndCallCompletionHandler);

    if (WKStringIsEqualToUTF8CString(command, "SetResourceMonitorList"))
        return setResourceMonitorList(stringValue(argument), WTF::move(completionHandler));


    if (WKStringIsEqualToUTF8CString(command, "SetPageScaleFactor")) {
        auto argumentDictionary = dictionaryValue(argument);
        auto scaleFactor = doubleValue(argumentDictionary, "scaleFactor");
        auto x = doubleValue(argumentDictionary, "x");
        auto y = doubleValue(argumentDictionary, "y");
        return setPageScaleFactor(static_cast<float>(scaleFactor), static_cast<int>(x), static_cast<int>(y), WTF::move(completionHandler));
    }

    if (WKStringIsEqualToUTF8CString(command, "SetObscuredContentInsets")) {
        auto insetValues = arrayValue(argument);
        auto top = static_cast<float>(doubleValue(WKArrayGetItemAtIndex(insetValues, 0)));
        auto right = static_cast<float>(doubleValue(WKArrayGetItemAtIndex(insetValues, 1)));
        auto bottom = static_cast<float>(doubleValue(WKArrayGetItemAtIndex(insetValues, 2)));
        auto left = static_cast<float>(doubleValue(WKArrayGetItemAtIndex(insetValues, 3)));
        return WKPageSetObscuredContentInsetsForTesting(TestController::singleton().mainWebView()->page(), top, right, bottom, left, completionHandler.leak(), adoptAndCallCompletionHandler);
    }

    if (WKStringIsEqualToUTF8CString(command, "UpdatePresentation"))
        return updatePresentation(WTF::move(completionHandler));

    if (WKStringIsEqualToUTF8CString(command, "FlushConsoleLogs"))
        return completionHandler(nullptr);

    if (WKStringIsEqualToUTF8CString(command, "TakeViewPortSnapshot"))
        return completionHandler(takeViewPortSnapshot().get());

    if (WKStringIsEqualToUTF8CString(command, "SetStatisticsShouldBlockThirdPartyCookies"))
        return setStatisticsShouldBlockThirdPartyCookies(booleanValue(argument), ThirdPartyCookieBlockingPolicy::All, WTF::move(completionHandler));

    if (WKStringIsEqualToUTF8CString(command, "SetStatisticsShouldDowngradeReferrer"))
        return setStatisticsShouldDowngradeReferrer(booleanValue(argument), WTF::move(completionHandler));

    if (WKStringIsEqualToUTF8CString(command, "SetStatisticsFirstPartyWebsiteDataRemovalMode"))
        return setStatisticsFirstPartyWebsiteDataRemovalMode(booleanValue(argument), WTF::move(completionHandler));

    if (WKStringIsEqualToUTF8CString(command, "StatisticsSetToSameSiteStrictCookies"))
        return setStatisticsToSameSiteStrictCookies(stringValue(argument), WTF::move(completionHandler));

    if (WKStringIsEqualToUTF8CString(command, "StatisticsSetFirstPartyHostCNAMEDomain")) {
        auto argumentDictionary = dictionaryValue(argument);
        auto firstPartyURLString = stringValue(argumentDictionary, "FirstPartyURL");
        auto cnameURLString = stringValue(argumentDictionary, "CNAME");
        setStatisticsFirstPartyHostCNAMEDomain(firstPartyURLString, cnameURLString, WTF::move(completionHandler));
        return;
    }

    if (WKStringIsEqualToUTF8CString(command, "StatisticsSetThirdPartyCNAMEDomain"))
        return setStatisticsThirdPartyCNAMEDomain(stringValue(argument), WTF::move(completionHandler));

    if (WKStringIsEqualToUTF8CString(command, "LoadedSubresourceDomains"))
        return loadedSubresourceDomains(WTF::move(completionHandler));

    if (WKStringIsEqualToUTF8CString(command, "RemoveAllSessionCredentials"))
        return TestController::singleton().removeAllSessionCredentials(WTF::move(completionHandler));

    if (WKStringIsEqualToUTF8CString(command, "SetStorageAccessPermission")) {
        auto argumentDictionary = dictionaryValue(argument);
        auto value = booleanValue(argumentDictionary, "Value");
        auto subFrameURL = stringValue(argumentDictionary, "SubFrameURL");
        auto page = mainWebView()->page();
        auto mainFrameURL = adoptWK(WKURLCopyString(WKPageCopyActiveURL(page)));
        return WKWebsiteDataStoreSetStorageAccessPermissionForTesting(websiteDataStore(), page, value, mainFrameURL.get(), subFrameURL, completionHandler.leak(), adoptAndCallCompletionHandler);
    }

    if (WKStringIsEqualToUTF8CString(command, "SetStorageAccess"))
        return WKWebsiteDataStoreSetStorageAccessForTesting(websiteDataStore(), booleanValue(argument), completionHandler.leak(), adoptAndCallCompletionHandler);

    if (WKStringIsEqualToUTF8CString(command, "SetStorageAccessAPIPerPageScopeEnabled")) {
        setStorageAccessAPIPerPageScopeEnabled(booleanValue(argument));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "GetAllStorageAccessEntries"))
        return getAllStorageAccessEntries(WTF::move(completionHandler));

    if (WKStringIsEqualToUTF8CString(command, "StatisticsResetToConsistentState")) {
        protectedCurrentInvocation()->dumpResourceLoadStatisticsIfNecessary();
        statisticsResetToConsistentState();
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "StatisticsDeleteCookiesForHost")) {
        auto argumentDictionary = dictionaryValue(argument);
        auto hostName = stringValue(argumentDictionary, "HostName");
        auto includeHttpOnlyCookies = booleanValue(argumentDictionary, "IncludeHttpOnlyCookies");
        return TestController::singleton().statisticsDeleteCookiesForHost(hostName, includeHttpOnlyCookies, WTF::move(completionHandler));
    }

    if (WKStringIsEqualToUTF8CString(command, "StatisticsClearInMemoryAndPersistentStore"))
        return statisticsClearInMemoryAndPersistentStore(WTF::move(completionHandler));

    if (WKStringIsEqualToUTF8CString(command, "StatisticsClearThroughWebsiteDataRemoval"))
        return statisticsClearThroughWebsiteDataRemoval(WTF::move(completionHandler));

    if (WKStringIsEqualToUTF8CString(command, "StatisticsClearInMemoryAndPersistentStoreModifiedSinceHours"))
        return statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(uint64Value(argument), WTF::move(completionHandler));


    if (WKStringIsEqualToUTF8CString(command, "StatisticsUpdateCookieBlocking"))
        return statisticsUpdateCookieBlocking(WTF::move(completionHandler));

    if (WKStringIsEqualToUTF8CString(command, "StatisticsProcessStatisticsAndDataRecords"))
        return TestController::singleton().statisticsProcessStatisticsAndDataRecords(WTF::move(completionHandler));

    if (WKStringIsEqualToUTF8CString(command, "SetStatisticsHasHadUserInteraction")) {
        auto argumentDictionary = dictionaryValue(argument);
        auto hostName = stringValue(argumentDictionary, "HostName");
        auto value = booleanValue(argumentDictionary, "Value");
        setStatisticsHasHadUserInteraction(hostName, value, WTF::move(completionHandler));
        return;
    }


    if (WKStringIsEqualToUTF8CString(command, "SetStatisticsPrevalentResourceForDebugMode")) {
        WKStringRef hostName = stringValue(argument);
        setStatisticsPrevalentResourceForDebugMode(hostName, WTF::move(completionHandler));
        return;
    }

    if (WKStringIsEqualToUTF8CString(command, "SetStatisticsLastSeen")) {
        auto argumentDictionary = dictionaryValue(argument);
        auto hostName = stringValue(argumentDictionary, "HostName");
        auto value = doubleValue(argumentDictionary, "Value");
        setStatisticsLastSeen(hostName, value, WTF::move(completionHandler));
        return;
    }

    if (WKStringIsEqualToUTF8CString(command, "SetStatisticsMergeStatistic")) {
        auto argumentDictionary = dictionaryValue(argument);
        auto hostName = stringValue(argumentDictionary, "HostName");
        auto topFrameDomain1 = stringValue(argumentDictionary, "TopFrameDomain1");
        auto topFrameDomain2 = stringValue(argumentDictionary, "TopFrameDomain2");
        auto lastSeen = doubleValue(argumentDictionary, "LastSeen");
        auto hadUserInteraction = booleanValue(argumentDictionary, "HadUserInteraction");
        auto mostRecentUserInteraction = doubleValue(argumentDictionary, "MostRecentUserInteraction");
        auto isGrandfathered = booleanValue(argumentDictionary, "IsGrandfathered");
        auto isPrevalent = booleanValue(argumentDictionary, "IsPrevalent");
        auto isVeryPrevalent = booleanValue(argumentDictionary, "IsVeryPrevalent");
        auto dataRecordsRemoved = uint64Value(argumentDictionary, "DataRecordsRemoved");
        setStatisticsMergeStatistic(hostName, topFrameDomain1, topFrameDomain2, lastSeen, hadUserInteraction, mostRecentUserInteraction, isGrandfathered, isPrevalent, isVeryPrevalent, dataRecordsRemoved, WTF::move(completionHandler));
        return;
    }

    if (WKStringIsEqualToUTF8CString(command, "SetStatisticsExpiredStatistic")) {
        auto argumentDictionary = dictionaryValue(argument);
        auto hostName = stringValue(argumentDictionary, "HostName");
        auto numberOfOperatingDaysPassed = static_cast<uint64_t>(doubleValue(argumentDictionary, "NumberOfOperatingDaysPassed"));
        auto hadUserInteraction = booleanValue(argumentDictionary, "HadUserInteraction");
        auto isScheduledForAllButCookieDataRemoval = booleanValue(argumentDictionary, "IsScheduledForAllButCookieDataRemoval");
        auto isPrevalent = booleanValue(argumentDictionary, "IsPrevalent");
        setStatisticsExpiredStatistic(hostName, numberOfOperatingDaysPassed, hadUserInteraction, isScheduledForAllButCookieDataRemoval, isPrevalent, WTF::move(completionHandler));
        return;
    }

    if (WKStringIsEqualToUTF8CString(command, "SetStatisticsPrevalentResource")) {
        auto argumentDictionary = dictionaryValue(argument);
        auto hostName = stringValue(argumentDictionary, "HostName");
        auto value = booleanValue(argumentDictionary, "Value");
        setStatisticsPrevalentResource(hostName, value, WTF::move(completionHandler));
        return;
    }

    if (WKStringIsEqualToUTF8CString(command, "SetStatisticsVeryPrevalentResource")) {
        auto argumentDictionary = dictionaryValue(argument);
        auto hostName = stringValue(argumentDictionary, "HostName");
        auto value = booleanValue(argumentDictionary, "Value");
        setStatisticsVeryPrevalentResource(hostName, value, WTF::move(completionHandler));
        return;
    }

    if (WKStringIsEqualToUTF8CString(command, "SetStatisticsDebugMode"))
        return setStatisticsDebugMode(booleanValue(argument), WTF::move(completionHandler));

    if (WKStringIsEqualToUTF8CString(command, "InstallTooltipCallback")) {
        m_tooltipCallbacks.append(dynamic_wk_cast<WKJSHandleRef>(argument));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "InstallCursorCallback")) {
        m_cursorCallbacks.append(dynamic_wk_cast<WKJSHandleRef>(argument));
        WKPageSetCursorDidChangeCallbackForTesting(mainWebView()->page(), cursorDidChangeForTesting, nullptr);
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "InstallBeginSwipeCallback")) {
        m_beginSwipeCallbacks.append(dynamic_wk_cast<WKJSHandleRef>(argument));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "InstallWillEndSwipeCallback")) {
        m_willEndSwipeCallbacks.append(dynamic_wk_cast<WKJSHandleRef>(argument));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "InstallDidEndSwipeCallback")) {
        m_didEndSwipeCallbacks.append(dynamic_wk_cast<WKJSHandleRef>(argument));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "InstallDidRemoveSwipeSnapshotCallback")) {
        m_didRemoveSwipeSnapshotCallbacks.append(dynamic_wk_cast<WKJSHandleRef>(argument));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "RunUIScript")) {
        unsigned callbackID = UIScriptInvocationData::nextCallbackID++;
        auto invocationData = new UIScriptInvocationData(callbackID, dynamic_wk_cast<WKStringRef>(argument), m_currentInvocation);
        m_uiScriptCallbacks.add(callbackID, Callbacks { }).iterator->value.append(dynamic_wk_cast<WKJSHandleRef>(argument2));
        WKPageCallAfterNextPresentationUpdate(mainWebView()->page(), invocationData, [] (WKErrorRef, void* context) {
            runUISideScriptImmediately(context);
        });
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "RunUIScriptImmediately")) {
        unsigned callbackID = UIScriptInvocationData::nextCallbackID++;
        auto invocationData = new UIScriptInvocationData(callbackID, dynamic_wk_cast<WKStringRef>(argument), m_currentInvocation);
        m_uiScriptCallbacks.add(callbackID, Callbacks { }).iterator->value.append(dynamic_wk_cast<WKJSHandleRef>(argument2));
        runUISideScriptImmediately(invocationData);
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "GetApplicationManifest")) {
        return WKPageGetApplicationManifest(mainWebView()->page(), completionHandler.leak(), [] (void* context, bool success) {
            auto completionHandler = WTF::adopt(static_cast<CompletionHandler<void(WKTypeRef)>::Impl*>(context));
            completionHandler(adoptWK(WKBooleanCreate(success)).get());
        });
    }

    if (WKStringIsEqualToUTF8CString(command, "IndicateFindMatch")) {
        auto index = static_cast<uint32_t>(WKDoubleGetValue(static_cast<WKDoubleRef>(argument)));
        WKPageIndicateFindMatch(mainWebView()->page(), index);
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "WaitBeforeFinishingFullscreenExit")) {
        waitBeforeFinishingFullscreenExit();
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "ScrollDuringEnterFullscreen")) {
        scrollDuringEnterFullscreen();
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "FinishFullscreenExit")) {
        finishFullscreenExit();
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "DumpAllHTTPRedirectedResponseHeaders")) {
        m_dumpAllHTTPRedirectedResponseHeaders = true;
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "RequestExitFullscreenFromUIProcess")) {
        requestExitFullscreenFromUIProcess();
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "DumpFullScreenCallbacks")) {
        dumpFullScreenCallbacks();
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "DumpFullScreenOrigin")) {
        dumpFullScreenOrigin();
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "StopLoading")) {
        WKPageStopLoading(mainWebView()->page());
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "KeyExistsInKeychain"))
        return completionHandler(adoptWK(WKBooleanCreate(keyExistsInKeychain(toWTFString(argument), toWTFString(argument2)))).get());

    if (WKStringIsEqualToUTF8CString(command, "SetShouldLogDownloadCallbacks")) {
        m_shouldLogDownloadCallbacks = WKBooleanGetValue(dynamic_wk_cast<WKBooleanRef>(argument));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "SetShouldLogDownloadSize")) {
        setShouldLogDownloadSize(WKBooleanGetValue(dynamic_wk_cast<WKBooleanRef>(argument)));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "SetShouldLogDownloadExpectedSize")) {
        setShouldLogDownloadExpectedSize(WKBooleanGetValue(dynamic_wk_cast<WKBooleanRef>(argument)));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "SetShouldDownloadContentDispositionAttachments")) {
        setShouldDownloadContentDispositionAttachments(WKBooleanGetValue(dynamic_wk_cast<WKBooleanRef>(argument)));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "SetShouldDecideNavigationPolicyAfterDelay")) {
        setShouldDecideNavigationPolicyAfterDelay(WKBooleanGetValue(dynamic_wk_cast<WKBooleanRef>(argument)));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "SetShouldDecideResponsePolicyAfterDelay")) {
        setShouldDecideResponsePolicyAfterDelay(WKBooleanGetValue(dynamic_wk_cast<WKBooleanRef>(argument)));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "SetNavigationGesturesEnabled")) {
        setNavigationGesturesEnabled(WKBooleanGetValue(dynamic_wk_cast<WKBooleanRef>(argument)));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "SetIgnoresViewportScaleLimits")) {
        setIgnoresViewportScaleLimits(WKBooleanGetValue(dynamic_wk_cast<WKBooleanRef>(argument)));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "SetUseDarkAppearanceForTesting")) {
        setUseDarkAppearanceForTesting(WKBooleanGetValue(dynamic_wk_cast<WKBooleanRef>(argument)));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "SetShouldDownloadUndisplayableMIMETypes")) {
        setShouldDownloadUndisplayableMIMETypes(WKBooleanGetValue(dynamic_wk_cast<WKBooleanRef>(argument)));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "SetShouldAllowDeviceOrientationAndMotionAccess")) {
        setShouldAllowDeviceOrientationAndMotionAccess(WKBooleanGetValue(dynamic_wk_cast<WKBooleanRef>(argument)));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "SetRejectsProtectionSpaceAndContinueForAuthenticationChallenges")) {
        setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(WKBooleanGetValue(dynamic_wk_cast<WKBooleanRef>(argument)));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "SetHandlesAuthenticationChallenges")) {
        setHandlesAuthenticationChallenges(WKBooleanGetValue(dynamic_wk_cast<WKBooleanRef>(argument)));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "SetShouldLogCanAuthenticateAgainstProtectionSpace")) {
        m_shouldLogCanAuthenticateAgainstProtectionSpace = WKBooleanGetValue(dynamic_wk_cast<WKBooleanRef>(argument));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "SetBlockAllPlugins")) {
        setBlockAllPlugins(WKBooleanGetValue(dynamic_wk_cast<WKBooleanRef>(argument)));
        return completionHandler(nullptr);
    }

    if (WKStringIsEqualToUTF8CString(command, "SetStatisticsShouldBlockThirdPartyCookiesOnSitesWithoutUserInteraction"))
        return setStatisticsShouldBlockThirdPartyCookies(booleanValue(argument), ThirdPartyCookieBlockingPolicy::AllOnlyOnSitesWithoutUserInteraction, WTF::move(completionHandler));

    if (WKStringIsEqualToUTF8CString(command, "SetStatisticsShouldBlockThirdPartyCookiesExceptPartitioned"))
        return setStatisticsShouldBlockThirdPartyCookies(booleanValue(argument), ThirdPartyCookieBlockingPolicy::AllExceptPartitioned, WTF::move(completionHandler));

    if (WKStringIsEqualToUTF8CString(command, "FindStringMatches")) {
        auto argumentDictionary = dictionaryValue(argument);
        auto string = stringValue(argumentDictionary, "String");
        auto findOptions = findOptionsFromArray(arrayValue(argumentDictionary, "FindOptions"));
        WKPageFindStringMatches(TestController::singleton().mainWebView()->page(), string, findOptions, 0);
        completionHandler(nullptr);
        return;
    }

    if (WKStringIsEqualToUTF8CString(command, "SetManagedDomains")) {
        const auto urlArray = WKURLArrayFromWKStringArray(argument);
        return setManagedDomains(urlArray.get(), WTF::move(completionHandler));
    }

    if (WKStringIsEqualToUTF8CString(command, "SetAppBoundDomains")) {
        const auto urlArray = WKURLArrayFromWKStringArray(argument);
        return setAppBoundDomains(urlArray.get(), WTF::move(completionHandler));
    }

    if (WKStringIsEqualToUTF8CString(command, "SetAuthenticationUsername")) {
        WKStringRef username = stringValue(argument);
        TestController::singleton().setAuthenticationUsername(toWTFString(username));
        completionHandler(nullptr);
        return;
    }

    if (WKStringIsEqualToUTF8CString(command, "SetAuthenticationPassword")) {
        WKStringRef password = stringValue(argument);
        TestController::singleton().setAuthenticationPassword(toWTFString(password));
        completionHandler(nullptr);
        return;
    }

    if (WKStringIsEqualToUTF8CString(command, "SetPluginSupportedMode")) {
        WKStringRef mode = stringValue(argument);
        TestController::singleton().setPluginSupportedMode(toWTFString(mode));
        completionHandler(nullptr);
        return;
    }

    if (WKStringIsEqualToUTF8CString(command, "SetAllowedMenuActions")) {
        auto argumentArray = dynamic_wk_cast<WKArrayRef>(argument);
        auto size = WKArrayGetSize(argumentArray);
        Vector<String> actions;
        actions.reserveInitialCapacity(size);
        for (size_t index = 0; index < size; ++index)
            actions.append(toWTFString(stringValue(WKArrayGetItemAtIndex(argumentArray, index))));
        TestController::singleton().setAllowedMenuActions(actions);
        completionHandler(nullptr);
        return;
    }

    if (WKStringIsEqualToUTF8CString(command, "SetOpenPanelFileURLs")) {
        const auto files = arrayValue(argument);
        auto fileURLs = adoptWK(WKMutableArrayCreate());

        const auto length = WKArrayGetSize(files);
        for (size_t i = 0; i < length; i++) {
            auto file = WKArrayGetItemAtIndex(files, i);
            String fileString = toWTFString(dynamic_wk_cast<WKStringRef>(file));
            auto fileURL = makeOpenPanelURL(currentTestURL(), fileString);
            WKArrayAppendItem(fileURLs.get(), fileURL.get());
        }

        TestController::singleton().setOpenPanelFileURLs(fileURLs.get());
        completionHandler(nullptr);
        return;
    }

    if (WKStringIsEqualToUTF8CString(command, "SetOpenPanelFileURLsMediaIcon")) {
#if PLATFORM(IOS_FAMILY)
        const auto dictionary = dynamic_wk_cast<WKDictionaryRef>(argument);
        const auto keys = WKDictionaryCopyKeys(dictionary);
        const auto length = WKArrayGetSize(keys);
        Vector<unsigned char> bytes;
        for (size_t i = 0; i < length; i++) {
            auto key = WKArrayGetItemAtIndex(keys, i);
            auto keyStr = toWTFString(stringValue(key)).utf8();
            auto intValue = doubleValue(dictionary, keyStr.data());
            bytes.append(static_cast<unsigned char>(intValue));
        }
        WKDataRef data = WKDataCreate(bytes.begin(), bytes.size());
        TestController::singleton().setOpenPanelFileURLsMediaIcon(data);
#endif
        completionHandler(nullptr);
        return;
    }

    if (WKStringIsEqualToUTF8CString(command, "AsyncMouseMoveTo")) {
        const auto x = doubleValue(argument);
        const auto y = doubleValue(argument2);
        const auto pointerType = stringValue(argument3);

        // Route event to the view that sent this message (e.g. a popup window).
        setTargetViewFromMessage(message);

        auto array = adoptWK(WKMutableArrayCreate());
        WKArrayAppendItem(array.get(), argument);
        WKArrayAppendItem(array.get(), argument2);
        WKPagePostMessageToInjectedBundle(targetView()->page(), toWK("SetMousePosition").get(), array.get());

        m_eventSenderProxy->mouseMoveTo(x, y, pointerType,
            [this, completionHandler = WTF::move(completionHandler)] mutable {
                setTargetView(nullptr);
                completionHandler(nullptr);
            });
        return;
    }

    if (WKStringIsEqualToUTF8CString(command, "AsyncMouseDown")) {
        const auto button = static_cast<uint64_t>(doubleValue(argument));
        const auto array = arrayValue(argument2);
        const auto pointerType = stringValue(argument3);

        setTargetViewFromMessage(message);

        m_eventSenderProxy->mouseDown(button, parseModifierArray(array), pointerType,
            [this, completionHandler = WTF::move(completionHandler)] mutable {
                setTargetView(nullptr);
                completionHandler(nullptr);
            });
        return;
    }

    if (WKStringIsEqualToUTF8CString(command, "AsyncMouseUp")) {
        const auto button = static_cast<uint64_t>(doubleValue(argument));
        const auto array = arrayValue(argument2);
        const auto pointerType = stringValue(argument3);

        setTargetViewFromMessage(message);

        m_eventSenderProxy->mouseUp(button, parseModifierArray(array), pointerType,
            [this, completionHandler = WTF::move(completionHandler)] mutable {
                setTargetView(nullptr);
                completionHandler(nullptr);
            });
        return;
    }

    if (WKStringIsEqualToUTF8CString(command, "AsyncKeyDown")) {
        const auto key = stringValue(argument);
        const auto array = arrayValue(argument2);
        m_eventSenderProxy->keyDown(key, parseModifierArray(array), 0,
            [completionHandler = WTF::move(completionHandler)] mutable { completionHandler(nullptr); });
        return;
    }

#if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
    if (WKStringIsEqualToUTF8CString(command, "AsyncTouchStart")) {
        m_eventSenderProxy->touchStart([completionHandler = WTF::move(completionHandler)] mutable {
            completionHandler(nullptr);
        });
        return;
    }
    if (WKStringIsEqualToUTF8CString(command, "AsyncTouchMove")) {
        m_eventSenderProxy->touchMove([completionHandler = WTF::move(completionHandler)] mutable {
            completionHandler(nullptr);
        });
        return;
    }
    if (WKStringIsEqualToUTF8CString(command, "AsyncTouchEnd")) {
        m_eventSenderProxy->touchEnd([completionHandler = WTF::move(completionHandler)] mutable {
            completionHandler(nullptr);
        });
        return;
    }
    if (WKStringIsEqualToUTF8CString(command, "AsyncTouchCancel")) {
        m_eventSenderProxy->touchCancel([completionHandler = WTF::move(completionHandler)] mutable {
            completionHandler(nullptr);
        });
        return;
    }
#endif

    ASSERT_NOT_REACHED();
}

void TestController::installUserScript(const TestInvocation& test)
{
    WKRetainPtr configuration = adoptWK(WKPageCopyPageConfiguration(mainWebView()->page()));
    WKRetainPtr controller = WKPageConfigurationGetUserContentController(configuration.get());
    WKUserContentControllerRemoveAllUserScripts(controller.get());
    WKUserContentControllerRemoveAllUserMessageHandlers(controller.get());

    if (!test.options().shouldInjectTestRunner())
        return;

    constexpr bool forMainFrameOnly { false };
    WKRetainPtr uiSenderScript = adoptWK(WKUserScriptCreateWithSource(toWK(eventSenderJS).get(), kWKInjectAtDocumentStart, forMainFrameOnly));
    WKRetainPtr script = adoptWK(WKUserScriptCreateWithSource(toWK(testRunnerJS).get(), kWKInjectAtDocumentStart, forMainFrameOnly));

    WKUserContentControllerAddUserScript(controller.get(), uiSenderScript.get());
    WKUserContentControllerAddUserScript(controller.get(), script.get());

    WKUserContentControllerAddScriptMessageHandler(controller.get(), toWK("webkitTestRunner").get(), didReceiveScriptMessage, nullptr);
}

#if ENABLE(CONTENT_EXTENSIONS) && !PLATFORM(COCOA)

struct ContentExtensionStoreCallbackContext {
    explicit ContentExtensionStoreCallbackContext(TestController& controller)
        : testController(controller)
    {
    }

    TestController& testController;
    uint32_t status { kWKUserContentExtensionStoreSuccess };
    WKRetainPtr<WKUserContentFilterRef> filter;
    bool done { false };
};

static void contentExtensionStoreCallback(WKUserContentFilterRef filter, uint32_t status, void* userData)
{
    auto* context = static_cast<ContentExtensionStoreCallbackContext*>(userData);
    context->status = status;
    context->filter = filter ? adoptWK(filter) : nullptr;
    context->done = true;
    context->testController.notifyDone();
}

static std::string contentExtensionJSONPath(WKURLRef url)
{
    auto toJSON = [](std::string path) {
        return path.substr(0, path.rfind('.')) + ".json";
    };

    auto path = testPath(url);
    if (path.length())
        return toJSON(path);

    return "LayoutTests/http/tests" + toJSON(toSTD(adoptWK(WKURLCopyPath(url)).get()));
}

void TestController::configureContentExtensionForTest(const TestInvocation& test)
{
    const char* contentExtensionsPath = libraryPathForTesting();
    if (!contentExtensionsPath)
        contentExtensionsPath = "/tmp/wktr-contentextensions";

    if (!test.urlContains("contentextensions/"_s)) {
        return;
    }

    std::string jsonFilePath(contentExtensionJSONPath(test.url()));
    std::ifstream jsonFile(jsonFilePath);
    if (!jsonFile.good()) {
        WTFLogAlways("Could not open file '%s'", jsonFilePath.c_str());
        return;
    }

    std::string jsonFileContents {std::istreambuf_iterator<char>(jsonFile), std::istreambuf_iterator<char>()};
    auto jsonSource = toWK(jsonFileContents.c_str());

    auto storePath = toWK(contentExtensionsPath);
    auto extensionStore = adoptWK(WKUserContentExtensionStoreCreate(storePath.get()));
    ASSERT(extensionStore);

    auto filterIdentifier = toWK("TestContentExtension");

    ContentExtensionStoreCallbackContext context(*this);
    WKUserContentExtensionStoreCompile(extensionStore.get(), filterIdentifier.get(), jsonSource.get(), &context, contentExtensionStoreCallback);
    runUntil(context.done, noTimeout);
    ASSERT(context.status == kWKUserContentExtensionStoreSuccess);
    ASSERT(context.filter);

    WKUserContentControllerAddUserContentFilter(userContentController(), context.filter.get());
}

void TestController::resetContentExtensions()
{
    if (!mainWebView())
        return;

    const char* contentExtensionsPath = libraryPathForTesting();
    if (!contentExtensionsPath)
        return;

    WKUserContentControllerRemoveAllUserContentFilters(userContentController());

    auto storePath = toWK(contentExtensionsPath);
    auto extensionStore = adoptWK(WKUserContentExtensionStoreCreate(storePath.get()));
    ASSERT(extensionStore);

    auto filterIdentifier = toWK("TestContentExtension");

    ContentExtensionStoreCallbackContext context(*this);
    WKUserContentExtensionStoreRemove(extensionStore.get(), filterIdentifier.get(), &context, contentExtensionStoreCallback);
    runUntil(context.done, noTimeout);
    ASSERT(!context.filter);
}

#endif // ENABLE(CONTENT_EXTENSIONS) && !PLATFORM(COCOA)

#if !ENABLE(CONTENT_EXTENSIONS)

void TestController::configureContentExtensionForTest(const TestInvocation&)
{
}

void TestController::resetContentExtensions()
{
}

#endif // !ENABLE(CONTENT_EXTENSIONS)

bool TestController::runTest(const char* inputLine)
{
    AutodrainedPool pool;

    WKTextCheckerSetTestingMode(true);
    
    auto command = parseInputLine(std::string(inputLine));

    m_state = RunningTest;

    TestOptions options = testOptionsForTest(command);

    m_mainResourceURL = adoptWK(createTestURL(command.pathOrURL));
    if (!m_mainResourceURL)
        return false;

    Ref currentInvocation = TestInvocation::create(m_mainResourceURL.get(), options);
    m_currentInvocation = currentInvocation.copyRef();

    if (command.shouldDumpPixels || m_shouldDumpPixelsForAllTests)
        currentInvocation->setIsPixelTest(command.expectedPixelHash);

    if (command.forceDumpPixels)
        currentInvocation->setForceDumpPixels(true);

    if (command.timeout > 0_s)
        currentInvocation->setCustomTimeout(command.timeout);

    currentInvocation->setDumpJSConsoleLogInStdErr(command.dumpJSConsoleLogInStdErr || options.dumpJSConsoleLogInStdErr());

    platformWillRunTest(currentInvocation);

    currentInvocation->invoke();
    m_currentInvocation = nullptr;
    m_mainResourceURL = nullptr;

    return true;
}

bool TestController::waitForCompletion(const WTF::Function<void ()>& function, WTF::Seconds timeout)
{
    m_doneResetting = false;
    function();
    runUntil(m_doneResetting, timeout);
    return !m_doneResetting;
}

bool TestController::handleControlCommand(std::span<const char> command)
{
    if (spanHasPrefix(command, "#CHECK FOR WORLD LEAKS"_span)) {
        if (m_checkForWorldLeaks)
            findAndDumpWorldLeaks();
        else
            WTFLogAlways("WebKitTestRunner asked to check for world leaks, but was not run with --world-leaks");
        return true;
    }

    if (spanHasPrefix(command, "#LIST CHILD PROCESSES"_span)) {
        findAndDumpWebKitProcessIdentifiers();
        return true;
    }

    return false;
}

void TestController::runTestingServerLoop()
{
    std::array<char, 2048> filenameBuffer;
    while (fgets(filenameBuffer.data(), filenameBuffer.size(), stdin)) {
        if (size_t newLineCharacterIndex = find(std::span<const char> { filenameBuffer }, '\n'); newLineCharacterIndex != notFound)
            filenameBuffer[newLineCharacterIndex] = '\0';

        if (!strlen(filenameBuffer.data()))
            continue;

        if (handleControlCommand(filenameBuffer))
            continue;

        if (!runTest(filenameBuffer.data()))
            break;
    }
}

void TestController::run()
{
    if (m_usingServerMode)
        runTestingServerLoop();
    else {
        for (size_t i = 0; i < m_paths.size(); ++i) {
            if (!runTest(m_paths[i].c_str()))
                break;
        }
        if (m_checkForWorldLeaks)
            findAndDumpWorldLeaks();
    }
}

void TestController::runUntil(bool& done, WTF::Seconds timeout)
{
    if (m_forceNoTimeout)
        timeout = noTimeout;

    platformRunUntil(done, timeout);
}

// WKContextInjectedBundleClient

void TestController::didReceiveMessageFromInjectedBundle(WKContextRef context, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveMessageFromInjectedBundle(messageName, messageBody);
}

void TestController::didReceiveSynchronousMessageFromInjectedBundleWithListener(WKContextRef context, WKStringRef messageName, WKTypeRef messageBody, WKMessageListenerRef listener, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody, listener);
}

WKTypeRef TestController::getInjectedBundleInitializationUserData(WKContextRef, const void* clientInfo)
{
    return static_cast<TestController*>(const_cast<void*>(clientInfo))->getInjectedBundleInitializationUserData().leakRef();
}

// WKPageInjectedBundleClient

void TestController::didReceivePageMessageFromInjectedBundle(WKPageRef page, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo)
{
    auto* testController = static_cast<TestController*>(const_cast<void*>(clientInfo));
    if (page != testController->mainWebView()->page()) {
        // If this is a Done message from an auxiliary view in its own WebProcess (due to process-swapping), we need to notify the injected bundle of the main WebView
        // that the test is done.
        if (WKStringIsEqualToUTF8CString(messageName, "Done") && testController->m_currentInvocation)
            WKPagePostMessageToInjectedBundle(testController->mainWebView()->page(), toWK("NotifyDone").get(), nullptr);
        if (!WKStringIsEqualToUTF8CString(messageName, "TextOutput"))
            return;
    }
    testController->didReceiveMessageFromInjectedBundle(messageName, messageBody);
}

void TestController::didReceiveSynchronousPageMessageFromInjectedBundleWithListenerFromMainFrameProcess(WKPageRef page, WKStringRef messageName, WKTypeRef messageBody, bool fromMainFrameProcess, WKMessageListenerRef listener, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody, listener, fromMainFrameProcess);
}

void TestController::networkProcessDidCrashWithDetails(WKContextRef context, WKProcessID processID, WKProcessTerminationReason reason, const void *clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->networkProcessDidCrash(processID, reason);
}

void TestController::serviceWorkerProcessDidCrashWithDetails(WKContextRef context, WKProcessID processID, WKProcessTerminationReason reason, const void *clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->serviceWorkerProcessDidCrash(processID, reason);
}

void TestController::gpuProcessDidCrashWithDetails(WKContextRef context, WKProcessID processID, WKProcessTerminationReason reason, const void *clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->gpuProcessDidCrash(processID, reason);
}

void TestController::didReceiveKeyDownMessageFromInjectedBundle(WKDictionaryRef dictionary, bool synchronous)
{
    m_eventSenderProxy->keyDown(stringValue(dictionary, "Key"), uint64Value(dictionary, "Modifiers"), uint64Value(dictionary, "Location"));
}

void TestController::didReceiveRawKeyDownMessageFromInjectedBundle(WKDictionaryRef dictionary, bool synchronous)
{
    m_eventSenderProxy->rawKeyDown(stringValue(dictionary, "Key"), uint64Value(dictionary, "Modifiers"), uint64Value(dictionary, "Location"));
}

void TestController::didReceiveRawKeyUpMessageFromInjectedBundle(WKDictionaryRef dictionary, bool synchronous)
{
    m_eventSenderProxy->rawKeyUp(stringValue(dictionary, "Key"), uint64Value(dictionary, "Modifiers"), uint64Value(dictionary, "Location"));
}

void TestController::didReceiveLiveDocumentsList(WKArrayRef liveDocumentList)
{
    auto numDocuments = WKArrayGetSize(liveDocumentList);

    HashMap<String, String> documentInfo;
    for (size_t i = 0; i < numDocuments; ++i) {
        if (auto dictionary = dictionaryValue(WKArrayGetItemAtIndex(liveDocumentList, i)))
            documentInfo.add(toWTFString(stringValue(dictionary, "id")), toWTFString(stringValue(dictionary, "url")));
    }

    if (!documentInfo.size()) {
        m_abandonedDocumentInfo.clear();
        return;
    }

    // Remove any documents which are no longer live.
    m_abandonedDocumentInfo.removeIf([&](auto& keyAndValue) {
        return !documentInfo.contains(keyAndValue.key);
    });
    
    // Add newly abandoned documents.
    String currentTestURL = m_currentInvocation ? toWTFString(adoptWK(WKURLCopyString(m_currentInvocation->url()))) : "no test"_s;
    for (const auto& it : documentInfo)
        m_abandonedDocumentInfo.add(it.key, AbandonedDocumentInfo(currentTestURL, it.value));
}

void TestController::didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
{
    if (WKStringIsEqualToUTF8CString(messageName, "LiveDocuments")) {
        didReceiveLiveDocumentsList(dynamic_wk_cast<WKArrayRef>(messageBody));
        AsyncTask::currentTask()->taskComplete();
        return;
    }

    if (WKStringIsEqualToUTF8CString(messageName, "EventSender")) {
        if (m_state != RunningTest || !m_currentInvocation)
            return;

        auto dictionary = dictionaryValue(messageBody);
        uint64_t testIdentifier = uint64Value(dictionary, "TestIdentifier");

        // This EventSender message was meant for another test, discard it
        // to prevent potential flakiness.
        if (testIdentifier != m_currentInvocation->identifier())
            return;

        auto subMessageName = stringValue(dictionary, "SubMessage");

        if (WKStringIsEqualToUTF8CString(subMessageName, "MouseDown")) {
            m_eventSenderProxy->mouseDown(uint64Value(dictionary, "Button"), uint64Value(dictionary, "Modifiers"), stringValue(dictionary, "PointerType"));
            return;
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "MouseUp")) {
            m_eventSenderProxy->mouseUp(uint64Value(dictionary, "Button"), uint64Value(dictionary, "Modifiers"), stringValue(dictionary, "PointerType"));
            return;
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "KeyDown")) {
            didReceiveKeyDownMessageFromInjectedBundle(dictionary, false);
            return;
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "RawKeyDown")) {
            didReceiveRawKeyDownMessageFromInjectedBundle(dictionary, false);
            return;
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "RawKeyUp")) {
            didReceiveRawKeyUpMessageFromInjectedBundle(dictionary, false);
            return;
        }
        
        if (WKStringIsEqualToUTF8CString(subMessageName, "MouseScrollBy")) {
            m_eventSenderProxy->mouseScrollBy(doubleValue(dictionary, "X"), doubleValue(dictionary, "Y"));
            return;
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "MouseScrollByWithWheelAndMomentumPhases")) {
            auto x = doubleValue(dictionary, "X");
            auto y = doubleValue(dictionary, "Y");
            auto phase = uint64Value(dictionary, "Phase");
            auto momentum = uint64Value(dictionary, "Momentum");
            m_eventSenderProxy->mouseScrollByWithWheelAndMomentumPhases(x, y, phase, momentum);
            return;
        }

#if PLATFORM(GTK)
        if (WKStringIsEqualToUTF8CString(subMessageName, "SetWheelHasPreciseDeltas")) {
            auto hasPreciseDeltas = booleanValue(dictionary, "HasPreciseDeltas");
            m_eventSenderProxy->setWheelHasPreciseDeltas(hasPreciseDeltas);
            return;
        }
#endif

        ASSERT_NOT_REACHED();
    }

    if (RefPtr currentInvocation = m_currentInvocation)
        currentInvocation->didReceiveMessageFromInjectedBundle(messageName, messageBody);
}

RefPtr<TestInvocation> TestController::protectedCurrentInvocation()
{
    return m_currentInvocation;
}

void TestController::didReceiveSynchronousMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody, WKMessageListenerRef listener, bool fromMainFrameProcess)
{
    auto completionHandler = [listener = retainWK(listener)] (WKTypeRef reply) {
        WKMessageListenerSendReply(listener.get(), reply);
    };

    if (WKStringIsEqualToUTF8CString(messageName, "EventSender")) {
        if (m_state != RunningTest || !m_currentInvocation)
            return completionHandler(nullptr);

        auto dictionary = dictionaryValue(messageBody);
        uint64_t testIdentifier = uint64Value(dictionary, "TestIdentifier");

        // This EventSender message was meant for another test, discard it
        // to prevent potential flakiness.
        if (testIdentifier != m_currentInvocation->identifier())
            return completionHandler(nullptr);

        auto subMessageName = stringValue(dictionary, "SubMessage");

        if (WKStringIsEqualToUTF8CString(subMessageName, "KeyDown")) {
            didReceiveKeyDownMessageFromInjectedBundle(dictionary, true);
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "MouseDown")) {
            m_eventSenderProxy->mouseDown(uint64Value(dictionary, "Button"), uint64Value(dictionary, "Modifiers"), stringValue(dictionary, "PointerType"));
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "MouseUp")) {
            m_eventSenderProxy->mouseUp(uint64Value(dictionary, "Button"), uint64Value(dictionary, "Modifiers"), stringValue(dictionary, "PointerType"));
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "RawKeyDown")) {
            didReceiveRawKeyDownMessageFromInjectedBundle(dictionary, true);
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "RawKeyUp")) {
            didReceiveRawKeyUpMessageFromInjectedBundle(dictionary, true);
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "MouseMoveTo")) {
            m_eventSenderProxy->mouseMoveTo(doubleValue(dictionary, "X"), doubleValue(dictionary, "Y"), stringValue(dictionary, "PointerType"));
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "WaitForDeferredMouseEvents"))
            return completionHandler(nullptr);

#if PLATFORM(MAC)
        if (WKStringIsEqualToUTF8CString(subMessageName, "MouseForceClick")) {
            m_eventSenderProxy->mouseForceClick();
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "StartAndCancelMouseForceClick")) {
            m_eventSenderProxy->startAndCancelMouseForceClick();
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "MouseForceDown")) {
            m_eventSenderProxy->mouseForceDown();
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "MouseForceUp")) {
            m_eventSenderProxy->mouseForceUp();
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "MouseForceChanged")) {
            m_eventSenderProxy->mouseForceChanged(doubleValue(dictionary, "Force"));
            return completionHandler(nullptr);
        }
#endif // PLATFORM(MAC)

        if (WKStringIsEqualToUTF8CString(subMessageName, "ContinuousMouseScrollBy")) {
            auto x = doubleValue(dictionary, "X");
            auto y = doubleValue(dictionary, "Y");
            auto paged = booleanValue(dictionary, "Paged");
            m_eventSenderProxy->continuousMouseScrollBy(x, y, paged);
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "LeapForward")) {
            m_eventSenderProxy->leapForward(uint64Value(dictionary, "TimeInMilliseconds"));
            return completionHandler(nullptr);
        }

#if ENABLE(TOUCH_EVENTS)
        if (WKStringIsEqualToUTF8CString(subMessageName, "AddTouchPoint")) {
            m_eventSenderProxy->addTouchPoint(uint64Value(dictionary, "X"), uint64Value(dictionary, "Y"));
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "UpdateTouchPoint")) {
            auto index = uint64Value(dictionary, "Index");
            auto x = uint64Value(dictionary, "X");
            auto y = uint64Value(dictionary, "Y");
            m_eventSenderProxy->updateTouchPoint(index, x, y);
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "SetTouchModifier")) {
            auto modifier = uint64Value(dictionary, "Modifier");
            auto enable = booleanValue(dictionary, "Enable");
            m_eventSenderProxy->setTouchModifier(modifier, enable);
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "SetTouchPointRadius")) {
            auto x = uint64Value(dictionary, "RadiusX");
            auto y = uint64Value(dictionary, "RadiusY");
            m_eventSenderProxy->setTouchPointRadius(x, y);
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "TouchStart")) {
            m_eventSenderProxy->touchStart();
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "TouchMove")) {
            m_eventSenderProxy->touchMove();
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "TouchEnd")) {
            m_eventSenderProxy->touchEnd();
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "TouchCancel")) {
            m_eventSenderProxy->touchCancel();
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "ClearTouchPoints")) {
            m_eventSenderProxy->clearTouchPoints();
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "ReleaseTouchPoint")) {
            m_eventSenderProxy->releaseTouchPoint(uint64Value(dictionary, "Index"));
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "CancelTouchPoint")) {
            m_eventSenderProxy->cancelTouchPoint(uint64Value(dictionary, "Index"));
            return completionHandler(nullptr);
        }
#endif

#if PLATFORM(MAC)
        if (WKStringIsEqualToUTF8CString(subMessageName, "SmartMagnify")) {
            m_eventSenderProxy->smartMagnify();
            return completionHandler(nullptr);
        }
#endif

#if ENABLE(MAC_GESTURE_EVENTS)
        if (WKStringIsEqualToUTF8CString(subMessageName, "ScaleGestureStart")) {
            auto scale = doubleValue(dictionary, "Scale");
            m_eventSenderProxy->scaleGestureStart(scale);
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "ScaleGestureChange")) {
            auto scale = doubleValue(dictionary, "Scale");
            m_eventSenderProxy->scaleGestureChange(scale);
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "ScaleGestureEnd")) {
            auto scale = doubleValue(dictionary, "Scale");
            m_eventSenderProxy->scaleGestureEnd(scale);
            return completionHandler(nullptr);
        }
#endif // ENABLE(MAC_GESTURE_EVENTS)

        if (WKStringIsEqualToUTF8CString(subMessageName, "SetPageZoom")) {
            auto* page = mainWebView()->page();
            WKPageSetTextZoomFactor(page, 1);
            WKPageSetPageZoomFactor(page, WKPageGetPageZoomFactor(page) * (booleanValue(dictionary, "ZoomIn") ? ZoomMultiplierRatio : (1.0 / ZoomMultiplierRatio)));
            return completionHandler(nullptr);
        }

        if (WKStringIsEqualToUTF8CString(subMessageName, "SetTextZoom")) {
            auto* page = mainWebView()->page();
            WKPageSetPageZoomFactor(page, 1);
            WKPageSetTextZoomFactor(page, WKPageGetTextZoomFactor(page) * (booleanValue(dictionary, "ZoomIn") ? ZoomMultiplierRatio : (1.0 / ZoomMultiplierRatio)));
            return completionHandler(nullptr);
        }

        ASSERT_NOT_REACHED();
    }

    auto setHTTPCookieAcceptPolicy = [&] (WKHTTPCookieAcceptPolicy policy, CompletionHandler<void(WKTypeRef)>&& completionHandler) {
        auto context = new CompletionHandler<void(WKTypeRef)>(WTF::move(completionHandler));
        WKHTTPCookieStoreSetHTTPCookieAcceptPolicy(WKWebsiteDataStoreGetHTTPCookieStore(websiteDataStore()), policy, context, [] (void* context) {
            auto completionHandlerPointer = static_cast<CompletionHandler<void(WKTypeRef)>*>(context);
            (*completionHandlerPointer)(nullptr);
            delete completionHandlerPointer;
        });
    };

    if (WKStringIsEqualToUTF8CString(messageName, "SetAlwaysAcceptCookies")) {
        auto policy = WKBooleanGetValue(static_cast<WKBooleanRef>(messageBody))
            ? kWKHTTPCookieAcceptPolicyAlways
            : kWKHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain;
        return setHTTPCookieAcceptPolicy(policy, WTF::move(completionHandler));
    }

    if (WKStringIsEqualToUTF8CString(messageName, "SetOnlyAcceptFirstPartyCookies")) {
        auto policy = WKBooleanGetValue(static_cast<WKBooleanRef>(messageBody))
            ? kWKHTTPCookieAcceptPolicyExclusivelyFromMainDocumentDomain
            : kWKHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain;
        return setHTTPCookieAcceptPolicy(policy, WTF::move(completionHandler));
    }

#if PLATFORM(MAC)
    if (WKStringIsEqualToUTF8CString(messageName, "AXGetRoot"))
        return completionHandler(handleAXGetRoot().get());

    if (WKStringIsEqualToUTF8CString(messageName, "AXCopyAttributeValueAsString"))
        return completionHandler(handleAXCopyAttributeValueAsString(dictionaryValue(messageBody)).get());

    if (WKStringIsEqualToUTF8CString(messageName, "AXCopyAttributeValueAsElement"))
        return completionHandler(handleAXCopyAttributeValueAsElement(dictionaryValue(messageBody)).get());

    if (WKStringIsEqualToUTF8CString(messageName, "AXCopyAttributeValueAsElementArray"))
        return completionHandler(handleAXCopyAttributeValueAsElementArray(dictionaryValue(messageBody)).get());

    if (WKStringIsEqualToUTF8CString(messageName, "AXCopyAttributeValueAsNumber"))
        return completionHandler(handleAXCopyAttributeValueAsNumber(dictionaryValue(messageBody)).get());

    if (WKStringIsEqualToUTF8CString(messageName, "AXCopyAttributeValueAsBoolean"))
        return completionHandler(handleAXCopyAttributeValueAsBoolean(dictionaryValue(messageBody)).get());

    if (WKStringIsEqualToUTF8CString(messageName, "AXElementsAreEqual"))
        return completionHandler(handleAXElementsAreEqual(dictionaryValue(messageBody)).get());

    if (WKStringIsEqualToUTF8CString(messageName, "AXCopyAttributeValueAsPoint"))
        return completionHandler(handleAXCopyAttributeValueAsPoint(dictionaryValue(messageBody)).get());

    if (WKStringIsEqualToUTF8CString(messageName, "AXCopyAttributeValueAsSize"))
        return completionHandler(handleAXCopyAttributeValueAsSize(dictionaryValue(messageBody)).get());

    if (WKStringIsEqualToUTF8CString(messageName, "AXSearchPredicate"))
        return completionHandler(handleAXSearchPredicate(dictionaryValue(messageBody)).get());

    if (WKStringIsEqualToUTF8CString(messageName, "AXPerformAction")) {
        handleAXPerformAction(dictionaryValue(messageBody));
        return completionHandler(nullptr);
    }
#endif

    if (WKStringIsEqualToUTF8CString(messageName, "GetStorageAreaMapCount")) {
        CompletionHandler<void(WKTypeRef)> replyHandler = [listener = retainWK(listener)](WKTypeRef reply) {
            WKMessageListenerSendReply(listener.get(), reply);
        };
        WKPageGetStorageAreaMapCountForTesting(TestController::singleton().mainWebView()->page(), replyHandler.leak(), [](uint64_t count, void* context) {
            auto replyHandler = WTF::adopt(static_cast<CompletionHandler<void(WKTypeRef)>::Impl*>(context));
            replyHandler(adoptWK(WKUInt64Create(count)).get());
        });
        return;
    }

    completionHandler(protectedCurrentInvocation()->didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody, fromMainFrameProcess).get());
}

WKRetainPtr<WKTypeRef> TestController::getInjectedBundleInitializationUserData()
{
    return nullptr;
}

// WKContextClient

static const char* terminationReasonToString(WKProcessTerminationReason reason)
{
    switch (reason) {
    case kWKProcessTerminationReasonExceededMemoryLimit:
        return "exceeded memory limit";
    case kWKProcessTerminationReasonExceededCPULimit:
        return "exceeded cpu limit";
        break;
    case kWKProcessTerminationReasonRequestedByClient:
        return "requested by client";
    case kWKProcessTerminationReasonCrash:
        return "crash";
    default:
        break;
    }
    ASSERT_NOT_REACHED();
    return "unknown reason";
}

void TestController::networkProcessDidCrash(WKProcessID processID, WKProcessTerminationReason reason)
{
    fprintf(stderr, "%s terminated (pid %ld) for reason: %s\n", networkProcessName().characters(), static_cast<long>(processID), terminationReasonToString(reason));
    fprintf(stderr, "#CRASHED - %s (pid %ld)\n", networkProcessName().characters(), static_cast<long>(processID));
    if (m_shouldExitWhenAuxiliaryProcessCrashes)
        exitProcess(1);
}

void TestController::serviceWorkerProcessDidCrash(WKProcessID processID, WKProcessTerminationReason reason)
{
    fprintf(stderr, "%s terminated (pid %ld) for reason: %s\n", "ServiceWorkerProcess", static_cast<long>(processID), terminationReasonToString(reason));
    fprintf(stderr, "#CRASHED - %s (pid %ld)\n", serviceWorkerProcessName().characters(), static_cast<long>(processID));
    if (m_shouldExitWhenAuxiliaryProcessCrashes)
        exitProcess(1);
}

void TestController::gpuProcessDidCrash(WKProcessID processID, WKProcessTerminationReason reason)
{
    fprintf(stderr, "%s terminated (pid %ld) for reason: %s\n", gpuProcessName().characters(), static_cast<long>(processID), terminationReasonToString(reason));
    fprintf(stderr, "#CRASHED - %s (pid %ld)\n", gpuProcessName().characters(), static_cast<long>(processID));
    if (m_shouldExitWhenAuxiliaryProcessCrashes)
        exitProcess(1);
}

// WKPageNavigationClient

void TestController::didCommitNavigation(WKPageRef page, WKNavigationRef navigation, WKTypeRef, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->didCommitNavigation(page, navigation);
}

void TestController::didFinishNavigation(WKPageRef page, WKNavigationRef navigation, WKTypeRef, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->didFinishNavigation(page, navigation);
}

void TestController::didFailProvisionalNavigation(WKPageRef page, WKNavigationRef navigation, WKErrorRef error, WKTypeRef userData, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->didFailProvisionalNavigation(page, error);
}

void TestController::didReceiveServerRedirectForProvisionalNavigation(WKPageRef page, WKNavigationRef navigation, WKTypeRef userData, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveServerRedirectForProvisionalNavigation(page, navigation, userData);
}

bool TestController::canAuthenticateAgainstProtectionSpace(WKPageRef page, WKProtectionSpaceRef protectionSpace, const void* clientInfo)
{
    return static_cast<TestController*>(const_cast<void*>(clientInfo))->canAuthenticateAgainstProtectionSpace(page, protectionSpace);
}

void TestController::didReceiveAuthenticationChallenge(WKPageRef page, WKAuthenticationChallengeRef authenticationChallenge, const void *clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveAuthenticationChallenge(page, /*frame,*/ authenticationChallenge);
}

void TestController::webProcessDidTerminate(WKPageRef page, WKProcessTerminationReason reason, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->webProcessDidTerminate(reason);
}

void TestController::didBeginNavigationGesture(WKPageRef page, const void *clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->didBeginNavigationGesture(page);
}

void TestController::willEndNavigationGesture(WKPageRef page, WKBackForwardListItemRef backForwardListItem, const void *clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->willEndNavigationGesture(page, backForwardListItem);
}

void TestController::didEndNavigationGesture(WKPageRef page, WKBackForwardListItemRef backForwardListItem, const void *clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->didEndNavigationGesture(page, backForwardListItem);
}

void TestController::didRemoveNavigationGestureSnapshot(WKPageRef page, const void *clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->didRemoveNavigationGestureSnapshot(page);
}

WKPluginLoadPolicy TestController::decidePolicyForPluginLoad(WKPageRef page, WKPluginLoadPolicy currentPluginLoadPolicy, WKDictionaryRef pluginInformation, WKStringRef* unavailabilityDescription, const void* clientInfo)
{
    return static_cast<TestController*>(const_cast<void*>(clientInfo))->decidePolicyForPluginLoad(page, currentPluginLoadPolicy, pluginInformation, unavailabilityDescription);
}

WKPluginLoadPolicy TestController::decidePolicyForPluginLoad(WKPageRef, WKPluginLoadPolicy currentPluginLoadPolicy, WKDictionaryRef pluginInformation, WKStringRef* unavailabilityDescription)
{
    if (m_shouldBlockAllPlugins)
        return kWKPluginLoadPolicyBlocked;

#if PLATFORM(MAC)
    WKStringRef bundleIdentifier = (WKStringRef)WKDictionaryGetItemForKey(pluginInformation, WKPluginInformationBundleIdentifierKey());
    if (!bundleIdentifier)
        return currentPluginLoadPolicy;

    if (WKStringIsEqualToUTF8CString(bundleIdentifier, "com.apple.QuickTime Plugin.plugin"))
        return currentPluginLoadPolicy;

    if (WKStringIsEqualToUTF8CString(bundleIdentifier, "com.apple.testnetscapeplugin"))
        return currentPluginLoadPolicy;

    // Please don't use any other plug-ins in tests, as they will not be installed on all machines.
    RELEASE_ASSERT_NOT_REACHED_WITH_MESSAGE("Unexpected plugin bundle identifier: %s", toSTD(bundleIdentifier).c_str());
#else
    return currentPluginLoadPolicy;
#endif
}

void TestController::setBlockAllPlugins(bool shouldBlock)
{
    m_shouldBlockAllPlugins = shouldBlock;

#if PLATFORM(MAC)
    auto policy = shouldBlock ? kWKPluginLoadClientPolicyBlock : kWKPluginLoadClientPolicyAllow;
    WKContextSetPluginLoadClientPolicy(m_context.get(), policy, toWK("").get(), toWK("com.apple.testnetscapeplugin").get(), toWK("").get());
    WKContextSetPluginLoadClientPolicy(m_context.get(), policy, toWK("").get(), toWK("com.macromedia.Flash Player.plugin").get(), toWK("").get());
#endif
}

void TestController::setPluginSupportedMode(const String& mode)
{
    if (m_unsupportedPluginMode == mode)
        return;

    m_unsupportedPluginMode = mode;
    if (m_unsupportedPluginMode.isEmpty()) {
        WKContextClearSupportedPlugins(m_context.get());
        return;
    }

    auto emptyArray = adoptWK(WKMutableArrayCreate());

    WKContextAddSupportedPlugin(m_context.get(), toWK("").get(), toWK("My personal PDF").get(), emptyArray.get(), emptyArray.get());

    auto nameNetscape = toWK("com.apple.testnetscapeplugin");
    auto mimeTypesNetscape = adoptWK(WKMutableArrayCreate());
    WKArrayAppendItem(mimeTypesNetscape.get(), toWK("application/x-webkit-test-netscape").get());
    auto namePdf = toWK("WebKit built-in PDF");

    if (m_unsupportedPluginMode == "allOrigins"_s) {
        WKContextAddSupportedPlugin(m_context.get(), toWK("").get(), nameNetscape.get(), mimeTypesNetscape.get(), emptyArray.get());
        WKContextAddSupportedPlugin(m_context.get(), toWK("").get(), namePdf.get(), emptyArray.get(), emptyArray.get());
        return;
    }

    if (m_unsupportedPluginMode == "specificOrigin"_s) {
        WKContextAddSupportedPlugin(m_context.get(), toWK("localhost").get(), nameNetscape.get(), mimeTypesNetscape.get(), emptyArray.get());
        WKContextAddSupportedPlugin(m_context.get(), toWK("localhost").get(), namePdf.get(), emptyArray.get(), emptyArray.get());
        return;
    }
}

void TestController::didCommitNavigation(WKPageRef page, WKNavigationRef navigation)
{
    mainWebView()->focus();
}

void TestController::didReceiveServerRedirectForProvisionalNavigation(WKPageRef page, WKNavigationRef navigation, WKTypeRef userData)
{
    m_didReceiveServerRedirectForProvisionalNavigation = true;
    return;
}

static ASCIILiteral toString(WKProtectionSpaceAuthenticationScheme scheme)
{
    switch (scheme) {
    case kWKProtectionSpaceAuthenticationSchemeDefault:
        return "ProtectionSpaceAuthenticationSchemeDefault"_s;
    case kWKProtectionSpaceAuthenticationSchemeHTTPBasic:
        return "ProtectionSpaceAuthenticationSchemeHTTPBasic"_s;
    case kWKProtectionSpaceAuthenticationSchemeHTMLForm:
        return "ProtectionSpaceAuthenticationSchemeHTMLForm"_s;
    case kWKProtectionSpaceAuthenticationSchemeNTLM:
        return "ProtectionSpaceAuthenticationSchemeNTLM"_s;
    case kWKProtectionSpaceAuthenticationSchemeNegotiate:
        return "ProtectionSpaceAuthenticationSchemeNegotiate"_s;
    case kWKProtectionSpaceAuthenticationSchemeClientCertificateRequested:
        return "ProtectionSpaceAuthenticationSchemeClientCertificateRequested"_s;
    case kWKProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested:
        return "ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested"_s;
    case kWKProtectionSpaceAuthenticationSchemeOAuth:
        return "ProtectionSpaceAuthenticationSchemeOAuth"_s;
    case kWKProtectionSpaceAuthenticationSchemeUnknown:
        return "ProtectionSpaceAuthenticationSchemeUnknown"_s;
    }
    ASSERT_NOT_REACHED();
    return "ProtectionSpaceAuthenticationSchemeUnknown"_s;
}

bool TestController::canAuthenticateAgainstProtectionSpace(WKPageRef page, WKProtectionSpaceRef protectionSpace)
{
    if (m_shouldLogCanAuthenticateAgainstProtectionSpace)
        protectedCurrentInvocation()->outputText("canAuthenticateAgainstProtectionSpace\n"_s);
    auto scheme = WKProtectionSpaceGetAuthenticationScheme(protectionSpace);
    if (scheme == kWKProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested) {
        auto host = toSTD(adoptWK(WKProtectionSpaceCopyHost(protectionSpace)));
        return host == "localhost" || host == "127.0.0.1" || m_localhostAliases.find(host) != m_localhostAliases.end() || (m_allowAnyHTTPSCertificateForAllowedHosts && m_allowedHosts.find(host) != m_allowedHosts.end());
    }
    return scheme <= kWKProtectionSpaceAuthenticationSchemeHTTPDigest || scheme == kWKProtectionSpaceAuthenticationSchemeOAuth;
}

void TestController::didFinishNavigation(WKPageRef page, WKNavigationRef navigation)
{
    if (m_state != Resetting)
        return;

    if (!WKURLIsEqual(adoptWK(WKFrameCopyURL(WKPageGetMainFrame(page))).get(), blankURL()))
        return;

    m_doneResetting = true;
    singleton().notifyDone();
}

void TestController::didFailProvisionalNavigation(WKPageRef page, WKErrorRef error)
{
    auto failingURL = adoptWK(WKErrorCopyFailingURL(error));
    m_lastProvisionalNavigationFailureURL = failingURL;

    if (m_usingServerMode)
        return;

    if (!m_mainResourceURL || !failingURL || !WKURLIsEqual(failingURL.get(), m_mainResourceURL.get()))
        return;

    auto failingURLString = toWTFString(adoptWK(WKURLCopyString(failingURL.get())));
    auto errorDomain = toWTFString(adoptWK(WKErrorCopyDomain(error)));
    auto errorDescription = toWTFString(adoptWK(WKErrorCopyLocalizedDescription(error)));
    int errorCode = WKErrorGetErrorCode(error);
    auto errorMessage = makeString("Failed: "_s, errorDescription, " (errorDomain="_s, errorDomain, ", code="_s, errorCode, ") for URL "_s, failingURLString);
    printf("%s\n", errorMessage.utf8().data());
}

WKRetainPtr<WKStringRef> TestController::lastProvisionalNavigationFailureURL() const
{
    if (!m_lastProvisionalNavigationFailureURL)
        return adoptWK(WKStringCreateWithUTF8CString(""));
    return adoptWK(WKURLCopyString(m_lastProvisionalNavigationFailureURL.get()));
}

void TestController::didReceiveAuthenticationChallenge(WKPageRef page, WKAuthenticationChallengeRef authenticationChallenge)
{
    WKProtectionSpaceRef protectionSpace = WKAuthenticationChallengeGetProtectionSpace(authenticationChallenge);
    WKAuthenticationDecisionListenerRef decisionListener = WKAuthenticationChallengeGetDecisionListener(authenticationChallenge);
    WKProtectionSpaceAuthenticationScheme authenticationScheme = WKProtectionSpaceGetAuthenticationScheme(protectionSpace);

    if (authenticationScheme == kWKProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested) {
        // Any non-empty credential signals to accept the server trust. Since the cross-platform API
        // doesn't expose a way to create a credential from server trust, we use a password credential.

        m_serverTrustEvaluationCallbackCallsCount++;

        if (m_allowsAnySSLCertificate) {
            auto credential = adoptWK(WKCredentialCreate(toWK("accept server trust").get(), toWK("").get(), kWKCredentialPersistenceNone));
            WKAuthenticationDecisionListenerUseCredential(decisionListener, credential.get());
            return;
        }
        WKAuthenticationDecisionListenerRejectProtectionSpaceAndContinue(decisionListener);
        return;
    }

    if (m_rejectsProtectionSpaceAndContinueForAuthenticationChallenges) {
        protectedCurrentInvocation()->outputText("Simulating reject protection space and continue for authentication challenge\n"_s);
        WKAuthenticationDecisionListenerRejectProtectionSpaceAndContinue(decisionListener);
        return;
    }

    auto host = toWTFString(adoptWK(WKProtectionSpaceCopyHost(protectionSpace)).get());
    int port = WKProtectionSpaceGetPort(protectionSpace);
    StringBuilder message;
    message.append(host, ':', port, " - didReceiveAuthenticationChallenge - "_s, toString(authenticationScheme), " - "_s);
    if (!m_handlesAuthenticationChallenges)
        message.append("Simulating cancelled authentication sheet\n"_s);
    else
        message.append("Responding with "_s, m_authenticationUsername, ':', m_authenticationPassword, '\n');
    protectedCurrentInvocation()->outputText(message.toString());

    if (!m_handlesAuthenticationChallenges) {
        WKAuthenticationDecisionListenerUseCredential(decisionListener, 0);
        return;
    }
    auto credential = adoptWK(WKCredentialCreate(toWK(m_authenticationUsername).get(), toWK(m_authenticationPassword).get(), kWKCredentialPersistenceForSession));
    WKAuthenticationDecisionListenerUseCredential(decisionListener, credential.get());
}


// WKDownloadClient
    
WKStringRef TestController::decideDestinationWithSuggestedFilename(WKDownloadRef download, WKURLResponseRef response, WKStringRef suggestedFilename, const void* clientInfo)
{
    return static_cast<TestController*>(const_cast<void*>(clientInfo))->decideDestinationWithSuggestedFilename(download, suggestedFilename);
}

void TestController::downloadDidFinish(WKDownloadRef download, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->downloadDidFinish(download);
}

void TestController::downloadDidFail(WKDownloadRef download, WKErrorRef error, WKDataRef, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->downloadDidFail(download, error);
}

bool TestController::downloadDidReceiveServerRedirectToURL(WKDownloadRef download, WKURLResponseRef, WKURLRequestRef newRequest, const void* clientInfo)
{
    return static_cast<TestController*>(const_cast<void*>(clientInfo))->downloadDidReceiveServerRedirectToURL(download, newRequest);
}

void TestController::downloadDidStart(WKDownloadRef download)
{
    if (m_shouldLogDownloadCallbacks)
        protectedCurrentInvocation()->outputText("Download started.\n"_s);
}

WKStringRef TestController::decideDestinationWithSuggestedFilename(WKDownloadRef download, WKStringRef filename)
{
    auto suggestedFilename = toWTFString(filename);

    if (m_shouldLogDownloadCallbacks)
        protectedCurrentInvocation()->outputText(makeString("Downloading URL with suggested filename \""_s, suggestedFilename, "\"\n"_s));

    const char* dumpRenderTreeTemp = libraryPathForTesting();
    if (!dumpRenderTreeTemp)
        return nullptr;

    auto temporaryFolder = String::fromUTF8(dumpRenderTreeTemp);
    if (suggestedFilename.isEmpty())
        suggestedFilename = "Unknown"_s;
    
    auto destination = makeString(temporaryFolder, pathSeparator, suggestedFilename);
    if (auto downloadIndex = m_downloadIndex++)
        destination = makeString(destination, downloadIndex);
    if (FileSystem::fileExists(destination))
        FileSystem::deleteFile(destination);

    return toWK(destination).leakRef();
}

void TestController::downloadDidFinish(WKDownloadRef)
{
    RefPtr currentInvocation = m_currentInvocation;
    if (m_shouldLogDownloadSize)
        currentInvocation->outputText(makeString("Download size: "_s, m_downloadTotalBytesWritten.value_or(0), ".\n"_s));
    if (m_shouldLogDownloadExpectedSize)
        currentInvocation->outputText(makeString("Download expected size: "_s, m_downloadTotalBytesExpectedToWrite.value_or(0), ".\n"_s));
    if (m_shouldLogDownloadCallbacks)
        currentInvocation->outputText("Download completed.\n"_s);
    currentInvocation->notifyDownloadDone();
}

bool TestController::downloadDidReceiveServerRedirectToURL(WKDownloadRef, WKURLRequestRef request)
{
    auto url = adoptWK(WKURLRequestCopyURL(request));
    if (m_shouldLogDownloadCallbacks)
        protectedCurrentInvocation()->outputText(makeString("Download was redirected to \""_s, toWTFString(adoptWK(WKURLCopyString(url.get()))), "\".\n"_s));
    return true;
}

void TestController::downloadDidFail(WKDownloadRef, WKErrorRef error)
{
    RefPtr currentInvocation = m_currentInvocation;
    if (m_shouldLogDownloadCallbacks) {
        currentInvocation->outputText("Download failed.\n"_s);

        auto domain = toWTFString(adoptWK(WKErrorCopyDomain(error)));
        auto description = toWTFString(adoptWK(WKErrorCopyLocalizedDescription(error)));
        int code = WKErrorGetErrorCode(error);

        currentInvocation->outputText(makeString("Failed: "_s, domain, ", code="_s, code, ", description="_s, description, '\n'));
    }
    currentInvocation->notifyDownloadDone();
}

void TestController::receivedServiceWorkerConsoleMessage(const String& message)
{
    protectedCurrentInvocation()->outputText(makeString("Received ServiceWorker Console Message: "_s, message, '\n'));
}

void TestController::downloadDidReceiveAuthenticationChallenge(WKDownloadRef, WKAuthenticationChallengeRef authenticationChallenge, const void *clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveAuthenticationChallenge(nullptr, authenticationChallenge);
}

void TestController::downloadDidWriteData(long long totalBytesWritten, long long totalBytesExpectedToWrite)
{
    if (!m_shouldLogDownloadCallbacks)
        return;
    m_downloadTotalBytesWritten = totalBytesWritten;
    m_downloadTotalBytesExpectedToWrite = totalBytesExpectedToWrite;
}

void TestController::downloadDidWriteData(WKDownloadRef download, long long bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->downloadDidWriteData(totalBytesWritten, totalBytesExpectedToWrite);
}

void TestController::webProcessDidTerminate(WKProcessTerminationReason reason)
{
    if (protectedCurrentInvocation()->options().shouldIgnoreWebProcessTermination())
        return;

    // This function can be called multiple times when crash logs are being saved on Windows, so
    // ensure we only print the crashed message once.
    if (!m_didPrintWebProcessCrashedMessage) {
        pid_t pid = WKPageGetProcessIdentifier(m_mainWebView->page());
        fprintf(stderr, "%s terminated (pid %ld) for reason: %s\n", webProcessName().characters(), static_cast<long>(pid), terminationReasonToString(reason));
        if (reason == kWKProcessTerminationReasonRequestedByClient) {
            fflush(stderr);
            return;
        }

        fprintf(stderr, "#CRASHED - %s (pid %ld)\n", webProcessName().characters(), static_cast<long>(pid));
        fflush(stderr);
        m_didPrintWebProcessCrashedMessage = true;
    }

    if (m_shouldExitWhenAuxiliaryProcessCrashes)
        exitProcess(1);
}

void TestController::didBeginNavigationGesture(WKPageRef)
{
    m_beginSwipeCallbacks.notifyListeners();
}

void TestController::willEndNavigationGesture(WKPageRef, WKBackForwardListItemRef)
{
    m_willEndSwipeCallbacks.notifyListeners();
}

void TestController::didEndNavigationGesture(WKPageRef, WKBackForwardListItemRef)
{
    m_didEndSwipeCallbacks.notifyListeners();
}

void TestController::didRemoveNavigationGestureSnapshot(WKPageRef)
{
    m_didRemoveSwipeSnapshotCallbacks.notifyListeners();
}

void TestController::simulateWebNotificationClick(WKDataRef notificationID)
{
    m_webNotificationProvider.simulateWebNotificationClick(mainWebView()->page(), notificationID);
}

void TestController::simulateWebNotificationClickForServiceWorkerNotifications()
{
    m_webNotificationProvider.simulateWebNotificationClickForServiceWorkerNotifications();
}

void TestController::setGeolocationPermission(bool enabled)
{
    bool permissionChanged = false;
    if (!m_isGeolocationPermissionSet || m_isGeolocationPermissionAllowed != enabled)
        permissionChanged = true;

    m_isGeolocationPermissionSet = true;
    m_isGeolocationPermissionAllowed = enabled;
    decidePolicyForGeolocationPermissionRequestIfPossible();

    if (!permissionChanged)
        return;

    for (auto& originString : m_geolocationPermissionQueryOrigins)
        WKPagePermissionChanged(toWK("geolocation").get(), toWK(originString).get());
}

void TestController::setScreenWakeLockPermission(bool enabled)
{
    m_screenWakeLockPermission = enabled;
}

void TestController::setMockGeolocationPosition(double latitude, double longitude, double accuracy, std::optional<double> altitude, std::optional<double> altitudeAccuracy, std::optional<double> heading, std::optional<double> speed, std::optional<double> floorLevel)
{
    m_geolocationProvider->setPosition(latitude, longitude, accuracy, altitude, altitudeAccuracy, heading, speed, floorLevel);
}

void TestController::setMockGeolocationPositionUnavailableError(WKStringRef errorMessage)
{
    m_geolocationProvider->setPositionUnavailableError(errorMessage);
}

void TestController::handleGeolocationPermissionRequest(WKGeolocationPermissionRequestRef geolocationPermissionRequest)
{
    m_geolocationPermissionRequests.append(geolocationPermissionRequest);
    decidePolicyForGeolocationPermissionRequestIfPossible();
}

bool TestController::isGeolocationProviderActive() const
{
    return m_geolocationProvider->isActive();
}

void TestController::setCameraPermission(bool enabled)
{
    m_canDecideUserMediaRequest = true;
    m_isCameraPermissionAllowed = enabled;
    decidePolicyForUserMediaPermissionRequestIfPossible();
}

void TestController::setMicrophonePermission(bool enabled)
{
    m_canDecideUserMediaRequest = true;
    m_isMicrophonePermissionAllowed = enabled;
    decidePolicyForUserMediaPermissionRequestIfPossible();
}

void TestController::resetUserMediaPermission()
{
    m_requestCount = 0;
    m_canDecideUserMediaRequest = true;
    m_isCameraPermissionAllowed = { };
    m_isMicrophonePermissionAllowed = { };
}

void TestController::setShouldDismissJavaScriptAlertsAsynchronously(bool value)
{
    m_shouldDismissJavaScriptAlertsAsynchronously = value;
}

void TestController::handleJavaScriptAlert(WKStringRef alertText, WKPageRunJavaScriptAlertResultListenerRef listener)
{
    protectedCurrentInvocation()->outputText(makeString("ALERT:"_s, addLeadingSpaceStripTrailingSpacesAddNewline(toWTFString(alertText))));

    if (!m_shouldDismissJavaScriptAlertsAsynchronously) {
        WKPageRunJavaScriptAlertResultListenerCall(listener);
        return;
    }

    WKRetain(listener);
    callOnMainThread([listener] {
        WKPageRunJavaScriptAlertResultListenerCall(listener);
        WKRelease(listener);
    });
}

void TestController::handleJavaScriptPrompt(WKStringRef message, WKStringRef defaultValue, WKPageRunJavaScriptPromptResultListenerRef listener)
{
    protectedCurrentInvocation()->outputText(makeString("PROMPT: "_s, toWTFString(message), ", default text:"_s, addLeadingSpaceStripTrailingSpacesAddNewline(toWTFString(defaultValue))));

    WKPageRunJavaScriptPromptResultListenerCall(listener, defaultValue);
}

void TestController::handleJavaScriptConfirm(WKStringRef message, WKPageRunJavaScriptConfirmResultListenerRef listener)
{
    protectedCurrentInvocation()->outputText(makeString("CONFIRM:"_s, addLeadingSpaceStripTrailingSpacesAddNewline(toWTFString(message))));

    WKPageRunJavaScriptConfirmResultListenerCall(listener, true);
}

bool TestController::handleDeviceOrientationAndMotionAccessRequest(WKSecurityOriginRef origin, WKFrameInfoRef frame)
{
    auto frameOrigin = adoptWK(WKFrameInfoCopySecurityOrigin(frame));
    protectedCurrentInvocation()->outputText(makeString("Received device orientation & motion access request for top level origin \""_s, originUserVisibleName(origin), "\", with frame origin \""_s, originUserVisibleName(frameOrigin.get()), "\".\n"_s));
    return m_shouldAllowDeviceOrientationAndMotionAccess;
}

void TestController::handleUserMediaPermissionRequest(WKFrameRef frame, WKSecurityOriginRef userMediaDocumentOrigin, WKSecurityOriginRef topLevelDocumentOrigin, WKUserMediaPermissionRequestRef request)
{
    m_requestCount++;
    m_userMediaPermissionRequests.append(request);
    decidePolicyForUserMediaPermissionRequestIfPossible();
}

void TestController::delayUserMediaRequestDecision()
{
    m_canDecideUserMediaRequest = false;
}

unsigned TestController::userMediaPermissionRequestCount()
{
    return m_requestCount;
}

void TestController::resetUserMediaPermissionRequestCount()
{
    m_requestCount = 0;
}

void TestController::decidePolicyForUserMediaPermissionRequestIfPossible()
{
    if (!m_canDecideUserMediaRequest)
        return;

    for (WKRetainPtr request : m_userMediaPermissionRequests) {
        if (m_isCameraPermissionAllowed && WKUserMediaPermissionRequestRequiresCameraCapture(request.get()) && !*m_isCameraPermissionAllowed) {
            WKUserMediaPermissionRequestDeny(request.get(), kWKPermissionDenied);
            continue;
        }

        if (m_isMicrophonePermissionAllowed && WKUserMediaPermissionRequestRequiresMicrophoneCapture(request.get()) && !*m_isMicrophonePermissionAllowed) {
            WKUserMediaPermissionRequestDeny(request.get(), kWKPermissionDenied);
            continue;
        }

        auto audioDeviceUIDs = adoptWK(WKUserMediaPermissionRequestAudioDeviceUIDs(request.get()));
        auto videoDeviceUIDs = adoptWK(WKUserMediaPermissionRequestVideoDeviceUIDs(request.get()));

        if (!WKUserMediaPermissionRequestRequiresDisplayCapture(request.get()) && !WKArrayGetSize(videoDeviceUIDs.get()) && !WKArrayGetSize(audioDeviceUIDs.get())) {
            WKUserMediaPermissionRequestDeny(request.get(), kWKNoConstraints);
            continue;
        }

        WKRetainPtr<WKStringRef> videoDeviceUID;
        if (WKArrayGetSize(videoDeviceUIDs.get()))
            videoDeviceUID = reinterpret_cast<WKStringRef>(WKArrayGetItemAtIndex(videoDeviceUIDs.get(), 0));
        else
            videoDeviceUID = toWK("");

        WKRetainPtr<WKStringRef> audioDeviceUID;
        if (WKArrayGetSize(audioDeviceUIDs.get()))
            audioDeviceUID = reinterpret_cast<WKStringRef>(WKArrayGetItemAtIndex(audioDeviceUIDs.get(), 0));
        else
            audioDeviceUID = toWK("");

        WKUserMediaPermissionRequestAllow(request.get(), audioDeviceUID.get(), videoDeviceUID.get());
    }
    m_userMediaPermissionRequests.clear();
}

void TestController::setCustomPolicyDelegate(bool enabled, bool permissive)
{
    m_policyDelegateEnabled = enabled;
    m_policyDelegatePermissive = permissive;
}

void TestController::decidePolicyForGeolocationPermissionRequestIfPossible()
{
    if (!m_isGeolocationPermissionSet)
        return;

    for (size_t i = 0; i < m_geolocationPermissionRequests.size(); ++i) {
        WKGeolocationPermissionRequestRef permissionRequest = m_geolocationPermissionRequests[i].get();
        if (m_isGeolocationPermissionAllowed)
            WKGeolocationPermissionRequestAllow(permissionRequest);
        else
            WKGeolocationPermissionRequestDeny(permissionRequest);
    }
    m_geolocationPermissionRequests.clear();
}

void TestController::decidePolicyForNotificationPermissionRequest(WKPageRef page, WKSecurityOriginRef origin, WKNotificationPermissionRequestRef request, const void*)
{
    TestController::singleton().decidePolicyForNotificationPermissionRequest(page, origin, request);
}

void TestController::decidePolicyForNotificationPermissionRequest(WKPageRef, WKSecurityOriginRef origin, WKNotificationPermissionRequestRef request)
{
    auto originName = originUserVisibleName(origin);
    auto securityOriginString = adoptWK(WKSecurityOriginCopyToString(origin));
    auto permissionState = m_webNotificationProvider.permissionState(origin);

    if (permissionState && !permissionState.value()) {
        WKNotificationPermissionRequestDeny(request);
        return;
    }

    if (m_notificationOriginsToDenyOnPrompt.contains(originName)) {
        m_webNotificationProvider.setPermission(toWTFString(securityOriginString.get()), false);
        WKNotificationPermissionRequestDeny(request);
        return;
    }

    m_webNotificationProvider.setPermission(toWTFString(securityOriginString.get()), true);
    WKNotificationPermissionRequestAllow(request);
}

void TestController::unavailablePluginButtonClicked(WKPageRef, WKPluginUnavailabilityReason, WKDictionaryRef, const void*)
{
    printf("MISSING PLUGIN BUTTON PRESSED\n");
}

void TestController::decidePolicyForNavigationAction(WKPageRef page, WKNavigationActionRef navigationAction, WKFramePolicyListenerRef listener, WKTypeRef, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->decidePolicyForNavigationAction(page, navigationAction, listener);
}

static ASCIILiteral navigationTypeToString(WKFrameNavigationType type)
{
    switch (type) {
    case kWKFrameNavigationTypeLinkClicked:
        return "link clicked"_s;
    case kWKFrameNavigationTypeFormSubmitted:
        return "form submitted"_s;
    case kWKFrameNavigationTypeBackForward:
        return "back/forward"_s;
    case kWKFrameNavigationTypeReload:
        return "reload"_s;
    case kWKFrameNavigationTypeFormResubmitted:
        return "form resubmitted"_s;
    case kWKFrameNavigationTypeOther:
        return "other"_s;
    }
    return "illegal value"_s;
}

void TestController::decidePolicyForNavigationAction(WKPageRef page, WKNavigationActionRef navigationAction, WKFramePolicyListenerRef listener)
{
    WKRetainPtr<WKFramePolicyListenerRef> retainedListener { listener };
    WKRetainPtr<WKNavigationActionRef> retainedNavigationAction { navigationAction };
    const bool shouldIgnore { m_policyDelegateEnabled && !m_policyDelegatePermissive };

    auto globalPrivacyControlEnabled = m_globalPrivacyControlEnabled;
    if (!globalPrivacyControlEnabled && m_currentInvocation && protectedCurrentInvocation()->options().globalPrivacyControl())
        globalPrivacyControlEnabled = false;

    auto decisionFunction = [
        shouldIgnore,
        retainedListener,
        retainedNavigationAction,
        shouldSwapToEphemeralSessionOnNextNavigation = m_shouldSwapToEphemeralSessionOnNextNavigation,
        shouldSwapToDefaultSessionOnNextNavigation = m_shouldSwapToDefaultSessionOnNextNavigation,
        globalPrivacyControlEnabled,
        page = WKRetainPtr { page }
    ] {
        if (shouldIgnore)
            WKFramePolicyListenerIgnore(retainedListener.get());
        else if (WKNavigationActionShouldPerformDownload(retainedNavigationAction.get()))
            WKFramePolicyListenerDownload(retainedListener.get());
        else {
            if (shouldSwapToEphemeralSessionOnNextNavigation || shouldSwapToDefaultSessionOnNextNavigation) {
                ASSERT(shouldSwapToEphemeralSessionOnNextNavigation != shouldSwapToDefaultSessionOnNextNavigation);
                WKRetainPtr policies = adoptWK(WKWebsitePoliciesCreate());
                WKWebsitePoliciesSetAllowsJSHandleCreationInPageWorld(policies.get(), true);
                if (globalPrivacyControlEnabled)
                    WKWebsitePoliciesSetGlobalPrivacyControlEnabled(policies.get(), *globalPrivacyControlEnabled);
                WKRetainPtr<WKWebsiteDataStoreRef> newSession = TestController::defaultWebsiteDataStore();
                if (shouldSwapToEphemeralSessionOnNextNavigation)
                    newSession = adoptWK(WKWebsiteDataStoreCreateNonPersistentDataStore());
                WKWebsitePoliciesSetDataStore(policies.get(), newSession.get());
                WKFramePolicyListenerUseWithPolicies(retainedListener.get(), policies.get());
            } else {
                WKRetainPtr policies = WKPageConfigurationGetDefaultWebsitePolicies(adoptWK(WKPageCopyPageConfiguration(page.get())).get());
                WKWebsitePoliciesSetAllowsJSHandleCreationInPageWorld(policies.get(), true);
                if (globalPrivacyControlEnabled)
                    WKWebsitePoliciesSetGlobalPrivacyControlEnabled(policies.get(), *globalPrivacyControlEnabled);
                WKFramePolicyListenerUseWithPolicies(retainedListener.get(), policies.get());
            }
        }
    };
    m_shouldSwapToEphemeralSessionOnNextNavigation = false;
    m_shouldSwapToDefaultSessionOnNextNavigation = false;

    auto request = adoptWK(WKNavigationActionCopyRequest(navigationAction));
    auto targetFrame = adoptWK(WKNavigationActionCopyTargetFrameInfo(navigationAction));

    // Block access to external URLs in subframe navigations.
    // The injected bundle's willSendRequestForFrame callback cannot emit the console message because
    // WKBundleFrameGetJavaScriptContext returns null for provisional frames in the new process when
    // site isolation is enabled.
    if (targetFrame && !WKFrameInfoGetIsMainFrame(targetFrame.get())) {
        if (auto url = adoptWK(WKURLRequestCopyURL(request.get()))) {
            auto host = adoptWK(WKURLCopyHostName(url.get()));
            auto scheme = adoptWK(WKURLCopyScheme(url.get()));
            if (isExternalURLBlockable(host.get(), scheme.get())) {
                bool mainFrameIsExternal = false;
                WKFrameRef mainFrame = WKPageGetMainFrame(page);
                if (mainFrame) {
                    auto mainFrameURL = adoptWK(WKFrameCopyURL(mainFrame));
                    if (!mainFrameURL || WKStringIsEqualToUTF8CString(adoptWK(WKURLCopyString(mainFrameURL.get())).get(), "about:blank"))
                        mainFrameURL = adoptWK(WKFrameCopyProvisionalURL(mainFrame));
                    mainFrameIsExternal = isMainFrameURLExternal(mainFrameURL.get());
                }
                if (!mainFrameIsExternal && !m_allowedHosts.count(toSTD(host))) {
                    auto urlString = adoptWK(WKURLCopyString(url.get()));
                    auto blockedURL = sanitizeExternalURL(urlString.get());
                    auto message = makeString("CONSOLE MESSAGE: Blocked access to external URL "_s, blockedURL, '\n');
                    if (protectedCurrentInvocation()->shouldDumpJSConsoleLogInStdErr()) {
                        if (auto string = message.tryGetUTF8())
                            SAFE_FPRINTF(stderr, "%s", *string);
                        else
                            SAFE_FPRINTF(stderr, "Out of memory\n");
                    } else
                        protectedCurrentInvocation()->outputText(WTF::move(message));
                    WKFramePolicyListenerIgnore(listener);
                    return;
                }
            }
        }
    }

    if (targetFrame && m_dumpPolicyDelegateCallbacks) {
        protectedCurrentInvocation()->outputText(makeString(" - decidePolicyForNavigationAction\n"_s, string(request.get(), page),
            " is main frame - "_s, targetFrame && WKFrameInfoGetIsMainFrame(targetFrame.get()) ? "yes"_s : "no"_s,
            " should open URLs externally - "_s, WKNavigationActionGetShouldOpenExternalSchemes(navigationAction) ? "yes"_s : "no"_s, '\n'));
    }

    if (m_policyDelegateEnabled) {
        auto url = adoptWK(WKURLRequestCopyURL(request.get()));
        if (!url) {
            WKFramePolicyListenerUse(listener);
            return;
        }
        auto urlScheme = adoptWK(WKURLCopyScheme(url.get()));

        StringBuilder stringBuilder;
        stringBuilder.append("Policy delegate: attempt to load "_s);
        if (isLocalFileScheme(urlScheme.get()))
            stringBuilder.append(toWTFString(adoptWK(WKURLCopyLastPathComponent(url.get())).get()));
        else
            stringBuilder.append(toWTFString(adoptWK(WKURLCopyString(url.get())).get()));
        stringBuilder.append(" with navigation type \'"_s, navigationTypeToString(WKNavigationActionGetNavigationType(navigationAction)), '\'');
        stringBuilder.append('\n');
        protectedCurrentInvocation()->outputText(stringBuilder.toString());
        if (!m_skipPolicyDelegateNotifyDone)
            WKPagePostMessageToInjectedBundle(mainWebView()->page(), toWK("NotifyDone").get(), nullptr);
    }

    if (m_shouldDecideNavigationPolicyAfterDelay)
        RunLoop::mainSingleton().dispatch(WTF::move(decisionFunction));
    else
        decisionFunction();
}

void TestController::decidePolicyForNavigationResponse(WKPageRef, WKNavigationResponseRef navigationResponse, WKFramePolicyListenerRef listener, WKTypeRef, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->decidePolicyForNavigationResponse(navigationResponse, listener);
}

void TestController::decidePolicyForNavigationResponse(WKNavigationResponseRef navigationResponse, WKFramePolicyListenerRef listener)
{
    WKRetainPtr<WKNavigationResponseRef> retainedNavigationResponse { navigationResponse };
    WKRetainPtr<WKFramePolicyListenerRef> retainedListener { listener };
    auto response = adoptWK(WKNavigationResponseCopyResponse(navigationResponse));

    bool shouldDownloadUndisplayableMIMETypes = m_shouldDownloadUndisplayableMIMETypes;
    bool responseIsAttachment = WKURLResponseIsAttachment(response.get());
    auto decisionFunction = [shouldDownloadUndisplayableMIMETypes, retainedNavigationResponse, retainedListener, responseIsAttachment, shouldDownloadContentDispositionAttachments = m_shouldDownloadContentDispositionAttachments]() {
        if (responseIsAttachment && shouldDownloadContentDispositionAttachments) {
            WKFramePolicyListenerDownload(retainedListener.get());
            return;
        }

        // Even though Response was already checked by WKBundlePagePolicyClient, the check did not include plugins
        // so we have to re-check again.
        if (WKNavigationResponseCanShowMIMEType(retainedNavigationResponse.get())) {
            WKFramePolicyListenerUse(retainedListener.get());
            return;
        }

        if (shouldDownloadUndisplayableMIMETypes)
            WKFramePolicyListenerDownload(retainedListener.get());
        else
            WKFramePolicyListenerIgnore(retainedListener.get());
    };

    if (m_policyDelegateEnabled) {
        if (responseIsAttachment)
            protectedCurrentInvocation()->outputText(makeString("Policy delegate: resource is an attachment, suggested file name \'"_s, toWTFString(adoptWK(WKURLResponseCopySuggestedFilename(response.get())).get()), "'\n"_s));
    }

    if (m_shouldDecideResponsePolicyAfterDelay)
        RunLoop::mainSingleton().dispatch(WTF::move(decisionFunction));
    else
        decisionFunction();
}

void TestController::didNavigateWithNavigationData(WKContextRef, WKPageRef, WKNavigationDataRef navigationData, WKFrameRef frame, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->didNavigateWithNavigationData(navigationData, frame);
}

void TestController::didNavigateWithNavigationData(WKNavigationDataRef navigationData, WKFrameRef)
{
    if (m_state != RunningTest)
        return;

    if (!m_shouldLogHistoryClientCallbacks)
        return;

    auto url = adoptWK(WKNavigationDataCopyURL(navigationData));
    auto urlString = toWTFString(adoptWK(WKURLCopyString(url.get())));
    auto title = toWTFString(adoptWK(WKNavigationDataCopyTitle(navigationData)));
    auto request = adoptWK(WKNavigationDataCopyOriginalRequest(navigationData));
    auto method = toWTFString(adoptWK(WKURLRequestCopyHTTPMethod(request.get())));

    // FIXME: Determine whether the navigation was successful / a client redirect rather than hard-coding the message here.
    protectedCurrentInvocation()->outputText(makeString("WebView navigated to url \""_s, urlString, "\" with title \""_s, title, "\" with HTTP equivalent method \""_s, method,
        "\".  The navigation was successful and was not a client redirect.\n"_s));
}

void TestController::didPerformClientRedirect(WKContextRef, WKPageRef, WKURLRef sourceURL, WKURLRef destinationURL, WKFrameRef frame, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->didPerformClientRedirect(sourceURL, destinationURL, frame);
}

void TestController::didPerformClientRedirect(WKURLRef sourceURL, WKURLRef destinationURL, WKFrameRef)
{
    if (m_state != RunningTest)
        return;

    if (!m_shouldLogHistoryClientCallbacks)
        return;

    auto source = toWTFString(adoptWK(WKURLCopyString(sourceURL)));
    auto destination = toWTFString(adoptWK(WKURLCopyString(destinationURL)));

    protectedCurrentInvocation()->outputText(makeString("WebView performed a client redirect from \""_s, source, "\" to \""_s, destination, "\".\n"_s));
}

void TestController::didPerformServerRedirect(WKContextRef, WKPageRef, WKURLRef sourceURL, WKURLRef destinationURL, WKFrameRef frame, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->didPerformServerRedirect(sourceURL, destinationURL, frame);
}

void TestController::didPerformServerRedirect(WKURLRef sourceURL, WKURLRef destinationURL, WKFrameRef)
{
    if (m_state != RunningTest)
        return;

    if (!m_shouldLogHistoryClientCallbacks)
        return;

    auto source = toWTFString(adoptWK(WKURLCopyString(sourceURL)));
    auto destination = toWTFString(adoptWK(WKURLCopyString(destinationURL)));

    protectedCurrentInvocation()->outputText(makeString("WebView performed a server redirect from \""_s, source, "\" to \""_s, destination, "\".\n"_s));
}

void TestController::didUpdateHistoryTitle(WKContextRef, WKPageRef, WKStringRef title, WKURLRef URL, WKFrameRef frame, const void* clientInfo)
{
    static_cast<TestController*>(const_cast<void*>(clientInfo))->didUpdateHistoryTitle(title, URL, frame);
}

void TestController::didUpdateHistoryTitle(WKStringRef title, WKURLRef URL, WKFrameRef)
{
    if (m_state != RunningTest)
        return;

    if (!m_shouldLogHistoryClientCallbacks)
        return;

    auto urlString = toWTFString(adoptWK(WKURLCopyString(URL)));
    protectedCurrentInvocation()->outputText(makeString("WebView updated the title for history URL \""_s, urlString, "\" to \""_s, toWTFString(title), "\".\n"_s));
}

void TestController::setNavigationGesturesEnabled(bool value)
{
    m_mainWebView->setNavigationGesturesEnabled(value);
}

void TestController::setIgnoresViewportScaleLimits(bool ignoresViewportScaleLimits)
{
    WKPageSetIgnoresViewportScaleLimits(m_mainWebView->page(), ignoresViewportScaleLimits);
}

void TestController::setUseDarkAppearanceForTesting(bool useDarkAppearance)
{
    WKPageSetUseDarkAppearanceForTesting(m_mainWebView->page(), useDarkAppearance);
}

void TestController::terminateGPUProcess()
{
    WKContextTerminateGPUProcess(context());
}

void TestController::terminateNetworkProcess()
{
    WKWebsiteDataStoreTerminateNetworkProcess(websiteDataStore());
}

void TestController::terminateServiceWorkers()
{
    WKContextTerminateServiceWorkers(context());
}

#if !PLATFORM(COCOA)
void TestController::platformWillRunTest(const TestInvocation&)
{
}

void TestController::platformInitializeDataStore(WKPageConfigurationRef configuration, const TestOptions& options)
{
    if (!options.useEphemeralSession())
        WKPageConfigurationSetWebsiteDataStore(configuration, defaultWebsiteDataStore());

    m_websiteDataStore = WKPageConfigurationGetWebsiteDataStore(configuration);
}

void TestController::platformCreateWebView(WKPageConfigurationRef configuration, const TestOptions& options)
{
    m_mainWebView = makeUnique<PlatformWebView>(configuration, options);
}

UniqueRef<PlatformWebView> TestController::platformCreateOtherPage(PlatformWebView* parentView, WKPageConfigurationRef configuration, const TestOptions& options)
{
    return makeUniqueRef<PlatformWebView>(configuration, options);
}

unsigned TestController::imageCountInGeneralPasteboard() const
{
    return 0;
}

void TestController::removeAllSessionCredentials(CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    completionHandler(nullptr);
}

bool TestController::didLoadAppInitiatedRequest()
{
    return false;
}

bool TestController::didLoadNonAppInitiatedRequest()
{
    return false;
}

void TestController::clearAppPrivacyReportTestingData()
{
}

#endif // !PLATFORM(COCOA)

void TestController::setPageScaleFactor(float scaleFactor, int x, int y, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKPageSetPageScaleFactorForTesting(mainWebView()->page(), scaleFactor, WKPointMake(x, y), completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::getAllStorageAccessEntries(CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    auto context = completionHandler.leak();
    WKWebsiteDataStoreGetAllStorageAccessEntries(websiteDataStore(), m_mainWebView->page(), context, [] (void* context, WKArrayRef domainList) {
        auto completionHandler = WTF::adopt(static_cast<CompletionHandler<void(WKTypeRef)>::Impl*>(context));
        completionHandler(domainList);
    });
}

void TestController::loadedSubresourceDomains(CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKPageLoadedSubresourceDomains(m_mainWebView->page(), [] (WKArrayRef domains, void* context) {
        auto completionHandler = WTF::adopt(static_cast<CompletionHandler<void(WKTypeRef)>::Impl*>(context));
        completionHandler(domains);
    }, completionHandler.leak());
}

void TestController::clearLoadedSubresourceDomains()
{
    WKPageClearLoadedSubresourceDomains(m_mainWebView->page());
}

void TestController::reloadFromOrigin()
{
    WKPageReloadFromOrigin(m_mainWebView->page());
}

struct GenericVoidContext {
    explicit GenericVoidContext(TestController& controller)
        : testController(controller)
    {
    }

    TestController& testController;
    bool done { false };
};

static void genericVoidCallback(void* userData)
{
    auto* context = static_cast<GenericVoidContext*>(userData);
    context->done = true;
    context->testController.notifyDone();
}

struct ClearDOMCacheCallbackContext {
    explicit ClearDOMCacheCallbackContext(TestController& controller)
        : testController(controller)
    {
    }

    TestController& testController;
    bool done { false };
};

static void clearDOMCacheCallback(void* userData)
{
    auto* context = static_cast<ClearDOMCacheCallbackContext*>(userData);
    context->done = true;
    context->testController.notifyDone();
}

void TestController::clearDOMCache(WKStringRef origin)
{
    ClearDOMCacheCallbackContext context(*this);

    auto cacheOrigin = adoptWK(WKSecurityOriginCreateFromString(origin));
    WKWebsiteDataStoreRemoveFetchCacheForOrigin(websiteDataStore(), cacheOrigin.get(), &context, clearDOMCacheCallback);
    runUntil(context.done, noTimeout);
}

void TestController::clearDOMCaches()
{
    ClearDOMCacheCallbackContext context(*this);

    WKWebsiteDataStoreRemoveAllFetchCaches(websiteDataStore(), &context, clearDOMCacheCallback);
    runUntil(context.done, noTimeout);
}

void TestController::clearMemoryCache()
{
    ClearDOMCacheCallbackContext context(*this);

    WKWebsiteDataStoreRemoveMemoryCaches(websiteDataStore(), &context, clearDOMCacheCallback);
    runUntil(context.done, noTimeout);
}

struct StorageVoidCallbackContext {
    explicit StorageVoidCallbackContext(TestController& controller)
        : testController(controller)
    {
    }

    TestController& testController;
    bool done { false };
};

static void StorageVoidCallback(void* userData)
{
    auto* context = static_cast<StorageVoidCallbackContext*>(userData);
    context->done = true;
    context->testController.notifyDone();
}

void TestController::syncLocalStorage()
{
    StorageVoidCallbackContext context(*this);
    WKWebsiteDataStoreSyncLocalStorage(TestController::websiteDataStore(), &context, StorageVoidCallback);
    runUntil(context.done, noTimeout);
}

void TestController::resetQuota()
{
    StorageVoidCallbackContext context(*this);
    WKWebsiteDataStoreResetQuota(TestController::websiteDataStore(), &context, StorageVoidCallback);
    runUntil(context.done, noTimeout);
}

void TestController::resetStoragePersistedState()
{
    StorageVoidCallbackContext context(*this);
    WKWebsiteDataStoreResetStoragePersistedState(TestController::websiteDataStore(), &context, StorageVoidCallback);
    runUntil(context.done, noTimeout);
}

void TestController::clearStorage()
{
    StorageVoidCallbackContext context(*this);
    WKWebsiteDataStoreClearStorage(TestController::websiteDataStore(), &context, StorageVoidCallback);
    runUntil(context.done, noTimeout);
}

void TestController::setOriginQuotaRatioEnabled(bool enabled)
{
    StorageVoidCallbackContext context(*this);
    WKWebsiteDataStoreSetOriginQuotaRatioEnabled(websiteDataStore(), enabled, &context, StorageVoidCallback);
    runUntil(context.done, noTimeout);
}

struct FetchCacheOriginsCallbackContext {
    FetchCacheOriginsCallbackContext(TestController& controller, WKStringRef origin)
        : testController(controller)
        , origin(origin)
    {
    }

    TestController& testController;
    WKStringRef origin;

    bool done { false };
    bool result { false };
};

static void fetchCacheOriginsCallback(WKArrayRef origins, void* userData)
{
    auto* context = static_cast<FetchCacheOriginsCallbackContext*>(userData);
    context->done = true;

    auto size = WKArrayGetSize(origins);
    for (size_t index = 0; index < size && !context->result; ++index) {
        WKSecurityOriginRef securityOrigin = reinterpret_cast<WKSecurityOriginRef>(WKArrayGetItemAtIndex(origins, index));
        if (WKStringIsEqual(context->origin, adoptWK(WKSecurityOriginCopyToString(securityOrigin)).get()))
            context->result = true;
    }
    context->testController.notifyDone();
}

bool TestController::hasDOMCache(WKStringRef origin)
{
    FetchCacheOriginsCallbackContext context(*this, origin);
    WKWebsiteDataStoreGetFetchCacheOrigins(websiteDataStore(), &context, fetchCacheOriginsCallback);
    runUntil(context.done, noTimeout);
    return context.result;
}

struct FetchCacheSizeForOriginCallbackContext {
    explicit FetchCacheSizeForOriginCallbackContext(TestController& controller)
        : testController(controller)
    {
    }

    TestController& testController;

    bool done { false };
    uint64_t result { 0 };
};

static void fetchCacheSizeForOriginCallback(uint64_t size, void* userData)
{
    auto* context = static_cast<FetchCacheSizeForOriginCallbackContext*>(userData);
    context->done = true;
    context->result = size;
    context->testController.notifyDone();
}

uint64_t TestController::domCacheSize(WKStringRef origin)
{
    FetchCacheSizeForOriginCallbackContext context(*this);
    WKWebsiteDataStoreGetFetchCacheSizeForOrigin(websiteDataStore(), origin, &context, fetchCacheSizeForOriginCallback);
    runUntil(context.done, noTimeout);
    return context.result;
}

#if !PLATFORM(COCOA)
void TestController::setAllowStorageQuotaIncrease(bool value)
{
    m_allowStorageQuotaIncrease = value;
}

void TestController::setQuota(uint64_t quota)
{
    m_quota = quota;
}

unsigned long long TestController::decideStorageQuota(unsigned long long currentQuota, unsigned long long currentUsage, unsigned long long spaceRequired)
{
    auto totalSpaceRequired = currentUsage + spaceRequired;
    if (m_allowStorageQuotaIncrease || totalSpaceRequired <= m_quota)
        return totalSpaceRequired;

    // Deny the request by leaving the quota unchanged.
    return currentQuota;
}

bool TestController::isDoingMediaCapture() const
{
    return false;
}
#endif

struct ResourceStatisticsCallbackContext {
    explicit ResourceStatisticsCallbackContext(TestController& controller)
        : testController(controller)
    {
    }

    TestController& testController;
    bool done { false };
    bool result { false };
    WKRetainPtr<WKStringRef> resourceLoadStatisticsRepresentation;
};

static void resourceStatisticsStringResultCallback(WKStringRef resourceLoadStatisticsRepresentation, void* userData)
{
    auto* context = static_cast<ResourceStatisticsCallbackContext*>(userData);
    context->resourceLoadStatisticsRepresentation = resourceLoadStatisticsRepresentation;
    context->done = true;
    context->testController.notifyDone();
}

static void resourceStatisticsVoidResultCallback(void* userData)
{
    auto* context = static_cast<ResourceStatisticsCallbackContext*>(userData);
    context->done = true;
    context->testController.notifyDone();
}

static void resourceStatisticsBooleanResultCallback(bool result, void* userData)
{
    auto* context = static_cast<ResourceStatisticsCallbackContext*>(userData);
    context->result = result;
    context->done = true;
    context->testController.notifyDone();
}

void TestController::clearStatisticsDataForDomain(WKStringRef domain)
{
    ResourceStatisticsCallbackContext context(*this);

    WKWebsiteDataStoreRemoveITPDataForDomain(websiteDataStore(), domain, &context, resourceStatisticsVoidResultCallback);
    runUntil(context.done, noTimeout);
}

bool TestController::doesStatisticsDomainIDExistInDatabase(unsigned domainID)
{
    ResourceStatisticsCallbackContext context(*this);
    WKWebsiteDataStoreDoesStatisticsDomainIDExistInDatabase(websiteDataStore(), domainID, &context, resourceStatisticsBooleanResultCallback);
    runUntil(context.done, noTimeout);
    return context.result;
}

void TestController::setStatisticsEnabled(bool value)
{
    WKWebsiteDataStoreSetResourceLoadStatisticsEnabled(websiteDataStore(), value);
}

bool TestController::isStatisticsEphemeral()
{
    ResourceStatisticsCallbackContext context(*this);
    WKWebsiteDataStoreIsStatisticsEphemeral(websiteDataStore(), &context, resourceStatisticsBooleanResultCallback);
    runUntil(context.done, noTimeout);
    return context.result;
}

void TestController::setStatisticsDebugMode(bool value, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreSetResourceLoadStatisticsDebugModeWithCompletionHandler(websiteDataStore(), value, completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::setStatisticsPrevalentResourceForDebugMode(WKStringRef hostName, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreSetResourceLoadStatisticsPrevalentResourceForDebugMode(websiteDataStore(), hostName, completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::setStatisticsLastSeen(WKStringRef host, double seconds, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreSetStatisticsLastSeen(websiteDataStore(), host, seconds, completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::setStatisticsMergeStatistic(WKStringRef host, WKStringRef topFrameDomain1, WKStringRef topFrameDomain2, double lastSeen, bool hadUserInteraction, double mostRecentUserInteraction, bool isGrandfathered, bool isPrevalent, bool isVeryPrevalent, int dataRecordsRemoved, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreSetStatisticsMergeStatistic(websiteDataStore(), host, topFrameDomain1, topFrameDomain2, lastSeen, hadUserInteraction, mostRecentUserInteraction, isGrandfathered, isPrevalent, isVeryPrevalent, dataRecordsRemoved, completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::setStatisticsExpiredStatistic(WKStringRef host, unsigned numberOfOperatingDaysPassed, bool hadUserInteraction, bool isScheduledForAllButCookieDataRemoval, bool isPrevalent, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreSetStatisticsExpiredStatistic(websiteDataStore(), host, numberOfOperatingDaysPassed, hadUserInteraction, isScheduledForAllButCookieDataRemoval, isPrevalent, completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::setStatisticsPrevalentResource(WKStringRef host, bool value, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreSetStatisticsPrevalentResource(websiteDataStore(), host, value, completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::setStatisticsVeryPrevalentResource(WKStringRef host, bool value, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreSetStatisticsVeryPrevalentResource(websiteDataStore(), host, value, completionHandler.leak(), adoptAndCallCompletionHandler);
}
    
String TestController::dumpResourceLoadStatistics()
{
    ResourceStatisticsCallbackContext context(*this);
    WKWebsiteDataStoreDumpResourceLoadStatistics(websiteDataStore(), &context, resourceStatisticsStringResultCallback);
    runUntil(context.done, noTimeout);
    return toWTFString(context.resourceLoadStatisticsRepresentation.get());
}

bool TestController::isStatisticsPrevalentResource(WKStringRef host)
{
    ResourceStatisticsCallbackContext context(*this);
    WKWebsiteDataStoreIsStatisticsPrevalentResource(websiteDataStore(), host, &context, resourceStatisticsBooleanResultCallback);
    runUntil(context.done, noTimeout);
    return context.result;
}

bool TestController::isStatisticsVeryPrevalentResource(WKStringRef host)
{
    ResourceStatisticsCallbackContext context(*this);
    WKWebsiteDataStoreIsStatisticsVeryPrevalentResource(websiteDataStore(), host, &context, resourceStatisticsBooleanResultCallback);
    runUntil(context.done, noTimeout);
    return context.result;
}

bool TestController::isStatisticsRegisteredAsSubresourceUnder(WKStringRef subresourceHost, WKStringRef topFrameHost)
{
    ResourceStatisticsCallbackContext context(*this);
    WKWebsiteDataStoreIsStatisticsRegisteredAsSubresourceUnder(websiteDataStore(), subresourceHost, topFrameHost, &context, resourceStatisticsBooleanResultCallback);
    runUntil(context.done, noTimeout);
    return context.result;
}

bool TestController::isStatisticsRegisteredAsSubFrameUnder(WKStringRef subFrameHost, WKStringRef topFrameHost)
{
    ResourceStatisticsCallbackContext context(*this);
    WKWebsiteDataStoreIsStatisticsRegisteredAsSubFrameUnder(websiteDataStore(), subFrameHost, topFrameHost, &context, resourceStatisticsBooleanResultCallback);
    runUntil(context.done, noTimeout);
    return context.result;
}

bool TestController::isStatisticsRegisteredAsRedirectingTo(WKStringRef hostRedirectedFrom, WKStringRef hostRedirectedTo)
{
    ResourceStatisticsCallbackContext context(*this);
    WKWebsiteDataStoreIsStatisticsRegisteredAsRedirectingTo(websiteDataStore(), hostRedirectedFrom, hostRedirectedTo, &context, resourceStatisticsBooleanResultCallback);
    runUntil(context.done, noTimeout);
    return context.result;
}

void TestController::setStatisticsHasHadUserInteraction(WKStringRef host, bool value, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreSetStatisticsHasHadUserInteraction(websiteDataStore(), host, value, completionHandler.leak(), adoptAndCallCompletionHandler);
}

bool TestController::isStatisticsHasHadUserInteraction(WKStringRef host)
{
    ResourceStatisticsCallbackContext context(*this);
    WKWebsiteDataStoreIsStatisticsHasHadUserInteraction(websiteDataStore(), host, &context, resourceStatisticsBooleanResultCallback);
    runUntil(context.done, noTimeout);
    return context.result;
}

bool TestController::isStatisticsOnlyInDatabaseOnce(WKStringRef subHost, WKStringRef topHost)
{
    ResourceStatisticsCallbackContext context(*this);
    WKWebsiteDataStoreIsStatisticsOnlyInDatabaseOnce(websiteDataStore(), subHost, topHost, &context, resourceStatisticsBooleanResultCallback);
    runUntil(context.done, noTimeout);
    return context.result;
}

void TestController::setStatisticsGrandfathered(WKStringRef host, bool value)
{
    WKWebsiteDataStoreSetStatisticsGrandfathered(websiteDataStore(), host, value);
}

bool TestController::isStatisticsGrandfathered(WKStringRef host)
{
    ResourceStatisticsCallbackContext context(*this);
    WKWebsiteDataStoreIsStatisticsGrandfathered(websiteDataStore(), host, &context, resourceStatisticsBooleanResultCallback);
    runUntil(context.done, noTimeout);
    return context.result;
}

void TestController::setStatisticsSubframeUnderTopFrameOrigin(WKStringRef host, WKStringRef topFrameHost)
{
    WKWebsiteDataStoreSetStatisticsSubframeUnderTopFrameOrigin(websiteDataStore(), host, topFrameHost);
}

void TestController::setStatisticsSubresourceUnderTopFrameOrigin(WKStringRef host, WKStringRef topFrameHost)
{
    WKWebsiteDataStoreSetStatisticsSubresourceUnderTopFrameOrigin(websiteDataStore(), host, topFrameHost);
}

void TestController::setStatisticsSubresourceUniqueRedirectTo(WKStringRef host, WKStringRef hostRedirectedTo)
{
    WKWebsiteDataStoreSetStatisticsSubresourceUniqueRedirectTo(websiteDataStore(), host, hostRedirectedTo);
}

void TestController::setStatisticsSubresourceUniqueRedirectFrom(WKStringRef host, WKStringRef hostRedirectedFrom)
{
    WKWebsiteDataStoreSetStatisticsSubresourceUniqueRedirectFrom(websiteDataStore(), host, hostRedirectedFrom);
}

void TestController::setStatisticsTopFrameUniqueRedirectTo(WKStringRef host, WKStringRef hostRedirectedTo)
{
    WKWebsiteDataStoreSetStatisticsTopFrameUniqueRedirectTo(websiteDataStore(), host, hostRedirectedTo);
}

void TestController::setStatisticsTopFrameUniqueRedirectFrom(WKStringRef host, WKStringRef hostRedirectedFrom)
{
    WKWebsiteDataStoreSetStatisticsTopFrameUniqueRedirectFrom(websiteDataStore(), host, hostRedirectedFrom);
}

void TestController::setStatisticsCrossSiteLoadWithLinkDecoration(WKStringRef fromHost, WKStringRef toHost, bool wasFiltered)
{
    ResourceStatisticsCallbackContext context(*this);
#if PLATFORM(COCOA)
    platformSetStatisticsCrossSiteLoadWithLinkDecoration(fromHost, toHost, wasFiltered, &context, &resourceStatisticsVoidResultCallback);
#else
    WKWebsiteDataStoreSetStatisticsCrossSiteLoadWithLinkDecoration(websiteDataStore(), fromHost, toHost, wasFiltered, &context, resourceStatisticsVoidResultCallback);
#endif
    runUntil(context.done, noTimeout);
}

void TestController::setStatisticsTimeToLiveUserInteraction(double seconds)
{
    ResourceStatisticsCallbackContext context(*this);
    WKWebsiteDataStoreSetStatisticsTimeToLiveUserInteraction(websiteDataStore(), seconds, &context, resourceStatisticsVoidResultCallback);
    runUntil(context.done, noTimeout);
}

void TestController::statisticsProcessStatisticsAndDataRecords(CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreStatisticsProcessStatisticsAndDataRecords(websiteDataStore(), completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::statisticsUpdateCookieBlocking(CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreStatisticsUpdateCookieBlocking(websiteDataStore(), completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::setStatisticsTimeAdvanceForTesting(double value)
{
    ResourceStatisticsCallbackContext context(*this);
    WKWebsiteDataStoreSetResourceLoadStatisticsTimeAdvanceForTesting(websiteDataStore(), value, &context, resourceStatisticsVoidResultCallback);
    runUntil(context.done, noTimeout);
}

void TestController::setStatisticsIsRunningTest(bool value)
{
    ResourceStatisticsCallbackContext context(*this);
    WKWebsiteDataStoreSetStatisticsIsRunningTest(websiteDataStore(), value, &context, resourceStatisticsVoidResultCallback);
    runUntil(context.done, noTimeout);
}

void TestController::setStatisticsShouldClassifyResourcesBeforeDataRecordsRemoval(bool value)
{
    WKWebsiteDataStoreSetStatisticsShouldClassifyResourcesBeforeDataRecordsRemoval(websiteDataStore(), value);
}

void TestController::setStatisticsMinimumTimeBetweenDataRecordsRemoval(double seconds)
{
    WKWebsiteDataStoreSetStatisticsMinimumTimeBetweenDataRecordsRemoval(websiteDataStore(), seconds);
}

void TestController::setStatisticsGrandfatheringTime(double seconds)
{
    WKWebsiteDataStoreSetStatisticsGrandfatheringTime(websiteDataStore(), seconds);
}

void TestController::setStatisticsMaxStatisticsEntries(unsigned entries)
{
    WKWebsiteDataStoreSetStatisticsMaxStatisticsEntries(websiteDataStore(), entries);
}

void TestController::setStatisticsPruneEntriesDownTo(unsigned entries)
{
    WKWebsiteDataStoreSetStatisticsPruneEntriesDownTo(websiteDataStore(), entries);
}

void TestController::statisticsClearInMemoryAndPersistentStore(CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreStatisticsClearInMemoryAndPersistentStore(websiteDataStore(), completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(unsigned hours, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreStatisticsClearInMemoryAndPersistentStoreModifiedSinceHours(websiteDataStore(), hours, completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::statisticsClearThroughWebsiteDataRemoval(CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreStatisticsClearThroughWebsiteDataRemoval(websiteDataStore(), completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::statisticsDeleteCookiesForHost(WKStringRef host, bool includeHttpOnlyCookies, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreStatisticsDeleteCookiesForTesting(websiteDataStore(), host, includeHttpOnlyCookies, completionHandler.leak(), adoptAndCallCompletionHandler);
}

bool TestController::isStatisticsHasLocalStorage(WKStringRef host)
{
    ResourceStatisticsCallbackContext context(*this);
    WKWebsiteDataStoreStatisticsHasLocalStorage(websiteDataStore(), host, &context, resourceStatisticsBooleanResultCallback);
    runUntil(context.done, noTimeout);
    return context.result;
}

void TestController::setStatisticsCacheMaxAgeCap(double seconds)
{
    ResourceStatisticsCallbackContext context(*this);
    WKWebsiteDataStoreSetStatisticsCacheMaxAgeCap(websiteDataStore(), seconds, &context, resourceStatisticsVoidResultCallback);
    runUntil(context.done, noTimeout);
}

bool TestController::hasStatisticsIsolatedSession(WKStringRef host)
{
    ResourceStatisticsCallbackContext context(*this);
    WKWebsiteDataStoreStatisticsHasIsolatedSession(websiteDataStore(), host, &context, resourceStatisticsBooleanResultCallback);
    runUntil(context.done, noTimeout);
    return context.result;
}

void TestController::setStatisticsShouldDowngradeReferrer(bool value, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreSetResourceLoadStatisticsShouldDowngradeReferrerForTesting(websiteDataStore(), value, completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::setStatisticsShouldBlockThirdPartyCookies(bool value, ThirdPartyCookieBlockingPolicy thirdPartyCookieBlockingPolicy, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKThirdPartyCookieBlockingPolicy blockingPolicy;
    switch (thirdPartyCookieBlockingPolicy) {
    case ThirdPartyCookieBlockingPolicy::AllOnlyOnSitesWithoutUserInteraction:
        blockingPolicy = kWKThirdPartyCookieBlockingPolicyAllOnlyOnSitesWithoutUserInteraction;
        break;
    case ThirdPartyCookieBlockingPolicy::AllExceptPartitioned:
        blockingPolicy = kWKThirdPartyCookieBlockingPolicyAllExceptPartitioned;
        break;
    case ThirdPartyCookieBlockingPolicy::All:
        blockingPolicy = kWKThirdPartyCookieBlockingPolicyAll;
        break;
    default:
        ASSERT_NOT_REACHED();
        blockingPolicy = kWKThirdPartyCookieBlockingPolicyAll;
        break;
    };
    WKWebsiteDataStoreSetResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting(websiteDataStore(), value, blockingPolicy, completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::setStatisticsFirstPartyWebsiteDataRemovalMode(bool value, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreSetResourceLoadStatisticsFirstPartyWebsiteDataRemovalModeForTesting(websiteDataStore(), value, completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::setStatisticsToSameSiteStrictCookies(WKStringRef hostName, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreSetResourceLoadStatisticsToSameSiteStrictCookiesForTesting(websiteDataStore(), hostName, completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::setStatisticsFirstPartyHostCNAMEDomain(WKStringRef firstPartyURLString, WKStringRef cnameURLString, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreSetResourceLoadStatisticsFirstPartyHostCNAMEDomainForTesting(websiteDataStore(), firstPartyURLString, cnameURLString, completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::setStatisticsThirdPartyCNAMEDomain(WKStringRef cnameURLString, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreSetResourceLoadStatisticsThirdPartyCNAMEDomainForTesting(websiteDataStore(), cnameURLString, completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::setAppBoundDomains(WKArrayRef originURLs, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreSetAppBoundDomainsForTesting(originURLs, completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::setManagedDomains(WKArrayRef originURLs, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKWebsiteDataStoreSetManagedDomainsForTesting(originURLs, completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::statisticsResetToConsistentState()
{
    ResourceStatisticsCallbackContext context(*this);
    WKWebsiteDataStoreStatisticsResetToConsistentState(websiteDataStore(), &context, resourceStatisticsVoidResultCallback);
    runUntil(context.done, noTimeout);
}

void TestController::removeAllCookies(CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKHTTPCookieStoreDeleteAllCookies(WKWebsiteDataStoreGetHTTPCookieStore(websiteDataStore()), completionHandler.leak(), adoptAndCallCompletionHandler);
}

void TestController::addMockMediaDevice(WKStringRef persistentID, WKStringRef label, WKStringRef type, WKDictionaryRef properties)
{
    bool isDefault = false;
    WKAddMockMediaDevice(context(), persistentID, label, type, properties, isDefault);
}

void TestController::clearMockMediaDevices()
{
    WKClearMockMediaDevices(context());
}

void TestController::removeMockMediaDevice(WKStringRef persistentID)
{
    WKRemoveMockMediaDevice(context(), persistentID);
}

void TestController::setMockMediaDeviceIsEphemeral(WKStringRef persistentID, bool isEphemeral)
{
    WKSetMockMediaDeviceIsEphemeral(context(), persistentID, isEphemeral);
}

void TestController::resetMockMediaDevices()
{
    WKResetMockMediaDevices(context());
}

void TestController::setMockCameraOrientation(uint64_t rotation, WKStringRef persistentId)
{
    WKPageSetMockCameraOrientationForTesting(m_mainWebView->page(), rotation, persistentId);
}

bool TestController::isMockRealtimeMediaSourceCenterEnabled() const
{
    return WKPageIsMockRealtimeMediaSourceCenterEnabled(m_mainWebView->page());
}

void TestController::setMockCaptureDevicesInterrupted(bool isCameraInterrupted, bool isMicrophoneInterrupted)
{
    WKPageSetMockCaptureDevicesInterrupted(m_mainWebView->page(), isCameraInterrupted, isMicrophoneInterrupted);
}

void TestController::triggerMockCaptureConfigurationChange(bool forCamera, bool forMicrophone, bool forDisplay)
{
    WKPageTriggerMockCaptureConfigurationChange(m_mainWebView->page(), forCamera, forMicrophone, forDisplay);
}

void TestController::setCaptureState(bool cameraState, bool microphoneState, bool displayState)
{
    WKPageSetMuted(m_mainWebView->page(), (cameraState ? kWKMediaCameraCaptureUnmuted : kWKMediaCameraCaptureMuted) | (microphoneState ? kWKMediaMicrophoneCaptureUnmuted : kWKMediaMicrophoneCaptureMuted) | (displayState ? kWKMediaScreenCaptureUnmuted : kWKMediaScreenCaptureMuted));
}

struct InAppBrowserPrivacyCallbackContext {
    explicit InAppBrowserPrivacyCallbackContext(TestController& controller)
        : testController(controller)
    {
    }

    TestController& testController;
    bool done { false };
    bool result { false };
};

static void inAppBrowserPrivacyBooleanResultCallback(bool result, void* userData)
{
    auto* context = static_cast<InAppBrowserPrivacyCallbackContext*>(userData);
    context->result = result;
    context->done = true;
    context->testController.notifyDone();
}

static void inAppBrowserPrivacyVoidResultCallback(void* userData)
{
    auto* context = static_cast<InAppBrowserPrivacyCallbackContext*>(userData);
    context->done = true;
    context->testController.notifyDone();
}

bool TestController::hasAppBoundSession()
{
    InAppBrowserPrivacyCallbackContext context(*this);
    WKWebsiteDataStoreHasAppBoundSession(TestController::websiteDataStore(), &context, inAppBrowserPrivacyBooleanResultCallback);
    runUntil(context.done, noTimeout);
    return context.result;
}

void TestController::clearAppBoundSession()
{
    InAppBrowserPrivacyCallbackContext context(*this);
    WKWebsiteDataStoreClearAppBoundSession(TestController::websiteDataStore(), &context, inAppBrowserPrivacyVoidResultCallback);
    runUntil(context.done, noTimeout);
}

void TestController::reinitializeAppBoundDomains()
{
    WKWebsiteDataStoreReinitializeAppBoundDomains(TestController::websiteDataStore());
}

void TestController::updateBundleIdentifierInNetworkProcess(const std::string& bundleIdentifier)
{
    InAppBrowserPrivacyCallbackContext context(*this);
    WKWebsiteDataStoreUpdateBundleIdentifierInNetworkProcess(TestController::websiteDataStore(), toWK(bundleIdentifier).get(), &context, inAppBrowserPrivacyVoidResultCallback);
    runUntil(context.done, noTimeout);
}

void TestController::clearBundleIdentifierInNetworkProcess()
{
    InAppBrowserPrivacyCallbackContext context(*this);
    WKWebsiteDataStoreClearBundleIdentifierInNetworkProcess(TestController::websiteDataStore(), &context, inAppBrowserPrivacyVoidResultCallback);
    runUntil(context.done, noTimeout);
}

#if !PLATFORM(COCOA)
TestFeatures TestController::platformSpecificFeatureOverridesDefaultsForTest(const TestCommand&) const
{
    return { };
}

void TestController::injectUserScript(WKStringRef)
{
}

void TestController::addTestKeyToKeychain(const String&, const String&, const String&)
{
}

void TestController::cleanUpKeychain(const String&, const String&)
{
}

bool TestController::keyExistsInKeychain(const String&, const String&)
{
    return false;
}

void TestController::setAllowedMenuActions(const Vector<String>&)
{
}

void TestController::platformEnsureGPUProcessConfiguredForOptions(const TestOptions&)
{
}
#endif

#if !PLATFORM(COCOA) && !PLATFORM(GTK) && !PLATFORM(WPE)
WKRetainPtr<WKStringRef> TestController::takeViewPortSnapshot()
{
    return adoptWK(WKStringCreateWithUTF8CString("not implemented"));
}
#endif

void TestController::setServiceWorkerFetchTimeoutForTesting(double seconds)
{
    WKWebsiteDataStoreSetServiceWorkerFetchTimeoutForTesting(websiteDataStore(), seconds);
}

void TestController::setTracksRepaints(bool trackRepaints)
{
    GenericVoidContext context(*this);
    WKPageSetTracksRepaintsForTesting(TestController::singleton().mainWebView()->page(), &context, trackRepaints, genericVoidCallback);
    runUntil(context.done, noTimeout);
}

struct PrivateClickMeasurementStringResultCallbackContext {
    explicit PrivateClickMeasurementStringResultCallbackContext(TestController& controller)
        : testController(controller)
    {
    }
    
    TestController& testController;
    bool done { false };
    WKRetainPtr<WKStringRef> privateClickMeasurementRepresentation;
};

static void privateClickMeasurementStringResultCallback(WKStringRef privateClickMeasurementRepresentation, void* userData)
{
    auto* context = static_cast<PrivateClickMeasurementStringResultCallbackContext*>(userData);
    context->privateClickMeasurementRepresentation = privateClickMeasurementRepresentation;
    context->done = true;
    context->testController.notifyDone();
}

String TestController::dumpPrivateClickMeasurement()
{
    PrivateClickMeasurementStringResultCallbackContext callbackContext(*this);
    WKPageDumpPrivateClickMeasurement(m_mainWebView->page(), privateClickMeasurementStringResultCallback, &callbackContext);
    runUntil(callbackContext.done, noTimeout);
    return toWTFString(callbackContext.privateClickMeasurementRepresentation.get());
}

struct PrivateClickMeasurementVoidCallbackContext {
    explicit PrivateClickMeasurementVoidCallbackContext(TestController& controller)
        : testController(controller)
    {
    }
    
    TestController& testController;
    bool done { false };
};

static void privateClickMeasurementVoidCallback(void* userData)
{
    auto* context = static_cast<PrivateClickMeasurementVoidCallbackContext*>(userData);
    context->done = true;
    context->testController.notifyDone();
}

void TestController::clearPrivateClickMeasurement()
{
    PrivateClickMeasurementVoidCallbackContext callbackContext(*this);
    WKPageClearPrivateClickMeasurement(m_mainWebView->page(), privateClickMeasurementVoidCallback, &callbackContext);
    runUntil(callbackContext.done, noTimeout);
}

void TestController::clearPrivateClickMeasurementsThroughWebsiteDataRemoval()
{
    PrivateClickMeasurementVoidCallbackContext callbackContext(*this);
    WKWebsiteDataStoreClearPrivateClickMeasurementsThroughWebsiteDataRemoval(websiteDataStore(), &callbackContext, privateClickMeasurementVoidCallback);
    runUntil(callbackContext.done, noTimeout);
}

void TestController::setPrivateClickMeasurementOverrideTimerForTesting(bool value)
{
    PrivateClickMeasurementVoidCallbackContext callbackContext(*this);
    WKPageSetPrivateClickMeasurementOverrideTimerForTesting(m_mainWebView->page(), value, privateClickMeasurementVoidCallback, &callbackContext);
    runUntil(callbackContext.done, noTimeout);
}

void TestController::markAttributedPrivateClickMeasurementsAsExpiredForTesting()
{
    PrivateClickMeasurementVoidCallbackContext callbackContext(*this);
    WKPageMarkAttributedPrivateClickMeasurementsAsExpiredForTesting(m_mainWebView->page(), privateClickMeasurementVoidCallback, &callbackContext);
    runUntil(callbackContext.done, noTimeout);
}

void TestController::setPrivateClickMeasurementEphemeralMeasurementForTesting(bool value)
{
    PrivateClickMeasurementVoidCallbackContext callbackContext(*this);
    WKPageSetPrivateClickMeasurementEphemeralMeasurementForTesting(m_mainWebView->page(), value, privateClickMeasurementVoidCallback, &callbackContext);
    runUntil(callbackContext.done, noTimeout);
}

void TestController::simulatePrivateClickMeasurementSessionRestart()
{
    PrivateClickMeasurementVoidCallbackContext callbackContext(*this);
    WKPageSimulatePrivateClickMeasurementSessionRestart(m_mainWebView->page(), privateClickMeasurementVoidCallback, &callbackContext);
    runUntil(callbackContext.done, noTimeout);
}

void TestController::setPrivateClickMeasurementTokenPublicKeyURLForTesting(WKURLRef url)
{
    PrivateClickMeasurementVoidCallbackContext callbackContext(*this);
    WKPageSetPrivateClickMeasurementTokenPublicKeyURLForTesting(m_mainWebView->page(), url, privateClickMeasurementVoidCallback, &callbackContext);
    runUntil(callbackContext.done, noTimeout);
}

void TestController::setPrivateClickMeasurementTokenSignatureURLForTesting(WKURLRef url)
{
    PrivateClickMeasurementVoidCallbackContext callbackContext(*this);
    WKPageSetPrivateClickMeasurementTokenSignatureURLForTesting(m_mainWebView->page(), url, privateClickMeasurementVoidCallback, &callbackContext);
    runUntil(callbackContext.done, noTimeout);
}

void TestController::setPrivateClickMeasurementAttributionReportURLsForTesting(WKURLRef sourceURL, WKURLRef destinationURL)
{
    PrivateClickMeasurementVoidCallbackContext callbackContext(*this);
    WKPageSetPrivateClickMeasurementAttributionReportURLsForTesting(m_mainWebView->page(), sourceURL, destinationURL, privateClickMeasurementVoidCallback, &callbackContext);
    runUntil(callbackContext.done, noTimeout);
}

void TestController::markPrivateClickMeasurementsAsExpiredForTesting()
{
    PrivateClickMeasurementVoidCallbackContext callbackContext(*this);
    WKPageMarkPrivateClickMeasurementsAsExpiredForTesting(m_mainWebView->page(), privateClickMeasurementVoidCallback, &callbackContext);
    runUntil(callbackContext.done, noTimeout);
}

void TestController::setPCMFraudPreventionValuesForTesting(WKStringRef unlinkableToken, WKStringRef secretToken, WKStringRef signature, WKStringRef keyID)
{
    PrivateClickMeasurementVoidCallbackContext callbackContext(*this);
    WKPageSetPCMFraudPreventionValuesForTesting(m_mainWebView->page(), unlinkableToken, secretToken, signature, keyID, privateClickMeasurementVoidCallback, &callbackContext);
    runUntil(callbackContext.done, noTimeout);
}

void TestController::setPrivateClickMeasurementAppBundleIDForTesting(WKStringRef appBundleID)
{
    PrivateClickMeasurementVoidCallbackContext callbackContext(*this);
    WKPageSetPrivateClickMeasurementAppBundleIDForTesting(m_mainWebView->page(), appBundleID, privateClickMeasurementVoidCallback, &callbackContext);
    runUntil(callbackContext.done, noTimeout);
}

WKURLRef TestController::currentTestURL() const
{
    return m_currentInvocation ? m_currentInvocation->url() : nullptr;
}

void TestController::setShouldAllowDeviceOrientationAndMotionAccess(bool value)
{
    m_shouldAllowDeviceOrientationAndMotionAccess = value;
    WKWebsiteDataStoreClearAllDeviceOrientationPermissions(websiteDataStore());
}

void TestController::setRequestStorageAccessThrowsExceptionUntilReload(bool enabled)
{
    auto configuration = adoptWK(WKPageCopyPageConfiguration(m_mainWebView->page()));
    auto preferences = WKPageConfigurationGetPreferences(configuration.get());
    WKPreferencesSetBoolValueForKeyForTesting(preferences, enabled, toWK("RequestStorageAccessThrowsExceptionUntilReload").get());
}

void TestController::setStorageAccessAPIPerPageScopeEnabled(bool enabled)
{
    auto configuration = adoptWK(WKPageCopyPageConfiguration(m_mainWebView->page()));
    auto preferences = WKPageConfigurationGetPreferences(configuration.get());
    WKPreferencesSetBoolValueForKeyForTesting(preferences, enabled, toWK("StorageAccessAPIPerPageScopeEnabled").get());
}

void TestController::setResourceMonitorList(WKStringRef rulesText, CompletionHandler<void(WKTypeRef)>&& completionHandler)
{
    WKContextSetResourceMonitorURLsForTesting(m_context.get(), rulesText, completionHandler.leak(), adoptAndCallCompletionHandler);
}

#if !PLATFORM(IOS_FAMILY)
void TestController::setHasMouseDeviceForTesting(bool)
{
}
#endif

#if PLATFORM(MAC)
// Client accessibility IPC implementation

// Private API for creating an AXUIElement from a remote token
extern "C" AXUIElementRef _AXUIElementCreateWithRemoteToken(CFDataRef remoteToken);

uint64_t TestController::storeAXElement(CFTypeRef element)
{
    if (!element)
        return 0;

    uint64_t token = m_nextAXElementToken++;
    m_axElementTokens.set(token, element);
    return token;
}

CFTypeRef TestController::getAXElement(uint64_t token)
{
    if (!token)
        return nullptr;

    auto tokenIterator = m_axElementTokens.find(token);
    if (tokenIterator == m_axElementTokens.end())
        return nullptr;

    return tokenIterator->value.get();
}

WKRetainPtr<WKTypeRef> TestController::handleAXGetRoot()
{
    CFDataRef remoteToken = getRemoteAccessibilityToken();
    if (!remoteToken)
        return nullptr;

    AXUIElementRef webContentElement = _AXUIElementCreateWithRemoteToken(remoteToken);
    if (!webContentElement)
        return nullptr;

    // Try to get children
    CFTypeRef childrenValue = nullptr;
    AXError error = AXUIElementCopyAttributeValue(webContentElement, kAXChildrenAttribute, &childrenValue);
    RetainPtr adoptedChildren = adoptCF(childrenValue);

    if (error != kAXErrorSuccess || !childrenValue)
        return nullptr;

    CFArrayRef children = static_cast<CFArrayRef>(childrenValue);
    CFIndex childCount = CFArrayGetCount(children);
    if (!childCount)
        return nullptr;

    AXUIElementRef child = static_cast<AXUIElementRef>(const_cast<void*>(CFArrayGetValueAtIndex(children, 0)));

    uint64_t token = storeAXElement(child);
    return adoptWK(WKUInt64Create(token));
}

RetainPtr<CFTypeRef> TestController::axCopyAttributeValue(WKDictionaryRef messageBody)
{
    uint64_t elementToken = uint64Value(messageBody, "elementToken");
    WKStringRef attributeName = stringValue(messageBody, "attributeName");

    AXUIElementRef element = static_cast<AXUIElementRef>(getAXElement(elementToken));
    if (!element)
        return nullptr;

    RetainPtr attributeNameCF = adoptCF(CFStringCreateWithCString(kCFAllocatorDefault, toSTD(attributeName).c_str(), kCFStringEncodingUTF8));
    CFTypeRef value = nullptr;
    AXError error = AXUIElementCopyAttributeValue(element, attributeNameCF.get(), &value);

    if (error != kAXErrorSuccess || !value)
        return nullptr;

    return adoptCF(value);
}

WKRetainPtr<WKTypeRef> TestController::handleAXCopyAttributeValueAsString(WKDictionaryRef messageBody)
{
    RetainPtr value = axCopyAttributeValue(messageBody);
    if (!value)
        return nullptr;

    if (CFGetTypeID(value.get()) != CFStringGetTypeID())
        return nullptr;

    return toWK(String(static_cast<CFStringRef>(value.get())));
}

WKRetainPtr<WKTypeRef> TestController::handleAXCopyAttributeValueAsElement(WKDictionaryRef messageBody)
{
    RetainPtr value = axCopyAttributeValue(messageBody);
    if (!value)
        return nullptr;

    if (CFGetTypeID(value.get()) != AXUIElementGetTypeID())
        return nullptr;

    uint64_t token = storeAXElement(value.get());
    return adoptWK(WKUInt64Create(token));
}

WKRetainPtr<WKTypeRef> TestController::handleAXCopyAttributeValueAsElementArray(WKDictionaryRef messageBody)
{
    RetainPtr value = axCopyAttributeValue(messageBody);
    if (!value)
        return nullptr;

    if (CFGetTypeID(value.get()) != CFArrayGetTypeID())
        return nullptr;

    CFArrayRef elementArray = static_cast<CFArrayRef>(value.get());
    CFIndex count = CFArrayGetCount(elementArray);

    Vector<WKTypeRef> tokens;
    tokens.reserveInitialCapacity(count);

    for (CFIndex i = 0; i < count; i++) {
        CFTypeRef childElement = CFArrayGetValueAtIndex(elementArray, i);
        if (CFGetTypeID(childElement) == AXUIElementGetTypeID()) {
            uint64_t token = storeAXElement(childElement);
            tokens.append(WKUInt64Create(token));
        }
    }

    // Build array from individual elements since Vector::data() is private
    WKRetainPtr result = adoptWK(WKMutableArrayCreate());
    for (WKTypeRef token : tokens) {
        WKArrayAppendItem(result.get(), token);
        WKRelease(token);
    }

    return result;
}

WKRetainPtr<WKTypeRef> TestController::handleAXCopyAttributeValueAsNumber(WKDictionaryRef messageBody)
{
    RetainPtr value = axCopyAttributeValue(messageBody);
    if (!value)
        return nullptr;

    if (CFGetTypeID(value.get()) != CFNumberGetTypeID())
        return nullptr;

    double doubleValue;
    CFNumberGetValue(static_cast<CFNumberRef>(value.get()), kCFNumberDoubleType, &doubleValue);

    return adoptWK(WKDoubleCreate(doubleValue));
}

WKRetainPtr<WKTypeRef> TestController::handleAXCopyAttributeValueAsBoolean(WKDictionaryRef messageBody)
{
    RetainPtr value = axCopyAttributeValue(messageBody);
    if (!value)
        return nullptr;

    if (CFGetTypeID(value.get()) != CFBooleanGetTypeID())
        return nullptr;

    bool boolValue = CFBooleanGetValue(static_cast<CFBooleanRef>(value.get()));

    return adoptWK(WKBooleanCreate(boolValue));
}

// Compare underlying AXUIElementRefs rather than tokens.
WKRetainPtr<WKTypeRef> TestController::handleAXElementsAreEqual(WKDictionaryRef messageBody)
{
    RetainPtr first = getAXElement(uint64Value(messageBody, "elementToken"));
    RetainPtr second = getAXElement(uint64Value(messageBody, "otherElementToken"));
    if (!first || !second)
        return adoptWK(WKBooleanCreate(false));

    return adoptWK(WKBooleanCreate(CFEqual(first.get(), second.get())));
}

WKRetainPtr<WKTypeRef> TestController::handleAXCopyAttributeValueAsPoint(WKDictionaryRef messageBody)
{
    RetainPtr value = axCopyAttributeValue(messageBody);
    if (!value)
        return nullptr;

    if (CFGetTypeID(value.get()) != AXValueGetTypeID())
        return nullptr;

    CGPoint point;
    if (!AXValueGetValue(static_cast<AXValueRef>(value.get()), static_cast<AXValueType>(kAXValueCGPointType), &point))
        return nullptr;

    WKRetainPtr dictionary = adoptWK(WKMutableDictionaryCreate());
    setValue(dictionary, "x", point.x);
    setValue(dictionary, "y", point.y);
    return dictionary;
}

WKRetainPtr<WKTypeRef> TestController::handleAXCopyAttributeValueAsSize(WKDictionaryRef messageBody)
{
    RetainPtr value = axCopyAttributeValue(messageBody);
    if (!value)
        return nullptr;

    if (CFGetTypeID(value.get()) != AXValueGetTypeID())
        return nullptr;

    CGSize size;
    if (!AXValueGetValue(static_cast<AXValueRef>(value.get()), static_cast<AXValueType>(kAXValueCGSizeType), &size))
        return nullptr;

    WKRetainPtr dictionary = adoptWK(WKMutableDictionaryCreate());
    setValue(dictionary, "width", size.width);
    setValue(dictionary, "height", size.height);
    return dictionary;
}

WKRetainPtr<WKTypeRef> TestController::handleAXSearchPredicate(WKDictionaryRef messageBody)
{
    uint64_t elementToken = uint64Value(messageBody, "elementToken");
    uint64_t startElementToken = uint64Value(messageBody, "startElementToken");
    bool isDirectionNext = booleanValue(messageBody, "isDirectionNext");
    uint64_t resultsLimit = uint64Value(messageBody, "resultsLimit");
    bool visibleOnly = booleanValue(messageBody, "visibleOnly");
    bool immediateDescendantsOnly = booleanValue(messageBody, "immediateDescendantsOnly");
    WKStringRef searchKey = stringValue(messageBody, "searchKey");
    WKStringRef searchText = stringValue(messageBody, "searchText");

    AXUIElementRef element = static_cast<AXUIElementRef>(getAXElement(elementToken));
    if (!element)
        return nullptr;

    // Build the search predicate parameter dictionary using CF APIs.
    RetainPtr paramDictionary = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));

    if (startElementToken) {
        if (AXUIElementRef startElement = static_cast<AXUIElementRef>(getAXElement(startElementToken)))
            CFDictionarySetValue(paramDictionary.get(), CFSTR("AXStartElement"), startElement);
    }

    CFDictionarySetValue(paramDictionary.get(), CFSTR("AXDirection"),
        isDirectionNext ? CFSTR("AXDirectionNext") : CFSTR("AXDirectionPrevious"));

    int resultsLimitInt = static_cast<int>(resultsLimit);
    RetainPtr resultsLimitNum = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &resultsLimitInt));
    CFDictionarySetValue(paramDictionary.get(), CFSTR("AXResultsLimit"), resultsLimitNum.get());

    if (searchKey) {
        RetainPtr searchKeyCF = adoptCF(CFStringCreateWithCString(kCFAllocatorDefault, toSTD(searchKey).c_str(), kCFStringEncodingUTF8));
        CFDictionarySetValue(paramDictionary.get(), CFSTR("AXSearchKey"), searchKeyCF.get());
    }

    if (searchText) {
        auto searchTextStd = toSTD(searchText);
        if (!searchTextStd.empty()) {
            RetainPtr searchTextCF = adoptCF(CFStringCreateWithCString(kCFAllocatorDefault, searchTextStd.c_str(), kCFStringEncodingUTF8));
            CFDictionarySetValue(paramDictionary.get(), CFSTR("AXSearchText"), searchTextCF.get());
        }
    }

    CFDictionarySetValue(paramDictionary.get(), CFSTR("AXVisibleOnly"), visibleOnly ? kCFBooleanTrue : kCFBooleanFalse);
    CFDictionarySetValue(paramDictionary.get(), CFSTR("AXImmediateDescendantsOnly"), immediateDescendantsOnly ? kCFBooleanTrue : kCFBooleanFalse);

    CFTypeRef resultValue = nullptr;
    AXError error = AXUIElementCopyParameterizedAttributeValue(element, CFSTR("AXUIElementsForSearchPredicate"), paramDictionary.get(), &resultValue);

    if (error != kAXErrorSuccess || !resultValue)
        return nullptr;

    RetainPtr result = adoptCF(resultValue);

    if (CFGetTypeID(result.get()) != CFArrayGetTypeID())
        return nullptr;

    CFArrayRef resultArray = static_cast<CFArrayRef>(result.get());
    CFIndex count = CFArrayGetCount(resultArray);

    WKRetainPtr tokenArray = adoptWK(WKMutableArrayCreate());
    for (CFIndex i = 0; i < count; i++) {
        CFTypeRef item = CFArrayGetValueAtIndex(resultArray, i);

        AXUIElementRef resultElement = nullptr;
        if (CFGetTypeID(item) == AXUIElementGetTypeID())
            resultElement = static_cast<AXUIElementRef>(const_cast<void*>(item));
        else if (CFGetTypeID(item) == CFDictionaryGetTypeID()) {
            CFTypeRef searchResultElement = CFDictionaryGetValue(static_cast<CFDictionaryRef>(item), CFSTR("AXSearchResultElement"));
            if (searchResultElement && CFGetTypeID(searchResultElement) == AXUIElementGetTypeID())
                resultElement = static_cast<AXUIElementRef>(const_cast<void*>(searchResultElement));
        }

        if (resultElement) {
            uint64_t token = storeAXElement(resultElement);
            WKRetainPtr tokenRef = adoptWK(WKUInt64Create(token));
            WKArrayAppendItem(tokenArray.get(), tokenRef.get());
        }
    }

    return tokenArray;
}

void TestController::handleAXPerformAction(WKDictionaryRef messageBody)
{
    uint64_t elementToken = uint64Value(messageBody, "elementToken");
    WKStringRef actionName = stringValue(messageBody, "actionName");

    AXUIElementRef element = static_cast<AXUIElementRef>(getAXElement(elementToken));
    if (!element)
        return;

    RetainPtr actionNameCF = adoptCF(CFStringCreateWithCString(kCFAllocatorDefault, toSTD(actionName).c_str(), kCFStringEncodingUTF8));
    AXUIElementPerformAction(element, actionNameCF.get());
}

#endif // PLATFORM(MAC)

#if !PLATFORM(COCOA)
void TestController::doAfterProcessingAllPendingMouseEvents(CompletionHandler<void()>&& handler)
{
    auto* completionHandler = new CompletionHandler<void()>(WTF::move(handler));
    WKPageDoAfterProcessingAllPendingMouseEvents(targetView()->page(), completionHandler, [](void* userData) {
        auto* completionHandler = static_cast<CompletionHandler<void()>*>(userData);
        (*completionHandler)();
        delete completionHandler;
    });
}

void TestController::doAfterProcessingAllPendingKeyEvents(CompletionHandler<void()>&& handler)
{
    auto* completionHandler = new CompletionHandler<void()>(WTF::move(handler));
    WKPageDoAfterProcessingAllPendingKeyEvents(mainWebView()->page(), completionHandler, [](void* userData) {
        auto* completionHandler = static_cast<CompletionHandler<void()>*>(userData);
        (*completionHandler)();
        delete completionHandler;
    });
}

#if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
void TestController::doAfterProcessingAllPendingWheelEvents(CompletionHandler<void()>&& handler)
{
    auto* completionHandler = new CompletionHandler<void()>(WTF::move(handler));
    WKPageDoAfterProcessingAllPendingWheelEvents(targetView()->page(), completionHandler, [](void* userData) {
        auto* completionHandler = static_cast<CompletionHandler<void()>*>(userData);
        (*completionHandler)();
        delete completionHandler;
    });
}

void TestController::doAfterProcessingAllPendingTouchEvents(CompletionHandler<void()>&& handler)
{
    auto* completionHandler = new CompletionHandler<void()>(WTF::move(handler));
    WKPageDoAfterProcessingAllPendingTouchEvents(targetView()->page(), completionHandler, [](void* userData) {
        auto* completionHandler = static_cast<CompletionHandler<void()>*>(userData);
        (*completionHandler)();
        delete completionHandler;
    });
}

void TestController::doAfterProcessingAllPendingTouchAndWheelEvents(CompletionHandler<void()>&& handler)
{
    doAfterProcessingAllPendingTouchEvents([this, handler = WTF::move(handler)] mutable {
        doAfterProcessingAllPendingWheelEvents(WTF::move(handler));
    });
}
#endif
#endif

} // namespace WTR
