00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00039
00040
00041
00042
00043
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
00054
00055
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
00110
00111
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 = (
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
00208 id == DOM::EventImpl::KEYDOWN_EVENT || id == DOM::EventImpl::KHTML_KEYPRESS_EVENT ||
00209 id == DOM::EventImpl::KEYUP_EVENT ||
00210
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
00217 {
00218 if ( m_inlineCode && !m_timerCallback )
00219 {
00220
00221 return true;
00222 kdDebug(6070) << "Window.open, smart policy, no event, inline code -> ok" << endl;
00223 }
00224 else
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
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
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
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 }