/*
 * Copyright (C) 2021 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 "HTTPServer.h"
#import "PlatformUtilities.h"
#import "TestNavigationDelegate.h"
#import "TestUIDelegate.h"
#import "TestWKWebView.h"
#import "WKWebViewConfigurationExtras.h"
#import <Foundation/NSURLRequest.h>
#import <WebKit/WKPreferencesPrivate.h>
#import <WebKit/WKWebViewPrivateForTesting.h>
#import <WebKit/WKWebsiteDataStorePrivate.h>
#import <WebKit/_WKSessionState.h>
#import <WebCore/ResourceRequest.h>
#import <pal/spi/cf/CFNetworkSPI.h>
#import <wtf/RunLoop.h>
#import <wtf/text/WTFString.h>

#if ENABLE(APP_PRIVACY_REPORT)
TEST(AppPrivacyReport, DefaultRequestIsAppInitiated)
{
    TestWebKitAPI::HTTPServer server(TestWebKitAPI::HTTPServer::respondWithChallengeThenOK);

    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);

    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]);
    NSString *url = [NSString stringWithFormat:@"http://127.0.0.1:%d/", server.port()];

    __block bool isDone = false;
    // Don't set the attribution API on NSURLRequest to make sure the default is app initiated.
    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
    [webView _test_waitForDidFinishNavigation];

    [webView _lastNavigationWasAppInitiated:^(BOOL isAppInitiated) {
        EXPECT_TRUE(isAppInitiated);
        isDone = true;
    }];

    TestWebKitAPI::Util::run(&isDone);

    isDone = false;
    [webView _appPrivacyReportTestingData:^(struct WKAppPrivacyReportTestingData data) {
        EXPECT_TRUE(data.hasLoadedAppInitiatedRequestTesting);
        EXPECT_FALSE(data.hasLoadedNonAppInitiatedRequestTesting);
        isDone = true;
    }];

    TestWebKitAPI::Util::run(&isDone);
}

TEST(AppPrivacyReport, AppInitiatedRequest)
{
    TestWebKitAPI::HTTPServer server(TestWebKitAPI::HTTPServer::respondWithChallengeThenOK);
    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);

    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]);
    NSString *url = [NSString stringWithFormat:@"http://127.0.0.1:%d/", server.port()];

    __block bool isDone = false;
    NSMutableURLRequest *appInitiatedRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
    appInitiatedRequest.attribution = NSURLRequestAttributionDeveloper;

    [webView loadRequest:appInitiatedRequest];
    [webView _test_waitForDidFinishNavigation];

    [webView _lastNavigationWasAppInitiated:^(BOOL isAppInitiated) {
        EXPECT_TRUE(isAppInitiated);
        isDone = true;
    }];

    TestWebKitAPI::Util::run(&isDone);

    isDone = false;
    [webView _appPrivacyReportTestingData:^(struct WKAppPrivacyReportTestingData data) {
        EXPECT_TRUE(data.hasLoadedAppInitiatedRequestTesting);
        EXPECT_FALSE(data.hasLoadedNonAppInitiatedRequestTesting);
        isDone = true;
    }];

    TestWebKitAPI::Util::run(&isDone);
}

TEST(AppPrivacyReport, NonAppInitiatedRequest)
{
    TestWebKitAPI::HTTPServer server(TestWebKitAPI::HTTPServer::respondWithChallengeThenOK);

    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);

    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]);
    NSString *url = [NSString stringWithFormat:@"http://127.0.0.1:%d/", server.port()];

    __block bool isDone = false;
    NSMutableURLRequest *nonAppInitiatedRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
    nonAppInitiatedRequest.attribution = NSURLRequestAttributionUser;

    [webView loadRequest:nonAppInitiatedRequest];
    [webView _test_waitForDidFinishNavigation];

    [webView _lastNavigationWasAppInitiated:^(BOOL isAppInitiated) {
        EXPECT_FALSE(isAppInitiated);
        isDone = true;
    }];

    TestWebKitAPI::Util::run(&isDone);

    isDone = false;
    [webView _appPrivacyReportTestingData:^(struct WKAppPrivacyReportTestingData data) {
        EXPECT_FALSE(data.hasLoadedAppInitiatedRequestTesting);
        EXPECT_TRUE(data.hasLoadedNonAppInitiatedRequestTesting);
        isDone = true;
    }];

    TestWebKitAPI::Util::run(&isDone);
}

TEST(AppPrivacyReport, AppInitiatedRequestWithNavigation)
{
    TestWebKitAPI::HTTPServer server(TestWebKitAPI::HTTPServer::respondWithChallengeThenOK);

    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);

    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]);
    NSString *appInitiatedURL = [NSString stringWithFormat:@"http://127.0.0.1:%d/", server.port()];
    NSString *nonAppInitiatedURL = [NSString stringWithFormat:@"http://localhost:%d/", server.port()];

    NSMutableURLRequest *appInitiatedRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:appInitiatedURL]];
    appInitiatedRequest.attribution = NSURLRequestAttributionDeveloper;

    [webView loadRequest:appInitiatedRequest];
    [webView _test_waitForDidFinishNavigation];

    __block bool isDone = false;
    [webView _lastNavigationWasAppInitiated:^(BOOL isAppInitiated) {
        EXPECT_TRUE(isAppInitiated);
        isDone = true;
    }];

    TestWebKitAPI::Util::run(&isDone);

    isDone = false;
    [webView _appPrivacyReportTestingData:^(struct WKAppPrivacyReportTestingData data) {
        EXPECT_TRUE(data.hasLoadedAppInitiatedRequestTesting);
        EXPECT_FALSE(data.hasLoadedNonAppInitiatedRequestTesting);
        isDone = true;
    }];

    TestWebKitAPI::Util::run(&isDone);

    isDone = false;
    NSMutableURLRequest *nonAppInitiatedRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:nonAppInitiatedURL]];
    nonAppInitiatedRequest.attribution = NSURLRequestAttributionUser;

    isDone = false;
    [webView _clearAppPrivacyReportTestingData:^{
        isDone = true;
    }];

    TestWebKitAPI::Util::run(&isDone);

    // Load a non app initated request and confirm the loads are marked correctly.
    [webView loadRequest:nonAppInitiatedRequest];
    [webView _test_waitForDidFinishNavigation];

    [webView _lastNavigationWasAppInitiated:^(BOOL isAppInitiated) {
        EXPECT_FALSE(isAppInitiated);
        isDone = true;
    }];

    TestWebKitAPI::Util::run(&isDone);

    isDone = false;
    [webView _appPrivacyReportTestingData:^(struct WKAppPrivacyReportTestingData data) {
        EXPECT_FALSE(data.hasLoadedAppInitiatedRequestTesting);
        EXPECT_TRUE(data.hasLoadedNonAppInitiatedRequestTesting);
        isDone = true;
    }];

    TestWebKitAPI::Util::run(&isDone);
}

TEST(AppPrivacyReport, AppInitiatedRequestWithSubFrame)
{
    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
    [configuration _setOverrideContentSecurityPolicy:@"script-src 'nonce-b'"];

    __block bool isDone = false;
    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
    NSMutableURLRequest *appInitiatedRequest = [NSMutableURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"page-with-csp" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
    appInitiatedRequest.attribution = NSURLRequestAttributionDeveloper;

    [webView loadRequest:appInitiatedRequest];

    [webView waitForMessage:@"MainFrame: B"];
    [webView waitForMessage:@"Subframe: B"];

    [webView _appPrivacyReportTestingData: ^(struct WKAppPrivacyReportTestingData data) {
        EXPECT_TRUE(data.hasLoadedAppInitiatedRequestTesting);
        EXPECT_FALSE(data.hasLoadedNonAppInitiatedRequestTesting);
        isDone = true;
    }];

    TestWebKitAPI::Util::run(&isDone);
}

TEST(AppPrivacyReport, NonAppInitiatedRequestWithSubFrame)
{
    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
    [configuration _setOverrideContentSecurityPolicy:@"script-src 'nonce-b'"];

    __block bool isDone = false;
    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
    NSMutableURLRequest *nonAppInitiatedRequest = [NSMutableURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"page-with-csp" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
    nonAppInitiatedRequest.attribution = NSURLRequestAttributionUser;

    [webView loadRequest:nonAppInitiatedRequest];

    [webView waitForMessage:@"MainFrame: B"];
    [webView waitForMessage:@"Subframe: B"];

    [webView _appPrivacyReportTestingData: ^(struct WKAppPrivacyReportTestingData data) {
        EXPECT_FALSE(data.hasLoadedAppInitiatedRequestTesting);
        EXPECT_TRUE(data.hasLoadedNonAppInitiatedRequestTesting);
        isDone = true;
    }];

    TestWebKitAPI::Util::run(&isDone);
}

static constexpr auto mainSWBytes = R"SWRESOURCE(
<script>
try {
    navigator.serviceWorker.register('/sw.js').then(function(reg) {
        if (reg.active) {
            alert('worker already active');
            return;
        }
        worker = reg.installing;
        worker.addEventListener('statechange', function() {
            if (worker.state == 'activated')
                alert('successfully registered');
        });
    }).catch(function(error) {
        alert('Registration failed with: ' + error);
    });
} catch(e) {
    alert('Exception: ' + e);
}
</script>
)SWRESOURCE"_s;

enum class ResponseType { Synthetic, Fetched };
enum class IsAppInitiated : bool { No, Yes };
static void runTest(ResponseType responseType, IsAppInitiated isAppInitiated)
{
    static bool isDone = false;
    [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler:^() {
        isDone = true;
    }];
    TestWebKitAPI::Util::run(&isDone);

    ASCIILiteral js;
    const char* expectedAlert = nullptr;

    switch (responseType) {
    case ResponseType::Synthetic:
        js = "self.addEventListener('fetch', (event) => { event.respondWith(new Response(new Blob(['<script>alert(\"synthetic response\")</script>'], {type: 'text/html'}))); })"_s;
        expectedAlert = "synthetic response";
        break;
    case ResponseType::Fetched:
        js = "self.addEventListener('fetch', (event) => { event.respondWith(fetch('/fetched.html')) });"_s;
        expectedAlert = "fetched from server";
        break;
    }

    TestWebKitAPI::HTTPServer server({
        { "/"_s, { mainSWBytes } },
        { "/sw.js"_s, { {{ "Content-Type"_s, "application/javascript"_s }}, js } },
        { "/fetched.html"_s, { "<script>alert('fetched from server')</script>"_s } },
    }, TestWebKitAPI::HTTPServer::Protocol::Https);

    auto webView = adoptNS([WKWebView new]);

    auto delegate = adoptNS([TestNavigationDelegate new]);
    [delegate setDidReceiveAuthenticationChallenge:^(WKWebView *, NSURLAuthenticationChallenge *challenge, void (^callback)(NSURLSessionAuthChallengeDisposition, NSURLCredential *)) {
        EXPECT_WK_STREQ(challenge.protectionSpace.authenticationMethod, NSURLAuthenticationMethodServerTrust);
        callback(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
    }];
    webView.get().navigationDelegate = delegate.get();

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://127.0.0.1:%d/", server.port()]]];
    auto attributionValue = isAppInitiated == IsAppInitiated::Yes ? NSURLRequestAttributionDeveloper : NSURLRequestAttributionUser;
    request.attribution = attributionValue;

    [webView loadRequest:request];
    EXPECT_WK_STREQ([webView _test_waitForAlert], "successfully registered");

    if (responseType != ResponseType::Fetched)
        server.cancel();

    bool expectingAppInitiatedRequests = isAppInitiated == IsAppInitiated::Yes;
    isDone = false;
    [webView _appPrivacyReportTestingData: ^(struct WKAppPrivacyReportTestingData data) {
        EXPECT_EQ(data.hasLoadedAppInitiatedRequestTesting, expectingAppInitiatedRequests);
        EXPECT_EQ(data.hasLoadedNonAppInitiatedRequestTesting, !expectingAppInitiatedRequests);
        isDone = true;
    }];

    isDone = false;
    [webView _clearAppPrivacyReportTestingData:^{
        isDone = true;
    }];

    TestWebKitAPI::Util::run(&isDone);

    [webView reload];
    EXPECT_WK_STREQ([webView _test_waitForAlert], expectedAlert);

    isDone = false;
    [webView _appPrivacyReportTestingData: ^(struct WKAppPrivacyReportTestingData data) {
        if (responseType == ResponseType::Synthetic) {
            EXPECT_FALSE(data.hasLoadedAppInitiatedRequestTesting);
            EXPECT_FALSE(data.hasLoadedNonAppInitiatedRequestTesting);
        } else {
            EXPECT_EQ(data.hasLoadedAppInitiatedRequestTesting, expectingAppInitiatedRequests);
            EXPECT_EQ(data.hasLoadedNonAppInitiatedRequestTesting, !expectingAppInitiatedRequests);
        }
        isDone = true;
    }];

    TestWebKitAPI::Util::run(&isDone);
}

TEST(AppPrivacyReport, NonAppInitiatedRequestWithServiceWorker)
{
    runTest(ResponseType::Synthetic, IsAppInitiated::No);
    runTest(ResponseType::Fetched, IsAppInitiated::No);
}

TEST(AppPrivacyReport, AppInitiatedRequestWithServiceWorker)
{
    runTest(ResponseType::Synthetic, IsAppInitiated::Yes);
    runTest(ResponseType::Fetched, IsAppInitiated::Yes);
}

TEST(AppPrivacyReport, MultipleWebViewsWithSharedServiceWorker)
{
    static bool isDone = false;

    [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler:^() {
        isDone = true;
    }];
    TestWebKitAPI::Util::run(&isDone);

    constexpr auto js = "self.addEventListener('fetch', (event) => { event.respondWith(fetch('/fetched.html')) })"_s;
    const char* expectedAlert = "fetched from server";

    TestWebKitAPI::HTTPServer server({
        { "/"_s, { mainSWBytes } },
        { "/sw.js"_s, { {{ "Content-Type"_s, "application/javascript"_s }}, js } },
        { "/fetched.html"_s, { "<script>alert('fetched from server')</script>"_s } },
    }, TestWebKitAPI::HTTPServer::Protocol::Https);

    auto webView1 = adoptNS([WKWebView new]);
    auto webView2 = adoptNS([WKWebView new]);

    auto delegate = adoptNS([TestNavigationDelegate new]);
    [delegate setDidReceiveAuthenticationChallenge:^(WKWebView *, NSURLAuthenticationChallenge *challenge, void (^callback)(NSURLSessionAuthChallengeDisposition, NSURLCredential *)) {
        EXPECT_WK_STREQ(challenge.protectionSpace.authenticationMethod, NSURLAuthenticationMethodServerTrust);
        callback(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
    }];
    webView1.get().navigationDelegate = delegate.get();
    webView2.get().navigationDelegate = delegate.get();

    NSMutableURLRequest *appInitiatedRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://127.0.0.1:%d/", server.port()]]];
    appInitiatedRequest.attribution = NSURLRequestAttributionDeveloper;
    [webView1 loadRequest:appInitiatedRequest];
    EXPECT_WK_STREQ([webView1 _test_waitForAlert], "successfully registered");

    [webView1 reload];
    EXPECT_WK_STREQ([webView1 _test_waitForAlert], expectedAlert);

    isDone = false;
    [webView1 _appPrivacyReportTestingData: ^(struct WKAppPrivacyReportTestingData data) {
        EXPECT_TRUE(data.hasLoadedAppInitiatedRequestTesting);
        EXPECT_FALSE(data.hasLoadedNonAppInitiatedRequestTesting);
        isDone = true;
    }];

    TestWebKitAPI::Util::run(&isDone);

    isDone = false;
    [webView1 _clearAppPrivacyReportTestingData:^{
        isDone = true;
    }];

    TestWebKitAPI::Util::run(&isDone);

    isDone = false;
    NSMutableURLRequest *nonAppInitiatedRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://127.0.0.1:%d/", server.port()]]];
    nonAppInitiatedRequest.attribution = NSURLRequestAttributionUser;
    [webView2 loadRequest:nonAppInitiatedRequest];
    EXPECT_WK_STREQ([webView2 _test_waitForAlert], "fetched from server");

    [webView2 reload];
    EXPECT_WK_STREQ([webView2 _test_waitForAlert], expectedAlert);

    [webView2 _appPrivacyReportTestingData: ^(struct WKAppPrivacyReportTestingData data) {
        EXPECT_FALSE(data.hasLoadedAppInitiatedRequestTesting);
        EXPECT_TRUE(data.hasLoadedNonAppInitiatedRequestTesting);
        isDone = true;
    }];
    TestWebKitAPI::Util::run(&isDone);
}

static void softUpdateTest(IsAppInitiated isAppInitiated)
{
    static bool isDone = false;
    [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler:^() {
        isDone = true;
    }];
    TestWebKitAPI::Util::run(&isDone);

    auto delegate = adoptNS([TestNavigationDelegate new]);
    [delegate setDidReceiveAuthenticationChallenge:^(WKWebView *, NSURLAuthenticationChallenge *challenge, void (^callback)(NSURLSessionAuthChallengeDisposition, NSURLCredential *)) {
        EXPECT_WK_STREQ(challenge.protectionSpace.authenticationMethod, NSURLAuthenticationMethodServerTrust);
        callback(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
    }];

    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
    auto webView1 = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
    auto webView2 = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);

    webView1.get().navigationDelegate = delegate.get();
    webView2.get().navigationDelegate = delegate.get();

    uint16_t serverPort;
    static constexpr auto js = "self.addEventListener('fetch', (event) => { event.respondWith(new Response(new Blob(['<script>alert(\"synthetic response\")</script>'], {type: 'text/html'}))); })"_s;

    {
        TestWebKitAPI::HTTPServer server1({
            { "/"_s, { mainSWBytes } },
            { "/sw.js"_s, { {{ "Content-Type"_s, "application/javascript"_s }}, js } },
        }, TestWebKitAPI::HTTPServer::Protocol::Https, nullptr, testIdentity());
        serverPort = server1.port();

        NSURLRequest *request = server1.request();
        if (isAppInitiated == IsAppInitiated::No) {
            NSMutableURLRequest *nonAppInitiatedRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://127.0.0.1:%d/", server1.port()]]];
            nonAppInitiatedRequest.attribution = NSURLRequestAttributionDeveloper;
            request = nonAppInitiatedRequest;
        }

        [webView1 loadRequest:request];
        EXPECT_WK_STREQ([webView1 _test_waitForAlert], "successfully registered");

        server1.cancel();
    }

    {
        TestWebKitAPI::HTTPServer server2({
            { "/"_s, { mainSWBytes } },
            { "/sw.js"_s, { {{ "Content-Type"_s, "application/javascript"_s }}, js } }
        }, TestWebKitAPI::HTTPServer::Protocol::Https, nullptr, testIdentity2(), serverPort);

        NSMutableURLRequest *request2 = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://127.0.0.1:%d/", server2.port()]]];
        auto attributionValue = isAppInitiated == IsAppInitiated::Yes ? NSURLRequestAttributionDeveloper : NSURLRequestAttributionUser;
        request2.attribution = attributionValue;

        isDone = false;
        [webView1 _clearAppPrivacyReportTestingData:^{
            isDone = true;
        }];

        TestWebKitAPI::Util::run(&isDone);

        [webView2 loadRequest:request2];
        EXPECT_WK_STREQ([webView2 _test_waitForAlert], "synthetic response");
    }

    isDone = false;
    bool expectingAppInitiatedRequests = isAppInitiated == IsAppInitiated::Yes ? true : false;
    while (!isDone) {
        [webView2 _appPrivacyReportTestingData: ^(struct WKAppPrivacyReportTestingData data) {
            if (!data.didPerformSoftUpdate)
                return;

            EXPECT_EQ(data.hasLoadedAppInitiatedRequestTesting, expectingAppInitiatedRequests);
            EXPECT_EQ(data.hasLoadedNonAppInitiatedRequestTesting, !expectingAppInitiatedRequests);
            isDone = true;
        }];
        TestWebKitAPI::Util::spinRunLoop(1);
    }
}

TEST(AppPrivacyReport, AppInitiatedRequestWithServiceWorkerSoftUpdate)
{
    softUpdateTest(IsAppInitiated::Yes);
}

TEST(AppPrivacyReport, NonAppInitiatedRequestWithServiceWorkerSoftUpdate)
{
    softUpdateTest(IsAppInitiated::No);
}

static void runWebProcessPlugInTest(IsAppInitiated isAppInitiated)
{
    TestWebKitAPI::HTTPServer server(TestWebKitAPI::HTTPServer::respondWithChallengeThenOK);

    WKWebViewConfiguration *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"AppPrivacyReportPlugIn"];
    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration]);

    NSString *url = [NSString stringWithFormat:@"http://127.0.0.1:%d/", server.port()];

    __block bool isDone = false;
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
    auto attributionValue = isAppInitiated == IsAppInitiated::Yes ? NSURLRequestAttributionDeveloper : NSURLRequestAttributionUser;
    request.attribution = attributionValue;

    [webView loadRequest:request];
    [webView _test_waitForDidFinishNavigation];

    isDone = false;
    bool expectingAppInitiatedRequests = isAppInitiated == IsAppInitiated::Yes ? true : false;
    [webView _appPrivacyReportTestingData:^(struct WKAppPrivacyReportTestingData data) {
        EXPECT_EQ(data.hasLoadedAppInitiatedRequestTesting, expectingAppInitiatedRequests);
        EXPECT_EQ(data.hasLoadedNonAppInitiatedRequestTesting, !expectingAppInitiatedRequests);
        isDone = true;
    }];

    TestWebKitAPI::Util::run(&isDone);
}

TEST(AppPrivacyReport, WebProcessPluginTestAppInitiated)
{
    runWebProcessPlugInTest(IsAppInitiated::Yes);
}

TEST(AppPrivacyReport, WebProcessPluginTestNonAppInitiated)
{
    runWebProcessPlugInTest(IsAppInitiated::No);
}

#if WK_HAVE_C_SPI

static constexpr auto mainSWBytesDefaultValue = R"SWRESOURCE(
<script>

function log(msg)
{
    window.webkit.messageHandlers.sw.postMessage(msg);
}

navigator.serviceWorker.addEventListener("message", function(event) {
    log(event.data);
});

try {
    navigator.serviceWorker.register('/sw.js').then(function(reg) {
        if (reg.active) {
            worker = reg.active;
            worker.postMessage("SECOND");
            return;
        }
        worker = reg.installing;
        worker.addEventListener('statechange', function() {
            if (worker.state == 'activated')
                worker.postMessage("FIRST");
        });
    }).catch(function(error) {
        log('Registration failed with: ' + error);
    });
} catch(e) {
    log('Exception: ' + e);
}
</script>
)SWRESOURCE"_s;

static constexpr auto scriptBytesDefaultValue = R"SWRESOURCE(
self.addEventListener('message', async (event) => {
    if (!self.internals) {
        event.source.postMessage('No internals');
        return;
    }

    queryAppPrivacyReportValue(event, false);
});

async function queryAppPrivacyReportValue(event, haveSentInitialMessage)
{
    var result = await internals.lastNavigationWasAppInitiated();
    if (result) {
        if (event.data == "FIRST") {
            event.source.postMessage('app initiated');
            return;
        }

        if (!haveSentInitialMessage)
            event.source.postMessage('starts app initiated');

        queryAppPrivacyReportValue(event, true);
        return;
    }

    event.source.postMessage('non app initiated');
}

)SWRESOURCE"_s;


static String expectedMessage;
static bool receivedMessage = false;

@interface SWAppInitiatedRequestMessageHandler : NSObject <WKScriptMessageHandler>
@end

@implementation SWAppInitiatedRequestMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
    EXPECT_WK_STREQ(message.body, expectedMessage);
    receivedMessage = true;
}
@end

TEST(AppPrivacyReport, RegisterServiceWorkerClientUpdatesAppInitiatedValue)
{
    static bool isDone = false;

    [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler:^() {
        isDone = true;
    }];
    TestWebKitAPI::Util::run(&isDone);

    WKWebViewConfiguration *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
    WKRetainPtr<WKContextRef> context = adoptWK(TestWebKitAPI::Util::createContextForInjectedBundleTest("InternalsInjectedBundleTest"));
    configuration.processPool = (WKProcessPool *)context.get();

    RetainPtr<SWAppInitiatedRequestMessageHandler> messageHandler = adoptNS([[SWAppInitiatedRequestMessageHandler alloc] init]);
    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"sw"];

    auto webView1 = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]);
    auto webView2 = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]);

    auto delegate = adoptNS([TestNavigationDelegate new]);
    [delegate setDidReceiveAuthenticationChallenge:^(WKWebView *, NSURLAuthenticationChallenge *challenge, void (^callback)(NSURLSessionAuthChallengeDisposition, NSURLCredential *)) {
        EXPECT_WK_STREQ(challenge.protectionSpace.authenticationMethod, NSURLAuthenticationMethodServerTrust);
        callback(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
    }];

    webView1.get().navigationDelegate = delegate.get();
    webView2.get().navigationDelegate = delegate.get();

    TestWebKitAPI::HTTPServer server({
        { "/main.html"_s, { mainSWBytesDefaultValue } },
        { "/sw.js"_s, { { { "Content-Type"_s, "application/javascript"_s } }, scriptBytesDefaultValue } },
    });

    // Load WebView with an app initiated request. We expect the ServiceWorkerThreadProxy to be app initiated.
    expectedMessage = "app initiated";
    [webView1 loadRequest:server.request("/main.html")];
    TestWebKitAPI::Util::run(&receivedMessage);

    // Load WebView with a non app initiated request. We expect the ServiceWorkerThreadProxy to be app initiated
    // at first, but then become non app initiated once the second webView is closed and its client is unregistered.
    expectedMessage = "starts app initiated";
    receivedMessage = false;
    NSMutableURLRequest *nonAppInitiatedRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://127.0.0.1:%d/main.html", server.port()]]];
    nonAppInitiatedRequest.attribution = NSURLRequestAttributionUser;

    [webView2 loadRequest:nonAppInitiatedRequest];
    TestWebKitAPI::Util::run(&receivedMessage);

    // Close the app initiated view. We expect that the existing worker will become non app initiated
    // now that all app initiated clients have been removed.
    expectedMessage = "non app initiated";
    receivedMessage = false;
    [webView1 _close];
    webView1 = nullptr;

    TestWebKitAPI::Util::run(&receivedMessage);
}

#endif // WK_HAVE_C_SPI

static void loadSimulatedRequestTest(IsAppInitiated isAppInitiated)
{
    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);

    auto delegate = adoptNS([[TestNavigationDelegate alloc] init]);
    [webView setNavigationDelegate:delegate.get()];

    NSMutableURLRequest *loadRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"about:blank"]];
    loadRequest.attribution = isAppInitiated == IsAppInitiated::Yes ? NSURLRequestAttributionDeveloper : NSURLRequestAttributionUser;

    NSString *HTML = @"<html><head></head><body><iframe src='http://127.0.0.1/'></iframe></body></html>";

    [webView loadSimulatedRequest:loadRequest responseHTMLString:HTML];
    [delegate waitForDidFinishNavigation];

    static bool isDone = false;
    bool expectingAppInitiatedRequests = isAppInitiated == IsAppInitiated::Yes ? true : false;
    [webView _appPrivacyReportTestingData:^(struct WKAppPrivacyReportTestingData data) {
        EXPECT_EQ(data.hasLoadedAppInitiatedRequestTesting, expectingAppInitiatedRequests);
        EXPECT_EQ(data.hasLoadedNonAppInitiatedRequestTesting, !expectingAppInitiatedRequests);
        isDone = true;
    }];
    TestWebKitAPI::Util::run(&isDone);
}

// FIXME: Re-enable these two tests once webkit.org/b/232166 is resolved.
TEST(AppPrivacyReport, LoadSimulatedRequestIsAppInitiated)
{
    loadSimulatedRequestTest(IsAppInitiated::Yes);
}

TEST(AppPrivacyReport, LoadSimulatedRequestIsNonAppInitiated)
{
    loadSimulatedRequestTest(IsAppInitiated::No);
}

static void restoreFromSessionStateTest(IsAppInitiated isAppInitiated)
{
    auto webView1 = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://www.apple.com/"]];
    request.attribution = isAppInitiated == IsAppInitiated::Yes ? NSURLRequestAttributionDeveloper : NSURLRequestAttributionUser;

    [webView1 loadRequest:request];
    [webView1 _test_waitForDidFinishNavigation];

    RetainPtr<_WKSessionState> sessionState = [webView1 _sessionState];
    [webView1 _close];

    static bool isDone = false;
    [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler:^() {
        isDone = true;
    }];
    TestWebKitAPI::Util::run(&isDone);

    auto webView2 = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
    [webView2 _restoreSessionState:sessionState.get() andNavigate:YES];
    [webView2 _test_waitForDidFinishNavigation];

    EXPECT_WK_STREQ(@"https://www.apple.com/", [[webView2 URL] absoluteString]);

    isDone = false;
    bool expectingAppInitiatedRequests = isAppInitiated == IsAppInitiated::Yes ? true : false;
    [webView2 _appPrivacyReportTestingData:^(struct WKAppPrivacyReportTestingData data) {
        EXPECT_EQ(data.hasLoadedAppInitiatedRequestTesting, expectingAppInitiatedRequests);
        EXPECT_EQ(data.hasLoadedNonAppInitiatedRequestTesting, !expectingAppInitiatedRequests);
        isDone = true;
    }];
    TestWebKitAPI::Util::run(&isDone);
}

TEST(AppPrivacyReport, RestoreFromSessionStateIsAppInitiated)
{
    restoreFromSessionStateTest(IsAppInitiated::Yes);
}

TEST(AppPrivacyReport, RestoreFromSessionStateIsNonAppInitiated)
{
    restoreFromSessionStateTest(IsAppInitiated::No);
}

static void restoreFromInteractionStateTest(IsAppInitiated isAppInitiated)
{
    auto webView1 = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://www.apple.com/"]];
    request.attribution = isAppInitiated == IsAppInitiated::Yes ? NSURLRequestAttributionDeveloper : NSURLRequestAttributionUser;

    [webView1 loadRequest:request];
    [webView1 _test_waitForDidFinishNavigation];

    id interactionState = [webView1 interactionState];
    [webView1 _close];

    static bool isDone = false;
    [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler:^() {
        isDone = true;
    }];
    TestWebKitAPI::Util::run(&isDone);

    auto webView2 = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
    [webView2 setInteractionState:interactionState];
    [webView2 _test_waitForDidFinishNavigation];

    EXPECT_WK_STREQ(@"https://www.apple.com/", [[webView2 URL] absoluteString]);

    isDone = false;
    bool expectingAppInitiatedRequests = isAppInitiated == IsAppInitiated::Yes ? true : false;
    [webView2 _appPrivacyReportTestingData:^(struct WKAppPrivacyReportTestingData data) {
        EXPECT_EQ(data.hasLoadedAppInitiatedRequestTesting, expectingAppInitiatedRequests);
        EXPECT_EQ(data.hasLoadedNonAppInitiatedRequestTesting, !expectingAppInitiatedRequests);
        isDone = true;
    }];
    TestWebKitAPI::Util::run(&isDone);
}

TEST(AppPrivacyReport, RestoreFromInteractionStateIsAppInitiated)
{
    restoreFromInteractionStateTest(IsAppInitiated::Yes);
}

TEST(AppPrivacyReport, RestoreFromInteractionStateIsNonAppInitiated)
{
    restoreFromInteractionStateTest(IsAppInitiated::No);
}

static void loadFileTest(IsAppInitiated isAppInitiated)
{
    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);

    NSURL *file = [[NSBundle mainBundle] URLForResource:@"file-with-iframe" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:file];
    request.attribution = isAppInitiated == IsAppInitiated::Yes ? NSURLRequestAttributionDeveloper : NSURLRequestAttributionUser;

    [webView loadFileRequest:request allowingReadAccessToURL:file.URLByDeletingLastPathComponent];
    [webView _test_waitForDidFinishNavigation];

    static bool isDone = false;
    bool expectingAppInitiatedRequests = isAppInitiated == IsAppInitiated::Yes ? true : false;
    [webView _appPrivacyReportTestingData:^(struct WKAppPrivacyReportTestingData data) {
        EXPECT_EQ(data.hasLoadedAppInitiatedRequestTesting, expectingAppInitiatedRequests);
        EXPECT_EQ(data.hasLoadedNonAppInitiatedRequestTesting, !expectingAppInitiatedRequests);
        isDone = true;
    }];
    TestWebKitAPI::Util::run(&isDone);
}

TEST(AppPrivacyReport, LoadFileRequestIsAppInitiated)
{
    loadFileTest(IsAppInitiated::Yes);
}

TEST(AppPrivacyReport, LoadFileRequestIsNonAppInitiated)
{
    loadFileTest(IsAppInitiated::No);
}

TEST(AppPrivacyReport, NSURLRequestConstructorAttribution)
{
    NSString *url = @"https://webkit.org";

    NSMutableURLRequest *appInitiatedRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
    EXPECT_EQ(appInitiatedRequest.attribution, NSURLRequestAttributionDeveloper);

    WebCore::ResourceRequest testRequest(appInitiatedRequest);
    EXPECT_TRUE(testRequest.isAppInitiated());

    WebCore::ResourceRequest testRequestCopy(testRequest);
    EXPECT_TRUE(testRequestCopy.isAppInitiated());

    auto nsRequestFromCopy = testRequestCopy.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody);
    EXPECT_EQ(nsRequestFromCopy.attribution, NSURLRequestAttributionDeveloper);
    
    appInitiatedRequest.attribution = NSURLRequestAttributionUser;
    WebCore::ResourceRequest testRequest2(appInitiatedRequest);
    EXPECT_FALSE(testRequest2.isAppInitiated());

    WebCore::ResourceRequest testRequestCopy2(testRequest2);
    EXPECT_FALSE(testRequestCopy2.isAppInitiated());

    auto nsRequestFromCopy2 = testRequestCopy2.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody);
    EXPECT_EQ(nsRequestFromCopy2.attribution, NSURLRequestAttributionUser);

    appInitiatedRequest.attribution = NSURLRequestAttributionDeveloper;
    WebCore::ResourceRequest testRequest3(appInitiatedRequest);
    EXPECT_TRUE(testRequest3.isAppInitiated());

    auto nsRequestFromModifiedRequest = testRequest3.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody);
    EXPECT_EQ(nsRequestFromModifiedRequest.attribution, NSURLRequestAttributionDeveloper);

    testRequest3.setIsAppInitiated(false);
    auto nsRequestFromModifiedRequest2 = testRequest3.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody);
    EXPECT_EQ(nsRequestFromModifiedRequest2.attribution, NSURLRequestAttributionUser);

    testRequest3.setIsAppInitiated(true);
    auto nsRequestFromModifiedRequest3 = testRequest3.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody);
    EXPECT_EQ(nsRequestFromModifiedRequest3.attribution, NSURLRequestAttributionDeveloper);

    // Changing the nsURLRequest copy generated by the accessor doesn't change the ResourceRequest
    appInitiatedRequest.attribution = NSURLRequestAttributionUser;
    EXPECT_TRUE(testRequest.isAppInitiated());

    WebCore::ResourceRequest testRequest4(appInitiatedRequest);
    EXPECT_FALSE(testRequest4.isAppInitiated());
}

#endif // APP_PRIVACY_REPORT
