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