summaryrefslogtreecommitdiffstats
path: root/tests/auto/widgets/origins/tst_origins.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/widgets/origins/tst_origins.cpp')
-rw-r--r--tests/auto/widgets/origins/tst_origins.cpp788
1 files changed, 0 insertions, 788 deletions
diff --git a/tests/auto/widgets/origins/tst_origins.cpp b/tests/auto/widgets/origins/tst_origins.cpp
deleted file mode 100644
index 21afead1d..000000000
--- a/tests/auto/widgets/origins/tst_origins.cpp
+++ /dev/null
@@ -1,788 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWebEngine module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "../util.h"
-
-#include <QtCore/qfile.h>
-#include <QtTest/QtTest>
-#include <QtWebEngineCore/qwebengineurlrequestjob.h>
-#include <QtWebEngineCore/qwebengineurlscheme.h>
-#include <QtWebEngineCore/qwebengineurlschemehandler.h>
-#include <QtWebEngineWidgets/qwebenginepage.h>
-#include <QtWebEngineWidgets/qwebengineprofile.h>
-#include <QtWebEngineWidgets/qwebenginesettings.h>
-#if defined(WEBSOCKETS)
-#include <QtWebSockets/qwebsocket.h>
-#include <QtWebSockets/qwebsocketserver.h>
-#include <QtWebChannel/qwebchannel.h>
-#endif
-#include <QtWidgets/qaction.h>
-
-#define QSL QStringLiteral
-#define QBAL QByteArrayLiteral
-#define THIS_DIR TESTS_SOURCE_DIR "origins/"
-
-void registerSchemes()
-{
- {
- QWebEngineUrlScheme scheme(QBAL("PathSyntax"));
- QWebEngineUrlScheme::registerScheme(scheme);
- }
-
- {
- QWebEngineUrlScheme scheme(QBAL("PathSyntax-Secure"));
- scheme.setFlags(QWebEngineUrlScheme::SecureScheme);
- QWebEngineUrlScheme::registerScheme(scheme);
- }
-
- {
- QWebEngineUrlScheme scheme(QBAL("PathSyntax-Secure-ServiceWorkersAllowed"));
- scheme.setFlags(QWebEngineUrlScheme::SecureScheme | QWebEngineUrlScheme::ServiceWorkersAllowed);
- QWebEngineUrlScheme::registerScheme(scheme);
- }
-
- {
- QWebEngineUrlScheme scheme(QBAL("PathSyntax-Local"));
- scheme.setFlags(QWebEngineUrlScheme::LocalScheme);
- QWebEngineUrlScheme::registerScheme(scheme);
- }
-
- {
- QWebEngineUrlScheme scheme(QBAL("PathSyntax-LocalAccessAllowed"));
- scheme.setFlags(QWebEngineUrlScheme::LocalAccessAllowed);
- QWebEngineUrlScheme::registerScheme(scheme);
- }
-
- {
- QWebEngineUrlScheme scheme(QBAL("PathSyntax-NoAccessAllowed"));
- scheme.setFlags(QWebEngineUrlScheme::NoAccessAllowed);
- QWebEngineUrlScheme::registerScheme(scheme);
- }
-
- {
- QWebEngineUrlScheme scheme(QBAL("PathSyntax-ServiceWorkersAllowed"));
- scheme.setFlags(QWebEngineUrlScheme::ServiceWorkersAllowed);
- QWebEngineUrlScheme::registerScheme(scheme);
- }
-
- {
- QWebEngineUrlScheme scheme(QBAL("PathSyntax-ViewSourceAllowed"));
- scheme.setFlags(QWebEngineUrlScheme::ViewSourceAllowed);
- QWebEngineUrlScheme::registerScheme(scheme);
- }
-
- {
- QWebEngineUrlScheme scheme(QBAL("HostSyntax"));
- scheme.setSyntax(QWebEngineUrlScheme::Syntax::Host);
- QWebEngineUrlScheme::registerScheme(scheme);
- }
-
- {
- QWebEngineUrlScheme scheme(QBAL("HostSyntax-ContentSecurityPolicyIgnored"));
- scheme.setSyntax(QWebEngineUrlScheme::Syntax::Host);
- scheme.setFlags(QWebEngineUrlScheme::ContentSecurityPolicyIgnored);
- QWebEngineUrlScheme::registerScheme(scheme);
- }
-
- {
- QWebEngineUrlScheme scheme(QBAL("HostAndPortSyntax"));
- scheme.setSyntax(QWebEngineUrlScheme::Syntax::HostAndPort);
- scheme.setDefaultPort(42);
- QWebEngineUrlScheme::registerScheme(scheme);
- }
-
- {
- QWebEngineUrlScheme scheme(QBAL("HostPortAndUserInformationSyntax"));
- scheme.setSyntax(QWebEngineUrlScheme::Syntax::HostPortAndUserInformation);
- scheme.setDefaultPort(42);
- QWebEngineUrlScheme::registerScheme(scheme);
- }
-}
-Q_CONSTRUCTOR_FUNCTION(registerSchemes)
-
-class TstUrlSchemeHandler final : public QWebEngineUrlSchemeHandler {
- Q_OBJECT
-
-public:
- TstUrlSchemeHandler(QWebEngineProfile *profile)
- {
- profile->installUrlSchemeHandler(QBAL("tst"), this);
-
- profile->installUrlSchemeHandler(QBAL("PathSyntax"), this);
- profile->installUrlSchemeHandler(QBAL("PathSyntax-Secure"), this);
- profile->installUrlSchemeHandler(QBAL("PathSyntax-Secure-ServiceWorkersAllowed"), this);
- profile->installUrlSchemeHandler(QBAL("PathSyntax-Local"), this);
- profile->installUrlSchemeHandler(QBAL("PathSyntax-LocalAccessAllowed"), this);
- profile->installUrlSchemeHandler(QBAL("PathSyntax-NoAccessAllowed"), this);
- profile->installUrlSchemeHandler(QBAL("PathSyntax-ServiceWorkersAllowed"), this);
- profile->installUrlSchemeHandler(QBAL("PathSyntax-ViewSourceAllowed"), this);
- profile->installUrlSchemeHandler(QBAL("HostSyntax"), this);
- profile->installUrlSchemeHandler(QBAL("HostSyntax-ContentSecurityPolicyIgnored"), this);
- profile->installUrlSchemeHandler(QBAL("HostAndPortSyntax"), this);
- profile->installUrlSchemeHandler(QBAL("HostPortAndUserInformationSyntax"), this);
- }
-
-private:
- void requestStarted(QWebEngineUrlRequestJob *job) override
- {
- QString pathPrefix = QSL(THIS_DIR);
- QString pathSuffix = job->requestUrl().path();
- QFile *file = new QFile(pathPrefix + pathSuffix, job);
- if (!file->open(QIODevice::ReadOnly)) {
- job->fail(QWebEngineUrlRequestJob::RequestFailed);
- return;
- }
- QByteArray mimeType = QBAL("text/html");
- if (pathSuffix.endsWith(QSL(".js")))
- mimeType = QBAL("application/javascript");
- job->reply(mimeType, file);
- }
-};
-
-class tst_Origins final : public QObject {
- Q_OBJECT
-
-private Q_SLOTS:
- void initTestCase();
- void cleanupTestCase();
-
- void jsUrlCanon();
- void jsUrlRelative();
- void jsUrlOrigin();
- void subdirWithAccess();
- void subdirWithoutAccess();
- void mixedSchemes();
- void mixedSchemesWithCsp();
- void mixedXHR();
-#if defined(WEBSOCKETS)
- void webSocket();
-#endif
- void dedicatedWorker();
- void sharedWorker();
- void serviceWorker();
- void viewSource();
- void createObjectURL();
-
-private:
- bool load(const QUrl &url)
- {
- QSignalSpy spy(m_page, &QWebEnginePage::loadFinished);
- m_page->load(url);
- return (!spy.empty() || spy.wait(20000))
- && spy.front().value(0).toBool();
- }
-
- QVariant eval(const QString &code)
- {
- return evaluateJavaScriptSync(m_page, code);
- }
-
- QWebEngineProfile m_profile;
- QWebEnginePage *m_page = nullptr;
- TstUrlSchemeHandler *m_handler = nullptr;
-};
-
-void tst_Origins::initTestCase()
-{
- m_page = new QWebEnginePage(&m_profile, nullptr);
- m_handler = new TstUrlSchemeHandler(&m_profile);
-}
-
-void tst_Origins::cleanupTestCase()
-{
- delete m_handler;
- delete m_page;
-}
-
-// Test URL parsing and canonicalization in Blink. The implementation of this
-// part is mostly shared between Blink and Chromium proper.
-void tst_Origins::jsUrlCanon()
-{
- QVERIFY(load(QSL("about:blank")));
-
- // Standard schemes are biased towards the authority part.
- QCOMPARE(eval(QSL("new URL(\"http:foo/bar\").href")), QVariant(QSL("http://foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"http:/foo/bar\").href")), QVariant(QSL("http://foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"http://foo/bar\").href")), QVariant(QSL("http://foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"http:///foo/bar\").href")), QVariant(QSL("http://foo/bar")));
-
- // The file scheme is however a (particularly) special case.
-#ifdef Q_OS_WIN
- QCOMPARE(eval(QSL("new URL(\"file:foo/bar\").href")), QVariant(QSL("file://foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"file:/foo/bar\").href")), QVariant(QSL("file://foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"file://foo/bar\").href")), QVariant(QSL("file://foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"file:///foo/bar\").href")), QVariant(QSL("file:///foo/bar")));
-#else
- QCOMPARE(eval(QSL("new URL(\"file:foo/bar\").href")), QVariant(QSL("file:///foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"file:/foo/bar\").href")), QVariant(QSL("file:///foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"file://foo/bar\").href")), QVariant(QSL("file://foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"file:///foo/bar\").href")), QVariant(QSL("file:///foo/bar")));
-#endif
-
- // The qrc scheme is a PathSyntax scheme, having only a path and nothing else.
- QCOMPARE(eval(QSL("new URL(\"qrc:foo/bar\").href")), QVariant(QSL("qrc:foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"qrc:/foo/bar\").href")), QVariant(QSL("qrc:/foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"qrc://foo/bar\").href")), QVariant(QSL("qrc://foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"qrc:///foo/bar\").href")), QVariant(QSL("qrc:///foo/bar")));
-
- // Same for unregistered schemes.
- QCOMPARE(eval(QSL("new URL(\"tst:foo/bar\").href")), QVariant(QSL("tst:foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"tst:/foo/bar\").href")), QVariant(QSL("tst:/foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"tst://foo/bar\").href")), QVariant(QSL("tst://foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"tst:///foo/bar\").href")), QVariant(QSL("tst:///foo/bar")));
-
- // A HostSyntax scheme is like http without the port & user information.
- QCOMPARE(eval(QSL("new URL(\"HostSyntax:foo/bar\").href")), QVariant(QSL("hostsyntax://foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"HostSyntax:foo:42/bar\").href")), QVariant(QSL("hostsyntax://foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"HostSyntax:a:b@foo/bar\").href")), QVariant(QSL("hostsyntax://foo/bar")));
-
- // A HostAndPortSyntax scheme is like http without the user information.
- QCOMPARE(eval(QSL("new URL(\"HostAndPortSyntax:foo/bar\").href")),
- QVariant(QSL("hostandportsyntax://foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"HostAndPortSyntax:foo:41/bar\").href")),
- QVariant(QSL("hostandportsyntax://foo:41/bar")));
- QCOMPARE(eval(QSL("new URL(\"HostAndPortSyntax:foo:42/bar\").href")),
- QVariant(QSL("hostandportsyntax://foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"HostAndPortSyntax:a:b@foo/bar\").href")),
- QVariant(QSL("hostandportsyntax://foo/bar")));
-
- // A HostPortAndUserInformationSyntax scheme is exactly like http.
- QCOMPARE(eval(QSL("new URL(\"HostPortAndUserInformationSyntax:foo/bar\").href")),
- QVariant(QSL("hostportanduserinformationsyntax://foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"HostPortAndUserInformationSyntax:foo:41/bar\").href")),
- QVariant(QSL("hostportanduserinformationsyntax://foo:41/bar")));
- QCOMPARE(eval(QSL("new URL(\"HostPortAndUserInformationSyntax:foo:42/bar\").href")),
- QVariant(QSL("hostportanduserinformationsyntax://foo/bar")));
- QCOMPARE(eval(QSL("new URL(\"HostPortAndUserInformationSyntax:a:b@foo/bar\").href")),
- QVariant(QSL("hostportanduserinformationsyntax://a:b@foo/bar")));
-}
-
-// Test relative URL resolution.
-void tst_Origins::jsUrlRelative()
-{
- QVERIFY(load(QSL("about:blank")));
-
- // Schemes with hosts, like http, work as expected.
- QCOMPARE(eval(QSL("new URL('bar', 'http://foo').href")), QVariant(QSL("http://foo/bar")));
- QCOMPARE(eval(QSL("new URL('baz', 'http://foo/bar').href")), QVariant(QSL("http://foo/baz")));
- QCOMPARE(eval(QSL("new URL('baz', 'http://foo/bar/').href")), QVariant(QSL("http://foo/bar/baz")));
- QCOMPARE(eval(QSL("new URL('/baz', 'http://foo/bar/').href")), QVariant(QSL("http://foo/baz")));
- QCOMPARE(eval(QSL("new URL('./baz', 'http://foo/bar/').href")), QVariant(QSL("http://foo/bar/baz")));
- QCOMPARE(eval(QSL("new URL('../baz', 'http://foo/bar/').href")), QVariant(QSL("http://foo/baz")));
- QCOMPARE(eval(QSL("new URL('../../baz', 'http://foo/bar/').href")), QVariant(QSL("http://foo/baz")));
- QCOMPARE(eval(QSL("new URL('//baz', 'http://foo/bar/').href")), QVariant(QSL("http://baz/")));
-
- // In the case of schemes without hosts, relative URLs only work if the URL
- // starts with a single slash -- and canonicalization does not guarantee
- // this. The following cases all fail with TypeErrors.
- QCOMPARE(eval(QSL("new URL('bar', 'tst:foo').href")), QVariant());
- QCOMPARE(eval(QSL("new URL('baz', 'tst:foo/bar').href")), QVariant());
- QCOMPARE(eval(QSL("new URL('bar', 'tst://foo').href")), QVariant());
- QCOMPARE(eval(QSL("new URL('bar', 'tst:///foo').href")), QVariant());
-
- // However, registered custom schemes have been patched to allow relative
- // URLs even without an initial slash.
- QCOMPARE(eval(QSL("new URL('bar', 'qrc:foo').href")), QVariant(QSL("qrc:bar")));
- QCOMPARE(eval(QSL("new URL('baz', 'qrc:foo/bar').href")), QVariant(QSL("qrc:foo/baz")));
- QCOMPARE(eval(QSL("new URL('bar', 'qrc://foo').href")), QVariant());
- QCOMPARE(eval(QSL("new URL('bar', 'qrc:///foo').href")), QVariant());
-
- // With a slash it works the same as http except 'foo' is part of the path and not the host.
- QCOMPARE(eval(QSL("new URL('bar', 'qrc:/foo').href")), QVariant(QSL("qrc:/bar")));
- QCOMPARE(eval(QSL("new URL('bar', 'qrc:/foo/').href")), QVariant(QSL("qrc:/foo/bar")));
- QCOMPARE(eval(QSL("new URL('baz', 'qrc:/foo/bar').href")), QVariant(QSL("qrc:/foo/baz")));
- QCOMPARE(eval(QSL("new URL('baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc:/foo/bar/baz")));
- QCOMPARE(eval(QSL("new URL('/baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc:/baz")));
- QCOMPARE(eval(QSL("new URL('./baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc:/foo/bar/baz")));
- QCOMPARE(eval(QSL("new URL('../baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc:/foo/baz")));
- QCOMPARE(eval(QSL("new URL('../../baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc:/baz")));
- QCOMPARE(eval(QSL("new URL('../../../baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc:/baz")));
-
- // If the relative URL begins with >= 2 slashes, then the scheme is treated
- // not as a Syntax::Path scheme but as a Syntax::HostPortAndUserInformation
- // scheme.
- QCOMPARE(eval(QSL("new URL('//baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc://baz/")));
- QCOMPARE(eval(QSL("new URL('///baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc://baz/")));
-}
-
-// Test origin serialization in Blink, implemented by blink::KURL and
-// blink::SecurityOrigin as opposed to GURL and url::Origin.
-void tst_Origins::jsUrlOrigin()
-{
- QVERIFY(load(QSL("about:blank")));
-
- // For network protocols the origin string must include the domain and port.
- QCOMPARE(eval(QSL("new URL(\"http://foo.com/page.html\").origin")), QVariant(QSL("http://foo.com")));
- QCOMPARE(eval(QSL("new URL(\"https://foo.com/page.html\").origin")), QVariant(QSL("https://foo.com")));
-
- // Even though file URL can also have domains, these are not included in the
- // origin string by Chromium. The standard does not specify a value here,
- // but suggests 'null' (https://url.spec.whatwg.org/#origin).
- QCOMPARE(eval(QSL("new URL(\"file:/etc/passwd\").origin")), QVariant(QSL("file://")));
- QCOMPARE(eval(QSL("new URL(\"file://foo.com/etc/passwd\").origin")), QVariant(QSL("file://")));
-
- // The qrc scheme should behave like file.
- QCOMPARE(eval(QSL("new URL(\"qrc:/crysis.css\").origin")), QVariant(QSL("qrc://")));
- QCOMPARE(eval(QSL("new URL(\"qrc://foo.com/crysis.css\").origin")), QVariant(QSL("qrc://")));
-
- // Same with unregistered schemes.
- QCOMPARE(eval(QSL("new URL(\"tst:/banana\").origin")), QVariant(QSL("tst://")));
- QCOMPARE(eval(QSL("new URL(\"tst://foo.com/banana\").origin")), QVariant(QSL("tst://")));
-
- // The non-PathSyntax schemes should have hosts and potentially ports.
- QCOMPARE(eval(QSL("new URL(\"HostSyntax:foo:41/bar\").origin")),
- QVariant(QSL("hostsyntax://foo")));
- QCOMPARE(eval(QSL("new URL(\"HostAndPortSyntax:foo:41/bar\").origin")),
- QVariant(QSL("hostandportsyntax://foo:41")));
- QCOMPARE(eval(QSL("new URL(\"HostAndPortSyntax:foo:42/bar\").origin")),
- QVariant(QSL("hostandportsyntax://foo")));
- QCOMPARE(eval(QSL("new URL(\"HostPortAndUserInformationSyntax:foo:41/bar\").origin")),
- QVariant(QSL("hostportanduserinformationsyntax://foo:41")));
- QCOMPARE(eval(QSL("new URL(\"HostPortAndUserInformationSyntax:foo:42/bar\").origin")),
- QVariant(QSL("hostportanduserinformationsyntax://foo")));
-
- // A PathSyntax scheme should have a 'universal' origin.
- QCOMPARE(eval(QSL("new URL(\"PathSyntax:foo\").origin")),
- QVariant(QSL("pathsyntax://")));
-
- // The NoAccessAllowed flag forces opaque origins.
- QCOMPARE(eval(QSL("new URL(\"PathSyntax-NoAccessAllowed:foo\").origin")),
- QVariant(QSL("null")));
-}
-
-class ScopedAttribute {
-public:
- ScopedAttribute(QWebEngineSettings *settings, QWebEngineSettings::WebAttribute attribute, bool newValue)
- : m_settings(settings)
- , m_attribute(attribute)
- , m_oldValue(m_settings->testAttribute(m_attribute))
- {
- m_settings->setAttribute(m_attribute, newValue);
- }
- ~ScopedAttribute()
- {
- m_settings->setAttribute(m_attribute, m_oldValue);
- }
-private:
- QWebEngineSettings *m_settings;
- QWebEngineSettings::WebAttribute m_attribute;
- bool m_oldValue;
-};
-
-// Test same-origin policy of file, qrc and custom schemes.
-//
-// Note the test case involves the main page trying to load an iframe from a
-// file that resides in a parent directory. This is just a small detail to
-// demonstrate the difference with Firefox where such access is not allowed.
-void tst_Origins::subdirWithAccess()
-{
- ScopedAttribute sa(m_page->settings(), QWebEngineSettings::LocalContentCanAccessFileUrls, true);
-
- QVERIFY(load(QSL("file:" THIS_DIR "resources/subdir/index.html")));
- QCOMPARE(eval(QSL("msg[0]")), QVariant(QSL("hello")));
- QCOMPARE(eval(QSL("msg[1]")), QVariant(QSL("world")));
-
- QVERIFY(load(QSL("qrc:/resources/subdir/index.html")));
- QCOMPARE(eval(QSL("msg[0]")), QVariant(QSL("hello")));
- QCOMPARE(eval(QSL("msg[1]")), QVariant(QSL("world")));
-
- QVERIFY(load(QSL("tst:/resources/subdir/index.html")));
- QCOMPARE(eval(QSL("msg[0]")), QVariant(QSL("hello")));
- QCOMPARE(eval(QSL("msg[1]")), QVariant(QSL("world")));
-}
-
-// In this variation the LocalContentCanAccessFileUrls attribute is disabled. As
-// a result all file URLs will be considered to have unique/opaque origins, that
-// is, they are not the 'same origin as' any other origin.
-//
-// Note that this applies only to file URLs and not qrc or custom schemes.
-//
-// See also (in Blink):
-// - the allow_file_access_from_file_urls option and
-// - the blink::SecurityOrigin::BlockLocalAccessFromLocalOrigin() method.
-void tst_Origins::subdirWithoutAccess()
-{
- ScopedAttribute sa(m_page->settings(), QWebEngineSettings::LocalContentCanAccessFileUrls, false);
-
- QVERIFY(load(QSL("file:" THIS_DIR "resources/subdir/index.html")));
- QCOMPARE(eval(QSL("msg[0]")), QVariant());
- QCOMPARE(eval(QSL("msg[1]")), QVariant());
-
- QVERIFY(load(QSL("qrc:/resources/subdir/index.html")));
- QCOMPARE(eval(QSL("msg[0]")), QVariant(QSL("hello")));
- QCOMPARE(eval(QSL("msg[1]")), QVariant(QSL("world")));
-
- QVERIFY(load(QSL("tst:/resources/subdir/index.html")));
- QCOMPARE(eval(QSL("msg[0]")), QVariant(QSL("hello")));
- QCOMPARE(eval(QSL("msg[1]")), QVariant(QSL("world")));
-}
-
-// Load the main page over one scheme with an iframe over another scheme.
-//
-// For file and qrc schemes, the iframe should load but it should not be
-// possible for scripts in different frames to interact.
-//
-// Additionally for unregistered custom schemes and custom schemes without
-// LocalAccessAllowed it should not be possible to load an iframe over the
-// file: scheme.
-void tst_Origins::mixedSchemes()
-{
- QVERIFY(load(QSL("file:" THIS_DIR "resources/mixedSchemes.html")));
- eval(QSL("setIFrameUrl('file:" THIS_DIR "resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadAndAccess")));
- eval(QSL("setIFrameUrl('qrc:/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
- eval(QSL("setIFrameUrl('tst:/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
-
- QVERIFY(load(QSL("qrc:/resources/mixedSchemes.html")));
- eval(QSL("setIFrameUrl('file:" THIS_DIR "resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
- eval(QSL("setIFrameUrl('qrc:/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadAndAccess")));
- eval(QSL("setIFrameUrl('tst:/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
-
- QVERIFY(load(QSL("tst:/resources/mixedSchemes.html")));
- eval(QSL("setIFrameUrl('file:" THIS_DIR "resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("cannotLoad")));
- eval(QSL("setIFrameUrl('qrc:/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
- eval(QSL("setIFrameUrl('tst:/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadAndAccess")));
-
- QVERIFY(load(QSL("PathSyntax:/resources/mixedSchemes.html")));
- eval(QSL("setIFrameUrl('PathSyntax:/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadAndAccess")));
- eval(QSL("setIFrameUrl('PathSyntax-Local:/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("cannotLoad")));
- eval(QSL("setIFrameUrl('PathSyntax-LocalAccessAllowed:/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
- eval(QSL("setIFrameUrl('PathSyntax-NoAccessAllowed:/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
-
- QVERIFY(load(QSL("PathSyntax-LocalAccessAllowed:/resources/mixedSchemes.html")));
- eval(QSL("setIFrameUrl('PathSyntax:/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
- eval(QSL("setIFrameUrl('PathSyntax-Local:/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
- eval(QSL("setIFrameUrl('PathSyntax-LocalAccessAllowed:/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadAndAccess")));
- eval(QSL("setIFrameUrl('PathSyntax-NoAccessAllowed:/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
-
- QVERIFY(load(QSL("PathSyntax-NoAccessAllowed:/resources/mixedSchemes.html")));
- eval(QSL("setIFrameUrl('PathSyntax:/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
- eval(QSL("setIFrameUrl('PathSyntax-Local:/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("cannotLoad")));
- eval(QSL("setIFrameUrl('PathSyntax-LocalAccessAllowed:/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
- eval(QSL("setIFrameUrl('PathSyntax-NoAccessAllowed:/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
-
- QVERIFY(load(QSL("HostSyntax://a/resources/mixedSchemes.html")));
- eval(QSL("setIFrameUrl('HostSyntax://a/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadAndAccess")));
- eval(QSL("setIFrameUrl('HostSyntax://b/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
-}
-
-// Like mixedSchemes but adds a Content-Security-Policy: frame-src 'none' header.
-void tst_Origins::mixedSchemesWithCsp()
-{
- QVERIFY(load(QSL("HostSyntax://a/resources/mixedSchemesWithCsp.html")));
- eval(QSL("setIFrameUrl('HostSyntax://a/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
- eval(QSL("setIFrameUrl('HostSyntax://b/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
-
- QVERIFY(load(QSL("HostSyntax-ContentSecurityPolicyIgnored://a/resources/mixedSchemesWithCsp.html")));
- eval(QSL("setIFrameUrl('HostSyntax-ContentSecurityPolicyIgnored://a/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadAndAccess")));
- eval(QSL("setIFrameUrl('HostSyntax-ContentSecurityPolicyIgnored://b/resources/mixedSchemes_frame.html')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
-}
-
-// Load the main page over one scheme, then make an XMLHttpRequest to a
-// different scheme.
-//
-// XMLHttpRequests can only be made to http, https, data, and chrome.
-void tst_Origins::mixedXHR()
-{
- QVERIFY(load(QSL("file:" THIS_DIR "resources/mixedXHR.html")));
- eval(QSL("sendXHR('file:" THIS_DIR "resources/mixedXHR.txt')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("ok")));
- eval(QSL("sendXHR('qrc:/resources/mixedXHR.txt')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("error")));
- eval(QSL("sendXHR('tst:/resources/mixedXHR.txt')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("error")));
- eval(QSL("sendXHR('data:,ok')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("ok")));
-
- QVERIFY(load(QSL("qrc:/resources/mixedXHR.html")));
- eval(QSL("sendXHR('file:" THIS_DIR "resources/mixedXHR.txt')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("ok")));
- eval(QSL("sendXHR('qrc:/resources/mixedXHR.txt')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("ok")));
- eval(QSL("sendXHR('tst:/resources/mixedXHR.txt')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("error")));
- eval(QSL("sendXHR('data:,ok')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("ok")));
-
- QVERIFY(load(QSL("tst:/resources/mixedXHR.html")));
- eval(QSL("sendXHR('file:" THIS_DIR "resources/mixedXHR.txt')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("error")));
- eval(QSL("sendXHR('qrc:/resources/mixedXHR.txt')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("error")));
- eval(QSL("sendXHR('tst:/resources/mixedXHR.txt')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("ok")));
- eval(QSL("sendXHR('data:,ok')"));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("ok")));
-}
-
-#if defined(WEBSOCKETS)
-class EchoServer : public QObject {
- Q_OBJECT
- Q_PROPERTY(QUrl url READ url NOTIFY urlChanged)
-public:
- EchoServer() : webSocketServer(QSL("EchoServer"), QWebSocketServer::NonSecureMode)
- {
- connect(&webSocketServer, &QWebSocketServer::newConnection, this, &EchoServer::onNewConnection);
- }
-
- bool listen()
- {
- if (webSocketServer.listen(QHostAddress::Any)) {
- Q_EMIT urlChanged();
- return true;
- }
- return false;
- }
-
- QUrl url() const
- {
- return webSocketServer.serverUrl();
- }
-
-Q_SIGNALS:
- void urlChanged();
-
-private:
- void onNewConnection()
- {
- QWebSocket *socket = webSocketServer.nextPendingConnection();
- connect(socket, &QWebSocket::textMessageReceived, this, &EchoServer::onTextMessageReceived);
- connect(socket, &QWebSocket::disconnected, socket, &QObject::deleteLater);
- }
-
- void onTextMessageReceived(const QString &message)
- {
- QWebSocket *socket = qobject_cast<QWebSocket *>(sender());
- socket->sendTextMessage(message);
- }
-
- QWebSocketServer webSocketServer;
-};
-
-// Try opening a WebSocket from pages loaded over various URL schemes.
-void tst_Origins::webSocket()
-{
- const int kAbnormalClosure = 1006;
-
- EchoServer echoServer;
- QWebChannel channel;
- channel.registerObject(QSL("echoServer"), &echoServer);
- m_page->setWebChannel(&channel);
- QVERIFY(echoServer.listen());
-
- QVERIFY(load(QSL("file:" THIS_DIR "resources/websocket.html")));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("ok")));
-
- QVERIFY(load(QSL("qrc:/resources/websocket.html")));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("ok")));
-
- // Only registered schemes can open WebSockets.
- QVERIFY(load(QSL("tst:/resources/websocket.html")));
- QTRY_COMPARE(eval(QSL("result")), QVariant(kAbnormalClosure));
-
- // Even an insecure registered scheme can open WebSockets.
- QVERIFY(load(QSL("PathSyntax:/resources/websocket.html")));
- QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("ok")));
-}
-#endif
-// Create a (Dedicated)Worker. Since dedicated workers can only be accessed from
-// one page, there is not much need for security restrictions.
-void tst_Origins::dedicatedWorker()
-{
- QVERIFY(load(QSL("file:" THIS_DIR "resources/dedicatedWorker.html")));
- QTRY_VERIFY(eval(QSL("done")).toBool());
- QCOMPARE(eval(QSL("result")), QVariant(42));
-
- QVERIFY(load(QSL("qrc:/resources/dedicatedWorker.html")));
- QTRY_VERIFY(eval(QSL("done")).toBool());
- QCOMPARE(eval(QSL("result")), QVariant(42));
-
- // Unregistered schemes cannot create Workers.
- QVERIFY(load(QSL("tst:/resources/dedicatedWorker.html")));
- QTRY_VERIFY(eval(QSL("done")).toBool());
- QVERIFY(eval(QSL("error")).toString()
- .contains(QSL("Access to dedicated workers is denied to origin 'tst://'")));
-
- // Even an insecure registered scheme can create Workers.
- QVERIFY(load(QSL("PathSyntax:/resources/dedicatedWorker.html")));
- QTRY_VERIFY(eval(QSL("done")).toBool());
- QCOMPARE(eval(QSL("result")), QVariant(42));
-
- // But not if the NoAccessAllowed flag is set.
- QVERIFY(load(QSL("PathSyntax-NoAccessAllowed:/resources/dedicatedWorker.html")));
- QTRY_VERIFY(eval(QSL("done")).toBool());
- QVERIFY(eval(QSL("error")).toString()
- .contains(QSL("cannot be accessed from origin 'null'")));
-}
-
-// Create a SharedWorker. Shared workers can be accessed from multiple pages,
-// and therefore the same-origin policy applies.
-void tst_Origins::sharedWorker()
-{
- {
- ScopedAttribute sa(m_page->settings(), QWebEngineSettings::LocalContentCanAccessFileUrls, false);
- QVERIFY(load(QSL("file:" THIS_DIR "resources/sharedWorker.html")));
- QTRY_VERIFY(eval(QSL("done")).toBool());
- QVERIFY(eval(QSL("error")).toString()
- .contains(QSL("cannot be accessed from origin 'null'")));
- }
-
- {
- ScopedAttribute sa(m_page->settings(), QWebEngineSettings::LocalContentCanAccessFileUrls, true);
- QVERIFY(load(QSL("file:" THIS_DIR "resources/sharedWorker.html")));
- QTRY_VERIFY(eval(QSL("done")).toBool());
- QCOMPARE(eval(QSL("result")), QVariant(42));
- }
-
- QVERIFY(load(QSL("qrc:/resources/sharedWorker.html")));
- QTRY_VERIFY(eval(QSL("done")).toBool());
- QCOMPARE(eval(QSL("result")), QVariant(42));
-
- // Unregistered schemes should not create SharedWorkers.
-
- QVERIFY(load(QSL("PathSyntax:/resources/sharedWorker.html")));
- QTRY_VERIFY(eval(QSL("done")).toBool());
- QCOMPARE(eval(QSL("result")), QVariant(42));
-
- QVERIFY(load(QSL("PathSyntax-NoAccessAllowed:/resources/sharedWorker.html")));
- QTRY_VERIFY(eval(QSL("done")).toBool());
- QVERIFY(eval(QSL("error")).toString()
- .contains(QSL("denied to origin 'null'")));
-}
-
-// Service workers have to be explicitly enabled for a scheme.
-void tst_Origins::serviceWorker()
-{
- QVERIFY(load(QSL("file:" THIS_DIR "resources/serviceWorker.html")));
- QTRY_VERIFY(eval(QSL("done")).toBool());
- QVERIFY(eval(QSL("error")).toString()
- .contains(QSL("The URL protocol of the current origin ('file://') is not supported.")));
-
- QVERIFY(load(QSL("qrc:/resources/serviceWorker.html")));
- QTRY_VERIFY(eval(QSL("done")).toBool());
- QVERIFY(eval(QSL("error")).toString()
- .contains(QSL("The URL protocol of the current origin ('qrc://') is not supported.")));
-
- QVERIFY(load(QSL("tst:/resources/serviceWorker.html")));
- QTRY_VERIFY(eval(QSL("done")).toBool());
- QVERIFY(eval(QSL("error")).toString()
- .contains(QSL("Cannot read property 'register' of undefined")));
-
- QVERIFY(load(QSL("PathSyntax:/resources/serviceWorker.html")));
- QTRY_VERIFY(eval(QSL("done")).toBool());
- QVERIFY(eval(QSL("error")).toString()
- .contains(QSL("Cannot read property 'register' of undefined")));
-
- QVERIFY(load(QSL("PathSyntax-Secure:/resources/serviceWorker.html")));
- QTRY_VERIFY(eval(QSL("done")).toBool());
- QVERIFY(eval(QSL("error")).toString()
- .contains(QSL("The URL protocol of the current origin ('pathsyntax-secure://') is not supported.")));
-
- QVERIFY(load(QSL("PathSyntax-ServiceWorkersAllowed:/resources/serviceWorker.html")));
- QTRY_VERIFY(eval(QSL("done")).toBool());
- QVERIFY(eval(QSL("error")).toString()
- .contains(QSL("Cannot read property 'register' of undefined")));
-
- QVERIFY(load(QSL("PathSyntax-Secure-ServiceWorkersAllowed:/resources/serviceWorker.html")));
- QTRY_VERIFY(eval(QSL("done")).toBool());
- QCOMPARE(eval(QSL("error")), QVariant());
-
- QVERIFY(load(QSL("PathSyntax-NoAccessAllowed:/resources/serviceWorker.html")));
- QTRY_VERIFY(eval(QSL("done")).toBool());
- QVERIFY(eval(QSL("error")).toString()
- .contains(QSL("Cannot read property 'register' of undefined")));
-}
-
-// Support for view-source must be enabled explicitly.
-void tst_Origins::viewSource()
-{
- QVERIFY(load(QSL("view-source:file:" THIS_DIR "resources/viewSource.html")));
-#ifdef Q_OS_WIN
- QCOMPARE(m_page->requestedUrl().toString(), QSL("file:///" THIS_DIR "resources/viewSource.html"));
-#else
- QCOMPARE(m_page->requestedUrl().toString(), QSL("file://" THIS_DIR "resources/viewSource.html"));
-#endif
-
- QVERIFY(load(QSL("view-source:qrc:/resources/viewSource.html")));
- QCOMPARE(m_page->requestedUrl().toString(), QSL("qrc:/resources/viewSource.html"));
-
- QVERIFY(load(QSL("view-source:tst:/resources/viewSource.html")));
- QCOMPARE(m_page->requestedUrl().toString(), QSL("about:blank"));
-
- QVERIFY(load(QSL("view-source:PathSyntax:/resources/viewSource.html")));
- QCOMPARE(m_page->requestedUrl().toString(), QSL("about:blank"));
-
- QVERIFY(load(QSL("view-source:PathSyntax-ViewSourceAllowed:/resources/viewSource.html")));
- QCOMPARE(m_page->requestedUrl().toString(), QSL("pathsyntax-viewsourceallowed:/resources/viewSource.html"));
-}
-
-void tst_Origins::createObjectURL()
-{
- // Legal for registered custom schemes.
- QVERIFY(load(QSL("qrc:/resources/createObjectURL.html")));
- QVERIFY(eval(QSL("result")).toString().startsWith(QSL("blob:qrc:")));
-
- // Illegal for unregistered schemes (renderer gets terminated).
- qRegisterMetaType<QWebEnginePage::RenderProcessTerminationStatus>("RenderProcessTerminationStatus");
- QSignalSpy loadFinishedSpy(m_page, &QWebEnginePage::loadFinished);
- QSignalSpy renderProcessTerminatedSpy(m_page, &QWebEnginePage::renderProcessTerminated);
- m_page->load(QSL("tst:/resources/createObjectURL.html"));
- QVERIFY(!renderProcessTerminatedSpy.empty() || renderProcessTerminatedSpy.wait(20000));
- QVERIFY(renderProcessTerminatedSpy.front().value(0).value<QWebEnginePage::RenderProcessTerminationStatus>()
- != QWebEnginePage::NormalTerminationStatus);
- QVERIFY(loadFinishedSpy.empty());
-}
-
-QTEST_MAIN(tst_Origins)
-#include "tst_origins.moc"