Return a QmldirContent for absoluteFilePath. The QmldirContent may be cached.
\a filePath is either a bundle URL, or a local file path.
+
+It can also be a remote path for a remote directory import, but it will have been cached by now in this case.
*/
-const QQmlTypeLoader::QmldirContent *QQmlTypeLoader::qmldirContent(const QString &filePath, const QString &uriHint)
-{
+const QQmlTypeLoader::QmldirContent *QQmlTypeLoader::qmldirContent(const QString &filePathIn, const QString &uriHint)
+{
+ QUrl url(filePathIn); //May already contain bundle or http scheme
+ if (url.scheme() == QLatin1String("http") || url.scheme() == QLatin1String("https"))
+ return *(m_importQmlDirCache.value(filePathIn)); //Can't load the remote here, but should be cached
+ else if (!QQmlFile::isBundle(filePathIn))
+ url = QUrl::fromLocalFile(filePathIn);
+ if (engine() && engine()->urlInterceptor())
+ url = engine()->urlInterceptor()->intercept(url, QQmlAbstractUrlInterceptor::QmldirFile);
+ Q_ASSERT(url.scheme() == QLatin1String("file") || url.scheme() == QLatin1String("bundle"));
+ QString filePath;
+ if (url.scheme() == QLatin1String("file"))
+ filePath = url.toLocalFile();
+ else
+ filePath = url.path();
+
QmldirContent *qmldir;
QmldirContent **val = m_importQmlDirCache.value(filePath);
if (!val) {
#define NOT_READABLE_ERROR QString(QLatin1String("module \"$$URI$$\" definition \"%1\" not readable"))
#define CASE_MISMATCH_ERROR QString(QLatin1String("cannot load module \"$$URI$$\": File name case mismatch for \"%1\""))
- if (QQmlFile::isBundle(filePath)) {
-
- QUrl url(filePath);
-
+ if (QQmlFile::isBundle(url.toString())) {
QQmlFile file(engine(), url);
if (file.isError()) {
- ERROR(NOT_READABLE_ERROR.arg(filePath));
+ ERROR(NOT_READABLE_ERROR.arg(url.toString()));
} else {
QString content(QString::fromUtf8(file.data(), file.size()));
qmldir->setContent(filePath, content);
--- /dev/null
+This qmldir file is intentionally invalid, as the URL interception should prevent it being accessed.
--- /dev/null
+import QtQml 2.0
+
+QtObject {
+ property url filePath: "doesNotExist.file"
+ property url resolvedUrl: Qt.resolvedUrl("doesNotExist.file");
+ property url absoluteUrl: Qt.resolvedUrl("file:///doesNotExist.file");
+ property string childString: "intercepted"
+ property string scriptString: "intercepted"
+}
--- /dev/null
+Note that the paths are relative the the qmldir file in the actual module path, not the intercepted qmldir file
--- /dev/null
+TestObject 2.0 ../../module/intercepted/Intercepted.qml
--- /dev/null
+import Test 2.0 //This import will be intercepted to make this file valid
+
+TestObject {}
class CustomSelector : public QQmlAbstractUrlInterceptor
{
public:
+ CustomSelector(const QUrl &base):m_base(base){}
virtual QUrl intercept(const QUrl &url, QQmlAbstractUrlInterceptor::DataType d)
{
if (url.scheme() != QStringLiteral("file"))
if (!m_interceptionPoints.contains(d))
return url;
+ if (url.path().endsWith("Test.2/qmldir"))//Special case
+ return QUrl::fromLocalFile(m_base.path() + "interception/module/intercepted/qmldir");
+
QString alteredPath = url.path();
int a = alteredPath.lastIndexOf('/');
if (a < 0)
return ret;
}
QList<QQmlAbstractUrlInterceptor::DataType> m_interceptionPoints;
+ QUrl m_base;
};
Q_DECLARE_METATYPE(QList<QQmlAbstractUrlInterceptor::DataType>);
<< testFileUrl("interception/qmldir/intercepted/doesNotExist.file").toString()
<< QStringLiteral("file:///intercepted/doesNotExist.file");
+ QTest::newRow("InterceptModule")//just a Test{}, needs to intercept the module import for it to work
+ << testFileUrl("interception/module/urlInterceptor.qml")
+ << (QList<QQmlAbstractUrlInterceptor::DataType>() << QQmlAbstractUrlInterceptor::QmldirFile )
+ << testFileUrl("interception/module/intercepted/doesNotExist.file").toString()
+ << QStringLiteral("intercepted")
+ << QStringLiteral("intercepted")
+ << testFileUrl("interception/module/intercepted/doesNotExist.file").toString()
+ << QStringLiteral("file:///doesNotExist.file");
+
QTest::newRow("InterceptStrings")
<< testFileUrl("interception/strings/urlInterceptor.qml")
<< (QList<QQmlAbstractUrlInterceptor::DataType>() << QQmlAbstractUrlInterceptor::UrlString)
QFETCH(QString, expectedAbsoluteUrl);
QQmlEngine e;
- CustomSelector cs;
+ e.setImportPathList(QStringList() << testFileUrl("interception/imports").toLocalFile());
+ CustomSelector cs(testFileUrl(""));
cs.m_interceptionPoints = interceptionPoint;
e.setUrlInterceptor(&cs);
QQmlComponent c(&e, testFile); //Note that this can get intercepted too