src/declarative/qml/qdeclarativexmlhttprequest.cpp
changeset 30 5dc02b23752f
child 37 758a864f9613
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "private/qdeclarativexmlhttprequest_p.h"
       
    43 
       
    44 #include "qdeclarativeengine.h"
       
    45 #include "private/qdeclarativeengine_p.h"
       
    46 #include "private/qdeclarativerefcount_p.h"
       
    47 #include "private/qdeclarativeengine_p.h"
       
    48 #include "private/qdeclarativeexpression_p.h"
       
    49 #include "qdeclarativeglobal_p.h"
       
    50 
       
    51 #include <QtCore/qobject.h>
       
    52 #include <QtScript/qscriptvalue.h>
       
    53 #include <QtScript/qscriptcontext.h>
       
    54 #include <QtScript/qscriptengine.h>
       
    55 #include <QtNetwork/qnetworkreply.h>
       
    56 #include <QtCore/qtextcodec.h>
       
    57 #include <QtCore/qxmlstream.h>
       
    58 #include <QtCore/qstack.h>
       
    59 #include <QtCore/qdebug.h>
       
    60 
       
    61 // From DOM-Level-3-Core spec
       
    62 // http://www.w3.org/TR/DOM-Level-3-Core/core.html
       
    63 #define INDEX_SIZE_ERR 1
       
    64 #define DOMSTRING_SIZE_ERR 2
       
    65 #define HIERARCHY_REQUEST_ERR 3
       
    66 #define WRONG_DOCUMENT_ERR 4
       
    67 #define INVALID_CHARACTER_ERR 5
       
    68 #define NO_DATA_ALLOWED_ERR 6
       
    69 #define NO_MODIFICATION_ALLOWED_ERR 7
       
    70 #define NOT_FOUND_ERR 8
       
    71 #define NOT_SUPPORTED_ERR 9
       
    72 #define INUSE_ATTRIBUTE_ERR 10
       
    73 #define INVALID_STATE_ERR 11
       
    74 #define SYNTAX_ERR 12
       
    75 #define INVALID_MODIFICATION_ERR 13
       
    76 #define NAMESPACE_ERR 14
       
    77 #define INVALID_ACCESS_ERR 15
       
    78 #define VALIDATION_ERR 16
       
    79 #define TYPE_MISMATCH_ERR 17
       
    80 
       
    81 #define THROW_DOM(error, desc) \
       
    82 { \
       
    83     QScriptValue errorValue = context->throwError(QLatin1String(desc)); \
       
    84     errorValue.setProperty(QLatin1String("code"), error); \
       
    85     return errorValue; \
       
    86 } 
       
    87 
       
    88 #define THROW_SYNTAX(desc) \
       
    89     return context->throwError(QScriptContext::SyntaxError, QLatin1String(desc));
       
    90 #define THROW_REFERENCE(desc) \
       
    91     return context->throwError(QScriptContext::ReferenceError, QLatin1String(desc));
       
    92 
       
    93 #define D(arg) (arg)->release()
       
    94 #define A(arg) (arg)->addref()
       
    95 
       
    96 QT_BEGIN_NAMESPACE
       
    97 
       
    98 DEFINE_BOOL_CONFIG_OPTION(xhrDump, QML_XHR_DUMP);
       
    99 
       
   100 class DocumentImpl;
       
   101 class NodeImpl 
       
   102 {
       
   103 public:
       
   104     NodeImpl() : type(Element), document(0), parent(0) {}
       
   105     virtual ~NodeImpl() { 
       
   106         for (int ii = 0; ii < children.count(); ++ii)
       
   107             delete children.at(ii);
       
   108         for (int ii = 0; ii < attributes.count(); ++ii)
       
   109             delete attributes.at(ii);
       
   110     }
       
   111 
       
   112     // These numbers are copied from the Node IDL definition
       
   113     enum Type { 
       
   114         Attr = 2, 
       
   115         CDATA = 4, 
       
   116         Comment = 8, 
       
   117         Document = 9, 
       
   118         DocumentFragment = 11, 
       
   119         DocumentType = 10,
       
   120         Element = 1, 
       
   121         Entity = 6, 
       
   122         EntityReference = 5,
       
   123         Notation = 12, 
       
   124         ProcessingInstruction = 7, 
       
   125         Text = 3
       
   126     };
       
   127     Type type;
       
   128 
       
   129     QString namespaceUri;
       
   130     QString name;
       
   131 
       
   132     QString data;
       
   133 
       
   134     void addref();
       
   135     void release();
       
   136 
       
   137     DocumentImpl *document;
       
   138     NodeImpl *parent;
       
   139 
       
   140     QList<NodeImpl *> children;
       
   141     QList<NodeImpl *> attributes;
       
   142 };
       
   143 
       
   144 class DocumentImpl : public QDeclarativeRefCount, public NodeImpl
       
   145 {
       
   146 public:
       
   147     DocumentImpl() : root(0) { type = Document; }
       
   148     virtual ~DocumentImpl() {
       
   149         if (root) delete root;
       
   150     }
       
   151 
       
   152     QString version;
       
   153     QString encoding;
       
   154     bool isStandalone;
       
   155 
       
   156     NodeImpl *root;
       
   157 
       
   158     void addref() { QDeclarativeRefCount::addref(); }
       
   159     void release() { QDeclarativeRefCount::release(); }
       
   160 };
       
   161 
       
   162 class NamedNodeMap
       
   163 {
       
   164 public:
       
   165     // JS API
       
   166     static QScriptValue length(QScriptContext *context, QScriptEngine *engine);
       
   167 
       
   168     // C++ API
       
   169     static QScriptValue prototype(QScriptEngine *);
       
   170     static QScriptValue create(QScriptEngine *, NodeImpl *, QList<NodeImpl *> *);
       
   171 
       
   172     NamedNodeMap();
       
   173     NamedNodeMap(const NamedNodeMap &);
       
   174     ~NamedNodeMap();
       
   175     bool isNull();
       
   176 
       
   177     NodeImpl *d;
       
   178     QList<NodeImpl *> *list;
       
   179 private:
       
   180     NamedNodeMap &operator=(const NamedNodeMap &);
       
   181 };
       
   182 
       
   183 class NamedNodeMapClass : public QScriptClass
       
   184 {
       
   185 public:
       
   186     NamedNodeMapClass(QScriptEngine *engine) : QScriptClass(engine) {}
       
   187 
       
   188     virtual QueryFlags queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id);
       
   189     virtual QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id);
       
   190 };
       
   191 
       
   192 class NodeList 
       
   193 {
       
   194 public:
       
   195     // JS API
       
   196     static QScriptValue length(QScriptContext *context, QScriptEngine *engine);
       
   197 
       
   198     // C++ API
       
   199     static QScriptValue prototype(QScriptEngine *);
       
   200     static QScriptValue create(QScriptEngine *, NodeImpl *);
       
   201 
       
   202     NodeList();
       
   203     NodeList(const NodeList &);
       
   204     ~NodeList();
       
   205     bool isNull();
       
   206 
       
   207     NodeImpl *d;
       
   208 private:
       
   209     NodeList &operator=(const NodeList &);
       
   210 };
       
   211 
       
   212 class NodeListClass : public QScriptClass
       
   213 {
       
   214 public:
       
   215     NodeListClass(QScriptEngine *engine) : QScriptClass(engine) {}
       
   216     virtual QueryFlags queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id);
       
   217     virtual QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id);
       
   218 };
       
   219 
       
   220 class Node
       
   221 {
       
   222 public:
       
   223     // JS API
       
   224     static QScriptValue nodeName(QScriptContext *context, QScriptEngine *engine);
       
   225     static QScriptValue nodeValue(QScriptContext *context, QScriptEngine *engine);
       
   226     static QScriptValue nodeType(QScriptContext *context, QScriptEngine *engine);
       
   227 
       
   228     static QScriptValue parentNode(QScriptContext *context, QScriptEngine *engine);
       
   229     static QScriptValue childNodes(QScriptContext *context, QScriptEngine *engine);
       
   230     static QScriptValue firstChild(QScriptContext *context, QScriptEngine *engine);
       
   231     static QScriptValue lastChild(QScriptContext *context, QScriptEngine *engine);
       
   232     static QScriptValue previousSibling(QScriptContext *context, QScriptEngine *engine);
       
   233     static QScriptValue nextSibling(QScriptContext *context, QScriptEngine *engine);
       
   234     static QScriptValue attributes(QScriptContext *context, QScriptEngine *engine);
       
   235 
       
   236     //static QScriptValue ownerDocument(QScriptContext *context, QScriptEngine *engine);
       
   237     //static QScriptValue namespaceURI(QScriptContext *context, QScriptEngine *engine);
       
   238     //static QScriptValue prefix(QScriptContext *context, QScriptEngine *engine);
       
   239     //static QScriptValue localName(QScriptContext *context, QScriptEngine *engine);
       
   240     //static QScriptValue baseURI(QScriptContext *context, QScriptEngine *engine);
       
   241     //static QScriptValue textContent(QScriptContext *context, QScriptEngine *engine);
       
   242 
       
   243     // C++ API
       
   244     static QScriptValue prototype(QScriptEngine *);
       
   245     static QScriptValue create(QScriptEngine *, NodeImpl *);
       
   246 
       
   247     Node();
       
   248     Node(const Node &o);
       
   249     ~Node();
       
   250     bool isNull() const;
       
   251 
       
   252     NodeImpl *d;
       
   253 
       
   254 private:
       
   255     Node &operator=(const Node &);
       
   256 };
       
   257 
       
   258 class Element : public Node
       
   259 {
       
   260 public:
       
   261     // C++ API
       
   262     static QScriptValue prototype(QScriptEngine *);
       
   263 };
       
   264 
       
   265 class Attr : public Node
       
   266 {
       
   267 public:
       
   268     // JS API
       
   269     static QScriptValue name(QScriptContext *context, QScriptEngine *engine);
       
   270     static QScriptValue specified(QScriptContext *context, QScriptEngine *engine);
       
   271     static QScriptValue value(QScriptContext *context, QScriptEngine *engine);
       
   272     static QScriptValue ownerElement(QScriptContext *context, QScriptEngine *engine);
       
   273     static QScriptValue schemaTypeInfo(QScriptContext *context, QScriptEngine *engine);
       
   274     static QScriptValue isId(QScriptContext *context, QScriptEngine *engine);
       
   275 
       
   276     // C++ API
       
   277     static QScriptValue prototype(QScriptEngine *);
       
   278 };
       
   279 
       
   280 class CharacterData : public Node
       
   281 {
       
   282 public:
       
   283     // JS API
       
   284     static QScriptValue length(QScriptContext *context, QScriptEngine *engine);
       
   285 
       
   286     // C++ API
       
   287     static QScriptValue prototype(QScriptEngine *);
       
   288 };
       
   289 
       
   290 class Text : public CharacterData
       
   291 {
       
   292 public:
       
   293     // JS API
       
   294     static QScriptValue isElementContentWhitespace(QScriptContext *context, QScriptEngine *engine);
       
   295     static QScriptValue wholeText(QScriptContext *context, QScriptEngine *engine);
       
   296 
       
   297     // C++ API
       
   298     static QScriptValue prototype(QScriptEngine *);
       
   299 };
       
   300 
       
   301 class CDATA : public Text
       
   302 {
       
   303 public:
       
   304     // C++ API
       
   305     static QScriptValue prototype(QScriptEngine *);
       
   306 };
       
   307 
       
   308 class Document : public Node
       
   309 {
       
   310 public:
       
   311     // JS API
       
   312     static QScriptValue xmlVersion(QScriptContext *context, QScriptEngine *engine);
       
   313     static QScriptValue xmlEncoding(QScriptContext *context, QScriptEngine *engine);
       
   314     static QScriptValue xmlStandalone(QScriptContext *context, QScriptEngine *engine);
       
   315     static QScriptValue documentElement(QScriptContext *context, QScriptEngine *engine);
       
   316 
       
   317     // C++ API
       
   318     static QScriptValue prototype(QScriptEngine *);
       
   319     static QScriptValue load(QScriptEngine *engine, const QByteArray &data);
       
   320 };
       
   321 
       
   322 QT_END_NAMESPACE
       
   323 
       
   324 Q_DECLARE_METATYPE(Node)
       
   325 Q_DECLARE_METATYPE(NodeList)
       
   326 Q_DECLARE_METATYPE(NamedNodeMap)
       
   327 
       
   328 QT_BEGIN_NAMESPACE
       
   329 
       
   330 void NodeImpl::addref() 
       
   331 {
       
   332     A(document);
       
   333 }
       
   334 
       
   335 void NodeImpl::release()
       
   336 {
       
   337     D(document);
       
   338 }
       
   339 
       
   340 QScriptValue Node::nodeName(QScriptContext *context, QScriptEngine *engine)
       
   341 {
       
   342     Node node = qscriptvalue_cast<Node>(context->thisObject());
       
   343     if (node.isNull()) return engine->undefinedValue();
       
   344 
       
   345     switch (node.d->type) {
       
   346     case NodeImpl::Document:
       
   347         return QScriptValue(QLatin1String("#document"));
       
   348     case NodeImpl::CDATA:
       
   349         return QScriptValue(QLatin1String("#cdata-section"));
       
   350     case NodeImpl::Text:
       
   351         return QScriptValue(QLatin1String("#text"));
       
   352     default:
       
   353         return QScriptValue(node.d->name);
       
   354     }
       
   355 }
       
   356 
       
   357 QScriptValue Node::nodeValue(QScriptContext *context, QScriptEngine *engine)
       
   358 {
       
   359     Node node = qscriptvalue_cast<Node>(context->thisObject());
       
   360     if (node.isNull()) return engine->undefinedValue();
       
   361 
       
   362     if (node.d->type == NodeImpl::Document ||
       
   363         node.d->type == NodeImpl::DocumentFragment ||
       
   364         node.d->type == NodeImpl::DocumentType ||
       
   365         node.d->type == NodeImpl::Element ||
       
   366         node.d->type == NodeImpl::Entity ||
       
   367         node.d->type == NodeImpl::EntityReference ||
       
   368         node.d->type == NodeImpl::Notation)
       
   369         return engine->nullValue();
       
   370 
       
   371     return QScriptValue(node.d->data);
       
   372 }
       
   373 
       
   374 QScriptValue Node::nodeType(QScriptContext *context, QScriptEngine *engine)
       
   375 {
       
   376     Node node = qscriptvalue_cast<Node>(context->thisObject());
       
   377     if (node.isNull()) return engine->undefinedValue();
       
   378     return QScriptValue(node.d->type);
       
   379 }
       
   380 
       
   381 QScriptValue Node::parentNode(QScriptContext *context, QScriptEngine *engine)
       
   382 {
       
   383     Node node = qscriptvalue_cast<Node>(context->thisObject());
       
   384     if (node.isNull()) return engine->undefinedValue();
       
   385 
       
   386     if (node.d->parent) return Node::create(engine, node.d->parent);
       
   387     else return engine->nullValue();
       
   388 }
       
   389 
       
   390 QScriptValue Node::childNodes(QScriptContext *context, QScriptEngine *engine)
       
   391 {
       
   392     Node node = qscriptvalue_cast<Node>(context->thisObject());
       
   393     if (node.isNull()) return engine->undefinedValue();
       
   394 
       
   395     return NodeList::create(engine, node.d);
       
   396 }
       
   397 
       
   398 QScriptValue Node::firstChild(QScriptContext *context, QScriptEngine *engine)
       
   399 {
       
   400     Node node = qscriptvalue_cast<Node>(context->thisObject());
       
   401     if (node.isNull()) return engine->undefinedValue();
       
   402 
       
   403     if (node.d->children.isEmpty()) return engine->nullValue();
       
   404     else return Node::create(engine, node.d->children.first());
       
   405 }
       
   406 
       
   407 QScriptValue Node::lastChild(QScriptContext *context, QScriptEngine *engine)
       
   408 {
       
   409     Node node = qscriptvalue_cast<Node>(context->thisObject());
       
   410     if (node.isNull()) return engine->undefinedValue();
       
   411 
       
   412     if (node.d->children.isEmpty()) return engine->nullValue();
       
   413     else return Node::create(engine, node.d->children.last());
       
   414 }
       
   415 
       
   416 QScriptValue Node::previousSibling(QScriptContext *context, QScriptEngine *engine)
       
   417 {
       
   418     Node node = qscriptvalue_cast<Node>(context->thisObject());
       
   419     if (node.isNull()) return engine->undefinedValue();
       
   420 
       
   421     if (!node.d->parent) return engine->nullValue();
       
   422 
       
   423     for (int ii = 0; ii < node.d->parent->children.count(); ++ii) {
       
   424         if (node.d->parent->children.at(ii) == node.d) {
       
   425             if (ii == 0) return engine->nullValue();
       
   426             else return Node::create(engine, node.d->parent->children.at(ii - 1));
       
   427         }
       
   428     }
       
   429 
       
   430     return engine->nullValue();
       
   431 }
       
   432 
       
   433 QScriptValue Node::nextSibling(QScriptContext *context, QScriptEngine *engine)
       
   434 {
       
   435     Node node = qscriptvalue_cast<Node>(context->thisObject());
       
   436     if (node.isNull()) return engine->undefinedValue();
       
   437 
       
   438     if (!node.d->parent) return engine->nullValue();
       
   439 
       
   440     for (int ii = 0; ii < node.d->parent->children.count(); ++ii) {
       
   441         if (node.d->parent->children.at(ii) == node.d) {
       
   442             if ((ii + 1) == node.d->parent->children.count()) return engine->nullValue();
       
   443             else return Node::create(engine, node.d->parent->children.at(ii + 1)); 
       
   444         }
       
   445     }
       
   446 
       
   447     return engine->nullValue();
       
   448 }
       
   449 
       
   450 QScriptValue Node::attributes(QScriptContext *context, QScriptEngine *engine)
       
   451 {
       
   452     Node node = qscriptvalue_cast<Node>(context->thisObject());
       
   453     if (node.isNull()) return engine->undefinedValue();
       
   454 
       
   455     if (node.d->type != NodeImpl::Element)
       
   456         return engine->nullValue();
       
   457     else
       
   458         return NamedNodeMap::create(engine, node.d, &node.d->attributes);
       
   459 }
       
   460 
       
   461 QScriptValue Node::prototype(QScriptEngine *engine)
       
   462 {
       
   463     QScriptValue proto = engine->newObject();
       
   464 
       
   465     proto.setProperty(QLatin1String("nodeName"), engine->newFunction(nodeName), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
   466     proto.setProperty(QLatin1String("nodeValue"), engine->newFunction(nodeValue), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
       
   467     proto.setProperty(QLatin1String("nodeType"), engine->newFunction(nodeType), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
   468     proto.setProperty(QLatin1String("parentNode"), engine->newFunction(parentNode), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
   469     proto.setProperty(QLatin1String("childNodes"), engine->newFunction(childNodes), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
   470     proto.setProperty(QLatin1String("firstChild"), engine->newFunction(firstChild), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
   471     proto.setProperty(QLatin1String("lastChild"), engine->newFunction(lastChild), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
   472     proto.setProperty(QLatin1String("previousSibling"), engine->newFunction(previousSibling), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
   473     proto.setProperty(QLatin1String("nextSibling"), engine->newFunction(nextSibling), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
   474     proto.setProperty(QLatin1String("attributes"), engine->newFunction(attributes), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
   475 
       
   476     return proto;
       
   477 }
       
   478 
       
   479 QScriptValue Node::create(QScriptEngine *engine, NodeImpl *data)
       
   480 {
       
   481     QScriptValue instance = engine->newObject();
       
   482 
       
   483     switch (data->type) {
       
   484     case NodeImpl::Attr:
       
   485         instance.setPrototype(Attr::prototype(engine));
       
   486         break;
       
   487     case NodeImpl::Comment:
       
   488     case NodeImpl::Document:
       
   489     case NodeImpl::DocumentFragment:
       
   490     case NodeImpl::DocumentType:
       
   491     case NodeImpl::Entity:
       
   492     case NodeImpl::EntityReference:
       
   493     case NodeImpl::Notation:
       
   494     case NodeImpl::ProcessingInstruction:
       
   495         return QScriptValue();
       
   496     case NodeImpl::CDATA:
       
   497         instance.setPrototype(CDATA::prototype(engine));
       
   498         break;
       
   499     case NodeImpl::Text:
       
   500         instance.setPrototype(Text::prototype(engine));
       
   501         break;
       
   502     case NodeImpl::Element:
       
   503         instance.setPrototype(Element::prototype(engine));
       
   504         break;
       
   505     }
       
   506 
       
   507     Node node;
       
   508     node.d = data;
       
   509     if (data) A(data);
       
   510 
       
   511     return engine->newVariant(instance, qVariantFromValue(node));
       
   512 }
       
   513 
       
   514 QScriptValue Element::prototype(QScriptEngine *engine)
       
   515 {
       
   516     QScriptValue proto = engine->newObject();
       
   517     proto.setPrototype(Node::prototype(engine));
       
   518 
       
   519     proto.setProperty(QLatin1String("tagName"), engine->newFunction(nodeName), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
   520 
       
   521     return proto;
       
   522 }
       
   523 
       
   524 QScriptValue Attr::prototype(QScriptEngine *engine)
       
   525 {
       
   526     QScriptValue proto = engine->newObject();
       
   527     proto.setPrototype(Node::prototype(engine));
       
   528 
       
   529     proto.setProperty(QLatin1String("name"), engine->newFunction(name), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
   530     proto.setProperty(QLatin1String("value"), engine->newFunction(value), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
   531     proto.setProperty(QLatin1String("ownerElement"), engine->newFunction(ownerElement), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
   532 
       
   533     return proto;
       
   534 }
       
   535 
       
   536 QScriptValue Attr::name(QScriptContext *context, QScriptEngine *engine)
       
   537 {
       
   538     Node node = qscriptvalue_cast<Node>(context->thisObject());
       
   539     if (node.isNull()) return engine->undefinedValue();
       
   540 
       
   541     return QScriptValue(node.d->name);
       
   542 }
       
   543 
       
   544 QScriptValue Attr::value(QScriptContext *context, QScriptEngine *engine)
       
   545 {
       
   546     Node node = qscriptvalue_cast<Node>(context->thisObject());
       
   547     if (node.isNull()) return engine->undefinedValue();
       
   548 
       
   549     return QScriptValue(node.d->data);
       
   550 }
       
   551 
       
   552 QScriptValue Attr::ownerElement(QScriptContext *context, QScriptEngine *engine)
       
   553 {
       
   554     Node node = qscriptvalue_cast<Node>(context->thisObject());
       
   555     if (node.isNull()) return engine->undefinedValue();
       
   556 
       
   557     return Node::create(engine, node.d->parent);
       
   558 }
       
   559 
       
   560 QScriptValue CharacterData::length(QScriptContext *context, QScriptEngine *engine)
       
   561 {
       
   562     Node node = qscriptvalue_cast<Node>(context->thisObject());
       
   563     if (node.isNull()) return engine->undefinedValue();
       
   564 
       
   565     return QScriptValue(node.d->data.length());
       
   566 }
       
   567 
       
   568 QScriptValue CharacterData::prototype(QScriptEngine *engine)
       
   569 {
       
   570     QScriptValue proto = engine->newObject();
       
   571     proto.setPrototype(Node::prototype(engine));
       
   572 
       
   573     proto.setProperty(QLatin1String("data"), engine->newFunction(nodeValue), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
       
   574     proto.setProperty(QLatin1String("length"), engine->newFunction(length), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
   575 
       
   576     return proto;
       
   577 }
       
   578 
       
   579 QScriptValue Text::isElementContentWhitespace(QScriptContext *context, QScriptEngine *engine)
       
   580 {
       
   581     Node node = qscriptvalue_cast<Node>(context->thisObject());
       
   582     if (node.isNull()) return engine->undefinedValue();
       
   583 
       
   584     return node.d->data.trimmed().isEmpty();
       
   585 }
       
   586 
       
   587 QScriptValue Text::wholeText(QScriptContext *context, QScriptEngine *engine)
       
   588 {
       
   589     Node node = qscriptvalue_cast<Node>(context->thisObject());
       
   590     if (node.isNull()) return engine->undefinedValue();
       
   591 
       
   592     return node.d->data;
       
   593 }
       
   594 
       
   595 QScriptValue Text::prototype(QScriptEngine *engine)
       
   596 {
       
   597     QScriptValue proto = engine->newObject();
       
   598     proto.setPrototype(CharacterData::prototype(engine));
       
   599 
       
   600     proto.setProperty(QLatin1String("isElementContentWhitespace"), engine->newFunction(isElementContentWhitespace), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
   601     proto.setProperty(QLatin1String("wholeText"), engine->newFunction(wholeText), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
   602 
       
   603     return proto;
       
   604 }
       
   605 
       
   606 QScriptValue CDATA::prototype(QScriptEngine *engine)
       
   607 {
       
   608     QScriptValue proto = engine->newObject();
       
   609     proto.setPrototype(Text::prototype(engine));
       
   610     return proto;
       
   611 }
       
   612 
       
   613 QScriptValue Document::prototype(QScriptEngine *engine)
       
   614 {
       
   615     QScriptValue proto = engine->newObject();
       
   616     proto.setPrototype(Node::prototype(engine));
       
   617 
       
   618     proto.setProperty(QLatin1String("xmlVersion"), engine->newFunction(xmlVersion), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
       
   619     proto.setProperty(QLatin1String("xmlEncoding"), engine->newFunction(xmlEncoding), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
       
   620     proto.setProperty(QLatin1String("xmlStandalone"), engine->newFunction(xmlStandalone), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
       
   621     proto.setProperty(QLatin1String("documentElement"), engine->newFunction(documentElement), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
   622 
       
   623     return proto;
       
   624 }
       
   625 
       
   626 QScriptValue Document::load(QScriptEngine *engine, const QByteArray &data)
       
   627 {
       
   628     Q_ASSERT(engine);
       
   629 
       
   630     DocumentImpl *document = 0;
       
   631     QStack<NodeImpl *> nodeStack;
       
   632 
       
   633     QXmlStreamReader reader(data);
       
   634 
       
   635     while (!reader.atEnd()) {
       
   636         switch (reader.readNext()) {
       
   637         case QXmlStreamReader::NoToken:
       
   638             break;
       
   639         case QXmlStreamReader::Invalid:
       
   640             break;
       
   641         case QXmlStreamReader::StartDocument:
       
   642             Q_ASSERT(!document);
       
   643             document = new DocumentImpl;
       
   644             document->document = document;
       
   645             document->version = reader.documentVersion().toString();
       
   646             document->encoding = reader.documentEncoding().toString();
       
   647             document->isStandalone = reader.isStandaloneDocument();
       
   648             break;
       
   649         case QXmlStreamReader::EndDocument:
       
   650             break;
       
   651         case QXmlStreamReader::StartElement: 
       
   652         {
       
   653             Q_ASSERT(document);
       
   654             NodeImpl *node = new NodeImpl;
       
   655             node->document = document;
       
   656             node->namespaceUri = reader.namespaceUri().toString();
       
   657             node->name = reader.name().toString();
       
   658             if (nodeStack.isEmpty()) {
       
   659                 document->root = node;
       
   660             } else {
       
   661                 node->parent = nodeStack.top();
       
   662                 node->parent->children.append(node);
       
   663             }
       
   664             nodeStack.append(node);
       
   665 
       
   666             foreach (const QXmlStreamAttribute &a, reader.attributes()) {
       
   667                 NodeImpl *attr = new NodeImpl;
       
   668                 attr->document = document;
       
   669                 attr->type = NodeImpl::Attr;
       
   670                 attr->namespaceUri = a.namespaceUri().toString();
       
   671                 attr->name = a.name().toString();
       
   672                 attr->data = a.value().toString();
       
   673                 attr->parent = node;
       
   674                 node->attributes.append(attr);
       
   675             }
       
   676         } 
       
   677             break;
       
   678         case QXmlStreamReader::EndElement:
       
   679             nodeStack.pop();
       
   680             break;
       
   681         case QXmlStreamReader::Characters:
       
   682         {
       
   683             NodeImpl *node = new NodeImpl;
       
   684             node->document = document;
       
   685             node->type = reader.isCDATA()?NodeImpl::CDATA:NodeImpl::Text;
       
   686             node->parent = nodeStack.top();
       
   687             node->parent->children.append(node);
       
   688             node->data = reader.text().toString();
       
   689         }
       
   690             break;
       
   691         case QXmlStreamReader::Comment:
       
   692             break;
       
   693         case QXmlStreamReader::DTD:
       
   694             break;
       
   695         case QXmlStreamReader::EntityReference:
       
   696             break;
       
   697         case QXmlStreamReader::ProcessingInstruction:
       
   698             break;
       
   699         }
       
   700     }
       
   701 
       
   702     if (!document || reader.hasError()) {
       
   703         if (document) D(document);
       
   704         return engine->nullValue();
       
   705     }
       
   706 
       
   707     QScriptValue instance = engine->newObject();
       
   708     instance.setPrototype(Document::prototype(engine));
       
   709     Node documentNode;
       
   710     documentNode.d = document;
       
   711     return engine->newVariant(instance, qVariantFromValue(documentNode));
       
   712 }
       
   713 
       
   714 Node::Node()
       
   715 : d(0)
       
   716 {
       
   717 }
       
   718 
       
   719 Node::Node(const Node &o)
       
   720 : d(o.d)
       
   721 {
       
   722     if (d) A(d);
       
   723 }
       
   724 
       
   725 Node::~Node()
       
   726 {
       
   727     if (d) D(d);
       
   728 }
       
   729 
       
   730 bool Node::isNull() const
       
   731 {
       
   732     return d == 0;
       
   733 }
       
   734 
       
   735 QScriptValue NamedNodeMap::length(QScriptContext *context, QScriptEngine *engine)
       
   736 {
       
   737     NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(context->thisObject().data());
       
   738     if (map.isNull()) return engine->undefinedValue();
       
   739 
       
   740     return QScriptValue(map.list->count());
       
   741 }
       
   742 
       
   743 QScriptValue NamedNodeMap::prototype(QScriptEngine *engine)
       
   744 {
       
   745     QScriptValue proto = engine->newObject();
       
   746 
       
   747     proto.setProperty(QLatin1String("length"), engine->newFunction(length), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
   748 
       
   749     return proto;
       
   750 }
       
   751 
       
   752 QScriptValue NamedNodeMap::create(QScriptEngine *engine, NodeImpl *data, QList<NodeImpl *> *list)
       
   753 {
       
   754     QScriptValue instance = engine->newObject();
       
   755     instance.setPrototype(NamedNodeMap::prototype(engine));
       
   756 
       
   757     NamedNodeMap map;
       
   758     map.d = data;
       
   759     map.list = list;
       
   760     if (data) A(data);
       
   761 
       
   762     instance.setData(engine->newVariant(qVariantFromValue(map)));
       
   763 
       
   764     if (!QDeclarativeScriptEngine::get(engine)->namedNodeMapClass)
       
   765         QDeclarativeScriptEngine::get(engine)->namedNodeMapClass= new NamedNodeMapClass(engine);
       
   766 
       
   767     instance.setScriptClass(QDeclarativeScriptEngine::get(engine)->namedNodeMapClass);
       
   768 
       
   769     return instance;
       
   770 }
       
   771 
       
   772 NamedNodeMap::NamedNodeMap()
       
   773 : d(0), list(0)
       
   774 {
       
   775 }
       
   776 
       
   777 NamedNodeMap::NamedNodeMap(const NamedNodeMap &o)
       
   778 : d(o.d), list(o.list)
       
   779 {
       
   780     if (d) A(d);
       
   781 }
       
   782 
       
   783 NamedNodeMap::~NamedNodeMap()
       
   784 {
       
   785     if (d) D(d);
       
   786 }
       
   787 
       
   788 bool NamedNodeMap::isNull()
       
   789 {
       
   790     return d == 0;
       
   791 }
       
   792 
       
   793 QScriptValue NodeList::length(QScriptContext *context, QScriptEngine *engine)
       
   794 {
       
   795     NodeList list = qscriptvalue_cast<NodeList>(context->thisObject().data());
       
   796     if (list.isNull()) return engine->undefinedValue();
       
   797 
       
   798     return QScriptValue(list.d->children.count());
       
   799 }
       
   800 
       
   801 QScriptValue NodeList::prototype(QScriptEngine *engine)
       
   802 {
       
   803     QScriptValue proto = engine->newObject();
       
   804 
       
   805     proto.setProperty(QLatin1String("length"), engine->newFunction(length), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
   806 
       
   807     return proto;
       
   808 }
       
   809 
       
   810 QScriptValue NodeList::create(QScriptEngine *engine, NodeImpl *data)
       
   811 {
       
   812     QScriptValue instance = engine->newObject();
       
   813     instance.setPrototype(NodeList::prototype(engine));
       
   814 
       
   815     NodeList list;
       
   816     list.d = data;
       
   817     if (data) A(data);
       
   818 
       
   819     instance.setData(engine->newVariant(qVariantFromValue(list)));
       
   820 
       
   821     if (!QDeclarativeScriptEngine::get(engine)->nodeListClass)
       
   822         QDeclarativeScriptEngine::get(engine)->nodeListClass= new NodeListClass(engine);
       
   823 
       
   824     instance.setScriptClass(QDeclarativeScriptEngine::get(engine)->nodeListClass);
       
   825 
       
   826     return instance;
       
   827 }
       
   828 
       
   829 NodeList::NodeList()
       
   830 : d(0)
       
   831 {
       
   832 }
       
   833 
       
   834 NodeList::NodeList(const NodeList &o)
       
   835 : d(o.d)
       
   836 {
       
   837     if (d) A(d);
       
   838 }
       
   839 
       
   840 NodeList::~NodeList()
       
   841 {
       
   842     if (d) D(d);
       
   843 }
       
   844 
       
   845 bool NodeList::isNull()
       
   846 {
       
   847     return d == 0;
       
   848 }
       
   849 
       
   850 NamedNodeMapClass::QueryFlags NamedNodeMapClass::queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id)
       
   851 {
       
   852     if (!(flags & HandlesReadAccess))
       
   853         return 0;
       
   854 
       
   855     NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(object.data());
       
   856     Q_ASSERT(!map.isNull());
       
   857 
       
   858     bool ok = false;
       
   859     QString nameString = name.toString();
       
   860     uint index = nameString.toUInt(&ok);
       
   861     if (ok) {
       
   862         if ((uint)map.list->count() <= index)
       
   863             return 0;
       
   864 
       
   865         *id = index;
       
   866         return HandlesReadAccess;
       
   867     } else {
       
   868         for (int ii = 0; ii < map.list->count(); ++ii) {
       
   869             if (map.list->at(ii) && map.list->at(ii)->name == nameString) {
       
   870                 *id = ii;
       
   871                 return HandlesReadAccess;
       
   872             }
       
   873         }
       
   874     }
       
   875 
       
   876     return 0;
       
   877 }
       
   878 
       
   879 QScriptValue NamedNodeMapClass::property(const QScriptValue &object, const QScriptString &, uint id)
       
   880 {
       
   881     NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(object.data());
       
   882     return Node::create(engine(), map.list->at(id));
       
   883 }
       
   884 
       
   885 NodeListClass::QueryFlags NodeListClass::queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id)
       
   886 {
       
   887     if (!(flags & HandlesReadAccess))
       
   888         return 0;
       
   889 
       
   890     bool ok = false;
       
   891     uint index = name.toString().toUInt(&ok);
       
   892     if (!ok)
       
   893         return 0;
       
   894 
       
   895     NodeList list = qscriptvalue_cast<NodeList>(object.data());
       
   896     if (list.isNull() || (uint)list.d->children.count() <= index)
       
   897         return 0; // ### I think we're meant to raise an exception
       
   898 
       
   899     *id = index;
       
   900     return HandlesReadAccess;
       
   901 }
       
   902 
       
   903 QScriptValue NodeListClass::property(const QScriptValue &object, const QScriptString &, uint id)
       
   904 {
       
   905     NodeList list = qscriptvalue_cast<NodeList>(object.data());
       
   906     return Node::create(engine(), list.d->children.at(id));
       
   907 }
       
   908 
       
   909 QScriptValue Document::documentElement(QScriptContext *context, QScriptEngine *engine)
       
   910 {
       
   911     Node document = qscriptvalue_cast<Node>(context->thisObject());
       
   912     if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
       
   913 
       
   914     return Node::create(engine, static_cast<DocumentImpl *>(document.d)->root);
       
   915 }
       
   916 
       
   917 QScriptValue Document::xmlStandalone(QScriptContext *context, QScriptEngine *engine)
       
   918 {
       
   919     Node document = qscriptvalue_cast<Node>(context->thisObject());
       
   920     if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
       
   921 
       
   922     return QScriptValue(static_cast<DocumentImpl *>(document.d)->isStandalone);
       
   923 }
       
   924 
       
   925 QScriptValue Document::xmlVersion(QScriptContext *context, QScriptEngine *engine)
       
   926 {
       
   927     Node document = qscriptvalue_cast<Node>(context->thisObject());
       
   928     if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
       
   929 
       
   930     return QScriptValue(static_cast<DocumentImpl *>(document.d)->version);
       
   931 }
       
   932 
       
   933 QScriptValue Document::xmlEncoding(QScriptContext *context, QScriptEngine *engine)
       
   934 {
       
   935     Node document = qscriptvalue_cast<Node>(context->thisObject());
       
   936     if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
       
   937 
       
   938     return QScriptValue(static_cast<DocumentImpl *>(document.d)->encoding);
       
   939 }
       
   940 
       
   941 class QDeclarativeXMLHttpRequest : public QObject
       
   942 {
       
   943 Q_OBJECT
       
   944 public:
       
   945     enum State { Unsent = 0, 
       
   946                  Opened = 1, HeadersReceived = 2,
       
   947                  Loading = 3, Done = 4 };
       
   948 
       
   949     QDeclarativeXMLHttpRequest(QNetworkAccessManager *manager);
       
   950     virtual ~QDeclarativeXMLHttpRequest();
       
   951 
       
   952     bool sendFlag() const;
       
   953     bool errorFlag() const;
       
   954     quint32 readyState() const;
       
   955     int replyStatus() const;
       
   956     QString replyStatusText() const;
       
   957 
       
   958     QScriptValue open(QScriptValue *me, const QString &, const QUrl &);
       
   959 
       
   960     void addHeader(const QString &, const QString &);
       
   961     QString header(const QString &name);
       
   962     QString headers();
       
   963     QScriptValue send(QScriptValue *me, const QByteArray &);
       
   964     QScriptValue abort(QScriptValue *me);
       
   965 
       
   966     QString responseBody() const;
       
   967     const QByteArray & rawResponseBody() const;
       
   968 private slots:
       
   969     void downloadProgress(qint64);
       
   970     void error(QNetworkReply::NetworkError);
       
   971     void finished();
       
   972 
       
   973 private:
       
   974     void requestFromUrl(const QUrl &url);
       
   975 
       
   976     State m_state;
       
   977     bool m_errorFlag;
       
   978     bool m_sendFlag;
       
   979     QString m_method;
       
   980     QUrl m_url;
       
   981     QByteArray m_responseEntityBody;
       
   982     QByteArray m_data;
       
   983     int m_redirectCount;
       
   984 
       
   985     typedef QPair<QByteArray, QByteArray> HeaderPair;
       
   986     typedef QList<HeaderPair> HeadersList;
       
   987     HeadersList m_headersList;
       
   988     void fillHeadersList();
       
   989 
       
   990     QScriptValue m_me; // Set to the data object while a send() is ongoing (to access the callback)
       
   991 
       
   992     QScriptValue dispatchCallback(QScriptValue *me);
       
   993     void printError(const QScriptValue&);
       
   994 
       
   995     int m_status;
       
   996     QString m_statusText;
       
   997     QNetworkRequest m_request;
       
   998     QDeclarativeGuard<QNetworkReply> m_network;
       
   999     void destroyNetwork();
       
  1000 
       
  1001     QNetworkAccessManager *m_nam;
       
  1002     QNetworkAccessManager *networkAccessManager() { return m_nam; }
       
  1003 };
       
  1004 
       
  1005 QDeclarativeXMLHttpRequest::QDeclarativeXMLHttpRequest(QNetworkAccessManager *manager)
       
  1006 : m_state(Unsent), m_errorFlag(false), m_sendFlag(false),
       
  1007   m_redirectCount(0), m_network(0), m_nam(manager)
       
  1008 {
       
  1009 }
       
  1010 
       
  1011 QDeclarativeXMLHttpRequest::~QDeclarativeXMLHttpRequest()
       
  1012 {
       
  1013     destroyNetwork();
       
  1014 }
       
  1015 
       
  1016 bool QDeclarativeXMLHttpRequest::sendFlag() const
       
  1017 {
       
  1018     return m_sendFlag;
       
  1019 }
       
  1020 
       
  1021 bool QDeclarativeXMLHttpRequest::errorFlag() const
       
  1022 {
       
  1023     return m_errorFlag;
       
  1024 }
       
  1025 
       
  1026 quint32 QDeclarativeXMLHttpRequest::readyState() const
       
  1027 {
       
  1028     return m_state;
       
  1029 }
       
  1030 
       
  1031 int QDeclarativeXMLHttpRequest::replyStatus() const
       
  1032 {
       
  1033     return m_status;
       
  1034 }
       
  1035 
       
  1036 QString QDeclarativeXMLHttpRequest::replyStatusText() const
       
  1037 {
       
  1038     return m_statusText;
       
  1039 }
       
  1040 
       
  1041 QScriptValue QDeclarativeXMLHttpRequest::open(QScriptValue *me, const QString &method, const QUrl &url)
       
  1042 {
       
  1043     destroyNetwork();
       
  1044     m_sendFlag = false;
       
  1045     m_errorFlag = false;
       
  1046     m_responseEntityBody = QByteArray();
       
  1047     m_method = method;
       
  1048     m_url = url;
       
  1049     m_state = Opened;
       
  1050     return dispatchCallback(me);
       
  1051 }
       
  1052 
       
  1053 void QDeclarativeXMLHttpRequest::addHeader(const QString &name, const QString &value)
       
  1054 {
       
  1055     QByteArray utfname = name.toUtf8();
       
  1056 
       
  1057     if (m_request.hasRawHeader(utfname)) {
       
  1058         m_request.setRawHeader(utfname, m_request.rawHeader(utfname) + ',' + value.toUtf8());
       
  1059     } else {
       
  1060         m_request.setRawHeader(utfname, value.toUtf8());
       
  1061     }
       
  1062 }
       
  1063 
       
  1064 QString QDeclarativeXMLHttpRequest::header(const QString &name)
       
  1065 {
       
  1066     QByteArray utfname = name.toLower().toUtf8();
       
  1067 
       
  1068     foreach (const HeaderPair &header, m_headersList) {
       
  1069         if (header.first == utfname)
       
  1070             return QString::fromUtf8(header.second);
       
  1071     }
       
  1072     return QString();
       
  1073 }
       
  1074 
       
  1075 QString QDeclarativeXMLHttpRequest::headers()
       
  1076 {
       
  1077     QString ret;
       
  1078 
       
  1079     foreach (const HeaderPair &header, m_headersList) {
       
  1080         if (ret.length())
       
  1081             ret.append(QString::fromUtf8("\r\n"));
       
  1082         ret.append(QString::fromUtf8(header.first));
       
  1083         ret.append(QString::fromUtf8(": "));
       
  1084         ret.append(QString::fromUtf8(header.second));
       
  1085     }
       
  1086     return ret;
       
  1087 }
       
  1088 
       
  1089 void QDeclarativeXMLHttpRequest::fillHeadersList()
       
  1090 {
       
  1091     QList<QByteArray> headerList = m_network->rawHeaderList();
       
  1092 
       
  1093     m_headersList.clear();
       
  1094     foreach (const QByteArray &header, headerList) {
       
  1095         HeaderPair pair (header.toLower(), m_network->rawHeader(header));
       
  1096 	if (pair.first == "set-cookie" ||
       
  1097 	    pair.first == "set-cookie2") 
       
  1098 	    continue;
       
  1099 
       
  1100         m_headersList << pair;
       
  1101     }
       
  1102 }
       
  1103 
       
  1104 void QDeclarativeXMLHttpRequest::requestFromUrl(const QUrl &url)
       
  1105 {
       
  1106     QNetworkRequest request = m_request;
       
  1107     request.setUrl(url);
       
  1108     if(m_method == QLatin1String("POST") ||
       
  1109        m_method == QLatin1String("PUT")) {
       
  1110         QVariant var = request.header(QNetworkRequest::ContentTypeHeader);
       
  1111         if (var.isValid()) {
       
  1112             QString str = var.toString();
       
  1113             int charsetIdx = str.indexOf(QLatin1String("charset="));
       
  1114             if (charsetIdx == -1) {
       
  1115                 // No charset - append
       
  1116                 if (!str.isEmpty()) str.append(QLatin1Char(';'));
       
  1117                 str.append(QLatin1String("charset=UTF-8"));
       
  1118             } else {
       
  1119                 charsetIdx += 8;
       
  1120                 int n = 0;
       
  1121                 int semiColon = str.indexOf(QLatin1Char(';'), charsetIdx);
       
  1122                 if (semiColon == -1) {
       
  1123                     n = str.length() - charsetIdx;
       
  1124                 } else {
       
  1125                     n = semiColon - charsetIdx;
       
  1126                 }
       
  1127 
       
  1128                 str.replace(charsetIdx, n, QLatin1String("UTF-8"));
       
  1129             }
       
  1130             request.setHeader(QNetworkRequest::ContentTypeHeader, str);
       
  1131         } else {
       
  1132             request.setHeader(QNetworkRequest::ContentTypeHeader, 
       
  1133                               QLatin1String("text/plain;charset=UTF-8"));
       
  1134         }
       
  1135     }
       
  1136 
       
  1137     if (xhrDump()) {
       
  1138         qWarning().nospace() << "XMLHttpRequest: " << qPrintable(m_method) << " " << qPrintable(url.toString());
       
  1139         if (!m_data.isEmpty()) {
       
  1140             qWarning().nospace() << "                " 
       
  1141                                  << qPrintable(QString::fromUtf8(m_data));
       
  1142         }
       
  1143     }
       
  1144 
       
  1145     if (m_method == QLatin1String("GET"))
       
  1146         m_network = networkAccessManager()->get(request);
       
  1147     else if (m_method == QLatin1String("HEAD"))
       
  1148         m_network = networkAccessManager()->head(request);
       
  1149     else if(m_method == QLatin1String("POST"))
       
  1150         m_network = networkAccessManager()->post(request, m_data);
       
  1151     else if(m_method == QLatin1String("PUT"))
       
  1152         m_network = networkAccessManager()->put(request, m_data);
       
  1153 
       
  1154     QObject::connect(m_network, SIGNAL(downloadProgress(qint64,qint64)), 
       
  1155                      this, SLOT(downloadProgress(qint64)));
       
  1156     QObject::connect(m_network, SIGNAL(error(QNetworkReply::NetworkError)),
       
  1157                      this, SLOT(error(QNetworkReply::NetworkError)));
       
  1158     QObject::connect(m_network, SIGNAL(finished()),
       
  1159                      this, SLOT(finished()));
       
  1160 }
       
  1161 
       
  1162 QScriptValue QDeclarativeXMLHttpRequest::send(QScriptValue *me, const QByteArray &data)
       
  1163 {
       
  1164     m_errorFlag = false;
       
  1165     m_sendFlag = true;
       
  1166     m_redirectCount = 0;
       
  1167     m_data = data;
       
  1168     m_me = *me;
       
  1169 
       
  1170     requestFromUrl(m_url);
       
  1171 
       
  1172     return QScriptValue();
       
  1173 }
       
  1174 
       
  1175 QScriptValue QDeclarativeXMLHttpRequest::abort(QScriptValue *me)
       
  1176 {
       
  1177     destroyNetwork();
       
  1178     m_responseEntityBody = QByteArray();
       
  1179     m_errorFlag = true;
       
  1180     m_request = QNetworkRequest();
       
  1181 
       
  1182     if (!(m_state == Unsent || 
       
  1183           (m_state == Opened && !m_sendFlag) ||
       
  1184           m_state == Done)) {
       
  1185 
       
  1186         m_state = Done;
       
  1187         m_sendFlag = false;
       
  1188         QScriptValue cbv = dispatchCallback(me);
       
  1189         if (cbv.isError()) return cbv;
       
  1190     }
       
  1191 
       
  1192     m_state = Unsent;
       
  1193     return QScriptValue();
       
  1194 }
       
  1195 
       
  1196 void QDeclarativeXMLHttpRequest::downloadProgress(qint64 bytes)
       
  1197 {
       
  1198     Q_UNUSED(bytes)
       
  1199     m_status = 
       
  1200         m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
       
  1201     m_statusText =
       
  1202         QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray());
       
  1203 
       
  1204     // ### We assume if this is called the headers are now available
       
  1205     if (m_state < HeadersReceived) {
       
  1206         m_state = HeadersReceived;
       
  1207         fillHeadersList ();
       
  1208         QScriptValue cbv = dispatchCallback(&m_me);
       
  1209         if (cbv.isError()) printError(cbv);
       
  1210     }
       
  1211 
       
  1212     bool wasEmpty = m_responseEntityBody.isEmpty();
       
  1213     m_responseEntityBody.append(m_network->readAll());
       
  1214     if (wasEmpty && !m_responseEntityBody.isEmpty()) {
       
  1215         m_state = Loading;
       
  1216         QScriptValue cbv = dispatchCallback(&m_me);
       
  1217         if (cbv.isError()) printError(cbv);
       
  1218     }
       
  1219 }
       
  1220 
       
  1221 void QDeclarativeXMLHttpRequest::error(QNetworkReply::NetworkError error)
       
  1222 {
       
  1223     Q_UNUSED(error)
       
  1224     m_status =
       
  1225         m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
       
  1226     m_statusText =
       
  1227         QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray());
       
  1228 
       
  1229     m_responseEntityBody = QByteArray();
       
  1230 
       
  1231     m_request = QNetworkRequest();
       
  1232     m_data.clear();
       
  1233     destroyNetwork();
       
  1234 
       
  1235     if (error == QNetworkReply::ContentAccessDenied ||
       
  1236         error == QNetworkReply::ContentOperationNotPermittedError ||
       
  1237         error == QNetworkReply::ContentNotFoundError ||
       
  1238         error == QNetworkReply::AuthenticationRequiredError ||
       
  1239         error == QNetworkReply::ContentReSendError) {
       
  1240         m_state = Loading;
       
  1241         QScriptValue cbv = dispatchCallback(&m_me);
       
  1242         if (cbv.isError()) printError(cbv);
       
  1243     } else {
       
  1244         m_errorFlag = true;
       
  1245     } 
       
  1246 
       
  1247     m_state = Done;
       
  1248     QScriptValue cbv = dispatchCallback(&m_me);
       
  1249     if (cbv.isError()) printError(cbv);
       
  1250 }
       
  1251 
       
  1252 #define XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION 15
       
  1253 void QDeclarativeXMLHttpRequest::finished()
       
  1254 {
       
  1255     m_redirectCount++;
       
  1256     if (m_redirectCount < XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION) {
       
  1257         QVariant redirect = m_network->attribute(QNetworkRequest::RedirectionTargetAttribute);
       
  1258         if (redirect.isValid()) {
       
  1259             QUrl url = m_network->url().resolved(redirect.toUrl());
       
  1260             destroyNetwork();
       
  1261             requestFromUrl(url);
       
  1262             return;
       
  1263         }
       
  1264     }
       
  1265 
       
  1266     m_status =
       
  1267         m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
       
  1268     m_statusText =
       
  1269         QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray());
       
  1270 
       
  1271     if (m_state < HeadersReceived) {
       
  1272         m_state = HeadersReceived;
       
  1273         fillHeadersList ();
       
  1274         QScriptValue cbv = dispatchCallback(&m_me);
       
  1275         if (cbv.isError()) printError(cbv);
       
  1276     }
       
  1277     m_responseEntityBody.append(m_network->readAll());
       
  1278 
       
  1279     if (xhrDump()) {
       
  1280         qWarning().nospace() << "XMLHttpRequest: RESPONSE " << qPrintable(m_url.toString());
       
  1281         if (!m_responseEntityBody.isEmpty()) {
       
  1282             qWarning().nospace() << "                " 
       
  1283                                  << qPrintable(QString::fromUtf8(m_responseEntityBody));
       
  1284         }
       
  1285     }
       
  1286 
       
  1287 
       
  1288     m_data.clear();
       
  1289     destroyNetwork();
       
  1290     if (m_state < Loading) {
       
  1291         m_state = Loading;
       
  1292         QScriptValue cbv = dispatchCallback(&m_me);
       
  1293         if (cbv.isError()) printError(cbv);
       
  1294     }
       
  1295     m_state = Done;
       
  1296     QScriptValue cbv = dispatchCallback(&m_me);
       
  1297     if (cbv.isError()) printError(cbv);
       
  1298 
       
  1299     m_me = QScriptValue();
       
  1300 }
       
  1301 
       
  1302 
       
  1303 QString QDeclarativeXMLHttpRequest::responseBody() const
       
  1304 {
       
  1305     QXmlStreamReader reader(m_responseEntityBody);
       
  1306     reader.readNext();
       
  1307     QTextCodec *codec = QTextCodec::codecForName(reader.documentEncoding().toString().toUtf8());
       
  1308     if (codec)
       
  1309         return codec->toUnicode(m_responseEntityBody);
       
  1310 
       
  1311     return QString::fromUtf8(m_responseEntityBody);
       
  1312 }
       
  1313 
       
  1314 const QByteArray &QDeclarativeXMLHttpRequest::rawResponseBody() const
       
  1315 {
       
  1316     return m_responseEntityBody;
       
  1317 }
       
  1318 
       
  1319 QScriptValue QDeclarativeXMLHttpRequest::dispatchCallback(QScriptValue *me)
       
  1320 {
       
  1321     QScriptValue v = me->property(QLatin1String("callback"));
       
  1322     return v.call();
       
  1323 }
       
  1324 
       
  1325 void QDeclarativeXMLHttpRequest::printError(const QScriptValue& sv)
       
  1326 {
       
  1327     QDeclarativeError error;
       
  1328     QDeclarativeExpressionPrivate::exceptionToError(sv.engine(), error);
       
  1329     QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate::get(sv.engine()), error);
       
  1330 }
       
  1331 
       
  1332 void QDeclarativeXMLHttpRequest::destroyNetwork()
       
  1333 {
       
  1334     if (m_network) {
       
  1335         m_network->disconnect();
       
  1336         m_network->deleteLater();
       
  1337         m_network = 0;
       
  1338     }
       
  1339 }
       
  1340 
       
  1341 // XMLHttpRequest methods
       
  1342 static QScriptValue qmlxmlhttprequest_open(QScriptContext *context, QScriptEngine *engine)
       
  1343 {
       
  1344     QScriptValue dataObject = context->thisObject().data();
       
  1345     QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(dataObject.toQObject());
       
  1346     if (!request) 
       
  1347         THROW_REFERENCE("Not an XMLHttpRequest object");
       
  1348 
       
  1349     if (context->argumentCount() < 2 || context->argumentCount() > 5)
       
  1350         THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
       
  1351 
       
  1352     // Argument 0 - Method
       
  1353     QString method = context->argument(0).toString().toUpper();
       
  1354     if (method != QLatin1String("GET") && 
       
  1355         method != QLatin1String("PUT") &&
       
  1356         method != QLatin1String("HEAD") &&
       
  1357         method != QLatin1String("POST"))
       
  1358         THROW_DOM(SYNTAX_ERR, "Unsupported HTTP method type");
       
  1359 
       
  1360 
       
  1361     // Argument 1 - URL
       
  1362     QUrl url = QUrl::fromEncoded(context->argument(1).toString().toUtf8());
       
  1363 
       
  1364     if (url.isRelative()) {
       
  1365         url = QDeclarativeScriptEngine::get(engine)->resolvedUrl(context,url);
       
  1366     }
       
  1367 
       
  1368     // Argument 2 - async (optional)
       
  1369     if (context->argumentCount() > 2 && !context->argument(2).toBoolean())
       
  1370         THROW_DOM(NOT_SUPPORTED_ERR, "Synchronous XMLHttpRequest calls are not supported");
       
  1371 
       
  1372 
       
  1373     // Argument 3/4 - user/pass (optional)
       
  1374     QString username, password;
       
  1375     if (context->argumentCount() > 3)
       
  1376         username = context->argument(3).toString();
       
  1377     if (context->argumentCount() > 4)
       
  1378         password = context->argument(4).toString();
       
  1379 
       
  1380 
       
  1381     // Clear the fragment (if any)
       
  1382     url.setFragment(QString());
       
  1383     // Set username/password
       
  1384     if (!username.isNull()) url.setUserName(username);
       
  1385     if (!password.isNull()) url.setPassword(password);
       
  1386 
       
  1387     return request->open(&dataObject, method, url);
       
  1388 }
       
  1389 
       
  1390 static QScriptValue qmlxmlhttprequest_setRequestHeader(QScriptContext *context, QScriptEngine *engine)
       
  1391 {
       
  1392     QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
       
  1393     if (!request) 
       
  1394         THROW_REFERENCE("Not an XMLHttpRequest object");
       
  1395 
       
  1396     if (context->argumentCount() != 2)
       
  1397         THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
       
  1398 
       
  1399 
       
  1400     if (request->readyState() != QDeclarativeXMLHttpRequest::Opened ||
       
  1401         request->sendFlag())
       
  1402         THROW_DOM(INVALID_STATE_ERR, "Invalid state");
       
  1403 
       
  1404 
       
  1405     QString name = context->argument(0).toString();
       
  1406     QString value = context->argument(1).toString();
       
  1407 
       
  1408     // ### Check that name and value are well formed
       
  1409 
       
  1410     QString nameUpper = name.toUpper();
       
  1411     if (nameUpper == QLatin1String("ACCEPT-CHARSET") ||
       
  1412         nameUpper == QLatin1String("ACCEPT-ENCODING") ||
       
  1413         nameUpper == QLatin1String("CONNECTION") ||
       
  1414         nameUpper == QLatin1String("CONTENT-LENGTH") ||
       
  1415         nameUpper == QLatin1String("COOKIE") ||
       
  1416         nameUpper == QLatin1String("COOKIE2") ||
       
  1417         nameUpper == QLatin1String("CONTENT-TRANSFER-ENCODING") ||
       
  1418         nameUpper == QLatin1String("DATE") ||
       
  1419         nameUpper == QLatin1String("EXPECT") ||
       
  1420         nameUpper == QLatin1String("HOST") ||
       
  1421         nameUpper == QLatin1String("KEEP-ALIVE") ||
       
  1422         nameUpper == QLatin1String("REFERER") ||
       
  1423         nameUpper == QLatin1String("TE") ||
       
  1424         nameUpper == QLatin1String("TRAILER") ||
       
  1425         nameUpper == QLatin1String("TRANSFER-ENCODING") ||
       
  1426         nameUpper == QLatin1String("UPGRADE") ||
       
  1427         nameUpper == QLatin1String("USER-AGENT") ||
       
  1428         nameUpper == QLatin1String("VIA") ||
       
  1429         nameUpper.startsWith(QLatin1String("PROXY-")) ||
       
  1430         nameUpper.startsWith(QLatin1String("SEC-"))) 
       
  1431         return engine->undefinedValue();
       
  1432 
       
  1433     request->addHeader(nameUpper, value);
       
  1434 
       
  1435     return engine->undefinedValue();
       
  1436 }
       
  1437 
       
  1438 static QScriptValue qmlxmlhttprequest_send(QScriptContext *context, QScriptEngine *)
       
  1439 {
       
  1440     QScriptValue dataObject = context->thisObject().data();
       
  1441     QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(dataObject.toQObject());
       
  1442     if (!request) 
       
  1443         THROW_REFERENCE("Not an XMLHttpRequest object");
       
  1444 
       
  1445     if (request->readyState() != QDeclarativeXMLHttpRequest::Opened)
       
  1446         THROW_DOM(INVALID_STATE_ERR, "Invalid state");
       
  1447 
       
  1448     if (request->sendFlag())
       
  1449         THROW_DOM(INVALID_STATE_ERR, "Invalid state");
       
  1450 
       
  1451     QByteArray data;
       
  1452     if (context->argumentCount() > 0)
       
  1453         data = context->argument(0).toString().toUtf8();
       
  1454 
       
  1455     return request->send(&dataObject, data);
       
  1456 }
       
  1457 
       
  1458 static QScriptValue qmlxmlhttprequest_abort(QScriptContext *context, QScriptEngine *)
       
  1459 {
       
  1460     QScriptValue dataObject = context->thisObject().data();
       
  1461     QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(dataObject.toQObject());
       
  1462     if (!request) 
       
  1463         THROW_REFERENCE("Not an XMLHttpRequest object");
       
  1464 
       
  1465     return request->abort(&dataObject);
       
  1466 }
       
  1467 
       
  1468 static QScriptValue qmlxmlhttprequest_getResponseHeader(QScriptContext *context, QScriptEngine *engine)
       
  1469 {
       
  1470     Q_UNUSED(engine)
       
  1471     QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
       
  1472     if (!request) 
       
  1473         THROW_REFERENCE("Not an XMLHttpRequest object");
       
  1474 
       
  1475     if (context->argumentCount() != 1)
       
  1476         THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
       
  1477 
       
  1478     if (request->readyState() != QDeclarativeXMLHttpRequest::Loading &&
       
  1479         request->readyState() != QDeclarativeXMLHttpRequest::Done &&
       
  1480         request->readyState() != QDeclarativeXMLHttpRequest::HeadersReceived)
       
  1481         THROW_DOM(INVALID_STATE_ERR, "Invalid state");
       
  1482 
       
  1483     QString headerName = context->argument(0).toString();
       
  1484 
       
  1485     return QScriptValue(request->header(headerName));
       
  1486 }
       
  1487 
       
  1488 static QScriptValue qmlxmlhttprequest_getAllResponseHeaders(QScriptContext *context, QScriptEngine *engine)
       
  1489 {
       
  1490     Q_UNUSED(engine)
       
  1491     QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
       
  1492     if (!request) 
       
  1493         THROW_REFERENCE("Not an XMLHttpRequest object");
       
  1494 
       
  1495     if (context->argumentCount() != 0)
       
  1496         THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
       
  1497 
       
  1498     if (request->readyState() != QDeclarativeXMLHttpRequest::Loading &&
       
  1499         request->readyState() != QDeclarativeXMLHttpRequest::Done &&
       
  1500         request->readyState() != QDeclarativeXMLHttpRequest::HeadersReceived)
       
  1501         THROW_DOM(INVALID_STATE_ERR, "Invalid state");
       
  1502 
       
  1503     return QScriptValue(request->headers());
       
  1504 }
       
  1505 
       
  1506 // XMLHttpRequest properties
       
  1507 static QScriptValue qmlxmlhttprequest_readyState(QScriptContext *context, QScriptEngine *engine)
       
  1508 {
       
  1509     Q_UNUSED(engine)
       
  1510     QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
       
  1511     if (!request) 
       
  1512         THROW_REFERENCE("Not an XMLHttpRequest object");
       
  1513 
       
  1514     return QScriptValue(request->readyState());
       
  1515 }
       
  1516 
       
  1517 static QScriptValue qmlxmlhttprequest_status(QScriptContext *context, QScriptEngine *engine)
       
  1518 {
       
  1519     Q_UNUSED(engine)
       
  1520     QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
       
  1521     if (!request) 
       
  1522         THROW_REFERENCE("Not an XMLHttpRequest object");
       
  1523 
       
  1524     if (request->readyState() == QDeclarativeXMLHttpRequest::Unsent ||
       
  1525         request->readyState() == QDeclarativeXMLHttpRequest::Opened)
       
  1526         THROW_DOM(INVALID_STATE_ERR, "Invalid state");
       
  1527 
       
  1528     if (request->errorFlag())
       
  1529         return QScriptValue(0);
       
  1530     else
       
  1531         return QScriptValue(request->replyStatus());
       
  1532 }
       
  1533 
       
  1534 static QScriptValue qmlxmlhttprequest_statusText(QScriptContext *context, QScriptEngine *engine)
       
  1535 {
       
  1536     Q_UNUSED(engine)
       
  1537     QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
       
  1538     if (!request) 
       
  1539         THROW_REFERENCE("Not an XMLHttpRequest object");
       
  1540 
       
  1541     if (request->readyState() == QDeclarativeXMLHttpRequest::Unsent ||
       
  1542         request->readyState() == QDeclarativeXMLHttpRequest::Opened)
       
  1543         THROW_DOM(INVALID_STATE_ERR, "Invalid state");
       
  1544 
       
  1545     if (request->errorFlag())
       
  1546         return QScriptValue(0);
       
  1547     else
       
  1548         return QScriptValue(request->replyStatusText());
       
  1549 }
       
  1550 
       
  1551 static QScriptValue qmlxmlhttprequest_responseText(QScriptContext *context, QScriptEngine *engine)
       
  1552 {
       
  1553     Q_UNUSED(engine)
       
  1554     QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
       
  1555     if (!request) 
       
  1556         THROW_REFERENCE("Not an XMLHttpRequest object");
       
  1557 
       
  1558     if (request->readyState() != QDeclarativeXMLHttpRequest::Loading &&
       
  1559         request->readyState() != QDeclarativeXMLHttpRequest::Done)
       
  1560         return QScriptValue(QString());
       
  1561     else 
       
  1562         return QScriptValue(request->responseBody());
       
  1563 }
       
  1564 
       
  1565 static QScriptValue qmlxmlhttprequest_responseXML(QScriptContext *context, QScriptEngine *engine)
       
  1566 {
       
  1567     QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
       
  1568     if (!request) 
       
  1569         THROW_REFERENCE("Not an XMLHttpRequest object");
       
  1570 
       
  1571     if (request->readyState() != QDeclarativeXMLHttpRequest::Loading &&
       
  1572         request->readyState() != QDeclarativeXMLHttpRequest::Done)
       
  1573         return engine->nullValue();
       
  1574     else  
       
  1575         return Document::load(engine, request->rawResponseBody());
       
  1576 }
       
  1577 
       
  1578 static QScriptValue qmlxmlhttprequest_onreadystatechange(QScriptContext *context, QScriptEngine *engine)
       
  1579 {
       
  1580     Q_UNUSED(engine);
       
  1581     QScriptValue dataObject = context->thisObject().data();
       
  1582     QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(dataObject.toQObject());
       
  1583     if (!request) 
       
  1584         THROW_REFERENCE("Not an XMLHttpRequest object");
       
  1585 
       
  1586     if (context->argumentCount()) {
       
  1587         QScriptValue v = context->argument(0);
       
  1588         dataObject.setProperty(QLatin1String("callback"), v);
       
  1589         return v;
       
  1590     } else {
       
  1591         return dataObject.property(QLatin1String("callback"));
       
  1592     }
       
  1593 }
       
  1594 
       
  1595 // Constructor
       
  1596 static QScriptValue qmlxmlhttprequest_new(QScriptContext *context, QScriptEngine *engine)
       
  1597 {
       
  1598     if (context->isCalledAsConstructor()) {
       
  1599         context->thisObject().setData(engine->newQObject(new QDeclarativeXMLHttpRequest(QDeclarativeScriptEngine::get(engine)->networkAccessManager()), QScriptEngine::ScriptOwnership));
       
  1600     }
       
  1601     return engine->undefinedValue();
       
  1602 }
       
  1603 
       
  1604 void qt_add_qmlxmlhttprequest(QScriptEngine *engine)
       
  1605 {
       
  1606     QScriptValue prototype = engine->newObject();
       
  1607 
       
  1608     // Methods
       
  1609     prototype.setProperty(QLatin1String("open"), engine->newFunction(qmlxmlhttprequest_open, 2));
       
  1610     prototype.setProperty(QLatin1String("setRequestHeader"), engine->newFunction(qmlxmlhttprequest_setRequestHeader, 2));
       
  1611     prototype.setProperty(QLatin1String("send"), engine->newFunction(qmlxmlhttprequest_send));
       
  1612     prototype.setProperty(QLatin1String("abort"), engine->newFunction(qmlxmlhttprequest_abort));
       
  1613     prototype.setProperty(QLatin1String("getResponseHeader"), engine->newFunction(qmlxmlhttprequest_getResponseHeader, 1));
       
  1614     prototype.setProperty(QLatin1String("getAllResponseHeaders"), engine->newFunction(qmlxmlhttprequest_getAllResponseHeaders));
       
  1615 
       
  1616     // Read-only properties
       
  1617     prototype.setProperty(QLatin1String("readyState"), engine->newFunction(qmlxmlhttprequest_readyState), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
  1618     prototype.setProperty(QLatin1String("status"), engine->newFunction(qmlxmlhttprequest_status), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
  1619     prototype.setProperty(QLatin1String("statusText"), engine->newFunction(qmlxmlhttprequest_statusText), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
  1620     prototype.setProperty(QLatin1String("responseText"), engine->newFunction(qmlxmlhttprequest_responseText), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
  1621     prototype.setProperty(QLatin1String("responseXML"), engine->newFunction(qmlxmlhttprequest_responseXML), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
       
  1622     prototype.setProperty(QLatin1String("onreadystatechange"), engine->newFunction(qmlxmlhttprequest_onreadystatechange), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
       
  1623 
       
  1624     // State values
       
  1625     prototype.setProperty(QLatin1String("UNSENT"), 0, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1626     prototype.setProperty(QLatin1String("OPENED"), 1, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1627     prototype.setProperty(QLatin1String("HEADERS_RECEIVED"), 2, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1628     prototype.setProperty(QLatin1String("LOADING"), 3, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1629     prototype.setProperty(QLatin1String("DONE"), 4, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1630 
       
  1631     // Constructor
       
  1632     QScriptValue constructor = engine->newFunction(qmlxmlhttprequest_new, prototype);
       
  1633     constructor.setProperty(QLatin1String("UNSENT"), 0, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1634     constructor.setProperty(QLatin1String("OPENED"), 1, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1635     constructor.setProperty(QLatin1String("HEADERS_RECEIVED"), 2, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1636     constructor.setProperty(QLatin1String("LOADING"), 3, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1637     constructor.setProperty(QLatin1String("DONE"), 4, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1638     engine->globalObject().setProperty(QLatin1String("XMLHttpRequest"), constructor);
       
  1639 
       
  1640     // DOM Exception
       
  1641     QScriptValue domExceptionPrototype = engine->newObject();
       
  1642     domExceptionPrototype.setProperty(QLatin1String("INDEX_SIZE_ERR"), INDEX_SIZE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1643     domExceptionPrototype.setProperty(QLatin1String("DOMSTRING_SIZE_ERR"), DOMSTRING_SIZE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1644     domExceptionPrototype.setProperty(QLatin1String("HIERARCHY_REQUEST_ERR"), HIERARCHY_REQUEST_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1645     domExceptionPrototype.setProperty(QLatin1String("WRONG_DOCUMENT_ERR"), WRONG_DOCUMENT_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1646     domExceptionPrototype.setProperty(QLatin1String("INVALID_CHARACTER_ERR"), INVALID_CHARACTER_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1647     domExceptionPrototype.setProperty(QLatin1String("NO_DATA_ALLOWED_ERR"), NO_DATA_ALLOWED_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1648     domExceptionPrototype.setProperty(QLatin1String("NO_MODIFICATION_ALLOWED_ERR"), NO_MODIFICATION_ALLOWED_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1649     domExceptionPrototype.setProperty(QLatin1String("NOT_FOUND_ERR"), NOT_FOUND_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1650     domExceptionPrototype.setProperty(QLatin1String("NOT_SUPPORTED_ERR"), NOT_SUPPORTED_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1651     domExceptionPrototype.setProperty(QLatin1String("INUSE_ATTRIBUTE_ERR"), INUSE_ATTRIBUTE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1652     domExceptionPrototype.setProperty(QLatin1String("INVALID_STATE_ERR"), INVALID_STATE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1653     domExceptionPrototype.setProperty(QLatin1String("SYNTAX_ERR"), SYNTAX_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1654     domExceptionPrototype.setProperty(QLatin1String("INVALID_MODIFICATION_ERR"), INVALID_MODIFICATION_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1655     domExceptionPrototype.setProperty(QLatin1String("NAMESPACE_ERR"), NAMESPACE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1656     domExceptionPrototype.setProperty(QLatin1String("INVALID_ACCESS_ERR"), INVALID_ACCESS_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1657     domExceptionPrototype.setProperty(QLatin1String("VALIDATION_ERR"), VALIDATION_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1658     domExceptionPrototype.setProperty(QLatin1String("TYPE_MISMATCH_ERR"), TYPE_MISMATCH_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
       
  1659 
       
  1660     engine->globalObject().setProperty(QLatin1String("DOMException"), domExceptionPrototype);
       
  1661 }
       
  1662 
       
  1663 QT_END_NAMESPACE
       
  1664 
       
  1665 #include <qdeclarativexmlhttprequest.moc>