QTextBrowser: set base URL and document URL before loading content

setHtml() or setMarkdown() can result in attempting to load resources
such as images that are needed to render the page.  Whenever the
resource has a relative URL, loading depends on the baseURL having
already been set so that a complete URL can be constructed.
QTextDocument::resource() is called to load images, and uses baseUrl().
A little later, QTextBrowserPrivate::resolveUrl() is given an URL that
already has been extended with the baseURL if known; but it has its own
logic to resolve the resource URL against currentURL, or else to treat
it as a local file path if a file exists at that location.  The autotest
was relying on this fallback to the local relative file path before; but
now it tests both with a local filename in the current directory for the
source HTML and also with a fully resolved source URL containing the
complete file path.

Also made minor style improvements in tst_QTextBrowser's TestBrowser class.

Change-Id: I46a850015d0e9c5bc5f13b9e37179a9323ab1980
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
Shawn Rutledge 2019-05-19 13:33:27 +02:00
parent ce211b1f83
commit 90243aebb6
2 changed files with 23 additions and 8 deletions

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@ -327,9 +327,15 @@ void QTextBrowserPrivate::setSource(const QUrl &url)
home = url;
if (doSetText) {
// Setting the base URL helps QTextDocument::resource() to find resources with relative paths.
// But don't set it unless it contains the document's path, because QTextBrowserPrivate::resolveUrl()
// can already deal with local files on the filesystem in case the base URL was not set.
QUrl baseUrl = currentURL.adjusted(QUrl::RemoveFilename);
if (!baseUrl.path().isEmpty())
q->document()->setBaseUrl(baseUrl);
q->document()->setMetaInformation(QTextDocument::DocumentUrl, currentURL.toString());
#ifndef QT_NO_TEXTHTMLPARSER
q->QTextEdit::setHtml(txt);
q->document()->setMetaInformation(QTextDocument::DocumentUrl, currentURL.toString());
#else
q->QTextEdit::setPlainText(txt);
#endif

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@ -38,7 +38,7 @@
class TestBrowser : public QTextBrowser
{
public:
inline TestBrowser() : htmlLoadAttempts(0) {
inline TestBrowser() {
show();
QApplication::setActiveWindow(this);
activateWindow();
@ -47,11 +47,12 @@ public:
QVERIFY(hasFocus());
}
virtual QVariant loadResource(int type, const QUrl &name);
QVariant loadResource(int type, const QUrl &name) override;
int htmlLoadAttempts;
int htmlLoadAttempts = 0;
QUrl lastResource;
QUrl sourceInsideLoadResource;
QUrl baseInsideLoadResource;
};
QVariant TestBrowser::loadResource(int type, const QUrl &name)
@ -60,6 +61,7 @@ QVariant TestBrowser::loadResource(int type, const QUrl &name)
htmlLoadAttempts++;
lastResource = name;
sourceInsideLoadResource = source();
baseInsideLoadResource = document()->baseUrl();
return QTextBrowser::loadResource(type, name);
}
@ -108,7 +110,7 @@ void tst_QTextBrowser::init()
void tst_QTextBrowser::cleanup()
{
delete browser;
browser = 0;
browser = nullptr;
}
void tst_QTextBrowser::noReloadOnAnchorJump()
@ -428,11 +430,18 @@ void tst_QTextBrowser::sourceInsideLoadResource()
#ifdef Q_OS_WINRT
QSKIP("Paths cannot be compared if applications are sandboxed.");
#endif
QUrl url = QUrl::fromLocalFile("pagewithimage.html");
QUrl url = QUrl::fromLocalFile("pagewithimage.html"); // "file://pagewithimage.html"
browser->setSource(url);
QCOMPARE(browser->lastResource, QUrl::fromLocalFile(QDir::current().filePath("foobar.png")));
// baseUrl was not set because the source URL was a relative one
QCOMPARE(browser->baseInsideLoadResource, QUrl());
QEXPECT_FAIL("", "This is currently not supported", Continue);
QCOMPARE(browser->sourceInsideLoadResource.toString(), url.toString());
url = QUrl::fromLocalFile(QDir::current().filePath("pagewithimage.html")); // "file:///home/user/path/to/pagewithimage.html"
browser->setSource(url);
QCOMPARE(browser->lastResource, QUrl::fromLocalFile(QDir::current().filePath("foobar.png")));
// baseUrl has the full path, and that's where relative-path resources come from
QCOMPARE(browser->baseInsideLoadResource, QUrl::fromLocalFile(QDir::currentPath() + QLatin1Char('/')));
}
void tst_QTextBrowser::textInteractionFlags_vs_readOnly()