1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
42 #include "private/qdeclarativexmlhttprequest_p.h"
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"
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>
61 #include <QtCore/QStringBuilder>
63 #ifndef QT_NO_XMLSTREAMREADER
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
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
85 #define THROW_DOM(error, desc) \
87 QScriptValue errorValue = context->throwError(QLatin1String(desc)); \
88 errorValue.setProperty(QLatin1String("code"), error); \
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));
97 #define D(arg) (arg)->release()
98 #define A(arg) (arg)->addref()
102 DEFINE_BOOL_CONFIG_OPTION(xhrDump, QML_XHR_DUMP);
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);
118 // These numbers are copied from the Node IDL definition
124 DocumentFragment = 11,
130 ProcessingInstruction = 7,
135 QString namespaceUri;
143 DocumentImpl *document;
146 QList<NodeImpl *> children;
147 QList<NodeImpl *> attributes;
150 class DocumentImpl : public QDeclarativeRefCount, public NodeImpl
153 DocumentImpl() : root(0) { type = Document; }
154 virtual ~DocumentImpl() {
155 if (root) delete root;
164 void addref() { QDeclarativeRefCount::addref(); }
165 void release() { QDeclarativeRefCount::release(); }
172 static QScriptValue length(QScriptContext *context, QScriptEngine *engine);
175 static QScriptValue prototype(QScriptEngine *);
176 static QScriptValue create(QScriptEngine *, NodeImpl *, QList<NodeImpl *> *);
179 NamedNodeMap(const NamedNodeMap &);
184 QList<NodeImpl *> *list;
186 NamedNodeMap &operator=(const NamedNodeMap &);
189 class NamedNodeMapClass : public QScriptClass
192 NamedNodeMapClass(QScriptEngine *engine) : QScriptClass(engine) {}
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);
202 static QScriptValue length(QScriptContext *context, QScriptEngine *engine);
205 static QScriptValue prototype(QScriptEngine *);
206 static QScriptValue create(QScriptEngine *, NodeImpl *);
209 NodeList(const NodeList &);
215 NodeList &operator=(const NodeList &);
218 class NodeListClass : public QScriptClass
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);
230 static QScriptValue nodeName(QScriptContext *context, QScriptEngine *engine);
231 static QScriptValue nodeValue(QScriptContext *context, QScriptEngine *engine);
232 static QScriptValue nodeType(QScriptContext *context, QScriptEngine *engine);
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);
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);
250 static QScriptValue prototype(QScriptEngine *);
251 static QScriptValue create(QScriptEngine *, NodeImpl *);
261 Node &operator=(const Node &);
264 class Element : public Node
268 static QScriptValue prototype(QScriptEngine *);
271 class Attr : public Node
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);
283 static QScriptValue prototype(QScriptEngine *);
286 class CharacterData : public Node
290 static QScriptValue length(QScriptContext *context, QScriptEngine *engine);
293 static QScriptValue prototype(QScriptEngine *);
296 class Text : public CharacterData
300 static QScriptValue isElementContentWhitespace(QScriptContext *context, QScriptEngine *engine);
301 static QScriptValue wholeText(QScriptContext *context, QScriptEngine *engine);
304 static QScriptValue prototype(QScriptEngine *);
307 class CDATA : public Text
311 static QScriptValue prototype(QScriptEngine *);
314 class Document : public Node
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);
324 static QScriptValue prototype(QScriptEngine *);
325 static QScriptValue load(QScriptEngine *engine, const QByteArray &data);
332 Q_DECLARE_METATYPE(Node)
333 Q_DECLARE_METATYPE(NodeList)
334 Q_DECLARE_METATYPE(NamedNodeMap)
338 void NodeImpl::addref()
343 void NodeImpl::release()
348 QScriptValue Node::nodeName(QScriptContext *context, QScriptEngine *engine)
350 Node node = qscriptvalue_cast<Node>(context->thisObject());
351 if (node.isNull()) return engine->undefinedValue();
353 switch (node.d->type) {
354 case NodeImpl::Document:
355 return QScriptValue(QLatin1String("#document"));
356 case NodeImpl::CDATA:
357 return QScriptValue(QLatin1String("#cdata-section"));
359 return QScriptValue(QLatin1String("#text"));
361 return QScriptValue(node.d->name);
365 QScriptValue Node::nodeValue(QScriptContext *context, QScriptEngine *engine)
367 Node node = qscriptvalue_cast<Node>(context->thisObject());
368 if (node.isNull()) return engine->undefinedValue();
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();
379 return QScriptValue(node.d->data);
382 QScriptValue Node::nodeType(QScriptContext *context, QScriptEngine *engine)
384 Node node = qscriptvalue_cast<Node>(context->thisObject());
385 if (node.isNull()) return engine->undefinedValue();
386 return QScriptValue(node.d->type);
389 QScriptValue Node::parentNode(QScriptContext *context, QScriptEngine *engine)
391 Node node = qscriptvalue_cast<Node>(context->thisObject());
392 if (node.isNull()) return engine->undefinedValue();
394 if (node.d->parent) return Node::create(engine, node.d->parent);
395 else return engine->nullValue();
398 QScriptValue Node::childNodes(QScriptContext *context, QScriptEngine *engine)
400 Node node = qscriptvalue_cast<Node>(context->thisObject());
401 if (node.isNull()) return engine->undefinedValue();
403 return NodeList::create(engine, node.d);
406 QScriptValue Node::firstChild(QScriptContext *context, QScriptEngine *engine)
408 Node node = qscriptvalue_cast<Node>(context->thisObject());
409 if (node.isNull()) return engine->undefinedValue();
411 if (node.d->children.isEmpty()) return engine->nullValue();
412 else return Node::create(engine, node.d->children.first());
415 QScriptValue Node::lastChild(QScriptContext *context, QScriptEngine *engine)
417 Node node = qscriptvalue_cast<Node>(context->thisObject());
418 if (node.isNull()) return engine->undefinedValue();
420 if (node.d->children.isEmpty()) return engine->nullValue();
421 else return Node::create(engine, node.d->children.last());
424 QScriptValue Node::previousSibling(QScriptContext *context, QScriptEngine *engine)
426 Node node = qscriptvalue_cast<Node>(context->thisObject());
427 if (node.isNull()) return engine->undefinedValue();
429 if (!node.d->parent) return engine->nullValue();
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));
438 return engine->nullValue();
441 QScriptValue Node::nextSibling(QScriptContext *context, QScriptEngine *engine)
443 Node node = qscriptvalue_cast<Node>(context->thisObject());
444 if (node.isNull()) return engine->undefinedValue();
446 if (!node.d->parent) return engine->nullValue();
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));
455 return engine->nullValue();
458 QScriptValue Node::attributes(QScriptContext *context, QScriptEngine *engine)
460 Node node = qscriptvalue_cast<Node>(context->thisObject());
461 if (node.isNull()) return engine->undefinedValue();
463 if (node.d->type != NodeImpl::Element)
464 return engine->nullValue();
466 return NamedNodeMap::create(engine, node.d, &node.d->attributes);
469 QScriptValue Node::prototype(QScriptEngine *engine)
471 QScriptValue proto = engine->newObject();
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);
487 QScriptValue Node::create(QScriptEngine *engine, NodeImpl *data)
489 QScriptValue instance = engine->newObject();
491 switch (data->type) {
493 instance.setPrototype(Attr::prototype(engine));
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));
508 instance.setPrototype(Text::prototype(engine));
510 case NodeImpl::Element:
511 instance.setPrototype(Element::prototype(engine));
519 return engine->newVariant(instance, QVariant::fromValue(node));
522 QScriptValue Element::prototype(QScriptEngine *engine)
524 QScriptValue proto = engine->newObject();
525 proto.setPrototype(Node::prototype(engine));
527 proto.setProperty(QLatin1String("tagName"), engine->newFunction(nodeName), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
532 QScriptValue Attr::prototype(QScriptEngine *engine)
534 QScriptValue proto = engine->newObject();
535 proto.setPrototype(Node::prototype(engine));
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);
544 QScriptValue Attr::name(QScriptContext *context, QScriptEngine *engine)
546 Node node = qscriptvalue_cast<Node>(context->thisObject());
547 if (node.isNull()) return engine->undefinedValue();
549 return QScriptValue(node.d->name);
552 QScriptValue Attr::value(QScriptContext *context, QScriptEngine *engine)
554 Node node = qscriptvalue_cast<Node>(context->thisObject());
555 if (node.isNull()) return engine->undefinedValue();
557 return QScriptValue(node.d->data);
560 QScriptValue Attr::ownerElement(QScriptContext *context, QScriptEngine *engine)
562 Node node = qscriptvalue_cast<Node>(context->thisObject());
563 if (node.isNull()) return engine->undefinedValue();
565 return Node::create(engine, node.d->parent);
568 QScriptValue CharacterData::length(QScriptContext *context, QScriptEngine *engine)
570 Node node = qscriptvalue_cast<Node>(context->thisObject());
571 if (node.isNull()) return engine->undefinedValue();
573 return QScriptValue(node.d->data.length());
576 QScriptValue CharacterData::prototype(QScriptEngine *engine)
578 QScriptValue proto = engine->newObject();
579 proto.setPrototype(Node::prototype(engine));
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);
587 QScriptValue Text::isElementContentWhitespace(QScriptContext *context, QScriptEngine *engine)
589 Node node = qscriptvalue_cast<Node>(context->thisObject());
590 if (node.isNull()) return engine->undefinedValue();
592 return node.d->data.trimmed().isEmpty();
595 QScriptValue Text::wholeText(QScriptContext *context, QScriptEngine *engine)
597 Node node = qscriptvalue_cast<Node>(context->thisObject());
598 if (node.isNull()) return engine->undefinedValue();
603 QScriptValue Text::prototype(QScriptEngine *engine)
605 QScriptValue proto = engine->newObject();
606 proto.setPrototype(CharacterData::prototype(engine));
608 proto.setProperty(QLatin1String("isElementContentWhitespace"), engine->newFunction(isElementContentWhitespace), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
609 proto.setProperty(QLatin1String("wholeText"), engine->newFunction(wholeText), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
614 QScriptValue CDATA::prototype(QScriptEngine *engine)
616 QScriptValue proto = engine->newObject();
617 proto.setPrototype(Text::prototype(engine));
621 QScriptValue Document::prototype(QScriptEngine *engine)
623 QScriptValue proto = engine->newObject();
624 proto.setPrototype(Node::prototype(engine));
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);
634 QScriptValue Document::load(QScriptEngine *engine, const QByteArray &data)
638 DocumentImpl *document = 0;
639 QStack<NodeImpl *> nodeStack;
641 QXmlStreamReader reader(data);
643 while (!reader.atEnd()) {
644 switch (reader.readNext()) {
645 case QXmlStreamReader::NoToken:
647 case QXmlStreamReader::Invalid:
649 case QXmlStreamReader::StartDocument:
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();
657 case QXmlStreamReader::EndDocument:
659 case QXmlStreamReader::StartElement:
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;
669 node->parent = nodeStack.top();
670 node->parent->children.append(node);
672 nodeStack.append(node);
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();
682 node->attributes.append(attr);
686 case QXmlStreamReader::EndElement:
689 case QXmlStreamReader::Characters:
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();
699 case QXmlStreamReader::Comment:
701 case QXmlStreamReader::DTD:
703 case QXmlStreamReader::EntityReference:
705 case QXmlStreamReader::ProcessingInstruction:
710 if (!document || reader.hasError()) {
711 if (document) D(document);
712 return engine->nullValue();
715 QScriptValue instance = engine->newObject();
716 instance.setPrototype(Document::prototype(engine));
718 documentNode.d = document;
719 return engine->newVariant(instance, QVariant::fromValue(documentNode));
727 Node::Node(const Node &o)
738 bool Node::isNull() const
743 QScriptValue NamedNodeMap::length(QScriptContext *context, QScriptEngine *engine)
745 NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(context->thisObject().data());
746 if (map.isNull()) return engine->undefinedValue();
748 return QScriptValue(map.list->count());
751 QScriptValue NamedNodeMap::prototype(QScriptEngine *engine)
753 QScriptValue proto = engine->newObject();
755 proto.setProperty(QLatin1String("length"), engine->newFunction(length), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
760 QScriptValue NamedNodeMap::create(QScriptEngine *engine, NodeImpl *data, QList<NodeImpl *> *list)
762 QScriptValue instance = engine->newObject();
763 instance.setPrototype(NamedNodeMap::prototype(engine));
770 instance.setData(engine->newVariant(QVariant::fromValue(map)));
772 if (!QDeclarativeScriptEngine::get(engine)->namedNodeMapClass)
773 QDeclarativeScriptEngine::get(engine)->namedNodeMapClass= new NamedNodeMapClass(engine);
775 instance.setScriptClass(QDeclarativeScriptEngine::get(engine)->namedNodeMapClass);
780 NamedNodeMap::NamedNodeMap()
785 NamedNodeMap::NamedNodeMap(const NamedNodeMap &o)
786 : d(o.d), list(o.list)
791 NamedNodeMap::~NamedNodeMap()
796 bool NamedNodeMap::isNull()
801 QScriptValue NodeList::length(QScriptContext *context, QScriptEngine *engine)
803 NodeList list = qscriptvalue_cast<NodeList>(context->thisObject().data());
804 if (list.isNull()) return engine->undefinedValue();
806 return QScriptValue(list.d->children.count());
809 QScriptValue NodeList::prototype(QScriptEngine *engine)
811 QScriptValue proto = engine->newObject();
813 proto.setProperty(QLatin1String("length"), engine->newFunction(length), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
818 QScriptValue NodeList::create(QScriptEngine *engine, NodeImpl *data)
820 QScriptValue instance = engine->newObject();
821 instance.setPrototype(NodeList::prototype(engine));
827 instance.setData(engine->newVariant(QVariant::fromValue(list)));
829 if (!QDeclarativeScriptEngine::get(engine)->nodeListClass)
830 QDeclarativeScriptEngine::get(engine)->nodeListClass= new NodeListClass(engine);
832 instance.setScriptClass(QDeclarativeScriptEngine::get(engine)->nodeListClass);
842 NodeList::NodeList(const NodeList &o)
848 NodeList::~NodeList()
853 bool NodeList::isNull()
858 NamedNodeMapClass::QueryFlags NamedNodeMapClass::queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id)
860 if (!(flags & HandlesReadAccess))
863 NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(object.data());
864 Q_ASSERT(!map.isNull());
867 QString nameString = name.toString();
868 uint index = nameString.toUInt(&ok);
870 if ((uint)map.list->count() <= index)
874 return HandlesReadAccess;
876 for (int ii = 0; ii < map.list->count(); ++ii) {
877 if (map.list->at(ii) && map.list->at(ii)->name == nameString) {
879 return HandlesReadAccess;
887 QScriptValue NamedNodeMapClass::property(const QScriptValue &object, const QScriptString &, uint id)
889 NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(object.data());
890 return Node::create(engine(), map.list->at(id));
893 NodeListClass::QueryFlags NodeListClass::queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id)
895 if (!(flags & HandlesReadAccess))
899 uint index = name.toString().toUInt(&ok);
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
908 return HandlesReadAccess;
911 QScriptValue NodeListClass::property(const QScriptValue &object, const QScriptString &, uint id)
913 NodeList list = qscriptvalue_cast<NodeList>(object.data());
914 return Node::create(engine(), list.d->children.at(id));
917 QScriptValue Document::documentElement(QScriptContext *context, QScriptEngine *engine)
919 Node document = qscriptvalue_cast<Node>(context->thisObject());
920 if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
922 return Node::create(engine, static_cast<DocumentImpl *>(document.d)->root);
925 QScriptValue Document::xmlStandalone(QScriptContext *context, QScriptEngine *engine)
927 Node document = qscriptvalue_cast<Node>(context->thisObject());
928 if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
930 return QScriptValue(static_cast<DocumentImpl *>(document.d)->isStandalone);
933 QScriptValue Document::xmlVersion(QScriptContext *context, QScriptEngine *engine)
935 Node document = qscriptvalue_cast<Node>(context->thisObject());
936 if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
938 return QScriptValue(static_cast<DocumentImpl *>(document.d)->version);
941 QScriptValue Document::xmlEncoding(QScriptContext *context, QScriptEngine *engine)
943 Node document = qscriptvalue_cast<Node>(context->thisObject());
944 if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
946 return QScriptValue(static_cast<DocumentImpl *>(document.d)->encoding);
949 class QDeclarativeXMLHttpRequest : public QObject
953 enum State { Unsent = 0,
954 Opened = 1, HeadersReceived = 2,
955 Loading = 3, Done = 4 };
957 QDeclarativeXMLHttpRequest(QNetworkAccessManager *manager);
958 virtual ~QDeclarativeXMLHttpRequest();
960 bool sendFlag() const;
961 bool errorFlag() const;
962 quint32 readyState() const;
963 int replyStatus() const;
964 QString replyStatusText() const;
966 QScriptValue open(QScriptValue *me, const QString &, const QUrl &);
968 void addHeader(const QString &, const QString &);
969 QString header(const QString &name);
971 QScriptValue send(QScriptValue *me, const QByteArray &);
972 QScriptValue abort(QScriptValue *me);
974 QString responseBody();
975 const QByteArray & rawResponseBody() const;
976 bool receivedXml() const;
978 void downloadProgress(qint64);
979 void error(QNetworkReply::NetworkError);
983 void requestFromUrl(const QUrl &url);
990 QByteArray m_responseEntityBody;
994 typedef QPair<QByteArray, QByteArray> HeaderPair;
995 typedef QList<HeaderPair> HeadersList;
996 HeadersList m_headersList;
997 void fillHeadersList();
1001 QByteArray m_charset;
1002 QTextCodec *m_textCodec;
1003 #ifndef QT_NO_TEXTCODEC
1004 QTextCodec* findTextCodec() const;
1006 void readEncoding();
1008 QScriptValue m_me; // Set to the data object while a send() is ongoing (to access the callback)
1010 QScriptValue dispatchCallback(QScriptValue *me);
1011 void printError(const QScriptValue&);
1014 QString m_statusText;
1015 QNetworkRequest m_request;
1016 QDeclarativeGuard<QNetworkReply> m_network;
1017 void destroyNetwork();
1019 QNetworkAccessManager *m_nam;
1020 QNetworkAccessManager *networkAccessManager() { return m_nam; }
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)
1029 QDeclarativeXMLHttpRequest::~QDeclarativeXMLHttpRequest()
1034 bool QDeclarativeXMLHttpRequest::sendFlag() const
1039 bool QDeclarativeXMLHttpRequest::errorFlag() const
1044 quint32 QDeclarativeXMLHttpRequest::readyState() const
1049 int QDeclarativeXMLHttpRequest::replyStatus() const
1054 QString QDeclarativeXMLHttpRequest::replyStatusText() const
1056 return m_statusText;
1059 QScriptValue QDeclarativeXMLHttpRequest::open(QScriptValue *me, const QString &method, const QUrl &url)
1063 m_errorFlag = false;
1064 m_responseEntityBody = QByteArray();
1068 return dispatchCallback(me);
1071 void QDeclarativeXMLHttpRequest::addHeader(const QString &name, const QString &value)
1073 QByteArray utfname = name.toUtf8();
1075 if (m_request.hasRawHeader(utfname)) {
1076 m_request.setRawHeader(utfname, m_request.rawHeader(utfname) + ',' + value.toUtf8());
1078 m_request.setRawHeader(utfname, value.toUtf8());
1082 QString QDeclarativeXMLHttpRequest::header(const QString &name)
1084 QByteArray utfname = name.toLower().toUtf8();
1086 foreach (const HeaderPair &header, m_headersList) {
1087 if (header.first == utfname)
1088 return QString::fromUtf8(header.second);
1093 QString QDeclarativeXMLHttpRequest::headers()
1097 foreach (const HeaderPair &header, m_headersList) {
1099 ret.append(QLatin1String("\r\n"));
1100 ret = ret % QString::fromUtf8(header.first) % QLatin1String(": ")
1101 % QString::fromUtf8(header.second);
1106 void QDeclarativeXMLHttpRequest::fillHeadersList()
1108 QList<QByteArray> headerList = m_network->rawHeaderList();
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")
1117 m_headersList << pair;
1121 void QDeclarativeXMLHttpRequest::requestFromUrl(const QUrl &url)
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"));
1138 int semiColon = str.indexOf(QLatin1Char(';'), charsetIdx);
1139 if (semiColon == -1) {
1140 n = str.length() - charsetIdx;
1142 n = semiColon - charsetIdx;
1145 str.replace(charsetIdx, n, QLatin1String("UTF-8"));
1147 request.setHeader(QNetworkRequest::ContentTypeHeader, str);
1149 request.setHeader(QNetworkRequest::ContentTypeHeader,
1150 QLatin1String("text/plain;charset=UTF-8"));
1155 qWarning().nospace() << "XMLHttpRequest: " << qPrintable(m_method) << " " << qPrintable(url.toString());
1156 if (!m_data.isEmpty()) {
1157 qWarning().nospace() << " "
1158 << qPrintable(QString::fromUtf8(m_data));
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);
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()));
1179 QScriptValue QDeclarativeXMLHttpRequest::send(QScriptValue *me, const QByteArray &data)
1181 m_errorFlag = false;
1183 m_redirectCount = 0;
1187 requestFromUrl(m_url);
1189 return QScriptValue();
1192 QScriptValue QDeclarativeXMLHttpRequest::abort(QScriptValue *me)
1195 m_responseEntityBody = QByteArray();
1197 m_request = QNetworkRequest();
1199 if (!(m_state == Unsent ||
1200 (m_state == Opened && !m_sendFlag) ||
1205 QScriptValue cbv = dispatchCallback(me);
1206 if (cbv.isError()) return cbv;
1210 return QScriptValue();
1213 void QDeclarativeXMLHttpRequest::downloadProgress(qint64 bytes)
1217 m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
1219 QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray());
1221 // ### We assume if this is called the headers are now available
1222 if (m_state < HeadersReceived) {
1223 m_state = HeadersReceived;
1225 QScriptValue cbv = dispatchCallback(&m_me);
1226 if (cbv.isError()) printError(cbv);
1229 bool wasEmpty = m_responseEntityBody.isEmpty();
1230 m_responseEntityBody.append(m_network->readAll());
1231 if (wasEmpty && !m_responseEntityBody.isEmpty()) {
1233 QScriptValue cbv = dispatchCallback(&m_me);
1234 if (cbv.isError()) printError(cbv);
1238 static const char *errorToString(QNetworkReply::NetworkError error)
1240 int idx = QNetworkReply::staticMetaObject.indexOfEnumerator("NetworkError");
1241 if (idx == -1) return "EnumLookupFailed";
1243 QMetaEnum e = QNetworkReply::staticMetaObject.enumerator(idx);
1245 const char *name = e.valueToKey(error);
1246 if (!name) return "EnumLookupFailed";
1250 void QDeclarativeXMLHttpRequest::error(QNetworkReply::NetworkError error)
1254 m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
1256 QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray());
1258 m_responseEntityBody = QByteArray();
1260 m_request = QNetworkRequest();
1265 qWarning().nospace() << "XMLHttpRequest: ERROR " << qPrintable(m_url.toString());
1266 qWarning().nospace() << " " << error << " " << errorToString(error) << " " << m_statusText;
1269 if (error == QNetworkReply::ContentAccessDenied ||
1270 error == QNetworkReply::ContentOperationNotPermittedError ||
1271 error == QNetworkReply::ContentNotFoundError ||
1272 error == QNetworkReply::AuthenticationRequiredError ||
1273 error == QNetworkReply::ContentReSendError) {
1275 QScriptValue cbv = dispatchCallback(&m_me);
1276 if (cbv.isError()) printError(cbv);
1282 QScriptValue cbv = dispatchCallback(&m_me);
1283 if (cbv.isError()) printError(cbv);
1286 #define XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION 15
1287 void QDeclarativeXMLHttpRequest::finished()
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());
1295 requestFromUrl(url);
1301 m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
1303 QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray());
1305 if (m_state < HeadersReceived) {
1306 m_state = HeadersReceived;
1308 QScriptValue cbv = dispatchCallback(&m_me);
1309 if (cbv.isError()) printError(cbv);
1311 m_responseEntityBody.append(m_network->readAll());
1315 qWarning().nospace() << "XMLHttpRequest: RESPONSE " << qPrintable(m_url.toString());
1316 if (!m_responseEntityBody.isEmpty()) {
1317 qWarning().nospace() << " "
1318 << qPrintable(QString::fromUtf8(m_responseEntityBody));
1325 if (m_state < Loading) {
1327 QScriptValue cbv = dispatchCallback(&m_me);
1328 if (cbv.isError()) printError(cbv);
1331 QScriptValue cbv = dispatchCallback(&m_me);
1332 if (cbv.isError()) printError(cbv);
1334 m_me = QScriptValue();
1338 void QDeclarativeXMLHttpRequest::readEncoding()
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;
1346 m_mime = header.second.mid(0, separatorIdx);
1347 int charsetIdx = header.second.indexOf("charset=");
1348 if (charsetIdx != -1) {
1350 separatorIdx = header.second.indexOf(';', charsetIdx);
1351 m_charset = header.second.mid(charsetIdx, separatorIdx >= 0 ? separatorIdx : header.second.length());
1358 if (m_mime.isEmpty() || m_mime == "text/xml" || m_mime == "application/xml" || m_mime.endsWith("+xml"))
1362 bool QDeclarativeXMLHttpRequest::receivedXml() const
1368 #ifndef QT_NO_TEXTCODEC
1369 QTextCodec* QDeclarativeXMLHttpRequest::findTextCodec() const
1371 QTextCodec *codec = 0;
1373 if (!m_charset.isEmpty())
1374 codec = QTextCodec::codecForName(m_charset);
1376 if (!codec && m_gotXml) {
1377 QXmlStreamReader reader(m_responseEntityBody);
1379 codec = QTextCodec::codecForName(reader.documentEncoding().toString().toUtf8());
1382 if (!codec && m_mime == "text/html")
1383 codec = QTextCodec::codecForHtml(m_responseEntityBody, 0);
1386 codec = QTextCodec::codecForUtfText(m_responseEntityBody, 0);
1389 codec = QTextCodec::codecForName("UTF-8");
1395 QString QDeclarativeXMLHttpRequest::responseBody()
1397 #ifndef QT_NO_TEXTCODEC
1399 m_textCodec = findTextCodec();
1401 return m_textCodec->toUnicode(m_responseEntityBody);
1404 return QString::fromUtf8(m_responseEntityBody);
1407 const QByteArray &QDeclarativeXMLHttpRequest::rawResponseBody() const
1409 return m_responseEntityBody;
1412 QScriptValue QDeclarativeXMLHttpRequest::dispatchCallback(QScriptValue *me)
1414 QScriptValue v = me->property(QLatin1String("callback"));
1418 void QDeclarativeXMLHttpRequest::printError(const QScriptValue& sv)
1420 QDeclarativeError error;
1421 QDeclarativeExpressionPrivate::exceptionToError(sv.engine(), error);
1422 QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate::get(sv.engine()), error);
1425 void QDeclarativeXMLHttpRequest::destroyNetwork()
1428 m_network->disconnect();
1429 m_network->deleteLater();
1434 // XMLHttpRequest methods
1435 static QScriptValue qmlxmlhttprequest_open(QScriptContext *context, QScriptEngine *engine)
1437 QScriptValue dataObject = context->thisObject().data();
1438 QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(dataObject.toQObject());
1440 THROW_REFERENCE("Not an XMLHttpRequest object");
1442 if (context->argumentCount() < 2 || context->argumentCount() > 5)
1443 THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
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");
1455 QUrl url = QUrl::fromEncoded(context->argument(1).toString().toUtf8());
1457 if (url.isRelative()) {
1458 url = QDeclarativeScriptEngine::get(engine)->resolvedUrl(context,url);
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");
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();
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);
1480 return request->open(&dataObject, method, url);
1483 static QScriptValue qmlxmlhttprequest_setRequestHeader(QScriptContext *context, QScriptEngine *engine)
1485 QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
1487 THROW_REFERENCE("Not an XMLHttpRequest object");
1489 if (context->argumentCount() != 2)
1490 THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
1493 if (request->readyState() != QDeclarativeXMLHttpRequest::Opened ||
1494 request->sendFlag())
1495 THROW_DOM(INVALID_STATE_ERR, "Invalid state");
1498 QString name = context->argument(0).toString();
1499 QString value = context->argument(1).toString();
1501 // ### Check that name and value are well formed
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();
1526 request->addHeader(nameUpper, value);
1528 return engine->undefinedValue();
1531 static QScriptValue qmlxmlhttprequest_send(QScriptContext *context, QScriptEngine *)
1533 QScriptValue dataObject = context->thisObject().data();
1534 QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(dataObject.toQObject());
1536 THROW_REFERENCE("Not an XMLHttpRequest object");
1538 if (request->readyState() != QDeclarativeXMLHttpRequest::Opened)
1539 THROW_DOM(INVALID_STATE_ERR, "Invalid state");
1541 if (request->sendFlag())
1542 THROW_DOM(INVALID_STATE_ERR, "Invalid state");
1545 if (context->argumentCount() > 0)
1546 data = context->argument(0).toString().toUtf8();
1548 return request->send(&dataObject, data);
1551 static QScriptValue qmlxmlhttprequest_abort(QScriptContext *context, QScriptEngine *)
1553 QScriptValue dataObject = context->thisObject().data();
1554 QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(dataObject.toQObject());
1556 THROW_REFERENCE("Not an XMLHttpRequest object");
1558 return request->abort(&dataObject);
1561 static QScriptValue qmlxmlhttprequest_getResponseHeader(QScriptContext *context, QScriptEngine *engine)
1564 QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
1566 THROW_REFERENCE("Not an XMLHttpRequest object");
1568 if (context->argumentCount() != 1)
1569 THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
1571 if (request->readyState() != QDeclarativeXMLHttpRequest::Loading &&
1572 request->readyState() != QDeclarativeXMLHttpRequest::Done &&
1573 request->readyState() != QDeclarativeXMLHttpRequest::HeadersReceived)
1574 THROW_DOM(INVALID_STATE_ERR, "Invalid state");
1576 QString headerName = context->argument(0).toString();
1578 return QScriptValue(request->header(headerName));
1581 static QScriptValue qmlxmlhttprequest_getAllResponseHeaders(QScriptContext *context, QScriptEngine *engine)
1584 QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
1586 THROW_REFERENCE("Not an XMLHttpRequest object");
1588 if (context->argumentCount() != 0)
1589 THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
1591 if (request->readyState() != QDeclarativeXMLHttpRequest::Loading &&
1592 request->readyState() != QDeclarativeXMLHttpRequest::Done &&
1593 request->readyState() != QDeclarativeXMLHttpRequest::HeadersReceived)
1594 THROW_DOM(INVALID_STATE_ERR, "Invalid state");
1596 return QScriptValue(request->headers());
1599 // XMLHttpRequest properties
1600 static QScriptValue qmlxmlhttprequest_readyState(QScriptContext *context, QScriptEngine *engine)
1603 QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
1605 THROW_REFERENCE("Not an XMLHttpRequest object");
1607 return QScriptValue(request->readyState());
1610 static QScriptValue qmlxmlhttprequest_status(QScriptContext *context, QScriptEngine *engine)
1613 QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
1615 THROW_REFERENCE("Not an XMLHttpRequest object");
1617 if (request->readyState() == QDeclarativeXMLHttpRequest::Unsent ||
1618 request->readyState() == QDeclarativeXMLHttpRequest::Opened)
1619 THROW_DOM(INVALID_STATE_ERR, "Invalid state");
1621 if (request->errorFlag())
1622 return QScriptValue(0);
1624 return QScriptValue(request->replyStatus());
1627 static QScriptValue qmlxmlhttprequest_statusText(QScriptContext *context, QScriptEngine *engine)
1630 QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
1632 THROW_REFERENCE("Not an XMLHttpRequest object");
1634 if (request->readyState() == QDeclarativeXMLHttpRequest::Unsent ||
1635 request->readyState() == QDeclarativeXMLHttpRequest::Opened)
1636 THROW_DOM(INVALID_STATE_ERR, "Invalid state");
1638 if (request->errorFlag())
1639 return QScriptValue(0);
1641 return QScriptValue(request->replyStatusText());
1644 static QScriptValue qmlxmlhttprequest_responseText(QScriptContext *context, QScriptEngine *engine)
1647 QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
1649 THROW_REFERENCE("Not an XMLHttpRequest object");
1651 if (request->readyState() != QDeclarativeXMLHttpRequest::Loading &&
1652 request->readyState() != QDeclarativeXMLHttpRequest::Done)
1653 return QScriptValue(QString());
1655 return QScriptValue(request->responseBody());
1658 static QScriptValue qmlxmlhttprequest_responseXML(QScriptContext *context, QScriptEngine *engine)
1660 QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
1662 THROW_REFERENCE("Not an XMLHttpRequest object");
1664 if (!request->receivedXml() ||
1665 (request->readyState() != QDeclarativeXMLHttpRequest::Loading &&
1666 request->readyState() != QDeclarativeXMLHttpRequest::Done))
1667 return engine->nullValue();
1669 return Document::load(engine, request->rawResponseBody());
1672 static QScriptValue qmlxmlhttprequest_onreadystatechange(QScriptContext *context, QScriptEngine *engine)
1675 QScriptValue dataObject = context->thisObject().data();
1676 QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(dataObject.toQObject());
1678 THROW_REFERENCE("Not an XMLHttpRequest object");
1680 if (context->argumentCount()) {
1681 QScriptValue v = context->argument(0);
1682 dataObject.setProperty(QLatin1String("callback"), v);
1685 return dataObject.property(QLatin1String("callback"));
1690 static QScriptValue qmlxmlhttprequest_new(QScriptContext *context, QScriptEngine *engine)
1692 if (context->isCalledAsConstructor()) {
1693 context->thisObject().setData(engine->newQObject(new QDeclarativeXMLHttpRequest(QDeclarativeScriptEngine::get(engine)->networkAccessManager()), QScriptEngine::ScriptOwnership));
1695 return engine->undefinedValue();
1698 void qt_add_qmlxmlhttprequest(QScriptEngine *engine)
1700 QScriptValue prototype = engine->newObject();
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));
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);
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);
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);
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);
1754 engine->globalObject().setProperty(QLatin1String("DOMException"), domExceptionPrototype);
1759 #endif // QT_NO_XMLSTREAMREADER
1761 #include <qdeclarativexmlhttprequest.moc>