void AbstractViewInspector::handleMessage(const QByteArray &message)
{
bool success = true;
- QDataStream ds(message);
+ QQmlDebugStream ds(message);
QByteArray type;
ds >> type;
}
QByteArray response;
- QDataStream rs(&response, QIODevice::WriteOnly);
+ QQmlDebugStream rs(&response, QIODevice::WriteOnly);
rs << QByteArray(RESPONSE) << requestId << success;
m_debugService->sendMessage(response);
}
void AbstractViewInspector::sendCurrentObjects(const QList<QObject*> &objects)
{
QByteArray message;
- QDataStream ds(&message, QIODevice::WriteOnly);
+ QQmlDebugStream ds(&message, QIODevice::WriteOnly);
ds << QByteArray(EVENT) << m_eventId++ << QByteArray(SELECT);
//We just eavesdrop and forward the messages to a port
//only if a client is connected to it.
QByteArray message;
- QDataStream ws(&message, QIODevice::WriteOnly);
+ QQmlDebugStream ws(&message, QIODevice::WriteOnly);
ws << QByteArray("MESSAGE") << type << QString::fromLocal8Bit(buf).toUtf8();
ws << QString::fromLatin1(ctxt.file).toUtf8();
ws << ctxt.line << QString::fromLatin1(ctxt.function).toUtf8();
handshake:
1. Client sends
- "QDeclarativeDebugServer" 0 version pluginNames
+ "QDeclarativeDebugServer" 0 version pluginNames [QDataStream version]
version: an int representing the highest protocol version the client knows
pluginNames: plugins available on client side
2. Server sends
- "QDeclarativeDebugClient" 0 version pluginNames pluginVersions
+ "QDeclarativeDebugClient" 0 version pluginNames pluginVersions [QDataStream version]
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
*/
const int protocolVersion = 1;
+int QQmlDebugServer::s_dataStreamVersion = QDataStream::Qt_4_7;
// print detailed information about loading of plugins
DEFINE_BOOL_CONFIG_OPTION(qmlDebugVerbose, QML_DEBUGGER_VERBOSE)
QByteArray message;
{
- QDataStream out(&message, QIODevice::WriteOnly);
+ QQmlDebugStream out(&message, QIODevice::WriteOnly);
QStringList pluginNames;
QList<float> pluginVersions;
foreach (QQmlDebugService *service, plugins.values()) {
Q_D(QQmlDebugServer);
- QDataStream in(message);
+ QQmlDebugStream in(message);
QString name;
int version;
in >> version >> d->clientPlugins;
+ //Get the supported QDataStream version
+ if (!in.atEnd()) {
+ in >> s_dataStreamVersion;
+ if (s_dataStreamVersion > QDataStream().version())
+ s_dataStreamVersion = QDataStream().version();
+ }
// Send the hello answer immediately, since it needs to arrive before
// the plugins below start sending messages.
QByteArray helloAnswer;
{
- QDataStream out(&helloAnswer, QIODevice::WriteOnly);
+ QQmlDebugStream out(&helloAnswer, QIODevice::WriteOnly);
QStringList pluginNames;
QList<float> pluginVersions;
foreach (QQmlDebugService *service, d->plugins.values()) {
pluginVersions << service->version();
}
- out << QString(QStringLiteral("QDeclarativeDebugClient")) << 0 << protocolVersion << pluginNames << pluginVersions;
+ out << QString(QStringLiteral("QDeclarativeDebugClient")) << 0 << protocolVersion
+ << pluginNames << pluginVersions << s_dataStreamVersion;
}
d->connection->send(QList<QByteArray>() << helloAnswer);
QList<QByteArray> prefixedMessages;
foreach (const QByteArray &message, messages) {
QByteArray prefixed;
- QDataStream out(&prefixed, QIODevice::WriteOnly);
+ QQmlDebugStream out(&prefixed, QIODevice::WriteOnly);
out << service->name() << message;
prefixedMessages << prefixed;
}
Q_PRIVATE_SLOT(d_func(), void _q_changeServiceState(const QString &serviceName,
QQmlDebugService::State state))
Q_PRIVATE_SLOT(d_func(), void _q_sendMessages(QList<QByteArray>))
+
+public:
+ static int s_dataStreamVersion;
};
QT_END_NAMESPACE
{
}
+QQmlDebugStream::QQmlDebugStream()
+ : QDataStream()
+{
+ setVersion(QQmlDebugServer::s_dataStreamVersion);
+}
+
+QQmlDebugStream::QQmlDebugStream(QIODevice *d)
+ : QDataStream(d)
+{
+ setVersion(QQmlDebugServer::s_dataStreamVersion);
+}
+
+QQmlDebugStream::QQmlDebugStream(QByteArray *ba, QIODevice::OpenMode flags)
+ : QDataStream(ba, flags)
+{
+ setVersion(QQmlDebugServer::s_dataStreamVersion);
+}
+
+QQmlDebugStream::QQmlDebugStream(const QByteArray &ba)
+ : QDataStream(ba)
+{
+ setVersion(QQmlDebugServer::s_dataStreamVersion);
+}
+
QT_END_NAMESPACE
#define QQMLDEBUGSERVICE_H
#include <QtCore/qobject.h>
+#include <QtCore/QDataStream>
#include <private/qtqmlglobal_p.h>
friend class QQmlDebugServerPrivate;
};
+class Q_QML_PRIVATE_EXPORT QQmlDebugStream : public QDataStream
+{
+public:
+ QQmlDebugStream();
+ explicit QQmlDebugStream(QIODevice *d);
+ QQmlDebugStream(QByteArray *ba, QIODevice::OpenMode flags);
+ QQmlDebugStream(const QByteArray &ba);
+};
+
QT_END_NAMESPACE
QT_END_HEADER
void QQmlEngineDebugService::processMessage(const QByteArray &message)
{
- QDataStream ds(message);
+ QQmlDebugStream ds(message);
QByteArray type;
int queryId;
ds >> type >> queryId;
+ QByteArray reply;
+ QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
+
if (type == "LIST_ENGINES") {
- QByteArray reply;
- QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("LIST_ENGINES_R");
rs << queryId << m_engines.count();
rs << engineName << engineId;
}
- sendMessage(reply);
} else if (type == "LIST_OBJECTS") {
int engineId = -1;
ds >> engineId;
QQmlEngine *engine =
qobject_cast<QQmlEngine *>(QQmlDebugService::objectForId(engineId));
- QByteArray reply;
- QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("LIST_OBJECTS_R") << queryId;
if (engine) {
buildStatesList(true, ctxtPriv->instances);
}
- sendMessage(reply);
} else if (type == "FETCH_OBJECT") {
int objectId;
bool recurse;
QObject *object = QQmlDebugService::objectForId(objectId);
- QByteArray reply;
- QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("FETCH_OBJECT_R") << queryId;
if (object) {
buildObjectDump(rs, object, recurse, dumpProperties);
}
- sendMessage(reply);
} else if (type == "WATCH_OBJECT") {
int objectId;
ds >> objectId;
bool ok = m_watch->addWatch(queryId, objectId);
- QByteArray reply;
- QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("WATCH_OBJECT_R") << queryId << ok;
- sendMessage(reply);
} else if (type == "WATCH_PROPERTY") {
int objectId;
QByteArray property;
ds >> objectId >> property;
bool ok = m_watch->addWatch(queryId, objectId, property);
- QByteArray reply;
- QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("WATCH_PROPERTY_R") << queryId << ok;
- sendMessage(reply);
} else if (type == "WATCH_EXPR_OBJECT") {
int debugId;
QString expr;
ds >> debugId >> expr;
bool ok = m_watch->addWatch(queryId, debugId, expr);
- QByteArray reply;
- QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("WATCH_EXPR_OBJECT_R") << queryId << ok;
- sendMessage(reply);
+
} else if (type == "NO_WATCH") {
bool ok = m_watch->removeWatch(queryId);
- QByteArray reply;
- QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("NO_WATCH_R") << queryId << ok;
- sendMessage(reply);
+
} else if (type == "EVAL_EXPRESSION") {
int objectId;
QString expr;
result = QString(QStringLiteral("<unknown context>"));
}
- QByteArray reply;
- QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("EVAL_EXPRESSION_R") << queryId << result;
- sendMessage(reply);
} else if (type == "SET_BINDING") {
int objectId;
QString propertyName;
bool ok = setBinding(objectId, propertyName, expr, isLiteralValue,
filename, line);
- QByteArray reply;
- QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("SET_BINDING_R") << queryId << ok;
- sendMessage(reply);
} else if (type == "RESET_BINDING") {
int objectId;
QString propertyName;
ds >> objectId >> propertyName;
bool ok = resetBinding(objectId, propertyName);
- QByteArray reply;
- QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("RESET_BINDING_R") << queryId << ok;
- sendMessage(reply);
} else if (type == "SET_METHOD_BODY") {
int objectId;
QString methodName;
ds >> objectId >> methodName >> methodBody;
bool ok = setMethodBody(objectId, methodName, methodBody);
- QByteArray reply;
- QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("SET_METHOD_BODY_R") << queryId << ok;
- sendMessage(reply);
}
+ sendMessage(reply);
}
bool QQmlEngineDebugService::setBinding(int objectId,
void QQmlEngineDebugService::propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value)
{
QByteArray reply;
- QDataStream rs(&reply, QIODevice::WriteOnly);
+ QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("UPDATE_WATCH") << id << objectId << QByteArray(property.name()) << valueContents(value);
int parentId = QQmlDebugService::idForObject(object->parent());
QByteArray reply;
- QDataStream rs(&reply, QIODevice::WriteOnly);
+ QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
//unique queryId -1
rs << QByteArray("OBJECT_CREATED") << -1 << engineId << objectId << parentId;
{
QByteArray data;
//### using QDataStream is relatively expensive
- QDataStream ds(&data, QIODevice::WriteOnly);
+ QQmlDebugStream ds(&data, QIODevice::WriteOnly);
ds << time << messageType << detailType;
if (messageType == (int)QQmlProfilerService::RangeData)
ds << detailData;
//indicate completion
QByteArray data;
- QDataStream ds(&data, QIODevice::WriteOnly);
+ QQmlDebugStream ds(&data, QIODevice::WriteOnly);
ds << (qint64)-1 << (int)Complete;
messages << data;
QMutexLocker lock(&m_initializeMutex);
QByteArray rwData = message;
- QDataStream stream(&rwData, QIODevice::ReadOnly);
+ QQmlDebugStream stream(&rwData, QIODevice::ReadOnly);
bool enabled;
stream >> enabled;
Q_D(QV8DebugService);
QMutexLocker lock(&d->initializeMutex);
- QDataStream ds(message);
+ QQmlDebugStream ds(message);
QByteArray header;
ds >> header;
sendDebugMessage(QString::fromUtf8(data));
} else if (command == V8_DEBUGGER_KEY_BREAK_ON_SIGNAL) {
- QDataStream rs(data);
+ QQmlDebugStream rs(data);
QByteArray signal;
bool enabled;
rs >> signal >> enabled;
QByteArray QV8DebugServicePrivate::packMessage(const QString &type, const QString &message)
{
QByteArray reply;
- QDataStream rs(&reply, QIODevice::WriteOnly);
+ QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
QByteArray cmd("V8DEBUG");
rs << cmd << type.toUtf8() << message.toUtf8();
return reply;
WriteResult WriteAsciiChunk(char *rawData, int size)
{
QByteArray data;
- QDataStream ds(&data, QIODevice::WriteOnly);
+ QQmlDebugStream ds(&data, QIODevice::WriteOnly);
ds << QV8ProfilerService::V8SnapshotChunk << QByteArray(rawData, size);
messages.append(data);
return kContinue;
{
QByteArray data;
//### using QDataStream is relatively expensive
- QDataStream ds(&data, QIODevice::WriteOnly);
+ QQmlDebugStream ds(&data, QIODevice::WriteOnly);
ds << messageType << filename << functionname << lineNumber << totalTime << selfTime << treeLevel;
return data;
{
Q_D(QV8ProfilerService);
- QDataStream ds(message);
+ QQmlDebugStream ds(message);
QByteArray command;
QByteArray option;
QByteArray title;
// indicate profiling started
QByteArray data;
- QDataStream ds(&data, QIODevice::WriteOnly);
+ QQmlDebugStream ds(&data, QIODevice::WriteOnly);
ds << (int)QV8ProfilerService::V8Started;
sendMessage(data);
} else {
// indicate completion, even without data
QByteArray data;
- QDataStream ds(&data, QIODevice::WriteOnly);
+ QQmlDebugStream ds(&data, QIODevice::WriteOnly);
ds << (int)QV8ProfilerService::V8Complete;
sendMessage(data);
//indicate completion
QByteArray data;
- QDataStream ds(&data, QIODevice::WriteOnly);
+ QQmlDebugStream ds(&data, QIODevice::WriteOnly);
ds << (int)QV8ProfilerService::V8SnapshotComplete;
messages.append(data);
//indicate completion
QByteArray data;
- QDataStream ds(&data, QIODevice::WriteOnly);
+ QQmlDebugStream ds(&data, QIODevice::WriteOnly);
ds << (int)QV8ProfilerService::V8Complete;
messages.append(data);
#include "qqmldebugclient.h"
#include "qqmldebugtestservice.h"
-#define PORT 13769
-#define STR_PORT "13769"
+#define PORT 3769
+#define STR_PORT "3769"
class tst_QQmlDebugService : public QObject
{
private:
QQmlDebugConnection *m_conn;
+
private slots:
- void initTestCase();
+ void initTestCase();
void name();
void version();
void state();
void idForObject();
void objectForId();
void objectToString();
+ void checkSupportForDataStreamVersion();
+ void checkSupportForOldDataStreamVersion();
};
void tst_QQmlDebugService::initTestCase()
duplicate.sendMessage("msg");
}
+void tst_QQmlDebugService::checkSupportForDataStreamVersion()
+{
+ QQmlDebugTestService service("tst_QQmlDebugService::sendMessage2()");
+ QQmlDebugTestClient client("tst_QQmlDebugService::sendMessage2()", m_conn);
+
+ QByteArray msg = "hello!";
+
+ QTRY_COMPARE(client.state(), QQmlDebugClient::Enabled);
+ QTRY_COMPARE(service.state(), QQmlDebugService::Enabled);
+
+ client.sendMessage(msg);
+ QByteArray resp = client.waitForResponse();
+ QCOMPARE(resp, msg);
+ QCOMPARE(m_conn->dataStreamVersion(), int(QDataStream::Qt_5_0));
+}
+
void tst_QQmlDebugService::idForObject()
{
QCOMPARE(QQmlDebugService::idForObject(0), -1);
delete obj;
}
+void tst_QQmlDebugService::checkSupportForOldDataStreamVersion()
+{
+ //create a new connection;
+ delete m_conn;
+ m_conn = new QQmlDebugConnection(this);
+ m_conn->setDataStreamVersion(QDataStream::Qt_4_7);
+ for (int i = 0; i < 50; ++i) {
+ // try for 5 seconds ...
+ m_conn->connectToHost("127.0.0.1", PORT);
+ if (m_conn->waitForConnected())
+ break;
+ QTest::qSleep(100);
+ }
+ QVERIFY(m_conn->isConnected());
+
+ QTRY_VERIFY(QQmlDebugService::hasDebuggingClient());
+ QQmlDebugTestService service("tst_QQmlDebugService::sendMessage2()");
+ QQmlDebugTestClient client("tst_QQmlDebugService::sendMessage2()", m_conn);
+
+ QByteArray msg = "hello!";
+
+ QTRY_COMPARE(client.state(), QQmlDebugClient::Enabled);
+ QTRY_COMPARE(service.state(), QQmlDebugService::Enabled);
+
+ client.sendMessage(msg);
+ QByteArray resp = client.waitForResponse();
+ QCOMPARE(resp, msg);
+ QCOMPARE(m_conn->dataStreamVersion(), int(QDataStream::Qt_4_7));
+}
+
int main(int argc, char *argv[])
{
void QQmlDebugConnectionPrivate::connected()
{
QPacket pack;
- pack << serverId << 0 << protocolVersion << plugins.keys();
+ pack << serverId << 0 << protocolVersion << plugins.keys()
+ << q->m_dataStreamVersion;
protocol->send(pack);
q->flush();
}
serverPlugins.insert(pluginNames.at(i), pluginVersion);
}
+ pack >> q->m_dataStreamVersion;
validHello = true;
}
}
}
QQmlDebugConnection::QQmlDebugConnection(QObject *parent)
- : QIODevice(parent), d(new QQmlDebugConnectionPrivate(this))
+ : QIODevice(parent), d(new QQmlDebugConnectionPrivate(this)),
+ m_dataStreamVersion(QDataStream::Qt_5_0)
{
}
}
}
+void QQmlDebugConnection::setDataStreamVersion(int dataStreamVersion)
+{
+ m_dataStreamVersion = dataStreamVersion;
+}
+
+int QQmlDebugConnection::dataStreamVersion()
+{
+ return m_dataStreamVersion;
+}
+
bool QQmlDebugConnection::isConnected() const
{
return state() == QAbstractSocket::ConnectedState;
void connectToHost(const QString &hostName, quint16 port);
+ void setDataStreamVersion(int dataStreamVersion);
+ int dataStreamVersion();
+
qint64 bytesAvailable() const;
bool isConnected() const;
QAbstractSocket::SocketState state() const;
private:
QQmlDebugConnectionPrivate *d;
+ int m_dataStreamVersion;
friend class QQmlDebugClient;
friend class QQmlDebugClientPrivate;
+ friend class QQmlDebugConnectionPrivate;
};
class QQmlDebugClientPrivate;