1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qqmldebugpluginmanager_p.h"
5#include "qqmldebugconnector_p.h"
6#include "qqmldebugservicefactory_p.h"
7#include <QtCore/QPluginLoader>
8#include <QtCore/QCborArray>
9#include <QtCore/QCoreApplication>
10#include <QtCore/QDir>
11#include <QtCore/QDebug>
12#include <QtCore/QDataStream>
13
14#include <private/qcoreapplication_p.h>
15#include <private/qqmlengine_p.h>
16
17QT_BEGIN_NAMESPACE
18
19// Connectors. We could add more plugins here, and distinguish by arguments to instance()
20Q_QML_DEBUG_PLUGIN_LOADER(QQmlDebugConnector)
21
22// Services
23Q_QML_DEBUG_PLUGIN_LOADER(QQmlDebugService)
24
25int QQmlDebugConnector::s_dataStreamVersion = QDataStream::Qt_4_7;
26
27struct QQmlDebugConnectorParams {
28 QString pluginKey;
29 QStringList services;
30 QString arguments;
31 QQmlDebugConnector *instance;
32
33 QQmlDebugConnectorParams() : instance(nullptr)
34 {
35 if (qApp) {
36 QCoreApplicationPrivate *appD =
37 static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(qApp));
38 if (appD)
39 arguments = appD->qmljsDebugArgumentsString();
40 }
41 }
42};
43
44Q_GLOBAL_STATIC(QQmlDebugConnectorParams, qmlDebugConnectorParams)
45
46void QQmlDebugConnector::setPluginKey(const QString &key)
47{
48 QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
49 if (params && params->pluginKey != key) {
50 if (params->instance)
51 qWarning() << "QML debugger: Cannot set plugin key after loading the plugin.";
52 else
53 params->pluginKey = key;
54 }
55}
56
57void QQmlDebugConnector::setServices(const QStringList &services)
58{
59 QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
60 if (params)
61 params->services = services;
62}
63
64QString QQmlDebugConnector::commandLineArguments()
65{
66 QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
67 if (!params)
68 return QString();
69 return params->arguments;
70}
71
72QQmlDebugConnector *QQmlDebugConnector::instance()
73{
74 QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
75 if (!params)
76 return nullptr;
77
78 if (!QQmlEnginePrivate::qml_debugging_enabled.load(m: std::memory_order_relaxed)) {
79 if (!params->arguments.isEmpty()) {
80 qWarning().noquote() << QString::fromLatin1(
81 ba: "QML Debugger: Ignoring \"-qmljsdebugger=%1\". Debugging "
82 "has not been enabled.").arg(a: params->arguments);
83 params->arguments.clear();
84 }
85 return nullptr;
86 }
87
88 if (!params->instance) {
89 if (!params->pluginKey.isEmpty()) {
90 params->instance = loadQQmlDebugConnector(key: params->pluginKey);
91 } else if (params->arguments.isEmpty()) {
92 return nullptr; // no explicit class name given and no command line arguments
93 } else if (params->arguments.startsWith(s: QLatin1String("connector:"))) {
94 static const int connectorBegin = int(strlen(s: "connector:"));
95
96 int connectorEnd = params->arguments.indexOf(c: QLatin1Char(','), from: connectorBegin);
97 if (connectorEnd == -1)
98 connectorEnd = params->arguments.size();
99
100 params->instance = loadQQmlDebugConnector(key: params->arguments.mid(
101 position: connectorBegin,
102 n: connectorEnd - connectorBegin));
103 } else {
104 params->instance = loadQQmlDebugConnector(
105 key: params->arguments.startsWith(s: QLatin1String("native")) ?
106 QStringLiteral("QQmlNativeDebugConnector") :
107 QStringLiteral("QQmlDebugServer"));
108 }
109
110 if (params->instance) {
111 const auto metaData = metaDataForQQmlDebugService();
112 for (const QPluginParsedMetaData &md : metaData) {
113 const auto keys = md.value(k: QtPluginMetaDataKeys::MetaData).toMap()
114 .value(key: QLatin1String("Keys")).toArray();
115 for (const QCborValue key : keys) {
116 QString keyString = key.toString();
117 if (params->services.isEmpty() || params->services.contains(str: keyString))
118 loadQQmlDebugService(key: keyString);
119 }
120 }
121 }
122 }
123
124 return params->instance;
125}
126
127QQmlDebugConnectorFactory::~QQmlDebugConnectorFactory()
128{
129 // This is triggered when the plugin is unloaded.
130 QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
131 if (params) {
132 params->pluginKey.clear();
133 params->arguments.clear();
134 params->services.clear();
135 delete params->instance;
136 params->instance = nullptr;
137 }
138}
139
140QT_END_NAMESPACE
141
142#include "moc_qqmldebugconnector_p.cpp"
143

source code of qtdeclarative/src/qml/debugger/qqmldebugconnector.cpp