Add missing QT_{BEGIN,END}_NAMESPACE
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlengine_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QQMLENGINE_P_H
43 #define QQMLENGINE_P_H
44
45 //
46 //  W A R N I N G
47 //  -------------
48 //
49 // This file is not part of the Qt API.  It exists purely as an
50 // implementation detail.  This header file may change from version to
51 // version without notice, or even be removed.
52 //
53 // We mean it.
54 //
55
56 #include "qqmlengine.h"
57
58 #include "qqmltypeloader_p.h"
59 #include "qqmlimport_p.h"
60 #include <private/qpodvector_p.h>
61 #include "qqml.h"
62 #include "qqmlvaluetype_p.h"
63 #include "qqmlcontext.h"
64 #include "qqmlcontext_p.h"
65 #include "qqmlexpression.h"
66 #include "qqmlproperty_p.h"
67 #include "qqmlpropertycache_p.h"
68 #include "qqmlmetatype_p.h"
69 #include "qqmldirparser_p.h"
70 #include <private/qintrusivelist_p.h>
71 #include <private/qrecyclepool_p.h>
72
73 #include <QtCore/qlist.h>
74 #include <QtCore/qpair.h>
75 #include <QtCore/qstack.h>
76 #include <QtCore/qmutex.h>
77 #include <QtCore/qstring.h>
78 #include <QtCore/qthread.h>
79
80 #include <private/qobject_p.h>
81
82 #include <private/qv8engine_p.h>
83 #include <private/qjsengine_p.h>
84
85 QT_BEGIN_NAMESPACE
86
87 class QQmlContext;
88 class QQmlEngine;
89 class QQmlContextPrivate;
90 class QQmlExpression;
91 class QQmlImportDatabase;
92 class QNetworkReply;
93 class QNetworkAccessManager;
94 class QQmlNetworkAccessManagerFactory;
95 class QQmlAbstractBinding;
96 class QQmlTypeNameCache;
97 class QQmlComponentAttached;
98 class QQmlCleanup;
99 class QQmlDelayedError;
100 class QQuickWorkerScriptEngine;
101 class QQmlVME;
102 class QDir;
103 class QQmlIncubator;
104
105 // This needs to be declared here so that the pool for it can live in QQmlEnginePrivate.
106 // The inline method definitions are in qqmljavascriptexpression_p.h
107 class QQmlJavaScriptExpressionGuard : public QQmlNotifierEndpoint
108 {
109 public:
110     inline QQmlJavaScriptExpressionGuard(QQmlJavaScriptExpression *);
111
112     static inline QQmlJavaScriptExpressionGuard *New(QQmlJavaScriptExpression *e,
113                                                              QQmlEngine *engine);
114     inline void Delete();
115
116     QQmlJavaScriptExpression *expression;
117     QQmlJavaScriptExpressionGuard *next;
118 };
119
120 class Q_QML_PRIVATE_EXPORT QQmlEnginePrivate : public QJSEnginePrivate
121 {
122     Q_DECLARE_PUBLIC(QQmlEngine)
123 public:
124     QQmlEnginePrivate(QQmlEngine *);
125     ~QQmlEnginePrivate();
126
127     void init();
128
129     class PropertyCapture {
130     public:
131         inline virtual ~PropertyCapture() {}
132         virtual void captureProperty(QQmlNotifier *) = 0;
133         virtual void captureProperty(QObject *, int, int) = 0;
134     };
135
136     PropertyCapture *propertyCapture;
137     inline void captureProperty(QQmlNotifier *);
138     inline void captureProperty(QObject *, int, int);
139
140     QRecyclePool<QQmlJavaScriptExpressionGuard> jsExpressionGuardPool;
141
142     QQmlContext *rootContext;
143     bool isDebugging;
144
145     bool outputWarningsToStdErr;
146
147     QQmlContextData *sharedContext;
148     QObject *sharedScope;
149
150     // Registered cleanup handlers
151     QQmlCleanup *cleanup;
152
153     // Bindings that have had errors during startup
154     QQmlDelayedError *erroredBindings;
155     int inProgressCreations;
156
157     QV8Engine *v8engine() const { return q_func()->handle(); }
158
159     QQuickWorkerScriptEngine *getWorkerScriptEngine();
160     QQuickWorkerScriptEngine *workerScriptEngine;
161
162     QUrl baseUrl;
163
164     typedef QPair<QQmlGuard<QObject>,int> FinalizeCallback;
165     void registerFinalizeCallback(QObject *obj, int index);
166
167     QQmlVME *activeVME;
168
169     QNetworkAccessManager *createNetworkAccessManager(QObject *parent) const;
170     QNetworkAccessManager *getNetworkAccessManager() const;
171     mutable QNetworkAccessManager *networkAccessManager;
172     mutable QQmlNetworkAccessManagerFactory *networkAccessManagerFactory;
173
174     QHash<QString,QSharedPointer<QQmlImageProviderBase> > imageProviders;
175
176     // Scarce resources are "exceptionally high cost" QVariant types where allowing the
177     // normal JavaScript GC to clean them up is likely to lead to out-of-memory or other
178     // out-of-resource situations.  When such a resource is passed into JavaScript we
179     // add it to the scarceResources list and it is destroyed when we return from the
180     // JavaScript execution that created it.  The user can prevent this behavior by
181     // calling preserve() on the object which removes it from this scarceResource list.
182     class ScarceResourceData {
183     public:
184         ScarceResourceData(const QVariant &data) : data(data) {}
185         QVariant data;
186         QIntrusiveListNode node;
187     };
188     QIntrusiveList<ScarceResourceData, &ScarceResourceData::node> scarceResources;
189     int scarceResourcesRefCount;
190     void referenceScarceResources();
191     void dereferenceScarceResources();
192
193     QQmlTypeLoader typeLoader;
194     QQmlImportDatabase importDatabase;
195
196     QString offlineStoragePath;
197
198     mutable quint32 uniqueId;
199     inline quint32 getUniqueId() const {
200         return uniqueId++;
201     }
202
203     // Unfortunate workaround to avoid a circular dependency between 
204     // qqmlengine_p.h and qqmlincubator_p.h
205     struct Incubator {
206         QIntrusiveListNode next;
207         // Unfortunate workaround for MSVC
208         QIntrusiveListNode nextWaitingFor;
209     };
210     QIntrusiveList<Incubator, &Incubator::next> incubatorList;
211     unsigned int incubatorCount;
212     QQmlIncubationController *incubationController;
213     void incubate(QQmlIncubator &, QQmlContextData *);
214
215     // These methods may be called from any thread
216     inline bool isEngineThread() const;
217     inline static bool isEngineThread(const QQmlEngine *);
218     template<typename T>
219     inline void deleteInEngineThread(T *);
220     template<typename T>
221     inline static void deleteInEngineThread(QQmlEngine *, T *);
222
223     // These methods may be called from the loader thread
224     QQmlMetaType::SingletonInstance *singletonTypeInstance(const QQmlMetaType::SingletonType &module);
225
226     // These methods may be called from the loader thread
227     inline QQmlPropertyCache *cache(QObject *obj);
228     inline QQmlPropertyCache *cache(const QMetaObject *);
229     inline QQmlPropertyCache *cache(QQmlType *, int, QQmlError &error);
230
231     // These methods may be called from the loader thread
232     bool isQObject(int);
233     QObject *toQObject(const QVariant &, bool *ok = 0) const;
234     QQmlMetaType::TypeCategory typeCategory(int) const;
235     bool isList(int) const;
236     int listType(int) const;
237     QQmlMetaObject rawMetaObjectForType(int) const;
238     QQmlMetaObject metaObjectForType(int) const;
239     QQmlPropertyCache *propertyCacheForType(int);
240     QQmlPropertyCache *rawPropertyCacheForType(int);
241     void registerCompositeType(QQmlCompiledData *);
242     void unregisterCompositeType(QQmlCompiledData *);
243
244     bool isTypeLoaded(const QUrl &url) const;
245     bool isScriptLoaded(const QUrl &url) const;
246
247     inline void setDebugChangesCache(const QHash<QUrl, QByteArray> &changes);
248     inline QHash<QUrl, QByteArray> debugChangesCache();
249
250     void sendQuit();
251     void warning(const QQmlError &);
252     void warning(const QList<QQmlError> &);
253     void warning(QQmlDelayedError *);
254     static void warning(QQmlEngine *, const QQmlError &);
255     static void warning(QQmlEngine *, const QList<QQmlError> &);
256     static void warning(QQmlEngine *, QQmlDelayedError *);
257     static void warning(QQmlEnginePrivate *, const QQmlError &);
258     static void warning(QQmlEnginePrivate *, const QList<QQmlError> &);
259
260     inline static QV8Engine *getV8Engine(QQmlEngine *e);
261     inline static QQmlEnginePrivate *get(QQmlEngine *e);
262     inline static const QQmlEnginePrivate *get(const QQmlEngine *e);
263     inline static QQmlEnginePrivate *get(QQmlContext *c);
264     inline static QQmlEnginePrivate *get(QQmlContextData *c);
265     inline static QQmlEngine *get(QQmlEnginePrivate *p);
266
267     static void registerBaseTypes(const char *uri, int versionMajor, int versionMinor);
268     static void registerQtQuick2Types(const char *uri, int versionMajor, int versionMinor);
269     static void defineQtQuick2Module();
270
271     static bool qml_debugging_enabled;
272
273     mutable QMutex mutex;
274
275 private:
276     // Locker locks the QQmlEnginePrivate data structures for read and write, if necessary.  
277     // Currently, locking is only necessary if the threaded loader is running concurrently.  If it is 
278     // either idle, or is running with the main thread blocked, no locking is necessary.  This way
279     // we only pay for locking when we have to.
280     // Consequently, this class should only be used to protect simple accesses or modifications of the 
281     // QQmlEnginePrivate structures or operations that can be guarenteed not to start activity
282     // on the loader thread.
283     // The Locker API is identical to QMutexLocker.  Locker reuses the QQmlEnginePrivate::mutex 
284     // QMutex instance and multiple Lockers are recursive in the same thread.
285     class Locker 
286     {
287     public:
288         inline Locker(const QQmlEngine *);
289         inline Locker(const QQmlEnginePrivate *);
290         inline ~Locker();
291
292         inline void unlock();
293         inline void relock();
294
295     private:
296         const QQmlEnginePrivate *m_ep;
297         quint32 m_locked:1;
298     };
299
300     // Must be called locked
301     QQmlPropertyCache *createCache(const QMetaObject *);
302     QQmlPropertyCache *createCache(QQmlType *, int, QQmlError &error);
303
304     // These members must be protected by a QQmlEnginePrivate::Locker as they are required by
305     // the threaded loader.  Only access them through their respective accessor methods.
306     QHash<QQmlMetaType::SingletonType, QQmlMetaType::SingletonInstance *> singletonTypeInstances;
307     QHash<const QMetaObject *, QQmlPropertyCache *> propertyCache;
308     QHash<QPair<QQmlType *, int>, QQmlPropertyCache *> typePropertyCache;
309     QHash<int, int> m_qmlLists;
310     QHash<int, QQmlCompiledData *> m_compositeTypes;
311     QHash<QUrl, QByteArray> debugChangesHash;
312
313     // These members is protected by the full QQmlEnginePrivate::mutex mutex
314     struct Deletable { Deletable():next(0) {} virtual ~Deletable() {} Deletable *next; };
315     QFieldList<Deletable, &Deletable::next> toDeleteInEngineThread;
316     void doDeleteInEngineThread();
317 };
318
319 QQmlEnginePrivate::Locker::Locker(const QQmlEngine *e)
320 : m_ep(QQmlEnginePrivate::get(e))
321 {
322     relock();
323 }
324
325 QQmlEnginePrivate::Locker::Locker(const QQmlEnginePrivate *e)
326 : m_ep(e), m_locked(false)
327 {
328     relock();
329 }
330
331 QQmlEnginePrivate::Locker::~Locker()
332 {
333     unlock();
334 }
335
336 void QQmlEnginePrivate::Locker::unlock()
337 {
338     if (m_locked) { 
339         m_ep->mutex.unlock();
340         m_locked = false;
341     }
342 }
343
344 void QQmlEnginePrivate::Locker::relock()
345 {
346     Q_ASSERT(!m_locked);
347     if (m_ep->typeLoader.isConcurrent()) {
348         m_ep->mutex.lock();
349         m_locked = true;
350     }
351 }
352
353 /*!
354 Returns true if the calling thread is the QQmlEngine thread.
355 */
356 bool QQmlEnginePrivate::isEngineThread() const
357 {
358     Q_Q(const QQmlEngine);
359     return QThread::currentThread() == q->thread();
360 }
361
362 /*!
363 Returns true if the calling thread is the QQmlEngine \a engine thread.
364 */
365 bool QQmlEnginePrivate::isEngineThread(const QQmlEngine *engine)
366 {
367     Q_ASSERT(engine);
368     return QQmlEnginePrivate::get(engine)->isEngineThread();
369 }
370
371 /*!
372 Delete \a value in the engine thread.  If the calling thread is the engine
373 thread, \a value will be deleted immediately.
374
375 This method should be used for *any* type that has resources that need to
376 be freed in the engine thread.  This is generally types that use V8 handles.
377 As there is some small overhead in checking the current thread, it is best
378 practice to check if any V8 handles actually need to be freed and delete 
379 the instance directly if not.
380 */
381 template<typename T>
382 void QQmlEnginePrivate::deleteInEngineThread(T *value)
383 {
384     Q_Q(QQmlEngine);
385
386     Q_ASSERT(value);
387     if (isEngineThread()) {
388         delete value;
389     } else { 
390         struct I : public Deletable {
391             I(T *value) : value(value) {}
392             ~I() { delete value; }
393             T *value;
394         };
395         I *i = new I(value);
396         mutex.lock();
397         bool wasEmpty = toDeleteInEngineThread.isEmpty();
398         toDeleteInEngineThread.append(i);
399         mutex.unlock();
400         if (wasEmpty)
401             QCoreApplication::postEvent(q, new QEvent(QEvent::User));
402     }
403 }
404
405 /*!
406 Delete \a value in the \a engine thread.  If the calling thread is the engine
407 thread, \a value will be deleted immediately.
408 */
409 template<typename T>
410 void QQmlEnginePrivate::deleteInEngineThread(QQmlEngine *engine, T *value)
411 {
412     Q_ASSERT(engine);
413     QQmlEnginePrivate::get(engine)->deleteInEngineThread<T>(value);
414 }
415
416 /*!
417 Returns a QQmlPropertyCache for \a obj if one is available.
418
419 If \a obj is null, being deleted or contains a dynamic meta object 0
420 is returned.
421
422 The returned cache is not referenced, so if it is to be stored, call addref().
423
424 XXX thread There is a potential future race condition in this and all the cache()
425 functions.  As the QQmlPropertyCache is returned unreferenced, when called 
426 from the loader thread, it is possible that the cache will have been dereferenced 
427 and deleted before the loader thread has a chance to use or reference it.  This
428 can't currently happen as the cache holds a reference to the 
429 QQmlPropertyCache until the QQmlEngine is destroyed.
430 */
431 QQmlPropertyCache *QQmlEnginePrivate::cache(QObject *obj)
432 {
433     if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted)
434         return 0;
435
436     Locker locker(this);
437     const QMetaObject *mo = obj->metaObject();
438     QQmlPropertyCache *rv = propertyCache.value(mo);
439     if (!rv) rv = createCache(mo);
440     return rv;
441 }
442
443 /*!
444 Returns a QQmlPropertyCache for \a metaObject.
445
446 As the cache is persisted for the life of the engine, \a metaObject must be
447 a static "compile time" meta-object, or a meta-object that is otherwise known to
448 exist for the lifetime of the QQmlEngine.
449
450 The returned cache is not referenced, so if it is to be stored, call addref().
451 */
452 QQmlPropertyCache *QQmlEnginePrivate::cache(const QMetaObject *metaObject)
453 {
454     Q_ASSERT(metaObject);
455
456     Locker locker(this);
457     QQmlPropertyCache *rv = propertyCache.value(metaObject);
458     if (!rv) rv = createCache(metaObject);
459     return rv;
460 }
461
462 /*!
463 Returns a QQmlPropertyCache for \a type with \a minorVersion.
464
465 The returned cache is not referenced, so if it is to be stored, call addref().
466 */
467 QQmlPropertyCache *QQmlEnginePrivate::cache(QQmlType *type, int minorVersion, QQmlError &error)
468 {
469     Q_ASSERT(type);
470
471     if (minorVersion == -1 || !type->containsRevisionedAttributes())
472         return cache(type->metaObject());
473
474     Locker locker(this);
475     QQmlPropertyCache *rv = typePropertyCache.value(qMakePair(type, minorVersion));
476     if (!rv) rv = createCache(type, minorVersion, error);
477     return rv;
478 }
479
480 QV8Engine *QQmlEnginePrivate::getV8Engine(QQmlEngine *e) 
481
482     Q_ASSERT(e);
483
484     return e->d_func()->v8engine(); 
485 }
486
487 QQmlEnginePrivate *QQmlEnginePrivate::get(QQmlEngine *e) 
488
489     Q_ASSERT(e);
490
491     return e->d_func();
492 }
493
494 const QQmlEnginePrivate *QQmlEnginePrivate::get(const QQmlEngine *e) 
495
496     Q_ASSERT(e);
497
498     return e->d_func();
499 }
500
501 QQmlEnginePrivate *QQmlEnginePrivate::get(QQmlContext *c) 
502
503     return (c && c->engine()) ? QQmlEnginePrivate::get(c->engine()) : 0; 
504 }
505
506 QQmlEnginePrivate *QQmlEnginePrivate::get(QQmlContextData *c) 
507
508     return (c && c->engine) ? QQmlEnginePrivate::get(c->engine) : 0; 
509 }
510
511 QQmlEngine *QQmlEnginePrivate::get(QQmlEnginePrivate *p) 
512
513     Q_ASSERT(p);
514
515     return p->q_func(); 
516 }
517
518 void QQmlEnginePrivate::captureProperty(QQmlNotifier *n)
519 {
520     if (propertyCapture)
521         propertyCapture->captureProperty(n);
522 }
523
524 void QQmlEnginePrivate::captureProperty(QObject *o, int c, int n)
525 {
526     if (propertyCapture)
527         propertyCapture->captureProperty(o, c, n);
528 }
529
530 void QQmlEnginePrivate::setDebugChangesCache(const QHash<QUrl, QByteArray> &changes)
531 {
532     Locker locker(this);
533     foreach (const QUrl &key, changes.keys())
534         debugChangesHash.insert(key, changes.value(key));
535 }
536
537 QHash<QUrl, QByteArray> QQmlEnginePrivate::debugChangesCache()
538 {
539     Locker locker(this);
540     return debugChangesHash;
541 }
542
543 QT_END_NAMESPACE
544
545 #endif // QQMLENGINE_P_H