Changeset 32766 in webkit


Ignore:
Timestamp:
May 1, 2008 11:15:39 AM (16 years ago)
Author:
alp@webkit.org
Message:

2008-05-01 Marc Ordinas i Llopis <marc.ordinasillopis@collabora.co.uk>

Reviewed by Alp Toker.
Qt parts OK'ed by Simon Hausmann.

Based on work by several authors.

https://bugs.webkit.org/show_bug.cgi?id=14750
Added support for NPAPI plugins on Gtk and Qt-x11 ports.

Location:
trunk
Files:
7 added
30 edited

Legend:

Unmodified
Added
Removed
  • trunk/ChangeLog

    r32712 r32766  
     12008-05-01  Marc Ordinas i Llopis  <marc.ordinasillopis@collabora.co.uk>
     2
     3        Reviewed by Alp Toker.
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=14750
     6        Added support for NPAPI plugins on Gtk and Qt-x11 ports.
     7
     8        * GNUmakefile.am: Added Xt library.
     9
    1102008-04-29  David Kilzer  <ddkilzer@apple.com>
    211
  • trunk/GNUmakefile.am

    r32420 r32766  
    247247if TARGET_X11
    248248global_cppflags += -DXP_UNIX
     249webcore_libadd += -lXt
    249250endif
    250251
  • trunk/WebCore/ChangeLog

    r32763 r32766  
     12008-05-01  Marc Ordinas i Llopis  <marc.ordinasillopis@collabora.co.uk>
     2
     3        Reviewed by Alp Toker.
     4        Qt parts OK'ed by Simon Hausmann.
     5
     6        https://bugs.webkit.org/show_bug.cgi?id=14750
     7        Added support for NPAPI plugins on Gtk and Qt-x11 ports.
     8
     9        * GNUmakefile.am: Added Gtk plugin files.
     10        * WebCore.pro: Added Qt plugins files, defined XP_UNIX and
     11        ENABLE_NETSCAPE_PLUGIN_API
     12        * bridge/npruntime_internal.h: Additional undefs that conflict
     13        with Qt headers.
     14        * page/gtk/FrameGtk.cpp: Create js bindings for PluginView.
     15        (WebCore::Frame::createScriptInstanceForWidget):
     16        * page/qt/FrameQt.cpp: Create js bindings for PluginView.
     17        (WebCore::Frame::createScriptInstanceForWidget):
     18        (WebCore::Frame::clearPlatformScriptObjects):
     19        (WebCore::Frame::disconnectPlatformScriptObjects):
     20        * platform/FileSystem.h: Qt FileSystem implementation.
     21        * platform/Widget.h: Members to differentiate between Qt plugins and
     22        NPAPI ones.
     23        * platform/gtk/ScrollViewGtk.cpp:
     24        (WebCore::ScrollView::addChild): Set containing window before calling setParent.
     25        * platform/gtk/TemporaryLinkStubs.cpp: Removed implemented functions.
     26        (PluginView::invalidateRegion):
     27        * platform/qt/FileSystemQt.cpp: Implemented functions necessary for
     28        NPAPI plugins.
     29        (WebCore::openTemporaryFile):
     30        (WebCore::closeFile):
     31        (WebCore::writeToFile):
     32        (WebCore::unloadModule): Delete module if unloaded.
     33        * platform/qt/TemporaryLinkStubs.cpp: Removed implemented functions.
     34        * platform/qt/WidgetQt.cpp: Differentiate between Qt plugins and
     35        NPAPI ones.
     36        (WebCore::WidgetPrivate::WidgetPrivate):
     37        (WebCore::Widget::isNPAPIPlugin):
     38        (WebCore::Widget::setIsNPAPIPlugin):
     39        * plugins/PluginPackage.cpp:
     40        (WebCore::PluginPackage::~PluginPackage): Unload the module before
     41        destruction.
     42        (WebCore::PluginPackage::compare): Moved here as it's platform
     43        independent.
     44        * plugins/PluginView.cpp: Moved platform-independent functions here.
     45        (WebCore::PluginView::PluginView): Initialize m_npWindow.ws_info on
     46        Unix platforms.
     47        (WebCore::PluginView::freeStringArray):
     48        (WebCore::startsWithBlankLine):
     49        (WebCore::locationAfterFirstBlankLine):
     50        (WebCore::findEOL):
     51        (WebCore::capitalizeRFC822HeaderFieldName):
     52        (WebCore::parseRFC822HeaderFields):
     53        (WebCore::PluginView::handlePost):
     54        * plugins/PluginView.h: Moved platform-independent functions here.
     55        Added member to signal plugin needs XEmbed extension.
     56        * plugins/gtk/PluginDataGtk.cpp: Added.
     57        (WebCore::PluginData::initPlugins):
     58        (WebCore::PluginData::refresh):
     59        * plugins/gtk/PluginDatabaseGtk.cpp:
     60        (WebCore::PluginDatabase::defaultPluginDirectories):
     61        (WebCore::PluginDatabase::isPreferredPluginDirectory):
     62        * plugins/gtk/PluginPackageGtk.cpp: Added.
     63        (WebCore::PluginPackage::determineQuirks):
     64        (WebCore::PluginPackage::fetchInfo):
     65        (WebCore::PluginPackage::load):
     66        (WebCore::PluginPackage::hash):
     67        (WebCore::PluginPackage::equal):
     68        (WebCore::PluginPackage::compareFileVersion):
     69        * plugins/gtk/PluginViewGtk.cpp: Added.
     70        (WebCore::PluginView::updateWindow):
     71        (WebCore::PluginView::setFocus):
     72        (WebCore::PluginView::show):
     73        (WebCore::PluginView::hide):
     74        (WebCore::PluginView::paint):
     75        (WebCore::PluginView::handleKeyboardEvent):
     76        (WebCore::PluginView::handleMouseEvent):
     77        (WebCore::PluginView::setParent):
     78        (WebCore::PluginView::setNPWindowRect):
     79        (WebCore::PluginView::attachToWindow):
     80        (WebCore::PluginView::detachFromWindow):
     81        (WebCore::PluginView::stop):
     82        (WebCore::PluginView::userAgent):
     83        (WebCore::PluginView::handlePostReadFile):
     84        (WebCore::PluginView::getValue):
     85        (WebCore::PluginView::invalidateRect):
     86        (WebCore::PluginView::forceRedraw):
     87        (WebCore::PluginView::~PluginView):
     88        (WebCore::plug_removed_cb): Added callback to handle plug removal.
     89        (WebCore::PluginView::init):
     90        * plugins/gtk/xembed.h: Added.
     91        * plugins/npapi.cpp:
     92        (NPN_GetValue): Return error if no view present.
     93        * plugins/qt/PluginDataQt.cpp:
     94        (WebCore::PluginData::initPlugins):
     95        (WebCore::PluginData::refresh):
     96        * plugins/qt/PluginDatabaseQt.cpp: Added.
     97        (WebCore::PluginDatabase::getPluginPathsInDirectories):
     98        (WebCore::addQtWebKitPluginDirectories):
     99        (WebCore::addMozillaPluginDirectories):
     100        (WebCore::PluginDatabase::defaultPluginDirectories):
     101        (WebCore::PluginDatabase::isPreferredPluginDirectory):
     102        * plugins/qt/PluginPackageQt.cpp: Added.
     103        (WebCore::PluginPackage::determineQuirks):
     104        (WebCore::PluginPackage::fetchInfo):
     105        (WebCore::PluginPackage::load):
     106        (WebCore::PluginPackage::hash):
     107        (WebCore::PluginPackage::equal):
     108        (WebCore::PluginPackage::compareFileVersion):
     109        * plugins/qt/PluginViewQt.cpp: Added.
     110        (WebCore::PluginView::updateWindow):
     111        (WebCore::PluginView::setFocus):
     112        (WebCore::PluginView::show):
     113        (WebCore::PluginView::hide):
     114        (WebCore::PluginView::paint):
     115        (WebCore::PluginView::handleKeyboardEvent):
     116        (WebCore::PluginView::handleMouseEvent):
     117        (WebCore::PluginView::setParent):
     118        (WebCore::PluginView::setNPWindowRect):
     119        (WebCore::PluginView::attachToWindow):
     120        (WebCore::PluginView::detachFromWindow):
     121        (WebCore::PluginView::stop):
     122        (WebCore::PluginView::userAgent):
     123        (WebCore::PluginView::handlePostReadFile):
     124        (WebCore::PluginView::getValue):
     125        (WebCore::PluginView::invalidateRect):
     126        (WebCore::PluginView::invalidateRegion):
     127        (WebCore::PluginView::forceRedraw):
     128        (WebCore::PluginView::~PluginView):
     129        (WebCore::PluginView::init):
     130        * plugins/win/PluginPackageWin.cpp: Moved platform-independent code
     131        to plugins/PluginPackage.cpp
     132        * plugins/win/PluginViewWin.cpp: Moved platform-independent code to
     133        plugins/PluginView.cpp
     134        (WebCore::PluginView::stop):
     135        (WebCore::PluginView::handlePostReadFile):
     136        (WebCore::PluginView::getValue): Moved this function to each platform.
     137
    11382008-05-01  Sam Weinig  <sam@webkit.org>
    2139
  • trunk/WebCore/GNUmakefile.am

    r32712 r32766  
    925925        WebCore/plugins/PluginView.cpp \
    926926        WebCore/plugins/npapi.cpp \
     927        WebCore/plugins/gtk/PluginDataGtk.cpp \
    927928        WebCore/plugins/gtk/PluginDatabaseGtk.cpp \
     929        WebCore/plugins/gtk/PluginPackageGtk.cpp \
     930        WebCore/plugins/gtk/PluginViewGtk.cpp \
    928931        WebCore/rendering/AutoTableLayout.cpp \
    929932        WebCore/rendering/bidi.cpp \
     
    987990        WebCore/xml/XMLHttpRequestProgressEvent.cpp \
    988991        WebCore/xml/XMLSerializer.cpp
     992if TARGET_X11
     993webcore_sources += \
     994        WebCore/plugins/gtk/gtk2xtbin.c
     995endif
    989996
    990997webkitgtk_headers += \
  • trunk/WebCore/WebCore.pro

    r32728 r32766  
    123123
    124124qt-port {
     125    unix {
     126        DEFINES += XP_UNIX ENABLE_NETSCAPE_PLUGIN_API=1
     127    }
     128
    125129RESOURCES += \
    126130            $$PWD/../WebCore/page/inspector/WebKit.qrc \
     
    10511055    ../WebKit/qt/Api/qwebpluginfactory.cpp
    10521056
    1053     unix: SOURCES += platform/qt/SystemTimeQt.cpp
     1057    unix: {
     1058        SOURCES += platform/qt/SystemTimeQt.cpp \
     1059                   plugins/qt/PluginDatabaseQt.cpp \
     1060                   plugins/qt/PluginPackageQt.cpp \
     1061                   plugins/qt/PluginViewQt.cpp
     1062    }
    10541063    else: SOURCES += platform/win/SystemTimeWin.cpp
    10551064
     
    10701079
    10711080gtk-port {
     1081    INCLUDEPATH += ../WebCore/plugins/gtk
    10721082    HEADERS += \
    10731083        ../WebCore/platform/gtk/ClipboardGtk.h \
  • trunk/WebCore/bridge/npruntime_internal.h

    r31234 r32766  
    11/*
    2  * Copyright (C) 2007 Collabora, Ltd.  All rights reserved.
     2 * Copyright (C) 2007-2008 Collabora Ltd.  All rights reserved.
    33 *
    44 * This library is free software; you can redistribute it and/or
     
    3939    #undef Complex
    4040    #undef Status
     41    #undef CursorShape
     42    #undef FocusIn
     43    #undef FocusOut
     44    #undef KeyPress
     45    #undef KeyRelease
     46    #undef Unsorted
     47    #undef Bool
     48    #undef FontChange
     49    #undef GrayScale
    4150#endif
  • trunk/WebCore/page/gtk/FrameGtk.cpp

    r32405 r32766  
    33 * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
    44 * Copyright (C) 2007 Holger Hans Peter Freyther
     5 * Copyright (C) 2008 Collabora Ltd.  All rights reserved.
    56 * All rights reserved.
    67 *
     
    3132
    3233#include "NotImplemented.h"
     34#include "PluginView.h"
     35#include "kjs_proxy.h"
     36#include "runtime_root.h"
    3337#include "runtime.h"
    3438
     
    3640namespace WebCore {
    3741
    38 PassRefPtr<KJS::Bindings::Instance> Frame::createScriptInstanceForWidget(Widget*)
     42PassRefPtr<KJS::Bindings::Instance> Frame::createScriptInstanceForWidget(Widget* widget)
    3943{
    40     notImplemented();
    41     return 0;
     44    // FIXME: Ideally we'd have an isPluginView() here but we can't add that to the open source tree right now.
     45    if (widget->isFrameView())
     46        return 0;
     47
     48    return static_cast<PluginView*>(widget)->bindingInstance();
    4249}
    4350
  • trunk/WebCore/page/qt/FrameQt.cpp

    r32405 r32766  
    77 * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
    88 * Copyright (C) 2007 Trolltech ASA
     9 * Copyright (C) 2008 Collabora Ltd.  All rights reserved.
    910 *
    1011 * All rights reserved.
     
    3435#include "config.h"
    3536#include "Frame.h"
     37
     38#include "PluginView.h"
    3639
    3740#include "Element.h"
     
    100103PassRefPtr<KJS::Bindings::Instance> Frame::createScriptInstanceForWidget(WebCore::Widget* widget)
    101104{
     105    if (widget->isFrameView())
     106        return 0;
     107    if (widget->isNPAPIPlugin())
     108        return static_cast<PluginView*>(widget)->bindingInstance();
     109
    102110    QWidget* nativeWidget = widget->nativeWidget();
    103111    if (!nativeWidget)
     
    108116void Frame::clearPlatformScriptObjects()
    109117{
     118    notImplemented();
    110119}
    111120
    112121void Frame::disconnectPlatformScriptObjects()
    113122{
     123    notImplemented();
    114124}
    115125
  • trunk/WebCore/platform/FileSystem.h

    r32666 r32766  
    3434#include <gmodule.h>
    3535#endif
     36#if PLATFORM(QT)
     37#include <QFile>
     38#include <QLibrary>
     39#endif
    3640
    3741#include <time.h>
     
    6872
    6973};
     74#elif PLATFORM(QT)
     75typedef QFile* PlatformFileHandle;
     76typedef QLibrary* PlatformModule;
     77const PlatformFileHandle invalidPlatformFileHandle = 0;
     78typedef unsigned PlatformModuleVersion;
    7079#else
    7180typedef int PlatformFileHandle;
  • trunk/WebCore/platform/Widget.h

    r31899 r32766  
    177177        QWidget* nativeWidget() const;
    178178
     179        void setIsNPAPIPlugin(bool);
     180        bool isNPAPIPlugin() const;
     181
    179182        virtual void setParent(ScrollView*);
    180183        ScrollView* parent() const;
  • trunk/WebCore/platform/gtk/ScrollViewGtk.cpp

    r31877 r32766  
    470470void ScrollView::addChild(Widget* child)
    471471{
     472    child->setContainingWindow(containingWindow());
    472473    child->setParent(this);
    473     child->setContainingWindow(containingWindow());
    474474    m_data->children.add(child);
    475475
    476     if (child->gtkWidget())
     476    if (child->gtkWidget() && !GTK_IS_SOCKET(child->gtkWidget()))
    477477        gtk_container_add(GTK_CONTAINER(containingWindow()), child->gtkWidget());
    478478}
  • trunk/WebCore/platform/gtk/TemporaryLinkStubs.cpp

    r31123 r32766  
    3434#include "KURL.h"
    3535#include "NotImplemented.h"
    36 #include "PluginPackage.h"
    37 #include "PluginData.h"
    3836#include "PluginView.h"
    3937#include "SharedBuffer.h"
     
    5957/********************************************************/
    6058
    61 int PluginPackage::compare(const PluginPackage&) const { notImplemented(); return 0; }
    62 bool PluginPackage::fetchInfo() { notImplemented(); return false; }
    63 unsigned PluginPackage::hash() const { notImplemented(); return 0; }
    64 bool PluginPackage::equal(const PluginPackage&, const PluginPackage&) { notImplemented(); return false; }
    65 bool PluginPackage::load() { notImplemented(); return false; }
    66 void PluginView::setNPWindowRect(const IntRect&) { notImplemented(); }
    67 const char* PluginView::userAgent() { notImplemented(); return 0; }
    68 void PluginView::invalidateRect(NPRect*) { notImplemented(); }
    6959void PluginView::invalidateRegion(NPRegion) { notImplemented(); }
    70 void PluginView::forceRedraw() { notImplemented(); }
    71 void PluginView::setFocus() { Widget::setFocus(); }
    72 void PluginView::show() { Widget::show(); }
    73 void PluginView::hide() { Widget::hide(); }
    74 void PluginView::paint(GraphicsContext*, const IntRect&) { notImplemented(); }
    75 void PluginView::setParent(ScrollView* view) { Widget::setParent(view); }
    76 void PluginView::attachToWindow() { notImplemented(); }
    77 void PluginView::detachFromWindow() { notImplemented(); }
    78 NPError PluginView::handlePost(const char*, const char*, uint32, const char*, bool, void*, bool, bool) { notImplemented(); return NPERR_GENERIC_ERROR; }
    79 void PluginView::updateWindow() const { notImplemented(); }
    80 void PluginView::handleKeyboardEvent(KeyboardEvent*) { notImplemented(); }
    81 void PluginView::handleMouseEvent(MouseEvent*) { notImplemented(); }
    82 PluginView::~PluginView() {}
    8360
    8461Color WebCore::focusRingColor() { return 0xFF0000FF; }
     
    9471PassRefPtr<SharedBuffer> SharedBuffer::createWithContentsOfFile(const String&) { notImplemented(); return 0; }
    9572
    96 void PluginData::initPlugins() { notImplemented(); }
    97 void PluginData::refresh() { notImplemented(); }
    98 
    9973}
    10074
  • trunk/WebCore/platform/qt/FileSystemQt.cpp

    r32666 r32766  
    3939#include <QDateTime>
    4040#include <QFile>
     41#include <QTemporaryFile>
    4142#include <QFileInfo>
     43#include <QDateTime>
    4244#include <QDir>
    4345
     
    9193String directoryName(const String& path)
    9294{
    93     notImplemented();
    94     return String();
     95    return String(QFileInfo(path).baseName());
    9596}
    9697
    97 bool unloadModule(PlatformModule)
     98CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
    9899{
    99     notImplemented();
    100     return false;
     100    QFile *temp = new QTemporaryFile(QString(prefix));
     101    if( temp->open(QIODevice::ReadWrite) ) {
     102        handle = temp;
     103        return String(temp->fileName()).utf8();
     104    }
     105    handle = invalidPlatformFileHandle;
     106    return 0;
     107}
     108
     109void closeFile(PlatformFileHandle& handle)
     110{
     111    if(handle) {
     112        handle->close();
     113        delete handle;
     114    }
     115}
     116
     117int writeToFile(PlatformFileHandle handle, const char* data, int length)
     118{
     119    if(handle && handle->exists() && handle->isWritable()) {
     120        handle->write(data, length);
     121    }
     122}
     123
     124bool unloadModule(PlatformModule module)
     125{
     126    if (module->unload())
     127        delete module;
    101128}
    102129
  • trunk/WebCore/platform/qt/TemporaryLinkStubs.cpp

    r31513 r32766  
    7373using namespace WebCore;
    7474
    75 void PluginDatabase::getPluginPathsInDirectories(HashSet<String>&) const { notImplemented(); }
    76 Vector<String> PluginDatabase::defaultPluginDirectories() { notImplemented(); return Vector<String>(); }
    77 bool PluginDatabase::isPreferredPluginDirectory(const String&) { notImplemented(); return false; }
    78 int PluginPackage::compare(const PluginPackage&) const { notImplemented(); return 0; }
    79 bool PluginPackage::fetchInfo() { notImplemented(); return false; }
    80 unsigned PluginPackage::hash() const { notImplemented(); return 0; }
    81 bool PluginPackage::equal(const PluginPackage&, const PluginPackage&) { notImplemented(); return false; }
    82 bool PluginPackage::load() { notImplemented(); return false; }
    83 void PluginView::setNPWindowRect(const IntRect&) { notImplemented(); }
    84 const char* PluginView::userAgent() { notImplemented(); return 0; }
    85 void PluginView::invalidateRect(NPRect*) { notImplemented(); }
    86 void PluginView::invalidateRegion(NPRegion) { notImplemented(); }
    87 void PluginView::forceRedraw() { notImplemented(); }
    88 void PluginView::setFocus() { Widget::setFocus(); }
    89 void PluginView::show() { Widget::show(); }
    90 void PluginView::hide() { Widget::hide(); }
    91 void PluginView::paint(GraphicsContext*, const IntRect&) { notImplemented(); }
    92 void PluginView::setParent(ScrollView* view) { Widget::setParent(view); }
    93 void PluginView::attachToWindow() { notImplemented(); }
    94 void PluginView::detachFromWindow() { notImplemented(); }
    95 NPError PluginView::handlePost(const char*, const char*, uint32, const char*, bool, void*, bool, bool) { notImplemented(); return NPERR_GENERIC_ERROR; }
    96 void PluginView::updateWindow() const { notImplemented(); }
    97 void PluginView::handleKeyboardEvent(KeyboardEvent*) { notImplemented(); }
    98 void PluginView::handleMouseEvent(MouseEvent*) { notImplemented(); }
    99 PluginView::~PluginView() {}
    100 
    10175namespace WebCore {
    10276
    10377Vector<String> supportedKeySizes() { notImplemented(); return Vector<String>(); }
    10478String signedPublicKeyAndChallengeString(unsigned keySizeIndex, const String &challengeString, const KURL &url) { return String(); }
    105 
    106 CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle) { notImplemented(); handle = invalidPlatformFileHandle; return 0; }
    107 void closeFile(PlatformFileHandle&) { notImplemented(); };
    108 int writeToFile(PlatformFileHandle, const char* data, int length) { return -1; };
    10979
    11080#if !defined(Q_OS_WIN)
  • trunk/WebCore/platform/qt/WidgetQt.cpp

    r32674 r32766  
    6363        , suppressInvalidation(false)
    6464        , m_widget(0)
     65        , isNPAPIPlugin(0)
    6566        , m_parentScrollView(0) { }
    6667    ~WidgetPrivate() {}
     
    7071    bool enabled;
    7172    bool suppressInvalidation;
     73    bool isNPAPIPlugin;
    7274    IntRect m_geometry;
    7375    QWidget *m_widget; //for plugins
     
    141143{
    142144    data->m_widget = widget;
     145}
     146
     147bool Widget::isNPAPIPlugin() const
     148{
     149    return data->isNPAPIPlugin;
     150}
     151
     152void Widget::setIsNPAPIPlugin(bool is)
     153{
     154    data->isNPAPIPlugin = is;
    143155}
    144156
  • trunk/WebCore/plugins/PluginPackage.cpp

    r31461 r32766  
    11/*
    22 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
    3  * Copyright (C) 2008 Collabora, Ltd.  All rights reserved.
     3 * Copyright (C) 2008 Collabora Ltd.  All rights reserved.
    44 *
    55 * Redistribution and use in source and binary forms, with or without
     
    2828#include "PluginPackage.h"
    2929
     30#include "CString.h"
    3031#include "MIMETypeRegistry.h"
     32#include "PluginDatabase.h"
    3133#include "PluginDebug.h"
    3234#include "Timer.h"
    3335#include "npruntime_impl.h"
     36#include <string.h>
    3437#include <wtf/OwnArrayPtr.h>
    3538
     
    3841PluginPackage::~PluginPackage()
    3942{
     43    // This destructor gets called during refresh() if PluginDatabase's
     44    // PluginSet hash is already populated, as it removes items from
     45    // the hash table. Calling the destructor on a loaded plug-in of
     46    // course would cause a crash, so we check to call unload before we
     47    // ASSERT.
     48    // FIXME: There is probably a better way to fix this.
     49    if (m_loadCount == 0)
     50        unloadWithoutShutdown();
     51    else
     52        unload();
     53
    4054    ASSERT(!m_isLoaded);
    4155}
     
    5771    unloadModule(m_module);
    5872    m_module = 0;
     73}
     74
     75
     76int PluginPackage::compare(const PluginPackage& compareTo) const
     77{
     78    // Sort plug-ins that allow multiple instances first.
     79    bool AallowsMultipleInstances = !quirks().contains(PluginQuirkDontAllowMultipleInstances);
     80    bool BallowsMultipleInstances = !compareTo.quirks().contains(PluginQuirkDontAllowMultipleInstances);
     81    if (AallowsMultipleInstances != BallowsMultipleInstances)
     82        return AallowsMultipleInstances ? -1 : 1;
     83
     84    // Sort plug-ins in a preferred path first.
     85    bool AisInPreferredDirectory = PluginDatabase::isPreferredPluginDirectory(parentDirectory());
     86    bool BisInPreferredDirectory = PluginDatabase::isPreferredPluginDirectory(compareTo.parentDirectory());
     87    if (AisInPreferredDirectory != BisInPreferredDirectory)
     88        return AisInPreferredDirectory ? -1 : 1;
     89
     90    int diff = strcmp(name().utf8().data(), compareTo.name().utf8().data());
     91    if (diff)
     92        return diff;
     93
     94    if (diff = compareFileVersion(compareTo.version()))
     95        return diff;
     96
     97    return strcmp(parentDirectory().utf8().data(), compareTo.parentDirectory().utf8().data());
    5998}
    6099
  • trunk/WebCore/plugins/PluginPackage.h

    r32614 r32766  
    104104
    105105    struct PluginPackageHash {
    106         static unsigned hash(const int key) { return reinterpret_cast<PluginPackage*>(key)->hash(); }
     106        static unsigned hash(const uintptr_t key) { return reinterpret_cast<PluginPackage*>(key)->hash(); }
    107107        static unsigned hash(const RefPtr<PluginPackage>& key) { return key->hash(); }
    108108
    109         static bool equal(const int a, const int b) { return equal(reinterpret_cast<PluginPackage*>(a), reinterpret_cast<PluginPackage*>(b)); }
     109        static bool equal(const uintptr_t a, const uintptr_t b) { return equal(reinterpret_cast<PluginPackage*>(a), reinterpret_cast<PluginPackage*>(b)); }
    110110        static bool equal(const RefPtr<PluginPackage>& a, const RefPtr<PluginPackage>& b) { return PluginPackage::equal(*a.get(), *b.get()); }
    111111        static const bool safeToCompareToEmptyOrDeleted = false;
  • trunk/WebCore/plugins/PluginView.cpp

    r31210 r32766  
    11/*
    22 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
    3  * Copyright (C) 2008 Collabora, Ltd. All rights reserved.
     3 * Copyright (C) 2008 Collabora Ltd. All rights reserved.
    44 *
    55 * Redistribution and use in source and binary forms, with or without
     
    121121
    122122    updateWindow();
     123
     124#if PLATFORM(WIN)
    123125    setNPWindowRect(rect);
     126#endif
    124127}
    125128
     
    392395    if (Page* page = m_parentFrame->page())
    393396        page->chrome()->setStatusbarText(m_parentFrame, String(message));
    394 }
    395 
    396 NPError PluginView::getValue(NPNVariable variable, void* value)
    397 {
    398     if (m_isJavaScriptPaused)
    399         return NPERR_GENERIC_ERROR;
    400 
    401     switch (variable) {
    402 #if ENABLE(NETSCAPE_PLUGIN_API)
    403         case NPNVWindowNPObject: {
    404             NPObject* windowScriptObject = m_parentFrame->windowScriptNPObject();
    405 
    406             // Return value is expected to be retained, as described here: <http://www.mozilla.org/projects/plugin/npruntime.html>
    407             if (windowScriptObject)
    408                 _NPN_RetainObject(windowScriptObject);
    409 
    410             void** v = (void**)value;
    411             *v = windowScriptObject;
    412            
    413             return NPERR_NO_ERROR;
    414         }
    415 
    416         case NPNVPluginElementNPObject: {
    417             NPObject* pluginScriptObject = 0;
    418 
    419             if (m_element->hasTagName(appletTag) || m_element->hasTagName(embedTag) || m_element->hasTagName(objectTag))
    420                 pluginScriptObject = static_cast<HTMLPlugInElement*>(m_element)->getNPObject();
    421 
    422             // Return value is expected to be retained, as described here: <http://www.mozilla.org/projects/plugin/npruntime.html>
    423             if (pluginScriptObject)
    424                 _NPN_RetainObject(pluginScriptObject);
    425 
    426             void** v = (void**)value;
    427             *v = pluginScriptObject;
    428 
    429             return NPERR_NO_ERROR;
    430         }
    431 #endif
    432 
    433         case NPNVnetscapeWindow: {
    434             PlatformWidget* w = reinterpret_cast<PlatformWidget*>(value);
    435 
    436             *w = containingWindow();
    437 
    438             return NPERR_NO_ERROR;
    439         }
    440         default:
    441             return NPERR_GENERIC_ERROR;
    442     }
    443397}
    444398
     
    598552    setParameters(paramNames, paramValues);
    599553
     554#ifdef XP_UNIX
     555    m_npWindow.ws_info = 0;
     556#endif
     557
    600558    m_mode = m_loadManually ? NP_FULL : NP_EMBED;
    601559
     
    672630}
    673631
     632void PluginView::freeStringArray(char** stringArray, int length)
     633{
     634    if (!stringArray)
     635        return;
     636
     637    for (int i = 0; i < length; i++)
     638        fastFree(stringArray[i]);
     639
     640    fastFree(stringArray);
     641}
     642
     643static inline bool startsWithBlankLine(const Vector<char>& buffer)
     644{
     645    return buffer.size() > 0 && buffer[0] == '\n';
     646}
     647
     648static inline int locationAfterFirstBlankLine(const Vector<char>& buffer)
     649{
     650    const char* bytes = buffer.data();
     651    unsigned length = buffer.size();
     652
     653    for (unsigned i = 0; i < length - 4; i++) {
     654        // Support for Acrobat. It sends "\n\n".
     655        if (bytes[i] == '\n' && bytes[i + 1] == '\n')
     656            return i + 2;
     657       
     658        // Returns the position after 2 CRLF's or 1 CRLF if it is the first line.
     659        if (bytes[i] == '\r' && bytes[i + 1] == '\n') {
     660            i += 2;
     661            if (i == 2)
     662                return i;
     663            else if (bytes[i] == '\n')
     664                // Support for Director. It sends "\r\n\n" (3880387).
     665                return i + 1;
     666            else if (bytes[i] == '\r' && bytes[i + 1] == '\n')
     667                // Support for Flash. It sends "\r\n\r\n" (3758113).
     668                return i + 2;
     669        }
     670    }
     671
     672    return -1;
     673}
     674
     675static inline const char* findEOL(const char* bytes, unsigned length)
     676{
     677    // According to the HTTP specification EOL is defined as
     678    // a CRLF pair. Unfortunately, some servers will use LF
     679    // instead. Worse yet, some servers will use a combination
     680    // of both (e.g. <header>CRLFLF<body>), so findEOL needs
     681    // to be more forgiving. It will now accept CRLF, LF or
     682    // CR.
     683    //
     684    // It returns NULL if EOLF is not found or it will return
     685    // a pointer to the first terminating character.
     686    for (unsigned i = 0; i < length; i++) {
     687        if (bytes[i] == '\n')
     688            return bytes + i;
     689        if (bytes[i] == '\r') {
     690            // Check to see if spanning buffer bounds
     691            // (CRLF is across reads). If so, wait for
     692            // next read.
     693            if (i + 1 == length)
     694                break;
     695
     696            return bytes + i;
     697        }
     698    }
     699
     700    return 0;
     701}
     702
     703static inline String capitalizeRFC822HeaderFieldName(const String& name)
     704{
     705    bool capitalizeCharacter = true;
     706    String result;
     707
     708    for (unsigned i = 0; i < name.length(); i++) {
     709        UChar c;
     710
     711        if (capitalizeCharacter && name[i] >= 'a' && name[i] <= 'z')
     712            c = toASCIIUpper(name[i]);
     713        else if (!capitalizeCharacter && name[i] >= 'A' && name[i] <= 'Z')
     714            c = toASCIILower(name[i]);
     715        else
     716            c = name[i];
     717
     718        if (name[i] == '-')
     719            capitalizeCharacter = true;
     720        else
     721            capitalizeCharacter = false;
     722
     723        result.append(c);
     724    }
     725
     726    return result;
     727}
     728
     729static inline HTTPHeaderMap parseRFC822HeaderFields(const Vector<char>& buffer, unsigned length)
     730{
     731    const char* bytes = buffer.data();
     732    const char* eol;
     733    String lastKey;
     734    HTTPHeaderMap headerFields;
     735
     736    // Loop ove rlines until we're past the header, or we can't find any more end-of-lines
     737    while ((eol = findEOL(bytes, length))) {
     738        const char* line = bytes;
     739        int lineLength = eol - bytes;
     740       
     741        // Move bytes to the character after the terminator as returned by findEOL.
     742        bytes = eol + 1;
     743        if ((*eol == '\r') && (*bytes == '\n'))
     744            bytes++; // Safe since findEOL won't return a spanning CRLF.
     745
     746        length -= (bytes - line);
     747        if (lineLength == 0)
     748            // Blank line; we're at the end of the header
     749            break;
     750        else if (*line == ' ' || *line == '\t') {
     751            // Continuation of the previous header
     752            if (lastKey.isNull()) {
     753                // malformed header; ignore it and continue
     754                continue;
     755            } else {
     756                // Merge the continuation of the previous header
     757                String currentValue = headerFields.get(lastKey);
     758                String newValue(line, lineLength);
     759
     760                headerFields.set(lastKey, currentValue + newValue);
     761            }
     762        } else {
     763            // Brand new header
     764            const char* colon;
     765            for (colon = line; *colon != ':' && colon != eol; colon++) {
     766                // empty loop
     767            }
     768            if (colon == eol)
     769                // malformed header; ignore it and continue
     770                continue;
     771            else {
     772                lastKey = capitalizeRFC822HeaderFieldName(String(line, colon - line));
     773                String value;
     774
     775                for (colon++; colon != eol; colon++) {
     776                    if (*colon != ' ' && *colon != '\t')
     777                        break;
     778                }
     779                if (colon == eol)
     780                    value = "";
     781                else
     782                    value = String(colon, eol - colon);
     783
     784                String oldValue = headerFields.get(lastKey);
     785                if (!oldValue.isNull()) {
     786                    String tmp = oldValue;
     787                    tmp += ", ";
     788                    tmp += value;
     789                    value = tmp;
     790                }
     791
     792                headerFields.set(lastKey, value);
     793            }
     794        }
     795    }
     796
     797    return headerFields;
     798}
     799
     800NPError PluginView::handlePost(const char* url, const char* target, uint32 len, const char* buf, bool file, void* notifyData, bool sendNotification, bool allowHeaders)
     801{
     802    if (!url || !len || !buf)
     803        return NPERR_INVALID_PARAM;
     804
     805    FrameLoadRequest frameLoadRequest;
     806
     807    HTTPHeaderMap headerFields;
     808    Vector<char> buffer;
     809   
     810    if (file) {
     811        NPError readResult = handlePostReadFile(buffer, len, buf);
     812        if(readResult != NPERR_NO_ERROR)
     813            return readResult;
     814    } else {
     815        buffer.resize(len);
     816        memcpy(buffer.data(), buf, len);
     817    }
     818
     819    const char* postData = buffer.data();
     820    int postDataLength = buffer.size();
     821
     822    if (allowHeaders) {
     823        if (startsWithBlankLine(buffer)) {
     824            postData++;
     825            postDataLength--;
     826        } else {
     827            int location = locationAfterFirstBlankLine(buffer);
     828            if (location != -1) {
     829                // If the blank line is somewhere in the middle of the buffer, everything before is the header
     830                headerFields = parseRFC822HeaderFields(buffer, location);
     831                unsigned dataLength = buffer.size() - location;
     832
     833                // Sometimes plugins like to set Content-Length themselves when they post,
     834                // but WebFoundation does not like that. So we will remove the header
     835                // and instead truncate the data to the requested length.
     836                String contentLength = headerFields.get("Content-Length");
     837
     838                if (!contentLength.isNull())
     839                    dataLength = min(contentLength.toInt(), (int)dataLength);
     840                headerFields.remove("Content-Length");
     841
     842                postData += location;
     843                postDataLength = dataLength;
     844            }
     845        }
     846    }
     847
     848    frameLoadRequest.resourceRequest().setHTTPMethod("POST");
     849    frameLoadRequest.resourceRequest().setURL(makeURL(m_baseURL, url));
     850    frameLoadRequest.resourceRequest().addHTTPHeaderFields(headerFields);
     851    frameLoadRequest.resourceRequest().setHTTPBody(FormData::create(postData, postDataLength));
     852    frameLoadRequest.setFrameName(target);
     853
     854    return load(frameLoadRequest, sendNotification, notifyData);
     855}
     856
    674857} // namespace WebCore
  • trunk/WebCore/plugins/PluginView.h

    r31210 r32766  
    11/*
    22 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
    3  * Copyright (C) 2008 Collabora, Ltd. All rights reserved.
     3 * Copyright (C) 2008 Collabora Ltd. All rights reserved.
    44 *
    55 * Redistribution and use in source and binary forms, with or without
     
    172172        NPError load(const FrameLoadRequest&, bool sendNotification, void* notifyData);
    173173        NPError handlePost(const char* url, const char* target, uint32 len, const char* buf, bool file, void* notifyData, bool sendNotification, bool allowHeaders);
     174        NPError handlePostReadFile(Vector<char>& buffer, uint32 len, const char* buf);
     175        static void freeStringArray(char** stringArray, int length);
    174176        void setCallingPlugin(bool) const;
    175177        RefPtr<PluginPackage> m_plugin;
     
    222224        bool m_haveInitialized;
    223225
     226#if PLATFORM(GTK) || defined(Q_WS_X11)
     227        bool m_needsXEmbed;
     228#endif
     229
    224230#if PLATFORM(WIN)
    225231        OwnPtr<PluginMessageThrottlerWin> m_messageThrottler;
  • trunk/WebCore/plugins/gtk/PluginDatabaseGtk.cpp

    r31747 r32766  
    3030#include "CString.h"
    3131#include "PluginPackage.h"
     32#include <gdkconfig.h>
    3233
    3334namespace WebCore {
     
    6061    Vector<String> directories;
    6162    gchar* directory;
     63
     64    directory = 0;
    6265
    6366#if defined(GDK_WINDOWING_X11)
     
    9699bool PluginDatabase::isPreferredPluginDirectory(const String& directory)
    97100{
    98     return false;
     101    gchar* homePath;
     102    bool retval = false;
     103
     104    homePath = 0;
     105
     106#if defined(GDK_WINDOWING_X11)
     107    homePath = g_build_filename(g_get_home_dir(), ".mozilla", "plugins", 0);
     108#elif defined(GDK_WINDOWING_WIN32)
     109    homePath = g_build_filename(g_get_home_dir(), "Application Data", "Mozilla", "plugins", 0);
     110#endif
     111
     112    if (homePath)
     113    retval = (strcmp(homePath, (directory.utf8()).data()) == 0);
     114
     115    return retval;
    99116}
    100117
  • trunk/WebCore/plugins/npapi.cpp

    r31234 r32766  
    138138NPError NPN_GetValue(NPP instance, NPNVariable variable, void* value)
    139139{
     140    // FIXME: Acrobat reader plugin calls NPN_GetValue before a PluginView
     141    // has been created
     142    if (!instance)
     143        return NPERR_GENERIC_ERROR;
     144
    140145    return pluginViewForInstance(instance)->getValue(variable, value);
    141146}
  • trunk/WebCore/plugins/qt/PluginDataQt.cpp

    r32479 r32766  
    11/*
    22    Copyright (C) 2008 Trolltech ASA
     3    Copyright (C) 2008 Collabora Ltd. All rights reserved.
    34
    45    This library is free software; you can redistribute it and/or
     
    2122#include "PluginData.h"
    2223
     24#include "PluginDatabase.h"
     25#include "PluginPackage.h"
     26
     27#if QT_VERSION >= 0x040400
    2328#include "ChromeClientQt.h"
    2429#include "Page.h"
    2530#include <qwebpage.h>
    2631#include <qwebpluginfactory.h>
     32#endif
    2733
    2834namespace WebCore {
     
    3339    QWebPage* webPage = static_cast<ChromeClientQt*>(m_page->chrome()->client())->m_webPage;
    3440    QWebPluginFactory* factory = webPage->pluginFactory();
    35     if (!factory)
    36         return;
     41    if (factory) {
    3742
    38     QList<QWebPluginFactory::Plugin> plugins = factory->plugins();
    39     for (int i = 0; i < plugins.count(); ++i) {
    40         const QWebPluginFactory::Plugin& plugin = plugins.at(i);
     43        QList<QWebPluginFactory::Plugin> qplugins = factory->plugins();
     44        for (int i = 0; i < qplugins.count(); ++i) {
     45            const QWebPluginFactory::Plugin& qplugin = qplugins.at(i);
    4146
     47            PluginInfo* info = new PluginInfo;
     48            info->name = qplugin.name;
     49            info->desc = qplugin.description;
     50
     51            for (int j = 0; j < qplugin.mimeTypes.count(); ++j) {
     52                const QWebPluginFactory::MimeType& mimeType = qplugin.mimeTypes.at(j);
     53
     54                MimeClassInfo* mimeInfo = new MimeClassInfo;
     55                mimeInfo->type = mimeType.name;
     56                mimeInfo->desc = mimeType.description;
     57                mimeInfo->suffixes = mimeType.fileExtensions.join("; ");
     58
     59                info->mimes.append(mimeInfo);
     60            }
     61
     62            m_plugins.append(info);
     63        }
     64    }
     65#endif
     66
     67    PluginDatabase *db = PluginDatabase::installedPlugins();
     68    const Vector<PluginPackage*> &plugins = db->plugins();
     69
     70    for (unsigned int i = 0; i < plugins.size(); ++i) {
    4271        PluginInfo* info = new PluginInfo;
    43         info->name = plugin.name;
    44         info->desc = plugin.description;
     72        PluginPackage* package = plugins[i];
    4573
    46         for (int j = 0; j < plugin.mimeTypes.count(); ++j) {
    47             const QWebPluginFactory::MimeType& mimeType = plugin.mimeTypes.at(j);
     74        info->name = package->name();
     75        info->file = package->fileName();
     76        info->desc = package->description();
    4877
    49             MimeClassInfo* mimeInfo = new MimeClassInfo;
    50             mimeInfo->type = mimeType.name;
    51             mimeInfo->desc = mimeType.description;
    52             mimeInfo->suffixes = mimeType.fileExtensions.join(QLatin1String("; "));
     78        const MIMEToDescriptionsMap& mimeToDescriptions = package->mimeToDescriptions();
     79        MIMEToDescriptionsMap::const_iterator end = mimeToDescriptions.end();
     80        for (MIMEToDescriptionsMap::const_iterator it = mimeToDescriptions.begin(); it != end; ++it) {
     81            MimeClassInfo* mime = new MimeClassInfo;
     82            info->mimes.append(mime);
    5383
    54             info->mimes.append(mimeInfo);
     84            mime->type = it->first;
     85            mime->desc = it->second;
     86            mime->plugin = info;
     87
     88            Vector<String> extensions = package->mimeToExtensions().get(mime->type);
     89
     90            for (unsigned i = 0; i < extensions.size(); i++) {
     91                if (i > 0)
     92                    mime->suffixes += ",";
     93
     94                mime->suffixes += extensions[i];
     95            }
    5596        }
    5697
    5798        m_plugins.append(info);
    5899    }
    59 #endif
    60100}
    61101
    62102void PluginData::refresh()
    63103{
    64     // nothing to do
     104    PluginDatabase *db = PluginDatabase::installedPlugins();
     105    db->refresh();
    65106}
    66107
  • trunk/WebCore/plugins/win/PluginPackageWin.cpp

    r31462 r32766  
    6767}
    6868
    69 int PluginPackage::compare(const PluginPackage& compareTo) const
    70 {
    71     // Sort plug-ins that allow multiple instances first.
    72     bool AallowsMultipleInstances = !quirks().contains(PluginQuirkDontAllowMultipleInstances);
    73     bool BallowsMultipleInstances = !compareTo.quirks().contains(PluginQuirkDontAllowMultipleInstances);
    74     if (AallowsMultipleInstances != BallowsMultipleInstances)
    75         return AallowsMultipleInstances ? -1 : 1;
    76 
    77     // Sort plug-ins in a preferred path first.
    78     bool AisInPreferredPath = PluginDatabase::isPreferredPluginDirectory(parentDirectory());
    79     bool BisInPreferredPath = PluginDatabase::isPreferredPluginDirectory(compareTo.parentDirectory());
    80     if (AisInPreferredPath != BisInPreferredPath)
    81         return AisInPreferredPath ? -1 : 1;
    82 
    83     int diff = strcmp(name().utf8().data(), compareTo.name().utf8().data());
    84     if (diff)
    85         return diff;
    86 
    87     if (diff = compareFileVersion(compareTo.version()))
    88         return diff;
    89 
    90     return strcmp(parentDirectory().utf8().data(), compareTo.parentDirectory().utf8().data());
    91 }
    92 
    9369bool PluginPackage::isPluginBlacklisted()
    9470{
  • trunk/WebCore/plugins/win/PluginViewWin.cpp

    r31131 r32766  
    11/*
    22 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
    3  * Copyright (C) 2008 Collabora, Ltd. All rights reserved.
     3 * Copyright (C) 2008 Collabora Ltd. All rights reserved.
    44 *
    55 * Redistribution and use in source and binary forms, with or without
     
    179179    if (m_plugin->pluginFuncs()->version < NPVERS_HAS_POPUPS_ENABLED_STATE &&
    180180        isWindowsMessageUserGesture(message) && !m_popPopupsStateTimer.isActive()) {
    181        
     181
    182182        pushPopupsEnabledState(true);
    183183
     
    563563    }
    564564
    565     KJS::JSLock::DropAllLocks;
     565    KJS::JSLock::DropAllLocks dropAllLocks;
    566566
    567567    // Clear the window
     
    589589}
    590590
    591 static void freeStringArray(char** stringArray, int length)
    592 {
    593     if (!stringArray)
    594         return;
    595 
    596     for (int i = 0; i < length; i++)
    597         fastFree(stringArray[i]);
    598 
    599     fastFree(stringArray);
    600 }
    601 
    602 static KURL makeURL(const KURL& baseURL, const char* relativeURLString)
    603 {
    604     String urlString = relativeURLString;
    605 
    606     // Strip return characters.
    607     urlString.replace('\n', "");
    608     urlString.replace('\r', "");
    609 
    610     return KURL(baseURL, urlString);
    611 }
    612 
    613 static inline bool startsWithBlankLine(const Vector<char>& buffer)
    614 {
    615     return buffer.size() > 0 && buffer[0] == '\n';
    616 }
    617 
    618591const char* PluginView::userAgent()
    619592{
     
    626599}
    627600
    628 static inline int locationAfterFirstBlankLine(const Vector<char>& buffer)
    629 {
    630     const char* bytes = buffer.data();
    631     unsigned length = buffer.size();
    632 
    633     for (unsigned i = 0; i < length - 4; i++) {
    634         // Support for Acrobat. It sends "\n\n".
    635         if (bytes[i] == '\n' && bytes[i + 1] == '\n')
    636             return i + 2;
    637        
    638         // Returns the position after 2 CRLF's or 1 CRLF if it is the first line.
    639         if (bytes[i] == '\r' && bytes[i + 1] == '\n') {
    640             i += 2;
    641             if (i == 2)
    642                 return i;
    643             else if (bytes[i] == '\n')
    644                 // Support for Director. It sends "\r\n\n" (3880387).
    645                 return i + 1;
    646             else if (bytes[i] == '\r' && bytes[i + 1] == '\n')
    647                 // Support for Flash. It sends "\r\n\r\n" (3758113).
    648                 return i + 2;
     601NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32 len, const char* buf)
     602{
     603    String filename(buf, len);
     604
     605    if (filename.startsWith("file:///"))
     606        filename = filename.substring(8);
     607
     608    // Get file info
     609    WIN32_FILE_ATTRIBUTE_DATA attrs;
     610    if (GetFileAttributesExW(filename.charactersWithNullTermination(), GetFileExInfoStandard, &attrs) == 0)
     611        return NPERR_FILE_NOT_FOUND;
     612
     613    if (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
     614        return NPERR_FILE_NOT_FOUND;
     615
     616    HANDLE fileHandle = CreateFileW(filename.charactersWithNullTermination(), FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
     617   
     618    if (fileHandle == INVALID_HANDLE_VALUE)
     619        return NPERR_FILE_NOT_FOUND;
     620
     621    buffer.resize(attrs.nFileSizeLow);
     622
     623    DWORD bytesRead;
     624    int retval = ReadFile(fileHandle, buffer.data(), attrs.nFileSizeLow, &bytesRead, 0);
     625
     626    CloseHandle(fileHandle);
     627
     628    if (retval == 0 || bytesRead != attrs.nFileSizeLow)
     629        return NPERR_FILE_NOT_FOUND;
     630}
     631
     632NPError PluginView::getValue(NPNVariable variable, void* value)
     633{
     634    switch (variable) {
     635#if ENABLE(NETSCAPE_PLUGIN_API)
     636        case NPNVWindowNPObject: {
     637        if (m_isJavaScriptPaused)
     638        return NPERR_GENERIC_ERROR;
     639
     640            NPObject* windowScriptObject = m_parentFrame->windowScriptNPObject();
     641
     642            // Return value is expected to be retained, as described here: <http://www.mozilla.org/projects/plugin/npruntime.html>
     643            if (windowScriptObject)
     644                _NPN_RetainObject(windowScriptObject);
     645
     646            void** v = (void**)value;
     647            *v = windowScriptObject;
     648
     649            return NPERR_NO_ERROR;
    649650        }
    650     }
    651 
    652     return -1;
    653 }
    654 
    655 static inline const char* findEOL(const char* bytes, unsigned length)
    656 {
    657     // According to the HTTP specification EOL is defined as
    658     // a CRLF pair. Unfortunately, some servers will use LF
    659     // instead. Worse yet, some servers will use a combination
    660     // of both (e.g. <header>CRLFLF<body>), so findEOL needs
    661     // to be more forgiving. It will now accept CRLF, LF or
    662     // CR.
    663     //
    664     // It returns NULL if EOLF is not found or it will return
    665     // a pointer to the first terminating character.
    666     for (unsigned i = 0; i < length; i++) {
    667         if (bytes[i] == '\n')
    668             return bytes + i;
    669         if (bytes[i] == '\r') {
    670             // Check to see if spanning buffer bounds
    671             // (CRLF is across reads). If so, wait for
    672             // next read.
    673             if (i + 1 == length)
    674                 break;
    675 
    676             return bytes + i;
     651
     652        case NPNVPluginElementNPObject: {
     653        if (m_isJavaScriptPaused)
     654        return NPERR_GENERIC_ERROR;
     655
     656            NPObject* pluginScriptObject = 0;
     657
     658            if (m_element->hasTagName(appletTag) || m_element->hasTagName(embedTag) || m_element->hasTagName(objectTag))
     659                pluginScriptObject = static_cast<HTMLPlugInElement*>(m_element)->getNPObject();
     660
     661            // Return value is expected to be retained, as described here: <http://www.mozilla.org/projects/plugin/npruntime.html>
     662            if (pluginScriptObject)
     663                _NPN_RetainObject(pluginScriptObject);
     664
     665            void** v = (void**)value;
     666            *v = pluginScriptObject;
     667
     668            return NPERR_NO_ERROR;
    677669        }
    678     }
    679 
    680     return 0;
    681 }
    682 
    683 static inline String capitalizeRFC822HeaderFieldName(const String& name)
    684 {
    685     bool capitalizeCharacter = true;
    686     String result;
    687 
    688     for (unsigned i = 0; i < name.length(); i++) {
    689         UChar c;
    690 
    691         if (capitalizeCharacter && name[i] >= 'a' && name[i] <= 'z')
    692             c = toASCIIUpper(name[i]);
    693         else if (!capitalizeCharacter && name[i] >= 'A' && name[i] <= 'Z')
    694             c = toASCIILower(name[i]);
    695         else
    696             c = name[i];
    697 
    698         if (name[i] == '-')
    699             capitalizeCharacter = true;
    700         else
    701             capitalizeCharacter = false;
    702 
    703         result.append(c);
    704     }
    705 
    706     return result;
    707 }
    708 
    709 static inline HTTPHeaderMap parseRFC822HeaderFields(const Vector<char>& buffer, unsigned length)
    710 {
    711     const char* bytes = buffer.data();
    712     const char* eol;
    713     String lastKey;
    714     HTTPHeaderMap headerFields;
    715 
    716     // Loop ove rlines until we're past the header, or we can't find any more end-of-lines
    717     while ((eol = findEOL(bytes, length))) {
    718         const char* line = bytes;
    719         int lineLength = eol - bytes;
    720        
    721         // Move bytes to the character after the terminator as returned by findEOL.
    722         bytes = eol + 1;
    723         if ((*eol == '\r') && (*bytes == '\n'))
    724             bytes++; // Safe since findEOL won't return a spanning CRLF.
    725 
    726         length -= (bytes - line);
    727         if (lineLength == 0)
    728             // Blank line; we're at the end of the header
    729             break;
    730         else if (*line == ' ' || *line == '\t') {
    731             // Continuation of the previous header
    732             if (lastKey.isNull()) {
    733                 // malformed header; ignore it and continue
    734                 continue;
    735             } else {
    736                 // Merge the continuation of the previous header
    737                 String currentValue = headerFields.get(lastKey);
    738                 String newValue(line, lineLength);
    739 
    740                 headerFields.set(lastKey, currentValue + newValue);
    741             }
    742         } else {
    743             // Brand new header
    744             const char* colon;
    745             for (colon = line; *colon != ':' && colon != eol; colon++) {
    746                 // empty loop
    747             }
    748             if (colon == eol)
    749                 // malformed header; ignore it and continue
    750                 continue;
    751             else {
    752                 lastKey = capitalizeRFC822HeaderFieldName(String(line, colon - line));
    753                 String value;
    754 
    755                 for (colon++; colon != eol; colon++) {
    756                     if (*colon != ' ' && *colon != '\t')
    757                         break;
    758                 }
    759                 if (colon == eol)
    760                     value = "";
    761                 else
    762                     value = String(colon, eol - colon);
    763 
    764                 String oldValue = headerFields.get(lastKey);
    765                 if (!oldValue.isNull()) {
    766                     String tmp = oldValue;
    767                     tmp += ", ";
    768                     tmp += value;
    769                     value = tmp;
    770                 }
    771 
    772                 headerFields.set(lastKey, value);
    773             }
     670#endif
     671
     672        case NPNVnetscapeWindow: {
     673            PlatformWidget* w = reinterpret_cast<PlatformWidget*>(value);
     674
     675            *w = containingWindow();
     676
     677            return NPERR_NO_ERROR;
    774678        }
    775     }
    776 
    777     return headerFields;
    778 }
    779 
    780 NPError PluginView::handlePost(const char* url, const char* target, uint32 len, const char* buf, bool file, void* notifyData, bool sendNotification, bool allowHeaders)
    781 {
    782     if (!url || !len || !buf)
    783         return NPERR_INVALID_PARAM;
    784 
    785     FrameLoadRequest frameLoadRequest;
    786 
    787     HTTPHeaderMap headerFields;
    788     Vector<char> buffer;
    789    
    790     if (file) {
    791         String filename(buf, len);
    792 
    793         if (filename.startsWith("file:///"))
    794             filename = filename.substring(8);
    795 
    796         // Get file info
    797         WIN32_FILE_ATTRIBUTE_DATA attrs;
    798         if (GetFileAttributesExW(filename.charactersWithNullTermination(), GetFileExInfoStandard, &attrs) == 0)
    799             return NPERR_FILE_NOT_FOUND;
    800 
    801         if (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
    802             return NPERR_FILE_NOT_FOUND;
    803 
    804         HANDLE fileHandle = CreateFileW(filename.charactersWithNullTermination(), FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
    805        
    806         if (fileHandle == INVALID_HANDLE_VALUE)
    807             return NPERR_FILE_NOT_FOUND;
    808 
    809         buffer.resize(attrs.nFileSizeLow);
    810 
    811         DWORD bytesRead;
    812         int retval = ReadFile(fileHandle, buffer.data(), attrs.nFileSizeLow, &bytesRead, 0);
    813 
    814         CloseHandle(fileHandle);
    815 
    816         if (retval == 0 || bytesRead != attrs.nFileSizeLow)
    817             return NPERR_FILE_NOT_FOUND;
    818     } else {
    819         buffer.resize(len);
    820         memcpy(buffer.data(), buf, len);
    821     }
    822 
    823     const char* postData = buffer.data();
    824     int postDataLength = buffer.size();
    825    
    826     if (allowHeaders) {
    827         if (startsWithBlankLine(buffer)) {
    828             postData++;
    829             postDataLength--;
    830         } else {
    831             int location = locationAfterFirstBlankLine(buffer);
    832             if (location != -1) {
    833                 // If the blank line is somewhere in the middle of the buffer, everything before is the header
    834                 headerFields = parseRFC822HeaderFields(buffer, location);
    835                 unsigned dataLength = buffer.size() - location;
    836 
    837                 // Sometimes plugins like to set Content-Length themselves when they post,
    838                 // but WebFoundation does not like that. So we will remove the header
    839                 // and instead truncate the data to the requested length.
    840                 String contentLength = headerFields.get("Content-Length");
    841 
    842                 if (!contentLength.isNull())
    843                     dataLength = min(contentLength.toInt(), (int)dataLength);
    844                 headerFields.remove("Content-Length");
    845 
    846                 postData += location;
    847                 postDataLength = dataLength;
    848             }
    849         }
    850     }
    851 
    852     frameLoadRequest.resourceRequest().setHTTPMethod("POST");
    853     frameLoadRequest.resourceRequest().setURL(makeURL(m_baseURL, url));
    854     frameLoadRequest.resourceRequest().addHTTPHeaderFields(headerFields);
    855     frameLoadRequest.resourceRequest().setHTTPBody(FormData::create(postData, postDataLength));
    856     frameLoadRequest.setFrameName(target);
    857 
    858     return load(frameLoadRequest, sendNotification, notifyData);
     679        default:
     680            return NPERR_GENERIC_ERROR;
     681    }
    859682}
    860683
     
    953776        m_window = CreateWindowEx(0, kWebPluginViewdowClassName, 0, flags,
    954777                                  0, 0, 0, 0, m_parentFrame->view()->containingWindow(), 0, Page::instanceHandle(), 0);
    955        
     778
    956779        // Calling SetWindowLongPtrA here makes the window proc ASCII, which is required by at least
    957780        // the Shockwave Director plug-in.
  • trunk/WebKit/gtk/ChangeLog

    r32723 r32766  
     12008-05-01  Marc Ordinas i Llopis  <marc.ordinasillopis@collabora.co.uk>
     2
     3        Reviewed by Alp Toker.
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=14750
     6        Added support for NPAPI plugins on Gtk and Qt-x11 ports.
     7
     8        * WebCoreSupport/FrameLoaderClientGtk.cpp:
     9        (WebKit::FrameLoaderClient::FrameLoaderClient):
     10        (WebKit::FrameLoaderClient::committedLoad):
     11        (WebKit::FrameLoaderClient::createPlugin):
     12        (WebKit::FrameLoaderClient::redirectDataToPlugin):
     13        (WebKit::FrameLoaderClient::finishedLoading):
     14        (WebKit::FrameLoaderClient::setMainDocumentError):
     15        * WebCoreSupport/FrameLoaderClientGtk.h:
     16
    1172008-04-30  Sean Egan  <seanegan@gmail.com>
    218
  • trunk/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp

    r31877 r32766  
    33 *  Copyright (C) 2007, 2008 Holger Hans Peter Freyther
    44 *  Copyright (C) 2007 Christian Dywan <christian@twotoasts.de>
     5 *  Copyright (C) 2008 Collabora Ltd.  All rights reserved.
    56 *
    67 *  This library is free software; you can redistribute it and/or
     
    5859FrameLoaderClient::FrameLoaderClient(WebKitWebFrame* frame)
    5960    : m_frame(frame)
     61    , m_pluginView(0)
    6062    , m_userAgent("")
    6163{
     
    163165void FrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
    164166{
    165     FrameLoader *fl = loader->frameLoader();
    166     fl->setEncoding(m_response.textEncodingName(), false);
    167     fl->addData(data, length);
     167    const String& textEncoding = loader->response().textEncodingName();
     168
     169    if (!m_pluginView) {
     170        ASSERT(loader->frame());
     171        // Setting the encoding on the frame loader is our way to get work done that is normally done
     172        // when the first bit of data is received, even for the case of a document with no data (like about:blank).
     173        String encoding = loader->overrideEncoding();
     174        bool userChosen = !encoding.isNull();
     175        if (!userChosen)
     176            encoding = loader->response().textEncodingName();
     177
     178        FrameLoader* frameLoader = loader->frameLoader();
     179        frameLoader->setEncoding(encoding, userChosen);
     180        if (data)
     181            frameLoader->addData(data, length);
     182    }
     183
     184    if (m_pluginView) {
     185        if (!m_hasSentResponseToPlugin) {
     186            m_pluginView->didReceiveResponse(loader->response());
     187            m_hasSentResponseToPlugin = true;
     188        }
     189        m_pluginView->didReceiveData(data, length);
     190    }
    168191}
    169192
     
    261284}
    262285
    263 Widget* FrameLoaderClient::createPlugin(const IntSize&, Element*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool)
    264 {
    265     notImplemented();
     286Widget* FrameLoaderClient::createPlugin(const IntSize& pluginSize, Element* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
     287{
     288    PluginView* pluginView = PluginView::create(core(m_frame), pluginSize, element, url, paramNames, paramValues, mimeType, loadManually);
     289
     290    if (pluginView->status() == PluginStatusLoadedSuccessfully)
     291        return pluginView;
     292
    266293    return 0;
    267294}
     
    291318void FrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
    292319{
    293     notImplemented();
    294     return;
     320    m_pluginView = static_cast<PluginView*>(pluginWidget);
    295321}
    296322
     
    588614void FrameLoaderClient::finishedLoading(DocumentLoader* documentLoader)
    589615{
    590     ASSERT(documentLoader->frame());
    591     // Setting the encoding on the frame loader is our way to get work done that is normally done
    592     // when the first bit of data is received, even for the case of a document with no data (like about:blank).
    593     String encoding = documentLoader->overrideEncoding();
    594     bool userChosen = !encoding.isNull();
    595     if (encoding.isNull())
    596         encoding = documentLoader->response().textEncodingName();
    597     documentLoader->frameLoader()->setEncoding(encoding, userChosen);
     616    if (!m_pluginView)
     617        committedLoad(documentLoader, 0, 0);
     618    else {
     619        m_pluginView->didFinishLoading();
     620        m_pluginView = 0;
     621        m_hasSentResponseToPlugin = false;
     622    }
    598623}
    599624
     
    711736}
    712737
    713 void FrameLoaderClient::setMainDocumentError(DocumentLoader*, const ResourceError&)
    714 {
    715     notImplemented();
     738void FrameLoaderClient::setMainDocumentError(DocumentLoader*, const ResourceError& error)
     739{
     740    if (m_pluginView) {
     741        m_pluginView->didFail(error);
     742        m_pluginView = 0;
     743        m_hasSentResponseToPlugin = false;
     744    }
    716745}
    717746
  • trunk/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h

    r31283 r32766  
    22 * Copyright (C) 2006 Zack Rusin <zack@kde.org>
    33 * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
     4 * Copyright (C) 2008 Collabora Ltd. All rights reserved.
    45 *
    56 * All rights reserved.
     
    3233#include "FrameLoaderClient.h"
    3334#include "ResourceResponse.h"
     35#include "PluginView.h"
    3436
    3537typedef struct _WebKitWebFrame WebKitWebFrame;
     
    171173        WebCore::ResourceResponse m_response;
    172174        WebCore::String m_userAgent;
     175
     176        // Plugin view to redirect data to
     177        WebCore::PluginView* m_pluginView;
     178        bool m_hasSentResponseToPlugin;
    173179    };
    174180
  • trunk/WebKit/qt/ChangeLog

    r32755 r32766  
     12008-05-01  Marc Ordinas i Llopis  <marc.ordinasillopis@collabora.co.uk>
     2
     3        Reviewed by Alp Toker.
     4        Qt parts OK'ed by Simon Hausmann.
     5
     6        https://bugs.webkit.org/show_bug.cgi?id=14750
     7        Added support for NPAPI plugins on Gtk and Qt-x11 ports.
     8
     9        * WebCoreSupport/FrameLoaderClientQt.cpp:
     10        (WebCore::FrameLoaderClientQt::FrameLoaderClientQt):
     11        (WebCore::FrameLoaderClientQt::finishedLoading):
     12        (WebCore::FrameLoaderClientQt::setMainDocumentError):
     13        (WebCore::FrameLoaderClientQt::committedLoad):
     14        (WebCore::FrameLoaderClientQt::objectContentType):
     15        (WebCore::FrameLoaderClientQt::createPlugin):
     16        (WebCore::FrameLoaderClientQt::redirectDataToPlugin):
     17        * WebCoreSupport/FrameLoaderClientQt.h:
     18
    1192008-04-30  Julien Chaffraix  <jchaffraix@webkit.org>
    220
  • trunk/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp

    r32682 r32766  
    33 * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
    44 * Copyright (C) 2007-2008 Trolltech ASA
     5 * Copyright (C) 2008 Collabora Ltd. All rights reserved.
    56 *
    67 * All rights reserved.
     
    3940#include "Page.h"
    4041#include "PluginData.h"
     42#include "PluginDatabase.h"
    4143#include "ProgressTracker.h"
    4244#include "RenderPart.h"
     
    133135    : m_frame(0)
    134136    , m_webFrame(0)
     137    , m_pluginView(0)
    135138    , m_firstData(false)
    136139    , m_policyFunction(0)
     
    507510void FrameLoaderClientQt::finishedLoading(DocumentLoader* loader)
    508511{
    509     if (m_firstData) {
    510         FrameLoader *fl = loader->frameLoader();
    511         fl->setEncoding(m_response.textEncodingName(), false);
    512         m_firstData = false;
     512    if (!m_pluginView) {
     513        if(m_firstData) {
     514            FrameLoader *fl = loader->frameLoader();
     515            fl->setEncoding(m_response.textEncodingName(), false);
     516            m_firstData = false;
     517        }
     518    }
     519    else {
     520        m_pluginView->didFinishLoading();
     521        m_pluginView = 0;
     522        m_hasSentResponseToPlugin = false;
    513523    }
    514524}
     
    653663void FrameLoaderClientQt::setMainDocumentError(WebCore::DocumentLoader* loader, const WebCore::ResourceError& error)
    654664{
    655     if (m_firstData) {
    656         loader->frameLoader()->setEncoding(m_response.textEncodingName(), false);
    657         m_firstData = false;
     665    if (!m_pluginView) {
     666        if (m_firstData) {
     667            loader->frameLoader()->setEncoding(m_response.textEncodingName(), false);
     668            m_firstData = false;
     669        }
     670    } else {
     671        m_pluginView->didFail(error);
     672        m_pluginView = 0;
     673        m_hasSentResponseToPlugin = false;
    658674    }
    659675}
     
    661677void FrameLoaderClientQt::committedLoad(WebCore::DocumentLoader* loader, const char* data, int length)
    662678{
    663     if (!m_frame)
    664         return;
    665     FrameLoader *fl = loader->frameLoader();
    666     if (m_firstData) {
    667         fl->setEncoding(m_response.textEncodingName(), false);
    668         m_firstData = false;
    669     }
    670     fl->addData(data, length);
     679    if (!m_pluginView) {
     680        if (!m_frame)
     681            return;
     682        FrameLoader *fl = loader->frameLoader();
     683        if (m_firstData) {
     684            fl->setEncoding(m_response.textEncodingName(), false);
     685            m_firstData = false;
     686        }
     687        fl->addData(data, length);
     688    } else {
     689        if (!m_hasSentResponseToPlugin) {
     690            m_pluginView->didReceiveResponse(loader->response());
     691            m_hasSentResponseToPlugin = true;
     692        }
     693        m_pluginView->didReceiveData(data, length);
     694    }
    671695}
    672696
     
    950974        return ObjectContentOtherPlugin;
    951975
    952     if (url.isEmpty())
     976    if (url.isEmpty() && !_mimeType.length())
    953977        return ObjectContentNone;
    954978
     
    964988    if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
    965989        return ObjectContentImage;
     990
     991    if (PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType))
     992        return ObjectContentNetscapePlugin;
    966993
    967994    if (m_frame->page() && m_frame->page()->pluginData()->supportsMimeType(mimeType))
     
    9871014const unsigned numqStyleSheetProperties = sizeof(qstyleSheetProperties) / sizeof(qstyleSheetProperties[0]);
    9881015
    989 Widget* FrameLoaderClientQt::createPlugin(const IntSize&, Element* element, const KURL& url, const Vector<String>& paramNames,
     1016Widget* FrameLoaderClientQt::createPlugin(const IntSize& pluginSize, Element* element, const KURL& url, const Vector<String>& paramNames,
    9901017                                          const Vector<String>& paramValues, const String& mimeType, bool loadManually)
    9911018{
     
    10291056            widget->setStyleSheet(styleSheet);
    10301057        }
    1031     }
    10321058
    10331059#if QT_VERSION >= 0x040400
    1034     if (!object) {
    1035         QWebPluginFactory* factory = m_webFrame->page()->pluginFactory();
    1036         if (factory)
    1037             object = factory->create(mimeType, qurl, params, values);
    1038     }
     1060        if (!object) {
     1061            QWebPluginFactory* factory = m_webFrame->page()->pluginFactory();
     1062            if (factory)
     1063                object = factory->create(mimeType, qurl, params, values);
     1064        }
    10391065#endif
    10401066
    1041     if (object) {
    1042         QWidget *widget = qobject_cast<QWidget *>(object);
    1043         QWidget *view = m_webFrame->page()->view();
    1044         if (widget && view) {
    1045             widget->setParent(view);
    1046             Widget* w= new Widget();
    1047             w->setNativeWidget(widget);
    1048             return w;
     1067        if (object) {
     1068            QWidget *widget = qobject_cast<QWidget *>(object);
     1069            QWidget *view = m_webFrame->page()->view();
     1070            if (widget && view) {
     1071                widget->setParent(view);
     1072                Widget* w= new Widget();
     1073                w->setNativeWidget(widget);
     1074                return w;
     1075            }
     1076            // FIXME: make things work for widgetless plugins as well
     1077            delete object;
    10491078        }
    1050         // FIXME: make things work for widgetless plugins as well
    1051         delete object;
     1079    } else { // NPAPI Plugins
     1080        PluginView* pluginView = PluginView::create(m_frame, pluginSize, element, url,
     1081            paramNames, paramValues, mimeType, loadManually);
     1082        return pluginView;
    10521083    }
    10531084
     
    10571088void FrameLoaderClientQt::redirectDataToPlugin(Widget* pluginWidget)
    10581089{
    1059     notImplemented();
    1060     return;
     1090    m_pluginView = static_cast<PluginView*>(pluginWidget);
    10611091}
    10621092
     
    10781108}
    10791109
    1080 
    10811110}
    10821111
  • trunk/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.h

    r32643 r32766  
    33 * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
    44 * Copyright (C) 2007-2008 Trolltech ASA
     5 * Copyright (C) 2008 Collabora Ltd. All rights reserved.
    56 *
    67 * All rights reserved.
     
    3940#include "RefCounted.h"
    4041#include "ResourceResponse.h"
     42#include "PluginView.h"
    4143class QWebFrame;
    4244
     
    205207        bool m_firstData;
    206208        FramePolicyFunction m_policyFunction;
     209
     210        // Plugin view to redirect data to
     211        WebCore::PluginView* m_pluginView;
     212        bool m_hasSentResponseToPlugin;
     213
    207214        bool m_loadSucceeded;
    208215    };
Note: See TracChangeset for help on using the changeset viewer.