As an intermediate stage, let's implement one direction of scripting using

current LC API first. No idea if it's workable w/o doing the other direction 
the way Koos did, but I figure it's better than trying to get a few thousand 
of untested LoC with completely new APIs working (and may be perhaps backportable), 
especially since I did a lot of the work before and can adapt it.

This commit does:
- Update the SDK headers for some of the new functions/enums
- Handle the LC requests in the part, and forward them via DBus to the viewer
- Similarly, have the viewer properly unpack and pass to the scripting engine
- The scripting code for now merely does some API initialization, no actual work.

svn path=/trunk/KDE/kdebase/apps/; revision=1116993
This commit is contained in:
Maks Orlovich 2010-04-20 20:08:43 +00:00
parent a3560e6cd5
commit a5c38428e3
15 changed files with 578 additions and 35 deletions

View file

@ -13,7 +13,7 @@ if (X11_Xt_LIB)
########### next target ############### ########### next target ###############
set(nsplugins_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/plugin_part.cpp ${CMAKE_CURRENT_SOURCE_DIR}/nspluginloader.cpp ) set(nsplugins_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/plugin_part.cpp ${CMAKE_CURRENT_SOURCE_DIR}/nspluginloader.cpp ${CMAKE_CURRENT_SOURCE_DIR}/comm/dbustypes.cpp)
set(nsplugins_PART_SRCS set(nsplugins_PART_SRCS
${nsplugins_SRCS} ${nsplugins_SRCS}
@ -25,6 +25,7 @@ if (X11_Xt_LIB)
QT4_ADD_DBUS_INTERFACE( nsplugins_PART_SRCS ${nsplugins_class_xml} nsplugins_class_interface ) QT4_ADD_DBUS_INTERFACE( nsplugins_PART_SRCS ${nsplugins_class_xml} nsplugins_class_interface )
set(nsplugins_instance_xml ${CMAKE_CURRENT_SOURCE_DIR}/viewer/org.kde.nsplugins.instance.xml) set(nsplugins_instance_xml ${CMAKE_CURRENT_SOURCE_DIR}/viewer/org.kde.nsplugins.instance.xml)
set_source_files_properties(${nsplugins_instance_xml} PROPERTIES INCLUDE "comm/dbustypes.h")
QT4_ADD_DBUS_INTERFACE( nsplugins_PART_SRCS ${nsplugins_instance_xml} nsplugins_instance_interface ) QT4_ADD_DBUS_INTERFACE( nsplugins_PART_SRCS ${nsplugins_instance_xml} nsplugins_instance_interface )
set(nsplugins_viewer_xml ${CMAKE_CURRENT_SOURCE_DIR}/viewer/org.kde.nsplugins.viewer.xml) set(nsplugins_viewer_xml ${CMAKE_CURRENT_SOURCE_DIR}/viewer/org.kde.nsplugins.viewer.xml)

View file

@ -0,0 +1,58 @@
/*
Support for scripting of plugins using the npruntime interface
Copyright (c) 2006, 2010 Maksim Orlovich <maksim@kde.org>
Copyright (c) 2009 by Marco Martin <notmart@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "dbustypes.h"
#include <QDBusMetaType>
const QDBusArgument& operator<<(QDBusArgument& arg, const NSLiveConnectResult& res)
{
arg.beginStructure();
arg << res.success;
arg << res.type;
arg << res.objid;
arg << res.value;
arg.endStructure();
return arg;
}
const QDBusArgument& operator>>(const QDBusArgument& arg, NSLiveConnectResult& res)
{
arg.beginStructure();
arg >> res.success;
arg >> res.type;
arg >> res.objid;
arg >> res.value;
arg.endStructure();
return arg;
}
namespace kdeNsPluginViewer {
void initDBusTypes()
{
qDBusRegisterMetaType<NSLiveConnectResult>();
}
}
// kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on;

View file

@ -0,0 +1,50 @@
/*
Support for scripting of plugins using the npruntime interface
Copyright (c) 2006, 2010 Maksim Orlovich <maksim@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef NSPLUGIN_VIEWER_LC_TYPES_H
#define NSPLUGIN_VIEWER_LC_TYPES_H
#include <QDBusArgument>
/* Type used for transferring scripting results over qdbus */
struct NSLiveConnectResult
{
NSLiveConnectResult() : success(false) {}
bool success;
int type;
quint32 objid;
QString value;
};
const QDBusArgument& operator<<(QDBusArgument& argument, const NSLiveConnectResult& res);
const QDBusArgument& operator>>(const QDBusArgument& argument, NSLiveConnectResult& res);
Q_DECLARE_METATYPE(NSLiveConnectResult)
namespace kdeNsPluginViewer {
void initDBusTypes();
}
#endif
// kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on;

View file

@ -57,6 +57,7 @@
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <unistd.h> #include <unistd.h>
NSPluginLoader *NSPluginLoader::s_instance = 0; NSPluginLoader *NSPluginLoader::s_instance = 0;
int NSPluginLoader::s_refCount = 0; int NSPluginLoader::s_refCount = 0;
@ -379,6 +380,9 @@ bool NSPluginLoader::loadViewer()
// get viewer dcop interface // get viewer dcop interface
_viewer = new org::kde::nsplugins::Viewer( _viewerDBusId, "/Viewer", QDBusConnection::sessionBus() ); _viewer = new org::kde::nsplugins::Viewer( _viewerDBusId, "/Viewer", QDBusConnection::sessionBus() );
// make sure we have the types setup
kdeNsPluginViewer::initDBusTypes();
return _viewer!=0; return _viewer!=0;
} }

View file

@ -35,6 +35,7 @@
#include <KUrl> #include <KUrl>
#include <kdemacros.h> #include <kdemacros.h>
#include <kprocess.h> #include <kprocess.h>
#include "comm/dbustypes.h"
#define EMBEDCLASS QX11EmbedContainer #define EMBEDCLASS QX11EmbedContainer
@ -54,6 +55,8 @@ public:
void javascriptResult(int id, const QString &result); void javascriptResult(int id, const QString &result);
OrgKdeNspluginsInstanceInterface* peer() { return _instanceInterface; }
private Q_SLOTS: private Q_SLOTS:
void loadPlugin(); void loadPlugin();

View file

@ -35,6 +35,8 @@
#include <kparts/browserinterface.h> #include <kparts/browserinterface.h>
#include <kparts/browserextension.h> #include <kparts/browserextension.h>
#include "nsplugins_instance_interface.h"
#include <QLabel> #include <QLabel>
@ -56,25 +58,49 @@ PluginLiveConnectExtension::PluginLiveConnectExtension(PluginPart* part)
PluginLiveConnectExtension::~PluginLiveConnectExtension() { PluginLiveConnectExtension::~PluginLiveConnectExtension() {
} }
static bool demarshalReturn(const NSLiveConnectResult& result, KParts::LiveConnectExtension::Type &type,
bool PluginLiveConnectExtension::get(const unsigned long, const QString &field, Type &type, unsigned long &retobj, QString &value) { unsigned long& retobj, QString& value)
Q_UNUSED(type); {
Q_UNUSED(retobj); if (result.success) {
Q_UNUSED(value); type = (KParts::LiveConnectExtension::Type)result.type;
kDebug(1432) << "PLUGIN:LiveConnect::get " << field; retobj = result.objid;
value = result.value;
return true;
}
return false; return false;
} }
bool PluginLiveConnectExtension::call(const unsigned long, const QString &func, const QStringList &args, Type &type, unsigned long &retobjid, QString &value) {
Q_UNUSED(type); bool PluginLiveConnectExtension::get(const unsigned long obj, const QString& f,
Q_UNUSED(retobjid); Type& typeOut, unsigned long& objOut, QString& valOut) {
Q_UNUSED(value); kDebug(1432) << "PLUGIN:LiveConnect::get " << obj << f;
kDebug(1432) << "PLUGIN:LiveConnect::call " << func << " args: " << args;
NSPluginInstance* instance = _part->instance();
if (instance) {
NSLiveConnectResult result;
result = instance->peer()->lcGet(obj, f);
return demarshalReturn(result, typeOut, objOut, valOut);
}
return false; return false;
} }
bool PluginLiveConnectExtension::put( const unsigned long, const QString &field, const QString &value) { bool PluginLiveConnectExtension::call(const unsigned long obj, const QString& f, const QStringList &args,
kDebug(1432) << "PLUGIN:LiveConnect::put " << field << " " << value; Type& typeOut, unsigned long& objOut, QString& valOut) {
kDebug(1432) << "PLUGIN:LiveConnect::call " << obj << f << args;
NSPluginInstance* instance = _part->instance();
if (instance) {
NSLiveConnectResult result;
result = instance->peer()->lcCall(obj, f, args);
return demarshalReturn(result, typeOut, objOut, valOut);
}
return false;
}
bool PluginLiveConnectExtension::put( const unsigned long objId, const QString &field, const QString &value) {
kDebug(1432) << "PLUGIN:LiveConnect::put " << objId << field << value;
if (objId == 0) {
if (_retval && field == "__nsplugin") { if (_retval && field == "__nsplugin") {
*_retval = value; *_retval = value;
return true; return true;
@ -82,9 +108,22 @@ bool PluginLiveConnectExtension::put( const unsigned long, const QString &field,
_part->changeSrc(value); _part->changeSrc(value);
return true; return true;
} }
}
NSPluginInstance *instance = _part->instance();
if (instance)
return instance->peer()->lcPut(objId, field, value);
return false; return false;
} }
void PluginLiveConnectExtension::unregister( const unsigned long objid ) {
NSPluginInstance *instance = _part->instance();
if (instance)
instance->peer()->lcUnregister(objid);
}
QString PluginLiveConnectExtension::evalJavaScript( const QString & script ) QString PluginLiveConnectExtension::evalJavaScript( const QString & script )
{ {
kDebug(1432) << "PLUGIN:LiveConnect::evalJavaScript " << script; kDebug(1432) << "PLUGIN:LiveConnect::evalJavaScript " << script;
@ -328,6 +367,12 @@ void PluginPart::requestURL(const QString& url, const QString& target)
emit _extension->openUrlRequest(new_url, arguments, browserArguments); emit _extension->openUrlRequest(new_url, arguments, browserArguments);
} }
NSPluginInstance* PluginPart::instance()
{
if (!_widget) return 0;
return dynamic_cast<NSPluginInstance*>(_widget.operator->());
}
void PluginPart::evalJavaScript(int id, const QString & script) void PluginPart::evalJavaScript(int id, const QString & script)
{ {
kDebug(1432) <<"evalJavascript: before widget check"; kDebug(1432) <<"evalJavascript: before widget check";
@ -340,7 +385,7 @@ void PluginPart::evalJavaScript(int id, const QString & script)
return; return;
_destructed = 0L; _destructed = 0L;
kDebug(1432) << "Liveconnect: script [" << script << "] evaluated to [" << rc << "]"; kDebug(1432) << "Liveconnect: script [" << script << "] evaluated to [" << rc << "]";
NSPluginInstance *ni = dynamic_cast<NSPluginInstance*>(_widget.operator->()); NSPluginInstance *ni = instance();
if (ni) if (ni)
ni->javascriptResult(id, rc); ni->javascriptResult(id, rc);
} }
@ -381,3 +426,4 @@ void PluginCanvasWidget::resizeEvent(QResizeEvent *ev)
#include "plugin_part.moc" #include "plugin_part.moc"
// kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on;

View file

@ -92,6 +92,7 @@ public:
void changeSrc(const QString& url); void changeSrc(const QString& url);
NSPluginInstance *instance();
protected: protected:
virtual bool openUrl(const KUrl &url); virtual bool openUrl(const KUrl &url);
virtual bool closeUrl(); virtual bool closeUrl();
@ -123,6 +124,7 @@ public:
virtual bool put(const unsigned long, const QString &field, const QString &value); virtual bool put(const unsigned long, const QString &field, const QString &value);
virtual bool get(const unsigned long, const QString&, Type&, unsigned long&, QString&); virtual bool get(const unsigned long, const QString&, Type&, unsigned long&, QString&);
virtual bool call(const unsigned long, const QString&, const QStringList&, Type&, unsigned long&, QString&); virtual bool call(const unsigned long, const QString&, const QStringList&, Type&, unsigned long&, QString&);
virtual void unregister( const unsigned long objid );
QString evalJavaScript( const QString & script ); QString evalJavaScript( const QString & script );

View file

@ -126,7 +126,8 @@
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
#define NP_VERSION_MAJOR 0 #define NP_VERSION_MAJOR 0
#define NP_VERSION_MINOR 13 #define NP_VERSION_MINOR 14
/* See note near NPVERS_HAS_NPRUNTIME_SCRIPTING */
/* The OS/2 version of Netscape uses RC_DATA to define the /* The OS/2 version of Netscape uses RC_DATA to define the
@ -397,7 +398,26 @@ typedef enum {
/* 12 and over are available on Mozilla builds starting with 0.9.9 */ /* 12 and over are available on Mozilla builds starting with 0.9.9 */
NPPVjavascriptPushCallerBool = 12, NPPVjavascriptPushCallerBool = 12,
NPPVpluginKeepLibraryInMemory = 13, /* available in Mozilla 1.0 */ NPPVpluginKeepLibraryInMemory = 13, /* available in Mozilla 1.0 */
NPPVpluginNeedsXEmbed = 14 NPPVpluginNeedsXEmbed = 14,
/* Get the NPObject for scripting the plugin. Introduced in Firefox
* 1.0 (NPAPI minor version 14).
*/
NPPVpluginScriptableNPObject = 15,
/* Get the plugin value (as \0-terminated UTF-8 string data) for
* form submission if the plugin is part of a form. Use
* NPN_MemAlloc() to allocate memory for the string data. Introduced
* in Mozilla 1.8b2 (NPAPI minor version 15).
*/
NPPVformValue = 16,
NPPVpluginUrlRequestsDisplayedBool = 17,
/* Checks if the plugin is interested in receiving the http body of
* all http requests (including failed ones, http status != 200).
*/
NPPVpluginWantsAllNetworkStreams = 18
} NPPVariable; } NPPVariable;
/* /*
@ -416,9 +436,23 @@ typedef enum {
NPNVDOMElement = (11 | NP_ABI_MASK), /* available in Mozilla 1.2 */ NPNVDOMElement = (11 | NP_ABI_MASK), /* available in Mozilla 1.2 */
NPNVDOMWindow = (12 | NP_ABI_MASK), NPNVDOMWindow = (12 | NP_ABI_MASK),
NPNVToolkit = (13 | NP_ABI_MASK), NPNVToolkit = (13 | NP_ABI_MASK),
NPNVSupportsXEmbedBool = 14 NPNVSupportsXEmbedBool = 14,
/* Get the NPObject wrapper for the browser window. */
NPNVWindowNPObject = 15,
/* Get the NPObject wrapper for the plugins DOM element. */
NPNVPluginElementNPObject = 16,
NPNVSupportsWindowless = 17
} NPNVariable; } NPNVariable;
typedef enum {
NPNURLVCookie = 501,
NPNURLVProxy
} NPNURLVariable;
/* /*
* The type of Tookkit the widgets use * The type of Tookkit the widgets use
*/ */
@ -611,6 +645,15 @@ enum NPEventType {
#define NPVERS_68K_HAS_LIVECONNECT 11 #define NPVERS_68K_HAS_LIVECONNECT 11
#define NPVERS_HAS_WINDOWLESS 11 #define NPVERS_HAS_WINDOWLESS 11
#define NPVERS_HAS_XPCONNECT_SCRIPTING 13 #define NPVERS_HAS_XPCONNECT_SCRIPTING 13
#define NPVERS_HAS_NPRUNTIME_SCRIPTING 14
#define NPVERS_HAS_FORM_VALUES 15
#define NPVERS_HAS_POPUPS_ENABLED_STATE 16
#define NPVERS_HAS_RESPONSE_HEADERS 17
#define NPVERS_HAS_NPOBJECT_ENUM 18
// KDE note: we claim 14 right now, though we do want to do enum.
#define NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL 19
#define NPVERS_HAS_ALL_NETWORK_STREAMS 20
#define NPVERS_HAS_URL_AND_AUTH_INFO 21
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
/* Function Prototypes */ /* Function Prototypes */

View file

@ -1651,6 +1651,13 @@ typedef void (* NP_LOADDS NPN_PopPopupsEnabledStateUPP)(NPP npp);
#endif #endif
#endif #endif
typedef bool (*NPN_EnumerateProcPtr)(NPP npp, NPObject *obj, NPIdentifier **identifier, uint32 *count);
typedef void (*NPN_PluginThreadAsyncCallProcPtr)(NPP instance, void (*func)(void *), void *userData);
typedef bool (*NPN_ConstructProcPtr)(NPP npp, NPObject* obj, const NPVariant *args, uint32 argCount, NPVariant *result);
typedef NPError (*NPN_GetValueForURLPtr)(NPP npp, NPNURLVariable variable, const char *url, char **value, uint32 *len);
typedef NPError (*NPN_SetValueForURLPtr)(NPP npp, NPNURLVariable variable, const char *url, const char *value, uint32 len);
typedef NPError (*NPN_GetAuthenticationInfoPtr)(NPP npp, const char *protocol, const char *host, int32 port, const char *scheme, const char *realm, char **username, uint32 *ulen, char **password, uint32 *plen);
typedef struct _NPPluginFuncs { typedef struct _NPPluginFuncs {
uint16 size; uint16 size;
uint16 version; uint16 version;
@ -1715,6 +1722,12 @@ typedef struct _NPNetscapeFuncs {
NPN_SetExceptionUPP setexception; NPN_SetExceptionUPP setexception;
NPN_PushPopupsEnabledStateUPP pushpopupsenabledstate; NPN_PushPopupsEnabledStateUPP pushpopupsenabledstate;
NPN_PopPopupsEnabledStateUPP poppopupsenabledstate; NPN_PopPopupsEnabledStateUPP poppopupsenabledstate;
NPN_EnumerateProcPtr enumerate;
NPN_PluginThreadAsyncCallProcPtr pluginthreadasynccall;
NPN_ConstructProcPtr construct;
// NPN_GetValueForURLPtr getvalueforurl;
// NPN_SetValueForURLPtr setvalueforurl;
// NPN_GetAuthenticationInfoPtr getauthenticationinfo;
} NPNetscapeFuncs; } NPNetscapeFuncs;
#ifdef XP_MAC #ifdef XP_MAC

View file

@ -7,7 +7,7 @@ endif (GLIB2_FOUND)
########### next target ############### ########### next target ###############
set(nspluginviewer_SRCS nsplugin.cpp viewer.cpp xtevents.cpp glibevents.cpp set(nspluginviewer_SRCS nsplugin.cpp viewer.cpp xtevents.cpp glibevents.cpp
pluginhost_xembed.cpp pluginhost_xt.cpp pluginhost.cpp scripting.cpp) pluginhost_xembed.cpp pluginhost_xt.cpp pluginhost.cpp scripting.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../comm/dbustypes.cpp)
qt4_add_dbus_adaptor( nspluginviewer_SRCS org.kde.nsplugins.class.xml nsplugin.h NSPluginClass ) qt4_add_dbus_adaptor( nspluginviewer_SRCS org.kde.nsplugins.class.xml nsplugin.h NSPluginClass )
qt4_add_dbus_adaptor( nspluginviewer_SRCS org.kde.nsplugins.instance.xml nsplugin.h NSPluginInstance ) qt4_add_dbus_adaptor( nspluginviewer_SRCS org.kde.nsplugins.instance.xml nsplugin.h NSPluginInstance )

View file

@ -4,7 +4,7 @@
Copyright (c) 2000 Matthias Hoelzer-Kluepfel <hoelzer@kde.org> Copyright (c) 2000 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
Stefan Schimanski <1Stein@gmx.de> Stefan Schimanski <1Stein@gmx.de>
2003-2005 George Staikos <staikos@kde.org> 2003-2005 George Staikos <staikos@kde.org>
2007, 2008 Maksim Orlovich <maksim@kde.org> 2007, 2008, 2010 Maksim Orlovich <maksim@kde.org>
2006, 2007, 2008 Apple Inc. 2006, 2007, 2008 Apple Inc.
2008 Collabora, Ltd. 2008 Collabora, Ltd.
2008 Sebastian Sauer <mail@dipe.org> 2008 Sebastian Sauer <mail@dipe.org>
@ -31,6 +31,7 @@
#include "classadaptor.h" #include "classadaptor.h"
#include "instanceadaptor.h" #include "instanceadaptor.h"
#include "vieweradaptor.h" #include "vieweradaptor.h"
#include "scripting.h"
#include "nsplugins_callback_interface.h" #include "nsplugins_callback_interface.h"
@ -636,6 +637,8 @@ NSPluginInstance::NSPluginInstance(NPP privateData, NPPluginFuncs *pluginFuncs,
QObject *parent ) QObject *parent )
: QObject( parent ) : QObject( parent )
{ {
kdeNsPluginViewer::initDBusTypes();
// The object name is the dbus object path // The object name is the dbus object path
(void) new InstanceAdaptor( this ); (void) new InstanceAdaptor( this );
setObjectName( QString( "/Instance_" ) + QString::number( ++s_instanceCounter ) ); setObjectName( QString( "/Instance_" ) + QString::number( ++s_instanceCounter ) );
@ -649,6 +652,7 @@ NSPluginInstance::NSPluginInstance(NPP privateData, NPPluginFuncs *pluginFuncs,
_handle = handle; _handle = handle;
_callback = new org::kde::nsplugins::CallBack( appId, callbackId, QDBusConnection::sessionBus() ); _callback = new org::kde::nsplugins::CallBack( appId, callbackId, QDBusConnection::sessionBus() );
_numJSRequests = 0; _numJSRequests = 0;
_scripting = 0;
KUrl base(src); KUrl base(src);
base.setFileName( QString() ); base.setFileName( QString() );
@ -687,6 +691,56 @@ NSPluginInstance::~NSPluginInstance()
kDebug(1431) << "<- ~NSPluginInstance"; kDebug(1431) << "<- ~NSPluginInstance";
} }
void NSPluginInstance::setupLiveConnect()
{
_scripting = ScriptExportEngine::create(this);
}
// Note: here we again narrow the types to the same ulong as LiveConnectExtension uses,
// so we don't end up with extra precision floating around
NSLiveConnectResult NSPluginInstance::lcGet(qulonglong objid, const QString& field)
{
NSLiveConnectResult result;
if (_scripting) {
KParts::LiveConnectExtension::Type type;
unsigned long outId;
result.success = _scripting->get(static_cast<unsigned long>(objid), field,
type, outId, result.value);
result.type = type;
result.objid = outId;
}
return result;
}
bool NSPluginInstance::lcPut(qulonglong objid, const QString& field, const QString& value)
{
if (_scripting)
return _scripting->put(static_cast<unsigned long>(objid), field, value);
return false;
}
NSLiveConnectResult NSPluginInstance::lcCall(qulonglong objid, const QString& func,
const QStringList& args)
{
NSLiveConnectResult result;
if (_scripting) {
KParts::LiveConnectExtension::Type type;
unsigned long outId;
result.success = _scripting->call(static_cast<unsigned long>(objid), func, args,
type, outId, result.value);
result.type = type;
result.objid = outId;
}
return result;
}
void NSPluginInstance::lcUnregister(qulonglong objid)
{
if (_scripting)
_scripting->unregister(static_cast<unsigned long>(objid));
}
void NSPluginInstance::destroy() void NSPluginInstance::destroy()
{ {
if ( !_destroyed ) { if ( !_destroyed ) {
@ -707,6 +761,10 @@ void NSPluginInstance::destroy()
delete _callback; delete _callback;
_callback = 0; _callback = 0;
kDebug(1431) << "delete scripting";
delete _scripting;
_scripting = 0;
kDebug(1431) << "destroy plugin"; kDebug(1431) << "destroy plugin";
NPSavedData *saved = 0; NPSavedData *saved = 0;
@ -1382,6 +1440,8 @@ int NSPluginClass::initialize()
_nsFuncs.invalidateregion = g_NPN_InvalidateRegion; _nsFuncs.invalidateregion = g_NPN_InvalidateRegion;
_nsFuncs.forceredraw = g_NPN_ForceRedraw; _nsFuncs.forceredraw = g_NPN_ForceRedraw;
ScriptExportEngine::fillInScriptingFunctions(&_nsFuncs);
_nsFuncs.pushpopupsenabledstate = g_NPN_PushPopupsEnabledState; _nsFuncs.pushpopupsenabledstate = g_NPN_PushPopupsEnabledState;
_nsFuncs.poppopupsenabledstate = g_NPN_PopPopupsEnabledState; _nsFuncs.poppopupsenabledstate = g_NPN_PopPopupsEnabledState;
@ -1478,6 +1538,9 @@ QDBusObjectPath NSPluginClass::newInstance( const QString &url, const QString &m
if ( !src.isEmpty() ) if ( !src.isEmpty() )
inst->requestURL( src, mimeType, QString(), 0, false, reload ); inst->requestURL( src, mimeType, QString(), 0, false, reload );
// init scripting, if possible
inst->setupLiveConnect();
_instances.append( inst ); _instances.append( inst );
return QDBusObjectPath(inst->objectName()); return QDBusObjectPath(inst->objectName());
} }
@ -1928,3 +1991,4 @@ void NSPluginStream::result(KJob *job)
#include "nsplugin.moc" #include "nsplugin.moc"
// vim: ts=4 sw=4 et // vim: ts=4 sw=4 et
// kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on;

View file

@ -46,6 +46,8 @@
#define MOZ_X11 #define MOZ_X11
#include "sdk/npupp.h" #include "sdk/npupp.h"
#include "comm/dbustypes.h"
typedef char* NP_GetMIMEDescriptionUPP(void); typedef char* NP_GetMIMEDescriptionUPP(void);
typedef NPError NP_InitializeUPP(NPNetscapeFuncs*, NPPluginFuncs*); typedef NPError NP_InitializeUPP(NPNetscapeFuncs*, NPPluginFuncs*);
typedef NPError NP_ShutdownUPP(void); typedef NPError NP_ShutdownUPP(void);
@ -63,6 +65,7 @@ class QTimer;
namespace kdeNsPluginViewer { namespace kdeNsPluginViewer {
void* g_NPN_MemAlloc(uint32 size); void* g_NPN_MemAlloc(uint32 size);
void g_NPN_MemFree(void* ptr); void g_NPN_MemFree(void* ptr);
class ScriptExportEngine;
} }
using namespace kdeNsPluginViewer; using namespace kdeNsPluginViewer;
@ -184,6 +187,16 @@ public:
void gotFocusIn(); void gotFocusIn();
void gotFocusOut(); void gotFocusOut();
// d-bus export scripting interface
NSLiveConnectResult lcCall(qulonglong obj, const QString& f, const QStringList& args);
NSLiveConnectResult lcGet (qulonglong obj, const QString& f);
bool lcPut(qulonglong obj, const QString& f, const QString& v);
void lcUnregister(qulonglong obj);
// Initialize root JS object export if possible.
void setupLiveConnect();
// last via NSPluginClass::newInstance() produced NSPluginInstance instance. // last via NSPluginClass::newInstance() produced NSPluginInstance instance.
static NSPluginInstance* lastPluginInstance(); static NSPluginInstance* lastPluginInstance();
static void setLastPluginInstance(NSPluginInstance*); static void setLastPluginInstance(NSPluginInstance*);
@ -227,6 +240,7 @@ public Q_SLOTS:
private: private:
friend class NSPluginStreamBase; friend class NSPluginStreamBase;
friend class kdeNsPluginViewer::ScriptExportEngine;
void destroy(); void destroy();
@ -283,6 +297,8 @@ private:
QMap<int, Request*> _jsrequests; QMap<int, Request*> _jsrequests;
int _numJSRequests; // entered in earlier than _jsrequests. int _numJSRequests; // entered in earlier than _jsrequests.
ScriptExportEngine *_scripting; //0 if plugin doesn't support it.
static NSPluginInstance* s_lastPluginInstance; static NSPluginInstance* s_lastPluginInstance;
}; };

View file

@ -21,5 +21,46 @@
</method> </method>
<method name="gotFocusOut"> <method name="gotFocusOut">
</method> </method>
<!-- Live connect stuff. We use 't' (uint64) for objids, to map
the LiveCOnnectExtension's ambiguous ulong.
Results are encoded as:
struct NSLiveConnectResult {
bool success;
int type;
quint64 objid;
QString value;
};
So (bits)
-->
<method name="lcGet">
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="NSLiveConnectResult"/>
<arg type="(bits)" direction="out"/>
<arg name="objid" type="t" />
<arg name="field" type="s" />
</method>
<method name="lcPut">
<arg type="b" direction="out"/>
<arg name="objid" type="t" />
<arg name="field" type="s" />
<arg name="value" type="s" />
</method>
<method name="lcCall">
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="NSLiveConnectResult"/>
<arg type="(bits)" direction="out"/>
<arg name="objid" type="t" />
<arg name="field" type="s" />
<arg name="args" type="as" />
</method>
<method name="lcUnregister">
<arg name="objid" type="t" />
</method>
</interface> </interface>
</node> </node>
<!--- kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on; -->

View file

@ -28,8 +28,9 @@
#include <cstring> #include <cstring>
namespace kdeNsPluginViewer { #include "scripting.h"
namespace kdeNsPluginViewer {
// npruntime API --- variants & identifiers // npruntime API --- variants & identifiers
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -240,12 +241,121 @@ static bool g_NPN_Construct(NPP, NPObject* npobj, const NPVariant* args,
return false; return false;
} }
// ### invalidate, NPN_evaluate, setException? static void g_NPN_SetException(NPObject* /*npobj*/, const NPUTF8* /*message*/)
{
kDebug(1431) << "[unimplemented]";
}
static bool g_NPN_Evaluate(NPP /*npp*/, NPObject* /*npobj*/, NPString* /*script*/,
NPVariant* /*result*/)
{
kDebug(1431) << "[unimplemented]";
return false;
}
// ### invalidate, NPN_evaluate, setException -- what should they do?
// now, a little adapter for representing native objects as NPRuntime ones. // now, a little adapter for representing native objects as NPRuntime ones.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// ScriptExportEngine
//-----------------------------------------------------------------------------
void ScriptExportEngine::fillInScriptingFunctions(NPNetscapeFuncs* nsFuncs)
{
nsFuncs->getstringidentifier = g_NPN_GetStringIdentifier;
nsFuncs->getstringidentifiers = g_NPN_GetStringIdentifiers;
nsFuncs->getintidentifier = g_NPN_GetIntIdentifier;
nsFuncs->identifierisstring = g_NPN_IdentifierIsString;
nsFuncs->utf8fromidentifier = g_NPN_UTF8FromIdentifier;
nsFuncs->intfromidentifier = g_NPN_IntFromIdentifier;
nsFuncs->createobject = g_NPN_CreateObject;
nsFuncs->retainobject = g_NPN_RetainObject;
nsFuncs->releaseobject = g_NPN_ReleaseObject;
nsFuncs->invoke = g_NPN_Invoke;
nsFuncs->invokeDefault = g_NPN_InvokeDefault;
nsFuncs->evaluate = g_NPN_Evaluate;
nsFuncs->getproperty = g_NPN_GetProperty;
nsFuncs->setproperty = g_NPN_SetProperty;
nsFuncs->removeproperty = g_NPN_RemoveProperty;
nsFuncs->hasproperty = g_NPN_HasProperty;
nsFuncs->hasmethod = g_NPN_HasMethod;
nsFuncs->releasevariantvalue = g_NPN_ReleaseVariantValue;
nsFuncs->setexception = g_NPN_SetException;
nsFuncs->enumerate = g_NPN_Enumerate;
nsFuncs->construct = g_NPN_Construct;
}
ScriptExportEngine* ScriptExportEngine::create(NSPluginInstance* inst) {
NPObject* rootObj = 0;
if (inst->NPGetValue(NPPVpluginScriptableNPObject, (void*)&rootObj) == NPERR_NO_ERROR) {
kDebug(1431) << "Detected support for scripting, root = " <<rootObj << endl;
if (rootObj)
return new ScriptExportEngine(inst, rootObj);
}
return 0;
}
ScriptExportEngine::ScriptExportEngine(NSPluginInstance* inst, NPObject* root):
_nextId(0), _pluginInstance(inst), _liveConnectRoot(root)
{
kDebug(1431) << _liveConnectRoot->referenceCount;
allocObjId(root); //Setup root as 0..
}
ScriptExportEngine::~ScriptExportEngine()
{
kDebug(1431) << _liveConnectRoot->referenceCount;
g_NPN_ReleaseObject(_liveConnectRoot);
}
NPObject* ScriptExportEngine::getScriptObject(unsigned long objid)
{
QHash<unsigned long, NPObject*>::const_iterator i = _objectsForId.constFind(objid);
if (i == _objectsForId.constEnd())
return 0;
else
return i.value();
}
unsigned long ScriptExportEngine::allocObjId(NPObject* object)
{
while(true) {
if (!_objectsForId.contains(_nextId)) { // && !_functionForId.contains(_nextId)) {
unsigned long freeID = _nextId;
++_nextId;
_objectsForId[freeID] = object;
_objectIds[object] = freeID;
return freeID;
}
++_nextId;
}
}
bool ScriptExportEngine::get(const unsigned long objid, const QString& field,
KParts::LiveConnectExtension::Type& typeOut,
unsigned long& retobjid, QString& value)
{
return false;
}
bool ScriptExportEngine::put(const unsigned long objid, const QString& field,
const QString& value)
{
return false;
}
bool ScriptExportEngine::call(const unsigned long objid, const QString& func, const QStringList& args,
KParts::LiveConnectExtension::Type& retType, unsigned long& retobjid, QString& value)
{
return false;
}
void ScriptExportEngine::unregister(const unsigned long objid)
{
}
} // namespace kdeNsPluginViewer } // namespace kdeNsPluginViewer
// kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on; // kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on;

View file

@ -0,0 +1,92 @@
/*
Support for scripting of plugins using the npruntime interface
Copyright (c) 2006, 2010 Maksim Orlovich <maksim@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "nsplugin.h"
#include "sdk/npruntime.h"
#include <kparts/browserextension.h>
#include <QHash>
namespace kdeNsPluginViewer {
class ScriptExportEngine
{
public:
/* Tries to create a scripting manager if the plugin supports it.
If not, returns 0
*/
static ScriptExportEngine* create(NSPluginInstance* instance);
/* Fills in the functions table with plugins API support */
static void fillInScriptingFunctions(NPNetscapeFuncs* nsFuncs);
~ScriptExportEngine();
/* LiveConnectExtension API... */
bool get(const unsigned long objid, const QString& field, KParts::LiveConnectExtension::Type& type, unsigned long& retobjid, QString& value);
bool put(const unsigned long objid, const QString& field, const QString& value);
bool call(const unsigned long objid, const QString& func, const QStringList& args,
KParts::LiveConnectExtension::Type& retType, unsigned long& retobjid, QString& value);
void unregister(const unsigned long objid);
private:
ScriptExportEngine(NSPluginInstance* inst, NPObject* root);
void setupReturn(const NPVariant& result, KParts::LiveConnectExtension::Type& type,
unsigned long& retobjid, QString& value);
QHash<unsigned long, NPObject*> _objectsForId;
QHash<NPObject*, unsigned long> _objectIds;
// Returns the object corresponding to ID, or null... 0 is the root object..
NPObject* getScriptObject(unsigned long objid);
#if 0
struct FunctionInfo {
NPObject* baseObject; //Object we're a function of.. we retain it..
QString name; //The function we are..
unsigned long id; //Our ID
unsigned long rc; //Our refcount..
};
QMap<unsigned long, FunctionInfo*> _functionForId;
QMap<QPair<NPObject*, QString>, FunctionInfo*> _functionForBaseAndName;
//Returns the function corresponding to ID, or null..
FunctionInfo* getFunctionInfo(const unsigned long objid);
#endif
unsigned long _nextId;
unsigned long allocObjId (NPObject* object);
unsigned long allocFuncId(NPObject* object, QString field);
NSPluginInstance* _pluginInstance;
NPObject* _liveConnectRoot;
//Nocopyable...
Q_DISABLE_COPY(ScriptExportEngine);
};
} // namespace kdeNsPluginViewer
// kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on;