Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmltypeloader_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant
4
5#ifndef QQMLTYPELOADER_P_H
6#define QQMLTYPELOADER_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <private/qqmldatablob_p.h>
20#include <private/qqmlimport_p.h>
21#include <private/qqmlmetatype_p.h>
22#include <private/qqmltypeloaderdata_p.h>
23#include <private/qqmltypeloaderthread_p.h>
24#include <private/qv4compileddata_p.h>
25#include <private/qv4engine_p.h>
26
27#include <QtQml/qtqmlglobal.h>
28#include <QtQml/qqmlerror.h>
29
30#include <QtCore/qtyperevision.h>
31
32#include <memory>
33
34QT_BEGIN_NAMESPACE
35
36class QQmlEngine;
37class QQmlEngineExtensionInterface;
38class QQmlExtensionInterface;
39class QQmlNetworkAccessManagerFactory;
40class QQmlProfiler;
41class QQmlQmldirData;
42class QQmlScriptBlob;
43class QQmlTypeData;
45
46class Q_QML_EXPORT QQmlTypeLoader
47{
48 Q_DECLARE_TR_FUNCTIONS(QQmlTypeLoader)
49public:
50 using ChecksumCache = QQmlTypeLoaderThreadData::ChecksumCache;
52
53 class Q_QML_EXPORT Blob : public QQmlDataBlob
54 {
55 public:
56 Blob(const QUrl &url, QQmlDataBlob::Type type, QQmlTypeLoader *loader);
57 ~Blob() override;
58
59 const QQmlImports *imports() const { return m_importCache.data(); }
60
61 void setCachedUnitStatus(QQmlMetaType::CachedUnitLookupError status) { m_cachedUnitStatus = status; }
62
63 struct PendingImport
64 {
65 QString uri;
66 QString qualifier;
67
68 QV4::CompiledData::Import::ImportType type
69 = QV4::CompiledData::Import::ImportType::ImportLibrary;
70 QV4::CompiledData::Location location;
71
72 QQmlImports::ImportFlags flags;
73 quint8 precedence = 0;
74 int priority = 0;
75
76 QTypeRevision version;
77
78 PendingImport() = default;
79 PendingImport(const QQmlRefPointer<Blob> &blob, const QV4::CompiledData::Import *import,
80 QQmlImports::ImportFlags flags);
81 };
82 using PendingImportPtr = std::shared_ptr<PendingImport>;
83
84 void importQmldirScripts(const PendingImportPtr &import, const QQmlTypeLoaderQmldirContent &qmldir, const QUrl &qmldirUrl);
85 bool handleLocalQmldirForImport(
86 const PendingImportPtr &import, const QString &qmldirFilePath,
87 const QString &qmldirUrl, QList<QQmlError> *errors);
88
89 protected:
90 bool addImport(const QV4::CompiledData::Import *import, QQmlImports::ImportFlags,
91 QList<QQmlError> *errors);
92 bool addImport(const PendingImportPtr &import, QList<QQmlError> *errors);
93
94 bool fetchQmldir(
95 const QUrl &url, const PendingImportPtr &import, int priority,
96 QList<QQmlError> *errors);
97 bool updateQmldir(const QQmlRefPointer<QQmlQmldirData> &data, const PendingImportPtr &import, QList<QQmlError> *errors);
98
99 private:
100 bool addScriptImport(const PendingImportPtr &import);
101 bool addFileImport(const PendingImportPtr &import, QList<QQmlError> *errors);
102 bool addLibraryImport(const PendingImportPtr &import, QList<QQmlError> *errors);
103
104 virtual bool qmldirDataAvailable(const QQmlRefPointer<QQmlQmldirData> &, QList<QQmlError> *);
105
106 virtual void scriptImported(
107 const QQmlRefPointer<QQmlScriptBlob> &, const QV4::CompiledData::Location &,
108 const QString &, const QString &)
109 {
110 assertTypeLoaderThread();
111 }
112
113 void dependencyComplete(const QQmlDataBlob::Ptr &) override;
114
115 bool loadImportDependencies(
116 const PendingImportPtr &currentImport, const QString &qmldirUri,
117 QQmlImports::ImportFlags flags, QList<QQmlError> *errors);
118
119 protected:
120
121 bool registerPendingTypes(const PendingImportPtr &import);
122
123 bool loadDependentImports(
124 const QList<QQmlDirParser::Import> &imports, const QString &qualifier,
125 QTypeRevision version, quint8 precedence, QQmlImports::ImportFlags flags,
126 QList<QQmlError> *errors);
127 virtual QString stringAt(int) const { return QString(); }
128
129 QQmlRefPointer<QQmlImports> m_importCache;
130 QList<PendingImportPtr> m_unresolvedImports;
131 QList<QQmlRefPointer<QQmlQmldirData>> m_qmldirs;
132 QQmlMetaType::CachedUnitLookupError m_cachedUnitStatus = QQmlMetaType::CachedUnitLookupError::NoError;
133 };
134
135 QQmlTypeLoader(QV4::ExecutionEngine *engine);
136 ~QQmlTypeLoader();
137
138 template<
139 typename Engine,
140 typename EnginePrivate = QQmlEnginePrivate,
142 static QQmlTypeLoader *get(Engine *engine)
143 {
144 return engine->handle()->typeLoader();
145 }
146
147 template<
148 typename Engine,
150 static QQmlTypeLoader *get(Engine *engine)
151 {
152 return Engine::get(engine)->handle()->typeLoader();
153 }
154
155 static void sanitizeUNCPath(QString *path)
156 {
157 // This handles the UNC path case as when the path is retrieved from the QUrl it
158 // will convert the host name from upper case to lower case. So the absoluteFilePath
159 // is changed at this point to make sure it will match later on in that case.
160 if (path->startsWith(QStringLiteral("//"))) {
161 // toLocalFile() since that faithfully restores all the things you can do to a
162 // path but not a URL, in particular weird characters like '%'.
163 *path = QUrl::fromLocalFile(*path).toLocalFile();
164 }
165 }
166
167 // We can't include QQmlTypeData here.
168 // Use a template specialized only for QQmlTypeData::TypeReference instead.
169 template<typename TypeReference>
171 QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache,
172 const QList<TypeReference> &compositeSingletons)
173 {
174 QQmlTypeLoaderThreadDataPtr data(&m_data);
175
176 QCryptographicHash hash(QCryptographicHash::Md5);
177 return (resolvedTypeCache->addToHash(&hash, &data->checksumCache)
178 && addTypeReferenceChecksumsToHash(
179 compositeSingletons, &data->checksumCache, &hash))
180 ? hash.result()
181 : QByteArray();
182 }
183
185 const QUrl &unNormalizedUrl, Mode mode = PreferSynchronous);
187 const QByteArray &data, const QUrl &url, Mode mode = PreferSynchronous);
188
190 const QUrl &unNormalizedUrl, Mode mode = PreferSynchronous);
191
193 const QUrl &relativeUrl, const QV4::CompiledData::Unit *unit);
194
195 QQmlRefPointer<QQmlScriptBlob> getScript(const QUrl &unNormalizedUrl, const QUrl &relativeUrl);
197
198 QString absoluteFilePath(const QString &path) const;
199
200 bool fileExists(const QString &filePath) const
201 {
202 Q_ASSERT(!filePath.endsWith(QLatin1Char('/')));
203 const qsizetype pastLastSlash = filePath.lastIndexOf(QLatin1Char('/')) + 1;
204 return fileExists(
205 filePath.left(pastLastSlash - 1),
206 filePath.mid(pastLastSlash, filePath.size() - pastLastSlash));
207 }
208
209 bool fileExists(const QString &dirPath, const QString &file) const;
210 bool directoryExists(const QString &path);
211
212 const QQmlTypeLoaderQmldirContent qmldirContent(const QString &filePath);
213 void setQmldirContent(const QString &filePath, const QString &content);
214
215 void clearCache();
216 void trimCache();
218 const QUrl &url,
219 const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit);
220
221 bool isTypeLoaded(const QUrl &url) const;
222 bool isScriptLoaded(const QUrl &url) const;
223
225 const QQmlDataBlob::Ptr &blob, const QByteArray &data, Mode mode = PreferSynchronous);
226
227 void drop(const QQmlDataBlob::Ptr &blob);
228
229 void initializeEngine(QQmlEngineExtensionInterface *, const char *);
230 void initializeEngine(QQmlExtensionInterface *, const char *);
231 void invalidate();
232
233 void addUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor);
234 void removeUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor);
236 QUrl interceptUrl(const QUrl &url, QQmlAbstractUrlInterceptor::DataType type) const;
237 bool hasUrlInterceptors() const;
238
239#if !QT_CONFIG(qml_debug)
240 quintptr profiler() const { return 0; }
241 void setProfiler(quintptr) {}
242#else
243 QQmlProfiler *profiler() const
244 {
245 QQmlTypeLoaderConfiguredDataConstPtr data(&m_data);
246 return data->profiler.data();
247 }
248 void setProfiler(QQmlProfiler *profiler);
249#endif // QT_CONFIG(qml_debug)
250
252 {
253 QQmlTypeLoaderConfiguredDataConstPtr data(&m_data);
254 return data->importPaths;
255 }
256 void setImportPathList(const QStringList &paths);
257 void addImportPath(const QString& dir);
258
260 {
261 QQmlTypeLoaderConfiguredDataConstPtr data(&m_data);
262 return data->pluginPaths;
263 }
264 void setPluginPathList(const QStringList &paths);
265 void addPluginPath(const QString& path);
266
267 void setPluginInitialized(const QString &plugin)
268 {
269 QQmlTypeLoaderThreadDataPtr data(&m_data);
270 data->initializedPlugins.insert(plugin);
271 }
272 bool isPluginInitialized(const QString &plugin) const
273 {
274 QQmlTypeLoaderThreadDataConstPtr data(&m_data);
275 return data->initializedPlugins.contains(plugin);
276 }
277
278 void setModulePluginProcessingDone(const QString &module)
279 {
280 QQmlTypeLoaderThreadDataPtr data(&m_data);
281 data->modulesForWhichPluginsHaveBeenProcessed.insert(module);
282 }
283 bool isModulePluginProcessingDone(const QString &module)
284 {
285 QQmlTypeLoaderThreadDataConstPtr data(&m_data);
286 return data->modulesForWhichPluginsHaveBeenProcessed.contains(module);
287 }
288
289#if QT_CONFIG(qml_network)
290 QQmlNetworkAccessManagerFactoryPtrConst networkAccessManagerFactory() const;
291 void setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory);
292 QNetworkAccessManager *createNetworkAccessManager(QObject *parent) const;
293#endif
294
295 bool writeCacheFile();
296 bool readCacheFile();
297 bool isDebugging();
298
299private:
300 friend struct PlainLoader;
301 friend struct CachedLoader;
302 friend struct StaticLoader;
303
304 friend class QQmlDataBlob;
306#if QT_CONFIG(qml_network)
307 friend class QQmlTypeLoaderNetworkReplyProxy;
308#endif // qml_network
309
310 enum PathType { Local, Remote, LocalOrRemote };
311
312 enum LocalQmldirResult {
313 QmldirFound,
314 QmldirNotFound,
315 QmldirInterceptedToRemote,
316 QmldirRejected
317 };
318
319 QQmlTypeLoaderThread *thread() const { return m_data.thread(); }
320 QV4::ExecutionEngine *engine() const { return m_data.engine(); }
321
322 void startThread();
323 void shutdownThread();
324 QQmlTypeLoaderThread *ensureThread()
325 {
326 if (!thread())
327 startThread();
328 return thread();
329 }
330
331 void trimCache(const QQmlTypeLoaderSharedDataPtr &data);
332
333 void loadThread(const QQmlDataBlob::Ptr &);
334 void loadWithStaticDataThread(const QQmlDataBlob::Ptr &, const QByteArray &);
335 void loadWithCachedUnitThread(const QQmlDataBlob::Ptr &blob, const QQmlPrivate::CachedQmlUnit *unit);
336#if QT_CONFIG(qml_network)
337 void networkReplyFinished(QNetworkReply *);
338 void networkReplyProgress(QNetworkReply *, qint64, qint64);
339#endif
340
341 enum class DataOrigin { Device, Static };
342 void setData(const QQmlDataBlob::Ptr &, const QByteArray &, DataOrigin);
343 void setData(const QQmlDataBlob::Ptr &, const QString &fileName);
344 void setData(const QQmlDataBlob::Ptr &, const QQmlDataBlob::SourceCodeData &);
345 void setCachedUnit(const QQmlDataBlob::Ptr &blob, const QQmlPrivate::CachedQmlUnit *unit);
346
347 QStringList importPathList(PathType type) const;
348 void clearQmldirInfo();
349
350 LocalQmldirResult locateLocalQmldir(
351 QQmlTypeLoader::Blob *blob, const QQmlTypeLoader::Blob::PendingImportPtr &import,
352 QList<QQmlError> *errors);
353
354 void load(const QQmlDataBlob::Ptr &blob, Mode mode = PreferSynchronous);
355 void loadWithCachedUnit(
356 const QQmlDataBlob::Ptr &blob, const QQmlPrivate::CachedQmlUnit *unit,
357 Mode mode = PreferSynchronous);
358
359 template<typename Loader>
360 void doLoad(const Loader &loader, const QQmlDataBlob::Ptr &blob, Mode mode);
361 void updateTypeCacheTrimThreshold(const QQmlTypeLoaderSharedDataPtr &data);
362
363 template<typename TypeReference>
364 static bool addTypeReferenceChecksumsToHash(
365 const QList<TypeReference> &typeRefs,
366 QHash<quintptr, QByteArray> *checksums, QCryptographicHash *hash)
367 {
368 for (const auto &typeRef: typeRefs) {
369 if (typeRef.typeData) {
370 const auto unit = typeRef.typeData->compilationUnit()->unitData();
371 hash->addData({unit->md5Checksum, sizeof(unit->md5Checksum)});
372 } else if (const QMetaObject *mo = typeRef.type.metaObject()) {
373 const auto propertyCache = QQmlMetaType::propertyCache(mo);
374 bool ok = false;
375 hash->addData(propertyCache->checksum(checksums, &ok));
376 if (!ok)
377 return false;
378 }
379 }
380 return true;
381 }
382
383 template<typename Blob>
384 QQmlRefPointer<Blob> finalizeBlob(QQmlRefPointer<Blob> &&blob, QQmlTypeLoader::Mode mode)
385 {
386 QQmlMetaType::CachedUnitLookupError error = QQmlMetaType::CachedUnitLookupError::NoError;
387 const QQmlMetaType::CacheMode cacheMode = aotCacheMode();
388 if (const QQmlPrivate::CachedQmlUnit *cachedUnit = (cacheMode != QQmlMetaType::RejectAll)
389 ? QQmlMetaType::findCachedCompilationUnit(blob->url(), cacheMode, &error)
390 : nullptr) {
391 loadWithCachedUnit(QQmlDataBlob::Ptr(blob.data()), cachedUnit, mode);
392 } else {
393 blob->setCachedUnitStatus(error);
394 load(QQmlDataBlob::Ptr(blob.data()), mode);
395 }
396
397 return blob;
398 }
399
400 QQmlMetaType::CacheMode aotCacheMode();
401
402 QQmlTypeLoaderLockedData m_data;
403};
404
405QT_END_NAMESPACE
406
407#endif // QQMLTYPELOADER_P_H
QQmlEngine * engine() const
Return the QQmlEngine this incubation controller is set on, or 0 if it has not been set on any engine...
The QQmlTypeLoader class abstracts loading files and their dependencies over the network.
void setModulePluginProcessingDone(const QString &module)
bool isPluginInitialized(const QString &plugin) const
QStringList pluginPathList() const
void drop(const QQmlDataBlob::Ptr &blob)
void initializeEngine(QQmlExtensionInterface *, const char *)
void loadWithStaticData(const QQmlDataBlob::Ptr &blob, const QByteArray &data, Mode mode=PreferSynchronous)
Load the provided blob with data.
bool isTypeLoaded(const QUrl &url) const
QUrl interceptUrl(const QUrl &url, QQmlAbstractUrlInterceptor::DataType type) const
QQmlRefPointer< QV4::CompiledData::CompilationUnit > injectModule(const QUrl &relativeUrl, const QV4::CompiledData::Unit *unit)
QQmlRefPointer< QQmlTypeData > getType(const QByteArray &data, const QUrl &url, Mode mode=PreferSynchronous)
Returns a QQmlTypeData for the given data with the provided base url.
static void sanitizeUNCPath(QString *path)
QQmlRefPointer< QQmlTypeData > getType(const QUrl &unNormalizedUrl, Mode mode=PreferSynchronous)
Returns a QQmlTypeData for the specified url.
bool isScriptLoaded(const QUrl &url) const
bool isModulePluginProcessingDone(const QString &module)
void setPluginInitialized(const QString &plugin)
friend class QQmlDataBlob
static QQmlTypeLoader * get(Engine *engine)
bool directoryExists(const QString &path)
Returns true if the path is a directory via a directory cache.
void setImportPathList(const QStringList &paths)
bool fileExists(const QString &filePath) const
void replaceCachedCompilationUnit(const QUrl &url, const QQmlRefPointer< QV4::CompiledData::CompilationUnit > &unit)
void addImportPath(const QString &dir)
bool fileExists(const QString &dirPath, const QString &file) const
void setPluginPathList(const QStringList &paths)
bool hasUrlInterceptors() const
QList< QQmlAbstractUrlInterceptor * > urlInterceptors() const
QString absoluteFilePath(const QString &path) const
Returns the absolute filename of path via a directory cache.
void initializeEngine(QQmlEngineExtensionInterface *, const char *)
QByteArray hashDependencies(QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache, const QList< TypeReference > &compositeSingletons)
void addUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor)
QQmlRefPointer< QQmlQmldirData > getQmldir(const QUrl &)
Returns a QQmlQmldirData for url.
QQmlRefPointer< QQmlScriptBlob > getScript(const QUrl &unNormalizedUrl, const QUrl &relativeUrl)
Return a QQmlScriptBlob for unNormalizedUrl or relativeUrl.
const QQmlTypeLoaderQmldirContent qmldirContent(const QString &filePath)
Return a QQmlTypeLoaderQmldirContent for absoluteFilePath.
void clearCache()
Clears cached information about loaded files, including any type data, scripts and qmldir information...
static QQmlTypeLoader * get(Engine *engine)
void removeUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor)
QQmlRefPointer< QQmlScriptBlob > getScript(const QUrl &unNormalizedUrl, Mode mode=PreferSynchronous)
void addPluginPath(const QString &path)
void setQmldirContent(const QString &filePath, const QString &content)
QStringList importPathList() const