diff options
author | Jüri Valdmann <juri.valdmann@qt.io> | 2017-12-15 13:04:02 +0100 |
---|---|---|
committer | Jüri Valdmann <juri.valdmann@qt.io> | 2018-01-08 13:53:50 +0000 |
commit | 6701ff310933ec33f9199b53d78299764f646387 (patch) | |
tree | 5ef941383eb8021acb81ed00a65cc25ff43906e8 /tests/auto/webchannel/tst_webchannel.cpp | |
parent | b90fbebbb5e257f771e96980109fb543647b1844 (diff) | |
download | qtwebchannel-6701ff310933ec33f9199b53d78299764f646387.tar.gz |
Allow deleting a channel during method invocation
A real-life use case is the session restore page in KDE Falkon or, more
generally, any kind of closeTab() method exposed to JS in a QWebEnginePage.
The approach taken in this patch will only work if the transport can also deal
with deletion during a messageReceived signal emission. Alternatively, method
invocation could be delayed via the event loop, but this would come with an
obvious performance penalty.
Change-Id: I2940f61e07c77365f6e3e7cd29463d4cb5b525a6
Reviewed-by: Milian Wolff <milian.wolff@kdab.com>
Diffstat (limited to 'tests/auto/webchannel/tst_webchannel.cpp')
-rw-r--r-- | tests/auto/webchannel/tst_webchannel.cpp | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/tests/auto/webchannel/tst_webchannel.cpp b/tests/auto/webchannel/tst_webchannel.cpp index f214b7e..602a101 100644 --- a/tests/auto/webchannel/tst_webchannel.cpp +++ b/tests/auto/webchannel/tst_webchannel.cpp @@ -814,6 +814,58 @@ void TestWebChannel::testAsyncObject() thread.wait(); } +class FunctionWrapper : public QObject +{ + Q_OBJECT + std::function<void()> m_fun; +public: + FunctionWrapper(std::function<void()> fun) : m_fun(std::move(fun)) {} +public slots: + void invoke() + { + m_fun(); + } +}; + +void TestWebChannel::testDeletionDuringMethodInvocation_data() +{ + QTest::addColumn<bool>("deleteChannel"); + QTest::addColumn<bool>("deleteTransport"); + QTest::newRow("delete neither") << false << false; + QTest::newRow("delete channel") << true << false; + QTest::newRow("delete transport") << false << true; + QTest::newRow("delete both") << true << true; +} + +void TestWebChannel::testDeletionDuringMethodInvocation() +{ + QFETCH(bool, deleteChannel); + QFETCH(bool, deleteTransport); + + QScopedPointer<QWebChannel> channel(new QWebChannel); + QScopedPointer<DummyTransport> transport(new DummyTransport(nullptr)); + FunctionWrapper deleter([&](){ + if (deleteChannel) + channel.reset(); + if (deleteTransport) + transport.reset(); + }); + channel->registerObject("deleter", &deleter); + channel->connectTo(transport.data()); + + transport->emitMessageReceived({ + {"type", TypeInvokeMethod}, + {"object", "deleter"}, + {"method", deleter.metaObject()->indexOfMethod("invoke()")}, + {"id", 42} + }); + + QCOMPARE(deleteChannel, !channel); + QCOMPARE(deleteTransport, !transport); + if (!deleteTransport) + QCOMPARE(transport->messagesSent().size(), deleteChannel ? 0 : 1); +} + static QHash<QString, QObject*> createObjects(QObject *parent) { const int num = 100; |