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