/*
 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
 * Copyright (C) 2008 Collabora, Ltd.  All rights reserved.
 * Copyright (C) 2009 Torch Mobile, 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. 
 */

#include "PluginPackage.h"

#include "PluginDatabase.h"
#include "PluginDebug.h"
#include <WebCore/MIMETypeRegistry.h>
#include <WebCore/Timer.h>
#include <WebCore/npruntime_impl.h>
#include <shlwapi.h>
#include <string.h>
#include <wtf/StdLibExtras.h>
#include <wtf/text/CString.h>

namespace WebCore {

static String getVersionInfo(const LPVOID versionInfoData, const String& info)
{
    LPVOID buffer;
    UINT bufferLength;
    String subInfo = "\\StringfileInfo\\040904E4\\" + info;
    bool retval = VerQueryValueW(versionInfoData,
        subInfo.wideCharacters().data(),
        &buffer, &bufferLength);
    if (!retval || bufferLength == 0)
        return String();

    // Subtract 1 from the length; we don't want the trailing null character.
    return String(reinterpret_cast<UChar*>(buffer), bufferLength - 1);
}

bool PluginPackage::isPluginBlacklisted()
{
    if (name() == "Citrix ICA Client") {
        // The Citrix ICA Client plug-in requires a Mozilla-based browser; see <rdar://6418681>.
        return true;
    }

    if (name() == "Silverlight Plug-In") {
        // workaround for <rdar://5557379> Crash in Silverlight when opening microsoft.com.
        // the latest 1.0 version of Silverlight does not reproduce this crash, so allow it
        // and any newer versions
        static const PlatformModuleVersion slPluginMinRequired(0x51BE0000, 0x00010000);

        if (compareFileVersion(slPluginMinRequired) < 0)
            return true;
    } else if (equalLettersIgnoringASCIICase(fileName(), "npmozax.dll")) {
        // Bug 15217: Mozilla ActiveX control complains about missing xpcom_core.dll
        return true;
    } else if (equalLettersIgnoringASCIICase(fileName(), "npwpf.dll")) {
        // Bug 57119: Microsoft Windows Presentation Foundation (WPF) plug-in complains about missing xpcom.dll
        return true;
    } else if (name() == "Yahoo Application State Plugin") {
        // https://bugs.webkit.org/show_bug.cgi?id=26860
        // Bug in Yahoo Application State plug-in earlier than 1.0.0.6 leads to heap corruption. 
        static const PlatformModuleVersion yahooAppStatePluginMinRequired(0x00000006, 0x00010000);
        if (compareFileVersion(yahooAppStatePluginMinRequired) < 0)
            return true;
    }

    return false;
}

void PluginPackage::determineQuirks(const String& mimeType)
{
    if (mimeType == "application/x-shockwave-flash") {
        static const PlatformModuleVersion flashTenVersion(0x00000000, 0x000a0000);

        // Pre 10 Flash only requests windowless plugins if we return a mozilla user agent
        if (compareFileVersion(flashTenVersion) < 0)
            m_quirks.add(PluginQuirkWantsMozillaUserAgent);

        m_quirks.add(PluginQuirkThrottleInvalidate);
        m_quirks.add(PluginQuirkThrottleWMUserPlusOneMessages);
        m_quirks.add(PluginQuirkFlashURLNotifyBug);
    }

    if (name().contains("Microsoft") && name().contains("Windows Media")) {
        // The WMP plugin sets its size on the first NPP_SetWindow call and never updates its size, so
        // call SetWindow when the plugin view has a correct size
        m_quirks.add(PluginQuirkDeferFirstSetWindowCall);

        // Windowless mode does not work at all with the WMP plugin so just remove that parameter 
        // and don't pass it to the plug-in.
        m_quirks.add(PluginQuirkRemoveWindowlessVideoParam);

        // WMP has a modal message loop that it enters whenever we call it or
        // ask it to paint. This modal loop can deliver messages to other
        // windows in WebKit at times when they are not expecting them (for
        // example, delivering a WM_PAINT message during a layout), and these
        // can cause crashes.
        m_quirks.add(PluginQuirkHasModalMessageLoop);
    }

    if (name() == "VLC Multimedia Plugin" || name() == "VLC Multimedia Plug-in") {
        // VLC hangs on NPP_Destroy if we call NPP_SetWindow with a null window handle
        m_quirks.add(PluginQuirkDontSetNullWindowHandleOnDestroy);

        // VLC 0.8.6d and 0.8.6e crash if multiple instances are created.
        // <rdar://problem/5773070> tracks allowing multiple instances when this
        // bug is fixed.
        m_quirks.add(PluginQuirkDontAllowMultipleInstances);
    }

    // The DivX plugin sets its size on the first NPP_SetWindow call and never updates its size, so
    // call SetWindow when the plugin view has a correct size
    if (mimeType == "video/divx")
        m_quirks.add(PluginQuirkDeferFirstSetWindowCall);

    // FIXME: This is a workaround for a problem in our NPRuntime bindings; if a plug-in creates an
    // NPObject and passes it to a function it's not possible to see what root object that NPObject belongs to.
    // Thus, we don't know that the object should be invalidated when the plug-in instance goes away.
    // See <rdar://problem/5487742>.
    if (mimeType == "application/x-silverlight")
        m_quirks.add(PluginQuirkDontUnloadPlugin);

    if (MIMETypeRegistry::isJavaAppletMIMEType(mimeType)) {
        // Because a single process cannot create multiple VMs, and we cannot reliably unload a
        // Java VM, we cannot unload the Java plugin, or we'll lose reference to our only VM
        m_quirks.add(PluginQuirkDontUnloadPlugin);

        // Setting the window region to an empty region causes bad scrolling repaint problems
        // with the Java plug-in.
        m_quirks.add(PluginQuirkDontClipToZeroRectWhenScrolling);
    }

    if (mimeType == "audio/x-pn-realaudio-plugin") {
        // Prevent the Real plugin from calling the Window Proc recursively, causing the stack to overflow.
        m_quirks.add(PluginQuirkDontCallWndProcForSameMessageRecursively);

        static const PlatformModuleVersion lastKnownUnloadableRealPlayerVersion(0x000B0B24, 0x00060000);

        // Unloading RealPlayer versions newer than 10.5 can cause a hang; see rdar://5669317.
        // FIXME: Resume unloading when this bug in the RealPlayer Plug-In is fixed (rdar://5713147)
        if (compareFileVersion(lastKnownUnloadableRealPlayerVersion) > 0)
            m_quirks.add(PluginQuirkDontUnloadPlugin);
    }
}

bool PluginPackage::fetchInfo()
{
    DWORD versionInfoSize, zeroHandle;
    versionInfoSize = GetFileVersionInfoSizeW(m_path.wideCharacters().data(), &zeroHandle);
    if (versionInfoSize == 0)
        return false;

    Vector<char> versionInfoData(versionInfoSize);

    if (!GetFileVersionInfoW(m_path.wideCharacters().data(), 0, versionInfoSize, versionInfoData.data()))
        return false;

    m_name = getVersionInfo(versionInfoData.data(), "ProductName");
    m_description = getVersionInfo(versionInfoData.data(), "FileDescription");
    if (m_name.isNull() || m_description.isNull())
        return false;

    VS_FIXEDFILEINFO* info;
    UINT infoSize;
    if (!VerQueryValueW(versionInfoData.data(), L"\\", (LPVOID*) &info, &infoSize) || infoSize < sizeof(VS_FIXEDFILEINFO))
        return false;
    m_moduleVersion.leastSig = info->dwFileVersionLS;
    m_moduleVersion.mostSig = info->dwFileVersionMS;

    if (isPluginBlacklisted())
        return false;

    Vector<String> types = getVersionInfo(versionInfoData.data(), "MIMEType").split('|');
    Vector<String> extensionLists = getVersionInfo(versionInfoData.data(), "FileExtents").split('|');
    Vector<String> descriptions = getVersionInfo(versionInfoData.data(), "FileOpenName").split('|');

    for (unsigned i = 0; i < types.size(); i++) {
        String type = types[i].convertToASCIILowercase();
        String description = i < descriptions.size() ? descriptions[i] : "";
        String extensionList = i < extensionLists.size() ? extensionLists[i] : "";

        Vector<String> extensionsVector = extensionList.split(',');

        // Get rid of the extension list that may be at the end of the description string.
        int pos = description.find("(*");
        if (pos != -1) {
            // There might be a space that we need to get rid of.
            if (pos > 1 && description[pos - 1] == ' ')
                pos--;
            description = description.left(pos);
        }

        // Determine the quirks for the MIME types this plug-in supports
        determineQuirks(type);

        m_mimeToExtensions.add(type, extensionsVector);
        m_mimeToDescriptions.add(type, description);
    }

    return true;
}

bool PluginPackage::load()
{
    if (m_freeLibraryTimer.isActive()) {
        ASSERT(m_module);
        m_freeLibraryTimer.stop();
    } else if (m_isLoaded) {
        if (m_quirks.contains(PluginQuirkDontAllowMultipleInstances))
            return false;
        m_loadCount++;
        return true;
    } else {
        WCHAR currentPath[MAX_PATH];

        if (!::GetCurrentDirectoryW(MAX_PATH, currentPath))
            return false;

        String path = m_path.substring(0, m_path.reverseFind('\\'));

        if (!::SetCurrentDirectoryW(path.wideCharacters().data()))
            return false;

        // Load the library
        m_module = ::LoadLibraryExW(m_path.wideCharacters().data(), 0, LOAD_WITH_ALTERED_SEARCH_PATH);

        if (!::SetCurrentDirectoryW(currentPath)) {
            if (m_module)
                ::FreeLibrary(m_module);
            return false;
        }
    }

    if (!m_module)
        return false;

    m_isLoaded = true;

    NP_GetEntryPointsFuncPtr NP_GetEntryPoints = 0;
    NP_InitializeFuncPtr NP_Initialize = 0;
    NPError npErr = NPERR_NO_ERROR;

    NP_Initialize = (NP_InitializeFuncPtr)GetProcAddress(m_module, "NP_Initialize");
    NP_GetEntryPoints = (NP_GetEntryPointsFuncPtr)GetProcAddress(m_module, "NP_GetEntryPoints");
#if ENABLE(NETSCAPE_PLUGIN_API)
    m_NPP_Shutdown = (NPP_ShutdownProcPtr)GetProcAddress(m_module, "NP_Shutdown");

    if (!NP_Initialize || !NP_GetEntryPoints || !m_NPP_Shutdown)
#else
    if (!NP_Initialize || !NP_GetEntryPoints)
#endif
        goto abort;

#if ENABLE(NETSCAPE_PLUGIN_API)
    memset(&m_pluginFuncs, 0, sizeof(m_pluginFuncs));
    m_pluginFuncs.size = sizeof(m_pluginFuncs);

    npErr = NP_GetEntryPoints(&m_pluginFuncs);
    LOG_NPERROR(npErr);
    if (npErr != NPERR_NO_ERROR)
        goto abort;

    initializeBrowserFuncs();

    npErr = NP_Initialize(&m_browserFuncs);
    LOG_NPERROR(npErr);

    if (npErr != NPERR_NO_ERROR)
        goto abort;
#endif
    m_loadCount++;
    return true;

abort:
    unloadWithoutShutdown();
    return false;
}

unsigned PluginPackage::hash() const
{ 
    const unsigned hashCodes[] = {
        m_name.impl()->hash(),
        m_description.impl()->hash(),
        m_mimeToExtensions.size()
    };

    return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes);
}

bool PluginPackage::equal(const PluginPackage& a, const PluginPackage& b)
{
    if (a.m_name != b.m_name)
        return false;

    if (a.m_description != b.m_description)
        return false;

    if (a.m_mimeToExtensions.size() != b.m_mimeToExtensions.size())
        return false;

    auto end = a.m_mimeToExtensions.end().keys();
    for (auto it = a.m_mimeToExtensions.begin().keys(); it != end; ++it) {
        if (!b.m_mimeToExtensions.contains(*it))
            return false;
    }

    return true;
}

uint16_t PluginPackage::NPVersion() const
{
    return NP_VERSION_MINOR;
}
}
