diff options
author | Kai Dohmen <psykai1993@googlemail.com> | 2016-04-28 22:08:55 +0200 |
---|---|---|
committer | Kai Dohmen <psykai1993@googlemail.com> | 2016-05-31 14:09:44 +0000 |
commit | fa2374d7c4dedea907e2df26fdad28bdee73b122 (patch) | |
tree | b3969de3ac547d8d198e3d08f8799faa0c8cdca7 /src/webchannel | |
parent | 034d052823c5d1f36dd1378716c7757c1c0c78d0 (diff) | |
download | qtwebchannel-fa2374d7c4dedea907e2df26fdad28bdee73b122.tar.gz |
Remove deleted transport objects
Added a QMultiHash which maps transport objects to wrapped object ids.
transportRemoved iterates over all matching wrapped objects and removes
the passed transport object from their transports-vector. If the
transports-vector is empty after removing the passed transport object
the objectDestroyed will be called on the wrapped object.
transportRemoved will be called either on the transports destoryed
signal or on disconnecting the webchannel from it.
Without this changes the QMetaObjectPublisher::wrappedObjects and
::registeredObjectIds would only be cleaned up if the website calls
deleteLater on QObjects but not on website reloads.
Task-number: QTBUG-50074
Change-Id: If294564fee2406edd7fb578852aeb269cac23a92
Reviewed-by: Milian Wolff <milian.wolff@kdab.com>
Diffstat (limited to 'src/webchannel')
-rw-r--r-- | src/webchannel/qmetaobjectpublisher.cpp | 24 | ||||
-rw-r--r-- | src/webchannel/qmetaobjectpublisher_p.h | 7 | ||||
-rw-r--r-- | src/webchannel/qwebchannel.cpp | 5 |
3 files changed, 35 insertions, 1 deletions
diff --git a/src/webchannel/qmetaobjectpublisher.cpp b/src/webchannel/qmetaobjectpublisher.cpp index a0c3af7..8fd8e4f 100644 --- a/src/webchannel/qmetaobjectpublisher.cpp +++ b/src/webchannel/qmetaobjectpublisher.cpp @@ -449,6 +449,29 @@ void QMetaObjectPublisher::objectDestroyed(const QObject *object) pendingPropertyUpdates.remove(object); } +void QMetaObjectPublisher::transportRemoved(QWebChannelAbstractTransport *transport) +{ + auto it = transportedWrappedObjects.find(transport); + // It is not allowed to modify a container while iterating over it. So save + // objects which should be removed and call objectDestroyed() on them later. + QVector<QObject*> objectsForDeletion; + while (it != transportedWrappedObjects.end() && it.key() == transport) { + if (wrappedObjects.contains(it.value())) { + QVector<QWebChannelAbstractTransport*> &transports = wrappedObjects[it.value()].transports; + transports.removeOne(transport); + if (transports.isEmpty()) + objectsForDeletion.append(wrappedObjects[it.value()].object); + } + + it++; + } + + transportedWrappedObjects.remove(transport); + + foreach (QObject *obj, objectsForDeletion) + objectDestroyed(obj); +} + // NOTE: transport can be a nullptr // in such a case, we need to ensure that the property is registered to // the target transports of the parentObjectId @@ -480,6 +503,7 @@ QJsonValue QMetaObjectPublisher::wrapResult(const QVariant &result, QWebChannelA oi.transports = webChannel->d_func()->transports; } wrappedObjects.insert(id, oi); + transportedWrappedObjects.insert(transport, id); initializePropertyUpdates(object, classInfo); } else if (wrappedObjects.contains(id)) { diff --git a/src/webchannel/qmetaobjectpublisher_p.h b/src/webchannel/qmetaobjectpublisher_p.h index c48fc84..fe75656 100644 --- a/src/webchannel/qmetaobjectpublisher_p.h +++ b/src/webchannel/qmetaobjectpublisher_p.h @@ -168,6 +168,11 @@ public: void objectDestroyed(const QObject *object); /** + * Remove wrapped objects which last transport relation is with the passed transport object. + */ + void transportRemoved(QWebChannelAbstractTransport *transport); + + /** * Given a QVariant containing a QObject*, wrap the object and register for property updates * return the objects class information. * @@ -248,6 +253,8 @@ private: // Map of objects wrapped from invocation returns QHash<QString, ObjectInfo> wrappedObjects; + // Map of transports to wrapped object ids + QMultiHash<QWebChannelAbstractTransport*, QString> transportedWrappedObjects; // Map of objects to maps of signal indices to a set of all their property indices. // The last value is a set as a signal can be the notify signal of multiple properties. diff --git a/src/webchannel/qwebchannel.cpp b/src/webchannel/qwebchannel.cpp index b7c62e9..7a63af9 100644 --- a/src/webchannel/qwebchannel.cpp +++ b/src/webchannel/qwebchannel.cpp @@ -81,9 +81,11 @@ QT_BEGIN_NAMESPACE */ void QWebChannelPrivate::_q_transportDestroyed(QObject *object) { - const int idx = transports.indexOf(static_cast<QWebChannelAbstractTransport*>(object)); + QWebChannelAbstractTransport *transport = static_cast<QWebChannelAbstractTransport*>(object); + const int idx = transports.indexOf(transport); if (idx != -1) { transports.remove(idx); + publisher->transportRemoved(transport); } } @@ -252,6 +254,7 @@ void QWebChannel::disconnectFrom(QWebChannelAbstractTransport *transport) disconnect(transport, 0, this, 0); disconnect(transport, 0, d->publisher, 0); d->transports.remove(idx); + d->publisher->transportRemoved(transport); } } |