File indexing completed on 2024-04-28 15:23:15

0001 /*
0002  *  This file is part of the KDE libraries
0003  *  Copyright (C) 2000 Harri Porten (porten@kde.org)
0004  *  Copyright (c) 2000 Daniel Molkentin (molkentin@kde.org)
0005  *  Copyright (c) 2000 Stefan Schimanski (schimmi@kde.org)
0006  *  Copyright (C) 2003 Apple Computer, Inc.
0007  *
0008  *  This library is free software; you can redistribute it and/or
0009  *  modify it under the terms of the GNU Library General Public
0010  *  License as published by the Free Software Foundation; either
0011  *  version 2 of the License, or (at your option) any later version.
0012  *
0013  *  This library is distributed in the hope that it will be useful,
0014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0016  *  Library General Public License for more details.
0017  *
0018  *  You should have received a copy of the GNU Library General Public
0019  *  License along with this library; if not, write to the Free Software
0020  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
0021  */
0022 
0023 #include "kjs_navigator.h"
0024 #include "kjs_navigator.lut.h"
0025 
0026 #include <QLocale>
0027 
0028 #include <kconfig.h>
0029 #include <kconfiggroup.h>
0030 #include <ksharedconfig.h>
0031 #include "khtml_debug.h"
0032 
0033 #include <kprotocolmanager.h>
0034 #include <kservice.h>
0035 #include <kservicetypetrader.h>
0036 #include <kjs/lookup.h>
0037 #include <kjs_binding.h>
0038 #include <khtml_part.h>
0039 #include <qsysinfo.h>
0040 #include <qstandardpaths.h>
0041 
0042 using namespace KJS;
0043 
0044 namespace KJS
0045 {
0046 
0047 // All objects that need plugin info must inherit from PluginBase
0048 // Its ctor and dtor take care of the refcounting on the static lists.
0049 class PluginBase : public JSObject
0050 {
0051 public:
0052     PluginBase(ExecState *exec, bool loadPluginInfo);
0053     virtual ~PluginBase();
0054 
0055     struct MimeClassInfo;
0056     struct PluginInfo;
0057 
0058     struct MimeClassInfo {
0059         QString type;
0060         QString desc;
0061         QString suffixes;
0062         PluginInfo *plugin;
0063     };
0064 
0065     struct PluginInfo {
0066         QString name;
0067         QString file;
0068         QString desc;
0069         QList<const MimeClassInfo *> mimes;
0070     };
0071 
0072     static QList<const PluginInfo *> *plugins;
0073     static QList<const MimeClassInfo *> *mimes;
0074 
0075 private:
0076     static int m_refCount;
0077 };
0078 
0079 class Plugins : public PluginBase
0080 {
0081 public:
0082     Plugins(ExecState *exec, bool pluginsEnabled)
0083         : PluginBase(exec, pluginsEnabled),
0084           m_pluginsEnabled(pluginsEnabled) {}
0085 
0086     using KJS::JSObject::getOwnPropertySlot;
0087     bool getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) override;
0088     JSValue *getValueProperty(ExecState *exec, int token) const;
0089     const ClassInfo *classInfo() const override
0090     {
0091         return &info;
0092     }
0093     static const ClassInfo info;
0094     static JSValue *pluginByName(ExecState *exec, const QString &name);
0095     bool pluginsEnabled() const
0096     {
0097         return m_pluginsEnabled;
0098     }
0099 private:
0100     static JSValue *indexGetter(ExecState *, JSObject *, const Identifier &, const PropertySlot &);
0101     static JSValue *nameGetter(ExecState *, JSObject *, const Identifier &, const PropertySlot &);
0102     bool m_pluginsEnabled;
0103 };
0104 
0105 class MimeTypes : public PluginBase
0106 {
0107 public:
0108     MimeTypes(ExecState *exec, bool pluginsEnabled)
0109         : PluginBase(exec, pluginsEnabled),
0110           m_pluginsEnabled(pluginsEnabled) {}
0111     using KJS::JSObject::getOwnPropertySlot;
0112     bool getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) override;
0113     const ClassInfo *classInfo() const override
0114     {
0115         return &info;
0116     }
0117     static const ClassInfo info;
0118     JSValue *getValueProperty(ExecState *exec, int token) const;
0119     static JSValue *mimeTypeByName(ExecState *exec, const QString &name);
0120     bool pluginsEnabled() const
0121     {
0122         return m_pluginsEnabled;
0123     }
0124 private:
0125     static JSValue *indexGetter(ExecState *, JSObject *, const Identifier &, const PropertySlot &);
0126     static JSValue *nameGetter(ExecState *, JSObject *, const Identifier &, const PropertySlot &);
0127     bool m_pluginsEnabled;
0128 };
0129 
0130 class Plugin : public PluginBase
0131 {
0132 public:
0133     Plugin(ExecState *exec, const PluginBase::PluginInfo *info)
0134         : PluginBase(exec, true)
0135     {
0136         m_info = info;
0137     }
0138     using KJS::JSObject::getOwnPropertySlot;
0139     bool getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) override;
0140     const ClassInfo *classInfo() const override
0141     {
0142         return &info;
0143     }
0144     static const ClassInfo info;
0145     JSValue *mimeByName(ExecState *exec, const QString &name) const;
0146     JSValue *getValueProperty(ExecState *exec, int token) const;
0147     const PluginBase::PluginInfo *pluginInfo() const
0148     {
0149         return m_info;
0150     }
0151 private:
0152     const PluginBase::PluginInfo *m_info;
0153     static JSValue *indexGetter(ExecState *, JSObject *, const Identifier &, const PropertySlot &);
0154     static JSValue *nameGetter(ExecState *, JSObject *, const Identifier &, const PropertySlot &);
0155 };
0156 
0157 class MimeType : public PluginBase
0158 {
0159 public:
0160     MimeType(ExecState *exec, const PluginBase::MimeClassInfo *info)
0161         : PluginBase(exec, true)
0162     {
0163         m_info = info;
0164     }
0165     using KJS::JSObject::getOwnPropertySlot;
0166     bool getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) override;
0167     const ClassInfo *classInfo() const override
0168     {
0169         return &info;
0170     }
0171     static const ClassInfo info;
0172     JSValue *getValueProperty(ExecState *exec, int token) const;
0173 private:
0174     const PluginBase::MimeClassInfo *m_info;
0175 };
0176 
0177 }
0178 
0179 QList<const PluginBase::PluginInfo *> *KJS::PluginBase::plugins;
0180 QList<const PluginBase::MimeClassInfo *> *KJS::PluginBase::mimes;
0181 int KJS::PluginBase::m_refCount;
0182 
0183 const ClassInfo Navigator::info = { "Navigator", nullptr, &NavigatorTable, nullptr };
0184 /*
0185 @begin NavigatorTable 12
0186   appCodeName   Navigator::AppCodeName  DontDelete|ReadOnly
0187   appName   Navigator::AppName  DontDelete|ReadOnly
0188   appVersion    Navigator::AppVersion   DontDelete|ReadOnly
0189   language  Navigator::Language DontDelete|ReadOnly
0190   userAgent Navigator::UserAgent    DontDelete|ReadOnly
0191   userLanguage  Navigator::UserLanguage DontDelete|ReadOnly
0192   browserLanguage Navigator::BrowserLanguage    DontDelete|ReadOnly
0193   platform  Navigator::Platform DontDelete|ReadOnly
0194   cpuClass      Navigator::CpuClass     DontDelete|ReadOnly
0195   plugins   Navigator::_Plugins DontDelete|ReadOnly
0196   mimeTypes Navigator::_MimeTypes   DontDelete|ReadOnly
0197   product   Navigator::Product  DontDelete|ReadOnly
0198   vendor    Navigator::Vendor   DontDelete|ReadOnly
0199   vendorSub Navigator::VendorSub    DontDelete|ReadOnly
0200   productSub    Navigator::ProductSub   DontDelete|ReadOnly
0201   cookieEnabled Navigator::CookieEnabled DontDelete|ReadOnly
0202   javaEnabled   Navigator::JavaEnabled  DontDelete|Function 0
0203 @end
0204 */
0205 KJS_IMPLEMENT_PROTOFUNC(NavigatorFunc)
0206 
0207 Navigator::Navigator(ExecState *exec, KHTMLPart *p)
0208     : JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()), m_part(p) { }
0209 
0210 bool Navigator::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0211 {
0212 #ifdef KJS_VERBOSE
0213     qCDebug(KHTML_LOG) << "Navigator::getOwnPropertySlot " << propertyName.ascii();
0214 #endif
0215     return getStaticPropertySlot<NavigatorFunc, Navigator, JSObject>(exec, &NavigatorTable, this, propertyName, slot);
0216 }
0217 
0218 JSValue *Navigator::getValueProperty(ExecState *exec, int token) const
0219 {
0220     QUrl url = m_part->url();
0221     QString host = url.host();
0222     if (host.isEmpty()) {
0223         host = "localhost";
0224     }
0225     QString userAgent  = KProtocolManager::userAgentForHost(host);
0226 // ### get the following from the spoofing UA files as well.
0227     QString appName = "Netscape";
0228     QString product = "Gecko";
0229     QString productSub = "20030107";
0230     QString vendor = "KDE";
0231     QString vendorSub = "";
0232 
0233     switch (token) {
0234     case AppCodeName:
0235         return jsString("Mozilla");
0236     case AppName:
0237         // If we find "Mozilla" but not "(compatible, ...)" we are a real Netscape
0238         if (userAgent.indexOf(QLatin1String("Mozilla")) >= 0 &&
0239                 userAgent.indexOf(QLatin1String("compatible")) == -1) {
0240             //qCDebug(KHTML_LOG) << "appName -> Mozilla";
0241             return jsString("Netscape");
0242         }
0243         if (userAgent.indexOf(QLatin1String("Microsoft")) >= 0 ||
0244                 userAgent.indexOf(QLatin1String("MSIE")) >= 0) {
0245             //qCDebug(KHTML_LOG) << "appName -> IE";
0246             return jsString("Microsoft Internet Explorer");
0247         }
0248         //qCDebug(KHTML_LOG) << "appName -> Default";
0249         return jsString(appName);
0250     case AppVersion:
0251         // We assume the string is something like Mozilla/version (properties)
0252         return jsString(userAgent.mid(userAgent.indexOf('/') + 1));
0253     case Product:
0254         // We are pretending to be Mozilla or Safari
0255         if (userAgent.indexOf(QLatin1String("Mozilla")) >= 0 &&
0256                 userAgent.indexOf(QLatin1String("compatible")) == -1) {
0257             return jsString("Gecko");
0258         }
0259         // When spoofing as IE, we use jsUndefined().
0260         if (userAgent.indexOf(QLatin1String("Microsoft")) >= 0 ||
0261                 userAgent.indexOf(QLatin1String("MSIE")) >= 0) {
0262             return jsUndefined();
0263         }
0264         return jsString(product);
0265     case ProductSub: {
0266         int ix = userAgent.indexOf("Gecko");
0267         if (ix >= 0 && userAgent.length() >= ix + 14 && userAgent.at(ix + 5) == '/' &&
0268                 userAgent.indexOf(QRegExp("\\d{8}"), ix + 6) == ix + 6) {
0269             // We have Gecko/<productSub> in the UA string
0270             return jsString(userAgent.mid(ix + 6, 8));
0271         }
0272     }
0273     return jsString(productSub);
0274     case Vendor:
0275         if (userAgent.indexOf(QLatin1String("Safari")) >= 0) {
0276             return jsString("Apple Computer, Inc.");
0277         }
0278         return jsString(vendor);
0279     case VendorSub:
0280         return jsString(vendorSub);
0281     case BrowserLanguage:
0282     case Language:
0283     case UserLanguage:
0284         return jsString(QLocale::languageToString(QLocale().language()));
0285     case UserAgent:
0286         return jsString(userAgent);
0287     case Platform:
0288         // yet another evil hack, but necessary to spoof some sites...
0289         if ((userAgent.indexOf(QLatin1String("Win"), 0, Qt::CaseInsensitive) >= 0)) {
0290             return jsString("Win32");
0291         } else if ((userAgent.indexOf(QLatin1String("Macintosh"), 0, Qt::CaseInsensitive) >= 0) ||
0292                    (userAgent.indexOf(QLatin1String("Mac_PowerPC"), 0, Qt::CaseInsensitive) >= 0)) {
0293             return jsString("MacPPC");
0294         } else {
0295             return jsString(QString::fromLatin1("%1 %2").arg(QSysInfo::kernelType()).arg(QSysInfo::currentCpuArchitecture()));
0296         }
0297     case CpuClass:
0298             return jsString(QSysInfo::currentCpuArchitecture());
0299     case _Plugins:
0300         return new Plugins(exec, m_part->pluginsEnabled());
0301     case _MimeTypes:
0302         return new MimeTypes(exec, m_part->pluginsEnabled());
0303     case CookieEnabled:
0304         return jsBoolean(true); /// ##### FIXME
0305     default:
0306         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMEvent::getValueProperty : " << token;
0307         return jsNull();
0308     }
0309 }
0310 
0311 /*******************************************************************/
0312 
0313 PluginBase::PluginBase(ExecState *exec, bool loadPluginInfo)
0314     : JSObject(exec->lexicalInterpreter()->builtinObjectPrototype())
0315 {
0316     if (loadPluginInfo && !plugins) {
0317         plugins = new QList<const PluginInfo *>;
0318         mimes = new QList<const MimeClassInfo *>;
0319 
0320         // read in using KServiceTypeTrader
0321         const KService::List offers = KServiceTypeTrader::self()->query("Browser/View");
0322         KService::List::const_iterator it;
0323         for (it = offers.begin(); it != offers.end(); ++it) {
0324 
0325             QVariant pluginsinfo = (**it).property("X-KDE-BrowserView-PluginsInfo");
0326             if (!pluginsinfo.isValid()) {
0327                 // <backwards compatible>
0328                 if ((**it).library() == QLatin1String("libnsplugin")) {
0329                     pluginsinfo = QVariant("nsplugins/pluginsinfo");
0330                 } else
0331                     // </backwards compatible>
0332                 {
0333                     continue;
0334                 }
0335             }
0336             // read configuration
0337             QString fn = QStandardPaths::locate(QStandardPaths::GenericDataLocation, pluginsinfo.toString());
0338             const KSharedConfig::Ptr sc = KSharedConfig::openConfig(fn);
0339             const int num = sc->group("").readEntry("number", 0);
0340             for (int n = 0; n < num; n++) {
0341                 const KConfigGroup kc = sc->group(QString::number(n));
0342                 PluginInfo *plugin = new PluginInfo;
0343 
0344                 plugin->name = kc.readEntry("name");
0345                 plugin->file = kc.readPathEntry("file", QString());
0346                 plugin->desc = kc.readEntry("description");
0347 
0348                 plugins->append(plugin);
0349 
0350                 const QStringList types = kc.readXdgListEntry("mime");
0351                 QStringList::const_iterator type;
0352                 for (type = types.begin(); type != types.end(); ++type) {
0353 
0354                     // get mime information
0355                     const QStringList tokens = (*type).split(':', QString::KeepEmptyParts);
0356                     if (tokens.count() < 3) { // we need 3 items
0357                         continue;
0358                     }
0359 
0360                     MimeClassInfo *mime = new MimeClassInfo;
0361                     QStringList::ConstIterator token = tokens.begin();
0362                     mime->type = (*token).toLower();
0363                     //qCDebug(KHTML_LOG) << "mime->type=" << mime->type;
0364                     ++token;
0365 
0366                     mime->suffixes = *token;
0367                     ++token;
0368 
0369                     mime->desc = *token;
0370                     ++token;
0371 
0372                     mime->plugin = plugin;
0373 
0374                     mimes->append(mime);
0375                     plugin->mimes.append(mime);
0376 
0377                 }
0378             }
0379         }
0380     }
0381 
0382     m_refCount++;
0383 }
0384 
0385 PluginBase::~PluginBase()
0386 {
0387     m_refCount--;
0388     if (m_refCount == 0) {
0389         if (plugins) {
0390             qDeleteAll(*plugins);
0391         }
0392         if (mimes) {
0393             qDeleteAll(*mimes);
0394         }
0395         delete plugins;
0396         delete mimes;
0397         plugins = nullptr;
0398         mimes = nullptr;
0399     }
0400 }
0401 
0402 /*******************************************************************/
0403 
0404 const ClassInfo Plugins::info = { "PluginArray", nullptr, &PluginsTable, nullptr };
0405 /*
0406 @begin PluginsTable 4
0407   length    Plugins_Length      DontDelete|ReadOnly
0408   refresh   Plugins_Refresh     DontDelete|Function 0
0409   item      Plugins_Item        DontDelete|Function 1
0410   namedItem     Plugins_NamedItem       DontDelete|Function 1
0411 @end
0412 */
0413 KJS_IMPLEMENT_PROTOFUNC(PluginsFunc)
0414 
0415 JSValue *Plugins::getValueProperty(ExecState *, int token) const
0416 {
0417     assert(token == Plugins_Length);
0418     Q_UNUSED(token);
0419     if (pluginsEnabled()) {
0420         return jsNumber(plugins->count());
0421     } else {
0422         return jsNumber(0);
0423     }
0424 }
0425 
0426 JSValue *Plugins::indexGetter(ExecState *exec, JSObject *, const Identifier & /*propertyName*/, const PropertySlot &slot)
0427 {
0428     return new Plugin(exec, plugins->at(slot.index()));
0429 }
0430 
0431 JSValue *Plugins::nameGetter(ExecState *exec, JSObject *, const Identifier &propertyName, const PropertySlot & /*slot*/)
0432 {
0433     return pluginByName(exec, propertyName.qstring());
0434 }
0435 
0436 bool Plugins::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0437 {
0438 #ifdef KJS_VERBOSE
0439     qCDebug(KHTML_LOG) << "Plugins::getOwnPropertySlot " << propertyName.qstring();
0440 #endif
0441     if (getStaticOwnPropertySlot<PluginsFunc, Plugins>(&PluginsTable, this, propertyName, slot)) {
0442         return true;
0443     }
0444 
0445     if (pluginsEnabled()) {
0446         // plugins[#]
0447         bool ok;
0448         unsigned int i = propertyName.toArrayIndex(&ok);
0449         if (ok && i < static_cast<unsigned>(plugins->count())) {
0450             slot.setCustomIndex(this, i, indexGetter);
0451             return true;
0452         }
0453 
0454         // plugin[name]
0455         QList<const PluginInfo *>::const_iterator it, end = plugins->constEnd();
0456         for (it = plugins->constBegin(); it != end; ++it) {
0457             if ((*it)->name == propertyName.qstring()) {
0458                 slot.setCustom(this, nameGetter);
0459                 return true;
0460             }
0461         }
0462     }
0463 
0464     return PluginBase::getOwnPropertySlot(exec, propertyName, slot);
0465 }
0466 
0467 JSValue *Plugins::pluginByName(ExecState *exec, const QString &name)
0468 {
0469     QList<const PluginInfo *>::const_iterator it, end = plugins->constEnd();
0470     for (it = plugins->constBegin(); it != end; ++it) {
0471         if ((*it)->name == name) {
0472             return new Plugin(exec, *it);
0473         }
0474     }
0475     return jsUndefined();
0476 }
0477 
0478 JSValue *PluginsFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
0479 {
0480     KJS_CHECK_THIS(KJS::Plugins, thisObj);
0481 
0482     KJS::Plugins *base = static_cast<KJS::Plugins *>(thisObj);
0483     if (!base->pluginsEnabled()) {
0484         return jsUndefined();
0485     }
0486 
0487     switch (id) {
0488     case Plugins_Refresh:
0489         return jsUndefined(); //## TODO
0490     case Plugins_Item: {
0491         bool ok;
0492         unsigned int i = args[0]->toString(exec).toArrayIndex(&ok);
0493         if (ok && i < static_cast<unsigned>(base->plugins->count())) {
0494             return new Plugin(exec, base->plugins->at(i));
0495         }
0496         return jsUndefined();
0497     }
0498     case Plugins_NamedItem: {
0499         UString s = args[0]->toString(exec);
0500         return base->pluginByName(exec, s.qstring());
0501     }
0502     default:
0503         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in PluginsFunc::callAsFunction : " << id;
0504         return jsUndefined();
0505     }
0506 }
0507 
0508 /*******************************************************************/
0509 
0510 const ClassInfo MimeTypes::info = { "MimeTypeArray", nullptr, &MimeTypesTable, nullptr };
0511 /*
0512 @begin MimeTypesTable 3
0513   length    MimeTypes_Length    DontDelete|ReadOnly
0514   item      MimeTypes_Item      DontDelete|Function 1
0515   namedItem     MimeTypes_NamedItem     DontDelete|Function 1
0516 @end
0517 */
0518 KJS_IMPLEMENT_PROTOFUNC(MimeTypesFunc)
0519 
0520 JSValue *MimeTypes::indexGetter(ExecState *exec, JSObject *, const Identifier & /*propertyName*/, const PropertySlot &slot)
0521 {
0522     return new MimeType(exec, mimes->at(slot.index()));
0523 }
0524 
0525 JSValue *MimeTypes::nameGetter(ExecState *exec, JSObject *, const Identifier &propertyName, const PropertySlot & /*slot*/)
0526 {
0527     return mimeTypeByName(exec, propertyName.qstring());
0528 }
0529 
0530 bool MimeTypes::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0531 {
0532 #ifdef KJS_VERBOSE
0533     qCDebug(KHTML_LOG) << "MimeTypes::getOwnPropertySlot " << propertyName.qstring();
0534 #endif
0535     if (getStaticOwnPropertySlot<MimeTypesFunc, MimeTypes>(&MimeTypesTable, this, propertyName, slot)) {
0536         return true;
0537     }
0538 
0539     if (pluginsEnabled()) {
0540         // mimeTypes[#]
0541         bool ok;
0542         unsigned int i = propertyName.toArrayIndex(&ok);
0543         if (ok && i < static_cast<unsigned>(mimes->count())) {
0544             slot.setCustomIndex(this, i, indexGetter);
0545             return true;
0546         }
0547 
0548         // mimeTypes[name]
0549         QList<const MimeClassInfo *>::const_iterator it, end = mimes->constEnd();
0550         for (it = mimes->constBegin(); it != end; ++it) {
0551             if ((*it)->type == propertyName.qstring()) {
0552                 slot.setCustom(this, nameGetter);
0553                 return true;
0554             }
0555         }
0556     }
0557 
0558     return PluginBase::getOwnPropertySlot(exec, propertyName, slot);
0559 }
0560 
0561 JSValue *MimeTypes::mimeTypeByName(ExecState *exec, const QString &name)
0562 {
0563     //qCDebug(KHTML_LOG) << "MimeTypes[" << name << "]";
0564     QList<const MimeClassInfo *>::const_iterator it, end = mimes->constEnd();
0565     for (it = mimes->constBegin(); it != end; ++it) {
0566         if ((*it)->type == name) {
0567             return new MimeType(exec, (*it));
0568         }
0569     }
0570     return jsUndefined();
0571 }
0572 
0573 JSValue *MimeTypes::getValueProperty(ExecState * /*exec*/, int token) const
0574 {
0575     assert(token == MimeTypes_Length);
0576     Q_UNUSED(token);
0577     if (pluginsEnabled()) {
0578         return jsNumber(mimes->count());
0579     } else {
0580         return jsNumber(0);
0581     }
0582 }
0583 
0584 JSValue *MimeTypesFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
0585 {
0586     KJS_CHECK_THIS(KJS::MimeTypes, thisObj);
0587     KJS::MimeTypes *base = static_cast<KJS::MimeTypes *>(thisObj);
0588 
0589     if (!base->pluginsEnabled()) {
0590         return jsUndefined();
0591     }
0592 
0593     switch (id) {
0594     case MimeTypes_Item: {
0595         bool ok;
0596         unsigned int i = args[0]->toString(exec).toArrayIndex(&ok);
0597         if (ok && i < static_cast<unsigned>(base->mimes->count())) {
0598             return new MimeType(exec, base->mimes->at(i));
0599         }
0600         return jsUndefined();
0601     }
0602     case MimeTypes_NamedItem: {
0603         UString s = args[0]->toString(exec);
0604         return base->mimeTypeByName(exec, s.qstring());
0605     }
0606     default:
0607         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in MimeTypesFunc::callAsFunction : " << id;
0608         return jsUndefined();
0609     }
0610 }
0611 
0612 /************************************************************************/
0613 const ClassInfo Plugin::info = { "Plugin", nullptr, &PluginTable, nullptr };
0614 /*
0615 @begin PluginTable 7
0616   name      Plugin_Name     DontDelete|ReadOnly
0617   filename      Plugin_FileName     DontDelete|ReadOnly
0618   description   Plugin_Description      DontDelete|ReadOnly
0619   length    Plugin_Length       DontDelete|ReadOnly
0620   item      Plugin_Item     DontDelete|Function 1
0621   namedItem     Plugin_NamedItem    DontDelete|Function 1
0622 @end
0623 */
0624 KJS_IMPLEMENT_PROTOFUNC(PluginFunc)
0625 
0626 JSValue *Plugin::indexGetter(ExecState *exec, JSObject *, const Identifier & /*propertyName*/, const PropertySlot &slot)
0627 {
0628     Plugin *thisObj = static_cast<Plugin *>(slot.slotBase());
0629     return new MimeType(exec, thisObj->m_info->mimes.at(slot.index()));
0630 }
0631 
0632 JSValue *Plugin::nameGetter(ExecState *exec, JSObject *, const Identifier &propertyName, const PropertySlot &slot)
0633 {
0634     Plugin *thisObj = static_cast<Plugin *>(slot.slotBase());
0635     return thisObj->mimeByName(exec, propertyName.qstring());
0636 }
0637 
0638 bool Plugin::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0639 {
0640 #ifdef KJS_VERBOSE
0641     qCDebug(KHTML_LOG) << "Plugin::getOwnPropertySlot " << propertyName.qstring();
0642 #endif
0643     if (getStaticOwnPropertySlot<PluginFunc, Plugin>(&PluginTable, this, propertyName, slot)) {
0644         return true;
0645     }
0646 
0647     // plugin[#]
0648     bool ok;
0649     unsigned int i = propertyName.toArrayIndex(&ok);
0650     if (ok && i < static_cast<unsigned>(m_info->mimes.count())) {
0651         slot.setCustomIndex(this, i, indexGetter);
0652         return true;
0653     }
0654 
0655     // plugin["name"]
0656     QList<const MimeClassInfo *>::const_iterator it, end = mimes->constEnd();
0657     for (it = mimes->constBegin(); it != end; ++it) {
0658         if ((*it)->type == propertyName.qstring()) {
0659             slot.setCustom(this, nameGetter);
0660             return true;
0661         }
0662     }
0663 
0664     return PluginBase::getOwnPropertySlot(exec, propertyName, slot);
0665 }
0666 
0667 JSValue *Plugin::mimeByName(ExecState *exec, const QString &name) const
0668 {
0669     const QList<const MimeClassInfo *> &mimes = m_info->mimes;
0670     QList<const MimeClassInfo *>::const_iterator it, end = mimes.end();
0671     for (it = mimes.begin(); it != end; ++it) {
0672         if ((*it)->type == name) {
0673             return new MimeType(exec, (*it));
0674         }
0675     }
0676     return jsUndefined();
0677 }
0678 
0679 JSValue *Plugin::getValueProperty(ExecState * /*exec*/, int token) const
0680 {
0681     switch (token) {
0682     case Plugin_Name:
0683         return jsString(UString(m_info->name));
0684     case Plugin_FileName:
0685         return jsString(UString(m_info->file));
0686     case Plugin_Description:
0687         return jsString(UString(m_info->desc));
0688     case Plugin_Length:
0689         return jsNumber(m_info->mimes.count());
0690     default:
0691         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in Plugin::getValueProperty : " << token;
0692         return jsUndefined();
0693     }
0694 }
0695 
0696 JSValue *PluginFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
0697 {
0698     KJS_CHECK_THIS(KJS::Plugin, thisObj);
0699     KJS::Plugin *plugin = static_cast<KJS::Plugin *>(thisObj);
0700     switch (id) {
0701     case Plugin_Item: {
0702         bool ok;
0703         unsigned int i = args[0]->toString(exec).toArrayIndex(&ok);
0704         if (ok && i < static_cast<unsigned>(plugin->pluginInfo()->mimes.count())) {
0705             return new MimeType(exec, plugin->pluginInfo()->mimes.at(i));
0706         }
0707         return jsUndefined();
0708     }
0709     case Plugin_NamedItem: {
0710         UString s = args[0]->toString(exec);
0711         return plugin->mimeByName(exec, s.qstring());
0712     }
0713     default:
0714         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in PluginFunc::callAsFunction : " << id;
0715         return jsUndefined();
0716     }
0717 }
0718 
0719 /*****************************************************************************/
0720 
0721 const ClassInfo MimeType::info = { "MimeType", nullptr, &MimeTypeTable, nullptr };
0722 /*
0723 @begin MimeTypeTable 4
0724   description   MimeType_Description        DontDelete|ReadOnly
0725   enabledPlugin MimeType_EnabledPlugin      DontDelete|ReadOnly
0726   suffixes  MimeType_Suffixes           DontDelete|ReadOnly
0727   type      MimeType_Type           DontDelete|ReadOnly
0728 @end
0729 */
0730 
0731 bool MimeType::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0732 {
0733 #ifdef KJS_VERBOSE
0734     qCDebug(KHTML_LOG) << "MimeType::get " << propertyName.qstring();
0735 #endif
0736     return getStaticValueSlot<MimeType, JSObject>(exec, &MimeTypeTable, this, propertyName, slot);
0737 }
0738 
0739 JSValue *MimeType::getValueProperty(ExecState *exec, int token) const
0740 {
0741     switch (token) {
0742     case MimeType_Type:
0743         return jsString(UString(m_info->type));
0744     case MimeType_Suffixes:
0745         return jsString(UString(m_info->suffixes));
0746     case MimeType_Description:
0747         return jsString(UString(m_info->desc));
0748     case MimeType_EnabledPlugin:
0749         return new Plugin(exec, m_info->plugin);
0750     default:
0751         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in MimeType::getValueProperty : " << token;
0752         return jsUndefined();
0753     }
0754 }
0755 
0756 JSValue *NavigatorFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &)
0757 {
0758     KJS_CHECK_THIS(KJS::Navigator, thisObj);
0759     Navigator *nav = static_cast<Navigator *>(thisObj);
0760     // javaEnabled()
0761     return jsBoolean(nav->part()->javaEnabled());
0762 }