Initial import from the monolithic Qt.
[profile/ivi/qtdeclarative.git] / src / declarative / debugger / qdeclarativedebugclient.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "private/qdeclarativedebugclient_p.h"
43
44 #include "private/qpacketprotocol_p.h"
45
46 #include <QtCore/qdebug.h>
47 #include <QtCore/qstringlist.h>
48
49 #include <private/qobject_p.h>
50
51 QT_BEGIN_NAMESPACE
52
53 const int protocolVersion = 1;
54 const QString serverId = QLatin1String("QDeclarativeDebugServer");
55 const QString clientId = QLatin1String("QDeclarativeDebugClient");
56
57 class QDeclarativeDebugClientPrivate : public QObjectPrivate
58 {
59     Q_DECLARE_PUBLIC(QDeclarativeDebugClient)
60 public:
61     QDeclarativeDebugClientPrivate();
62
63     QString name;
64     QDeclarativeDebugConnection *connection;
65 };
66
67 class QDeclarativeDebugConnectionPrivate : public QObject
68 {
69     Q_OBJECT
70 public:
71     QDeclarativeDebugConnectionPrivate(QDeclarativeDebugConnection *c);
72     QDeclarativeDebugConnection *q;
73     QPacketProtocol *protocol;
74
75     bool gotHello;
76     QStringList serverPlugins;
77     QHash<QString, QDeclarativeDebugClient *> plugins;
78
79     void advertisePlugins();
80
81 public Q_SLOTS:
82     void connected();
83     void readyRead();
84 };
85
86 QDeclarativeDebugConnectionPrivate::QDeclarativeDebugConnectionPrivate(QDeclarativeDebugConnection *c)
87 : QObject(c), q(c), protocol(0), gotHello(false)
88 {
89     protocol = new QPacketProtocol(q, this);
90     QObject::connect(c, SIGNAL(connected()), this, SLOT(connected()));
91     QObject::connect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead()));
92 }
93
94 void QDeclarativeDebugConnectionPrivate::advertisePlugins()
95 {
96     if (!q->isConnected())
97         return;
98
99     QPacket pack;
100     pack << serverId << 1 << plugins.keys();
101     protocol->send(pack);
102     q->flush();
103 }
104
105 void QDeclarativeDebugConnectionPrivate::connected()
106 {
107     QPacket pack;
108     pack << serverId << 0 << protocolVersion << plugins.keys();
109     protocol->send(pack);
110     q->flush();
111 }
112
113 void QDeclarativeDebugConnectionPrivate::readyRead()
114 {
115     if (!gotHello) {
116         QPacket pack = protocol->read();
117         QString name;
118
119         pack >> name;
120
121         bool validHello = false;
122         if (name == clientId) {
123             int op = -1;
124             pack >> op;
125             if (op == 0) {
126                 int version = -1;
127                 pack >> version;
128                 if (version == protocolVersion) {
129                     pack >> serverPlugins;
130                     validHello = true;
131                 }
132             }
133         }
134
135         if (!validHello) {
136             qWarning("QDeclarativeDebugConnection: Invalid hello message");
137             QObject::disconnect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead()));
138             return;
139         }
140
141         gotHello = true;
142
143         QHash<QString, QDeclarativeDebugClient *>::Iterator iter = plugins.begin();
144         for (; iter != plugins.end(); ++iter) {
145             QDeclarativeDebugClient::Status newStatus = QDeclarativeDebugClient::Unavailable;
146             if (serverPlugins.contains(iter.key()))
147                 newStatus = QDeclarativeDebugClient::Enabled;
148             iter.value()->statusChanged(newStatus);
149         }
150     }
151
152     while (protocol->packetsAvailable()) {
153         QPacket pack = protocol->read();
154         QString name;
155         pack >> name;
156
157         if (name == clientId) {
158             int op = -1;
159             pack >> op;
160
161             if (op == 1) {
162                 // Service Discovery
163                 QStringList oldServerPlugins = serverPlugins;
164                 pack >> serverPlugins;
165
166                 QHash<QString, QDeclarativeDebugClient *>::Iterator iter = plugins.begin();
167                 for (; iter != plugins.end(); ++iter) {
168                     const QString pluginName = iter.key();
169                     QDeclarativeDebugClient::Status newStatus = QDeclarativeDebugClient::Unavailable;
170                     if (serverPlugins.contains(pluginName))
171                         newStatus = QDeclarativeDebugClient::Enabled;
172
173                     if (oldServerPlugins.contains(pluginName)
174                             != serverPlugins.contains(pluginName)) {
175                         iter.value()->statusChanged(newStatus);
176                     }
177                 }
178             } else {
179                 qWarning() << "QDeclarativeDebugConnection: Unknown control message id" << op;
180             }
181         } else {
182             QByteArray message;
183             pack >> message;
184
185             QHash<QString, QDeclarativeDebugClient *>::Iterator iter =
186                 plugins.find(name);
187             if (iter == plugins.end()) {
188                 qWarning() << "QDeclarativeDebugConnection: Message received for missing plugin" << name;
189             } else {
190                 (*iter)->messageReceived(message);
191             }
192         }
193     }
194 }
195
196 QDeclarativeDebugConnection::QDeclarativeDebugConnection(QObject *parent)
197 : QTcpSocket(parent), d(new QDeclarativeDebugConnectionPrivate(this))
198 {
199 }
200
201 QDeclarativeDebugConnection::~QDeclarativeDebugConnection()
202 {
203     QHash<QString, QDeclarativeDebugClient*>::iterator iter = d->plugins.begin();
204     for (; iter != d->plugins.end(); ++iter) {
205          iter.value()->d_func()->connection = 0;
206          iter.value()->statusChanged(QDeclarativeDebugClient::NotConnected);
207     }
208 }
209
210 bool QDeclarativeDebugConnection::isConnected() const
211 {
212     return state() == ConnectedState;
213 }
214
215 QDeclarativeDebugClientPrivate::QDeclarativeDebugClientPrivate()
216 : connection(0)
217 {
218 }
219
220 QDeclarativeDebugClient::QDeclarativeDebugClient(const QString &name, 
221                                            QDeclarativeDebugConnection *parent)
222 : QObject(*(new QDeclarativeDebugClientPrivate), parent)
223 {
224     Q_D(QDeclarativeDebugClient);
225     d->name = name;
226     d->connection = parent;
227
228     if (!d->connection)
229         return;
230
231     if (d->connection->d->plugins.contains(name)) {
232         qWarning() << "QDeclarativeDebugClient: Conflicting plugin name" << name;
233         d->connection = 0;
234     } else {
235         d->connection->d->plugins.insert(name, this);
236         d->connection->d->advertisePlugins();
237     }
238 }
239
240 QDeclarativeDebugClient::~QDeclarativeDebugClient()
241 {
242     Q_D(const QDeclarativeDebugClient);
243     if (d->connection && d->connection->d) {
244         d->connection->d->plugins.remove(d->name);
245         d->connection->d->advertisePlugins();
246     }
247 }
248
249 QString QDeclarativeDebugClient::name() const
250 {
251     Q_D(const QDeclarativeDebugClient);
252     return d->name;
253 }
254
255 QDeclarativeDebugClient::Status QDeclarativeDebugClient::status() const
256 {
257     Q_D(const QDeclarativeDebugClient);
258     if (!d->connection
259             || !d->connection->isConnected()
260             || !d->connection->d->gotHello)
261         return NotConnected;
262
263     if (d->connection->d->serverPlugins.contains(d->name))
264         return Enabled;
265
266     return Unavailable;
267 }
268
269 void QDeclarativeDebugClient::sendMessage(const QByteArray &message)
270 {
271     Q_D(QDeclarativeDebugClient);
272
273     if (status() != Enabled)
274         return;
275
276     QPacket pack;
277     pack << d->name << message;
278     d->connection->d->protocol->send(pack);
279     d->connection->d->q->flush();
280 }
281
282 void QDeclarativeDebugClient::statusChanged(Status)
283 {
284 }
285
286 void QDeclarativeDebugClient::messageReceived(const QByteArray &)
287 {
288 }
289
290 QT_END_NAMESPACE
291
292 #include <qdeclarativedebugclient.moc>