[Telepathy-commits] [telepathy-qt4/master] ReadinessHelper: Propagate error message when a feature fails introspection.

Andre Moreira Magalhaes (andrunko) andre.magalhaes at collabora.co.uk
Fri Mar 6 11:28:12 PST 2009


---
 TelepathyQt4/Client/account.cpp            |    7 +-
 TelepathyQt4/Client/connection-manager.cpp |    4 +-
 TelepathyQt4/Client/connection.cpp         |   10 +--
 TelepathyQt4/Client/readiness-helper.cpp   |  102 ++++++++++++++++++++++-----
 TelepathyQt4/Client/readiness-helper.h     |   14 +++-
 TelepathyQt4/Client/text-channel.cpp       |    6 +-
 6 files changed, 107 insertions(+), 36 deletions(-)

diff --git a/TelepathyQt4/Client/account.cpp b/TelepathyQt4/Client/account.cpp
index d605ad6..dde67de 100644
--- a/TelepathyQt4/Client/account.cpp
+++ b/TelepathyQt4/Client/account.cpp
@@ -993,7 +993,7 @@ void Account::gotMainProperties(QDBusPendingCallWatcher *watcher)
         debug() << "Account basic functionality is ready";
         mPriv->readinessHelper->setIntrospectCompleted(FeatureCore, true);
     } else {
-        mPriv->readinessHelper->setIntrospectCompleted(FeatureCore, false);
+        mPriv->readinessHelper->setIntrospectCompleted(FeatureCore, false, reply.error());
 
         warning().nospace() <<
             "GetAll(Account) failed: " <<
@@ -1021,7 +1021,7 @@ void Account::gotAvatar(QDBusPendingCallWatcher *watcher)
         // check if the feature is already there, and for some reason retrieveAvatar
         // failed when called the second time
         if (!mPriv->readinessHelper->missingFeatures().contains(FeatureAvatar)) {
-            mPriv->readinessHelper->setIntrospectCompleted(FeatureAvatar, false);
+            mPriv->readinessHelper->setIntrospectCompleted(FeatureAvatar, false, reply.error());
         }
 
         warning().nospace() <<
@@ -1056,7 +1056,8 @@ void Account::onConnectionManagerReady(PendingOperation *operation)
         mPriv->readinessHelper->setIntrospectCompleted(FeatureProtocolInfo, true);
     }
     else {
-        mPriv->readinessHelper->setIntrospectCompleted(FeatureProtocolInfo, false);
+        mPriv->readinessHelper->setIntrospectCompleted(FeatureProtocolInfo, false,
+                operation->errorName(), operation->errorMessage());
     }
 }
 
diff --git a/TelepathyQt4/Client/connection-manager.cpp b/TelepathyQt4/Client/connection-manager.cpp
index 82f67a4..15e4f89 100644
--- a/TelepathyQt4/Client/connection-manager.cpp
+++ b/TelepathyQt4/Client/connection-manager.cpp
@@ -667,7 +667,7 @@ void ConnectionManager::gotProtocols(QDBusPendingCallWatcher *watcher)
 
         mPriv->introspectParameters();
     } else {
-        mPriv->readinessHelper->setIntrospectCompleted(FeatureCore, false);
+        mPriv->readinessHelper->setIntrospectCompleted(FeatureCore, false, reply.error());
 
         warning().nospace() <<
             "ConnectionManager.ListProtocols failed: " <<
@@ -706,7 +706,7 @@ void ConnectionManager::gotParameters(QDBusPendingCallWatcher *watcher)
             mPriv->readinessHelper->setIntrospectCompleted(FeatureCore, true);
         } else {
             // we could not retrieve the params for any protocol, fail core.
-            mPriv->readinessHelper->setIntrospectCompleted(FeatureCore, false);
+            mPriv->readinessHelper->setIntrospectCompleted(FeatureCore, false, reply.error());
         }
 
 #if 0
diff --git a/TelepathyQt4/Client/connection.cpp b/TelepathyQt4/Client/connection.cpp
index 1bbda28..4662bc7 100644
--- a/TelepathyQt4/Client/connection.cpp
+++ b/TelepathyQt4/Client/connection.cpp
@@ -803,9 +803,6 @@ void Connection::gotStatus(QDBusPendingCallWatcher *watcher)
             reply.error().name() << ":" << reply.error().message();
 
         invalidate(reply.error());
-
-        // introspect core failed
-        mPriv->readinessHelper->setIntrospectCompleted(FeatureCore, false);
         return;
     }
 
@@ -889,7 +886,8 @@ void Connection::gotSelfContact(PendingOperation *op)
         // check if the feature is already there, and for some reason introspectSelfContact
         // failed when called the second time
         if (!mPriv->readinessHelper->missingFeatures().contains(FeatureSelfContact)) {
-            mPriv->readinessHelper->setIntrospectCompleted(FeatureSelfContact, false);
+            mPriv->readinessHelper->setIntrospectCompleted(FeatureSelfContact, false,
+                    op->errorName(), op->errorMessage());
         }
     }
 }
@@ -906,7 +904,7 @@ void Connection::gotSimpleStatuses(QDBusPendingCallWatcher *watcher)
     else {
         warning().nospace() << "Getting simple presence statuses failed with " <<
             reply.error().name() << ":" << reply.error().message();
-        mPriv->readinessHelper->setIntrospectCompleted(FeatureSimplePresence, false);
+        mPriv->readinessHelper->setIntrospectCompleted(FeatureSimplePresence, false, reply.error());
     }
 
     watcher->deleteLater();
@@ -928,7 +926,7 @@ void Connection::gotSelfHandle(QDBusPendingCallWatcher *watcher)
     } else {
         warning().nospace() << "Getting self handle failed with " <<
             reply.error().name() << ":" << reply.error().message();
-        mPriv->readinessHelper->setIntrospectCompleted(FeatureCore, false);
+        mPriv->readinessHelper->setIntrospectCompleted(FeatureCore, false, reply.error());
     }
 
     watcher->deleteLater();
diff --git a/TelepathyQt4/Client/readiness-helper.cpp b/TelepathyQt4/Client/readiness-helper.cpp
index 999f103..4115e85 100644
--- a/TelepathyQt4/Client/readiness-helper.cpp
+++ b/TelepathyQt4/Client/readiness-helper.cpp
@@ -28,6 +28,7 @@
 #include <TelepathyQt4/Client/PendingReady>
 #include <TelepathyQt4/Constants>
 
+#include <QDBusError>
 #include <QTimer>
 
 namespace Telepathy
@@ -44,7 +45,9 @@ struct ReadinessHelper::Private
     ~Private();
 
     void setCurrentStatus(uint newStatus);
-    void setIntrospectCompleted(const Feature &feature, bool success);
+    void setIntrospectCompleted(const Feature &feature, bool success,
+            const QString &errorName = QString(),
+            const QString &errorMessage = QString());
     void iterateIntrospection();
 
     void abortOperations(const QString &errorName, const QString &errorMessage);
@@ -61,6 +64,7 @@ struct ReadinessHelper::Private
     Features missingFeatures;
     Features pendingFeatures;
     Features inFlightFeatures;
+    QHash<Feature, QPair<QString, QString> > missingFeaturesErrors;
     QList<PendingReady *> pendingOperations;
 
     bool pendingStatusChange;
@@ -121,7 +125,8 @@ void ReadinessHelper::Private::setCurrentStatus(uint newStatus)
     }
 }
 
-void ReadinessHelper::Private::setIntrospectCompleted(const Feature &feature, bool success)
+void ReadinessHelper::Private::setIntrospectCompleted(const Feature &feature,
+        bool success, const QString &errorName, const QString &errorMessage)
 {
     debug() << "ReadinessHelper::setIntrospectCompleted: feature:" << feature <<
         "- success:" << success;
@@ -148,6 +153,12 @@ void ReadinessHelper::Private::setIntrospectCompleted(const Feature &feature, bo
     }
     else {
         missingFeatures.insert(feature);
+        missingFeaturesErrors.insert(feature,
+                QPair<QString, QString>(errorName, errorMessage));
+        if (errorName.isEmpty()) {
+            warning() << "ReadinessHelper::setIntrospectCompleted: Feature" <<
+                feature << "introspection failed but no error message was given";
+        }
     }
 
     pendingFeatures.remove(feature);
@@ -177,7 +188,10 @@ void ReadinessHelper::Private::iterateIntrospection()
         Introspectable introspectable = i.value();
         Features dependsOnFeatures = introspectable.dependsOnFeatures;
         if (!dependsOnFeatures.intersect(missingFeatures).isEmpty()) {
-            missingFeatures += feature;
+            missingFeatures.insert(feature);
+            missingFeaturesErrors.insert(feature,
+                    QPair<QString, QString>(TELEPATHY_ERROR_NOT_AVAILABLE,
+                        "Feature depend on other features that are not available"));
         }
         ++i;
     }
@@ -185,15 +199,14 @@ void ReadinessHelper::Private::iterateIntrospection()
     // check if any pending operations for becomeReady should finish now
     // based on their requested features having nothing more than what
     // satisfiedFeatures + missingFeatures has
+    QString errorName;
+    QString errorMessage;
     foreach (PendingReady *operation, pendingOperations) {
         if ((operation->requestedFeatures() - (satisfiedFeatures + missingFeatures)).isEmpty()) {
-            if (parent->isReady(operation->requestedFeatures())) {
+            if (parent->isReady(operation->requestedFeatures(), &errorName, &errorMessage)) {
                 operation->setFinished();
             } else {
-                // TODO get the error from somewhere, maybe add an error param
-                //      to setIntrospectCompleted
-                operation->setFinishedWithError(TELEPATHY_ERROR_NOT_AVAILABLE,
-                        "Some features not available");
+                operation->setFinishedWithError(errorName, errorMessage);
             }
             pendingOperations.removeOne(operation);
         }
@@ -243,7 +256,9 @@ void ReadinessHelper::Private::iterateIntrospection()
                 debug() << "feature" << feature << "depends on interfaces" <<
                     introspectable.dependsOnInterfaces << ", but interface" << interface <<
                     "is not present";
-                setIntrospectCompleted(feature, false);
+                setIntrospectCompleted(feature, false,
+                        QLatin1String(TELEPATHY_ERROR_NOT_AVAILABLE),
+                        QLatin1String("Feature depend on interfaces that are not available"));
                 return; // will be called with a single-shot soon again
             }
         }
@@ -260,6 +275,7 @@ void ReadinessHelper::Private::abortOperations(const QString &errorName,
 {
     foreach (PendingReady *operation, pendingOperations) {
         operation->setFinishedWithError(errorName, errorMessage);
+        pendingOperations.removeOne(operation);
     }
 }
 
@@ -341,37 +357,73 @@ Features ReadinessHelper::missingFeatures() const
     return mPriv->missingFeatures;
 }
 
-bool ReadinessHelper::isReady(const Feature &feature) const
+bool ReadinessHelper::isReady(const Feature &feature,
+        QString *errorName, QString *errorMessage) const
 {
     if (!mPriv->proxy->isValid()) {
+        if (errorName) {
+            *errorName = mPriv->proxy->invalidationReason();
+        }
+        if (errorMessage) {
+            *errorMessage = mPriv->proxy->invalidationMessage();
+        }
+        return false;
+    }
+
+    if (!mPriv->supportedFeatures.contains(feature)) {
+        if (errorName) {
+            *errorName = QLatin1String(TELEPATHY_ERROR_INVALID_ARGUMENT);
+        }
+        if (errorMessage) {
+            *errorMessage = QLatin1String("Unsupported feature");
+        }
         return false;
     }
 
+    bool ret = true;
+
     if (feature.isCritical()) {
         if (!mPriv->satisfiedFeatures.contains(feature)) {
             debug() << "ReadinessHelper::isReady: critical feature" << feature << "not ready";
-            return false;
+            ret = false;
         }
     } else {
         if (!mPriv->satisfiedFeatures.contains(feature) &&
             !mPriv->missingFeatures.contains(feature)) {
             debug() << "ReadinessHelper::isReady: feature" << feature << "not ready";
-            return false;
+            ret = false;
         }
     }
-    return true;
+
+    if (!ret) {
+        QPair<QString, QString> error = mPriv->missingFeaturesErrors[feature];
+        if (errorName) {
+            *errorName = error.first;
+        }
+        if (errorMessage) {
+            *errorMessage = error.second;
+        }
+    }
+
+    return ret;
 }
 
-bool ReadinessHelper::isReady(const Features &features) const
+bool ReadinessHelper::isReady(const Features &features, QString *errorName, QString *errorMessage) const
 {
     if (!mPriv->proxy->isValid()) {
+        if (errorName) {
+            *errorName = mPriv->proxy->invalidationReason();
+        }
+        if (errorMessage) {
+            *errorMessage = mPriv->proxy->invalidationMessage();
+        }
         return false;
     }
 
     Q_ASSERT(!features.isEmpty());
 
     foreach (const Feature &feature, features) {
-        if (!isReady(feature)) {
+        if (!isReady(feature, errorName, errorMessage)) {
             return false;
         }
     }
@@ -388,8 +440,9 @@ PendingReady *ReadinessHelper::becomeReady(const Features &requestedFeatures)
             requestedFeatures << "- supportedFeatures =" << mPriv->supportedFeatures;
         PendingReady *operation =
             new PendingReady(requestedFeatures, mPriv->proxy);
-        operation->setFinishedWithError(TELEPATHY_ERROR_INVALID_ARGUMENT,
-                "Requested features contains invalid feature");
+        operation->setFinishedWithError(
+                QLatin1String(TELEPATHY_ERROR_INVALID_ARGUMENT),
+                QLatin1String("Requested features contains unsupported feature"));
         return operation;
     }
 
@@ -420,13 +473,20 @@ PendingReady *ReadinessHelper::becomeReady(const Features &requestedFeatures)
     return operation;
 }
 
-void ReadinessHelper::setIntrospectCompleted(const Feature &feature, bool success)
+void ReadinessHelper::setIntrospectCompleted(const Feature &feature, bool success,
+        const QString &errorName, const QString &errorMessage)
 {
     if (!mPriv->proxy->isValid()) {
         // proxy became invalid, ignore here
         return;
     }
-    mPriv->setIntrospectCompleted(feature, success);
+    mPriv->setIntrospectCompleted(feature, success, errorName, errorMessage);
+}
+
+void ReadinessHelper::setIntrospectCompleted(const Feature &feature, bool success,
+        const QDBusError &error)
+{
+    setIntrospectCompleted(feature, success, error.name(), error.message());
 }
 
 void ReadinessHelper::iterateIntrospection()
@@ -437,6 +497,10 @@ void ReadinessHelper::iterateIntrospection()
 void ReadinessHelper::onProxyInvalidated(Telepathy::Client::DBusProxy *proxy,
         const QString &errorName, const QString &errorMessage)
 {
+    // clear satisfied and missing features as we have public methods to get them
+    mPriv->satisfiedFeatures.clear();
+    mPriv->missingFeatures.clear();
+
     mPriv->abortOperations(errorName, errorMessage);
 }
 
diff --git a/TelepathyQt4/Client/readiness-helper.h b/TelepathyQt4/Client/readiness-helper.h
index 5f5ec43..201cb13 100644
--- a/TelepathyQt4/Client/readiness-helper.h
+++ b/TelepathyQt4/Client/readiness-helper.h
@@ -33,6 +33,8 @@
 #include <QSet>
 #include <QStringList>
 
+class QDBusError;
+
 namespace Telepathy
 {
 namespace Client
@@ -100,11 +102,17 @@ public:
     Features actualFeatures() const;
     Features missingFeatures() const;
 
-    bool isReady(const Feature &feature) const;
-    bool isReady(const Features &features) const;
+    bool isReady(const Feature &feature,
+            QString *errorName = 0, QString *errorMessage = 0) const;
+    bool isReady(const Features &features,
+            QString *errorName = 0, QString *errorMessage = 0) const;
     PendingReady *becomeReady(const Features &requestedFeatures);
 
-    void setIntrospectCompleted(const Feature &feature, bool success);
+    void setIntrospectCompleted(const Feature &feature, bool success,
+            const QString &errorName = QString(),
+            const QString &errorMessage = QString());
+    void setIntrospectCompleted(const Feature &feature, bool success,
+            const QDBusError &error);
 
 Q_SIGNALS:
     void statusReady(uint status);
diff --git a/TelepathyQt4/Client/text-channel.cpp b/TelepathyQt4/Client/text-channel.cpp
index 72a627f..37162cb 100644
--- a/TelepathyQt4/Client/text-channel.cpp
+++ b/TelepathyQt4/Client/text-channel.cpp
@@ -953,12 +953,12 @@ void TextChannel::gotProperties(QDBusPendingCallWatcher *watcher)
         ReadinessHelper *readinessHelper = mPriv->readinessHelper;
         if (readinessHelper->requestedFeatures().contains(FeatureMessageQueue) &&
             !readinessHelper->isReady(Features() << FeatureMessageQueue)) {
-            readinessHelper->setIntrospectCompleted(FeatureMessageQueue, false);
+            readinessHelper->setIntrospectCompleted(FeatureMessageQueue, false, reply.error());
         }
 
         if (readinessHelper->requestedFeatures().contains(FeatureMessageCapabilities) &&
             !readinessHelper->isReady(Features() << FeatureMessageCapabilities)) {
-            readinessHelper->setIntrospectCompleted(FeatureMessageCapabilities, false);
+            readinessHelper->setIntrospectCompleted(FeatureMessageCapabilities, false, reply.error());
         }
         return;
     }
@@ -982,7 +982,7 @@ void TextChannel::gotPendingMessages(QDBusPendingCallWatcher *watcher)
             reply.error().message();
 
         // TODO should we fail here?
-        mPriv->readinessHelper->setIntrospectCompleted(FeatureMessageQueue, false);
+        mPriv->readinessHelper->setIntrospectCompleted(FeatureMessageQueue, false, reply.error());
         return;
     }
 
-- 
1.5.6.5




More information about the telepathy-commits mailing list