summaryrefslogtreecommitdiffstats
path: root/kjsembed/jsobjectproxy.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit90825e2392b2d70e43c7a25b8a3752299a933894 (patch)
treee33aa27f02b74604afbfd0ea4f1cfca8833d882a /kjsembed/jsobjectproxy.cpp
downloadtdebindings-90825e2392b2d70e43c7a25b8a3752299a933894.tar.gz
tdebindings-90825e2392b2d70e43c7a25b8a3752299a933894.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebindings@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kjsembed/jsobjectproxy.cpp')
-rw-r--r--kjsembed/jsobjectproxy.cpp306
1 files changed, 306 insertions, 0 deletions
diff --git a/kjsembed/jsobjectproxy.cpp b/kjsembed/jsobjectproxy.cpp
new file mode 100644
index 00000000..c8b43a5d
--- /dev/null
+++ b/kjsembed/jsobjectproxy.cpp
@@ -0,0 +1,306 @@
+/*
+* Copyright (C) 2001-2003, Richard J. Moore <rich@kde.org>
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Library General Public
+* License as published by the Free Software Foundation; either
+* version 2 of the License, or (at your option) any later version.
+*
+* This library 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
+* Library General Public License for more details.
+*
+* You should have received a copy of the GNU Library General Public License
+* along with this library; see the file COPYING.LIB. If not, write to
+* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+* Boston, MA 02110-1301, USA.
+*/
+
+#include <qobject.h>
+#include <qobjectlist.h>
+#include <qmetaobject.h>
+#include <qregexp.h>
+#include <qsignal.h>
+#include <qstrlist.h>
+#include <qvariant.h>
+
+#include <private/qucomextra_p.h>
+
+#include <kjs/interpreter.h>
+#include <kjs/types.h>
+#include <kjs/ustring.h>
+
+#include "kjsembedpart.h"
+#include "jssecuritypolicy.h"
+#include "jsfactory.h"
+#include "global.h"
+
+#include "jsobjectproxy.h"
+#include "jsobjectproxy_imp.h"
+#include "jsobjecteventproxy.h"
+#include "jseventmapper.h"
+#include "slotutils.h"
+
+#include "bindings/bindingobject.h"
+
+//#include "kjsembedpart_imp.h"
+#include "jsfactory_imp.h"
+
+using namespace KJS;
+
+namespace KJSEmbed {
+
+ typedef Bindings::JSObjectProxyImp JSObjectProxyImp;
+
+ JSObjectProxy::JSObjectProxy( KJSEmbedPart *part, QObject *target, QObject *r, const JSSecurityPolicy *sp )
+ : JSProxy( JSProxy::ObjectProxy ),
+ jspart( part ), js( part->interpreter() ), obj( target ), root( r ) {
+ policy = sp ? sp : JSSecurityPolicy::defaultPolicy();
+ }
+
+ JSObjectProxy::JSObjectProxy( KJSEmbedPart *part, QObject *target, QObject *r )
+ : JSProxy( JSProxy::ObjectProxy ),
+ jspart( part ), js( part->interpreter() ), obj( target ), root( r ) {
+ policy = JSSecurityPolicy::defaultPolicy();
+ }
+
+ JSObjectProxy::JSObjectProxy( KJSEmbedPart *part, QObject *target )
+ : JSProxy( JSProxy::ObjectProxy ),
+ jspart( part ), js( part->interpreter() ), obj( target ), root( target ) {
+ policy = JSSecurityPolicy::defaultPolicy();
+ }
+ JSObjectProxy::~JSObjectProxy() {
+ if ( owner() == JavaScript && obj->parent() == 0 )
+ delete obj;
+ }
+
+ void JSObjectProxy::setSecurityPolicy( const JSSecurityPolicy *pol ) {
+ policy = pol ? pol : new JSSecurityPolicy();
+ }
+
+ bool JSObjectProxy::isAllowed( KJS::Interpreter *js ) const {
+ return policy->isInterpreterAllowed( this, js );
+ }
+
+ KJS::UString JSObjectProxy::toString( KJS::ExecState *exec ) const {
+ if ( !exec ) {
+ kdWarning() << "JS toString with null state, ignoring" << endl;
+ return KJS::UString();
+ }
+ if ( !isAllowed( exec->interpreter() ) ) {
+ kdWarning() << "JS toString request from unknown interpreter, ignoring" << endl;
+ return KJS::UString();
+ }
+
+ QString s( "%1 (%2)" );
+ s = s.arg( obj ? obj->name() : "Dead Object" );
+ s = s.arg( obj ? obj->className() : "" );
+ return KJS::UString( s );
+ }
+
+ KJS::Value JSObjectProxy::get( KJS::ExecState *exec, const KJS::Identifier &p ) const {
+ if ( !isAllowed( exec->interpreter() ) ) {
+ kdWarning() << "JS get request from unknown interpreter, ignoring" << endl;
+ return KJS::Null();
+ }
+
+ if ( !policy->isPropertyAllowed( this, obj, p.ascii() ) )
+ return ObjectImp::get( exec, p );
+
+ if ( !obj ) {
+ kdDebug( 80001 ) << "JS getting '" << p.ustring().qstring() << "' but qobj has died" << endl;
+ return ObjectImp::get( exec, p );
+ }
+ kdDebug( 80001 ) << "JS getting '" << p.ascii() << endl;
+
+ // Properties
+ QString prop = p.ustring().qstring();
+ QMetaObject *meta = obj->metaObject();
+
+ if ( meta->findProperty( p.ascii(), true ) != -1 ) {
+ QVariant val = obj->property( prop.ascii() );
+ kdDebug( 80001 ) << "JS getting '" << p.ascii() << "' ( " << val.typeName() << ")" << endl;
+
+ return convertToValue( exec, val );
+ }
+
+ return ObjectImp::get
+ ( exec, p );
+ }
+
+ void JSObjectProxy::put( KJS::ExecState *exec,
+ const KJS::Identifier &p, const KJS::Value &v,
+ int attr ) {
+ if ( !isAllowed( exec->interpreter() ) ) {
+ kdWarning() << "JS put request from unknown interpreter, ignoring" << endl;
+ return ;
+ }
+
+ if ( !policy->hasCapability( JSSecurityPolicy::CapabilitySetProperties ) ) {
+ ObjectImp::put( exec, p, v, attr );
+ return ;
+ }
+
+ if ( !obj ) {
+ kdDebug( 80001 ) << "JS setting '" << p.ascii() << "' but qobj has died" << endl;
+ ObjectImp::put( exec, p, v, attr );
+ return ;
+ }
+
+ // Properties
+ QMetaObject *meta = obj->metaObject();
+ int propIndex = meta->findProperty( p.ascii(), true );
+ if ( propIndex != -1 ) {
+ QVariant val = convertToVariant( exec, v );
+ if ( meta->property(propIndex, true)->isEnumType() ) {
+ obj->setProperty( p.ascii(), val.toUInt() );
+ } else if ( val.isValid() ) {
+ obj->setProperty( p.ascii(), val );
+ } else {
+ kdWarning(80001) << "Error setting value." << endl;
+ }
+ } else {
+ ObjectImp::put( exec, p, v, attr );
+ }
+
+ if ( jspart->factory() ->eventMapper() ->isEventHandler( p ) ) {
+ if ( evproxy.isNull() )
+ evproxy = new KJSEmbed::JSObjectEventProxy( this );
+ evproxy->addFilter( jspart->factory() ->eventMapper() ->findEventType( p ) );
+ kdDebug( 80001 ) << "Adding event handler " << p.ascii() << endl;
+ }
+ }
+
+ //
+ // Implementation of JS Method Bindings
+ //
+
+ void JSObjectProxy::addBindings( KJS::ExecState *exec, KJS::Object &object ) {
+ kdDebug( 80001 ) << "JSObjectProxy::addBindings() " << ( obj->name() ? obj->name() : "dunno" )
+ << ", class " << obj->className() << endl;
+
+ if ( policy->hasCapability( JSSecurityPolicy::CapabilityGetProperties | JSSecurityPolicy::CapabilitySetProperties ) ) {
+ object.put( exec, "properties", KJS::Object( new JSObjectProxyImp( exec, JSObjectProxyImp::MethodProps, this ) ) );
+ }
+
+ if ( policy->hasCapability( JSSecurityPolicy::CapabilityTree ) ) {
+ JSObjectProxyImp::addBindingsTree( exec, object, this );
+ JSObjectProxyImp::addBindingsDOM( exec, object, this );
+ }
+
+ if ( policy->hasCapability( JSSecurityPolicy::CapabilitySlots ) ) {
+ addBindingsSlots( exec, object );
+ JSObjectProxyImp::addBindingsConnect( exec, object, this );
+ }
+
+ addBindingsClass( exec, object );
+ }
+
+ void JSObjectProxy::addBindingsClass( KJS::ExecState *exec, KJS::Object & /*object*/ ) {
+ KJS::Identifier clazzid;
+ QObject *o = obj;
+ Bindings::BindingObject *bo = dynamic_cast<Bindings::BindingObject *>( o );
+ if ( bo ) {
+ clazzid = KJS::Identifier( bo->jsClassName() ? bo->jsClassName() : obj->className() );
+ } else {
+ clazzid = KJS::Identifier( obj->className() );
+ }
+
+ KJS::Object global = js->globalObject();
+ if ( global.hasProperty( exec, clazzid ) ) {
+ kdDebug( 80001 ) << "addBindingsClass() " << clazzid.qstring() << " already known" << endl;
+
+ KJS::Object clazz = global.get( exec, clazzid ).toObject( exec );
+ Bindings::JSFactoryImp *imp = dynamic_cast<Bindings::JSFactoryImp *>( clazz.imp() );
+ if ( !imp ) {
+ kdWarning() << "addBindingsClass() Class was not created by normal means" << endl;
+ return ;
+ }
+
+ kdDebug( 80001 ) << "addBindingsClass() Adding enums" << endl;
+ imp->setDefaultValue( js->builtinObject().construct( exec, KJS::List() ) );
+ addBindingsEnum( exec, clazz );
+ } else {
+ kdWarning() << "addBindingsClass() " << clazzid.qstring() << " not known" << endl;
+ }
+ }
+
+ void JSObjectProxy::addBindingsEnum( KJS::ExecState *exec, KJS::Object &object ) {
+ QMetaObject * mo = obj->metaObject();
+ QStrList enumList = mo->enumeratorNames( true );
+
+ for ( QStrListIterator iter( enumList ); iter.current(); ++iter ) {
+
+ const QMetaEnum *me = mo->enumerator( iter.current(), true );
+ for ( uint i = 0 ; i < me->count ; i++ ) {
+ QCString key( ( me->items ) [ i ].key );
+ int val = ( me->items ) [ i ].value;
+ object.put( exec, key.data(), KJS::Number( val ), KJS::ReadOnly );
+ }
+ }
+ }
+
+ void JSObjectProxy::addBindingsSlots( KJS::ExecState *exec, KJS::Object &object ) {
+ // Publish slots with supported signatures as methods.
+ QMetaObject * mo = obj->metaObject();
+ QStrList slotList( mo->slotNames( true ) );
+ for ( QStrListIterator iter( slotList ); iter.current(); ++iter ) {
+ addSlotBinding( iter.current(), exec, object );
+ }
+ }
+
+ void JSObjectProxy::addSlotBinding( const QCString &name, KJS::ExecState *exec, KJS::Object &object ) {
+ // Lookup and bind slot
+ QMetaObject * mo = obj->metaObject();
+ int slotid = mo->findSlot( name.data(), true );
+ if ( slotid == -1 )
+ return ;
+
+ const QMetaData *md = mo->slot( slotid, true );
+ if ( md->access != QMetaData::Public )
+ return ;
+
+ // Find signature
+ int id = Bindings::JSSlotUtils::findSignature( name );
+ // kdDebug( 80001 )<<"JSObjectProxy::addSlotBinding()::slot:"<<name<<" id:"<<id<<endl;
+ if ( id < 0 )
+ return ;
+
+ QCString jsname = name;
+ jsname.detach();
+ jsname.replace( QRegExp( "\\([^\\)]*\\)" ), "" );
+
+ // Find the return type, we only care if it is a pointer type
+ const QUMethod *m = md->method;
+ const char *retclass = 0;
+ QCString ptr( "ptr" );
+
+ if ( m->count && ( m->parameters->inOut == QUParameter::Out )
+ && ( ptr == m->parameters->type->desc() ) ) {
+ retclass = ( const char * ) m->parameters->typeExtra;
+ // kdDebug(80001) << "Return type is a pointer, type " << retclass << endl;
+ }
+
+ // Create the Imp
+ JSObjectProxyImp *imp = new JSObjectProxyImp( exec, JSObjectProxyImp::MethodSlot,
+ retclass ? retclass : "", id, name, this );
+
+ if ( !object.hasProperty( exec, KJS::Identifier( jsname ) ) ) {
+ // The identifier is unused
+ object.put( exec, KJS::Identifier( jsname.data() ), KJS::Object( imp ) );
+ } else {
+ // The identifier has already been used
+ QString s( name );
+ QCString cs = QString( "%1%2" ).arg( jsname ).arg( s.contains( ',' ) + 1 ).ascii();
+ //kdDebug(80001) << "Method " << jsname << " exists, using " << cs << " for " << s << endl;
+ object.put( exec, KJS::Identifier( cs.data() ), KJS::Object( imp ) );
+ }
+ }
+
+} // namespace KJSEmbed
+
+// Local Variables:
+// c-basic-offset: 4
+// End:
+