SIM Application Toolkit: fix potential race condition
[meego-ux:meego-app-satk.git] / stkagentservice.cpp
1 /*
2  * satk - SIM application toolkit
3  * Copyright © 2011, Intel Corporation.
4  *
5  * This program is licensed under the terms and conditions of the
6  * Apache License, version 2.0.  The full text of the Apache License is at
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Written by - Luc Yriarte <luc.yriarte@linux.intel.com>
10  */
11
12
13 #include "stkagentservice.h"
14
15 /* Qt includes */
16 #include <QtDebug>
17 #include <QtGui/QApplication>
18 #include <QIcon>
19
20 /* oFono SIM Toolkit utilities*/
21 #include "stkofonoutils.h"
22
23 /* SIM Toolkit widgets */
24 #include "stkmenumodel.h"
25
26 /* Fallback return values */
27 #define FALLBACK_BOOL       false
28 #define FALLBACK_UCHAR      255
29 #define FALLBACK_QSTRING    ""
30
31
32 StkAgentService::StkAgentService(SimIf * simIf, QObject *parent) :
33     QObject(parent)
34 {
35     mSimIf = simIf;
36     mExitOnRelease = false;
37 }
38
39
40 void StkAgentService::Cancel()
41 {
42     // handle method call org.ofono.SimToolkitAgent.Cancel
43 qDebug() << "Cancel" ;
44     closeLastWidget();
45 }
46
47
48 bool StkAgentService::ConfirmCallSetup(const QString &info, uchar icon)
49 {
50     // handle method call org.ofono.SimToolkitAgent.ConfirmCallSetup
51     bool out0 = FALLBACK_BOOL;
52 qDebug() << "ConfirmCallSetup: " << info << "(" << icon << ")";
53     closeLastWidget();
54     StkDialog * dlg = addNewWidget(info, icon,"qrc:/StkYesNo.qml");
55     dlg->setShowBackButton(false);
56     dlg->initView();
57     if (dlg->exec() != QDialog::Accepted)
58         return out0;
59     AgentResponse ret = dlg->getAgentResponse();
60     switch (ret) {
61     case Yes:
62         out0 = true;
63         break;
64     case No:
65         out0 = false;
66         break;
67     case End:
68         connection().send(message().createErrorReply(STK_ERR_END,""));
69         break;
70     default:
71         Q_ASSERT(false);
72     }
73     return out0;
74 }
75
76
77 bool StkAgentService::ConfirmLaunchBrowser(const QString &info, uchar icon, const QString &url)
78 {
79     // handle method call org.ofono.SimToolkitAgent.ConfirmLaunchBrowser
80     bool out0 = FALLBACK_BOOL;
81 qDebug() << "ConfirmLaunchBrowser: " << info << "(" << icon << ")" << " -- url: " << url;
82     closeLastWidget();
83     StkDialog * web = addNewWidget(url, icon,"qrc:/StkWebView.qml");
84     StkDialog * dlg = addNewWidget(info, icon,"qrc:/StkYesNo.qml");
85     dlg->setShowBackButton(false);
86     dlg->setShowEndButton(false);
87     dlg->initView();
88     if (dlg->exec() != QDialog::Accepted)
89         return out0;
90     AgentResponse ret = dlg->getAgentResponse();
91     switch (ret) {
92     case Yes:
93         web->setUrl(url);
94         web->initView();
95         web->exec();
96         out0 = true;
97         break;
98     case No:
99         closeLastWidget(); // StkYesNo
100         closeLastWidget(); // StkWebView
101         out0 = false;
102         break;
103     default:
104         Q_ASSERT(false);
105     }
106     return out0;
107 }
108
109
110 bool StkAgentService::ConfirmOpenChannel(const QString &info, uchar icon)
111 {
112     // handle method call org.ofono.SimToolkitAgent.ConfirmOpenChannel
113     bool out0 = FALLBACK_BOOL;
114 qDebug() << "ConfirmOpenChannel: " << info << "(" << icon << ")";
115     closeLastWidget();
116     StkDialog * dlg = addNewWidget(info, icon,"qrc:/StkYesNo.qml");
117     dlg->setShowBackButton(false);
118     dlg->initView();
119     if (dlg->exec() != QDialog::Accepted)
120         return out0;
121     AgentResponse ret = dlg->getAgentResponse();
122     switch (ret) {
123     case Yes:
124         out0 = true;
125         break;
126     case No:
127         out0 = false;
128         break;
129     case End:
130         connection().send(message().createErrorReply(STK_ERR_END,""));
131         break;
132     default:
133         Q_ASSERT(false);
134     }
135     return out0;
136 }
137
138
139 void StkAgentService::DisplayAction(const QString &text, uchar icon)
140 {
141     // handle method call org.ofono.SimToolkitAgent.DisplayAction
142 qDebug() << "DisplayAction: " << text << "(" << icon << ")";
143     closeLastWidget();
144     StkDialog * dlg = addNewWidget(text, icon,"qrc:/StkMessage.qml");
145     dlg->initView();
146     if (dlg->exec() != QDialog::Accepted)
147         return;
148     AgentResponse ret = dlg->getAgentResponse();
149     switch (ret) {
150     case End:
151         connection().send(message().createErrorReply(STK_ERR_END,""));
152         break;
153     default:
154         Q_ASSERT(false);
155     }
156 }
157
158
159 void StkAgentService::DisplayActionInformation(const QString &text, uchar icon)
160 {
161     // handle method call org.ofono.SimToolkitAgent.DisplayActionInformation
162 qDebug() << "DisplayActionInformation: " << text << "(" << icon << ")";
163     closeLastWidget();
164     StkDialog * dlg = addNewWidget(text, icon,"qrc:/StkMessage.qml");
165     dlg->setShowEndButton(false);
166     dlg->initView();
167     dlg->exec();
168 }
169
170
171 void StkAgentService::DisplayText(const QString &title, uchar icon, bool urgent)
172 {
173     // handle method call org.ofono.SimToolkitAgent.DisplayText
174 qDebug() << "DisplayText: " << title << "(" << icon << ")" << " urgent: " << urgent;
175     closeLastWidget();
176     StkDialog * dlg = addNewWidget(title, icon,"qrc:/StkPopup.qml");
177     dlg->initView();
178     if (dlg->exec() != QDialog::Accepted)
179         return;
180     AgentResponse ret = dlg->getAgentResponse();
181     switch (ret) {
182     case Ok:
183         break;
184     case Back:
185         connection().send(message().createErrorReply(STK_ERR_BACK,""));
186         break;
187     case End:
188         connection().send(message().createErrorReply(STK_ERR_END,""));
189         break;
190     default:
191         Q_ASSERT(false);
192     }
193 }
194
195
196 void StkAgentService::LoopTone(const QString &tone, const QString &text, uchar icon)
197 {
198     // handle method call org.ofono.SimToolkitAgent.LoopTone
199 qDebug() << "LoopTone: " << tone << " : " << text << "(" << icon << ")";
200     closeLastWidget();
201     StkDialog *dlg = addNewWidget(text + "(playing: " + tone + ")",
202                                   icon, "qrc:/StkPlaySound.qml");
203     dlg->setLoopTone(true);
204     dlg->setToneSource(tone);
205     dlg->initView();
206     dlg->show();
207 }
208
209
210 void StkAgentService::PlayTone(const QString &tone, const QString &text, uchar icon)
211 {
212     // handle method call org.ofono.SimToolkitAgent.PlayTone
213 qDebug() << "PlayTone: " << tone << " : " << text << "(" << icon << ")";
214     closeLastWidget();
215     StkDialog * dlg = addNewWidget(text + "(playing: " + tone + ")",
216                                    icon, "qrc:/StkPlaySound.qml");
217     dlg->setToneSource(tone);
218     dlg->initView();
219     if (dlg->exec() != QDialog::Accepted)
220         return;
221     AgentResponse ret = dlg->getAgentResponse();
222     switch (ret) {
223     case Ok:
224         break;
225     case End:
226         connection().send(message().createErrorReply(STK_ERR_END,""));
227         break;
228     default:
229         Q_ASSERT(false);
230     }
231 }
232
233
234 void StkAgentService::Release()
235 {
236     // handle method call org.ofono.SimToolkitAgent.Release
237 qDebug() << "Release" ;
238     while (closeLastWidget()) {}
239     if (mExitOnRelease)
240         QApplication::instance()->exit();
241 }
242
243
244 bool StkAgentService::RequestConfirmation(const QString &title, uchar icon)
245 {
246     // handle method call org.ofono.SimToolkitAgent.RequestConfirmation
247     bool out0 = FALLBACK_BOOL;
248 qDebug() << "RequestConfirmation: " << title << "(" << icon << ")";
249     closeLastWidget();
250     StkDialog * dlg = addNewWidget(title, icon,"qrc:/StkYesNo.qml");
251     dlg->initView();
252     if (dlg->exec() != QDialog::Accepted)
253         return out0;
254     AgentResponse ret = dlg->getAgentResponse();
255     switch (ret) {
256     case Yes:
257         out0 = true;
258         break;
259     case No:
260         out0 = false;
261         break;
262     case Back:
263         connection().send(message().createErrorReply(STK_ERR_BACK,""));
264         break;
265     case End:
266         connection().send(message().createErrorReply(STK_ERR_END,""));
267         break;
268     default:
269         Q_ASSERT(false);
270     }
271     return out0;
272 }
273
274
275 QString StkAgentService::RequestDigit(const QString &title, uchar icon)
276 {
277     // handle method call org.ofono.SimToolkitAgent.RequestDigit
278     QString out0 = FALLBACK_QSTRING;
279 qDebug() << "RequestDigit: " << title << "(" << icon << ")";
280     closeLastWidget();
281     StkDialog * dlg = addNewWidget(title, icon,"qrc:/StkInputKey.qml");
282     dlg->setNumeric(true);
283     dlg->initView();
284     if (dlg->exec() != QDialog::Accepted)
285         return out0;
286     AgentResponse ret = dlg->getAgentResponse();
287     switch (ret) {
288     case Ok:
289         out0 = dlg->getResponseData().toString();
290         break;
291     case Back:
292         connection().send(message().createErrorReply(STK_ERR_BACK,""));
293         break;
294     case End:
295         connection().send(message().createErrorReply(STK_ERR_END,""));
296         break;
297     default:
298         Q_ASSERT(false);
299     }
300     return out0;
301 }
302
303
304 QString StkAgentService::RequestDigits(const QString &title, uchar icon,
305                                        const QString &defaultValue,
306                                        uchar minChars, uchar maxChars, bool hideTyping)
307 {
308     // handle method call org.ofono.SimToolkitAgent.RequestDigits
309     QString out0 = defaultValue;
310 qDebug() << "RequestDigits: " << title << "(" << icon << ")" << " (" << defaultValue
311          << ") [" << minChars << ".." << maxChars << "] passwd:" << hideTyping;
312     closeLastWidget();
313     StkDialog * dlg = addNewWidget(title, icon,
314                                    hideTyping ? "qrc:/StkPassword.qml" : "qrc:/StkInputText.qml");
315     dlg->setDefaultText(defaultValue);
316     dlg->setCharBounds((int)minChars,(int)maxChars);
317     dlg->setHideTyping(hideTyping);
318     dlg->setNumeric(true);
319     dlg->initView();
320     if (dlg->exec() != QDialog::Accepted)
321         return out0;
322     AgentResponse ret = dlg->getAgentResponse();
323     switch (ret) {
324     case Ok:
325         out0 = dlg->getResponseData().toString();
326         break;
327     case Back:
328         connection().send(message().createErrorReply(STK_ERR_BACK,""));
329         break;
330     case End:
331         connection().send(message().createErrorReply(STK_ERR_END,""));
332         break;
333     default:
334         Q_ASSERT(false);
335     }
336     return out0;
337 }
338
339
340 QString StkAgentService::RequestInput(const QString &title, uchar icon,
341                                       const QString &defaultValue,
342                                       uchar minChars, uchar maxChars, bool hideTyping)
343 {
344     // handle method call org.ofono.SimToolkitAgent.RequestInput
345     QString out0 = defaultValue;
346 qDebug() << "RequestInput: " << title << "(" << icon << ")" << " (" << defaultValue
347          << ") [" << minChars << ".." << maxChars << "] passwd:" << hideTyping;
348     closeLastWidget();
349     StkDialog * dlg = addNewWidget(title, icon,
350                                    hideTyping ? "qrc:/StkPassword.qml" : "qrc:/StkInputText.qml");
351     dlg->setDefaultText(defaultValue);
352     dlg->setCharBounds((int)minChars,(int)maxChars);
353     dlg->setHideTyping(hideTyping);
354     dlg->setNumeric(false);
355     dlg->initView();
356     if (dlg->exec() != QDialog::Accepted)
357         return out0;
358     AgentResponse ret = dlg->getAgentResponse();
359     switch (ret) {
360     case Ok:
361         out0 = dlg->getResponseData().toString();
362         break;
363     case Back:
364         connection().send(message().createErrorReply(STK_ERR_BACK,""));
365         break;
366     case End:
367         connection().send(message().createErrorReply(STK_ERR_END,""));
368         break;
369     default:
370         Q_ASSERT(false);
371     }
372     return out0;
373 }
374
375
376 QString StkAgentService::RequestKey(const QString &title, uchar icon)
377 {
378     // handle method call org.ofono.SimToolkitAgent.RequestKey
379     QString out0 = FALLBACK_QSTRING;
380 qDebug() << "RequestKey: " << title << "(" << icon << ")";
381     closeLastWidget();
382     StkDialog * dlg = addNewWidget(title, icon,"qrc:/StkInputKey.qml");
383     dlg->setNumeric(false);
384     dlg->initView();
385     if (dlg->exec() != QDialog::Accepted)
386         return out0;
387     AgentResponse ret = dlg->getAgentResponse();
388     switch (ret) {
389     case Ok:
390         out0 = dlg->getResponseData().toString();
391         break;
392     case Back:
393         connection().send(message().createErrorReply(STK_ERR_BACK,""));
394         break;
395     case End:
396         connection().send(message().createErrorReply(STK_ERR_END,""));
397         break;
398     default:
399         Q_ASSERT(false);
400     }
401     return out0;
402 }
403
404
405 uchar StkAgentService::RequestSelection(const QString &title, uchar icon, OfonoMenuList items,
406                                         short defaultValue)
407 {
408     // handle method call org.ofono.SimToolkitAgent.RequestSelection
409     uchar out0 = FALLBACK_UCHAR;
410 qDebug() << "RequestSelection: " << title << "(" << icon << ")" << " default: " << defaultValue;
411     closeLastWidget();
412      QList<StkMenuItem> dlgitems;
413     foreach (const OfonoMenuEntry entry, items)
414         dlgitems.append(StkMenuItem(StkOfonoUtils::findIconUrl(entry.icon), entry.label));
415     StkDialog * dlg = addNewWidget(title, icon,"qrc:/StkMenu.qml");
416     dlg->setMenuItems(dlgitems);
417     dlg->setSelection(int(defaultValue));
418     dlg->initView();
419     if (dlg->exec() != QDialog::Accepted)
420         return out0;
421     AgentResponse ret = dlg->getAgentResponse();
422     switch (ret) {
423     case Ok:
424         out0 = (uchar)dlg->getResponseData().toInt();
425        break;
426     case Back:
427         connection().send(message().createErrorReply(STK_ERR_BACK,""));
428         break;
429     case End:
430         connection().send(message().createErrorReply(STK_ERR_END,""));
431         break;
432     default:
433         Q_ASSERT(false);
434     }
435     return out0;
436 }
437
438
439 /* private functions */
440
441
442 StkDialog * StkAgentService::addNewWidget(const QString &info, uchar icon,
443                                           const QString &qmlViewUrl)
444 {
445     StkDialog * dlg = new StkDialog(new SimImageProvider(mSimIf),
446                                     StkOfonoUtils::findIconUrl(icon), info, qmlViewUrl);
447     mWidgetStack.append(dlg);
448     return dlg;
449 }
450
451
452 bool StkAgentService::closeLastWidget()
453 {
454     if (!mWidgetStack.isEmpty()) {
455         QWidget * widget = mWidgetStack.takeLast();
456         widget->close();
457         delete widget;
458     }
459     return !mWidgetStack.isEmpty();
460 }