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 }