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 <memory>
31
32QT_BEGIN_NAMESPACE
33
34class QQmlEngine;
35class QQmlEngineExtensionInterface;
36class QQmlExtensionInterface;
37class QQmlNetworkAccessManagerFactory;
38class QQmlProfiler;
39class QQmlQmldirData;
40class QQmlScriptBlob;
41class QQmlTypeData;
43
44class Q_QML_EXPORT QQmlTypeLoader
45{
46 Q_DECLARE_TR_FUNCTIONS(QQmlTypeLoader)
47public:
48 using ChecksumCache = QQmlTypeLoaderThreadData::ChecksumCache;
50
51 class Q_QML_EXPORT Blob : public QQmlDataBlob
52 {
53 public:
54 Blob(const QUrl &url, QQmlDataBlob::Type type, QQmlTypeLoader *loader);
55 ~Blob() override;
56
57 const QQmlImports *imports() const { return m_importCache.data(); }
58
59 void setCachedUnitStatus(QQmlMetaType::CachedUnitLookupError status) { m_cachedUnitStatus = status; }
60
61 struct PendingImport
62 {
63 QString uri;
64 QString qualifier;
65
66 QV4::CompiledData::Import::ImportType type
67 = QV4::CompiledData::Import::ImportType::ImportLibrary;
68 QV4::CompiledData::Location location;
69
70 QQmlImports::ImportFlags flags;
71 quint8 precedence = 0;
72 int priority = 0;
73
74 QTypeRevision version;
75
76 PendingImport() = default;
77 PendingImport(const QQmlRefPointer<Blob> &blob, const QV4::CompiledData::Import *import,
78 QQmlImports::ImportFlags flags);
79 };
80 using PendingImportPtr = std::shared_ptr<PendingImport>;
81
82 void importQmldirScripts(const PendingImportPtr &import, const QQmlTypeLoaderQmldirContent &qmldir, const QUrl &qmldirUrl);
83 bool handleLocalQmldirForImport(
84 const PendingImportPtr &import, const QString &qmldirFilePath,
85 const QString &qmldirUrl, QList<QQmlError> *errors);
86
87 protected:
88 bool addImport(const QV4::CompiledData::Import *import, QQmlImports::ImportFlags,
89 QList<QQmlError> *errors);
90 bool addImport(const PendingImportPtr &import, QList<QQmlError> *errors);
91
92 bool fetchQmldir(
93 const QUrl &url, const PendingImportPtr &import, int priority,
94 QList<QQmlError> *errors);
95 bool updateQmldir(const QQmlRefPointer<QQmlQmldirData> &data, const PendingImportPtr &import, QList<QQmlError> *errors);
96
97 private:
98 bool addScriptImport(const PendingImportPtr &import);
99 bool addFileImport(const PendingImportPtr &import, QList<QQmlError> *errors);
100 bool addLibraryImport(const PendingImportPtr &import, QList<QQmlError> *errors);
101
102 virtual bool qmldirDataAvailable(const QQmlRefPointer<QQmlQmldirData> &, QList<QQmlError> *);
103
104 virtual void scriptImported(
105 const QQmlRefPointer<QQmlScriptBlob> &, const QV4::CompiledData::Location &,
106 const QString &, const QString &)
107 {
108 assertTypeLoaderThread();
109 }
110
111 void dependencyComplete(const QQmlDataBlob::Ptr &) override;
112
113 bool loadImportDependencies(
114 const PendingImportPtr &currentImport, const QString &qmldirUri,
115 QQmlImports::ImportFlags flags, QList<QQmlError> *errors);
116
117 protected:
118
119 bool registerPendingTypes(const PendingImportPtr &import);
120
121 bool loadDependentImports(
122 const QList<QQmlDirParser::Import> &imports, const QString &qualifier,
123 QTypeRevision version, quint8 precedence, QQmlImports::ImportFlags flags,
124 QList<QQmlError> *errors);
125 virtual QString stringAt(int) const { return QString(); }
126
127 QQmlRefPointer<QQmlImports> m_importCache;
128 QList<PendingImportPtr> m_unresolvedImports;
129 QList<QQmlRefPointer<QQmlQmldirData>> m_qmldirs;
130 QQmlMetaType::CachedUnitLookupError m_cachedUnitStatus = QQmlMetaType::CachedUnitLookupError::NoError;
131 };
132
133 QQmlTypeLoader(QV4::ExecutionEngine *engine);
134 ~QQmlTypeLoader();
135
136 template<
137 typename Engine,
138 typename EnginePrivate = QQmlEnginePrivate,
140 static QQmlTypeLoader *get(Engine *engine)
141 {
142 return engine->handle()->typeLoader();
143 }
144
145 template<
146 typename Engine,
148 static QQmlTypeLoader *get(Engine *engine)
149 {
150 return Engine::get(engine)->handle()->typeLoader();
151 }
152
153 static void sanitizeUNCPath(QString *path)
154 {
155 // This handles the UNC path case as when the path is retrieved from the QUrl it
156 // will convert the host name from upper case to lower case. So the absoluteFilePath
157 // is changed at this point to make sure it will match later on in that case.
158 if (path->startsWith(QStringLiteral("//"))) {
159 // toLocalFile() since that faithfully restores all the things you can do to a
160 // path but not a URL, in particular weird characters like '%'.
161 *path = QUrl::fromLocalFile(*path).toLocalFile();
162 }
163 }
164
165 // We can't include QQmlTypeData here.
166 // Use a template specialized only for QQmlTypeData::TypeReference instead.
167 template<typename TypeReference>
169 QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache,
170 const QList<TypeReference> &compositeSingletons)
171 {
172 QQmlTypeLoaderThreadDataPtr data(&m_data);
173
174 QCryptographicHash hash(QCryptographicHash::Md5);
175 return (resolvedTypeCache->addToHash(&hash, &data->checksumCache)
176 && addTypeReferenceChecksumsToHash(
177 compositeSingletons, &data->checksumCache, &hash))
178 ? hash.result()
179 : QByteArray();
180 }
181
183 const QUrl &unNormalizedUrl, Mode mode = PreferSynchronous);
185 const QByteArray &data, const QUrl &url, Mode mode = PreferSynchronous);
186
188 const QUrl &unNormalizedUrl, Mode mode = PreferSynchronous);
189
191 const QUrl &relativeUrl, const QV4::CompiledData::Unit *unit);
192
193 QQmlRefPointer<QQmlScriptBlob> getScript(const QUrl &unNormalizedUrl, const QUrl &relativeUrl);
195
196 QString absoluteFilePath(const QString &path);
197
198 bool fileExists(const QString &filePath)
199 {
200 Q_ASSERT(!filePath.endsWith(QLatin1Char('/')));
201 const qsizetype pastLastSlash = filePath.lastIndexOf(QLatin1Char('/')) + 1;
202 return fileExists(
203 filePath.left(pastLastSlash - 1),
204 filePath.mid(pastLastSlash, filePath.size() - pastLastSlash));
205 }
206
207 bool fileExists(const QString &dirPath, const QString &file);
208 bool directoryExists(const QString &path);
209
210 const QQmlTypeLoaderQmldirContent qmldirContent(const QString &filePath);
211 void setQmldirContent(const QString &filePath, const QString &content);
212
213 void clearCache();
214 void trimCache();
215
216 bool isTypeLoaded(const QUrl &url) const;
217 bool isScriptLoaded(const QUrl &url) const;
218
220 const QQmlDataBlob::Ptr &blob, const QByteArray &data, Mode mode = PreferSynchronous);
221
222 void drop(const QQmlDataBlob::Ptr &blob);
223
224 void initializeEngine(QQmlEngineExtensionInterface *, const char *);
225 void initializeEngine(QQmlExtensionInterface *, const char *);
226 void invalidate();
227
228 void addUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor);
229 void removeUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor);
231 QUrl interceptUrl(const QUrl &url, QQmlAbstractUrlInterceptor::DataType type) const;
232 bool hasUrlInterceptors() const;
233
234#if !QT_CONFIG(qml_debug)
235 quintptr profiler() const { return 0; }
236 void setProfiler(quintptr) {}
237#else
238 QQmlProfiler *profiler() const
239 {
240 QQmlTypeLoaderConfiguredDataConstPtr data(&m_data);
241 return data->profiler.data();
242 }
243 void setProfiler(QQmlProfiler *profiler);
244#endif // QT_CONFIG(qml_debug)
245
247 {
248 QQmlTypeLoaderConfiguredDataConstPtr data(&m_data);
249 return data->importPaths;
250 }
251 void setImportPathList(const QStringList &paths);
252 void addImportPath(const QString& dir);
253
255 {
256 QQmlTypeLoaderConfiguredDataConstPtr data(&m_data);
257 return data->pluginPaths;
258 }
259 void setPluginPathList(const QStringList &paths);
260 void addPluginPath(const QString& path);
261
262 void setPluginInitialized(const QString &plugin)
263 {
264 QQmlTypeLoaderThreadDataPtr data(&m_data);
265 data->initializedPlugins.insert(plugin);
266 }
267 bool isPluginInitialized(const QString &plugin) const
268 {
269 QQmlTypeLoaderThreadDataConstPtr data(&m_data);
270 return data->initializedPlugins.contains(plugin);
271 }
272
273 void setModulePluginProcessingDone(const QString &module)
274 {
275 QQmlTypeLoaderThreadDataPtr data(&m_data);
276 data->modulesForWhichPluginsHaveBeenProcessed.insert(module);
277 }
278 bool isModulePluginProcessingDone(const QString &module)
279 {
280 QQmlTypeLoaderThreadDataConstPtr data(&m_data);
281 return data->modulesForWhichPluginsHaveBeenProcessed.contains(module);
282 }
283
284#if QT_CONFIG(qml_network)
285 QQmlNetworkAccessManagerFactoryPtrConst networkAccessManagerFactory() const;
286 void setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory);
287 QNetworkAccessManager *createNetworkAccessManager(QObject *parent) const;
288#endif
289
290 bool writeCacheFile();
291 bool readCacheFile();
292 bool isDebugging();
293
294private:
295 friend struct PlainLoader;
296 friend struct CachedLoader;
297 friend struct StaticLoader;
298
299 friend class QQmlDataBlob;
301#if QT_CONFIG(qml_network)
302 friend class QQmlTypeLoaderNetworkReplyProxy;
303#endif // qml_network
304
305 enum PathType { Local, Remote, LocalOrRemote };
306
307 enum LocalQmldirResult {
308 QmldirFound,
309 QmldirNotFound,
310 QmldirInterceptedToRemote,
311 QmldirRejected
312 };
313
314 QQmlTypeLoaderThread *thread() const { return m_data.thread(); }
315 QV4::ExecutionEngine *engine() const { return m_data.engine(); }
316
317 void startThread();
318 void shutdownThread();
319 QQmlTypeLoaderThread *ensureThread()
320 {
321 if (!thread())
322 startThread();
323 return thread();
324 }
325
326 void trimCache(const QQmlTypeLoaderSharedDataPtr &data);
327
328 void loadThread(const QQmlDataBlob::Ptr &);
329 void loadWithStaticDataThread(const QQmlDataBlob::Ptr &, const QByteArray &);
330 void loadWithCachedUnitThread(const QQmlDataBlob::Ptr &blob, const QQmlPrivate::CachedQmlUnit *unit);
331#if QT_CONFIG(qml_network)
332 void networkReplyFinished(QNetworkReply *);
333 void networkReplyProgress(QNetworkReply *, qint64, qint64);
334#endif
335
336 enum class DataOrigin { Device, Static };
337 void setData(const QQmlDataBlob::Ptr &, const QByteArray &, DataOrigin);
338 void setData(const QQmlDataBlob::Ptr &, const QString &fileName);
339 void setData(const QQmlDataBlob::Ptr &, const QQmlDataBlob::SourceCodeData &);
340 void setCachedUnit(const QQmlDataBlob::Ptr &blob, const QQmlPrivate::CachedQmlUnit *unit);
341
342 QStringList importPathList(PathType type) const;
343 void clearQmldirInfo();
344
345 LocalQmldirResult locateLocalQmldir(
346 QQmlTypeLoader::Blob *blob, const QQmlTypeLoader::Blob::PendingImportPtr &import,
347 QList<QQmlError> *errors);
348
349 void load(const QQmlDataBlob::Ptr &blob, Mode mode = PreferSynchronous);
350 void loadWithCachedUnit(
351 const QQmlDataBlob::Ptr &blob, const QQmlPrivate::CachedQmlUnit *unit,
352 Mode mode = PreferSynchronous);
353
354 template<typename Loader>
355 void doLoad(const Loader &loader, const QQmlDataBlob::Ptr &blob, Mode mode);
356 void updateTypeCacheTrimThreshold(const QQmlTypeLoaderSharedDataPtr &data);
357
358 template<typename TypeReference>
359 static bool addTypeReferenceChecksumsToHash(
360 const QList<TypeReference> &typeRefs,
361 QHash<quintptr, QByteArray> *checksums, QCryptographicHash *hash)
362 {
363 for (const auto &typeRef: typeRefs) {
364 if (typeRef.typeData) {
365 const auto unit = typeRef.typeData->compilationUnit()->unitData();
366 hash->addData({unit->md5Checksum, sizeof(unit->md5Checksum)});
367 } else if (const QMetaObject *mo = typeRef.type.metaObject()) {
368 const auto propertyCache = QQmlMetaType::propertyCache(mo);
369 bool ok = false;
370 hash->addData(propertyCache->checksum(checksums, &ok));
371 if (!ok)
372 return false;
373 }
374 }
375 return true;
376 }
377
378 template<typename Blob>
379 QQmlRefPointer<Blob> finalizeBlob(QQmlRefPointer<Blob> &&blob, QQmlTypeLoader::Mode mode)
380 {
381 QQmlMetaType::CachedUnitLookupError error = QQmlMetaType::CachedUnitLookupError::NoError;
382 const QQmlMetaType::CacheMode cacheMode = aotCacheMode();
383 if (const QQmlPrivate::CachedQmlUnit *cachedUnit = (cacheMode != QQmlMetaType::RejectAll)
384 ? QQmlMetaType::findCachedCompilationUnit(blob->url(), cacheMode, &error)
385 : nullptr) {
386 loadWithCachedUnit(QQmlDataBlob::Ptr(blob.data()), cachedUnit, mode);
387 } else {
388 blob->setCachedUnitStatus(error);
389 load(QQmlDataBlob::Ptr(blob.data()), mode);
390 }
391
392 return blob;
393 }
394
395 QQmlMetaType::CacheMode aotCacheMode();
396
397 QQmlTypeLoaderLockedData m_data;
398};
399
400QT_END_NAMESPACE
401
402#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
bool fileExists(const QString &filePath)
QStringList pluginPathList() const
void drop(const QQmlDataBlob::Ptr &blob)
void initializeEngine(QQmlExtensionInterface *, const char *)
bool fileExists(const QString &dirPath, const QString &file)
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
QString absoluteFilePath(const QString &path)
Returns the absolute filename of path via a directory cache.
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)
void addImportPath(const QString &dir)
void setPluginPathList(const QStringList &paths)
bool hasUrlInterceptors() const
QList< QQmlAbstractUrlInterceptor * > urlInterceptors() const
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