7#include <private/qhooks_p.h>
8#include <private/qversionedpacket_p.h>
10#include <QtQml/qjsengine.h>
11#include <QtCore/qdebug.h>
12#include <QtCore/qjsonarray.h>
13#include <QtCore/qjsondocument.h>
14#include <QtCore/qjsonobject.h>
15#include <QtCore/qjsonvalue.h>
16#include <QtCore/qpointer.h>
17#include <QtCore/qvector.h>
20#define TRACE_PROTOCOL(s)
28# define QML_DEBUG_EXPORT Q_DECL_EXPORT
30# define QML_DEBUG_EXPORT
46 QQmlNativeDebugConnector::setDataStreamVersion(version);
64 responseBuffer->clear();
72 QByteArray msg = QByteArray::fromHex(hexData);
74 QQmlDebugConnector *instance = QQmlDebugConnector::instance();
78 QQmlDebugService *recipient = instance->service(serviceName);
82 TRACE_PROTOCOL(
"Recipient: " << recipient <<
" got message: " << msg);
84 recipient->messageReceived(msg);
93 QQmlDebugConnector *instance = QQmlDebugConnector::instance();
97 QString name = QString::fromLatin1(data);
98 QQmlDebugService *service = instance->service(name);
99 if (!service || service->state() == QQmlDebugService::Enabled)
102 service->stateAboutToBeChanged(QQmlDebugService::Enabled);
103 service->setState(QQmlDebugService::Enabled);
104 service->stateChanged(QQmlDebugService::Enabled);
110 QQmlDebugConnector *instance = QQmlDebugConnector::instance();
114 QString name = QString::fromLatin1(data);
115 QQmlDebugService *service = instance->service(name);
116 if (!service || service->state() == QQmlDebugService::Unavailable)
119 service->stateAboutToBeChanged(QQmlDebugService::Unavailable);
120 service->setState(QQmlDebugService::Unavailable);
121 service->stateChanged(QQmlDebugService::Unavailable);
144 qtHookData[QHooks::Startup] = quintptr(&qt_qmlDebugTestHooks);
156QQmlNativeDebugConnector::QQmlNativeDebugConnector()
157 : m_blockingMode(
false)
159 const QString args = commandLineArguments();
160 const auto lstjsDebugArguments = QStringView{args}.split(QLatin1Char(
','), Qt::SkipEmptyParts);
161 QStringList services;
162 for (
const QStringView &strArgument : lstjsDebugArguments) {
163 if (strArgument == QLatin1String(
"block")) {
164 m_blockingMode =
true;
165 }
else if (strArgument == QLatin1String(
"native")) {
168 }
else if (strArgument.startsWith(QLatin1String(
"services:"))) {
169 services.append(strArgument.mid(9).toString());
170 }
else if (!services.isEmpty()) {
171 services.append(strArgument.toString());
172 }
else if (!strArgument.startsWith(QLatin1String(
"connector:"))) {
173 qWarning(
"QML Debugger: Invalid argument \"%s\" detected. Ignoring the same.",
174 strArgument.toUtf8().constData());
177 setServices(services);
180QQmlNativeDebugConnector::~QQmlNativeDebugConnector()
182 for (QQmlDebugService *service : std::as_const(m_services)) {
183 service->stateAboutToBeChanged(QQmlDebugService::NotConnected);
184 service->setState(QQmlDebugService::NotConnected);
185 service->stateChanged(QQmlDebugService::NotConnected);
189bool QQmlNativeDebugConnector::blockingMode()
const
191 return m_blockingMode;
194QQmlDebugService *QQmlNativeDebugConnector::service(
const QString &name)
const
196 for (QVector<QQmlDebugService *>::ConstIterator i = m_services.begin(); i != m_services.end();
198 if ((*i)->name() == name)
204void QQmlNativeDebugConnector::addEngine(QJSEngine *engine)
206 Q_ASSERT(!m_engines.contains(engine));
209 for (QQmlDebugService *service : std::as_const(m_services))
210 service->engineAboutToBeAdded(engine);
212 announceObjectAvailability(QLatin1String(
"qmlengine"), engine,
true);
214 for (QQmlDebugService *service : std::as_const(m_services))
215 service->engineAdded(engine);
217 m_engines.append(engine);
220void QQmlNativeDebugConnector::removeEngine(QJSEngine *engine)
222 Q_ASSERT(m_engines.contains(engine));
225 for (QQmlDebugService *service : std::as_const(m_services))
226 service->engineAboutToBeRemoved(engine);
228 announceObjectAvailability(QLatin1String(
"qmlengine"), engine,
false);
230 for (QQmlDebugService *service : std::as_const(m_services))
231 service->engineRemoved(engine);
233 m_engines.removeOne(engine);
236bool QQmlNativeDebugConnector::hasEngine(QJSEngine *engine)
const
238 return m_engines.contains(engine);
241void QQmlNativeDebugConnector::announceObjectAvailability(
const QString &objectType,
242 QObject *object,
bool available)
245 ob.insert(QLatin1String(
"objecttype"), objectType);
246 ob.insert(QLatin1String(
"object"), QString::number(quintptr(object)));
247 ob.insert(QLatin1String(
"available"), available);
251 QByteArray ba = doc.toJson(QJsonDocument::Compact);
260bool QQmlNativeDebugConnector::addService(
const QString &name, QQmlDebugService *service)
262 TRACE_PROTOCOL(
"Add service to connector: " << qPrintable(name) << service);
263 for (
auto it = m_services.cbegin(), end = m_services.cend(); it != end; ++it) {
264 if ((*it)->name() == name)
268 connect(service, &QQmlDebugService::messageToClient,
269 this, &QQmlNativeDebugConnector::sendMessage);
270 connect(service, &QQmlDebugService::messagesToClient,
271 this, &QQmlNativeDebugConnector::sendMessages);
273 service->setState(QQmlDebugService::Unavailable);
275 m_services << service;
279bool QQmlNativeDebugConnector::removeService(
const QString &name)
281 for (QVector<QQmlDebugService *>::Iterator i = m_services.begin(); i != m_services.end(); ++i) {
282 if ((*i)->name() == name) {
283 QQmlDebugService *service = *i;
285 service->setState(QQmlDebugService::NotConnected);
287 disconnect(service, &QQmlDebugService::messagesToClient,
288 this, &QQmlNativeDebugConnector::sendMessages);
289 disconnect(service, &QQmlDebugService::messageToClient,
290 this, &QQmlNativeDebugConnector::sendMessage);
298bool QQmlNativeDebugConnector::open(
const QVariantHash &configuration)
300 m_blockingMode = configuration.value(QStringLiteral(
"block"), m_blockingMode).toBool();
306void QQmlNativeDebugConnector::setDataStreamVersion(
int version)
308 Q_ASSERT(version <= QDataStream::Qt_DefaultCompiledVersion);
309 s_dataStreamVersion = version;
312void QQmlNativeDebugConnector::sendMessage(
const QString &name,
const QByteArray &message)
314 (*responseBuffer) += name.toUtf8() +
' ' + QByteArray::number(message.size()) +
' ' + message;
315 qt_qmlDebugMessageBuffer = responseBuffer->constData();
316 qt_qmlDebugMessageLength = responseBuffer->size();
331void QQmlNativeDebugConnector::sendMessages(
const QString &name,
const QList<QByteArray> &messages)
333 for (
int i = 0; i != messages.size(); ++i)
334 sendMessage(name, messages.at(i));
339 return key == QLatin1String(
"QQmlNativeDebugConnector") ?
new QQmlNativeDebugConnector :
nullptr;
344#include "moc_qqmlnativedebugconnector.cpp"
Q_GLOBAL_STATIC(QReadWriteLock, g_updateMutex)
quintptr qt_qmlDebugTestHooks[]
QML_DEBUG_EXPORT const char * qt_qmlDebugMessageBuffer
QML_DEBUG_EXPORT void qt_qmlDebugClearBuffer()
QML_DEBUG_EXPORT void qt_qmlDebugSetStreamVersion(int version)
QML_DEBUG_EXPORT int qt_qmlDebugMessageLength
QML_DEBUG_EXPORT void qt_qmlDebugConnectorOpen()
QML_DEBUG_EXPORT bool qt_qmlDebugSendDataToService(const char *serviceName, const char *hexData)
QML_DEBUG_EXPORT void qt_qmlDebugObjectAvailable()
QML_DEBUG_EXPORT void qt_qmlDebugMessageAvailable()
QML_DEBUG_EXPORT bool qt_qmlDebugDisableService(const char *data)
static QT_USE_NAMESPACE bool expectSyncronousResponse
QML_DEBUG_EXPORT bool qt_qmlDebugEnableService(const char *data)
QML_DEBUG_EXPORT bool qt_qmlDebugConnectionBlocker
#define TRACE_PROTOCOL(x)