/*
 * 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 "NetscapePluginModule.h"

#include "Module.h"
#include "NPRuntimeUtilities.h"
#include "NetscapeBrowserFuncs.h"
#include <wtf/PassOwnPtr.h>
#include <wtf/text/CString.h>

namespace WebKit {

static Vector<NetscapePluginModule*>& initializedNetscapePluginModules()
{
    DEFINE_STATIC_LOCAL(Vector<NetscapePluginModule*>, initializedNetscapePluginModules, ());
    return initializedNetscapePluginModules;
}

NetscapePluginModule::NetscapePluginModule(const String& pluginPath)
    : m_pluginPath(pluginPath)
    , m_isInitialized(false)
    , m_loadCount(0)
    , m_shutdownProcPtr(0)
    , m_pluginFuncs()
{
}

NetscapePluginModule::~NetscapePluginModule()
{
    ASSERT(initializedNetscapePluginModules().find(this) == notFound);
}

Vector<String> NetscapePluginModule::sitesWithData()
{
    Vector<String> sites;

    incrementLoadCount();
    tryGetSitesWithData(sites);
    decrementLoadCount();

    return sites;
}

bool NetscapePluginModule::clearSiteData(const String& site, uint64_t flags, uint64_t maxAge)
{
    incrementLoadCount();
    bool result = tryClearSiteData(site, flags, maxAge);
    decrementLoadCount();

    return result;
}

bool NetscapePluginModule::tryGetSitesWithData(Vector<String>& sites)
{
    if (!m_isInitialized)
        return false;

    // Check if the plug-in supports NPP_GetSitesWithData.
    if (!m_pluginFuncs.getsiteswithdata)
        return false;

    char** siteArray = m_pluginFuncs.getsiteswithdata();

    // There were no sites with data.
    if (!siteArray)
        return true;

    for (int i = 0; siteArray[i]; ++i) {
        char* site = siteArray[i];

        String siteString = String::fromUTF8(site);
        if (!siteString.isNull())
            sites.append(siteString);

        npnMemFree(site);
    }

    npnMemFree(siteArray);
    return true;
}

bool NetscapePluginModule::tryClearSiteData(const String& site, uint64_t flags, uint64_t maxAge)
{
    if (!m_isInitialized)
        return false;

    // Check if the plug-in supports NPP_ClearSiteData.
    if (!m_pluginFuncs.clearsitedata)
        return false;

    CString siteString;
    if (!site.isNull())
        siteString = site.utf8();

    return m_pluginFuncs.clearsitedata(siteString.data(), flags, maxAge) == NPERR_NO_ERROR;
}

void NetscapePluginModule::shutdown()
{
    ASSERT(m_isInitialized);

    m_shutdownProcPtr();

    m_isInitialized = false;

    size_t pluginModuleIndex = initializedNetscapePluginModules().find(this);
    ASSERT(pluginModuleIndex != notFound);
    
    initializedNetscapePluginModules().remove(pluginModuleIndex);
}

PassRefPtr<NetscapePluginModule> NetscapePluginModule::getOrCreate(const String& pluginPath)
{
    // First, see if we already have a module with this plug-in path.
    for (size_t i = 0; i < initializedNetscapePluginModules().size(); ++i) {
        NetscapePluginModule* pluginModule = initializedNetscapePluginModules()[i];

        if (pluginModule->m_pluginPath == pluginPath)
            return pluginModule;
    }

    RefPtr<NetscapePluginModule> pluginModule(adoptRef(new NetscapePluginModule(pluginPath)));
    
    // Try to load and initialize the plug-in module.
    if (!pluginModule->load())
        return 0;
    
    return pluginModule.release();
}

void NetscapePluginModule::incrementLoadCount()
{
    if (!m_loadCount) {
        // Load the plug-in module if necessary.
        load();
    }
    
    m_loadCount++;
}
    
void NetscapePluginModule::decrementLoadCount()
{
    ASSERT(m_loadCount > 0);
    m_loadCount--;
    
    if (!m_loadCount) {
        shutdown();
        unload();
    }
}

bool NetscapePluginModule::load()
{
    if (m_isInitialized) {
        ASSERT(initializedNetscapePluginModules().find(this) != notFound);
        return true;
    }

    if (!tryLoad()) {
        unload();
        return false;
    }
    
    m_isInitialized = true;

    ASSERT(initializedNetscapePluginModules().find(this) == notFound);
    initializedNetscapePluginModules().append(this);

    determineQuirks();

    return true;
}

bool NetscapePluginModule::tryLoad()
{
#if PLUGIN_ARCHITECTURE(X11)
    applyX11QuirksBeforeLoad();
#endif

    m_module = adoptPtr(new Module(m_pluginPath));
    if (!m_module->load())
        return false;

    NP_InitializeFuncPtr initializeFuncPtr = m_module->functionPointer<NP_InitializeFuncPtr>("NP_Initialize");
    if (!initializeFuncPtr)
        return false;

#if !PLUGIN_ARCHITECTURE(X11)
    NP_GetEntryPointsFuncPtr getEntryPointsFuncPtr = m_module->functionPointer<NP_GetEntryPointsFuncPtr>("NP_GetEntryPoints");
    if (!getEntryPointsFuncPtr)
        return false;
#endif

    m_shutdownProcPtr = m_module->functionPointer<NPP_ShutdownProcPtr>("NP_Shutdown");
    if (!m_shutdownProcPtr)
        return false;

    m_pluginFuncs.size = sizeof(NPPluginFuncs);
    m_pluginFuncs.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;

    // On Mac, NP_Initialize must be called first, then NP_GetEntryPoints. On Windows, the order is
    // reversed. Failing to follow this order results in crashes (e.g., in Silverlight on Mac and
    // in Flash and QuickTime on Windows).
#if PLUGIN_ARCHITECTURE(MAC)
#ifndef NP_NO_CARBON
    // Plugins (at least QT) require that you call UseResFile on the resource file before loading it.
    ResFileRefNum currentResourceFile = CurResFile();
    
    ResFileRefNum pluginResourceFile = m_module->bundleResourceMap();
    UseResFile(pluginResourceFile);
#endif
    bool result = initializeFuncPtr(netscapeBrowserFuncs()) == NPERR_NO_ERROR && getEntryPointsFuncPtr(&m_pluginFuncs) == NPERR_NO_ERROR;

#ifndef NP_NO_CARBON
    // Restore the resource file.
    UseResFile(currentResourceFile);
#endif

    return result;
#elif PLUGIN_ARCHITECTURE(WIN)
    if (getEntryPointsFuncPtr(&m_pluginFuncs) != NPERR_NO_ERROR || initializeFuncPtr(netscapeBrowserFuncs()) != NPERR_NO_ERROR)
        return false;
#elif PLUGIN_ARCHITECTURE(X11)
    if (initializeFuncPtr(netscapeBrowserFuncs(), &m_pluginFuncs) != NPERR_NO_ERROR)
        return false;
#endif

    return true;
}

void NetscapePluginModule::unload()
{
    ASSERT(!m_isInitialized);

    m_module = 0;
}

} // namespace WebKit

