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

#include "config.h"
#include "NetscapeBrowserFuncs.h"

#include "NPRuntimeUtilities.h"
#include "NetscapePlugin.h"
#include "PluginController.h"
#include <WebCore/HTTPHeaderMap.h>
#include <WebCore/IdentifierRep.h>
#include <WebCore/NotImplemented.h>
#include <WebCore/SharedBuffer.h>
#include <utility>

#if PLATFORM(QT)
#include <QX11Info>
#elif PLATFORM(GTK)
#include <gdk/gdkx.h>
#endif

using namespace WebCore;
using namespace std;

namespace WebKit {

// Helper class for delaying destruction of a plug-in.
class PluginDestructionProtector {
public:
    explicit PluginDestructionProtector(NetscapePlugin* plugin)
        : m_protector(static_cast<Plugin*>(plugin)->controller())
    {
    }
    
private:
    PluginController::PluginDestructionProtector m_protector;
};

static bool startsWithBlankLine(const char* bytes, unsigned length)
{
    return length > 0 && bytes[0] == '\n';
}

static int locationAfterFirstBlankLine(const char* bytes, unsigned length)
{
    for (unsigned i = 0; i < length - 4; i++) {
        // Support for Acrobat. It sends "\n\n".
        if (bytes[i] == '\n' && bytes[i + 1] == '\n')
            return i + 2;
        
        // Returns the position after 2 CRLF's or 1 CRLF if it is the first line.
        if (bytes[i] == '\r' && bytes[i + 1] == '\n') {
            i += 2;
            if (i == 2)
                return i;

            if (bytes[i] == '\n') {
                // Support for Director. It sends "\r\n\n" (3880387).
                return i + 1;
            }

            if (bytes[i] == '\r' && bytes[i + 1] == '\n') {
                // Support for Flash. It sends "\r\n\r\n" (3758113).
                return i + 2;
            }
        }
    }

    return -1;
}

static const char* findEndOfLine(const char* bytes, unsigned length)
{
    // According to the HTTP specification EOL is defined as
    // a CRLF pair. Unfortunately, some servers will use LF
    // instead. Worse yet, some servers will use a combination
    // of both (e.g. <header>CRLFLF<body>), so findEOL needs
    // to be more forgiving. It will now accept CRLF, LF or
    // CR.
    //
    // It returns 0 if EOLF is not found or it will return
    // a pointer to the first terminating character.
    for (unsigned i = 0; i < length; i++) {
        if (bytes[i] == '\n')
            return bytes + i;
        if (bytes[i] == '\r') {
            // Check to see if spanning buffer bounds
            // (CRLF is across reads). If so, wait for
            // next read.
            if (i + 1 == length)
                break;

            return bytes + i;
        }
    }

    return 0;
}

static String capitalizeRFC822HeaderFieldName(const String& name)
{
    bool capitalizeCharacter = true;
    String result;

    for (unsigned i = 0; i < name.length(); i++) {
        UChar c;

        if (capitalizeCharacter && name[i] >= 'a' && name[i] <= 'z')
            c = toASCIIUpper(name[i]);
        else if (!capitalizeCharacter && name[i] >= 'A' && name[i] <= 'Z')
            c = toASCIILower(name[i]);
        else
            c = name[i];

        if (name[i] == '-')
            capitalizeCharacter = true;
        else
            capitalizeCharacter = false;

        result.append(c);
    }

    return result;
}

static HTTPHeaderMap parseRFC822HeaderFields(const char* bytes, unsigned length)
{
    String lastHeaderKey;
    HTTPHeaderMap headerFields;

    // Loop over lines until we're past the header, or we can't find any more end-of-lines
    while (const char* endOfLine = findEndOfLine(bytes, length)) {
        const char* line = bytes;
        int lineLength = endOfLine - bytes;

        // Move bytes to the character after the terminator as returned by findEndOfLine.
        bytes = endOfLine + 1;
        if ((*endOfLine == '\r') && (*bytes == '\n'))
            bytes++; // Safe since findEndOfLine won't return a spanning CRLF.

        length -= (bytes - line);
        if (!lineLength) {
            // Blank line; we're at the end of the header
            break;
        }

        if (*line == ' ' || *line == '\t') {
            // Continuation of the previous header
            if (lastHeaderKey.isNull()) {
                // malformed header; ignore it and continue
                continue;
            } 
            
            // Merge the continuation of the previous header
            String currentValue = headerFields.get(lastHeaderKey);
            String newValue(line, lineLength);
            
            headerFields.set(lastHeaderKey, currentValue + newValue);
        } else {
            // Brand new header
            const char* colon = line;
            while (*colon != ':' && colon != endOfLine)
                colon++;

            if (colon == endOfLine) {
                // malformed header; ignore it and continue
                continue;
            }

            lastHeaderKey = capitalizeRFC822HeaderFieldName(String(line, colon - line));
            String value;
            
            for (colon++; colon != endOfLine; colon++) {
                if (*colon != ' ' && *colon != '\t')
                    break;
            }
            if (colon == endOfLine)
                value = "";
            else
                value = String(colon, endOfLine - colon);
            
            String oldValue = headerFields.get(lastHeaderKey);
            if (!oldValue.isNull()) {
                String tmp = oldValue;
                tmp += ", ";
                tmp += value;
                value = tmp;
            }
            
            headerFields.set(lastHeaderKey, value);
        }
    }

    return headerFields;
}
    
static NPError parsePostBuffer(bool isFile, const char *buffer, uint32_t length, bool parseHeaders, HTTPHeaderMap& headerFields, Vector<uint8_t>& bodyData)
{
    RefPtr<SharedBuffer> fileContents;
    const char* postBuffer = 0;
    uint32_t postBufferSize = 0;

    if (isFile) {
        fileContents = SharedBuffer::createWithContentsOfFile(String::fromUTF8(buffer));
        if (!fileContents)
            return NPERR_FILE_NOT_FOUND;

        postBuffer = fileContents->data();
        postBufferSize = fileContents->size();

        // FIXME: The NPAPI spec states that the file should be deleted here.
    } else {
        postBuffer = buffer;
        postBufferSize = length;
    }

    if (parseHeaders) {
        if (startsWithBlankLine(postBuffer, postBufferSize)) {
            postBuffer++;
            postBufferSize--;
        } else {
            int location = locationAfterFirstBlankLine(postBuffer, postBufferSize);
            if (location != -1) {
                // If the blank line is somewhere in the middle of the buffer, everything before is the header
                headerFields = parseRFC822HeaderFields(postBuffer, location);
                unsigned dataLength = postBufferSize - location;
                
                // Sometimes plugins like to set Content-Length themselves when they post,
                // but WebFoundation does not like that. So we will remove the header
                // and instead truncate the data to the requested length.
                String contentLength = headerFields.get("Content-Length");
                
                if (!contentLength.isNull())
                    dataLength = min(contentLength.toInt(), (int)dataLength);
                headerFields.remove("Content-Length");
                
                postBuffer += location;
                postBufferSize = dataLength;
                
            }
        }
    }

    ASSERT(bodyData.isEmpty());
    bodyData.append(postBuffer, postBufferSize);

    return NPERR_NO_ERROR;
}

static String makeURLString(const char* url)
{
    String urlString(url);
    
    // Strip return characters.
    urlString.replace('\r', "");
    urlString.replace('\n', "");

    return urlString;
}

static NPError NPN_GetURL(NPP npp, const char* url, const char* target)
{
    if (!url)
        return NPERR_GENERIC_ERROR;
    
    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
    plugin->loadURL("GET", makeURLString(url), target, HTTPHeaderMap(), Vector<uint8_t>(), false, 0);
    
    return NPERR_GENERIC_ERROR;
}

static NPError NPN_PostURL(NPP npp, const char* url, const char* target, uint32_t len, const char* buf, NPBool file)
{
    HTTPHeaderMap headerFields;
    Vector<uint8_t> postData;
    
    // NPN_PostURL only allows headers if the post buffer points to a file.
    bool parseHeaders = file;

    NPError error = parsePostBuffer(file, buf, len, parseHeaders, headerFields, postData);
    if (error != NPERR_NO_ERROR)
        return error;

    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
    plugin->loadURL("POST", makeURLString(url), target, headerFields, postData, false, 0);
    return NPERR_NO_ERROR;
}

static NPError NPN_RequestRead(NPStream* stream, NPByteRange* rangeList)
{
    notImplemented();
    return NPERR_GENERIC_ERROR;
}

static NPError NPN_NewStream(NPP instance, NPMIMEType type, const char* target, NPStream** stream)
{
    notImplemented();
    return NPERR_GENERIC_ERROR;
}
    
static int32_t NPN_Write(NPP instance, NPStream* stream, int32_t len, void* buffer)
{
    notImplemented();    
    return -1;
}
    
static NPError NPN_DestroyStream(NPP npp, NPStream* stream, NPReason reason)
{
    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
    
    return plugin->destroyStream(stream, reason);
}

static void NPN_Status(NPP npp, const char* message)
{
    String statusbarText;
    if (!message)
        statusbarText = "";
    else
        statusbarText = String::fromUTF8WithLatin1Fallback(message, strlen(message));

    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
    plugin->setStatusbarText(statusbarText);
}
    
static const char* NPN_UserAgent(NPP npp)
{
    return NetscapePlugin::userAgent(npp);
}

static void* NPN_MemAlloc(uint32_t size)
{
    return npnMemAlloc(size);
}

static void NPN_MemFree(void* ptr)
{
    npnMemFree(ptr);
}

static uint32_t NPN_MemFlush(uint32_t size)
{
    return 0;
}

static void NPN_ReloadPlugins(NPBool reloadPages)
{
    notImplemented();
}

static JRIEnv* NPN_GetJavaEnv(void)
{
    notImplemented();
    return 0;
}

static jref NPN_GetJavaPeer(NPP instance)
{
    notImplemented();
    return 0;
}

static NPError NPN_GetURLNotify(NPP npp, const char* url, const char* target, void* notifyData)
{
    if (!url)
        return NPERR_GENERIC_ERROR;

    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
    plugin->loadURL("GET", makeURLString(url), target, HTTPHeaderMap(), Vector<uint8_t>(), true, notifyData);
    
    return NPERR_NO_ERROR;
}

static NPError NPN_PostURLNotify(NPP npp, const char* url, const char* target, uint32_t len, const char* buf, NPBool file, void* notifyData)
{
    HTTPHeaderMap headerFields;
    Vector<uint8_t> postData;
    NPError error = parsePostBuffer(file, buf, len, true, headerFields, postData);
    if (error != NPERR_NO_ERROR)
        return error;

    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
    plugin->loadURL("POST", makeURLString(url), target, headerFields, postData, true, notifyData);
    return NPERR_NO_ERROR;
}

#if PLATFORM(MAC)
// true if the browser supports hardware compositing of Core Animation plug-ins.
static const unsigned WKNVSupportsCompositingCoreAnimationPluginsBool = 74656;

// The Core Animation render server port.
static const unsigned WKNVCALayerRenderServerPort = 71879;

#endif

static NPError NPN_GetValue(NPP npp, NPNVariable variable, void *value)
{
    switch (variable) {
        case NPNVWindowNPObject: {
            RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
            PluginDestructionProtector protector(plugin.get());

            NPObject* windowNPObject = plugin->windowScriptNPObject();
            if (!windowNPObject)
                return NPERR_GENERIC_ERROR;

            *(NPObject**)value = windowNPObject;
            break;
        }
        case NPNVPluginElementNPObject: {
            RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
            PluginDestructionProtector protector(plugin.get());

            NPObject* pluginElementNPObject = plugin->pluginElementNPObject();
            *(NPObject**)value = pluginElementNPObject;
            break;
        }
        case NPNVprivateModeBool: {
            RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);

            *(NPBool*)value = plugin->isPrivateBrowsingEnabled();
            break;
        }
#if PLATFORM(MAC)
        case NPNVsupportsCoreGraphicsBool:
            // Always claim to support the Core Graphics drawing model.
            *(NPBool*)value = true;
            break;

        case WKNVSupportsCompositingCoreAnimationPluginsBool:
        case NPNVsupportsCoreAnimationBool: {
            RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
            
            *(NPBool*)value = plugin->isAcceleratedCompositingEnabled();
            break;
        }
        case NPNVsupportsCocoaBool:
            // Always claim to support the Cocoa event model.
            *(NPBool*)value = true;
            break;

        case WKNVCALayerRenderServerPort: {
            RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);

            *(mach_port_t*)value = plugin->compositingRenderServerPort();
            break;
        }
        
#ifndef NP_NO_QUICKDRAW
        case NPNVsupportsQuickDrawBool:
            // We don't support the QuickDraw drawing model.
            *(NPBool*)value = false;
            break;
#endif
#ifndef NP_NO_CARBON
       case NPNVsupportsCarbonBool:
            // FIXME: We should support the Carbon event model.
            *(NPBool*)value = false;
            break;
#endif
#elif PLATFORM(WIN)
       case NPNVnetscapeWindow: {
           RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
           *reinterpret_cast<HWND*>(value) = plugin->containingWindow();
           break;
       }
       case NPNVSupportsWindowless:
           *(NPBool*)value = true;
           break;
#elif PLUGIN_ARCHITECTURE(X11)
       case NPNVxDisplay:
#if PLATFORM(QT)
           *reinterpret_cast<Display**>(value) = QX11Info::display();
           break;
#elif PLATFORM(GTK)
           *reinterpret_cast<Display**>(value) = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
           break;
#else
           goto default;
#endif
       case NPNVSupportsXEmbedBool:
           *static_cast<NPBool*>(value) = true;
           break;
       case NPNVSupportsWindowless:
           *static_cast<NPBool*>(value) = true;
           break;

       case NPNVToolkit: {
           const uint32_t expectedGTKToolKitVersion = 2;

           RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
           *reinterpret_cast<uint32_t*>(value) = plugin->quirks().contains(PluginQuirks::RequiresGTKToolKit) ?
                                                 expectedGTKToolKitVersion : 0;
           break;
       }

       // TODO: implement NPNVnetscapeWindow once we want to support windowed plugins.
#endif
        default:
            notImplemented();
            return NPERR_GENERIC_ERROR;
    }

    return NPERR_NO_ERROR;
}

static NPError NPN_SetValue(NPP npp, NPPVariable variable, void *value)
{
    switch (variable) {
#if PLATFORM(MAC)
        case NPPVpluginDrawingModel: {
            RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
            
            NPDrawingModel drawingModel = static_cast<NPDrawingModel>(reinterpret_cast<uintptr_t>(value));
            return plugin->setDrawingModel(drawingModel);
        }

        case NPPVpluginEventModel: {
            RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
            
            NPEventModel eventModel = static_cast<NPEventModel>(reinterpret_cast<uintptr_t>(value));
            return plugin->setEventModel(eventModel);
        }
#endif

        case NPPVpluginWindowBool: {
            RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
            plugin->setIsWindowed(value);
            return NPERR_NO_ERROR;
        }

        case NPPVpluginTransparentBool: {
            RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
            plugin->setIsTransparent(value);
            return NPERR_NO_ERROR;
        }

        default:
            notImplemented();
            return NPERR_GENERIC_ERROR;
    }
}

static void NPN_InvalidateRect(NPP npp, NPRect* invalidRect)
{
    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
    plugin->invalidate(invalidRect);
}

static void NPN_InvalidateRegion(NPP npp, NPRegion invalidRegion)
{
    // FIXME: We could at least figure out the bounding rectangle of the invalid region.
    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
    plugin->invalidate(0);
}

static void NPN_ForceRedraw(NPP instance)
{
    notImplemented();
}

static NPIdentifier NPN_GetStringIdentifier(const NPUTF8 *name)
{
    return static_cast<NPIdentifier>(IdentifierRep::get(name));
}
    
static void NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers)
{
    ASSERT(names);
    ASSERT(identifiers);

    if (!names || !identifiers)
        return;

    for (int32_t i = 0; i < nameCount; ++i)
        identifiers[i] = NPN_GetStringIdentifier(names[i]);
}

static NPIdentifier NPN_GetIntIdentifier(int32_t intid)
{
    return static_cast<NPIdentifier>(IdentifierRep::get(intid));
}

static bool NPN_IdentifierIsString(NPIdentifier identifier)
{
    return static_cast<IdentifierRep*>(identifier)->isString();
}

static NPUTF8 *NPN_UTF8FromIdentifier(NPIdentifier identifier)
{
    const char* string = static_cast<IdentifierRep*>(identifier)->string();
    if (!string)
        return 0;

    uint32_t stringLength = strlen(string);
    char* utf8String = npnMemNewArray<char>(stringLength + 1);
    memcpy(utf8String, string, stringLength);
    utf8String[stringLength] = '\0';
    
    return utf8String;
}

static int32_t NPN_IntFromIdentifier(NPIdentifier identifier)
{
    return static_cast<IdentifierRep*>(identifier)->number();
}

static NPObject* NPN_CreateObject(NPP npp, NPClass *npClass)
{
    return createNPObject(npp, npClass);
}

static NPObject *NPN_RetainObject(NPObject *npObject)
{
    retainNPObject(npObject);
    return npObject;
}

static void NPN_ReleaseObject(NPObject *npObject)
{
    releaseNPObject(npObject);
}

static bool NPN_Invoke(NPP, NPObject *npObject, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
{
    if (npObject->_class->invoke)
        return npObject->_class->invoke(npObject, methodName, arguments, argumentCount, result);

    return false;
}

static bool NPN_InvokeDefault(NPP, NPObject *npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
{
    if (npObject->_class->invokeDefault)
        return npObject->_class->invokeDefault(npObject, arguments, argumentCount, result);

    return false;
}

static bool NPN_Evaluate(NPP npp, NPObject *npObject, NPString *script, NPVariant* result)
{
    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
    PluginDestructionProtector protector(plugin.get());
    
    String scriptString = String::fromUTF8WithLatin1Fallback(script->UTF8Characters, script->UTF8Length);
    
    return plugin->evaluate(npObject, scriptString, result);
}

static bool NPN_GetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, NPVariant* result)
{
    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
    PluginDestructionProtector protector(plugin.get());
    
    if (npObject->_class->getProperty)
        return npObject->_class->getProperty(npObject, propertyName, result);
    
    return false;
}

static bool NPN_SetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, const NPVariant* value)
{
    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
    PluginDestructionProtector protector(plugin.get());
    
    if (npObject->_class->setProperty)
        return npObject->_class->setProperty(npObject, propertyName, value);

    return false;
}

static bool NPN_RemoveProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName)
{
    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
    PluginDestructionProtector protector(plugin.get());
    
    if (npObject->_class->removeProperty)
        return npObject->_class->removeProperty(npObject, propertyName);

    return false;
}

static bool NPN_HasProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName)
{
    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
    PluginDestructionProtector protector(plugin.get());
    
    if (npObject->_class->hasProperty)
        return npObject->_class->hasProperty(npObject, propertyName);

    return false;
}

static bool NPN_HasMethod(NPP npp, NPObject* npObject, NPIdentifier methodName)
{
    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
    PluginDestructionProtector protector(plugin.get());
    
    if (npObject->_class->hasMethod)
        return npObject->_class->hasMethod(npObject, methodName);

    return false;
}

static void NPN_ReleaseVariantValue(NPVariant* variant)
{
    releaseNPVariantValue(variant);
}

static void NPN_SetException(NPObject*, const NPUTF8* message)
{
    NetscapePlugin::setException(message);
}

static void NPN_PushPopupsEnabledState(NPP npp, NPBool enabled)
{
    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
    plugin->pushPopupsEnabledState(enabled);
}
    
static void NPN_PopPopupsEnabledState(NPP npp)
{
    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
    plugin->popPopupsEnabledState();
}
    
static bool NPN_Enumerate(NPP npp, NPObject* npObject, NPIdentifier** identifiers, uint32_t* identifierCount)
{
    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
    PluginDestructionProtector protector(plugin.get());
    
    if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(npObject->_class) && npObject->_class->enumerate)
        return npObject->_class->enumerate(npObject, identifiers, identifierCount);

    return false;
}

static void NPN_PluginThreadAsyncCall(NPP instance, void (*func) (void*), void* userData)
{
    notImplemented();
}

static bool NPN_Construct(NPP npp, NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
{
    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
    PluginDestructionProtector protector(plugin.get());
    
    if (NP_CLASS_STRUCT_VERSION_HAS_CTOR(npObject->_class) && npObject->_class->construct)
        return npObject->_class->construct(npObject, arguments, argumentCount, result);

    return false;
}

static NPError copyCString(const CString& string, char** value, uint32_t* len)
{
    ASSERT(!string.isNull());
    ASSERT(value);
    ASSERT(len);

    *value = npnMemNewArray<char>(string.length());
    if (!*value)
        return NPERR_GENERIC_ERROR;

    memcpy(*value, string.data(), string.length());
    *len = string.length();
    return NPERR_NO_ERROR;
}

static NPError NPN_GetValueForURL(NPP npp, NPNURLVariable variable, const char* url, char** value, uint32_t* len)
{
    if (!value || !len)
        return NPERR_GENERIC_ERROR;
    
    switch (variable) {
        case NPNURLVCookie: {
            RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
            PluginDestructionProtector protector(plugin.get());
            
            String cookies = plugin->cookiesForURL(makeURLString(url));
            if (cookies.isNull())
                return NPERR_GENERIC_ERROR;

            return copyCString(cookies.utf8(), value, len);
        }

        case NPNURLVProxy: {
            RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
            PluginDestructionProtector protector(plugin.get());
            
            String proxies = plugin->proxiesForURL(makeURLString(url));
            if (proxies.isNull())
                return NPERR_GENERIC_ERROR;

            return copyCString(proxies.utf8(), value, len);
        }
        default:
            notImplemented();
            return NPERR_GENERIC_ERROR;
    }
}

static NPError NPN_SetValueForURL(NPP npp, NPNURLVariable variable, const char* url, const char* value, uint32_t len)
{
    switch (variable) {
        case NPNURLVCookie: {
            RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
            PluginDestructionProtector protector(plugin.get());
            
            plugin->setCookiesForURL(makeURLString(url), String(value, len));
            return NPERR_NO_ERROR;
        }

        case NPNURLVProxy:
            // Can't set the proxy for a URL.
            return NPERR_GENERIC_ERROR;

        default:
            notImplemented();
            return NPERR_GENERIC_ERROR;
    }
}

static NPError NPN_GetAuthenticationInfo(NPP instance, const char* protocol, const char* host, int32_t port, const char* scheme, 
                                         const char* realm, char** username, uint32_t* ulen, char** password, uint32_t* plen)
{
    notImplemented();
    return NPERR_GENERIC_ERROR;
}

static uint32_t NPN_ScheduleTimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID))
{
    notImplemented();
    return NPERR_GENERIC_ERROR;
}

static void NPN_UnscheduleTimer(NPP instance, uint32_t timerID)
{
    notImplemented();
}

#if PLATFORM(MAC)
static NPError NPN_PopUpContextMenu(NPP npp, NPMenu* menu)
{
    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);

    return plugin->popUpContextMenu(menu);
}

static NPBool NPN_ConvertPoint(NPP npp, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double* destX, double* destY, NPCoordinateSpace destSpace)
{
    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);

    double destinationX;
    double destinationY;

    bool returnValue = plugin->convertPoint(sourceX, sourceY, sourceSpace, destinationX, destinationY, destSpace);

    if (destX)
        *destX = destinationX;
    if (destY)
        *destY = destinationY;

    return returnValue;
}
#endif

static void initializeBrowserFuncs(NPNetscapeFuncs &netscapeFuncs)
{
    netscapeFuncs.size = sizeof(NPNetscapeFuncs);
    netscapeFuncs.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
    
    netscapeFuncs.geturl = NPN_GetURL;
    netscapeFuncs.posturl = NPN_PostURL;
    netscapeFuncs.requestread = NPN_RequestRead;
    netscapeFuncs.newstream = NPN_NewStream;
    netscapeFuncs.write = NPN_Write;
    netscapeFuncs.destroystream = NPN_DestroyStream;
    netscapeFuncs.status = NPN_Status;
    netscapeFuncs.uagent = NPN_UserAgent;
    netscapeFuncs.memalloc = NPN_MemAlloc;
    netscapeFuncs.memfree = NPN_MemFree;
    netscapeFuncs.memflush = NPN_MemFlush;
    netscapeFuncs.reloadplugins = NPN_ReloadPlugins;
    netscapeFuncs.getJavaEnv = NPN_GetJavaEnv;
    netscapeFuncs.getJavaPeer = NPN_GetJavaPeer;
    netscapeFuncs.geturlnotify = NPN_GetURLNotify;
    netscapeFuncs.posturlnotify = NPN_PostURLNotify;
    netscapeFuncs.getvalue = NPN_GetValue;
    netscapeFuncs.setvalue = NPN_SetValue;
    netscapeFuncs.invalidaterect = NPN_InvalidateRect;
    netscapeFuncs.invalidateregion = NPN_InvalidateRegion;
    netscapeFuncs.forceredraw = NPN_ForceRedraw;
    
    netscapeFuncs.getstringidentifier = NPN_GetStringIdentifier;
    netscapeFuncs.getstringidentifiers = NPN_GetStringIdentifiers;
    netscapeFuncs.getintidentifier = NPN_GetIntIdentifier;
    netscapeFuncs.identifierisstring = NPN_IdentifierIsString;
    netscapeFuncs.utf8fromidentifier = NPN_UTF8FromIdentifier;
    netscapeFuncs.intfromidentifier = NPN_IntFromIdentifier;
    netscapeFuncs.createobject = NPN_CreateObject;
    netscapeFuncs.retainobject = NPN_RetainObject;
    netscapeFuncs.releaseobject = NPN_ReleaseObject;
    netscapeFuncs.invoke = NPN_Invoke;
    netscapeFuncs.invokeDefault = NPN_InvokeDefault;
    netscapeFuncs.evaluate = NPN_Evaluate;
    netscapeFuncs.getproperty = NPN_GetProperty;
    netscapeFuncs.setproperty = NPN_SetProperty;
    netscapeFuncs.removeproperty = NPN_RemoveProperty;
    netscapeFuncs.hasproperty = NPN_HasProperty;
    netscapeFuncs.hasmethod = NPN_HasMethod;
    netscapeFuncs.releasevariantvalue = NPN_ReleaseVariantValue;
    netscapeFuncs.setexception = NPN_SetException;
    netscapeFuncs.pushpopupsenabledstate = NPN_PushPopupsEnabledState;
    netscapeFuncs.poppopupsenabledstate = NPN_PopPopupsEnabledState;
    netscapeFuncs.enumerate = NPN_Enumerate;
    netscapeFuncs.pluginthreadasynccall = NPN_PluginThreadAsyncCall;
    netscapeFuncs.construct = NPN_Construct;
    netscapeFuncs.getvalueforurl = NPN_GetValueForURL;
    netscapeFuncs.setvalueforurl = NPN_SetValueForURL;
    netscapeFuncs.getauthenticationinfo = NPN_GetAuthenticationInfo;
    netscapeFuncs.scheduletimer = NPN_ScheduleTimer;
    netscapeFuncs.unscheduletimer = NPN_UnscheduleTimer;
#if PLATFORM(MAC)
    netscapeFuncs.popupcontextmenu = NPN_PopUpContextMenu;
    netscapeFuncs.convertpoint = NPN_ConvertPoint;
#else
    netscapeFuncs.popupcontextmenu = 0;
    netscapeFuncs.convertpoint = 0;
#endif
}
    
NPNetscapeFuncs* netscapeBrowserFuncs()
{
    static NPNetscapeFuncs netscapeFuncs;
    static bool initialized = false;
    
    if (!initialized) {
        initializeBrowserFuncs(netscapeFuncs);
        initialized = true;
    }

    return &netscapeFuncs;
}

} // namespace WebKit
