diff --git a/polkit-agent/dialog.cpp b/polkit-agent/dialog.cpp index 48249bd..142f8fd 100644 --- a/polkit-agent/dialog.cpp +++ b/polkit-agent/dialog.cpp @@ -61,7 +61,12 @@ void Dialog::setConfirmationResult(const QString &passwd) { m_password = passwd; - emit finished(this); + emit accepted(); +} + +void Dialog::rejected() +{ + emit cancel(); } void Dialog::show() @@ -71,3 +76,8 @@ void Dialog::show() m_view->setX((m_view->screen()->geometry().width() - m_view->geometry().width()) / 2); m_view->setY((m_view->screen()->geometry().height() - m_view->geometry().height()) / 2); } + +void Dialog::authenticationFailure() +{ + emit failure(); +} diff --git a/polkit-agent/dialog.h b/polkit-agent/dialog.h index 9bff50e..5199b98 100644 --- a/polkit-agent/dialog.h +++ b/polkit-agent/dialog.h @@ -39,8 +39,11 @@ public: ~Dialog(); Q_INVOKABLE void setConfirmationResult(const QString &password = QString()); + Q_INVOKABLE void rejected(); Q_INVOKABLE void show(); + Q_INVOKABLE void authenticationFailure(); + Q_PROPERTY(QString message READ message NOTIFY changed) Q_PROPERTY(QString action READ action NOTIFY changed) Q_PROPERTY(QString cookie READ cookie NOTIFY changed) @@ -62,8 +65,10 @@ signals: // properties of this window dynamically for now void changed(); - // Send approval to the D-Bus helper daemon - void finished(Dialog *dialog); + void failure(); + + void cancel(); + void accepted(); private: QString m_action; diff --git a/polkit-agent/main.qml b/polkit-agent/main.qml index 0c9a06f..cb20b34 100644 --- a/polkit-agent/main.qml +++ b/polkit-agent/main.qml @@ -11,6 +11,14 @@ Item { width: 450 height: heightValue + Connections { + target: confirmation + function onFailure() { + doneButton.enabled = true + passwordInput.enabled = true + } + } + onHeightValueChanged: { rootWindow.height = heightValue rootWindow.maximumHeight = heightValue @@ -109,6 +117,7 @@ Item { Layout.fillWidth: true selectByMouse: true focus: true + onAccepted: { if (passwordInput.text) confirmation.setConfirmationResult(passwordInput.text) @@ -126,7 +135,7 @@ Item { text: qsTr("Cancel") Layout.fillWidth: true height: 50 - onClicked: confirmation.setConfirmationResult("") + onClicked: confirmation.rejected() } Button { @@ -135,7 +144,11 @@ Item { Layout.fillWidth: true flat: true height: 50 - onClicked: confirmation.setConfirmationResult(passwordInput.text) + onClicked: { + doneButton.enabled = false + passwordInput.enabled = false + confirmation.setConfirmationResult(passwordInput.text) + } } } } diff --git a/polkit-agent/polkitagentlistener.cpp b/polkit-agent/polkitagentlistener.cpp index 2fee6b1..790c7c5 100644 --- a/polkit-agent/polkitagentlistener.cpp +++ b/polkit-agent/polkitagentlistener.cpp @@ -25,6 +25,7 @@ PolKitAgentListener::PolKitAgentListener(QObject *parent) : PolkitQt1::Agent::Listener(parent) , m_dialog(nullptr) + , m_inProgress(false) { } @@ -39,61 +40,106 @@ void PolKitAgentListener::initiateAuthentication(const QString &actionId, { Q_UNUSED(details); - if (m_dialog) { - m_dialog->deleteLater(); - m_dialog = nullptr; + if (m_inProgress) { + result->setCompleted(); + return; } + m_identities = identities; + m_cookie = cookie; + m_result = result; + m_session.clear(); + + m_inProgress = true; + m_dialog = new Dialog(actionId, message, cookie, identities.first().toString(), iconName, result); + m_session = new PolkitQt1::Agent::Session(identities.first(), cookie, result); + + connect(m_dialog.data(), &Dialog::accepted, this, &PolKitAgentListener::onDialogAccepted); + connect(m_dialog.data(), &Dialog::cancel, this, &PolKitAgentListener::onDialogCanceled); + + m_dialog.data()->show(); + m_session.data()->initiate(); - for (const PolkitQt1::Identity &i : identities) { - PolkitQt1::Agent::Session *session; - session = new PolkitQt1::Agent::Session(i, cookie, result); - Q_ASSERT(session); - m_sessionIdentity[session] = i; - connect(session, &PolkitQt1::Agent::Session::request, this, &PolKitAgentListener::request); - connect(session, &PolkitQt1::Agent::Session::completed, this, &PolKitAgentListener::completed); - session->initiate(); + if (!identities.isEmpty()) { + m_selectedUser = identities[0]; } + + m_numTries = 0; + + tryAgain(); } void PolKitAgentListener::request(const QString &request, bool echo) { Q_UNUSED(request); Q_UNUSED(echo); +} + +void PolKitAgentListener::completed(bool gainedAuthorization) +{ + m_gainedAuthorization = gainedAuthorization; - PolkitQt1::Agent::Session *session = qobject_cast(sender()); - Q_ASSERT(session); - Q_ASSERT(m_dialog); + finishObtainPrivilege(); +} - PolkitQt1::Identity identity = m_sessionIdentity[session]; +void PolKitAgentListener::tryAgain() +{ + m_wasCancelled = false; - connect(m_dialog, &Dialog::finished, this, [=] { - if (m_dialog->identity() == m_sessionIdentity[session].toString() - && !m_dialog->password().isEmpty()) { - session->setResponse(m_dialog->password()); - } else { - session->cancel(); - } - }); + if (m_selectedUser.isValid()) { + m_session = new PolkitQt1::Agent::Session(m_selectedUser, m_cookie, m_result); + connect(m_session.data(), SIGNAL(request(QString, bool)), this, SLOT(request(QString, bool))); + connect(m_session.data(), SIGNAL(completed(bool)), this, SLOT(completed(bool))); - m_dialog->show(); + m_session.data()->initiate(); + } } -void PolKitAgentListener::completed(bool gainedAuthorization) +void PolKitAgentListener::finishObtainPrivilege() { - Q_UNUSED(gainedAuthorization); + m_numTries++; + + if (!m_gainedAuthorization && !m_wasCancelled && !m_dialog.isNull()) { + m_dialog.data()->authenticationFailure(); - PolkitQt1::Agent::Session *session = qobject_cast(sender()); - Q_ASSERT(session); - Q_ASSERT(m_dialog); + if (m_numTries < 3) { + m_session.data()->deleteLater(); - if (m_dialog->identity() == m_sessionIdentity[session].toString()) { - session->result()->setCompleted(); + tryAgain(); + return; + } + } + + if (!m_session.isNull()) { + m_session.data()->result()->setCompleted(); + } else { + m_result->setCompleted(); + } + + m_session.data()->deleteLater(); + + if (!m_dialog.isNull()) { + m_dialog.data()->deleteLater(); + } + + m_inProgress = false; +} + +void PolKitAgentListener::onDialogAccepted() +{ + if (!m_dialog.isNull()) { + m_session.data()->setResponse(m_dialog.data()->password()); + } +} + +void PolKitAgentListener::onDialogCanceled() +{ + m_wasCancelled = true; - m_dialog->deleteLater(); - m_dialog = nullptr; + if (!m_session.isNull()) { + m_session.data()->cancel(); } - session->deleteLater(); + finishObtainPrivilege(); } diff --git a/polkit-agent/polkitagentlistener.h b/polkit-agent/polkitagentlistener.h index a04a697..ab9d825 100644 --- a/polkit-agent/polkitagentlistener.h +++ b/polkit-agent/polkitagentlistener.h @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -52,8 +53,26 @@ public slots: void completed(bool gainedAuthorization); private: - QHash m_sessionIdentity; - Dialog *m_dialog; + void tryAgain(); + void finishObtainPrivilege(); + +private slots: + void onDialogAccepted(); + void onDialogCanceled(); + +private: + QPointer m_dialog; + QPointer m_session; + PolkitQt1::Identity::List m_identities; + PolkitQt1::Agent::AsyncResult *m_result; + PolkitQt1::Identity m_selectedUser; + QString m_cookie; + + bool m_inProgress; + bool m_gainedAuthorization; + bool m_wasCancelled; + + int m_numTries; }; #endif // POLKITAGENTLISTENER_H