/*
 * Copyright (C) 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 "PlatformUtilities.h"
#import "Test.h"
#import "TestWKWebView.h"
#import <WebKit/WKWebViewPrivate.h>
#import <WebKit/_WKFocusedElementInfo.h>
#import <WebKit/_WKFormInputSession.h>
#import <WebKit/_WKInputDelegate.h>
#import <wtf/BlockPtr.h>
#import <wtf/RetainPtr.h>

static bool done;
static bool willSubmitFormValuesCalled;

@interface InputDelegate : NSObject <_WKInputDelegate, WKURLSchemeHandler>
@property (nonatomic, copy) BOOL(^shouldStartInputSessionHandler)(id <_WKFocusedElementInfo>);
@end

@implementation InputDelegate {
    BlockPtr<BOOL(id <_WKFocusedElementInfo>)> _shouldStartInputSessionHandler;
}

- (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)task
{
    EXPECT_TRUE(willSubmitFormValuesCalled);
    EXPECT_STREQ(task.request.URL.absoluteString.UTF8String, "test:///formtarget");
    EXPECT_NOT_NULL(task.request.HTTPBody);
    EXPECT_EQ(task.request.HTTPBody.length, 62u);
    EXPECT_STREQ(static_cast<const char*>(task.request.HTTPBody.bytes), "testname1=testvalue1&testname2=testvalue2&testname3=testvalue3");
    done = true;
}

- (void)webView:(WKWebView *)webView stopURLSchemeTask:(id <WKURLSchemeTask>)task
{
}

- (void)_webView:(WKWebView *)webView willSubmitFormValues:(NSDictionary *)values userObject:(NSObject <NSSecureCoding> *)userObject submissionHandler:(void (^)(void))submissionHandler
{
    EXPECT_EQ(values.count, 2u);
    EXPECT_STREQ([[values objectForKey:@"testname1"] UTF8String], "testvalue1");
    EXPECT_STREQ([[values objectForKey:@"testname2"] UTF8String], "testvalue2");
    willSubmitFormValuesCalled = true;
    submissionHandler();
}

- (BOOL)_webView:(WKWebView *)webView focusShouldStartInputSession:(id <_WKFocusedElementInfo>)info
{
    if (_shouldStartInputSessionHandler)
        return _shouldStartInputSessionHandler(info);
    return [info isUserInitiated];
}

- (BOOL(^)(id <_WKFocusedElementInfo>))shouldStartInputSessionHandler
{
    return _shouldStartInputSessionHandler.get();
}

- (void)setShouldStartInputSessionHandler:(BOOL(^)(id <_WKFocusedElementInfo>))handler
{
    _shouldStartInputSessionHandler = makeBlockPtr(handler);
}

@end

TEST(WebKit, FormSubmission)
{
    auto delegate = adoptNS([[InputDelegate alloc] init]);
    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
    [configuration setURLSchemeHandler:delegate.get() forURLScheme:@"test"];
    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
    [webView _setInputDelegate:delegate.get()];
    [webView loadHTMLString:@"<body onload='document.getElementById(\"formID\").submit()'><form id='formID' method='post' action='test:///formtarget'>"
        "<input type='text' name='testname1' value='testvalue1'/>"
        "<input type='password' name='testname2' value='testvalue2'/>"
        "<input type='hidden' name='testname3' value='testvalue3'/>"
    "</form></body>" baseURL:nil];
    TestWebKitAPI::Util::run(&done);
}

#if PLATFORM(IOS_FAMILY)

TEST(WebKit, FocusedElementInfo)
{
    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
    auto delegate = adoptNS([[InputDelegate alloc] init]);
    [webView _setInputDelegate:delegate.get()];

    __block RetainPtr<id <_WKFocusedElementInfo>> currentElement;
    [delegate setShouldStartInputSessionHandler:^BOOL(id<_WKFocusedElementInfo> element) {
        currentElement = element;
        return NO;
    }];

    [webView synchronouslyLoadHTMLString:@"<label for='foo'>bar</label><input id='foo'>"];
    [webView stringByEvaluatingJavaScript:@"foo.focus()"];
    [webView waitForNextPresentationUpdate];
    EXPECT_WK_STREQ("", [currentElement placeholder]);
    EXPECT_WK_STREQ("bar", [currentElement label]);

    [webView synchronouslyLoadHTMLString:@"<input placeholder='bar'>"];
    [webView stringByEvaluatingJavaScript:@"document.querySelector('input').focus()"];
    [webView waitForNextPresentationUpdate];
    EXPECT_WK_STREQ("bar", [currentElement placeholder]);
    EXPECT_WK_STREQ("", [currentElement label]);

    [webView synchronouslyLoadHTMLString:@"<label for='baz'>garply</label><select id='baz'></select>"];
    [webView stringByEvaluatingJavaScript:@"baz.focus()"];
    [webView waitForNextPresentationUpdate];
    EXPECT_WK_STREQ("", [currentElement placeholder]);
    EXPECT_WK_STREQ("garply", [currentElement label]);

    [webView synchronouslyLoadHTMLString:@"<label for='foo' style='display: none'>bar</label><label for='foo'></label><input id='foo'><label for='foo'>garply</label>"];
    [webView stringByEvaluatingJavaScript:@"foo.focus()"];
    [webView waitForNextPresentationUpdate];
    EXPECT_WK_STREQ("", [currentElement placeholder]);
    EXPECT_WK_STREQ("garply", [currentElement label]);
}

#endif // PLATFORM(IOS_FAMILY)


