diff options
author | Kai Koehne <kai.koehne@nokia.com> | 2010-09-22 19:03:57 (GMT) |
---|---|---|
committer | Kai Koehne <kai.koehne@nokia.com> | 2010-09-28 05:55:32 (GMT) |
commit | fd9771c29d401d88779ab7c5d7715c9ca41dd723 (patch) | |
tree | 0e96e0871e8914f5747bfc1a1314d76a78620b6d | |
parent | 7b796b4dcdebfba55c4754d241edb334217fc550 (diff) | |
download | Qt-fd9771c29d401d88779ab7c5d7715c9ca41dd723.zip Qt-fd9771c29d401d88779ab7c5d7715c9ca41dd723.tar.gz Qt-fd9771c29d401d88779ab7c5d7715c9ca41dd723.tar.bz2 |
Make QmlDebug protocol more robust
The protocol so far was client->server only. That is, there was no
sane way for a client to check whether a plugin on the server (service)
was available or not. E.g. calling Client::setEnabled(true) 'succeeded',
without a check whether there is actually a service to talk to.
The new protocol replaces this shortcoming by a service discovery
mechanism: Both client & service announce their available plugins at
handshake time, and later on if there are changes. The status is
reflected in Client::status() and Service::Status() , which are either
NotConnected - no network connection, or not registered properly
Unavailable - TCP/IP connection works, but no plugin with the same
name on the other side
Enabled - You can connect to plugin on other side
The status changes happen automatically (no setEnabled() anymore).
Furthermore a version ID was added to the handshake, so that we can
extend the protocol further in the future :)
12 files changed, 362 insertions, 180 deletions
diff --git a/src/declarative/debugger/qdeclarativedebug.cpp b/src/declarative/debugger/qdeclarativedebug.cpp index 1ffe441..7a5e5f6 100644 --- a/src/declarative/debugger/qdeclarativedebug.cpp +++ b/src/declarative/debugger/qdeclarativedebug.cpp @@ -55,10 +55,12 @@ public: QDeclarativeEngineDebugClient(QDeclarativeDebugConnection *client, QDeclarativeEngineDebugPrivate *p); protected: + virtual void statusChanged(Status status); virtual void messageReceived(const QByteArray &); private: QDeclarativeEngineDebugPrivate *priv; + friend class QDeclarativeEngineDebugPrivate; }; class QDeclarativeEngineDebugPrivate : public QObjectPrivate @@ -66,7 +68,9 @@ class QDeclarativeEngineDebugPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QDeclarativeEngineDebug) public: QDeclarativeEngineDebugPrivate(QDeclarativeDebugConnection *); + ~QDeclarativeEngineDebugPrivate(); + void statusChanged(QDeclarativeEngineDebug::Status status); void message(const QByteArray &); QDeclarativeEngineDebugClient *client; @@ -93,12 +97,18 @@ QDeclarativeEngineDebugClient::QDeclarativeEngineDebugClient(QDeclarativeDebugCo QDeclarativeEngineDebugPrivate *p) : QDeclarativeDebugClient(QLatin1String("QDeclarativeEngine"), client), priv(p) { - setEnabled(true); +} + +void QDeclarativeEngineDebugClient::statusChanged(Status status) +{ + if (priv) + priv->statusChanged(static_cast<QDeclarativeEngineDebug::Status>(status)); } void QDeclarativeEngineDebugClient::messageReceived(const QByteArray &data) { - priv->message(data); + if (priv) + priv->message(data); } QDeclarativeEngineDebugPrivate::QDeclarativeEngineDebugPrivate(QDeclarativeDebugConnection *c) @@ -106,6 +116,12 @@ QDeclarativeEngineDebugPrivate::QDeclarativeEngineDebugPrivate(QDeclarativeDebug { } +QDeclarativeEngineDebugPrivate::~QDeclarativeEngineDebugPrivate() +{ + if (client) + client->priv = 0; +} + int QDeclarativeEngineDebugPrivate::getId() { return nextId++; @@ -228,6 +244,11 @@ void QDeclarativeEngineDebugPrivate::decode(QDataStream &ds, QDeclarativeDebugCo } } +void QDeclarativeEngineDebugPrivate::statusChanged(QDeclarativeEngineDebug::Status status) +{ + emit q_func()->statusChanged(status); +} + void QDeclarativeEngineDebugPrivate::message(const QByteArray &data) { QDataStream ds(data); @@ -350,12 +371,19 @@ QDeclarativeEngineDebug::QDeclarativeEngineDebug(QDeclarativeDebugConnection *cl { } +QDeclarativeEngineDebug::Status QDeclarativeEngineDebug::status() const +{ + Q_D(const QDeclarativeEngineDebug); + + return static_cast<QDeclarativeEngineDebug::Status>(d->client->status()); +} + QDeclarativeDebugPropertyWatch *QDeclarativeEngineDebug::addWatch(const QDeclarativeDebugPropertyReference &property, QObject *parent) { Q_D(QDeclarativeEngineDebug); QDeclarativeDebugPropertyWatch *watch = new QDeclarativeDebugPropertyWatch(parent); - if (d->client->isConnected()) { + if (d->client->status() == QDeclarativeDebugClient::Enabled) { int queryId = d->getId(); watch->m_queryId = queryId; watch->m_client = this; @@ -384,7 +412,7 @@ QDeclarativeDebugObjectExpressionWatch *QDeclarativeEngineDebug::addWatch(const { Q_D(QDeclarativeEngineDebug); QDeclarativeDebugObjectExpressionWatch *watch = new QDeclarativeDebugObjectExpressionWatch(parent); - if (d->client->isConnected()) { + if (d->client->status() == QDeclarativeDebugClient::Enabled) { int queryId = d->getId(); watch->m_queryId = queryId; watch->m_client = this; @@ -407,7 +435,7 @@ QDeclarativeDebugWatch *QDeclarativeEngineDebug::addWatch(const QDeclarativeDebu Q_D(QDeclarativeEngineDebug); QDeclarativeDebugWatch *watch = new QDeclarativeDebugWatch(parent); - if (d->client->isConnected()) { + if (d->client->status() == QDeclarativeDebugClient::Enabled) { int queryId = d->getId(); watch->m_queryId = queryId; watch->m_client = this; @@ -443,7 +471,7 @@ void QDeclarativeEngineDebug::removeWatch(QDeclarativeDebugWatch *watch) d->watched.remove(watch->queryId()); - if (d->client && d->client->isConnected()) { + if (d->client && d->client->status() == QDeclarativeDebugClient::Enabled) { QByteArray message; QDataStream ds(&message, QIODevice::WriteOnly); ds << QByteArray("NO_WATCH") << watch->queryId(); @@ -456,7 +484,7 @@ QDeclarativeDebugEnginesQuery *QDeclarativeEngineDebug::queryAvailableEngines(QO Q_D(QDeclarativeEngineDebug); QDeclarativeDebugEnginesQuery *query = new QDeclarativeDebugEnginesQuery(parent); - if (d->client->isConnected()) { + if (d->client->status() == QDeclarativeDebugClient::Enabled) { query->m_client = this; int queryId = d->getId(); query->m_queryId = queryId; @@ -478,7 +506,7 @@ QDeclarativeDebugRootContextQuery *QDeclarativeEngineDebug::queryRootContexts(co Q_D(QDeclarativeEngineDebug); QDeclarativeDebugRootContextQuery *query = new QDeclarativeDebugRootContextQuery(parent); - if (d->client->isConnected() && engine.debugId() != -1) { + if (d->client->status() == QDeclarativeDebugClient::Enabled && engine.debugId() != -1) { query->m_client = this; int queryId = d->getId(); query->m_queryId = queryId; @@ -500,7 +528,7 @@ QDeclarativeDebugObjectQuery *QDeclarativeEngineDebug::queryObject(const QDeclar Q_D(QDeclarativeEngineDebug); QDeclarativeDebugObjectQuery *query = new QDeclarativeDebugObjectQuery(parent); - if (d->client->isConnected() && object.debugId() != -1) { + if (d->client->status() == QDeclarativeDebugClient::Enabled && object.debugId() != -1) { query->m_client = this; int queryId = d->getId(); query->m_queryId = queryId; @@ -523,7 +551,7 @@ QDeclarativeDebugObjectQuery *QDeclarativeEngineDebug::queryObjectRecursive(cons Q_D(QDeclarativeEngineDebug); QDeclarativeDebugObjectQuery *query = new QDeclarativeDebugObjectQuery(parent); - if (d->client->isConnected() && object.debugId() != -1) { + if (d->client->status() == QDeclarativeDebugClient::Enabled && object.debugId() != -1) { query->m_client = this; int queryId = d->getId(); query->m_queryId = queryId; @@ -546,7 +574,7 @@ QDeclarativeDebugExpressionQuery *QDeclarativeEngineDebug::queryExpressionResult Q_D(QDeclarativeEngineDebug); QDeclarativeDebugExpressionQuery *query = new QDeclarativeDebugExpressionQuery(parent); - if (d->client->isConnected() && objectDebugId != -1) { + if (d->client->status() == QDeclarativeDebugClient::Enabled && objectDebugId != -1) { query->m_client = this; query->m_expr = expr; int queryId = d->getId(); @@ -570,7 +598,7 @@ bool QDeclarativeEngineDebug::setBindingForObject(int objectDebugId, const QStri { Q_D(QDeclarativeEngineDebug); - if (d->client->isConnected() && objectDebugId != -1) { + if (d->client->status() == QDeclarativeDebugClient::Enabled && objectDebugId != -1) { QByteArray message; QDataStream ds(&message, QIODevice::WriteOnly); ds << QByteArray("SET_BINDING") << objectDebugId << propertyName << bindingExpression << isLiteralValue; @@ -585,7 +613,7 @@ bool QDeclarativeEngineDebug::resetBindingForObject(int objectDebugId, const QSt { Q_D(QDeclarativeEngineDebug); - if (d->client->isConnected() && objectDebugId != -1) { + if (d->client->status() == QDeclarativeDebugClient::Enabled && objectDebugId != -1) { QByteArray message; QDataStream ds(&message, QIODevice::WriteOnly); ds << QByteArray("RESET_BINDING") << objectDebugId << propertyName; @@ -601,7 +629,7 @@ bool QDeclarativeEngineDebug::setMethodBody(int objectDebugId, const QString &me { Q_D(QDeclarativeEngineDebug); - if (d->client->isConnected() && objectDebugId != -1) { + if (d->client->status() == QDeclarativeDebugClient::Enabled && objectDebugId != -1) { QByteArray message; QDataStream ds(&message, QIODevice::WriteOnly); ds << QByteArray("SET_METHOD_BODY") << objectDebugId << methodName << methodBody; diff --git a/src/declarative/debugger/qdeclarativedebug_p.h b/src/declarative/debugger/qdeclarativedebug_p.h index 2b1a115..3d83e8a 100644 --- a/src/declarative/debugger/qdeclarativedebug_p.h +++ b/src/declarative/debugger/qdeclarativedebug_p.h @@ -69,7 +69,11 @@ class Q_DECLARATIVE_EXPORT QDeclarativeEngineDebug : public QObject { Q_OBJECT public: - QDeclarativeEngineDebug(QDeclarativeDebugConnection *, QObject * = 0); + enum Status { NotConnected, Unavailable, Enabled }; + + explicit QDeclarativeEngineDebug(QDeclarativeDebugConnection *, QObject * = 0); + + Status status() const; QDeclarativeDebugPropertyWatch *addWatch(const QDeclarativeDebugPropertyReference &, QObject *parent = 0); @@ -101,6 +105,7 @@ public: Q_SIGNALS: void newObjects(); + void statusChanged(Status status); private: Q_DECLARE_PRIVATE(QDeclarativeEngineDebug) diff --git a/src/declarative/debugger/qdeclarativedebugclient.cpp b/src/declarative/debugger/qdeclarativedebugclient.cpp index 2e52b40..f7d7243 100644 --- a/src/declarative/debugger/qdeclarativedebugclient.cpp +++ b/src/declarative/debugger/qdeclarativedebugclient.cpp @@ -50,6 +50,20 @@ QT_BEGIN_NAMESPACE +const int protocolVersion = 1; +const QString serverId = QLatin1String("QDeclarativeDebugServer"); +const QString clientId = QLatin1String("QDeclarativeDebugClient"); + +class QDeclarativeDebugClientPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeDebugClient) +public: + QDeclarativeDebugClientPrivate(); + + QString name; + QDeclarativeDebugConnection *client; +}; + class QDeclarativeDebugConnectionPrivate : public QObject { Q_OBJECT @@ -58,40 +72,123 @@ public: QDeclarativeDebugConnection *q; QPacketProtocol *protocol; - QStringList enabled; + bool gotHello; + QStringList serverPlugins; QHash<QString, QDeclarativeDebugClient *> plugins; + + void advertisePlugins(); + public Q_SLOTS: void connected(); void readyRead(); }; QDeclarativeDebugConnectionPrivate::QDeclarativeDebugConnectionPrivate(QDeclarativeDebugConnection *c) -: QObject(c), q(c), protocol(0) +: QObject(c), q(c), protocol(0), gotHello(false) { protocol = new QPacketProtocol(q, this); QObject::connect(c, SIGNAL(connected()), this, SLOT(connected())); QObject::connect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); } +void QDeclarativeDebugConnectionPrivate::advertisePlugins() +{ + if (!q->isConnected() || !gotHello) + return; + + QPacket pack; + pack << serverId << 1 << plugins.keys(); + protocol->send(pack); +} + void QDeclarativeDebugConnectionPrivate::connected() { QPacket pack; - pack << QString(QLatin1String("QDeclarativeDebugServer")) << enabled; + pack << serverId << 0 << protocolVersion << plugins.keys(); protocol->send(pack); } void QDeclarativeDebugConnectionPrivate::readyRead() { - QPacket pack = protocol->read(); - QString name; QByteArray message; - pack >> name >> message; + if (!gotHello) { + QPacket pack = protocol->read(); + QString name; + + pack >> name; + + bool validHello = false; + if (name == clientId) { + int op = -1; + pack >> op; + if (op == 0) { + int version = -1; + pack >> version; + if (version == protocolVersion) { + pack >> serverPlugins; + validHello = true; + } + } + } - QHash<QString, QDeclarativeDebugClient *>::Iterator iter = - plugins.find(name); - if (iter == plugins.end()) { - qWarning() << "QDeclarativeDebugConnection: Message received for missing plugin" << name; - } else { - (*iter)->messageReceived(message); + if (!validHello) { + qWarning("QDeclarativeDebugConnection: Invalid hello message"); + QObject::disconnect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); + return; + } + + qDebug() << "Available server side plugins: " << serverPlugins; + + QHash<QString, QDeclarativeDebugClient *>::Iterator iter = plugins.begin(); + for (; iter != plugins.end(); ++iter) { + QDeclarativeDebugClient::Status newStatus = QDeclarativeDebugClient::Unavailable; + if (serverPlugins.contains(iter.key())) + newStatus = QDeclarativeDebugClient::Enabled; + iter.value()->statusChanged(newStatus); + } + gotHello = true; + } + + while (protocol->packetsAvailable()) { + QPacket pack = protocol->read(); + QString name; + pack >> name; + + if (name == clientId) { + int op = -1; + pack >> op; + + if (op == 1) { + // Service Discovery + QStringList oldServerPlugins = serverPlugins; + pack >> serverPlugins; + + QHash<QString, QDeclarativeDebugClient *>::Iterator iter = plugins.begin(); + for (; iter != plugins.end(); ++iter) { + const QString pluginName = iter.key(); + QDeclarativeDebugClient::Status newStatus = QDeclarativeDebugClient::Unavailable; + if (serverPlugins.contains(pluginName)) + newStatus = QDeclarativeDebugClient::Enabled; + + if (oldServerPlugins.contains(pluginName) + != serverPlugins.contains(pluginName)) { + iter.value()->statusChanged(newStatus); + } + } + } else { + qWarning() << "QDeclarativeDebugConnection: Unknown control message id" << op; + } + } else { + QByteArray message; + pack >> message; + + QHash<QString, QDeclarativeDebugClient *>::Iterator iter = + plugins.find(name); + if (iter == plugins.end()) { + qWarning() << "QDeclarativeDebugConnection: Message received for missing plugin" << name; + } else { + (*iter)->messageReceived(message); + } + } } } @@ -100,24 +197,22 @@ QDeclarativeDebugConnection::QDeclarativeDebugConnection(QObject *parent) { } -bool QDeclarativeDebugConnection::isConnected() const +QDeclarativeDebugConnection::~QDeclarativeDebugConnection() { - return state() == ConnectedState; + QHash<QString, QDeclarativeDebugClient*>::iterator iter = d->plugins.begin(); + for (; iter != d->plugins.end(); ++iter) { + iter.value()->d_func()->client = 0; + iter.value()->statusChanged(QDeclarativeDebugClient::NotConnected); + } } -class QDeclarativeDebugClientPrivate : public QObjectPrivate +bool QDeclarativeDebugConnection::isConnected() const { - Q_DECLARE_PUBLIC(QDeclarativeDebugClient) -public: - QDeclarativeDebugClientPrivate(); - - QString name; - QDeclarativeDebugConnection *client; - bool enabled; -}; + return state() == ConnectedState; +} QDeclarativeDebugClientPrivate::QDeclarativeDebugClientPrivate() -: client(0), enabled(false) +: client(0) { } @@ -137,60 +232,44 @@ QDeclarativeDebugClient::QDeclarativeDebugClient(const QString &name, d->client = 0; } else { d->client->d->plugins.insert(name, this); + d->client->d->advertisePlugins(); } } -QString QDeclarativeDebugClient::name() const +QDeclarativeDebugClient::~QDeclarativeDebugClient() { Q_D(const QDeclarativeDebugClient); - return d->name; + if (d->client && d->client->d) { + d->client->d->plugins.remove(d->name); + d->client->d->advertisePlugins(); + } } -bool QDeclarativeDebugClient::isEnabled() const +QString QDeclarativeDebugClient::name() const { Q_D(const QDeclarativeDebugClient); - return d->enabled; -} - -void QDeclarativeDebugClient::setEnabled(bool e) -{ - Q_D(QDeclarativeDebugClient); - if (e == d->enabled) - return; - - d->enabled = e; - - if (d->client) { - if (e) - d->client->d->enabled.append(d->name); - else - d->client->d->enabled.removeAll(d->name); - - if (d->client->state() == QTcpSocket::ConnectedState) { - QPacket pack; - pack << QString(QLatin1String("QDeclarativeDebugServer")); - if (e) pack << (int)1; - else pack << (int)2; - pack << d->name; - d->client->d->protocol->send(pack); - } - } + return d->name; } -bool QDeclarativeDebugClient::isConnected() const +QDeclarativeDebugClient::Status QDeclarativeDebugClient::status() const { Q_D(const QDeclarativeDebugClient); + if (!d->client + || !d->client->isConnected() + || !d->client->d->gotHello) + return NotConnected; - if (!d->client) - return false; - return d->client->isConnected(); + if (d->client->d->serverPlugins.contains(d->name)) + return Enabled; + + return Unavailable; } void QDeclarativeDebugClient::sendMessage(const QByteArray &message) { Q_D(QDeclarativeDebugClient); - if (!d->client || !d->client->isConnected()) + if (status() != Enabled) return; QPacket pack; @@ -198,6 +277,10 @@ void QDeclarativeDebugClient::sendMessage(const QByteArray &message) d->client->d->protocol->send(pack); } +void QDeclarativeDebugClient::statusChanged(Status status) +{ +} + void QDeclarativeDebugClient::messageReceived(const QByteArray &) { } diff --git a/src/declarative/debugger/qdeclarativedebugclient_p.h b/src/declarative/debugger/qdeclarativedebugclient_p.h index 4144a66..8d1706d 100644 --- a/src/declarative/debugger/qdeclarativedebugclient_p.h +++ b/src/declarative/debugger/qdeclarativedebugclient_p.h @@ -57,6 +57,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeDebugConnection : public QTcpSocket Q_DISABLE_COPY(QDeclarativeDebugConnection) public: QDeclarativeDebugConnection(QObject * = 0); + ~QDeclarativeDebugConnection(); bool isConnected() const; private: @@ -73,18 +74,19 @@ class Q_DECLARATIVE_EXPORT QDeclarativeDebugClient : public QObject Q_DISABLE_COPY(QDeclarativeDebugClient) public: + enum Status { NotConnected, Unavailable, Enabled }; + QDeclarativeDebugClient(const QString &, QDeclarativeDebugConnection *parent); + ~QDeclarativeDebugClient(); QString name() const; - bool isEnabled() const; - void setEnabled(bool); - - bool isConnected() const; + Status status() const; void sendMessage(const QByteArray &); protected: + virtual void statusChanged(Status); virtual void messageReceived(const QByteArray &); private: diff --git a/src/declarative/debugger/qdeclarativedebugservice.cpp b/src/declarative/debugger/qdeclarativedebugservice.cpp index 1f2bf4f..0fbc1e3 100644 --- a/src/declarative/debugger/qdeclarativedebugservice.cpp +++ b/src/declarative/debugger/qdeclarativedebugservice.cpp @@ -54,6 +54,30 @@ QT_BEGIN_NAMESPACE +/* + QDeclarativeDebug Protocol (Version 1): + + handshake: + 1. Client sends + "QDeclarativeDebugServer" 0 version pluginNames + version: an int representing the highest protocol version the client knows + pluginNames: plugins available on client side + 2. Server sends + "QDeclarativeDebugClient" 0 version pluginNames + version: an int representing the highest protocol version the client & server know + pluginNames: plugins available on server side. plugins both in the client and server message are enabled. + client plugin advertisement + 1. Client sends + "QDeclarativeDebugServer" 1 pluginNames + server plugin advertisement + 1. Server sends + "QDeclarativeDebugClient" 1 pluginNames + plugin communication: + Everything send with a header different to "QDeclarativeDebugServer" is sent to the appropriate plugin. + */ + +const int protocolVersion = 1; + class QDeclarativeDebugServerPrivate; class QDeclarativeDebugServer : public QObject { @@ -82,11 +106,13 @@ class QDeclarativeDebugServerPrivate : public QObjectPrivate public: QDeclarativeDebugServerPrivate(); + void advertisePlugins(); + int port; QTcpSocket *connection; QPacketProtocol *protocol; QHash<QString, QDeclarativeDebugService *> plugins; - QStringList enabledPlugins; + QStringList clientPlugins; QTcpServer *tcpServer; bool gotHello; }; @@ -106,6 +132,18 @@ QDeclarativeDebugServerPrivate::QDeclarativeDebugServerPrivate() { } +void QDeclarativeDebugServerPrivate::advertisePlugins() +{ + if (!connection + || connection->state() != QTcpSocket::ConnectedState + || !gotHello) + return; + + QPacket pack; + pack << QString(QLatin1String("QDeclarativeDebugClient")) << 1 << plugins.keys(); + protocol->send(pack); +} + void QDeclarativeDebugServer::listen() { Q_D(QDeclarativeDebugServer); @@ -202,9 +240,13 @@ void QDeclarativeDebugServer::readyRead() if (!d->gotHello) { QPacket hello = d->protocol->read(); - QString name; - hello >> name >> d->enabledPlugins; - if (name != QLatin1String("QDeclarativeDebugServer")) { + + QString name; + int op; + hello >> name >> op; + + if (name != QLatin1String("QDeclarativeDebugServer") + || op != 0) { qWarning("QDeclarativeDebugServer: Invalid hello message"); QObject::disconnect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); d->protocol->deleteLater(); @@ -213,6 +255,23 @@ void QDeclarativeDebugServer::readyRead() d->connection = 0; return; } + + int version; + hello >> version >> d->clientPlugins; + + QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin(); + for (; iter != d->plugins.end(); ++iter) { + QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable; + if (d->clientPlugins.contains(iter.key())) + newStatus = QDeclarativeDebugService::Enabled; + iter.value()->statusChanged(newStatus); + } + + QPacket helloAnswer; + helloAnswer << QString(QLatin1String("QDeclarativeDebugClient")) << 0 << protocolVersion << d->plugins.keys(); + d->protocol->send(helloAnswer); + d->connection->flush(); + d->gotHello = true; qWarning("QDeclarativeDebugServer: Connection established"); } @@ -226,32 +285,29 @@ void QDeclarativeDebugServer::readyRead() pack >> name; if (name == debugServer) { - int op = -1; QString plugin; - pack >> op >> plugin; + int op = -1; + pack >> op; if (op == 1) { - // Enable - if (!d->enabledPlugins.contains(plugin)) { - d->enabledPlugins.append(plugin); - QHash<QString, QDeclarativeDebugService *>::Iterator iter = - d->plugins.find(plugin); - if (iter != d->plugins.end()) - (*iter)->enabledChanged(true); - } - - } else if (op == 2) { - // Disable - if (d->enabledPlugins.contains(plugin)) { - d->enabledPlugins.removeAll(plugin); - QHash<QString, QDeclarativeDebugService *>::Iterator iter = - d->plugins.find(plugin); - if (iter != d->plugins.end()) - (*iter)->enabledChanged(false); + // Service Discovery + QStringList oldClientPlugins = d->clientPlugins; + pack >> d->clientPlugins; + + QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin(); + for (; iter != d->plugins.end(); ++iter) { + const QString pluginName = iter.key(); + QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable; + if (d->clientPlugins.contains(pluginName)) + newStatus = QDeclarativeDebugService::Enabled; + + if (oldClientPlugins.contains(pluginName) + != d->clientPlugins.contains(pluginName)) { + iter.value()->statusChanged(newStatus); + } } } else { qWarning("QDeclarativeDebugServer: Invalid control message %d", op); } - } else { QByteArray message; pack >> message; @@ -287,6 +343,16 @@ QDeclarativeDebugService::QDeclarativeDebugService(const QString &name, QObject d->server = 0; } else { d->server->d_func()->plugins.insert(name, this); + d->server->d_func()->advertisePlugins(); + } +} + +QDeclarativeDebugService::~QDeclarativeDebugService() +{ + Q_D(const QDeclarativeDebugService); + if (d->server) { + d->server->d_func()->plugins.remove(d->name); + d->server->d_func()->advertisePlugins(); } } @@ -296,10 +362,16 @@ QString QDeclarativeDebugService::name() const return d->name; } -bool QDeclarativeDebugService::isEnabled() const +QDeclarativeDebugService::Status QDeclarativeDebugService::status() const { Q_D(const QDeclarativeDebugService); - return (d->server && d->server->d_func()->enabledPlugins.contains(d->name)); + if (!d->server + || !d->server->hasDebuggingClient()) + return NotConnected; + if (d->server->d_func()->clientPlugins.contains(d->name)) + return Enabled; + + return Unavailable; } namespace { @@ -422,7 +494,7 @@ void QDeclarativeDebugService::sendMessage(const QByteArray &message) d->server->d_func()->connection->flush(); } -void QDeclarativeDebugService::enabledChanged(bool) +void QDeclarativeDebugService::statusChanged(Status) { } diff --git a/src/declarative/debugger/qdeclarativedebugservice_p.h b/src/declarative/debugger/qdeclarativedebugservice_p.h index c461ddf..0cadbe5 100644 --- a/src/declarative/debugger/qdeclarativedebugservice_p.h +++ b/src/declarative/debugger/qdeclarativedebugservice_p.h @@ -56,12 +56,15 @@ class Q_DECLARATIVE_EXPORT QDeclarativeDebugService : public QObject Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeDebugService) Q_DISABLE_COPY(QDeclarativeDebugService) + public: - QDeclarativeDebugService(const QString &, QObject *parent = 0); + explicit QDeclarativeDebugService(const QString &, QObject *parent = 0); + ~QDeclarativeDebugService(); QString name() const; - bool isEnabled() const; + enum Status { NotConnected, Unavailable, Enabled }; + Status status() const; void sendMessage(const QByteArray &); @@ -74,7 +77,7 @@ public: static bool hasDebuggingClient(); protected: - virtual void enabledChanged(bool); + virtual void statusChanged(Status); virtual void messageReceived(const QByteArray &); private: diff --git a/src/declarative/debugger/qdeclarativedebugtrace.cpp b/src/declarative/debugger/qdeclarativedebugtrace.cpp index b2b0c8a..03e2d56 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace.cpp +++ b/src/declarative/debugger/qdeclarativedebugtrace.cpp @@ -78,7 +78,7 @@ void QDeclarativeDebugTrace::endRange(RangeType t) void QDeclarativeDebugTrace::addEventImpl(EventType event) { - if (!isEnabled()) + if (status() != Enabled) return; QByteArray data; @@ -89,7 +89,7 @@ void QDeclarativeDebugTrace::addEventImpl(EventType event) void QDeclarativeDebugTrace::startRangeImpl(RangeType range) { - if (!isEnabled()) + if (status() != Enabled) return; QByteArray data; @@ -100,7 +100,7 @@ void QDeclarativeDebugTrace::startRangeImpl(RangeType range) void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &u) { - if (!isEnabled()) + if (status() != Enabled) return; QByteArray data; @@ -111,7 +111,7 @@ void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &u) void QDeclarativeDebugTrace::endRangeImpl(RangeType range) { - if (!isEnabled()) + if (status() != Enabled) return; QByteArray data; diff --git a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp index adba190..dd58baf 100644 --- a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp +++ b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp @@ -324,13 +324,16 @@ void tst_QDeclarativeDebug::initTestCase() bool ok = m_conn->waitForConnected(); Q_ASSERT(ok); QTRY_VERIFY(QDeclarativeDebugService::hasDebuggingClient()); - m_dbg = new QDeclarativeEngineDebug(m_conn, this); + QTRY_VERIFY(m_dbg->status() == QDeclarativeEngineDebug::Enabled); } void tst_QDeclarativeDebug::cleanupTestCase() { + delete m_dbg; + delete m_conn; qDeleteAll(m_components); + delete m_engine; } void tst_QDeclarativeDebug::setMethodBody() diff --git a/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp b/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp index 7db0e60..72af3eb 100644 --- a/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp +++ b/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp @@ -66,9 +66,7 @@ private slots: void initTestCase(); void name(); - void isEnabled(); - void setEnabled(); - void isConnected(); + void status(); void sendMessage(); }; @@ -96,46 +94,33 @@ void tst_QDeclarativeDebugClient::name() QCOMPARE(client.name(), name); } -void tst_QDeclarativeDebugClient::isEnabled() +void tst_QDeclarativeDebugClient::status() { - QDeclarativeDebugClient client("tst_QDeclarativeDebugClient::isEnabled()", m_conn); - QCOMPARE(client.isEnabled(), false); -} + { + QDeclarativeDebugConnection dummyConn; + QDeclarativeDebugClient client("tst_QDeclarativeDebugClient::status()", &dummyConn); + QCOMPARE(client.status(), QDeclarativeDebugClient::NotConnected); + } -void tst_QDeclarativeDebugClient::setEnabled() -{ - QDeclarativeDebugTestService service("tst_QDeclarativeDebugClient::setEnabled()"); - QDeclarativeDebugTestClient client("tst_QDeclarativeDebugClient::setEnabled()", m_conn); + QDeclarativeDebugTestClient client("tst_QDeclarativeDebugClient::status()", m_conn); + QCOMPARE(client.status(), QDeclarativeDebugClient::Unavailable); - QCOMPARE(service.isEnabled(), false); + { + QDeclarativeDebugTestService service("tst_QDeclarativeDebugClient::status()"); + QDeclarativeDebugTest::waitForSignal(&client, SIGNAL(statusHasChanged())); + QCOMPARE(client.status(), QDeclarativeDebugClient::Enabled); + } + QDeclarativeDebugTest::waitForSignal(&client, SIGNAL(statusHasChanged())); - client.setEnabled(true); - QCOMPARE(client.isEnabled(), true); - QDeclarativeDebugTest::waitForSignal(&service, SIGNAL(enabledStateChanged())); - QCOMPARE(service.isEnabled(), true); - - client.setEnabled(false); - QCOMPARE(client.isEnabled(), false); - QDeclarativeDebugTest::waitForSignal(&service, SIGNAL(enabledStateChanged())); - QCOMPARE(service.isEnabled(), false); -} - -void tst_QDeclarativeDebugClient::isConnected() -{ - QDeclarativeDebugClient client1("tst_QDeclarativeDebugClient::isConnected() A", m_conn); - QCOMPARE(client1.isConnected(), true); - - QDeclarativeDebugConnection conn; - QDeclarativeDebugClient client2("tst_QDeclarativeDebugClient::isConnected() B", &conn); - QCOMPARE(client2.isConnected(), false); - - QDeclarativeDebugClient client3("tst_QDeclarativeDebugClient::isConnected() C", 0); - QCOMPARE(client3.isConnected(), false); + QCOMPARE(client.status(), QDeclarativeDebugClient::Unavailable); // duplicate plugin name - QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugClient: Conflicting plugin name \"tst_QDeclarativeDebugClient::isConnected() A\" "); - QDeclarativeDebugClient client4("tst_QDeclarativeDebugClient::isConnected() A", m_conn); - QCOMPARE(client4.isConnected(), false); + QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugClient: Conflicting plugin name \"tst_QDeclarativeDebugClient::status()\" "); + QDeclarativeDebugClient client2("tst_QDeclarativeDebugClient::status()", m_conn); + QCOMPARE(client2.status(), QDeclarativeDebugClient::NotConnected); + + QDeclarativeDebugClient client3("tst_QDeclarativeDebugClient::status3()", 0); + QCOMPARE(client3.status(), QDeclarativeDebugClient::NotConnected); } void tst_QDeclarativeDebugClient::sendMessage() @@ -145,6 +130,7 @@ void tst_QDeclarativeDebugClient::sendMessage() QByteArray msg = "hello!"; + QDeclarativeDebugTest::waitForSignal(&client, SIGNAL(statusHasChanged())); client.sendMessage(msg); QByteArray resp = client.waitForResponse(); QCOMPARE(resp, msg); diff --git a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp index 4683199..bce4713 100644 --- a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp +++ b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp @@ -66,8 +66,7 @@ private slots: void initTestCase(); void name(); - void isEnabled(); - void enabledChanged(); + void status(); void sendMessage(); void idForObject(); void objectForId(); @@ -97,31 +96,24 @@ void tst_QDeclarativeDebugService::name() QCOMPARE(service.name(), name); } -void tst_QDeclarativeDebugService::isEnabled() +void tst_QDeclarativeDebugService::status() { - QDeclarativeDebugTestService service("tst_QDeclarativeDebugService::isEnabled()", m_conn); - QCOMPARE(service.isEnabled(), false); + QDeclarativeDebugTestService service("tst_QDeclarativeDebugService::status()"); + QCOMPARE(service.status(), QDeclarativeDebugService::Unavailable); - QDeclarativeDebugTestClient client("tst_QDeclarativeDebugService::isEnabled()", m_conn); - client.setEnabled(true); - QDeclarativeDebugTest::waitForSignal(&service, SIGNAL(enabledStateChanged())); - QCOMPARE(service.isEnabled(), true); + { + QDeclarativeDebugTestClient client("tst_QDeclarativeDebugService::status()", m_conn); + QDeclarativeDebugTest::waitForSignal(&service, SIGNAL(statusHasChanged())); + QCOMPARE(service.status(), QDeclarativeDebugService::Enabled); + } - QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugService: Conflicting plugin name \"tst_QDeclarativeDebugService::isEnabled()\" "); - QDeclarativeDebugService duplicate("tst_QDeclarativeDebugService::isEnabled()", m_conn); - QCOMPARE(duplicate.isEnabled(), false); -} - -void tst_QDeclarativeDebugService::enabledChanged() -{ - QDeclarativeDebugTestService service("tst_QDeclarativeDebugService::enabledChanged()"); - QDeclarativeDebugTestClient client("tst_QDeclarativeDebugService::enabledChanged()", m_conn); + QDeclarativeDebugTest::waitForSignal(&service, SIGNAL(statusHasChanged())); + QCOMPARE(service.status(), QDeclarativeDebugService::Unavailable); - QCOMPARE(service.enabled, false); + QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugService: Conflicting plugin name \"tst_QDeclarativeDebugService::status()\" "); - client.setEnabled(true); - QDeclarativeDebugTest::waitForSignal(&service, SIGNAL(enabledStateChanged())); - QCOMPARE(service.enabled, true); + QDeclarativeDebugService duplicate("tst_QDeclarativeDebugService::status()"); + QCOMPARE(duplicate.status(), QDeclarativeDebugService::NotConnected); } void tst_QDeclarativeDebugService::sendMessage() @@ -131,6 +123,11 @@ void tst_QDeclarativeDebugService::sendMessage() QByteArray msg = "hello!"; + if (service.status() != QDeclarativeDebugService::Enabled) + QDeclarativeDebugTest::waitForSignal(&service, SIGNAL(statusHasChanged())); + if (client.status() != QDeclarativeDebugClient::Enabled) + QDeclarativeDebugTest::waitForSignal(&client, SIGNAL(statusHasChanged())); + client.sendMessage(msg); QByteArray resp = client.waitForResponse(); QCOMPARE(resp, msg); diff --git a/tests/auto/declarative/shared/debugutil.cpp b/tests/auto/declarative/shared/debugutil.cpp index c0c3eca..5f68e44 100644 --- a/tests/auto/declarative/shared/debugutil.cpp +++ b/tests/auto/declarative/shared/debugutil.cpp @@ -60,7 +60,7 @@ bool QDeclarativeDebugTest::waitForSignal(QObject *receiver, const char *member, } QDeclarativeDebugTestService::QDeclarativeDebugTestService(const QString &s, QObject *parent) - : QDeclarativeDebugService(s, parent), enabled(false) + : QDeclarativeDebugService(s, parent) { } @@ -69,10 +69,9 @@ void QDeclarativeDebugTestService::messageReceived(const QByteArray &ba) sendMessage(ba); } -void QDeclarativeDebugTestService::enabledChanged(bool e) +void QDeclarativeDebugTestService::statusChanged(Status) { - enabled = e; - emit enabledStateChanged(); + emit statusHasChanged(); } @@ -92,9 +91,13 @@ QByteArray QDeclarativeDebugTestClient::waitForResponse() return lastMsg; } +void QDeclarativeDebugTestClient::statusChanged(Status status) +{ + emit statusHasChanged(); +} + void QDeclarativeDebugTestClient::messageReceived(const QByteArray &ba) { lastMsg = ba; emit serverMessage(ba); } - diff --git a/tests/auto/declarative/shared/debugutil_p.h b/tests/auto/declarative/shared/debugutil_p.h index e6bb7ad..434e053 100644 --- a/tests/auto/declarative/shared/debugutil_p.h +++ b/tests/auto/declarative/shared/debugutil_p.h @@ -62,15 +62,13 @@ class QDeclarativeDebugTestService : public QDeclarativeDebugService Q_OBJECT public: QDeclarativeDebugTestService(const QString &s, QObject *parent = 0); - bool enabled; signals: - void enabledStateChanged(); + void statusHasChanged(); protected: virtual void messageReceived(const QByteArray &ba); - - virtual void enabledChanged(bool e); + virtual void statusChanged(Status status); }; class QDeclarativeDebugTestClient : public QDeclarativeDebugClient @@ -82,9 +80,11 @@ public: QByteArray waitForResponse(); signals: + void statusHasChanged(); void serverMessage(const QByteArray &); protected: + virtual void statusChanged(Status status); virtual void messageReceived(const QByteArray &ba); private: |