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

#if ENABLE(MEDIA_STREAM) && PLATFORM(MAC)

#import "DeprecatedGlobalValues.h"
#import "PlatformUtilities.h"
#import "Test.h"
#import "TestWKWebView.h"
#import <WebKit/WKPreferencesPrivate.h>
#import <WebKit/WKUIDelegatePrivate.h>
#import <WebKit/WKWebView.h>
#import <WebKit/WKWebViewConfiguration.h>
#import <WebKit/WKWebViewConfigurationPrivate.h>

static bool shouldDeny = false;
static _WKCaptureDevices requestedDevices = 0;

@interface GetDisplayMediaMessageHandler : NSObject <WKScriptMessageHandler>
@end

@implementation GetDisplayMediaMessageHandler

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
    lastScriptMessage = message;
    receivedScriptMessage = true;
}
@end

@interface GetDisplayMediaUIDelegate : NSObject<WKUIDelegate>
- (void)_webView:(WKWebView *)webView requestUserMediaAuthorizationForDevices:(_WKCaptureDevices)devices url:(NSURL *)url mainFrameURL:(NSURL *)mainFrameURL decisionHandler:(void (^)(BOOL authorized))decisionHandler;
- (void)_webView:(WKWebView *)webView checkUserMediaPermissionForURL:(NSURL *)url mainFrameURL:(NSURL *)mainFrameURL frameIdentifier:(NSUInteger)frameIdentifier decisionHandler:(void (^)(NSString *salt, BOOL authorized))decisionHandler;
@end

@implementation GetDisplayMediaUIDelegate
- (void)_webView:(WKWebView *)webView requestUserMediaAuthorizationForDevices:(_WKCaptureDevices)devices url:(NSURL *)url mainFrameURL:(NSURL *)mainFrameURL decisionHandler:(void (^)(BOOL authorized))decisionHandler
{
    wasPrompted = true;

    if (shouldDeny) {
        decisionHandler(NO);
        return;
    }

    requestedDevices = devices;
    BOOL needsMicrophoneAuthorization = !!(requestedDevices & _WKCaptureDeviceMicrophone);
    BOOL needsCameraAuthorization = !!(requestedDevices & _WKCaptureDeviceCamera);
    BOOL needsDisplayCaptureAuthorization = !!(requestedDevices & _WKCaptureDeviceDisplay);
    if (!needsMicrophoneAuthorization && !needsCameraAuthorization && !needsDisplayCaptureAuthorization) {
        decisionHandler(NO);
        return;
    }

    decisionHandler(YES);
}

- (void)_webView:(WKWebView *)webView checkUserMediaPermissionForURL:(NSURL *)url mainFrameURL:(NSURL *)mainFrameURL frameIdentifier:(NSUInteger)frameIdentifier decisionHandler:(void (^)(NSString *salt, BOOL authorized))decisionHandler
{
    decisionHandler(@"0x987654321", YES);
}
@end

namespace TestWebKitAPI {

class GetDisplayMediaTest : public testing::Test {
public:
    virtual void SetUp()
    {
        m_configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
        auto context = adoptWK(TestWebKitAPI::Util::createContextForInjectedBundleTest("InternalsInjectedBundleTest"));
        m_configuration.get().processPool = (WKProcessPool *)context.get();

        auto handler = adoptNS([[GetDisplayMediaMessageHandler alloc] init]);
        [[m_configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];

        auto preferences = [m_configuration preferences];
        preferences._mediaCaptureRequiresSecureConnection = NO;
        m_configuration.get()._mediaCaptureEnabled = YES;
        preferences._mockCaptureDevicesEnabled = YES;
        preferences._screenCaptureEnabled = YES;

        m_webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:m_configuration.get() addToWindow:YES]);

        m_uiDelegate = adoptNS([[GetDisplayMediaUIDelegate alloc] init]);
        m_webView.get().UIDelegate = m_uiDelegate.get();
        [m_webView focus];

        [m_webView synchronouslyLoadTestPageNamed:@"getDisplayMedia"];
    }

    bool haveStream(bool expected)
    {
        int retryCount = 10;
        while (retryCount--) {
            auto result = [m_webView stringByEvaluatingJavaScript:@"haveStream()"];
            if (result.boolValue == expected)
                return YES;

            TestWebKitAPI::Util::spinRunLoop(10);
        }

        return NO;
    }

    void promptForCapture(NSString* constraints, bool shouldSucceed)
    {
        [m_webView stringByEvaluatingJavaScript:@"stop()"];
        EXPECT_TRUE(haveStream(false));

        wasPrompted = false;
        receivedScriptMessage = false;

        NSString *script = [NSString stringWithFormat:@"promptForCapture(%@)", constraints];
        [m_webView stringByEvaluatingJavaScript:script];

        TestWebKitAPI::Util::run(&receivedScriptMessage);
        if (shouldSucceed) {
            EXPECT_STREQ([(NSString *)[lastScriptMessage body] UTF8String], "allowed");
            EXPECT_TRUE(haveStream(true));
            EXPECT_TRUE(wasPrompted);
        } else {
            EXPECT_STREQ([(NSString *)[lastScriptMessage body] UTF8String], "denied");
            EXPECT_TRUE(haveStream(false));
            if (shouldDeny)
                EXPECT_TRUE(wasPrompted);
            else
                EXPECT_FALSE(wasPrompted);
        }
    }

    RetainPtr<WKWebViewConfiguration> m_configuration;
    RetainPtr<GetDisplayMediaUIDelegate> m_uiDelegate;
    RetainPtr<TestWKWebView> m_webView;
};

TEST_F(GetDisplayMediaTest, BasicPrompt)
{
    promptForCapture(@"{ audio: true, video: true }", true);
    promptForCapture(@"{ audio: true, video: false }", false);
    promptForCapture(@"{ audio: false, video: true }", true);
    promptForCapture(@"{ audio: false, video: false }", false);
}

TEST_F(GetDisplayMediaTest, Constraints)
{
    promptForCapture(@"{ video: {width: 640} }", true);
    promptForCapture(@"{ video: true, audio: { volume: 0.5 } }", true);
    promptForCapture(@"{ video: {height: 480}, audio: true }", true);
    promptForCapture(@"{ video: {width: { exact: 640} } }", false);
}

TEST_F(GetDisplayMediaTest, PromptOnceAfterDenial)
{
    promptForCapture(@"{ video: true }", true);
    shouldDeny = true;
    promptForCapture(@"{ video: true }", false);
    shouldDeny = false;
    promptForCapture(@"{ video: true }", true);
}

} // namespace TestWebKitAPI

#endif // ENABLE(MEDIA_STREAM) && PLATFORM(MAC)
