/*
 * Copyright (C) 2014 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"

#if PLATFORM(MAC)

#import "PlatformUtilities.h"
#import "TestNavigationDelegate.h"
#import "TestURLSchemeHandler.h"
#import <WebKit/WKNavigationActionPrivate.h>
#import <WebKit/WKWebViewPrivate.h>
#import <wtf/RetainPtr.h>

static bool createdWebView;
static bool decidedPolicy;
static bool finishedNavigation;
static RetainPtr<WKNavigationAction> action;
static RetainPtr<WKWebView> newWebView;

@interface ShouldOpenExternalURLsInNewWindowActionsController : NSObject <WKNavigationDelegate, WKUIDelegate>
@end

@implementation ShouldOpenExternalURLsInNewWindowActionsController

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    decisionHandler(webView == newWebView.get() ? WKNavigationActionPolicyCancel : WKNavigationActionPolicyAllow);

    action = navigationAction;
    decidedPolicy = true;
}

- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
    finishedNavigation = true;
}

- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
{
    action = navigationAction;
    newWebView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration]);

    createdWebView = true;
    return newWebView.get();
}

@end

TEST(WebKit, ShouldOpenExternalURLsInWindowOpen)
{
    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);

    auto window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:YES]);
    [[window contentView] addSubview:webView.get()];

    auto controller = adoptNS([[ShouldOpenExternalURLsInNewWindowActionsController alloc] init]);
    [webView setNavigationDelegate:controller.get()];
    [webView setUIDelegate:controller.get()];

    [webView loadHTMLString:@"<body onclick=\"window.open('https://webkit.org/destination')\">" baseURL:[NSURL URLWithString:@"http://webkit.org"]];
    TestWebKitAPI::Util::run(&finishedNavigation);
    finishedNavigation = false;

    NSPoint clickPoint = NSMakePoint(100, 100);

    [[webView hitTest:clickPoint] mouseDown:[NSEvent mouseEventWithType:NSEventTypeLeftMouseDown location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]];
    [[webView hitTest:clickPoint] mouseUp:[NSEvent mouseEventWithType:NSEventTypeLeftMouseUp location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]];
    TestWebKitAPI::Util::run(&createdWebView);
    createdWebView = false;

    // User-initiated window.open to the same host should allow external schemes but not App Links.
    ASSERT_TRUE([action _shouldOpenExternalSchemes]);
    ASSERT_FALSE([action _shouldOpenAppLinks]);

    decidedPolicy = false;
    [newWebView setNavigationDelegate:controller.get()];
    TestWebKitAPI::Util::run(&decidedPolicy);
    decidedPolicy = false;

    // User-initiated window.open to the same host should allow external schemes but not App Links.
    ASSERT_TRUE([action _shouldOpenExternalSchemes]);
    ASSERT_FALSE([action _shouldOpenAppLinks]);

    [webView loadHTMLString:@"<body onclick=\"window.open('http://apple.com/destination')\">" baseURL:[NSURL URLWithString:@"http://webkit.org"]];
    TestWebKitAPI::Util::run(&finishedNavigation);
    finishedNavigation = false;

    [[webView hitTest:clickPoint] mouseDown:[NSEvent mouseEventWithType:NSEventTypeLeftMouseDown location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]];
    [[webView hitTest:clickPoint] mouseUp:[NSEvent mouseEventWithType:NSEventTypeLeftMouseUp location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]];
    TestWebKitAPI::Util::run(&createdWebView);
    createdWebView = false;

    // User-initiated window.open to different host should allow external schemes and App Links.
    ASSERT_TRUE([action _shouldOpenExternalSchemes]);
    ASSERT_TRUE([action _shouldOpenAppLinks]);

    decidedPolicy = false;
    [newWebView setNavigationDelegate:controller.get()];
    TestWebKitAPI::Util::run(&decidedPolicy);
    decidedPolicy = false;

    // User-initiated window.open to different host should allow external schemes and App Links.
    ASSERT_TRUE([action _shouldOpenExternalSchemes]);
    ASSERT_TRUE([action _shouldOpenAppLinks]);

    newWebView = nullptr;
    action = nullptr;
}

TEST(WebKit, ShouldOpenExternalURLsInTargetedLink)
{
    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);

    auto window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:YES]);
    [[window contentView] addSubview:webView.get()];

    auto controller = adoptNS([[ShouldOpenExternalURLsInNewWindowActionsController alloc] init]);
    [webView setNavigationDelegate:controller.get()];
    [webView setUIDelegate:controller.get()];

    [webView loadHTMLString:@"<a style=\"display: block; height: 100%\" href=\"https://webkit.org/destination.html\" target=\"_blank\">" baseURL:[NSURL URLWithString:@"http://webkit.org"]];
    TestWebKitAPI::Util::run(&finishedNavigation);
    finishedNavigation = false;

    NSPoint clickPoint = NSMakePoint(100, 100);

    decidedPolicy = false;
    [[webView hitTest:clickPoint] mouseDown:[NSEvent mouseEventWithType:NSEventTypeLeftMouseDown location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]];
    [[webView hitTest:clickPoint] mouseUp:[NSEvent mouseEventWithType:NSEventTypeLeftMouseUp location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]];
    TestWebKitAPI::Util::run(&decidedPolicy);
    decidedPolicy = false;

    // User-initiated targeted navigation to the same host should allow external schemes but not App Links.
    ASSERT_TRUE([action _shouldOpenExternalSchemes]);
    ASSERT_FALSE([action _shouldOpenAppLinks]);

    TestWebKitAPI::Util::run(&createdWebView);
    createdWebView = false;

    // User-initiated targeted navigation to the same host should allow external schemes but not App Links.
    ASSERT_TRUE([action _shouldOpenExternalSchemes]);
    ASSERT_FALSE([action _shouldOpenAppLinks]);

    decidedPolicy = false;
    [newWebView setNavigationDelegate:controller.get()];
    TestWebKitAPI::Util::run(&decidedPolicy);
    decidedPolicy = false;

    // User-initiated targeted navigation to the same host should allow external schemes but not App Links.
    ASSERT_TRUE([action _shouldOpenExternalSchemes]);
    ASSERT_FALSE([action _shouldOpenAppLinks]);

    [webView loadHTMLString:@"<a style=\"display: block; height: 100%\" href=\"http://apple.com/destination.html\" target=\"_blank\">" baseURL:[NSURL URLWithString:@"http://webkit.org"]];
    TestWebKitAPI::Util::run(&finishedNavigation);
    finishedNavigation = false;

    decidedPolicy = false;
    [[webView hitTest:clickPoint] mouseDown:[NSEvent mouseEventWithType:NSEventTypeLeftMouseDown location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]];
    [[webView hitTest:clickPoint] mouseUp:[NSEvent mouseEventWithType:NSEventTypeLeftMouseUp location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]];
    TestWebKitAPI::Util::run(&decidedPolicy);
    decidedPolicy = false;

    // User-initiated targeted navigation to different host should allow external schemes and App Links.
    ASSERT_TRUE([action _shouldOpenExternalSchemes]);
    ASSERT_TRUE([action _shouldOpenAppLinks]);

    TestWebKitAPI::Util::run(&createdWebView);
    createdWebView = false;

    // User-initiated targeted navigation to different host should allow external schemes and App Links.
    ASSERT_TRUE([action _shouldOpenExternalSchemes]);
    ASSERT_TRUE([action _shouldOpenAppLinks]);

    decidedPolicy = false;
    [newWebView setNavigationDelegate:controller.get()];
    TestWebKitAPI::Util::run(&decidedPolicy);
    decidedPolicy = false;

    // User-initiated targeted navigation to different host should allow external schemes and App Links.
    ASSERT_TRUE([action _shouldOpenExternalSchemes]);
    ASSERT_TRUE([action _shouldOpenAppLinks]);

    newWebView = nullptr;
    action = nullptr;
}

TEST(WebKit, RestoreShouldOpenExternalURLsPolicyAfterCrash)
{
    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
    auto window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:YES]);
    [[window contentView] addSubview:webView.get()];
    auto controller = adoptNS([[ShouldOpenExternalURLsInNewWindowActionsController alloc] init]);
    [webView setNavigationDelegate:controller.get()];
    [webView setUIDelegate:controller.get()];

    finishedNavigation = false;
    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"should-open-external-schemes" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
    [webView loadRequest:request];
    TestWebKitAPI::Util::run(&finishedNavigation);
    finishedNavigation = false;

    // Before crash
    decidedPolicy = false;
    [webView evaluateJavaScript:@"navigateToTelURLInNestedZeroTimer()" completionHandler:nil]; // Non-user initiated navigation because it is performed in a nested timer callback.
    TestWebKitAPI::Util::run(&decidedPolicy);
    decidedPolicy = false;

    ASSERT_TRUE([action _shouldOpenExternalSchemes]);
    ASSERT_FALSE([action _shouldOpenAppLinks]);

    // Crash
    [webView _killWebContentProcessAndResetState];
    [webView reload];

    finishedNavigation = false;
    TestWebKitAPI::Util::run(&finishedNavigation);
    finishedNavigation = false;

    // After crash
    decidedPolicy = false;
    [webView evaluateJavaScript:@"navigateToTelURLInNestedZeroTimer()" completionHandler:nil]; // Non-user initiated navigation because it is performed in a nested timer callback.
    TestWebKitAPI::Util::run(&decidedPolicy);
    decidedPolicy = false;

    ASSERT_TRUE([action _shouldOpenExternalSchemes]);
    ASSERT_FALSE([action _shouldOpenAppLinks]);
};



static const char* iframeBytes = R"schemeresource(
<script>
top.location.href = "externalScheme://someotherhost/foo";
</script>
)schemeresource";

static const char* mainFrameBytes = R"schemeresource(
<script>
function clicked() {
    var iframe = document.createElement('iframe');
    iframe.src = "custom://firsthost/iframe.html";
    document.body.appendChild(iframe);
}
</script>

<a style="display: block; height: 100%" onclick="clicked();">Click to start iframe dance</a>
)schemeresource";

TEST(WebKit, IFrameWithSameOriginAsMainFramePropagates)
{
    auto schemeHandler = adoptNS([[TestURLSchemeHandler alloc] init]);
    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
    [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"custom"];

    [schemeHandler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
        NSURL *requestURL = [task request].URL;
        
        NSString *responseText = nil;
        if ([[task request].URL.absoluteString containsString:@"iframe.html"])
            responseText = [NSString stringWithUTF8String:iframeBytes];
        else if ([[task request].URL.absoluteString containsString:@"mainframe.html"])
            responseText = [NSString stringWithUTF8String:mainFrameBytes];

        auto response = adoptNS([[NSURLResponse alloc] initWithURL:requestURL MIMEType:@"text/html" expectedContentLength:[responseText length] textEncodingName:nil]);
        [task didReceiveResponse:response.get()];
        [task didReceiveData:[responseText dataUsingEncoding:NSUTF8StringEncoding]];
        [task didFinish];
    }];

    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
    auto navigationDelegate = adoptNS([[TestNavigationDelegate alloc] init]);
    [webView setNavigationDelegate:navigationDelegate.get()];

    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"custom://firsthost/mainframe.html"]]];
    [navigationDelegate waitForDidFinishNavigation];
    
    // Install the decidePolicyListener
    static bool openAppLinks;
    static bool externalSchemes;
    static bool finished = false;
    navigationDelegate.get().decidePolicyForNavigationAction = ^(WKNavigationAction *action, void (^decisionHandler)(WKNavigationActionPolicy)) {
        if (!action.targetFrame.mainFrame) {
            decisionHandler(WKNavigationActionPolicyAllow);
            return;
        }

        openAppLinks = [action _shouldOpenAppLinks];
        externalSchemes = [action _shouldOpenExternalSchemes];
        
        decisionHandler(WKNavigationActionPolicyCancel);
        finished = true;
    };
    
    // Click the link
    NSPoint clickPoint = NSMakePoint(100, 100);
    [[webView hitTest:clickPoint] mouseDown:[NSEvent mouseEventWithType:NSEventTypeLeftMouseDown location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[webView.get().window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]];
    [[webView hitTest:clickPoint] mouseUp:[NSEvent mouseEventWithType:NSEventTypeLeftMouseUp location:clickPoint modifierFlags:0 timestamp:0 windowNumber:[webView.get().window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1]];

    TestWebKitAPI::Util::run(&finished);
    
    ASSERT_TRUE(openAppLinks);
    ASSERT_TRUE(externalSchemes);
};

#endif
