0dd7adecac404191565c5f5176784b8fbb63f64a
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmltypeloader_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 QQMLTYPELOADER_P_H
43 #define QQMLTYPELOADER_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 <QtCore/qobject.h>
57 #include <QtCore/qatomic.h>
58 #include <QtNetwork/qnetworkreply.h>
59 #include <QtQml/qqmlerror.h>
60 #include <QtQml/qqmlengine.h>
61
62 #include <private/qv8_p.h>
63 #include <private/qhashedstring_p.h>
64 #include <private/qqmlscript_p.h>
65 #include <private/qqmlimport_p.h>
66 #include <private/qqmlcleanup_p.h>
67 #include <private/qqmldirparser_p.h>
68
69 QT_BEGIN_NAMESPACE
70
71 class QQmlScriptData;
72 class QQmlScriptBlob;
73 class QQmlQmldirData;
74 class QQmlTypeLoader;
75 class QQmlCompiledData;
76 class QQmlComponentPrivate;
77 class QQmlTypeData;
78 class QQmlDataLoader;
79 class QQmlExtensionInterface;
80
81 // Exported for QtQuick1
82 class Q_QML_PRIVATE_EXPORT QQmlDataBlob : public QQmlRefCount
83 {
84 public:
85     enum Status {
86         Null,                    // Prior to QQmlDataLoader::load()
87         Loading,                 // Prior to data being received and dataReceived() being called
88         WaitingForDependencies,  // While there are outstanding addDependency()s
89         Complete,                // Finished
90         Error                    // Error
91     };
92
93     enum Type {
94         QmlFile,
95         JavaScriptFile,
96         QmldirFile
97     };
98
99     QQmlDataBlob(const QUrl &, Type);
100     virtual ~QQmlDataBlob();
101
102     Type type() const;
103
104     Status status() const;
105     bool isNull() const;
106     bool isLoading() const;
107     bool isWaiting() const;
108     bool isComplete() const;
109     bool isError() const;
110     bool isCompleteOrError() const;
111
112     qreal progress() const;
113
114     QUrl url() const;
115     QUrl finalUrl() const;
116     QString finalUrlString() const;
117
118     QList<QQmlError> errors() const;
119
120 protected:
121     // Can be called from within callbacks
122     void setError(const QQmlError &);
123     void setError(const QList<QQmlError> &errors);
124     void addDependency(QQmlDataBlob *);
125
126     // Callbacks made in load thread
127     virtual void dataReceived(const QByteArray &) = 0;
128     virtual void done();
129     virtual void networkError(QNetworkReply::NetworkError);
130     virtual void dependencyError(QQmlDataBlob *);
131     virtual void dependencyComplete(QQmlDataBlob *);
132     virtual void allDependenciesDone();
133
134     // Callbacks made in main thread
135     virtual void downloadProgressChanged(qreal);
136     virtual void completed();
137 private:
138     friend class QQmlDataLoader;
139     friend class QQmlDataLoaderThread;
140
141     void tryDone();
142     void cancelAllWaitingFor();
143     void notifyAllWaitingOnMe();
144     void notifyComplete(QQmlDataBlob *);
145
146     struct ThreadData {
147         inline ThreadData();
148         inline QQmlDataBlob::Status status() const;
149         inline void setStatus(QQmlDataBlob::Status);
150         inline bool isAsync() const;
151         inline void setIsAsync(bool);
152         inline quint8 progress() const;
153         inline void setProgress(quint8);
154
155     private:
156         QAtomicInt _p;
157     };
158     ThreadData m_data;
159
160     // m_errors should *always* be written before the status is set to Error.
161     // We use the status change as a memory fence around m_errors so that locking
162     // isn't required.  Once the status is set to Error (or Complete), m_errors 
163     // cannot be changed.
164     QList<QQmlError> m_errors;
165
166     Type m_type;
167
168     QUrl m_url;
169     QUrl m_finalUrl;
170     mutable QString m_finalUrlString;
171
172     // List of QQmlDataBlob's that are waiting for me to complete.
173     QList<QQmlDataBlob *> m_waitingOnMe;
174
175     // List of QQmlDataBlob's that I am waiting for to complete.
176     QList<QQmlDataBlob *> m_waitingFor;
177
178     // Manager that is currently fetching data for me
179     QQmlDataLoader *m_manager;
180     int m_redirectCount:30;
181     bool m_inCallback:1;
182     bool m_isDone:1;
183 };
184
185 class QQmlDataLoaderThread;
186 // Exported for QtQuick1
187 class Q_QML_PRIVATE_EXPORT QQmlDataLoader 
188 {
189 public:
190     QQmlDataLoader(QQmlEngine *);
191     ~QQmlDataLoader();
192
193     void lock();
194     void unlock();
195
196     bool isConcurrent() const { return true; }
197
198     enum Mode { PreferSynchronous, Asynchronous };
199
200     void load(QQmlDataBlob *, Mode = PreferSynchronous);
201     void loadWithStaticData(QQmlDataBlob *, const QByteArray &, Mode = PreferSynchronous);
202
203     QQmlEngine *engine() const;
204     void initializeEngine(QQmlExtensionInterface *, const char *);
205
206 private:
207     friend class QQmlDataBlob;
208     friend class QQmlDataLoaderThread;
209     friend class QQmlDataLoaderNetworkReplyProxy;
210
211     void loadThread(QQmlDataBlob *);
212     void loadWithStaticDataThread(QQmlDataBlob *, const QByteArray &);
213     void networkReplyFinished(QNetworkReply *);
214     void networkReplyProgress(QNetworkReply *, qint64, qint64);
215     
216     typedef QHash<QNetworkReply *, QQmlDataBlob *> NetworkReplies;
217
218     void setData(QQmlDataBlob *, const QByteArray &);
219
220     QQmlEngine *m_engine;
221     QQmlDataLoaderThread *m_thread;
222     NetworkReplies m_networkReplies;
223 };
224
225 // Exported for QtQuick1
226 class Q_QML_PRIVATE_EXPORT QQmlTypeLoader : public QQmlDataLoader
227 {
228     Q_DECLARE_TR_FUNCTIONS(QQmlTypeLoader)
229 public:
230     QQmlTypeLoader(QQmlEngine *);
231     ~QQmlTypeLoader();
232
233     enum Option {
234         None,
235         PreserveParser
236     };
237     Q_DECLARE_FLAGS(Options, Option)
238
239     QQmlTypeData *get(const QUrl &url);
240     QQmlTypeData *get(const QByteArray &, const QUrl &url, Options = None);
241     void clearCache();
242
243     QQmlScriptBlob *getScript(const QUrl &);
244     QQmlQmldirData *getQmldir(const QUrl &);
245
246     QString absoluteFilePath(const QString &path);
247     bool directoryExists(const QString &path);
248     const QQmlDirParser *qmlDirParser(const QString &absoluteFilePath);
249 private:
250     typedef QHash<QUrl, QQmlTypeData *> TypeCache;
251     typedef QHash<QUrl, QQmlScriptBlob *> ScriptCache;
252     typedef QHash<QUrl, QQmlQmldirData *> QmldirCache;
253     typedef QStringHash<bool> StringSet;
254     typedef QStringHash<StringSet*> ImportDirCache;
255     typedef QStringHash<QQmlDirParser*> ImportQmlDirCache;
256
257     TypeCache m_typeCache;
258     ScriptCache m_scriptCache;
259     QmldirCache m_qmldirCache;
260     ImportDirCache m_importDirCache;
261     ImportQmlDirCache m_importQmlDirCache;
262 };
263
264 Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlTypeLoader::Options)
265
266 class Q_AUTOTEST_EXPORT QQmlTypeData : public QQmlDataBlob
267 {
268 public:
269     struct TypeReference
270     {
271         TypeReference() : type(0), majorVersion(0), minorVersion(0), typeData(0) {}
272
273         QQmlScript::Location location;
274         QQmlType *type;
275         int majorVersion;
276         int minorVersion;
277         QQmlTypeData *typeData;
278     };
279
280     struct ScriptReference
281     {
282         ScriptReference() : script(0) {}
283
284         QQmlScript::Location location;
285         QString qualifier;
286         QQmlScriptBlob *script;
287     };
288
289     QQmlTypeData(const QUrl &, QQmlTypeLoader::Options, QQmlTypeLoader *);
290     ~QQmlTypeData();
291
292     QQmlTypeLoader *typeLoader() const;
293
294     const QQmlImports &imports() const;
295     const QQmlScript::Parser &parser() const;
296
297     const QList<TypeReference> &resolvedTypes() const;
298     const QList<ScriptReference> &resolvedScripts() const;
299     const QSet<QString> &namespaces() const;
300
301     QQmlCompiledData *compiledData() const;
302
303     // Used by QQmlComponent to get notifications
304     struct TypeDataCallback {
305         ~TypeDataCallback() {}
306         virtual void typeDataProgress(QQmlTypeData *, qreal) {}
307         virtual void typeDataReady(QQmlTypeData *) {}
308     };
309     void registerCallback(TypeDataCallback *);
310     void unregisterCallback(TypeDataCallback *);
311
312 protected:
313     virtual void done();
314     virtual void completed();
315     virtual void dataReceived(const QByteArray &);
316     virtual void allDependenciesDone();
317     virtual void downloadProgressChanged(qreal);
318
319 private:
320     void resolveTypes();
321     void compile();
322
323     QQmlTypeLoader::Options m_options;
324
325     QQmlQmldirData *qmldirForUrl(const QUrl &);
326
327     QQmlScript::Parser scriptParser;
328     QQmlImports m_imports;
329
330     QList<ScriptReference> m_scripts;
331     QList<QQmlQmldirData *> m_qmldirs;
332
333     QSet<QString> m_namespaces;
334
335     QList<TypeReference> m_types;
336     bool m_typesResolved:1;
337
338     QQmlCompiledData *m_compiledData;
339
340     QList<TypeDataCallback *> m_callbacks;
341    
342     QQmlTypeLoader *m_typeLoader;
343 };
344
345 // QQmlScriptData instances are created, uninitialized, by the loader in the 
346 // load thread.  The first time they are used by the VME, they are initialized which
347 // creates their v8 objects and they are referenced and added to the  engine's cleanup
348 // list.  During QQmlCleanup::clear() all v8 resources are destroyed, and the 
349 // reference that was created is released but final deletion only occurs once all the
350 // references as released.  This is all intended to ensure that the v8 resources are
351 // only created and destroyed in the main thread :)
352 class Q_AUTOTEST_EXPORT QQmlScriptData : public QQmlCleanup, 
353                                                  public QQmlRefCount
354 {
355 public:
356     QQmlScriptData();
357     ~QQmlScriptData();
358
359     QUrl url;
360     QString urlString;
361     QQmlTypeNameCache *importCache;
362     QList<QQmlScriptBlob *> scripts;
363     QQmlScript::Object::ScriptBlock::Pragmas pragmas;
364
365     bool isInitialized() const { return hasEngine(); }
366     void initialize(QQmlEngine *);
367
368 protected:
369     virtual void clear(); // From QQmlCleanup
370
371 private:
372     friend class QQmlVME;
373     friend class QQmlScriptBlob;
374
375     bool m_loaded;
376     QByteArray m_programSource;
377     v8::Persistent<v8::Script> m_program;
378     v8::Persistent<v8::Object> m_value;
379 };
380
381 class Q_AUTOTEST_EXPORT QQmlScriptBlob : public QQmlDataBlob
382 {
383 public:
384     QQmlScriptBlob(const QUrl &, QQmlTypeLoader *);
385     ~QQmlScriptBlob();
386
387     struct ScriptReference
388     {
389         ScriptReference() : script(0) {}
390
391         QQmlScript::Location location;
392         QString qualifier;
393         QQmlScriptBlob *script;
394     };
395
396     QQmlScript::Object::ScriptBlock::Pragmas pragmas() const;
397
398     QQmlTypeLoader *typeLoader() const;
399     const QQmlImports &imports() const;
400
401     QQmlScriptData *scriptData() const;
402
403 protected:
404     virtual void dataReceived(const QByteArray &);
405     virtual void done();
406
407 private:
408     QQmlScript::Object::ScriptBlock::Pragmas m_pragmas;
409     QString m_source;
410
411     QQmlImports m_imports;
412     QList<ScriptReference> m_scripts;
413     QQmlScriptData *m_scriptData;
414
415     QQmlTypeLoader *m_typeLoader;
416 };
417
418 class Q_AUTOTEST_EXPORT QQmlQmldirData : public QQmlDataBlob
419 {
420 public:
421     QQmlQmldirData(const QUrl &);
422
423     const QQmlDirComponents &dirComponents() const;
424
425 protected:
426     virtual void dataReceived(const QByteArray &);
427
428 private:
429     QQmlDirComponents m_components;
430
431 };
432
433 QT_END_NAMESPACE
434
435 #endif // QQMLTYPELOADER_P_H