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

#import "AuthenticationChallengeDisposition.h"
#import "AuthenticationChallengeProxy.h"
#import "AuthenticationDecisionListener.h"
#import "CompletionHandlerCallChecker.h"
#import "DownloadProxy.h"
#import "Logging.h"
#import "SystemPreviewController.h"
#import "WKNSURLAuthenticationChallenge.h"
#import "WKNSURLExtras.h"
#import "WebCredential.h"
#import "WebPageProxy.h"
#import "WebProcessProxy.h"
#import "_WKDownloadDelegate.h"
#import "_WKDownloadInternal.h"
#import <WebCore/ResourceError.h>
#import <WebCore/ResourceResponse.h>
#import <wtf/BlockPtr.h>
#import <wtf/FileSystem.h>

namespace WebKit {

DownloadClient::DownloadClient(id <_WKDownloadDelegate> delegate)
    : m_delegate(delegate)
{
    m_delegateMethods.downloadDidStart = [delegate respondsToSelector:@selector(_downloadDidStart:)];
    m_delegateMethods.downloadDidReceiveResponse = [delegate respondsToSelector:@selector(_download:didReceiveResponse:)];
    m_delegateMethods.downloadDidReceiveData = [delegate respondsToSelector:@selector(_download:didReceiveData:)];
    m_delegateMethods.downloadDecideDestinationWithSuggestedFilenameAllowOverwrite = [delegate respondsToSelector:@selector(_download:decideDestinationWithSuggestedFilename:allowOverwrite:)];
    m_delegateMethods.downloadDecideDestinationWithSuggestedFilenameCompletionHandler = [delegate respondsToSelector:@selector(_download:decideDestinationWithSuggestedFilename:completionHandler:)];
    m_delegateMethods.downloadDidFinish = [delegate respondsToSelector:@selector(_downloadDidFinish:)];
    m_delegateMethods.downloadDidFail = [delegate respondsToSelector:@selector(_download:didFailWithError:)];
    m_delegateMethods.downloadDidCancel = [delegate respondsToSelector:@selector(_downloadDidCancel:)];
    m_delegateMethods.downloadDidReceiveServerRedirectToURL = [delegate respondsToSelector:@selector(_download:didReceiveServerRedirectToURL:)];
    m_delegateMethods.downloadDidReceiveAuthenticationChallengeCompletionHandler = [delegate respondsToSelector:@selector(_download:didReceiveAuthenticationChallenge:completionHandler:)];
    m_delegateMethods.downloadShouldDecodeSourceDataOfMIMEType = [delegate respondsToSelector:@selector(_download:shouldDecodeSourceDataOfMIMEType:)];
    m_delegateMethods.downloadDidCreateDestination = [delegate respondsToSelector:@selector(_download:didCreateDestination:)];
    m_delegateMethods.downloadProcessDidCrash = [delegate respondsToSelector:@selector(_downloadProcessDidCrash:)];
}

void DownloadClient::didStart(DownloadProxy& downloadProxy)
{
#if USE(SYSTEM_PREVIEW)
    if (downloadProxy.isSystemPreviewDownload()) {
        if (auto* webPage = downloadProxy.originatingPage()) {
            // FIXME: Update the MIME-type once it is known in the ResourceResponse.
            webPage->systemPreviewController()->start(URL(URL(), webPage->currentURL()), "application/octet-stream"_s, downloadProxy.systemPreviewDownloadInfo());
        }
        takeActivityToken(downloadProxy);
        return;
    }
#endif

    if (m_delegateMethods.downloadDidStart)
        [m_delegate _downloadDidStart:wrapper(downloadProxy)];
}

void DownloadClient::didReceiveResponse(DownloadProxy& downloadProxy, const WebCore::ResourceResponse& response)
{
#if USE(SYSTEM_PREVIEW)
    if (downloadProxy.isSystemPreviewDownload() && response.isSuccessful()) {
        downloadProxy.setExpectedContentLength(response.expectedContentLength());
        downloadProxy.setBytesLoaded(0);
        if (auto* webPage = downloadProxy.originatingPage())
            webPage->systemPreviewController()->updateProgress(0);
        return;
    }
#endif

    if (m_delegateMethods.downloadDidReceiveResponse)
        [m_delegate _download:wrapper(downloadProxy) didReceiveResponse:response.nsURLResponse()];
}

void DownloadClient::didReceiveData(DownloadProxy& downloadProxy, uint64_t length)
{
#if USE(SYSTEM_PREVIEW)
    if (downloadProxy.isSystemPreviewDownload()) {
        downloadProxy.setBytesLoaded(downloadProxy.bytesLoaded() + length);
        if (auto* webPage = downloadProxy.originatingPage())
            webPage->systemPreviewController()->updateProgress(static_cast<float>(downloadProxy.bytesLoaded()) / downloadProxy.expectedContentLength());
        return;
    }
#endif

    if (m_delegateMethods.downloadDidReceiveData)
        [m_delegate _download:wrapper(downloadProxy) didReceiveData:length];
}

void DownloadClient::didReceiveAuthenticationChallenge(DownloadProxy& downloadProxy, AuthenticationChallengeProxy& authenticationChallenge)
{
    // FIXME: System Preview needs code here.
    if (!m_delegateMethods.downloadDidReceiveAuthenticationChallengeCompletionHandler) {
        authenticationChallenge.listener().completeChallenge(WebKit::AuthenticationChallengeDisposition::PerformDefaultHandling);
        return;
    }

    [m_delegate _download:wrapper(downloadProxy) didReceiveAuthenticationChallenge:wrapper(authenticationChallenge) completionHandler:makeBlockPtr([authenticationChallenge = makeRef(authenticationChallenge), checker = CompletionHandlerCallChecker::create(m_delegate.get().get(), @selector(_download:didReceiveAuthenticationChallenge:completionHandler:))] (NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential) {
        if (checker->completionHandlerHasBeenCalled())
            return;
        checker->didCallCompletionHandler();
        switch (disposition) {
        case NSURLSessionAuthChallengeUseCredential:
            authenticationChallenge->listener().completeChallenge(AuthenticationChallengeDisposition::UseCredential, credential ? WebCore::Credential(credential) : WebCore::Credential());
            break;
        case NSURLSessionAuthChallengePerformDefaultHandling:
            authenticationChallenge->listener().completeChallenge(AuthenticationChallengeDisposition::PerformDefaultHandling);
            break;
            
        case NSURLSessionAuthChallengeCancelAuthenticationChallenge:
            authenticationChallenge->listener().completeChallenge(AuthenticationChallengeDisposition::Cancel);
            break;
            
        case NSURLSessionAuthChallengeRejectProtectionSpace:
            authenticationChallenge->listener().completeChallenge(AuthenticationChallengeDisposition::RejectProtectionSpaceAndContinue);
            break;
            
        default:
            [NSException raise:NSInvalidArgumentException format:@"Invalid NSURLSessionAuthChallengeDisposition (%ld)", (long)disposition];
        }
    }).get()];
}

void DownloadClient::didCreateDestination(DownloadProxy& downloadProxy, const String& destination)
{
#if USE(SYSTEM_PREVIEW)
    if (downloadProxy.isSystemPreviewDownload()) {
        downloadProxy.setDestinationFilename(destination);
        return;
    }
#endif

    if (m_delegateMethods.downloadDidCreateDestination)
        [m_delegate _download:wrapper(downloadProxy) didCreateDestination:destination];
}

void DownloadClient::processDidCrash(DownloadProxy& downloadProxy)
{
#if USE(SYSTEM_PREVIEW)
    if (downloadProxy.isSystemPreviewDownload()) {
        if (auto* webPage = downloadProxy.originatingPage())
            webPage->systemPreviewController()->cancel();
        releaseActivityTokenIfNecessary(downloadProxy);
        return;
    }
#endif

    if (m_delegateMethods.downloadProcessDidCrash)
        [m_delegate _downloadProcessDidCrash:wrapper(downloadProxy)];
}

void DownloadClient::decideDestinationWithSuggestedFilename(DownloadProxy& downloadProxy, const String& filename, Function<void(AllowOverwrite, String)>&& completionHandler)
{
#if USE(SYSTEM_PREVIEW)
    if (downloadProxy.isSystemPreviewDownload()) {
        NSString *temporaryDirectory = FileSystem::createTemporaryDirectory(@"SystemPreviews");
        NSString *destination = [temporaryDirectory stringByAppendingPathComponent:filename];
        completionHandler(AllowOverwrite::Yes, destination);
        return;
    }
#endif

    if (!m_delegateMethods.downloadDecideDestinationWithSuggestedFilenameAllowOverwrite && !m_delegateMethods.downloadDecideDestinationWithSuggestedFilenameCompletionHandler)
        return completionHandler(AllowOverwrite::No, { });

    if (m_delegateMethods.downloadDecideDestinationWithSuggestedFilenameAllowOverwrite) {
        BOOL allowOverwrite = NO;
        ALLOW_DEPRECATED_DECLARATIONS_BEGIN
        NSString *destination = [m_delegate _download:wrapper(downloadProxy) decideDestinationWithSuggestedFilename:filename allowOverwrite:&allowOverwrite];
        ALLOW_DEPRECATED_DECLARATIONS_END
        completionHandler(allowOverwrite ? AllowOverwrite::Yes : AllowOverwrite::No, destination);
    } else {
        [m_delegate _download:wrapper(downloadProxy) decideDestinationWithSuggestedFilename:filename completionHandler:makeBlockPtr([checker = CompletionHandlerCallChecker::create(m_delegate.get().get(), @selector(_download:decideDestinationWithSuggestedFilename:completionHandler:)), completionHandler = WTFMove(completionHandler)] (BOOL allowOverwrite, NSString *destination) {
            if (checker->completionHandlerHasBeenCalled())
                return;
            checker->didCallCompletionHandler();
            completionHandler(allowOverwrite ? AllowOverwrite::Yes : AllowOverwrite::No, destination);
        }).get()];
    }
}

void DownloadClient::didFinish(DownloadProxy& downloadProxy)
{
#if USE(SYSTEM_PREVIEW)
    if (downloadProxy.isSystemPreviewDownload()) {
        if (auto* webPage = downloadProxy.originatingPage()) {
            WTF::URL destinationURL = WTF::URL::fileURLWithFileSystemPath(downloadProxy.destinationFilename());
            if (!destinationURL.fragmentIdentifier().length())
                destinationURL.setFragmentIdentifier(downloadProxy.request().url().fragmentIdentifier());
            webPage->systemPreviewController()->finish(destinationURL);
        }
        releaseActivityTokenIfNecessary(downloadProxy);
        return;
    }
#endif

    if (m_delegateMethods.downloadDidFinish)
        [m_delegate _downloadDidFinish:wrapper(downloadProxy)];
}

void DownloadClient::didFail(DownloadProxy& downloadProxy, const WebCore::ResourceError& error)
{
#if USE(SYSTEM_PREVIEW)
    if (downloadProxy.isSystemPreviewDownload()) {
        if (auto* webPage = downloadProxy.originatingPage())
            webPage->systemPreviewController()->fail(error);
        releaseActivityTokenIfNecessary(downloadProxy);
        return;
    }
#endif

    if (m_delegateMethods.downloadDidFail)
        [m_delegate _download:wrapper(downloadProxy) didFailWithError:error.nsError()];
}

void DownloadClient::didCancel(DownloadProxy& downloadProxy)
{
#if USE(SYSTEM_PREVIEW)
    if (downloadProxy.isSystemPreviewDownload()) {
        if (auto* webPage = downloadProxy.originatingPage())
            webPage->systemPreviewController()->cancel();
        releaseActivityTokenIfNecessary(downloadProxy);
        return;
    }
#endif

    if (m_delegateMethods.downloadDidCancel)
        [m_delegate _downloadDidCancel:wrapper(downloadProxy)];
}

void DownloadClient::willSendRequest(DownloadProxy& downloadProxy, WebCore::ResourceRequest&& request, const WebCore::ResourceResponse&, CompletionHandler<void(WebCore::ResourceRequest&&)>&& completionHandler)
{
    if (m_delegateMethods.downloadDidReceiveServerRedirectToURL)
        [m_delegate _download:wrapper(downloadProxy) didReceiveServerRedirectToURL:[NSURL _web_URLWithWTFString:request.url().string()]];

    completionHandler(WTFMove(request));
}

#if USE(SYSTEM_PREVIEW)
void DownloadClient::takeActivityToken(DownloadProxy& downloadProxy)
{
#if PLATFORM(IOS_FAMILY)
    if (auto* webPage = downloadProxy.originatingPage()) {
        RELEASE_LOG_IF(webPage->isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - UIProcess is taking a background assertion because it is downloading a system preview", this);
        ASSERT(!m_activity);
        m_activity = webPage->process().throttler().backgroundActivity("System preview download"_s).moveToUniquePtr();
    }
#else
    UNUSED_PARAM(downloadProxy);
#endif
}

void DownloadClient::releaseActivityTokenIfNecessary(DownloadProxy& downloadProxy)
{
#if PLATFORM(IOS_FAMILY)
    if (m_activity) {
        RELEASE_LOG_IF(downloadProxy.originatingPage()->isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p UIProcess is releasing a background assertion because a system preview download completed", this);
        m_activity = nullptr;
    }
#else
    UNUSED_PARAM(downloadProxy);
#endif
}
#endif

} // namespace WebKit
