/*
 * 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:(ResourceHandle*)handle messageQueue:(MessageQueue<Function<void()>>*)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 = 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
