From 8556133d620e7b64076d7b73de00451e16545c3b Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 23 May 2018 12:28:46 +0200 Subject: On network redirects, update finalUrl, not url We want all further imports to be relative to the redirected URL, not the base one. Note that this will incorporate any prior URL interceptions into the final URL if a redirect happens. We don't really want this to happen because the result of interception is not meant to be the base for further URL lookup. However, as interception occurs before redirection, this is unavoidable. Don't use URL interceptors on remote URLs. Task-number: QTBUG-67882 Change-Id: I6693d14c8af8212dda9954d0bd0293c3c85441ef (cherry picked from commit cda2680d801acce4e221b23e88d9b3c5504f86e8) Reviewed-by: Simon Hausmann --- src/qml/qml/qqmltypeloader.cpp | 19 +++++++++++-------- tests/auto/qml/qqmltypeloader/data/Base.qml | 3 +++ tests/auto/qml/qqmltypeloader/data/Load.qml | 11 +++++++++++ .../qml/qqmltypeloader/data/redirected/Imported.qml | 5 +++++ .../qml/qqmltypeloader/data/redirected/Redirected.qml | 5 +++++ tests/auto/qml/qqmltypeloader/data/redirected/qmldir | 1 + tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp | 18 ++++++++++++++++++ tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro | 7 ++++++- 8 files changed, 60 insertions(+), 9 deletions(-) create mode 100644 tests/auto/qml/qqmltypeloader/data/Base.qml create mode 100644 tests/auto/qml/qqmltypeloader/data/Load.qml create mode 100644 tests/auto/qml/qqmltypeloader/data/redirected/Imported.qml create mode 100644 tests/auto/qml/qqmltypeloader/data/redirected/Redirected.qml create mode 100644 tests/auto/qml/qqmltypeloader/data/redirected/qmldir diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index afcb9cdbe9..339ede461a 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -357,9 +357,8 @@ qreal QQmlDataBlob::progress() const /*! Returns the physical url of the data. Initially this is the same as -finalUrl(), but if a network redirect happens while fetching the data, this url -is updated to reflect the new location. Also, if a URL interceptor is set, it -will work on this URL and leave finalUrl() alone. +finalUrl(), but if a URL interceptor is set, it will work on this URL +and leave finalUrl() alone. \sa finalUrl() */ @@ -380,8 +379,12 @@ QString QQmlDataBlob::urlString() const Returns the logical URL to be used for resolving further URLs referred to in the code. -This is the blob url passed to the constructor. If a network redirect -happens while fetching the data, this url remains the same. +This is the blob url passed to the constructor. If a URL interceptor rewrites +the URL, this one stays the same. If a network redirect happens while fetching +the data, this url is updated to reflect the new location. Therefore, if both +an interception and a redirection happen, the final url will indirectly +incorporate the result of the interception, potentially breaking further +lookups. \sa url() */ @@ -1195,15 +1198,15 @@ void QQmlTypeLoader::networkReplyFinished(QNetworkReply *reply) QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); if (redirect.isValid()) { QUrl url = reply->url().resolved(redirect.toUrl()); - blob->m_url = url; - blob->m_urlString.clear(); + blob->m_finalUrl = url; + blob->m_finalUrlString.clear(); QNetworkReply *reply = m_thread->networkAccessManager()->get(QNetworkRequest(url)); QObject *nrp = m_thread->networkReplyProxy(); QObject::connect(reply, SIGNAL(finished()), nrp, SLOT(finished())); m_networkReplies.insert(reply, blob); #ifdef DATABLOB_DEBUG - qWarning("QQmlDataBlob: redirected to %s", qPrintable(blob->urlString())); + qWarning("QQmlDataBlob: redirected to %s", qPrintable(blob->finalUrlString())); #endif return; } diff --git a/tests/auto/qml/qqmltypeloader/data/Base.qml b/tests/auto/qml/qqmltypeloader/data/Base.qml new file mode 100644 index 0000000000..431c659424 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/Base.qml @@ -0,0 +1,3 @@ +import QtQml 2.0 + +QtObject {} diff --git a/tests/auto/qml/qqmltypeloader/data/Load.qml b/tests/auto/qml/qqmltypeloader/data/Load.qml new file mode 100644 index 0000000000..0b893bb5cd --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/Load.qml @@ -0,0 +1,11 @@ +import QtQuick 2.0 + +Item { + property int xy: loader.xy + Loader { + id: loader + asynchronous: true + source: 'Base.qml' + property int xy: item.xy + } +} diff --git a/tests/auto/qml/qqmltypeloader/data/redirected/Imported.qml b/tests/auto/qml/qqmltypeloader/data/redirected/Imported.qml new file mode 100644 index 0000000000..62954fe1b2 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/redirected/Imported.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +QtObject { + property int xy: 323232 +} diff --git a/tests/auto/qml/qqmltypeloader/data/redirected/Redirected.qml b/tests/auto/qml/qqmltypeloader/data/redirected/Redirected.qml new file mode 100644 index 0000000000..40fec5ed31 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/redirected/Redirected.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +Imported { + +} diff --git a/tests/auto/qml/qqmltypeloader/data/redirected/qmldir b/tests/auto/qml/qqmltypeloader/data/redirected/qmldir new file mode 100644 index 0000000000..8eb1fa5c18 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/redirected/qmldir @@ -0,0 +1 @@ +Imported 1.0 Imported.qml diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp index 5a3d76e903..e00d08183f 100644 --- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp +++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp @@ -33,6 +33,7 @@ #include #include #include +#include "../../shared/testhttpserver.h" #include "../../shared/util.h" class tst_QQMLTypeLoader : public QQmlDataTest @@ -48,6 +49,7 @@ private slots: void keepSingleton(); void keepRegistrations(); void intercept(); + void redirect(); }; void tst_QQMLTypeLoader::testLoadComplete() @@ -410,6 +412,22 @@ void tst_QQMLTypeLoader::intercept() QVERIFY(factory.loadedFiles.contains(QLatin1String(QT_TESTCASE_BUILDDIR) + "/Slow/qmldir")); } +void tst_QQMLTypeLoader::redirect() +{ + TestHTTPServer server; + QVERIFY2(server.listen(), qPrintable(server.errorString())); + QVERIFY(server.serveDirectory(dataDirectory())); + server.addRedirect("Base.qml", server.urlString("/redirected/Redirected.qml")); + + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(server.urlString("/Load.qml"), QQmlComponent::Asynchronous); + QTRY_VERIFY2(component.isReady(), qPrintable(component.errorString())); + + QObject *object = component.create(); + QTRY_COMPARE(object->property("xy").toInt(), 323232); +} + QTEST_MAIN(tst_QQMLTypeLoader) #include "tst_qqmltypeloader.moc" diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro index 3a20e94741..0352561e03 100644 --- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro +++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro @@ -3,7 +3,12 @@ TARGET = tst_qqmltypeloader QT += qml testlib qml-private quick macx:CONFIG -= app_bundle -SOURCES += tst_qqmltypeloader.cpp +SOURCES += \ + tst_qqmltypeloader.cpp \ + ../../shared/testhttpserver.cpp + +HEADERS += \ + ../../shared/testhttpserver.h include (../../shared/util.pri) -- cgit v1.2.3