/*
 * 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"

#import "PlatformUtilities.h"
#import <WebKit/WKPreferences.h>
#import <WebKit/WKUIDelegatePrivate.h>
#import <WebKit/WKWebView.h>
#import <WebKit/WKWebViewConfiguration.h>
#import <WebKit/WKWindowFeaturesPrivate.h>
#import <wtf/RetainPtr.h>

@class OpenAndCloseWindowUIDelegate;
@class OpenAndCloseWindowUIDelegateAsync;
@class CheckWindowFeaturesUIDelegate;

static bool isDone;
static RetainPtr<WKWebView> openedWebView;
static RetainPtr<WKWindowFeatures> openWindowFeatures;
static RetainPtr<OpenAndCloseWindowUIDelegate> sharedUIDelegate;
static RetainPtr<OpenAndCloseWindowUIDelegateAsync> sharedUIDelegateAsync;
static RetainPtr<CheckWindowFeaturesUIDelegate> sharedCheckWindowFeaturesUIDelegate;

static void resetToConsistentState()
{
    isDone = false;
    openedWebView = nil;
    sharedUIDelegate = nil;
    sharedUIDelegateAsync = nil;
    sharedCheckWindowFeaturesUIDelegate = nil;
}

@interface OpenAndCloseWindowUIDelegate : NSObject <WKUIDelegate>
@property (nonatomic, assign) WKWebView *expectedClosingView;
@end

@implementation OpenAndCloseWindowUIDelegate

- (void)webViewDidClose:(WKWebView *)webView
{
    EXPECT_EQ(_expectedClosingView, webView);
    isDone = true;
}

- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
{
    openedWebView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]);
    [openedWebView setUIDelegate:sharedUIDelegate.get()];
    _expectedClosingView = openedWebView.get();
    return openedWebView.get();
}

@end

TEST(WebKit, OpenAndCloseWindow)
{
    resetToConsistentState();

    RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);

    sharedUIDelegate = adoptNS([[OpenAndCloseWindowUIDelegate alloc] init]);
    [webView setUIDelegate:sharedUIDelegate.get()];

    [webView configuration].preferences.javaScriptCanOpenWindowsAutomatically = YES;

    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"open-and-close-window" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
    [webView loadRequest:request];

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

@interface OpenAndCloseWindowUIDelegateAsync : OpenAndCloseWindowUIDelegate
@property (nonatomic) BOOL shouldCallback;
@property (nonatomic, assign) id savedCompletionHandler;
@property (nonatomic) BOOL shouldCallbackWithNil;
@end

@implementation OpenAndCloseWindowUIDelegateAsync

- (void)dealloc
{
    [_savedCompletionHandler release];
    [super dealloc];
}

- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
{
    ASSERT_NOT_REACHED();
    return nil;
}

- (void)_webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures completionHandler:(void (^)(WKWebView *webView))completionHandler
{
    if (_shouldCallback) {
        if (!_shouldCallbackWithNil) {
            dispatch_async(dispatch_get_main_queue(), ^ {
                openedWebView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]);
                [openedWebView setUIDelegate:sharedUIDelegateAsync.get()];
                self.expectedClosingView = openedWebView.get();
                completionHandler(openedWebView.get());
            });
        } else {
            dispatch_async(dispatch_get_main_queue(), ^ {
                self.expectedClosingView = webView;
                completionHandler(nil);
            });
        }
        return;
    }

    _savedCompletionHandler = [completionHandler copy];
    isDone = true;
}

@end

TEST(WebKit, OpenAndCloseWindowAsync)
{
    resetToConsistentState();

    RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);

    sharedUIDelegateAsync = adoptNS([[OpenAndCloseWindowUIDelegateAsync alloc] init]);
    sharedUIDelegateAsync.get().shouldCallback = YES;
    [webView setUIDelegate:sharedUIDelegateAsync.get()];

    [webView configuration].preferences.javaScriptCanOpenWindowsAutomatically = YES;

    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"open-and-close-window" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
    [webView loadRequest:request];

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

TEST(WebKit, OpenAsyncWithNil)
{
    resetToConsistentState();

    RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);

    sharedUIDelegateAsync = adoptNS([[OpenAndCloseWindowUIDelegateAsync alloc] init]);
    sharedUIDelegateAsync.get().shouldCallback = YES;
    sharedUIDelegateAsync.get().shouldCallbackWithNil = YES;
    [webView setUIDelegate:sharedUIDelegateAsync.get()];

    [webView configuration].preferences.javaScriptCanOpenWindowsAutomatically = YES;

    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"open-and-close-window" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
    [webView loadRequest:request];

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

// https://bugs.webkit.org/show_bug.cgi?id=171083 - Try to figure out why this fails for some configs but not others, and resolve.
//TEST(WebKit, OpenAndCloseWindowAsyncCallbackException)
//{
//    resetToConsistentState();
//
//    RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
//
//    sharedUIDelegateAsync = adoptNS([[OpenAndCloseWindowUIDelegateAsync alloc] init]);
//    sharedUIDelegateAsync.get().shouldCallback = NO;
//    [webView setUIDelegate:sharedUIDelegateAsync.get()];
//
//    [webView configuration].preferences.javaScriptCanOpenWindowsAutomatically = YES;
//
//    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"open-and-close-window" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
//    [webView loadRequest:request];
//
//    TestWebKitAPI::Util::run(&isDone);
//
//    bool caughtException = false;
//    @try {
//        sharedUIDelegateAsync = nil;
//        openedWebView = nil;
//        webView = nil;
//    }
//    @catch (NSException *) {
//        caughtException = true;
//    }
//
//    EXPECT_EQ(caughtException, true);
//}


@interface CheckWindowFeaturesUIDelegate : NSObject <WKUIDelegate>

@property (nullable, nonatomic, readonly) NSNumber *menuBarVisibility;
@property (nullable, nonatomic, readonly) NSNumber *statusBarVisibility;
@property (nullable, nonatomic, readonly) NSNumber *toolbarsVisibility;

@end

@implementation CheckWindowFeaturesUIDelegate

- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
{
    openWindowFeatures = windowFeatures;
    isDone = true;

    return nil;
}

@end

TEST(WebKit, OpenWindowFeatures)
{
    resetToConsistentState();

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

    sharedCheckWindowFeaturesUIDelegate = adoptNS([[CheckWindowFeaturesUIDelegate alloc] init]);
    [webView setUIDelegate:sharedCheckWindowFeaturesUIDelegate.get()];
    [webView configuration].preferences.javaScriptCanOpenWindowsAutomatically = YES;
    NSString *windowOpenFormatString = @"window.open(\"about:blank\", \"_blank\", \"%@\")";

    [webView evaluateJavaScript:@"window.open(\"about:blank\")" completionHandler:nil];
    TestWebKitAPI::Util::run(&isDone);
    isDone = false;

//  https://bugs.webkit.org/show_bug.cgi?id=174271 - WebCore currently doesn't distinguish between unspecified (nil) and false
//  for the following window features.
//  EXPECT_TRUE([openWindowFeatures menuBarVisibility] == nil);
//  EXPECT_TRUE([openWindowFeatures statusBarVisibility] == nil);
//  EXPECT_TRUE([openWindowFeatures toolbarsVisibility] == nil);
//  EXPECT_TRUE([openWindowFeatures allowsResizing] == nil);
//  EXPECT_TRUE([openWindowFeatures _locationBarVisibility] == nil);
//  EXPECT_TRUE([openWindowFeatures _scrollbarsVisibility] == nil);
//  EXPECT_TRUE([openWindowFeatures _fullscreenDisplay] == nil);
//  EXPECT_TRUE([openWindowFeatures _dialogDisplay] == nil);
    openWindowFeatures = nullptr;

    NSString *featuresStringAllSpecifiedAndTrue = @"menubar=yes,status=yes,toolbar=yes,resizable=yes,location=yes,scrollbars=yes,fullscreen=yes";
    [webView evaluateJavaScript:[NSString stringWithFormat:windowOpenFormatString, featuresStringAllSpecifiedAndTrue] completionHandler:nil];
    TestWebKitAPI::Util::run(&isDone);
    isDone = false;

    EXPECT_TRUE([openWindowFeatures menuBarVisibility].boolValue);
    EXPECT_TRUE([openWindowFeatures statusBarVisibility].boolValue);
    EXPECT_TRUE([openWindowFeatures toolbarsVisibility].boolValue);
    EXPECT_TRUE([openWindowFeatures allowsResizing].boolValue);
    EXPECT_TRUE([openWindowFeatures _locationBarVisibility].boolValue);
    EXPECT_TRUE([openWindowFeatures _scrollbarsVisibility].boolValue);
    EXPECT_TRUE([openWindowFeatures _fullscreenDisplay].boolValue);
    openWindowFeatures = nullptr;

    NSString *featuresStringAllSpecifiedAndFalse = @"menubar=no,status=no,toolbar=no,resizable=no,location=no,scrollbars=no,fullscreen=no";
    [webView evaluateJavaScript:[NSString stringWithFormat:windowOpenFormatString, featuresStringAllSpecifiedAndFalse] completionHandler:nil];
    TestWebKitAPI::Util::run(&isDone);
    isDone = false;

    EXPECT_FALSE([openWindowFeatures menuBarVisibility].boolValue);
    EXPECT_FALSE([openWindowFeatures statusBarVisibility ].boolValue);
    EXPECT_FALSE([openWindowFeatures toolbarsVisibility].boolValue);
//  https://bugs.webkit.org/show_bug.cgi?id=174388 - This property doesn't accurately reflect the parameters passed by the webpage.
//  EXPECT_FALSE([openWindowFeatures allowsResizing].boolValue);
    EXPECT_FALSE([openWindowFeatures _locationBarVisibility].boolValue);
    EXPECT_FALSE([openWindowFeatures _scrollbarsVisibility].boolValue);
    EXPECT_FALSE([openWindowFeatures _fullscreenDisplay].boolValue);
    openWindowFeatures = nullptr;
}

@interface OpenWindowThenDocumentOpenUIDelegate : NSObject <WKUIDelegate>
@end

@implementation OpenWindowThenDocumentOpenUIDelegate

- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
{
    openedWebView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]);
    [openedWebView setUIDelegate:sharedUIDelegate.get()];
    return openedWebView.get();
}

@end

TEST(WebKit, OpenWindowThenDocumentOpen)
{
    resetToConsistentState();

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

    auto uiDelegate = adoptNS([[OpenWindowThenDocumentOpenUIDelegate alloc] init]);
    [webView setUIDelegate:uiDelegate.get()];
    [webView configuration].preferences.javaScriptCanOpenWindowsAutomatically = YES;

    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"open-window-then-write-to-it" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
    [webView loadRequest:request];

    while (!openedWebView)
        TestWebKitAPI::Util::sleep(0.1);

    // Both WebViews should have the same URL because of document.open().
    while (![[[openedWebView URL] absoluteString] isEqualToString:[[webView URL] absoluteString]])
        TestWebKitAPI::Util::sleep(0.1);

    EXPECT_TRUE([[[openedWebView _mainFrameURL] absoluteString] isEqualToString:[[webView URL] absoluteString]]);
}

TEST(WebKit, OpenFileURLWithHost)
{
    resetToConsistentState();

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

    auto uiDelegate = adoptNS([[OpenWindowThenDocumentOpenUIDelegate alloc] init]);
    [webView setUIDelegate:uiDelegate.get()];
    [webView configuration].preferences.javaScriptCanOpenWindowsAutomatically = YES;

    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"open-window-with-file-url-with-host" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
    [webView loadRequest:request];

    while (![[[webView URL] absoluteString] hasSuffix:@"#test"])
        TestWebKitAPI::Util::spinRunLoop();

    while (![[[webView URL] absoluteString] hasPrefix:@"file:///"])
        TestWebKitAPI::Util::spinRunLoop();
}
