| # khtml Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# kjs_binding.cpp

    00001 // -*- c-basic-offset: 2 -*-
    00002 /*
    00003  *  This file is part of the KDE libraries
    00004  *  Copyright (C) 1999-2003 Harri Porten (porten@kde.org)
    00005  *  Copyright (C) 2001-2003 David Faure (faure@kde.org)
    00006  *  Copyright (C) 2003 Apple Computer, Inc.
    00007  *
    00008  *  This library is free software; you can redistribute it and/or
    00009  *  modify it under the terms of the GNU Library General Public
    00010  *  License as published by the Free Software Foundation; either
    00011  *  version 2 of the License, or (at your option) any later version.
    00012  *
    00013  *  This library is distributed in the hope that it will be useful,
    00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00016  *  Library General Public License for more details.
    00017  *
    00018  *  You should have received a copy of the GNU Library General Public
    00019  *  License along with this library; if not, write to the Free Software
    00020  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00021  */
    00022
    00023 #include "kjs_binding.h"
    00024 #include "kjs_dom.h"
    00025
    00026 #include "dom/dom_exception.h"
    00027 #include "dom/dom2_range.h"
    00028 #include "xml/dom2_eventsimpl.h"
    00029 #include "khtmlpart_p.h"
    00030
    00031 #include <kdebug.h>
    00032 #include <kparts/browserextension.h>
    00033
    00034 #include <assert.h>
    00035
    00036 using namespace KJS;
    00037
    00038 /* TODO:
    00039  * The catch all (...) clauses below shouldn't be necessary.
    00040  * But they helped to view for example www.faz.net in an stable manner.
    00041  * Those unknown exceptions should be treated as severe bugs and be fixed.
    00042  *
    00043  * these may be CSS exceptions - need to check - pmk
    00044  */
    00045
    00046 Value DOMObject::get(ExecState *exec, const Identifier &p) const
    00047 {
    00048   Value result;
    00049   try {
    00050     result = tryGet(exec,p);
    00051   }
    00052   catch (DOM::DOMException e) {
    00053     // ### translate code into readable string ?
    00054     // ### oh, and s/QString/i18n or I18N_NOOP (the code in kjs uses I18N_NOOP... but where is it translated ?)
    00055     //     and where does it appear to the user ?
    00056     Object err = Error::create(exec, GeneralError, QString("DOM exception %1").arg(e.code).local8Bit());
    00057     exec->setException( err );
    00058     result = Undefined();
    00059   }
    00060   catch (...) {
    00061     kdError(6070) << "Unknown exception in DOMObject::get()" << endl;
    00062     result = String("Unknown exception");
    00063   }
    00064
    00065   return result;
    00066 }
    00067
    00068 void DOMObject::put(ExecState *exec, const Identifier &propertyName,
    00069                     const Value &value, int attr)
    00070 {
    00071   try {
    00072     tryPut(exec, propertyName, value, attr);
    00073   }
    00074   catch (DOM::DOMException e) {
    00075     Object err = Error::create(exec, GeneralError, QString("DOM exception %1").arg(e.code).local8Bit());
    00076     exec->setException(err);
    00077   }
    00078   catch (...) {
    00079     kdError(6070) << "Unknown exception in DOMObject::put()" << endl;
    00080   }
    00081 }
    00082
    00083 UString DOMObject::toString(ExecState *) const
    00084 {
    00085   return "[object " + className() + "]";
    00086 }
    00087
    00088 Value DOMFunction::get(ExecState *exec, const Identifier &propertyName) const
    00089 {
    00090   try {
    00091     return tryGet(exec, propertyName);
    00092   }
    00093   catch (DOM::DOMException e) {
    00094     Object err = Error::create(exec, GeneralError, QString("DOM exception %1").arg(e.code).local8Bit());
    00095     exec->setException(err);
    00096     return Undefined();
    00097   }
    00098   catch (...) {
    00099     kdError(6070) << "Unknown exception in DOMFunction::get()" << endl;
    00100     return String("Unknown exception");
    00101   }
    00102 }
    00103
    00104 Value DOMFunction::call(ExecState *exec, Object &thisObj, const List &args)
    00105 {
    00106   try {
    00107     return tryCall(exec, thisObj, args);
    00108   }
    00109   // pity there's no way to distinguish between these in JS code
    00110   // ### Look into setting prototypes of these & the use of instanceof so the exception
    00111   // type can be determined. See what other browsers do.
    00112   catch (DOM::DOMException e) {
    00113     Object err = Error::create(exec, GeneralError, QString("DOM Exception %1").arg(e.code).local8Bit());
    00114     err.put(exec, "code", Number(e.code));
    00115     exec->setException(err);
    00116     return Undefined();
    00117   }
    00118   catch (DOM::RangeException e) {
    00119     Object err = Error::create(exec, GeneralError, QString("DOM Range Exception %1").arg(e.code).local8Bit());
    00120     err.put(exec, "code", Number(e.code));
    00121     exec->setException(err);
    00122     return Undefined();
    00123   }
    00124   catch (DOM::CSSException e) {
    00125     Object err = Error::create(exec, GeneralError, QString("CSS Exception %1").arg(e.code).local8Bit());
    00126     err.put(exec, "code", Number(e.code));
    00127     exec->setException(err);
    00128     return Undefined();
    00129   }
    00130   catch (DOM::EventException e) {
    00131     Object err = Error::create(exec, GeneralError, QString("DOM Event Exception %1").arg(e.code).local8Bit());
    00132     err.put(exec, "code", Number(e.code));
    00133     exec->setException(err);
    00134     return Undefined();
    00135   }
    00136   catch (...) {
    00137     kdError(6070) << "Unknown exception in DOMFunction::call()" << endl;
    00138     Object err = Error::create(exec, GeneralError, "Unknown exception");
    00139     exec->setException(err);
    00140     return Undefined();
    00141   }
    00142 }
    00143
    00144 typedef QPtrList<ScriptInterpreter> InterpreterList;
    00145 static InterpreterList *interpreterList;
    00146
    00147 ScriptInterpreter::ScriptInterpreter( const Object &global, khtml::ChildFrame* frame )
    00148   : Interpreter( global ), m_frame( frame ), m_domObjects(1021),
    00149     m_evt( 0L ), m_inlineCode(false), m_timerCallback(false)
    00150 {
    00151 #ifdef KJS_VERBOSE
    00152   kdDebug(6070) << "ScriptInterpreter::ScriptInterpreter " << this << " for part=" << m_frame << endl;
    00153 #endif
    00154   if ( !interpreterList )
    00155     interpreterList = new InterpreterList;
    00156   interpreterList->append( this );
    00157 }
    00158
    00159 ScriptInterpreter::~ScriptInterpreter()
    00160 {
    00161 #ifdef KJS_VERBOSE
    00162   kdDebug(6070) << "ScriptInterpreter::~ScriptInterpreter " << this << " for part=" << m_frame << endl;
    00163 #endif
    00164   assert( interpreterList && interpreterList->contains( this ) );
    00165   interpreterList->remove( this );
    00166   if ( interpreterList->isEmpty() ) {
    00167     delete interpreterList;
    00168     interpreterList = 0;
    00169   }
    00170 }
    00171
    00172 void ScriptInterpreter::forgetDOMObject( void* objectHandle )
    00173 {
    00174   if( !interpreterList ) return;
    00175
    00176   QPtrListIterator<ScriptInterpreter> it( *interpreterList );
    00177   while ( it.current() ) {
    00178     (*it)->deleteDOMObject( objectHandle );
    00179     ++it;
    00180   }
    00181 }
    00182
    00183 void ScriptInterpreter::mark()
    00184 {
    00185   Interpreter::mark();
    00186 #ifdef KJS_VERBOSE
    00187   kdDebug(6070) << "ScriptInterpreter::mark " << this << " marking " << m_domObjects.count() << " DOM objects" << endl;
    00188 #endif
    00189   QPtrDictIterator<DOMObject> it( m_domObjects );
    00190   for( ; it.current(); ++it )
    00191     it.current()->mark();
    00192 }
    00193
    00194 KParts::ReadOnlyPart* ScriptInterpreter::part() const {
    00195     return m_frame->m_part;
    00196 }
    00197
    00198 bool ScriptInterpreter::isWindowOpenAllowed() const
    00199 {
    00200   if ( m_evt )
    00201   {
    00202     int id = m_evt->handle()->id();
    00203     bool eventOk = ( // mouse events
    00204       id == DOM::EventImpl::CLICK_EVENT ||
    00205       id == DOM::EventImpl::MOUSEUP_EVENT || id == DOM::EventImpl::MOUSEDOWN_EVENT ||
    00206       id == DOM::EventImpl::KHTML_ECMA_CLICK_EVENT || id == DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT ||
    00207       // keyboard events
    00208       id == DOM::EventImpl::KEYDOWN_EVENT || id == DOM::EventImpl::KHTML_KEYPRESS_EVENT ||
    00209       id == DOM::EventImpl::KEYUP_EVENT ||
    00210       // other accepted events
    00211       id == DOM::EventImpl::SELECT_EVENT || id == DOM::EventImpl::CHANGE_EVENT ||
    00212       id == DOM::EventImpl::SUBMIT_EVENT );
    00213     kdDebug(6070) << "Window.open, smart policy: id=" << id << " eventOk=" << eventOk << endl;
    00214     if (eventOk)
    00215       return true;
    00216   } else // no event
    00217   {
    00218     if ( m_inlineCode && !m_timerCallback )
    00219     {
    00220       // This is the <a href="javascript:window.open('...')> case -> we let it through
    00221       return true;
    00222       kdDebug(6070) << "Window.open, smart policy, no event, inline code -> ok" << endl;
    00223     }
    00224     else // This is the <script>window.open(...)</script> case or a timer callback -> block it
    00225       kdDebug(6070) << "Window.open, smart policy, no event, <script> tag -> refused" << endl;
    00226   }
    00227   return false;
    00228 }
    00229
    00230
    00231 UString::UString(const QString &d)
    00232 {
    00233   unsigned int len = d.length();
    00234   UChar *dat = new UChar[len];
    00235   memcpy(dat, d.unicode(), len * sizeof(UChar));
    00236   rep = UString::Rep::create(dat, len);
    00237 }
    00238
    00239 UString::UString(const DOM::DOMString &d)
    00240 {
    00241   if (d.isNull()) {
    00242     attach(&Rep::null);
    00243     return;
    00244   }
    00245
    00246   unsigned int len = d.length();
    00247   UChar *dat = new UChar[len];
    00248   memcpy(dat, d.unicode(), len * sizeof(UChar));
    00249   rep = UString::Rep::create(dat, len);
    00250 }
    00251
    00252 DOM::DOMString UString::string() const
    00253 {
    00254   return DOM::DOMString((QChar*) data(), size());
    00255 }
    00256
    00257 QString UString::qstring() const
    00258 {
    00259   return QString((QChar*) data(), size());
    00260 }
    00261
    00262 QConstString UString::qconststring() const
    00263 {
    00264   return QConstString((QChar*) data(), size());
    00265 }
    00266
    00267 DOM::DOMString Identifier::string() const
    00268 {
    00269   return DOM::DOMString((QChar*) data(), size());
    00270 }
    00271
    00272 QString Identifier::qstring() const
    00273 {
    00274   return QString((QChar*) data(), size());
    00275 }
    00276
    00277 DOM::Node KJS::toNode(const Value& val)
    00278 {
    00279   Object obj = Object::dynamicCast(val);
    00280   if (obj.isNull() || !obj.inherits(&DOMNode::info))
    00281     return DOM::Node();
    00282
    00283   const DOMNode *dobj = static_cast<const DOMNode*>(obj.imp());
    00284   return dobj->toNode();
    00285 }
    00286
    00287 Value KJS::getString(DOM::DOMString s)
    00288 {
    00289   if (s.isNull())
    00290     return Null();
    00291   else
    00292     return String(s);
    00293 }
    00294
    00295 QVariant KJS::ValueToVariant(ExecState* exec, const Value &val) {
    00296   QVariant res;
    00297   switch (val.type()) {
    00298   case BooleanType:
    00299     res = QVariant(val.toBoolean(exec), 0);
    00300     break;
    00301   case NumberType:
    00302     res = QVariant(val.toNumber(exec));
    00303     break;
    00304   case StringType:
    00305     res = QVariant(val.toString(exec).qstring());
    00306     break;
    00307   default:
    00308     // everything else will be 'invalid'
    00309     break;
    00310   }
    00311   return res;
    00312 }
    00313
    00314 class EmbedLiveConnect : public ObjectImp
    00315 {
    00316   friend Value KJS::getLiveConnectValue(KParts::LiveConnectExtension *lc, const QString & name, const int type, const QString & value, int id);
    00317   EmbedLiveConnect(KParts::LiveConnectExtension *lc, UString n, KParts::LiveConnectExtension::Type t, int id);
    00318 public:
    00319   ~EmbedLiveConnect();
    00320
    00321   virtual Value get(ExecState *, const Identifier & prop) const;
    00322   virtual void put(ExecState * exec, const Identifier &prop, const Value & value, int=None);
    00323   virtual Value call(ExecState * exec, Object &, const List &args);
    00324   virtual bool implementsCall() const;
    00325   virtual bool toBoolean(ExecState *) const;
    00326   virtual Value toPrimitive(ExecState *exec, Type) const;
    00327   virtual UString toString(ExecState *) const;
    00328
    00329 private:
    00330   EmbedLiveConnect(const EmbedLiveConnect &);
    00331   QGuardedPtr<KParts::LiveConnectExtension> m_liveconnect;
    00332   UString name;
    00333   KParts::LiveConnectExtension::Type objtype;
    00334   unsigned long objid;
    00335 };
    00336
    00337 Value KJS::getLiveConnectValue(KParts::LiveConnectExtension *lc, const QString & name, const int type, const QString & value, int id)
    00338 {
    00339   KParts::LiveConnectExtension::Type t=(KParts::LiveConnectExtension::Type)type;
    00340   switch(t) {
    00341     case KParts::LiveConnectExtension::TypeBool: {
    00342       bool ok;
    00343       int i = value.toInt(&ok);
    00344       if (ok)
    00345         return Boolean(i);
    00346       return Boolean(!strcasecmp(value.latin1(), "true"));
    00347     }
    00348     case KParts::LiveConnectExtension::TypeObject:
    00349     case KParts::LiveConnectExtension::TypeFunction:
    00350       return Value(new EmbedLiveConnect(lc, name, t, id));
    00351     case KParts::LiveConnectExtension::TypeNumber: {
    00352       bool ok;
    00353       int i = value.toInt(&ok);
    00354       if (ok)
    00355         return Number(i);
    00356       else
    00357         return Number(value.toDouble(&ok));
    00358     }
    00359     case KParts::LiveConnectExtension::TypeString:
    00360       return String(value);
    00361     case KParts::LiveConnectExtension::TypeVoid:
    00362     default:
    00363       return Undefined();
    00364   }
    00365 }
    00366
    00367 /* only with gcc > 3.4 KDE_NO_EXPORT */
    00368 EmbedLiveConnect::EmbedLiveConnect(KParts::LiveConnectExtension *lc, UString n, KParts::LiveConnectExtension::Type t, int id)
    00369   : m_liveconnect (lc), name(n), objtype(t), objid(id)
    00370 {}
    00371
    00372 /* only with gcc > 3.4 KDE_NO_EXPORT */
    00373 EmbedLiveConnect::~EmbedLiveConnect() {
    00374   if (m_liveconnect)
    00375     m_liveconnect->unregister(objid);
    00376 }
    00377
    00378 KDE_NO_EXPORT
    00379 Value EmbedLiveConnect::get(ExecState *, const Identifier & prop) const
    00380 {
    00381   if (m_liveconnect) {
    00382     KParts::LiveConnectExtension::Type rettype;
    00383     QString retval;
    00384     unsigned long retobjid;
    00385     if (m_liveconnect->get(objid, prop.qstring(), rettype, retobjid, retval))
    00386       return getLiveConnectValue(m_liveconnect, prop.qstring(), rettype, retval, retobjid);
    00387   }
    00388   return Undefined();
    00389 }
    00390
    00391 KDE_NO_EXPORT
    00392 void EmbedLiveConnect::put(ExecState * exec, const Identifier &prop, const Value & value, int)
    00393 {
    00394   if (m_liveconnect)
    00395     m_liveconnect->put(objid, prop.qstring(), value.toString(exec).qstring());
    00396 }
    00397
    00398 KDE_NO_EXPORT
    00399 bool EmbedLiveConnect::implementsCall() const {
    00400   return objtype == KParts::LiveConnectExtension::TypeFunction;
    00401 }
    00402
    00403 KDE_NO_EXPORT
    00404 Value EmbedLiveConnect::call(ExecState *exec, Object&, const List &args)
    00405 {
    00406   if (m_liveconnect) {
    00407     QStringList qargs;
    00408     for (ListIterator i = args.begin(); i != args.end(); ++i)
    00409       qargs.append((*i).toString(exec).qstring());
    00410     KParts::LiveConnectExtension::Type rtype;
    00411     QString rval;
    00412     unsigned long robjid;
    00413     if (m_liveconnect->call(objid, name.qstring(), qargs, rtype, robjid, rval))
    00414       return getLiveConnectValue(m_liveconnect, name.qstring(), rtype, rval, robjid);
    00415   }
    00416   return Undefined();
    00417 }
    00418
    00419 KDE_NO_EXPORT
    00420 bool EmbedLiveConnect::toBoolean(ExecState *) const {
    00421   return true;
    00422 }
    00423
    00424 KDE_NO_EXPORT
    00425 Value EmbedLiveConnect::toPrimitive(ExecState *exec, Type) const {
    00426   return String(toString(exec));
    00427 }
    00428
    00429 KDE_NO_EXPORT
    00430 UString EmbedLiveConnect::toString(ExecState *) const {
    00431   QString str;
    00432   const char *type = objtype == KParts::LiveConnectExtension::TypeFunction ? "Function" : "Object";
    00433   str.sprintf("[object %s ref=%d]", type, (int) objid);
    00434   return UString(str);
    00435 }

This file is part of the documentation for khtml Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:33:16 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003