/*
 * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#import "config.h"
#import "WKProcessPoolInternal.h"

#import "AutomationClient.h"
#import "CacheModel.h"
#import "DownloadClient.h"
#import "Logging.h"
#import "PluginProcessManager.h"
#import "SandboxUtilities.h"
#import "UIGamepadProvider.h"
#import "WKObject.h"
#import "WKWebViewInternal.h"
#import "WKWebsiteDataStoreInternal.h"
#import "WebBackForwardCache.h"
#import "WebCertificateInfo.h"
#import "WebCookieManagerProxy.h"
#import "WebProcessCache.h"
#import "WebProcessMessages.h"
#import "WebProcessPool.h"
#import "_WKAutomationDelegate.h"
#import "_WKAutomationSessionInternal.h"
#import "_WKDownloadDelegate.h"
#import "_WKDownloadInternal.h"
#import "_WKProcessPoolConfigurationInternal.h"
#import <WebCore/CertificateInfo.h>
#import <WebCore/PluginData.h>
#import <WebCore/RegistrableDomain.h>
#import <pal/spi/cf/CFNetworkSPI.h>
#import <pal/spi/cocoa/NSKeyedArchiverSPI.h>
#import <wtf/BlockPtr.h>
#import <wtf/RetainPtr.h>
#import <wtf/WeakObjCPtr.h>

#if PLATFORM(IOS_FAMILY)
#import <WebCore/WebCoreThreadSystemInterface.h>
#import "WKGeolocationProviderIOS.h"
#endif

static WKProcessPool *sharedProcessPool;

@implementation WKProcessPool {
    WeakObjCPtr<id <_WKAutomationDelegate>> _automationDelegate;
    WeakObjCPtr<id <_WKDownloadDelegate>> _downloadDelegate;

    RetainPtr<_WKAutomationSession> _automationSession;
#if PLATFORM(IOS_FAMILY)
    RetainPtr<WKGeolocationProviderIOS> _geolocationProvider;
    RetainPtr<id <_WKGeolocationCoreLocationProvider>> _coreLocationProvider;
#endif // PLATFORM(IOS_FAMILY)
}

- (instancetype)_initWithConfiguration:(_WKProcessPoolConfiguration *)configuration
{
    if (!(self = [super init]))
        return nil;

    API::Object::constructInWrapper<WebKit::WebProcessPool>(self, *configuration->_processPoolConfiguration);

    return self;
}

- (instancetype)init
{
    return [self _initWithConfiguration:adoptNS([[_WKProcessPoolConfiguration alloc] init]).get()];
}

- (void)dealloc
{
    _processPool->~WebProcessPool();

    [super dealloc];
}

+ (BOOL)supportsSecureCoding
{
    return YES;
}

- (void)encodeWithCoder:(NSCoder *)coder
{
    if (self == sharedProcessPool) {
        [coder encodeBool:YES forKey:@"isSharedProcessPool"];
        return;
    }
}

- (instancetype)initWithCoder:(NSCoder *)coder
{
    if (!(self = [self init]))
        return nil;

    if ([coder decodeBoolForKey:@"isSharedProcessPool"]) {
        [self release];

        return [[WKProcessPool _sharedProcessPool] retain];
    }

    return self;
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"<%@: %p; configuration = %@>", NSStringFromClass(self.class), self, wrapper(_processPool->configuration())];
}

- (_WKProcessPoolConfiguration *)_configuration
{
    return wrapper(_processPool->configuration().copy());
}

- (API::Object&)_apiObject
{
    return *_processPool;
}

#if PLATFORM(IOS_FAMILY)
- (WKGeolocationProviderIOS *)_geolocationProvider
{
    if (!_geolocationProvider)
        _geolocationProvider = adoptNS([[WKGeolocationProviderIOS alloc] initWithProcessPool:*_processPool]);
    return _geolocationProvider.get();
}
#endif // PLATFORM(IOS_FAMILY)

@end

@implementation WKProcessPool (WKPrivate)

+ (WKProcessPool *)_sharedProcessPool
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedProcessPool = [[WKProcessPool alloc] init];
    });

    return sharedProcessPool;
}

+ (NSArray<WKProcessPool *> *)_allProcessPoolsForTesting
{
    auto& allPools = WebKit::WebProcessPool::allProcessPools();
    auto nsAllPools = adoptNS([[NSMutableArray alloc] initWithCapacity:allPools.size()]);
    for (auto* pool : allPools)
        [nsAllPools addObject:wrapper(*pool)];
    return nsAllPools.autorelease();
}

+ (NSURL *)_websiteDataURLForContainerWithURL:(NSURL *)containerURL
{
    return [WKProcessPool _websiteDataURLForContainerWithURL:containerURL bundleIdentifierIfNotInContainer:nil];
}

+ (NSURL *)_websiteDataURLForContainerWithURL:(NSURL *)containerURL bundleIdentifierIfNotInContainer:(NSString *)bundleIdentifier
{
    NSURL *url = [containerURL URLByAppendingPathComponent:@"Library" isDirectory:YES];
    url = [url URLByAppendingPathComponent:@"WebKit" isDirectory:YES];

    if (!WebKit::processHasContainer() && bundleIdentifier)
        url = [url URLByAppendingPathComponent:bundleIdentifier isDirectory:YES];

    return [url URLByAppendingPathComponent:@"WebsiteData" isDirectory:YES];
}

- (void)_setAllowsSpecificHTTPSCertificate:(NSArray *)certificateChain forHost:(NSString *)host
{
    _processPool->allowSpecificHTTPSCertificateForHost(WebKit::WebCertificateInfo::create(WebCore::CertificateInfo((__bridge CFArrayRef)certificateChain)).ptr(), host);
}

- (void)_registerURLSchemeAsCanDisplayOnlyIfCanRequest:(NSString *)scheme
{
    _processPool->registerURLSchemeAsCanDisplayOnlyIfCanRequest(scheme);
}

- (void)_setCanHandleHTTPSServerTrustEvaluation:(BOOL)value
{
}

static WebKit::HTTPCookieAcceptPolicy toHTTPCookieAcceptPolicy(NSHTTPCookieAcceptPolicy policy)
{
    switch (static_cast<NSUInteger>(policy)) {
    case NSHTTPCookieAcceptPolicyAlways:
        return WebKit::HTTPCookieAcceptPolicy::AlwaysAccept;
    case NSHTTPCookieAcceptPolicyNever:
        return WebKit::HTTPCookieAcceptPolicy::Never;
    case NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain:
        return WebKit::HTTPCookieAcceptPolicy::OnlyFromMainDocumentDomain;
    case NSHTTPCookieAcceptPolicyExclusivelyFromMainDocumentDomain:
        return WebKit::HTTPCookieAcceptPolicy::ExclusivelyFromMainDocumentDomain;
    }

    ASSERT_NOT_REACHED();
    return WebKit::HTTPCookieAcceptPolicy::AlwaysAccept;
}

- (void)_setCookieAcceptPolicy:(NSHTTPCookieAcceptPolicy)policy
{
    _processPool->supplement<WebKit::WebCookieManagerProxy>()->setHTTPCookieAcceptPolicy(PAL::SessionID::defaultSessionID(), toHTTPCookieAcceptPolicy(policy), []() { });
}

- (id)_objectForBundleParameter:(NSString *)parameter
{
    return [_processPool->bundleParameters() objectForKey:parameter];
}

- (void)_setObject:(id <NSCopying, NSSecureCoding>)object forBundleParameter:(NSString *)parameter
{
    auto copy = adoptNS([(NSObject *)object copy]);
    auto keyedArchiver = secureArchiver();

    @try {
        [keyedArchiver encodeObject:copy.get() forKey:@"parameter"];
        [keyedArchiver finishEncoding];
    } @catch (NSException *exception) {
        LOG_ERROR("Failed to encode bundle parameter: %@", exception);
    }

    if (copy)
        [_processPool->ensureBundleParameters() setObject:copy.get() forKey:parameter];
    else
        [_processPool->ensureBundleParameters() removeObjectForKey:parameter];

    auto data = keyedArchiver.get().encodedData;
    _processPool->sendToAllProcesses(Messages::WebProcess::SetInjectedBundleParameter(parameter, IPC::DataReference(static_cast<const uint8_t*>([data bytes]), [data length])));
}

- (void)_setObjectsForBundleParametersWithDictionary:(NSDictionary *)dictionary
{
    auto copy = adoptNS([[NSDictionary alloc] initWithDictionary:dictionary copyItems:YES]);
    auto keyedArchiver = secureArchiver();

    @try {
        [keyedArchiver encodeObject:copy.get() forKey:@"parameters"];
        [keyedArchiver finishEncoding];
    } @catch (NSException *exception) {
        LOG_ERROR("Failed to encode bundle parameters: %@", exception);
    }

    [_processPool->ensureBundleParameters() setValuesForKeysWithDictionary:copy.get()];

    auto data = keyedArchiver.get().encodedData;
    _processPool->sendToAllProcesses(Messages::WebProcess::SetInjectedBundleParameters(IPC::DataReference(static_cast<const uint8_t*>([data bytes]), [data length])));
}

#if !TARGET_OS_IPHONE

#if ENABLE(NETSCAPE_PLUGIN_API)

static bool isPluginLoadClientPolicyAcceptable(unsigned policy)
{
    return policy <= WebCore::PluginLoadClientPolicyMaximum;
}
static HashMap<String, HashMap<String, HashMap<String, uint8_t>>> toPluginLoadClientPoliciesHashMap(NSDictionary* dictionary)
{
    __block HashMap<String, HashMap<String, HashMap<String, uint8_t>>> pluginLoadClientPolicies;
    [dictionary enumerateKeysAndObjectsUsingBlock:^(id nsHost, id nsPoliciesForHost, BOOL *stop) {
        if (![nsHost isKindOfClass:[NSString class]]) {
            RELEASE_LOG_ERROR(Plugins, "_resetPluginLoadClientPolicies was called with dictionary in wrong format");
            return;
        }
        if (![nsPoliciesForHost isKindOfClass:[NSDictionary class]]) {
            RELEASE_LOG_ERROR(Plugins, "_resetPluginLoadClientPolicies was called with dictionary in wrong format");
            return;
        }

        String host = (NSString *)nsHost;
        __block HashMap<String, HashMap<String, uint8_t>> policiesForHost;
        [nsPoliciesForHost enumerateKeysAndObjectsUsingBlock:^(id nsIdentifier, id nsVersionsToPolicies, BOOL *stop) {
            if (![nsIdentifier isKindOfClass:[NSString class]]) {
                RELEASE_LOG_ERROR(Plugins, "_resetPluginLoadClientPolicies was called with dictionary in wrong format");
                return;
            }
            if (![nsVersionsToPolicies isKindOfClass:[NSDictionary class]]) {
                RELEASE_LOG_ERROR(Plugins, "_resetPluginLoadClientPolicies was called with dictionary in wrong format");
                return;
            }

            String bundleIdentifier = (NSString *)nsIdentifier;
            __block HashMap<String, uint8_t> versionsToPolicies;
            [nsVersionsToPolicies enumerateKeysAndObjectsUsingBlock:^(id nsVersion, id nsPolicy, BOOL *stop) {
                if (![nsVersion isKindOfClass:[NSString class]]) {
                    RELEASE_LOG_ERROR(Plugins, "_resetPluginLoadClientPolicies was called with dictionary in wrong format");
                    return;
                }
                if (![nsPolicy isKindOfClass:[NSNumber class]]) {
                    RELEASE_LOG_ERROR(Plugins, "_resetPluginLoadClientPolicies was called with dictionary in wrong format");
                    return;
                }
                unsigned policy = ((NSNumber *)nsPolicy).unsignedIntValue;
                if (!isPluginLoadClientPolicyAcceptable(policy)) {
                    RELEASE_LOG_ERROR(Plugins, "_resetPluginLoadClientPolicies was called with dictionary in wrong format");
                    return;
                }
                String version = (NSString *)nsVersion;
                versionsToPolicies.add(version, static_cast<uint8_t>(policy));
            }];
            if (!versionsToPolicies.isEmpty())
                policiesForHost.add(bundleIdentifier, WTFMove(versionsToPolicies));
        }];
        if (!policiesForHost.isEmpty())
            pluginLoadClientPolicies.add(host, WTFMove(policiesForHost));
    }];
    return pluginLoadClientPolicies;
}

static NSDictionary *policiesHashMapToDictionary(const HashMap<String, HashMap<String, HashMap<String, uint8_t>>>& map)
{
    auto policies = adoptNS([[NSMutableDictionary alloc] initWithCapacity:map.size()]);
    for (auto& hostPair : map) {
        NSString *host = hostPair.key;
        policies.get()[host] = adoptNS([[NSMutableDictionary alloc] initWithCapacity:hostPair.value.size()]).get();
        for (auto& bundleIdentifierPair : hostPair.value) {
            NSString *bundlerIdentifier = bundleIdentifierPair.key;
            policies.get()[host][bundlerIdentifier] = adoptNS([[NSMutableDictionary alloc] initWithCapacity:bundleIdentifierPair.value.size()]).get();
            for (auto& versionPair : bundleIdentifierPair.value) {
                NSString *version = versionPair.key;
                policies.get()[host][bundlerIdentifier][version] = adoptNS([[NSNumber alloc] initWithUnsignedInt:versionPair.value]).get();
            }
        }
    }
    return policies.autorelease();
}

#endif

- (void)_resetPluginLoadClientPolicies:(NSDictionary *)policies
{
#if ENABLE(NETSCAPE_PLUGIN_API)
    _processPool->resetPluginLoadClientPolicies(toPluginLoadClientPoliciesHashMap(policies));
#endif
}

-(NSDictionary *)_pluginLoadClientPolicies
{
    auto& map = _processPool->pluginLoadClientPolicies();
    return policiesHashMapToDictionary(map);
}
#endif


- (id <_WKDownloadDelegate>)_downloadDelegate
{
    return _downloadDelegate.getAutoreleased();
}

- (void)_setDownloadDelegate:(id <_WKDownloadDelegate>)downloadDelegate
{
    _downloadDelegate = downloadDelegate;
    _processPool->setDownloadClient(makeUniqueRef<WebKit::DownloadClient>(downloadDelegate));
}

- (id <_WKAutomationDelegate>)_automationDelegate
{
    return _automationDelegate.getAutoreleased();
}

- (void)_setAutomationDelegate:(id <_WKAutomationDelegate>)automationDelegate
{
    _automationDelegate = automationDelegate;
    _processPool->setAutomationClient(makeUnique<WebKit::AutomationClient>(self, automationDelegate));
}

- (void)_warmInitialProcess
{
    _processPool->prewarmProcess();
}

- (void)_automationCapabilitiesDidChange
{
    _processPool->updateAutomationCapabilities();
}

- (void)_setAutomationSession:(_WKAutomationSession *)automationSession
{
    _automationSession = automationSession;
    _processPool->setAutomationSession(automationSession ? automationSession->_session.get() : nullptr);
}

- (NSURL *)_javaScriptConfigurationDirectory
{
    return [NSURL fileURLWithPath:_processPool->javaScriptConfigurationDirectory() isDirectory:YES];
}

- (void)_setJavaScriptConfigurationDirectory:(NSURL *)directory
{
    if (directory && ![directory isFileURL])
        [NSException raise:NSInvalidArgumentException format:@"%@ is not a file URL", directory];
    _processPool->setJavaScriptConfigurationDirectory(directory.path);
}

- (void)_addSupportedPlugin:(NSString *) domain named:(NSString *) name withMimeTypes: (NSSet<NSString *> *) nsMimeTypes withExtensions: (NSSet<NSString *> *) nsExtensions
{
    HashSet<String> mimeTypes;
    for (NSString *mimeType in nsMimeTypes)
        mimeTypes.add(mimeType);
    HashSet<String> extensions;
    for (NSString *extension in nsExtensions)
        extensions.add(extension);

    _processPool->addSupportedPlugin(domain, name, WTFMove(mimeTypes), WTFMove(extensions));
}

- (void)_clearSupportedPlugins
{
    _processPool->clearSupportedPlugins();
}

- (void)_terminateNetworkProcess
{
    _processPool->terminateNetworkProcess();
}

- (void)_sendNetworkProcessWillSuspendImminently
{
    _processPool->sendNetworkProcessWillSuspendImminentlyForTesting();
}

- (void)_sendNetworkProcessDidResume
{
    _processPool->sendNetworkProcessDidResume();
}

- (void)_terminateServiceWorkerProcesses
{
    _processPool->terminateServiceWorkerProcesses();
}

- (void)_setUseSeparateServiceWorkerProcess:(BOOL)useSeparateServiceWorkerProcess
{
    _processPool->setUseSeparateServiceWorkerProcess(useSeparateServiceWorkerProcess);
}

- (pid_t)_networkProcessIdentifier
{
    return _processPool->networkProcessIdentifier();
}

- (pid_t)_prewarmedProcessIdentifier
{
    return _processPool->prewarmedProcessIdentifier();
}

- (void)_syncNetworkProcessCookies
{
    _processPool->syncNetworkProcessCookies();
}

- (void)_clearWebProcessCache
{
    _processPool->webProcessCache().clear();
}

- (size_t)_webProcessCount
{
    return _processPool->processes().size();
}

- (void)_makeNextWebProcessLaunchFailForTesting
{
    _processPool->setShouldMakeNextWebProcessLaunchFailForTesting(true);
}

- (void)_makeNextNetworkProcessLaunchFailForTesting
{
    _processPool->setShouldMakeNextNetworkProcessLaunchFailForTesting(true);
}

- (BOOL)_hasPrewarmedWebProcess
{
    for (auto& process : _processPool->processes()) {
        if (process->isPrewarmed())
            return YES;
    }
    return NO;
}

- (size_t)_webProcessCountIgnoringPrewarmed
{
    return [self _webProcessCount] - ([self _hasPrewarmedWebProcess] ? 1 : 0);
}

- (size_t)_webProcessCountIgnoringPrewarmedAndCached
{
    size_t count = 0;
    for (auto& process : _processPool->processes()) {
        if (!process->isInProcessCache() && !process->isPrewarmed())
            ++count;
    }
    return count;
}

- (size_t)_webPageContentProcessCount
{
    auto result = _processPool->processes().size();
#if ENABLE(SERVICE_WORKER)
    if (_processPool->useSeparateServiceWorkerProcess())
        result -= _processPool->serviceWorkerProxiesCount();
#endif
    return result;
}

- (void)_preconnectToServer:(NSURL *)serverURL
{
}

- (size_t)_pluginProcessCount
{
#if !PLATFORM(IOS_FAMILY)
    return WebKit::PluginProcessManager::singleton().pluginProcesses().size();
#else
    return 0;
#endif
}

- (NSUInteger)_maximumSuspendedPageCount
{
    return _processPool->backForwardCache().capacity();
}

- (NSUInteger)_processCacheCapacity
{
    return _processPool->webProcessCache().capacity();
}

- (NSUInteger)_processCacheSize
{
    return _processPool->webProcessCache().size();
}

- (size_t)_serviceWorkerProcessCount
{
#if ENABLE(SERVICE_WORKER)
    return _processPool->serviceWorkerProxiesCount();
#else
    return 0;
#endif
}

+ (void)_forceGameControllerFramework
{
#if ENABLE(GAMEPAD)
    WebKit::UIGamepadProvider::setUsesGameControllerFramework();
#endif
}

- (BOOL)_isCookieStoragePartitioningEnabled
{
    return _processPool->cookieStoragePartitioningEnabled();
}

- (void)_setCookieStoragePartitioningEnabled:(BOOL)enabled
{
    _processPool->setCookieStoragePartitioningEnabled(enabled);
}

- (BOOL)_isStorageAccessAPIEnabled
{
    return _processPool->storageAccessAPIEnabled();
}

- (void)_setStorageAccessAPIEnabled:(BOOL)enabled
{
    _processPool->setStorageAccessAPIEnabled(enabled);
}

- (void)_synthesizeAppIsBackground:(BOOL)background
{
    _processPool->synthesizeAppIsBackground(background);
}

- (void)_setAllowsAnySSLCertificateForServiceWorker:(BOOL)allows
{
#if ENABLE(SERVICE_WORKER)
    _processPool->setAllowsAnySSLCertificateForServiceWorker(allows);
#endif
}

#if PLATFORM(IOS_FAMILY)
- (id <_WKGeolocationCoreLocationProvider>)_coreLocationProvider
{
    return _coreLocationProvider.get();
}

- (void)_setCoreLocationProvider:(id<_WKGeolocationCoreLocationProvider>)coreLocationProvider
{
    if (_geolocationProvider)
        [NSException raise:NSGenericException format:@"Changing the location provider is not supported after a web view in the process pool has begun servicing geolocation requests."];

    _coreLocationProvider = coreLocationProvider;
}
#endif // PLATFORM(IOS_FAMILY)

- (_WKDownload *)_downloadURLRequest:(NSURLRequest *)request originatingWebView:(WKWebView *)webView
{
    return nil;
}

- (_WKDownload *)_resumeDownloadFromData:(NSData *)resumeData path:(NSString *)path originatingWebView:(WKWebView *)webView
{
    return nil;
}

- (_WKDownload *)_downloadURLRequest:(NSURLRequest *)request websiteDataStore:(WKWebsiteDataStore *)dataStore originatingWebView:(WKWebView *)webView
{
    return wrapper(_processPool->download(*dataStore->_websiteDataStore, [webView _page], request));
}

- (_WKDownload *)_resumeDownloadFromData:(NSData *)resumeData websiteDataStore:(WKWebsiteDataStore *)dataStore  path:(NSString *)path originatingWebView:(WKWebView *)webView
{
    return wrapper(_processPool->resumeDownload(*dataStore->_websiteDataStore, [webView _page], API::Data::createWithoutCopying(resumeData).get(), path));
}

- (void)_getActivePagesOriginsInWebProcessForTesting:(pid_t)pid completionHandler:(void(^)(NSArray<NSString *> *))completionHandler
{
    _processPool->activePagesOriginsInWebProcessForTesting(pid, [completionHandler = makeBlockPtr(completionHandler)] (Vector<String>&& activePagesOrigins) {
        NSMutableArray<NSString *> *array = [[[NSMutableArray alloc] initWithCapacity:activePagesOrigins.size()] autorelease];
        for (auto& origin : activePagesOrigins)
            [array addObject:origin];
        completionHandler(array);
    });
}

- (BOOL)_networkProcessHasEntitlementForTesting:(NSString *)entitlement
{
    return _processPool->networkProcessHasEntitlementForTesting(entitlement);
}

- (void)_clearPermanentCredentialsForProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
    _processPool->clearPermanentCredentialsForProtectionSpace(WebCore::ProtectionSpace(protectionSpace));
}

- (void)_allowAnyTLSCertificateForWebSocketTesting
{
    _processPool->setAllowsAnySSLCertificateForWebSocket(true);
}

- (void)_seedResourceLoadStatisticsForTestingWithFirstParty:(NSURL *)firstPartyURL thirdParty:(NSURL *)thirdPartyURL shouldScheduleNotification:(BOOL)shouldScheduleNotification completionHandler:(void(^)(void))completionHandler
{
#if ENABLE(RESOURCE_LOAD_STATISTICS)
    _processPool->seedResourceLoadStatisticsForTesting(WebCore::RegistrableDomain { firstPartyURL }, WebCore::RegistrableDomain { thirdPartyURL }, shouldScheduleNotification, [completionHandler = makeBlockPtr(completionHandler)] () {
        completionHandler();
    });
#else
    UNUSED_PARAM(firstPartyURL);
    UNUSED_PARAM(thirdPartyURL);
    UNUSED_PARAM(shouldScheduleNotification);
    UNUSED_PARAM(completionHandler);
#endif
}

@end
