/*
 * Copyright (C) 2008 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. ``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
 * 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. 
 */

#if USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)

#import "HostedNetscapePluginStream.h"

#import "NetscapePluginHostProxy.h"
#import "NetscapePluginInstanceProxy.h"
#import "WebFrameInternal.h"
#import "WebHostedNetscapePluginView.h"
#import "WebKitErrorsPrivate.h"
#import "WebKitPluginHost.h"
#import "WebNSURLExtras.h"
#import "WebNSURLRequestExtras.h"
#import "WebResourceLoadScheduler.h"
#import <WebCore/Document.h>
#import <WebCore/DocumentLoader.h>
#import <WebCore/Frame.h>
#import <WebCore/FrameLoader.h>
#import <WebCore/PlatformStrategies.h>
#import <WebCore/SecurityOrigin.h>
#import <WebCore/SecurityPolicy.h>
#import <WebCore/WebCoreURLResponse.h>
#import <pal/spi/cf/CFNetworkSPI.h>
#import <wtf/CompletionHandler.h>
#import <wtf/RefCountedLeakCounter.h>

using namespace WebCore;

namespace WebKit {

DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, hostedNetscapePluginStreamCounter, ("HostedNetscapePluginStream"));

HostedNetscapePluginStream::HostedNetscapePluginStream(NetscapePluginInstanceProxy* instance, uint32_t streamID, NSURLRequest *request)
    : m_instance(instance)
    , m_streamID(streamID)
    , m_request(adoptNS([request mutableCopy]))
    , m_requestURL([request URL])
    , m_frameLoader(0)
{
    String referrer = SecurityPolicy::generateReferrerHeader(core([instance->pluginView() webFrame])->document()->referrerPolicy(), [request URL], core([instance->pluginView() webFrame])->loader().outgoingReferrer());
    if (referrer.isEmpty())
        [m_request.get() _web_setHTTPReferrer:nil];
    else
        [m_request.get() _web_setHTTPReferrer:referrer];

#ifndef NDEBUG
    hostedNetscapePluginStreamCounter.increment();
#endif
}

HostedNetscapePluginStream::HostedNetscapePluginStream(NetscapePluginInstanceProxy* instance, WebCore::FrameLoader* frameLoader)
    : m_instance(instance)
    , m_streamID(1)
    , m_frameLoader(frameLoader)
{
#ifndef NDEBUG
    hostedNetscapePluginStreamCounter.increment();
#endif
}

HostedNetscapePluginStream::~HostedNetscapePluginStream()
{
#ifndef NDEBUG
    hostedNetscapePluginStreamCounter.decrement();
#endif
}

void HostedNetscapePluginStream::startStreamWithResponse(NSURLResponse *response)
{
    didReceiveResponse(0, response);
}
    
void HostedNetscapePluginStream::startStream(NSURL *responseURL, long long expectedContentLength, NSDate *lastModifiedDate, NSString *mimeType, NSData *headers)
{
    m_responseURL = responseURL;
    m_mimeType = mimeType;

    char* mimeTypeUTF8 = const_cast<char*>([mimeType UTF8String]);
    int mimeTypeUTF8Length = mimeTypeUTF8 ? strlen (mimeTypeUTF8) + 1 : 0;
    
    const char *url = [responseURL _web_URLCString];
    int urlLength = url ? strlen(url) + 1 : 0;
    
    _WKPHStartStream(m_instance->hostProxy()->port(),
                     m_instance->pluginID(),
                     m_streamID,
                     const_cast<char*>(url), urlLength,
                     expectedContentLength,
                     [lastModifiedDate timeIntervalSince1970],
                     mimeTypeUTF8, mimeTypeUTF8Length,
                     const_cast<char*>(reinterpret_cast<const char*>([headers bytes])), [headers length]);
}
                     
void HostedNetscapePluginStream::didReceiveData(WebCore::NetscapePlugInStreamLoader*, const char* bytes, int length)
{
    _WKPHStreamDidReceiveData(m_instance->hostProxy()->port(),
                              m_instance->pluginID(),
                              m_streamID,
                              const_cast<char*>(bytes), length);
}
    
void HostedNetscapePluginStream::didFinishLoading(WebCore::NetscapePlugInStreamLoader*)
{
    _WKPHStreamDidFinishLoading(m_instance->hostProxy()->port(),
                                m_instance->pluginID(),
                                m_streamID);
    m_instance->disconnectStream(this);
}

void HostedNetscapePluginStream::willSendRequest(NetscapePlugInStreamLoader*, ResourceRequest&& request, const ResourceResponse&, CompletionHandler<void(WebCore::ResourceRequest&&)>&& callback)
{
    // FIXME: We should notify the plug-in with NPP_URLRedirectNotify here.
    callback(WTFMove(request));
}

void HostedNetscapePluginStream::didReceiveResponse(NetscapePlugInStreamLoader*, const ResourceResponse& response)
{
    NSURLResponse *r = response.nsURLResponse();
    
    NSMutableData *theHeaders = nil;
    long long expectedContentLength = [r expectedContentLength];
    
    if ([r isKindOfClass:[NSHTTPURLResponse class]]) {
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)r;
        theHeaders = [NSMutableData dataWithCapacity:1024];
        
        // FIXME: it would be nice to be able to get the raw HTTP header block.
        // This includes the HTTP version, the real status text,
        // all headers in their original order and including duplicates,
        // and all original bytes verbatim, rather than sent through Unicode translation.
        // Unfortunately NSHTTPURLResponse doesn't provide access at that low a level.
        
        [theHeaders appendBytes:"HTTP " length:5];
        char statusStr[10];
        long statusCode = [httpResponse statusCode];
        snprintf(statusStr, sizeof(statusStr), "%ld", statusCode);
        [theHeaders appendBytes:statusStr length:strlen(statusStr)];
        [theHeaders appendBytes:" OK\n" length:4];
        
        // HACK: pass the headers through as UTF-8.
        // This is not the intended behavior; we're supposed to pass original bytes verbatim.
        // But we don't have the original bytes, we have NSStrings built by the URL loading system.
        // It hopefully shouldn't matter, since RFC2616/RFC822 require ASCII-only headers,
        // but surely someone out there is using non-ASCII characters, and hopefully UTF-8 is adequate here.
        // It seems better than NSASCIIStringEncoding, which will lose information if non-ASCII is used.
        
        NSDictionary *headerDict = [httpResponse allHeaderFields];
        NSArray *keys = [[headerDict allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
        NSEnumerator *i = [keys objectEnumerator];
        NSString *k;
        while ((k = [i nextObject]) != nil) {
            NSString *v = [headerDict objectForKey:k];
            [theHeaders appendData:[k dataUsingEncoding:NSUTF8StringEncoding]];
            [theHeaders appendBytes:": " length:2];
            [theHeaders appendData:[v dataUsingEncoding:NSUTF8StringEncoding]];
            [theHeaders appendBytes:"\n" length:1];
        }
        
        // If the content is encoded (most likely compressed), then don't send its length to the plugin,
        // which is only interested in the decoded length, not yet known at the moment.
        // <rdar://problem/4470599> tracks a request for -[NSURLResponse expectedContentLength] to incorporate this logic.
        NSString *contentEncoding = (NSString *)[[(NSHTTPURLResponse *)r allHeaderFields] objectForKey:@"Content-Encoding"];
        if (contentEncoding && ![contentEncoding isEqualToString:@"identity"])
            expectedContentLength = -1;

        [theHeaders appendBytes:"\0" length:1];
    }
    
    startStream([r URL], expectedContentLength, [r _lastModifiedDate], [r MIMEType], theHeaders);
}

NPReason HostedNetscapePluginStream::reasonForError(NSError *error)
{
    if (!error)
        return NPRES_DONE;

    if ([[error domain] isEqualToString:NSURLErrorDomain] && [error code] == NSURLErrorCancelled)
        return NPRES_USER_BREAK;

    return NPRES_NETWORK_ERR;
}

void HostedNetscapePluginStream::didFail(WebCore::NetscapePlugInStreamLoader*, const WebCore::ResourceError& error)
{
    if (NetscapePluginHostProxy* hostProxy = m_instance->hostProxy())
        _WKPHStreamDidFail(hostProxy->port(), m_instance->pluginID(), m_streamID, reasonForError(error));
    m_instance->disconnectStream(this);
}

bool HostedNetscapePluginStream::wantsAllStreams() const
{
    // FIXME: Implement.
    return false;
}

void HostedNetscapePluginStream::start()
{
    ASSERT(m_request);
    ASSERT(!m_frameLoader);
    ASSERT(!m_loader);

    webResourceLoadScheduler().schedulePluginStreamLoad(*core([m_instance->pluginView() webFrame]), *this, m_request.get(), [this, protectedThis = makeRef(*this)] (RefPtr<WebCore::NetscapePlugInStreamLoader>&& loader) {
        m_loader = WTFMove(loader);
    });
}

void HostedNetscapePluginStream::stop()
{
    ASSERT(!m_frameLoader);
    
    if (!m_loader->isDone())
        m_loader->cancel(m_loader->cancelledError());
}
    
void HostedNetscapePluginStream::cancelLoad(NPReason reason)
{
    cancelLoad(errorForReason(reason));
}

void HostedNetscapePluginStream::cancelLoad(NSError *error)
{
    if (m_frameLoader) {
        ASSERT(!m_loader);
        
        DocumentLoader* documentLoader = m_frameLoader->activeDocumentLoader();
        if (documentLoader && documentLoader->isLoadingMainResource())
            documentLoader->cancelMainResourceLoad(error);
        return;
    }

    if (!m_loader->isDone()) {
        // Cancelling the load will disconnect the stream so there's no need to do it explicitly.
        m_loader->cancel(error);
    } else
        m_instance->disconnectStream(this);
}

NSError *HostedNetscapePluginStream::pluginCancelledConnectionError() const
{
    return [[[NSError alloc] _initWithPluginErrorCode:WebKitErrorPlugInCancelledConnection
                                           contentURL:m_responseURL ? m_responseURL.get() : m_requestURL.get()
                                        pluginPageURL:nil
                                           pluginName:[[m_instance->pluginView() pluginPackage] pluginInfo].name
                                             MIMEType:m_mimeType.get()] autorelease];
}

NSError *HostedNetscapePluginStream::errorForReason(NPReason reason) const
{
    if (reason == NPRES_DONE)
        return nil;

    if (reason == NPRES_USER_BREAK)
        return [NSError _webKitErrorWithDomain:NSURLErrorDomain
                                          code:NSURLErrorCancelled 
                                           URL:m_responseURL ? m_responseURL.get() : m_requestURL.get()];

    return pluginCancelledConnectionError();
}

} // namespace WebKit

#endif // USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)

