/*
 * Copyright (C) 2004-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 "WebCoreResourceHandleAsOperationQueueDelegate.h"

#import "AuthenticationChallenge.h"
#import "AuthenticationMac.h"
#import "Logging.h"
#import "NetworkingContext.h"
#import "ResourceHandle.h"
#import "ResourceHandleClient.h"
#import "ResourceRequest.h"
#import "ResourceResponse.h"
#import "SharedBuffer.h"
#import "SynchronousLoaderClient.h"
#import "WebCoreURLResponse.h"
#import <pal/spi/cf/CFNetworkSPI.h>
#import <wtf/BlockPtr.h>
#import <wtf/MainThread.h>

using namespace WebCore;

static bool scheduledWithCustomRunLoopMode(const Optional<SchedulePairHashSet>& pairs)
{
    if (!pairs)
        return false;
    for (auto& pair : *pairs) {
        auto mode = pair->mode();
        if (mode != kCFRunLoopCommonModes && mode != kCFRunLoopDefaultMode)
            return true;
    }
    return false;
}

@implementation WebCoreResourceHandleAsOperationQueueDelegate

- (void)callFunctionOnMainThread:(Function<void()>&&)function
{
    // Sync xhr uses the message queue.
    if (m_messageQueue)
        return m_messageQueue->append(makeUnique<Function<void()>>(WTFMove(function)));

    // This is the common case.
    if (!scheduledWithCustomRunLoopMode(m_scheduledPairs))
        return callOnMainThread(WTFMove(function));

    // If we have been scheduled in a custom run loop mode, schedule a block in that mode.
    auto block = makeBlockPtr([alreadyCalled = false, function = WTFMove(function)] () mutable {
        if (alreadyCalled)
            return;
        alreadyCalled = true;
        function();
        function = nullptr;
    });
    for (auto& pair : *m_scheduledPairs)
        CFRunLoopPerformBlock(pair->runLoop(), pair->mode(), block.get());
}

- (id)initWithHandle:(WebCore::ResourceHandle*)handle messageQueue:(RefPtr<WebCore::SynchronousLoaderMessageQueue>&&)messageQueue
{
    self = [self init];
    if (!self)
        return nil;

    m_handle = handle;
    if (m_handle && m_handle->context()) {
        if (auto* pairs = m_handle->context()->scheduledRunLoopPairs())
            m_scheduledPairs = *pairs;
    }
    m_messageQueue = WTFMove(messageQueue);

    return self;
}

- (void)detachHandle
{
    LockHolder lock(m_mutex);

    m_handle = nullptr;

    m_messageQueue = nullptr;
    m_requestResult = nullptr;
    m_cachedResponseResult = nullptr;
    m_boolResult = NO;
    m_semaphore.signal(); // OK to signal even if we are not waiting.
}

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

- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)redirectResponse
{
    ASSERT(!isMainThread());
    UNUSED_PARAM(connection);

    redirectResponse = synthesizeRedirectResponseIfNecessary([connection currentRequest], newRequest, redirectResponse);

    // See <rdar://problem/5380697>. This is a workaround for a behavior change in CFNetwork where willSendRequest gets called more often.
    if (!redirectResponse)
        return newRequest;

#if !LOG_DISABLED
    if ([redirectResponse isKindOfClass:[NSHTTPURLResponse class]])
        LOG(Network, "Handle %p delegate connection:%p willSendRequest:%@ redirectResponse:%d, Location:<%@>", m_handle, connection, [newRequest description], static_cast<int>([(id)redirectResponse statusCode]), [[(id)redirectResponse allHeaderFields] objectForKey:@"Location"]);
    else
        LOG(Network, "Handle %p delegate connection:%p willSendRequest:%@ redirectResponse:non-HTTP", m_handle, connection, [newRequest description]); 
#endif

    auto protectedSelf = retainPtr(self);
    auto work = [self, protectedSelf, newRequest = retainPtr(newRequest), redirectResponse = retainPtr(redirectResponse)] () mutable {
        if (!m_handle) {
            m_requestResult = nullptr;
            m_semaphore.signal();
            return;
        }

        ResourceRequest redirectRequest = newRequest.get();
        if ([newRequest.get() HTTPBodyStream]) {
            ASSERT(m_handle->firstRequest().httpBody());
            redirectRequest.setHTTPBody(m_handle->firstRequest().httpBody());
        }
        if (m_handle->firstRequest().httpContentType().isEmpty())
            redirectRequest.clearHTTPContentType();
        m_handle->willSendRequest(WTFMove(redirectRequest), redirectResponse.get(), [self, protectedSelf = WTFMove(protectedSelf)](ResourceRequest&& request) {
            m_requestResult = request.nsURLRequest(HTTPBodyUpdatePolicy::UpdateHTTPBody);
            m_semaphore.signal();
        });
    };

    [self callFunctionOnMainThread:WTFMove(work)];
    m_semaphore.wait();

    LockHolder lock(m_mutex);
    if (!m_handle)
        return nil;

    RetainPtr<NSURLRequest> requestResult = m_requestResult;

    // Make sure protectedSelf gets destroyed on the main thread in case this is the last strong reference to self
    // as we do not want to get destroyed on a non-main thread.
    [self callFunctionOnMainThread:[protectedSelf = WTFMove(protectedSelf)] { }];

    return requestResult.autorelease();
}

ALLOW_DEPRECATED_IMPLEMENTATIONS_BEGIN
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
ALLOW_DEPRECATED_IMPLEMENTATIONS_END
{
    ASSERT(!isMainThread());
    UNUSED_PARAM(connection);

    LOG(Network, "Handle %p delegate connection:%p didReceiveAuthenticationChallenge:%p", m_handle, connection, challenge);

    auto work = [self, protectedSelf = retainPtr(self), challenge = retainPtr(challenge)] () mutable {
        if (!m_handle) {
            [[challenge sender] cancelAuthenticationChallenge:challenge.get()];
            return;
        }
        m_handle->didReceiveAuthenticationChallenge(core(challenge.get()));
    };

    [self callFunctionOnMainThread:WTFMove(work)];
}

ALLOW_DEPRECATED_IMPLEMENTATIONS_BEGIN
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
ALLOW_DEPRECATED_IMPLEMENTATIONS_END
{
    ASSERT(!isMainThread());
    UNUSED_PARAM(connection);

    LOG(Network, "Handle %p delegate connection:%p canAuthenticateAgainstProtectionSpace:%@://%@:%u realm:%@ method:%@ %@%@", m_handle, connection, [protectionSpace protocol], [protectionSpace host], [protectionSpace port], [protectionSpace realm], [protectionSpace authenticationMethod], [protectionSpace isProxy] ? @"proxy:" : @"", [protectionSpace isProxy] ? [protectionSpace proxyType] : @"");

    auto protectedSelf = retainPtr(self);
    auto work = [self, protectedSelf, protectionSpace = retainPtr(protectionSpace)] () mutable {
        if (!m_handle) {
            m_boolResult = NO;
            m_semaphore.signal();
            return;
        }
        m_handle->canAuthenticateAgainstProtectionSpace(ProtectionSpace(protectionSpace.get()), [self, protectedSelf = WTFMove(protectedSelf)] (bool result) mutable {
            m_boolResult = result;
            m_semaphore.signal();
        });
    };

    [self callFunctionOnMainThread:WTFMove(work)];
    m_semaphore.wait();

    LockHolder lock(m_mutex);
    if (!m_handle)
        return NO;

    auto boolResult = m_boolResult;

    // Make sure protectedSelf gets destroyed on the main thread in case this is the last strong reference to self
    // as we do not want to get destroyed on a non-main thread.
    [self callFunctionOnMainThread:[protectedSelf = WTFMove(protectedSelf)] { }];

    return boolResult;
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)r
{
    ASSERT(!isMainThread());

    LOG(Network, "Handle %p delegate connection:%p didReceiveResponse:%p (HTTP status %d, reported MIMEType '%s')", m_handle, connection, r, [r respondsToSelector:@selector(statusCode)] ? [(id)r statusCode] : 0, [[r MIMEType] UTF8String]);

    auto protectedSelf = retainPtr(self);
    auto work = [self, protectedSelf, r = retainPtr(r), connection = retainPtr(connection)] () mutable {
        RefPtr<ResourceHandle> protectedHandle(m_handle);
        if (!m_handle || !m_handle->client()) {
            m_semaphore.signal();
            return;
        }

        // Avoid MIME type sniffing if the response comes back as 304 Not Modified.
        int statusCode = [r respondsToSelector:@selector(statusCode)] ? [(id)r statusCode] : 0;
        if (statusCode != 304) {
            bool isMainResourceLoad = m_handle->firstRequest().requester() == ResourceRequest::Requester::Main;
            adjustMIMETypeIfNecessary([r _CFURLResponse], isMainResourceLoad);
        }

        if ([m_handle->firstRequest().nsURLRequest(HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody) _propertyForKey:@"ForceHTMLMIMEType"])
            [r _setMIMEType:@"text/html"];

        ResourceResponse resourceResponse(r.get());
        resourceResponse.setSource(ResourceResponse::Source::Network);
        ResourceHandle::getConnectionTimingData(connection.get(), resourceResponse.deprecatedNetworkLoadMetrics());

        m_handle->didReceiveResponse(WTFMove(resourceResponse), [self, protectedSelf = WTFMove(protectedSelf)] {
            m_semaphore.signal();
        });
    };

    [self callFunctionOnMainThread:WTFMove(work)];
    m_semaphore.wait();

    // Make sure we get destroyed on the main thread.
    [self callFunctionOnMainThread:[protectedSelf = WTFMove(protectedSelf)] { }];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data lengthReceived:(long long)lengthReceived
{
    ASSERT(!isMainThread());
    UNUSED_PARAM(connection);
    UNUSED_PARAM(lengthReceived);

    LOG(Network, "Handle %p delegate connection:%p didReceiveData:%p lengthReceived:%lld", m_handle, connection, data, lengthReceived);

    auto work = [self = self, protectedSelf = retainPtr(self), data = retainPtr(data)] () mutable {
        if (!m_handle || !m_handle->client())
            return;
        // FIXME: If we get more than 2B bytes in a single chunk, this code won't do the right thing.
        // However, with today's computers and networking speeds, this won't happen in practice.
        // Could be an issue with a giant local file.

        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=19793
        // -1 means we do not provide any data about transfer size to inspector so it would use
        // Content-Length headers or content size to show transfer size.
        m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::create(data.get()), -1);
    };

    [self callFunctionOnMainThread:WTFMove(work)];
}

- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
{
    ASSERT(!isMainThread());
    UNUSED_PARAM(connection);
    UNUSED_PARAM(bytesWritten);

    LOG(Network, "Handle %p delegate connection:%p didSendBodyData:%d totalBytesWritten:%d totalBytesExpectedToWrite:%d", m_handle, connection, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);

    auto work = [self = self, protectedSelf = retainPtr(self), totalBytesWritten = totalBytesWritten, totalBytesExpectedToWrite = totalBytesExpectedToWrite] () mutable {
        if (!m_handle || !m_handle->client())
            return;
        m_handle->client()->didSendData(m_handle, totalBytesWritten, totalBytesExpectedToWrite);
    };

    [self callFunctionOnMainThread:WTFMove(work)];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    ASSERT(!isMainThread());
    UNUSED_PARAM(connection);

    LOG(Network, "Handle %p delegate connectionDidFinishLoading:%p", m_handle, connection);

    auto work = [self = self, protectedSelf = retainPtr(self)] () mutable {
        if (!m_handle || !m_handle->client())
            return;

        m_handle->client()->didFinishLoading(m_handle);
        if (m_messageQueue) {
            m_messageQueue->kill();
            m_messageQueue = nullptr;
        }
    };

    [self callFunctionOnMainThread:WTFMove(work)];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    ASSERT(!isMainThread());
    UNUSED_PARAM(connection);

    LOG(Network, "Handle %p delegate connection:%p didFailWithError:%@", m_handle, connection, error);

    auto work = [self = self, protectedSelf = retainPtr(self), error = retainPtr(error)] () mutable {
        if (!m_handle || !m_handle->client())
            return;

        m_handle->client()->didFail(m_handle, error.get());
        if (m_messageQueue) {
            m_messageQueue->kill();
            m_messageQueue = nullptr;
        }
    };

    [self callFunctionOnMainThread:WTFMove(work)];
}


- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
    ASSERT(!isMainThread());
    UNUSED_PARAM(connection);

    LOG(Network, "Handle %p delegate connection:%p willCacheResponse:%p", m_handle, connection, cachedResponse);

    auto protectedSelf = retainPtr(self);
    auto work = [self, protectedSelf, cachedResponse = retainPtr(cachedResponse)] () mutable {
        if (!m_handle || !m_handle->client()) {
            m_cachedResponseResult = nullptr;
            m_semaphore.signal();
            return;
        }

        m_handle->client()->willCacheResponseAsync(m_handle, cachedResponse.get(), [self, protectedSelf = WTFMove(protectedSelf)] (NSCachedURLResponse * response) mutable {
            m_cachedResponseResult = response;
            m_semaphore.signal();
        });
    };

    [self callFunctionOnMainThread:WTFMove(work)];
    m_semaphore.wait();

    LockHolder lock(m_mutex);
    if (!m_handle)
        return nil;

    RetainPtr<NSCachedURLResponse> cachedResponseResult = m_cachedResponseResult;

    // Make sure protectedSelf gets destroyed on the main thread in case this is the last strong reference to self
    // as we do not want to get destroyed on a non-main thread.
    [self callFunctionOnMainThread:[protectedSelf = WTFMove(protectedSelf)] { }];

    return cachedResponseResult.autorelease();
}

@end

@implementation WebCoreResourceHandleWithCredentialStorageAsOperationQueueDelegate

- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection
{
    ASSERT(!isMainThread());
    UNUSED_PARAM(connection);
    return NO;
}

@end
