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);
199
200 bool fileExists(const QString &filePath)
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);
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();
217
218 bool isTypeLoaded(const QUrl &url) const;
219 bool isScriptLoaded(const QUrl &url) const;
220
222 const QQmlDataBlob::Ptr &blob, const QByteArray &data, Mode mode = PreferSynchronous);
223
224 void drop(const QQmlDataBlob::Ptr &blob);
225
226 void initializeEngine(QQmlEngineExtensionInterface *, const char *);
227 void initializeEngine(QQmlExtensionInterface *, const char *);
228 void invalidate();
229
230 void addUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor);
231 void removeUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor);
233 QUrl interceptUrl(const QUrl &url, QQmlAbstractUrlInterceptor::DataType type) const;
234 bool hasUrlInterceptors() const;
235
236#if !QT_CONFIG(qml_debug)
237 quintptr profiler() const { return 0; }
238 void setProfiler(quintptr) {}
239#else
240 QQmlProfiler *profiler() const
241 {
242 QQmlTypeLoaderConfiguredDataConstPtr data(&m_data);
243 return data->profiler.data();
244 }
245 void setProfiler(QQmlProfiler *profiler);
246#endif // QT_CONFIG(qml_debug)
247
249 {
250 QQmlTypeLoaderConfiguredDataConstPtr data(&m_data);
251 return data->importPaths;
252 }
253 void setImportPathList(const QStringList &paths);
254 void addImportPath(const QString& dir);
255
257 {
258 QQmlTypeLoaderConfiguredDataConstPtr data(&m_data);
259 return data->pluginPaths;
260 }
261 void setPluginPathList(const QStringList &paths);
262 void addPluginPath(const QString& path);
263
264 void setPluginInitialized(const QString &plugin)
265 {
266 QQmlTypeLoaderThreadDataPtr data(&m_data);
267 data->initializedPlugins.insert(plugin);
268 }
269 bool isPluginInitialized(const QString &plugin) const
270 {
271 QQmlTypeLoaderThreadDataConstPtr data(&m_data);
272 return data->initializedPlugins.contains(plugin);
273 }
274
275 void setModulePluginProcessingDone(const QString &module)
276 {
277 QQmlTypeLoaderThreadDataPtr data(&m_data);
278 data->modulesForWhichPluginsHaveBeenProcessed.insert(module);
279 }
280 bool isModulePluginProcessingDone(const QString &module)
281 {
282 QQmlTypeLoaderThreadDataConstPtr data(&m_data);
283 return data->modulesForWhichPluginsHaveBeenProcessed.contains(module);
284 }
285
286#if QT_CONFIG(qml_network)
287 QQmlNetworkAccessManagerFactoryPtrConst networkAccessManagerFactory() const;
288 void setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory);
289 QNetworkAccessManager *createNetworkAccessManager(QObject *parent) const;
290#endif
291
292 bool writeCacheFile();
293 bool readCacheFile();
294 bool isDebugging();
295
296private:
297 friend struct PlainLoader;
298 friend struct CachedLoader;
299 friend struct StaticLoader;
300
301 friend class QQmlDataBlob;
303#if QT_CONFIG(qml_network)
304 friend class QQmlTypeLoaderNetworkReplyProxy;
305#endif // qml_network
306
307 enum PathType { Local, Remote, LocalOrRemote };
308
309 enum LocalQmldirResult {
310 QmldirFound,
311 QmldirNotFound,
312 QmldirInterceptedToRemote,
313 QmldirRejected
314 };
315
316 QQmlTypeLoaderThread *thread() const { return m_data.thread(); }
317 QV4::ExecutionEngine *engine() const { return m_data.engine(); }
318
319 void startThread();
320 void shutdownThread();
321 QQmlTypeLoaderThread *ensureThread()
322 {
323 if (!thread())
324 startThread();
325 return thread();
326 }
327
328 void trimCache(const QQmlTypeLoaderSharedDataPtr &data);
329
330 void loadThread(const QQmlDataBlob::Ptr &);
331 void loadWithStaticDataThread(const QQmlDataBlob::Ptr &, const QByteArray &);
332 void loadWithCachedUnitThread(const QQmlDataBlob::Ptr &blob, const QQmlPrivate::CachedQmlUnit *unit);
333#if QT_CONFIG(qml_network)
334 void networkReplyFinished(QNetworkReply *);
335 void networkReplyProgress(QNetworkReply *, qint64, qint64);
336#endif
337
338 enum class DataOrigin { Device, Static };
339 void setData(const QQmlDataBlob::Ptr &, const QByteArray &, DataOrigin);
340 void setData(const QQmlDataBlob::Ptr &, const QString &fileName);
341 void setData(const QQmlDataBlob::Ptr &, const QQmlDataBlob::SourceCodeData &);
342 void setCachedUnit(const QQmlDataBlob::Ptr &blob, const QQmlPrivate::CachedQmlUnit *unit);
343
344 QStringList importPathList(PathType type) const;
345 void clearQmldirInfo();
346
347 LocalQmldirResult locateLocalQmldir(
348 QQmlTypeLoader::Blob *blob, const QQmlTypeLoader::Blob::PendingImportPtr &import,
349 QList<QQmlError> *errors);
350
351 void load(const QQmlDataBlob::Ptr &blob, Mode mode = PreferSynchronous);
352 void loadWithCachedUnit(
353 const QQmlDataBlob::Ptr &blob, const QQmlPrivate::CachedQmlUnit *unit,
354 Mode mode = PreferSynchronous);
355
356 template<typename Loader>
357 void doLoad(const Loader &loader, const QQmlDataBlob::Ptr &blob, Mode mode);
358 void updateTypeCacheTrimThreshold(const QQmlTypeLoaderSharedDataPtr &data);
359
360 template<typename TypeReference>
361 static bool addTypeReferenceChecksumsToHash(
362 const QList<TypeReference> &typeRefs,
363 QHash<quintptr, QByteArray> *checksums, QCryptographicHash *hash)
364 {
365 for (const auto &typeRef: typeRefs) {
366 if (typeRef.typeData) {
367 const auto unit = typeRef.typeData->compilationUnit()->unitData();
368 hash->addData({unit->md5Checksum, sizeof(unit->md5Checksum)});
369 } else if (const QMetaObject *mo = typeRef.type.metaObject()) {
370 const auto propertyCache = QQmlMetaType::propertyCache(mo);
371 bool ok = false;
372 hash->addData(propertyCache->checksum(checksums, &ok));
373 if (!ok)
374 return false;
375 }
376 }
377 return true;
378 }
379
380 template<typename Blob>
381 QQmlRefPointer<Blob> finalizeBlob(QQmlRefPointer<Blob> &&blob, QQmlTypeLoader::Mode mode)
382 {
383 QQmlMetaType::CachedUnitLookupError error = QQmlMetaType::CachedUnitLookupError::NoError;
384 const QQmlMetaType::CacheMode cacheMode = aotCacheMode();
385 if (const QQmlPrivate::CachedQmlUnit *cachedUnit = (cacheMode != QQmlMetaType::RejectAll)
386 ? QQmlMetaType::findCachedCompilationUnit(blob->url(), cacheMode, &error)
387 : nullptr) {
388 loadWithCachedUnit(QQmlDataBlob::Ptr(blob.data()), cachedUnit, mode);
389 } else {
390 blob->setCachedUnitStatus(error);
391 load(QQmlDataBlob::Ptr(blob.data()), mode);
392 }
393
394 return blob;
395 }
396
397 QQmlMetaType::CacheMode aotCacheMode();
398
399 QQmlTypeLoaderLockedData m_data;
400};
401
402QT_END_NAMESPACE
403
404#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