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