1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2015 The Qt Company Ltd. |
4 | ** Contact: http://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the test suite of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL21$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see http://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at http://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 2.1 or version 3 as published by the Free |
20 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and |
21 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the |
22 | ** following information to ensure the GNU Lesser General Public License |
23 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and |
24 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
25 | ** |
26 | ** As a special exception, The Qt Company gives you certain additional |
27 | ** rights. These rights are described in The Qt Company LGPL Exception |
28 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
29 | ** |
30 | ** $QT_END_LICENSE$ |
31 | ** |
32 | ****************************************************************************/ |
33 | |
34 | #include "maliciousplugin_p.h" |
35 | |
36 | #include <QThread> |
37 | #include <QMutex> |
38 | #include <QSet> |
39 | #include <QDebug> |
40 | |
41 | #include <QtOrganizer/qorganizeritemrequests.h> |
42 | #include <QtOrganizer/qorganizermanager.h> |
43 | |
44 | #ifndef MALICIOUSPLUGINTARGET |
45 | #define MALICIOUSPLUGINTARGET organizer_maliciousplugin |
46 | #endif |
47 | |
48 | #ifndef MALICIOUSPLUGINNAME |
49 | #define MALICIOUSPLUGINNAME maliciousplugin |
50 | #endif |
51 | |
52 | #define makestr(x) (#x) |
53 | #define makename(x) makestr(x) |
54 | |
55 | QTORGANIZER_USE_NAMESPACE |
56 | |
57 | class MaliciousThreadObject : public QObject |
58 | { |
59 | Q_OBJECT |
60 | |
61 | public: |
62 | MaliciousThreadObject() {} |
63 | |
64 | public slots: |
65 | void activateRequest(QOrganizerAbstractRequest *req) |
66 | { |
67 | mutex.lock(); |
68 | if (activeRequests.contains(value: req)) |
69 | QOrganizerManagerEngine::updateRequestState(request: req, state: QOrganizerAbstractRequest::ActiveState); |
70 | mutex.unlock(); |
71 | } |
72 | |
73 | void finishRequest(QOrganizerAbstractRequest *req) |
74 | { |
75 | QOrganizerManager::Error errorResult = QOrganizerManager::NoError; |
76 | QMap<int, QOrganizerManager::Error> errorMap; |
77 | QList<QOrganizerItemId> idResult; |
78 | QList<QOrganizerItem> itemResult; |
79 | QList<QOrganizerCollection> collectionResult; |
80 | |
81 | mutex.lock(); |
82 | if (activeRequests.contains(value: req)) { |
83 | switch (req->type()) { |
84 | case QOrganizerAbstractRequest::ItemSaveRequest: |
85 | QOrganizerManagerEngine::updateItemSaveRequest(request: static_cast<QOrganizerItemSaveRequest *>(req), result: itemResult, error: errorResult, errorMap, newState: QOrganizerAbstractRequest::FinishedState); |
86 | break; |
87 | |
88 | case QOrganizerAbstractRequest::ItemFetchRequest: |
89 | QOrganizerManagerEngine::updateItemFetchRequest(request: static_cast<QOrganizerItemFetchRequest *>(req), result: itemResult, error: errorResult, newState: QOrganizerAbstractRequest::FinishedState); |
90 | break; |
91 | |
92 | case QOrganizerAbstractRequest::ItemIdFetchRequest: |
93 | QOrganizerManagerEngine::updateItemIdFetchRequest(request: static_cast<QOrganizerItemIdFetchRequest *>(req), result: idResult, error: errorResult, newState: QOrganizerAbstractRequest::FinishedState); |
94 | break; |
95 | |
96 | case QOrganizerAbstractRequest::ItemFetchByIdRequest: |
97 | QOrganizerManagerEngine::updateItemFetchByIdRequest(request: static_cast<QOrganizerItemFetchByIdRequest *>(req), result: itemResult, error: errorResult, errorMap, QOrganizerAbstractRequest::FinishedState); |
98 | break; |
99 | |
100 | case QOrganizerAbstractRequest::ItemFetchForExportRequest: |
101 | QOrganizerManagerEngine::updateItemFetchForExportRequest(request: static_cast<QOrganizerItemFetchForExportRequest *>(req), result: itemResult, error: errorResult, newState: QOrganizerAbstractRequest::FinishedState); |
102 | break; |
103 | |
104 | case QOrganizerAbstractRequest::ItemOccurrenceFetchRequest: |
105 | QOrganizerManagerEngine::updateItemOccurrenceFetchRequest(request: static_cast<QOrganizerItemOccurrenceFetchRequest *>(req), result: itemResult, error: errorResult, newState: QOrganizerAbstractRequest::FinishedState); |
106 | break; |
107 | |
108 | case QOrganizerAbstractRequest::ItemRemoveRequest: |
109 | QOrganizerManagerEngine::updateItemRemoveRequest(request: static_cast <QOrganizerItemRemoveRequest *>(req), error: errorResult, errorMap, newState: QOrganizerAbstractRequest::FinishedState); |
110 | break; |
111 | |
112 | case QOrganizerAbstractRequest::ItemRemoveByIdRequest: |
113 | QOrganizerManagerEngine::updateItemRemoveByIdRequest(request: static_cast <QOrganizerItemRemoveByIdRequest *>(req), error: errorResult, errorMap, newState: QOrganizerAbstractRequest::FinishedState); |
114 | break; |
115 | |
116 | case QOrganizerAbstractRequest::CollectionSaveRequest: |
117 | QOrganizerManagerEngine::updateCollectionSaveRequest(request: static_cast <QOrganizerCollectionSaveRequest *>(req), result: collectionResult, error: errorResult, errorMap, newState: QOrganizerAbstractRequest::FinishedState); |
118 | break; |
119 | |
120 | case QOrganizerAbstractRequest::CollectionFetchRequest: |
121 | QOrganizerManagerEngine::updateCollectionFetchRequest(request: static_cast<QOrganizerCollectionFetchRequest *>(req), result: collectionResult, error: errorResult, newState: QOrganizerAbstractRequest::FinishedState); |
122 | break; |
123 | |
124 | case QOrganizerAbstractRequest::CollectionRemoveRequest: |
125 | QOrganizerManagerEngine::updateCollectionRemoveRequest(request: static_cast<QOrganizerCollectionRemoveRequest *>(req), error: errorResult, errorMap, newState: QOrganizerAbstractRequest::FinishedState); |
126 | break; |
127 | |
128 | default: |
129 | break; |
130 | } |
131 | } |
132 | activeRequests.remove(value: req); |
133 | mutex.unlock(); |
134 | } |
135 | |
136 | public: |
137 | QMutex mutex; |
138 | QSet<QOrganizerAbstractRequest *> activeRequests; |
139 | }; |
140 | |
141 | |
142 | class MaliciousThread : public QThread |
143 | { |
144 | Q_OBJECT |
145 | |
146 | public: |
147 | MaliciousThread(); |
148 | ~MaliciousThread(); |
149 | |
150 | QObject *eventLoopQuitHack; |
151 | }; |
152 | |
153 | MaliciousThread::MaliciousThread() |
154 | { |
155 | eventLoopQuitHack = new QObject; |
156 | eventLoopQuitHack->moveToThread(thread: this); |
157 | connect(asender: eventLoopQuitHack, SIGNAL(destroyed(QObject*)), SLOT(quit()), atype: Qt::DirectConnection); |
158 | } |
159 | |
160 | MaliciousThread::~MaliciousThread() |
161 | { |
162 | eventLoopQuitHack->deleteLater(); |
163 | wait(); |
164 | } |
165 | |
166 | |
167 | MaliciousAsyncManagerEngine::MaliciousAsyncManagerEngine() |
168 | : QOrganizerManagerEngine() |
169 | { |
170 | thread = new MaliciousThread(); |
171 | threadObject = new MaliciousThreadObject(); |
172 | threadObject->moveToThread(thread); |
173 | |
174 | connect(sender: this, SIGNAL(doStartRequest(QOrganizerAbstractRequest*)), receiver: threadObject, SLOT(activateRequest(QOrganizerAbstractRequest*)), Qt::BlockingQueuedConnection); |
175 | connect(sender: this, SIGNAL(doFinishRequest(QOrganizerAbstractRequest*)), receiver: threadObject, SLOT(finishRequest(QOrganizerAbstractRequest*)), Qt::BlockingQueuedConnection); |
176 | |
177 | thread->start(); |
178 | } |
179 | |
180 | MaliciousAsyncManagerEngine::~MaliciousAsyncManagerEngine() |
181 | { |
182 | delete thread; |
183 | delete threadObject; |
184 | } |
185 | |
186 | QString MaliciousAsyncManagerEngine::managerName() const |
187 | { |
188 | return QString(makename(MALICIOUSPLUGINNAME)); |
189 | } |
190 | |
191 | bool MaliciousAsyncManagerEngine::startRequest(QOrganizerAbstractRequest *req) |
192 | { |
193 | threadObject->mutex.lock(); |
194 | threadObject->activeRequests.insert(value: req); |
195 | threadObject->mutex.unlock(); |
196 | |
197 | // Spawn a thread to do stuff on another thread |
198 | emit doStartRequest(req); |
199 | emit doFinishRequest(req); |
200 | |
201 | return true; |
202 | } |
203 | |
204 | bool MaliciousAsyncManagerEngine::cancelRequest(QOrganizerAbstractRequest *req) |
205 | { |
206 | updateRequestState(request: req, state: QOrganizerAbstractRequest::CanceledState); |
207 | QOrganizerManagerEngine::cancelRequest(request: req); |
208 | return true; |
209 | } |
210 | |
211 | void MaliciousAsyncManagerEngine::requestDestroyed(QOrganizerAbstractRequest *req) |
212 | { |
213 | threadObject->mutex.lock(); |
214 | threadObject->activeRequests.remove(value: req); |
215 | threadObject->mutex.unlock(); |
216 | QOrganizerManagerEngine::requestDestroyed(request: req); |
217 | } |
218 | |
219 | |
220 | QString MaliciousEngineFactory::managerName() const |
221 | { |
222 | return QString(makename(MALICIOUSPLUGINNAME)); |
223 | } |
224 | |
225 | QOrganizerManagerEngine *MaliciousEngineFactory::engine(const QMap<QString, QString> ¶meters, QOrganizerManager::Error *error) |
226 | { |
227 | Q_UNUSED(parameters); |
228 | *error = QOrganizerManager::NoError; |
229 | return new MaliciousAsyncManagerEngine(); |
230 | } |
231 | |
232 | #include "maliciousplugin.moc" |
233 | |