Add named referencies implementation
[accounts-sso:vitalyrepins-signon.git] / lib / SignOn / identityimpl.cpp
1 /*
2  * This file is part of signon
3  *
4  * Copyright (C) 2009-2010 Nokia Corporation.
5  *
6  * Contact: Aurel Popirtac <ext-aurel.popirtac@nokia.com>
7  * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * version 2.1 as published by the Free Software Foundation.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  */
23 #include <stdarg.h>
24
25 #include <QByteArray>
26 #include <QDBusArgument>
27 #include <QTimer>
28
29 #include <signond/signoncommon.h>
30
31 #include "libsignoncommon.h"
32 #include "identityimpl.h"
33 #include "identityinfo.h"
34 #include "identityinfoimpl.h"
35 #include "authsessionimpl.h"
36
37 #define SIGNOND_AUTH_SESSION_CANCEL_TIMEOUT 5000 //ms
38
39 #define SIGNOND_IDENTITY_QUERY_AVAILABLE_METHODS_METHOD \
40     SIGNOND_NORMALIZE_METHOD_SIGNATURE("queryAvailableMethods()")
41 #define SIGNOND_IDENTITY_REQUEST_CREDENTIALS_UPDATE_METHOD \
42     SIGNOND_NORMALIZE_METHOD_SIGNATURE("requestCredentialsUpdate(const QString &)")
43 #define SIGNOND_IDENTITY_STORE_CREDENTIALS_METHOD \
44     SIGNOND_NORMALIZE_METHOD_SIGNATURE("storeCredentials(const IdentityInfo &)")
45 #define SIGNOND_IDENTITY_REMOVE_METHOD \
46     SIGNOND_NORMALIZE_METHOD_SIGNATURE("remove()")
47 #define SIGNOND_IDENTITY_QUERY_INFO_METHOD \
48     SIGNOND_NORMALIZE_METHOD_SIGNATURE("queryInfo()")
49 #define SIGNOND_IDENTITY_ADD_REFERENCE_METHOD \
50     SIGNOND_NORMALIZE_METHOD_SIGNATURE("addReference(const QString &)")
51 #define SIGNOND_IDENTITY_REMOVE_REFERENCE_METHOD \
52     SIGNOND_NORMALIZE_METHOD_SIGNATURE("removeReference(const QString &)")
53 #define SIGNOND_IDENTITY_VERIFY_USER_METHOD \
54     SIGNOND_NORMALIZE_METHOD_SIGNATURE("verifyUser(const QString &)")
55 #define SIGNOND_IDENTITY_VERIFY_SECRET_METHOD \
56     SIGNOND_NORMALIZE_METHOD_SIGNATURE("verifySecret(const QString &)")
57 #define SIGNOND_IDENTITY_SIGN_OUT_METHOD \
58     SIGNOND_NORMALIZE_METHOD_SIGNATURE("signOut()")
59
60
61 namespace SignOn {
62
63     IdentityImpl::IdentityImpl(Identity *parent, const quint32 id)
64         : QObject(parent),
65           m_parent(parent),
66           m_identityInfo(new IdentityInfo),
67           m_operationQueueHandler(this),
68           m_tmpIdentityInfo(NULL),
69           m_DBusInterface(NULL),
70           m_state(NeedsRegistration),
71           m_infoQueried(true),
72           m_signOutRequestedByThisIdentity(false)
73     {
74         m_identityInfo->setId(id);
75         sendRegisterRequest();
76     }
77
78     IdentityImpl::~IdentityImpl()
79     {
80         if (m_identityInfo)
81             delete m_identityInfo;
82
83         if (m_tmpIdentityInfo)
84             delete m_tmpIdentityInfo;
85
86         if (!m_authSessions.empty())
87             foreach (AuthSession *session, m_authSessions)
88                 destroySession(session);
89     }
90
91     void IdentityImpl::updateState(State state)
92     {
93         const char *stateStr;
94         switch (state)
95         {
96             case PendingRegistration: stateStr = "PendingRegistration"; break;
97             case NeedsRegistration: stateStr = "NeedsRegistration"; break;
98             case NeedsUpdate: stateStr = "NeedsUpdate"; break;
99             case Ready: stateStr = "Ready"; break;
100             case Removed: stateStr = "Removed"; break;
101             default: stateStr = "Unknown"; break;
102         }
103         TRACE() << "Updating state: " << stateStr;
104         m_state = state;
105     }
106
107     void IdentityImpl::copyInfo(const IdentityInfo &info)
108     {
109         m_identityInfo->impl->copy(*(info.impl));
110     }
111
112     quint32 IdentityImpl::id() const
113     {
114        return m_identityInfo->id();
115     }
116
117     AuthSession *IdentityImpl::createSession(const QString &methodName, QObject *parent)
118     {
119         foreach (AuthSession *authSession, m_authSessions) {
120             if (authSession->name() == methodName) {
121                 qWarning() << QString::fromLatin1(
122                         "Authentication session for method "
123                         "`%1` already requested.").arg(methodName);
124                 return 0;
125             }
126         }
127
128         AuthSession *session = new AuthSession(id(), methodName, parent);
129         m_authSessions.append(session);
130         return session;
131     }
132
133     void IdentityImpl::destroySession(AuthSession *session)
134     {
135         session->blockSignals(true);
136         m_authSessions.removeOne(session);
137         session->deleteLater();
138     }
139
140     void IdentityImpl::queryAvailableMethods()
141     {
142         TRACE() << "Querying available identity authentication methods.";
143         checkConnection();
144
145         switch (m_state) {
146             case NeedsRegistration:
147                 m_operationQueueHandler.enqueueOperation(
148                                             SIGNOND_IDENTITY_QUERY_AVAILABLE_METHODS_METHOD);
149                 sendRegisterRequest();
150                 break;
151             case PendingRegistration:
152                 m_operationQueueHandler.enqueueOperation(
153                                             SIGNOND_IDENTITY_QUERY_AVAILABLE_METHODS_METHOD);
154                 break;
155             case NeedsUpdate:
156                 m_operationQueueHandler.enqueueOperation(
157                                             SIGNOND_IDENTITY_QUERY_AVAILABLE_METHODS_METHOD);
158
159                 /* This flag tells the queryInfo() reply slot that the current query
160                    should not reply with the 'info()' signal */
161                 m_infoQueried = false;
162                 updateContents();
163                 break;
164             case Removed:
165                 emit m_parent->error(Error(Error::IdentityNotFound,
166                                      QLatin1String("Removed from database.")));
167                 return;
168             case Ready:
169                 /* fall trough */
170             default:
171                 emit m_parent->methodsAvailable(m_identityInfo->methods());
172         }
173     }
174
175     void IdentityImpl::requestCredentialsUpdate(const QString &message)
176     {
177         TRACE() << "Requesting credentials update.";
178         checkConnection();
179
180         switch (m_state) {
181             case NeedsRegistration:
182                 m_operationQueueHandler.enqueueOperation(
183                                 SIGNOND_IDENTITY_REQUEST_CREDENTIALS_UPDATE_METHOD,
184                                 QList<QGenericArgument *>() << (new Q_ARG(QString, message)));
185                 sendRegisterRequest();
186                 return;
187             case PendingRegistration:
188                 m_operationQueueHandler.enqueueOperation(
189                                 SIGNOND_IDENTITY_REQUEST_CREDENTIALS_UPDATE_METHOD,
190                                 QList<QGenericArgument *>() << (new Q_ARG(QString, message)));
191                 return;
192             case NeedsUpdate:
193                 break;
194             case Removed:
195                 emit m_parent->error(
196                         Error(Error::IdentityNotFound,
197                               QLatin1String("Removed from database.")));
198                 return;
199             case Ready:
200                 /* fall trough */
201             default:
202                 break;
203         }
204
205         QList<QVariant> args;
206         args << message;
207         bool result = sendRequest(__func__, args,
208                                   SLOT(storeCredentialsReply(const quint32)));
209         if (!result) {
210             TRACE() << "Error occurred.";
211             emit m_parent->error(
212                     Error(Error::InternalCommunication,
213                           SIGNOND_INTERNAL_COMMUNICATION_ERR_STR));
214         }
215     }
216
217     void IdentityImpl::storeCredentials(const IdentityInfo &info)
218     {
219         TRACE() << "Storing credentials";
220         checkConnection();
221
222         switch (m_state) {
223             case NeedsRegistration:
224                 {
225                 IdentityInfo localInfo =
226                     info.impl->isEmpty() ? *m_identityInfo : *(m_tmpIdentityInfo = new IdentityInfo(info));
227
228                 m_operationQueueHandler.enqueueOperation(
229                                         SIGNOND_IDENTITY_STORE_CREDENTIALS_METHOD,
230                                         QList<QGenericArgument *>() << (new Q_ARG(SignOn::IdentityInfo, localInfo)));
231                 sendRegisterRequest();
232                 return;
233                 }
234             case PendingRegistration:
235                 {
236                 IdentityInfo localInfo =
237                     info.impl->isEmpty() ? *m_identityInfo : *(m_tmpIdentityInfo = new IdentityInfo(info));
238                 m_operationQueueHandler.enqueueOperation(
239                                         SIGNOND_IDENTITY_STORE_CREDENTIALS_METHOD,
240                                         QList<QGenericArgument *>() << (new Q_ARG(SignOn::IdentityInfo, localInfo)));
241                 return;
242                 }
243             case Removed:
244                 break;
245             case NeedsUpdate:
246                 break;
247             case Ready:
248                 /* fall trough */
249             default:
250                 break;
251         }
252
253         if (info.impl->isEmpty()) {
254             emit m_parent->error(
255                 Error(Error::StoreFailed,
256                       QLatin1String("Invalid Identity data.")));
257             return;
258         }
259
260         QList<QVariant> args;
261
262         args << m_identityInfo->id()
263              << info.userName()
264              << info.secret()
265              << info.isStoringSecret()
266              << QVariant(info.impl->m_authMethods)
267              << info.caption()
268              << info.realms()
269              << QVariant(info.accessControlList())
270              << info.type();
271
272         TRACE() << args;
273
274         bool result = sendRequest(__func__, args,
275                                   SLOT(storeCredentialsReply(const quint32)));
276         if (!result) {
277             TRACE() << "Error occurred.";
278             emit m_parent->error(
279                     Error(Error::InternalCommunication,
280                           SIGNOND_INTERNAL_COMMUNICATION_ERR_STR));
281         }
282     }
283
284     void IdentityImpl::remove()
285     {
286         TRACE() << "Removing credentials.";
287
288         /* If the Identity is not stored, it makes no sense to request a removal
289             -- this condition could be removed; there is the case when there is an ongoing
290                store operation.
291         */
292
293         if (id() != SIGNOND_NEW_IDENTITY) {
294             checkConnection();
295
296             switch (m_state) {
297                 case NeedsRegistration:
298                     m_operationQueueHandler.enqueueOperation(SIGNOND_IDENTITY_REMOVE_METHOD);
299                     sendRegisterRequest();
300                     return;
301                 case PendingRegistration:
302                     m_operationQueueHandler.enqueueOperation(SIGNOND_IDENTITY_REMOVE_METHOD);
303                     return;
304                 case Removed:
305                     emit m_parent->error(
306                             Error(Error::IdentityNotFound,
307                                   QLatin1String("Already removed from database.")));
308                     return;
309                 case NeedsUpdate:
310                     break;
311                 case Ready:
312                 /* fall trough */
313                 default:
314                     break;
315             }
316
317             bool result = sendRequest(__func__, QList<QVariant>(),
318                                       SLOT(removeReply()));
319             if (!result) {
320                 TRACE() << "Error occurred.";
321                 emit m_parent->error(
322                         Error(Error::InternalCommunication,
323                               SIGNOND_INTERNAL_COMMUNICATION_ERR_STR));
324             }
325         } else {
326             emit m_parent->error(
327                     Error(Error::Unknown,
328                           QLatin1String("Remove request failed. The identity is not stored")));
329         }
330     }
331
332     void IdentityImpl::addReference(const QString &reference)
333     {
334         TRACE() << "Adding reference to identity";
335         checkConnection();
336
337         switch (m_state) {
338             case NeedsRegistration:
339                 m_operationQueueHandler.enqueueOperation(
340                                 SIGNOND_IDENTITY_ADD_REFERENCE_METHOD,
341                                 QList<QGenericArgument *>() << (new Q_ARG(QString, reference)));
342                 sendRegisterRequest();
343                 return;
344             case PendingRegistration:
345                 m_operationQueueHandler.enqueueOperation(
346                                 SIGNOND_IDENTITY_ADD_REFERENCE_METHOD,
347                                 QList<QGenericArgument *>() << (new Q_ARG(QString, reference)));
348                 return;
349             case NeedsUpdate:
350                 break;
351             case Removed:
352                 emit m_parent->error(
353                         Error(Error::IdentityNotFound,
354                               QLatin1String("Removed from database.")));
355                 return;
356             case Ready:
357                 /* fall trough */
358             default:
359                 break;
360         }
361
362         bool result = sendRequest(__func__, QList<QVariant>() << QVariant(reference),
363                                   SLOT(addReferenceReply(const quint32)));
364         if (!result) {
365             TRACE() << "Error occurred.";
366             emit m_parent->error(
367                     Error(Error::InternalCommunication,
368                           SIGNOND_INTERNAL_COMMUNICATION_ERR_STR));
369         }
370     }
371
372     void IdentityImpl::removeReference(const QString &reference)
373     {
374         TRACE() << "Removing reference from identity";
375         checkConnection();
376
377         switch (m_state) {
378             case NeedsRegistration:
379                 m_operationQueueHandler.enqueueOperation(
380                                 SIGNOND_IDENTITY_REMOVE_REFERENCE_METHOD,
381                                 QList<QGenericArgument *>() << (new Q_ARG(QString, reference)));
382                 sendRegisterRequest();
383                 return;
384             case PendingRegistration:
385                 m_operationQueueHandler.enqueueOperation(
386                                 SIGNOND_IDENTITY_REMOVE_REFERENCE_METHOD,
387                                 QList<QGenericArgument *>() << (new Q_ARG(QString, reference)));
388                 return;
389             case NeedsUpdate:
390                 break;
391             case Removed:
392                 emit m_parent->error(
393                         Error(Error::IdentityNotFound,
394                               QLatin1String("Removed from database.")));
395                 return;
396             case Ready:
397                 /* fall trough */
398             default:
399                 break;
400         }
401
402         bool result = sendRequest(__func__, QList<QVariant>() << QVariant(reference),
403                                   SLOT(removeReferenceReply(const quint32)));
404         if (!result) {
405             TRACE() << "Error occurred.";
406             emit m_parent->error(
407                     Error(Error::InternalCommunication,
408                           SIGNOND_INTERNAL_COMMUNICATION_ERR_STR));
409         }
410     }
411
412     void IdentityImpl::queryInfo()
413     {
414         TRACE() << "Querying info.";
415         checkConnection();
416
417         switch (m_state) {
418             case NeedsRegistration:
419                 m_operationQueueHandler.enqueueOperation(SIGNOND_IDENTITY_QUERY_INFO_METHOD);
420                 sendRegisterRequest();
421                 return;
422             case PendingRegistration:
423                 m_operationQueueHandler.enqueueOperation(SIGNOND_IDENTITY_QUERY_INFO_METHOD);
424                 return;
425             case Removed:
426                 emit m_parent->error(
427                         Error(Error::IdentityNotFound,
428                               QLatin1String("Removed from database.")));
429                 return;
430             case NeedsUpdate:
431                 m_infoQueried = true;
432                 updateContents();
433                 break;
434             case Ready:
435                 emit m_parent->info(IdentityInfo(*m_identityInfo));
436                 return;
437             default:
438                 break;
439         }
440     }
441
442     void IdentityImpl::verifyUser(const QString &message)
443     {
444         TRACE() << "Verifying user.";
445         checkConnection();
446
447         switch (m_state) {
448             case NeedsRegistration:
449                 m_operationQueueHandler.enqueueOperation(
450                                         SIGNOND_IDENTITY_VERIFY_USER_METHOD,
451                                         QList<QGenericArgument *>() << (new Q_ARG(QString, message)));
452                 sendRegisterRequest();
453                 return;
454             case PendingRegistration:
455                 m_operationQueueHandler.enqueueOperation(
456                                         SIGNOND_IDENTITY_VERIFY_USER_METHOD,
457                                         QList<QGenericArgument *>() << (new Q_ARG(QString, message)));
458                 return;
459             case Removed:
460                 emit m_parent->error(
461                         Error(Error::IdentityNotFound,
462                               QLatin1String("Removed from database.")));
463                 return;
464             case NeedsUpdate:
465                 break;
466             case Ready:
467                 /* fall trough */
468             default:
469                 break;
470         }
471
472         bool result = sendRequest(__func__, QList<QVariant>() << message,
473                                   SLOT(verifyUserReply(const bool)));
474         if (!result) {
475             TRACE() << "Error occurred.";
476             emit m_parent->error(
477                     Error(Error::InternalCommunication,
478                           SIGNOND_INTERNAL_COMMUNICATION_ERR_STR));
479         }
480     }
481
482     void IdentityImpl::verifySecret(const QString &secret)
483     {
484         TRACE() << "Verifying secret." << secret;
485         checkConnection();
486
487         switch (m_state) {
488             case NeedsRegistration:
489                 m_operationQueueHandler.enqueueOperation(
490                                         SIGNOND_IDENTITY_VERIFY_SECRET_METHOD,
491                                         QList<QGenericArgument *>() << (new Q_ARG(QString, secret)));
492                 sendRegisterRequest();
493                 return;
494             case PendingRegistration:
495                 m_operationQueueHandler.enqueueOperation(
496                                         SIGNOND_IDENTITY_VERIFY_SECRET_METHOD,
497                                         QList<QGenericArgument *>() << (new Q_ARG(QString, secret)));
498                 return;
499             case Removed:
500                 emit m_parent->error(
501                         Error(Error::IdentityNotFound,
502                               QLatin1String("Removed from database.")));
503                 return;
504             case NeedsUpdate:
505                 break;
506             case Ready:
507                 /* fall trough */
508             default:
509                 break;
510         }
511
512         bool result = sendRequest(__func__, QList<QVariant>() << QVariant(secret),
513                                   SLOT(verifySecretReply(const bool)));
514         if (!result) {
515             TRACE() << "Error occurred.";
516             emit m_parent->error(
517                     Error(Error::InternalCommunication,
518                           SIGNOND_INTERNAL_COMMUNICATION_ERR_STR));
519         }
520     }
521
522     void IdentityImpl::signOut()
523     {
524         TRACE() << "Signing out.";
525         checkConnection();
526
527         /* if this is a stored identity, inform server about signing out
528            so that other client identity objects having the same id will
529            be able to perform the operation.
530         */
531         if (id() != SIGNOND_NEW_IDENTITY) {
532             switch (m_state) {
533                 case NeedsRegistration:
534                     m_operationQueueHandler.enqueueOperation(SIGNOND_IDENTITY_SIGN_OUT_METHOD);
535                     sendRegisterRequest();
536                     return;
537                 case PendingRegistration:
538                     m_operationQueueHandler.enqueueOperation(SIGNOND_IDENTITY_SIGN_OUT_METHOD);
539                     return;
540                 case Removed:
541                     break;
542                 case NeedsUpdate:
543                     break;
544                 case Ready:
545                     break;
546                 default:
547                     break;
548             }
549
550             bool result = sendRequest(__func__, QList<QVariant>(),
551                                       SLOT(signOutReply()));
552             if (!result) {
553                 TRACE() << "Error occurred.";
554                 emit m_parent->error(
555                         Error(Error::InternalCommunication,
556                               SIGNOND_INTERNAL_COMMUNICATION_ERR_STR));
557             } else {
558                 m_signOutRequestedByThisIdentity = true;
559             }
560         }
561
562         clearAuthSessionsCache();
563     }
564
565     void IdentityImpl::clearAuthSessionsCache()
566     {
567         while (!m_authSessions.empty()) {
568             AuthSession *session = m_authSessions.takeFirst();
569             connect(session,
570                     SIGNAL(error(AuthSession::AuthSessionError, const QString &)),
571                     this,
572                     SLOT(authSessionCancelReply(AuthSession::AuthSessionError)));
573
574             session->cancel();
575             QTimer::singleShot(SIGNOND_AUTH_SESSION_CANCEL_TIMEOUT, session, SLOT(deleteLater()));
576         }
577     }
578
579     void IdentityImpl::authSessionCancelReply(AuthSession::AuthSessionError error)
580     {
581         TRACE() << "CANCEL SESSION REPLY";
582
583         bool deleteTheSender = false;
584         switch (error) {
585             /* fall trough */
586             case AuthSession::CanceledError:
587             case AuthSession::WrongStateError: deleteTheSender = true; break;
588             default: break;
589         }
590
591         if (deleteTheSender) {
592             QObject *sender = QObject::sender();
593             if (sender) {
594                 TRACE() << "DELETING SESSION";
595                 sender->deleteLater();
596             }
597         }
598     }
599
600     void IdentityImpl::storeCredentialsReply(const quint32 id)
601     {
602         if (id != this->id()) {
603             m_identityInfo->setId(id);
604             foreach (AuthSession *session, m_authSessions)
605                 session->impl->setId(id);
606         }
607
608         if (m_tmpIdentityInfo) {
609             *m_identityInfo = *m_tmpIdentityInfo;
610             delete m_tmpIdentityInfo;
611             m_tmpIdentityInfo = NULL;
612         }
613         emit m_parent->credentialsStored(id);
614     }
615
616     void IdentityImpl::removeReply()
617     {
618         m_identityInfo->impl->clear();
619         updateState(Removed);
620         emit m_parent->removed();
621     }
622
623     void IdentityImpl::addReferenceReply(const quint32 count)
624     {
625         Q_UNUSED(count);
626         emit m_parent->referenceAdded();
627     }
628
629     void IdentityImpl::removeReferenceReply(const quint32 count)
630     {
631         Q_UNUSED(count);
632         emit m_parent->referenceRemoved();
633     }
634
635     void IdentityImpl::queryInfoReply(const QList<QVariant> &infoData)
636     {
637         updateCachedData(infoData);
638         updateState(Ready);
639
640         if (m_infoQueried)
641             emit m_parent->info(IdentityInfo(*m_identityInfo));
642         else
643             emit m_parent->methodsAvailable(m_identityInfo->methods());
644
645         m_infoQueried = true;
646     }
647
648     void IdentityImpl::verifyUserReply(const bool valid)
649     {
650         emit m_parent->userVerified(valid);
651     }
652
653     void IdentityImpl::verifySecretReply(const bool valid)
654     {
655         emit m_parent->secretVerified(valid);
656     }
657
658     void IdentityImpl::signOutReply()
659     {
660         emit m_parent->signedOut();
661     }
662
663     void IdentityImpl::infoUpdated(int state)
664     {
665         const char *stateStr;
666         switch ((IdentityState)state) {
667             /* Data updated on the server side. */
668             case IdentityDataUpdated:
669                 updateState(NeedsUpdate);
670                 stateStr = "NeedsUpdate";
671                 break;
672             /* Data removed on the server side. */
673             case IdentityRemoved:
674                 updateState(Removed);
675                 stateStr = "Removed";
676                 break;
677             /* A remote client identity signed out,
678                thus server informed this object to do the same */
679             case IdentitySignedOut:
680                 //if this is not the identity that requested the signing out
681                 if (!m_signOutRequestedByThisIdentity) {
682                     clearAuthSessionsCache();
683                     emit m_parent->signedOut();
684                 }
685                 stateStr = "SignedOut";
686                 break;
687             default: stateStr = "Unknown";
688                 break;
689         }
690         TRACE() << "\n\nSERVER INFO UPDATED." << stateStr << QString(QLatin1String(" %1 ")).arg(id()) << "\n\n";
691     }
692
693     void IdentityImpl::errorReply(const QDBusError& err)
694     {
695         TRACE() << err.name();
696
697         /* Signon specific errors */
698         if (err.name() == SIGNOND_UNKNOWN_ERR_NAME) {
699             emit m_parent->error(Error(Error::Unknown, err.message()));
700             return;
701         } else if (err.name() == SIGNOND_INTERNAL_SERVER_ERR_NAME) {
702             emit m_parent->error(Error(Error::InternalServer, err.message()));
703             return;
704         } else if (err.name() == SIGNOND_IDENTITY_NOT_FOUND_ERR_NAME) {
705             emit m_parent->error(Error(Error::IdentityNotFound, err.message()));
706             return;
707         } else if (err.name() == SIGNOND_METHOD_NOT_AVAILABLE_ERR_NAME) {
708             emit m_parent->error(Error(Error::MethodNotAvailable, err.message()));
709             return;
710         } else if (err.name() == SIGNOND_PERMISSION_DENIED_ERR_NAME) {
711             emit m_parent->error(Error(Error::PermissionDenied, err.message()));
712             return;
713         } else if (err.name() == SIGNOND_PERMISSION_DENIED_ERR_NAME) {
714             emit m_parent->error(Error(Error::PermissionDenied, err.message()));
715             return;
716         } else if (err.name() == SIGNOND_STORE_FAILED_ERR_NAME) {
717             emit m_parent->error(Error(Error::StoreFailed, err.message()));
718             if (m_tmpIdentityInfo) {
719                 delete m_tmpIdentityInfo;
720                 m_tmpIdentityInfo = NULL;
721             }
722             return;
723         } else if (err.name() == SIGNOND_REMOVE_FAILED_ERR_NAME) {
724             emit m_parent->error(Error(Error::RemoveFailed, err.message()));
725             return;
726         } else if (err.name() == SIGNOND_SIGNOUT_FAILED_ERR_NAME) {
727             emit m_parent->error(Error(Error::SignOutFailed, err.message()));
728             return;
729         } else if (err.name() == SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_NAME) {
730             emit m_parent->error(Error(Error::IdentityOperationCanceled, err.message()));
731             return;
732         } else if (err.name() == SIGNOND_CREDENTIALS_NOT_AVAILABLE_ERR_NAME) {
733             emit m_parent->error(Error(Error::CredentialsNotAvailable, err.message()));
734             return;
735         }
736         else {
737             if (m_state == this->PendingRegistration)
738                 updateState(NeedsRegistration);
739
740             TRACE() << "Non internal SSO error reply.";
741         }
742
743         /* Qt DBUS specific errors */
744         if (err.type() != QDBusError::NoError) {
745             emit m_parent->error(Error(Error::InternalCommunication, err.message()));
746             return;
747         }
748
749         emit m_parent->error(Error(Error::Unknown, err.message()));
750     }
751
752     void IdentityImpl::updateContents()
753     {
754         bool result = sendRequest("queryInfo", QList<QVariant>(),
755                                   SLOT(queryInfoReply(const QList<QVariant> &)));
756
757         if (!result) {
758             TRACE() << "Error occurred.";
759             emit m_parent->error(
760                     Error(Error::InternalCommunication,
761                           SIGNOND_INTERNAL_COMMUNICATION_ERR_STR));
762         }
763     }
764
765     bool IdentityImpl::sendRequest(const char *remoteMethod, const QList<QVariant> &args, const char *replySlot)
766     {
767         return m_DBusInterface->callWithCallback(QLatin1String(remoteMethod),
768                                                   args,
769                                                   this,
770                                                   replySlot,
771                                                   SLOT(errorReply(const QDBusError&)));
772     }
773
774     bool IdentityImpl::sendRegisterRequest()
775     {
776         QDBusInterface iface(SIGNOND_SERVICE,
777                              SIGNOND_DAEMON_OBJECTPATH,
778                              SIGNOND_DAEMON_INTERFACE,
779                              SIGNOND_BUS);
780
781         if (!iface.isValid()) {
782             TRACE() << "Signon Daemon not started. Start on demand "
783                        "could delay the first call's result.";
784             if (iface.lastError().isValid()) {
785                 QDBusError err = iface.lastError();
786                 TRACE() << "\nError name:" << err.name()
787                         << "\nMessage: " << err.message()
788                         << "\nType: " << QDBusError::errorString(err.type());
789
790                 m_operationQueueHandler.clearOperationsQueue();
791                 updateState(NeedsRegistration);
792                 return false;
793             }
794         }
795
796         QList<QVariant> args;
797         QString registerMethodName = QLatin1String("registerNewIdentity");
798         QByteArray registerReplyMethodName =
799             SLOT(registerReply(const QDBusObjectPath &));
800
801         if (id() != SIGNOND_NEW_IDENTITY) {
802             registerMethodName = QLatin1String("registerStoredIdentity");
803             args << m_identityInfo->id();
804             registerReplyMethodName =
805                 SLOT(registerReply(const QDBusObjectPath &, const QList<QVariant> &));
806         }
807
808         if (!iface.callWithCallback(
809                                 registerMethodName,
810                                 args,
811                                 this,
812                                 registerReplyMethodName.data(),
813                                 SLOT(errorReply(const QDBusError &)))) {
814
815             QDBusError err = iface.lastError();
816             TRACE() << "\nError name:" << err.name()
817                     << "\nMessage: " << err.message()
818                     << "\nType: " << QDBusError::errorString(err.type());
819             return false;
820         }
821         updateState(PendingRegistration);
822         return true;
823     }
824
825     void IdentityImpl::updateCachedData(const QList<QVariant> &infoDataConst)
826     {
827         QList<QVariant> infoData = infoDataConst;
828         if (!infoData.isEmpty())
829             m_identityInfo->setId(infoData.takeFirst().toUInt());
830
831         if (!infoData.isEmpty())
832             m_identityInfo->setUserName(infoData.takeFirst().toString());
833
834         if (!infoData.isEmpty())
835             m_identityInfo->setSecret(infoData.takeFirst().toString());
836
837         if (!infoData.isEmpty())
838             m_identityInfo->setCaption(infoData.takeFirst().toString());
839
840         if (!infoData.isEmpty())
841             m_identityInfo->setRealms(infoData.takeFirst().toStringList());
842
843         if (!infoData.isEmpty()) {
844             QDBusArgument arg(infoData.takeFirst().value<QDBusArgument>());
845             QMap<QString, QVariant> map = qdbus_cast<QMap<QString, QVariant> >(arg);
846             QMapIterator<QString, QVariant> it(map);
847             while (it.hasNext()) {
848                 it.next();
849                 m_identityInfo->setMethod(it.key(), it.value().toStringList());
850             }
851         }
852
853         if (!infoData.isEmpty())
854             m_identityInfo->setType((IdentityInfo::CredentialsType)(infoData.takeFirst().toInt()));
855
856         if (!infoData.isEmpty())
857             m_identityInfo->setRefCount((infoData.takeFirst().toInt()));
858
859     }
860
861     void IdentityImpl::checkConnection()
862     {
863         if (m_state == PendingRegistration || m_state == NeedsRegistration)
864             return;
865
866         if (!m_DBusInterface
867             || !m_DBusInterface->isValid()
868             || m_DBusInterface->lastError().isValid())
869         {
870             updateState(NeedsRegistration);
871             m_operationQueueHandler.stopOperationsProcessing();
872         }
873     }
874
875     void IdentityImpl::registerReply(const QDBusObjectPath &objectPath)
876     {
877         registerReply(objectPath, QList<QVariant>());
878     }
879
880     void IdentityImpl::registerReply(const QDBusObjectPath &objectPath, const QList<QVariant> &infoData)
881     {
882         m_DBusInterface = new QDBusInterface(SIGNOND_SERVICE,
883                                              objectPath.path(),
884                                              QLatin1String(SIGNOND_IDENTITY_INTERFACE),
885                                              SIGNOND_BUS,
886                                              this);
887         if (!m_DBusInterface->isValid()) {
888             TRACE() << "The interface cannot be registered!!! " << m_DBusInterface->lastError();
889             updateState(NeedsRegistration);
890
891             delete m_DBusInterface;
892             m_DBusInterface = NULL;
893
894             int count = m_operationQueueHandler.queuedOperationsCount();
895             for (int i = 0; i < count; ++i) {
896                 emit m_parent->error(
897                         Error(Error::Unknown,
898                               QLatin1String("Could not establish valid "
899                                             "connection to remote object.")));
900             }
901             return;
902         }
903
904         connect(
905                 m_DBusInterface,
906                 SIGNAL(infoUpdated(int)),
907                 this,
908                 SLOT(infoUpdated(int)));
909
910         connect(m_DBusInterface, SIGNAL(unregistered()), SLOT(removeObjectDestroyed()));
911
912         if (!infoData.empty())
913             updateCachedData(infoData);
914
915         updateState(Ready);
916         if (m_operationQueueHandler.queuedOperationsCount() > 0)
917             m_operationQueueHandler.execQueuedOperations();
918     }
919
920     void IdentityImpl::removeObjectDestroyed()
921     {
922         updateState(NeedsRegistration);
923     }
924
925 } //namespace SignOn