1/*
2 * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
3 * Copyright (C) 2008 Collabora Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "PluginPackage.h"
29
30#include "CString.h"
31#include "MIMETypeRegistry.h"
32#include "npruntime_impl.h"
33#include "PluginDatabase.h"
34#include "PluginDebug.h"
35
36namespace WebCore {
37
38bool PluginPackage::fetchInfo()
39{
40    if (!load())
41        return false;
42
43    NPP_GetValueProcPtr gv = (NPP_GetValueProcPtr)m_module->resolve("NP_GetValue");
44    typedef char *(*NPP_GetMIMEDescriptionProcPtr)();
45    NPP_GetMIMEDescriptionProcPtr gm =
46        (NPP_GetMIMEDescriptionProcPtr)m_module->resolve("NP_GetMIMEDescription");
47    if (!gm || !gv)
48        return false;
49
50    char *buf = 0;
51    NPError err = gv(0, NPPVpluginNameString, (void*) &buf);
52    if (err != NPERR_NO_ERROR)
53        return false;
54
55    m_name = buf;
56    err = gv(0, NPPVpluginDescriptionString, (void*) &buf);
57    if (err != NPERR_NO_ERROR)
58        return false;
59
60    m_description = buf;
61    determineModuleVersionFromDescription();
62
63    String s = gm();
64    Vector<String> types;
65    s.split(UChar(';'), false, types);
66    for (unsigned i = 0; i < types.size(); ++i) {
67        Vector<String> mime;
68        types[i].split(UChar(':'), true, mime);
69        if (mime.size() > 0) {
70            Vector<String> exts;
71            if (mime.size() > 1)
72                mime[1].split(UChar(','), false, exts);
73            determineQuirks(mime[0]);
74            m_mimeToExtensions.add(mime[0], exts);
75            if (mime.size() > 2)
76                m_mimeToDescriptions.add(mime[0], mime[2]);
77        }
78    }
79
80    return true;
81}
82
83static NPError staticPluginQuirkRequiresGtkToolKit_NPN_GetValue(NPP instance, NPNVariable variable, void* value)
84{
85    if (variable == NPNVToolkit) {
86        *static_cast<uint32*>(value) = 2;
87        return NPERR_NO_ERROR;
88    }
89
90    return NPN_GetValue(instance, variable, value);
91}
92
93bool PluginPackage::load()
94{
95    if (m_isLoaded) {
96        m_loadCount++;
97        return true;
98    }
99
100    m_module = new QLibrary((QString)m_path);
101    m_module->setLoadHints(QLibrary::ResolveAllSymbolsHint);
102    if (!m_module->load()) {
103        LOG(Plugins, "%s not loaded (%s)", m_path.utf8().data(),
104                m_module->errorString().toLatin1().constData());
105        return false;
106    }
107
108    m_isLoaded = true;
109
110    NP_InitializeFuncPtr NP_Initialize;
111    NPError npErr;
112
113    NP_Initialize = (NP_InitializeFuncPtr)m_module->resolve("NP_Initialize");
114    m_NPP_Shutdown = (NPP_ShutdownProcPtr)m_module->resolve("NP_Shutdown");
115
116    if (!NP_Initialize || !m_NPP_Shutdown)
117        goto abort;
118
119    memset(&m_pluginFuncs, 0, sizeof(m_pluginFuncs));
120    m_pluginFuncs.size = sizeof(m_pluginFuncs);
121
122    initializeBrowserFuncs();
123
124    if (m_path.contains("npwrapper.")) {
125        // nspluginwrapper relies on the toolkit value to know if glib is available
126        // It does so in NP_Initialize with a null instance, therefore it is done this way:
127        m_browserFuncs.getvalue = staticPluginQuirkRequiresGtkToolKit_NPN_GetValue;
128    }
129
130#if defined(XP_UNIX)
131    npErr = NP_Initialize(&m_browserFuncs, &m_pluginFuncs);
132#else
133    npErr = NP_Initialize(&m_browserFuncs);
134#endif
135    if (npErr != NPERR_NO_ERROR)
136        goto abort;
137
138    m_loadCount++;
139    return true;
140
141abort:
142    unloadWithoutShutdown();
143    return false;
144}
145
146}
147