|
9 | 9 | #include "configure.h" |
10 | 10 | #include "linglong/api/types/helper.h" |
11 | 11 | #include "linglong/api/types/v1/Generators.hpp" // IWYU pragma: keep |
| 12 | +#include "linglong/api/types/v1/InteractionReply.hpp" |
12 | 13 | #include "linglong/api/types/v1/PackageInfoV2.hpp" |
13 | 14 | #include "linglong/api/types/v1/PackageManager1JobInfo.hpp" |
14 | 15 | #include "linglong/api/types/v1/PackageManager1PruneResult.hpp" |
|
45 | 46 |
|
46 | 47 | #include <QDBusInterface> |
47 | 48 | #include <QDBusReply> |
| 49 | +#include <QDBusServiceWatcher> |
48 | 50 | #include <QDBusUnixFileDescriptor> |
49 | 51 | #include <QEventLoop> |
50 | 52 | #include <QMetaObject> |
51 | 53 | #include <QTimer> |
52 | 54 |
|
53 | 55 | #include <algorithm> |
| 56 | +#include <chrono> |
54 | 57 | #include <cstdint> |
55 | 58 | #include <functional> |
56 | 59 | #include <unordered_map> |
@@ -655,7 +658,7 @@ QVariantMap PackageManager::installFromLayer(const QDBusUnixFileDescriptor &fd, |
655 | 658 | PackageTask &taskRef = dynamic_cast<PackageTask &>(task); |
656 | 659 | if (msgType == api::types::v1::InteractionMessageType::Upgrade |
657 | 660 | && !options.skipInteraction) { |
658 | | - if (!taskRef.waitConfirm(msgType, additionalMessage)) { |
| 661 | + if (!this->waitConfirm(taskRef, msgType, additionalMessage)) { |
659 | 662 | return; |
660 | 663 | } |
661 | 664 | } |
@@ -1887,6 +1890,117 @@ auto PackageManager::InitRunContext(const QString &runContextCfg, |
1887 | 1890 | }); |
1888 | 1891 | } |
1889 | 1892 |
|
| 1893 | +void PackageManager::ReplyInteraction(QDBusObjectPath object_path, const QVariantMap &replies) |
| 1894 | +{ |
| 1895 | + Q_EMIT this->ReplyReceived(object_path, replies); |
| 1896 | +} |
| 1897 | + |
| 1898 | +void PackageManager::onPeerDisconnected() noexcept |
| 1899 | +{ |
| 1900 | + LogW("peer caller disconnected"); |
| 1901 | + Q_EMIT CallerDisconnected(); |
| 1902 | +} |
| 1903 | + |
| 1904 | +bool PackageManager::waitConfirm( |
| 1905 | + PackageTask &taskRef, |
| 1906 | + api::types::v1::InteractionMessageType msgType, |
| 1907 | + const api::types::v1::PackageManager1RequestInteractionAdditionalMessage |
| 1908 | + &additionalMessage) noexcept |
| 1909 | +{ |
| 1910 | + auto objectPath = QDBusObjectPath(taskRef.taskObjectPath().c_str()); |
| 1911 | + QEventLoop loop; |
| 1912 | + QTimer timeoutTimer; |
| 1913 | + timeoutTimer.setSingleShot(true); |
| 1914 | + |
| 1915 | + auto callerContext = taskRef.callerContext(); |
| 1916 | + std::unique_ptr<QDBusServiceWatcher> watcher; |
| 1917 | + |
| 1918 | + QMetaObject::Connection callerDisconnectedConn; |
| 1919 | + |
| 1920 | + if (callerContext.isPeerMode()) { |
| 1921 | + callerDisconnectedConn = |
| 1922 | + connect(this, &PackageManager::CallerDisconnected, &loop, [&taskRef, &loop]() { |
| 1923 | + taskRef.updateState(linglong::api::types::v1::State::Canceled, "caller disconnected"); |
| 1924 | + loop.exit(1); |
| 1925 | + }); |
| 1926 | + |
| 1927 | + auto connected = callerContext.connection.connect("", |
| 1928 | + "/org/freedesktop/DBus/Local", |
| 1929 | + "org.freedesktop.DBus.Local", |
| 1930 | + "Disconnected", |
| 1931 | + this, |
| 1932 | + SLOT(onPeerDisconnected())); |
| 1933 | + if (!connected) { |
| 1934 | + LogW("failed to connect to Disconnected signal for peer mode"); |
| 1935 | + } |
| 1936 | + } else { |
| 1937 | + auto callerName = callerContext.callerBusName(); |
| 1938 | + if (!callerName.isEmpty()) { |
| 1939 | + watcher = |
| 1940 | + std::make_unique<QDBusServiceWatcher>(callerName, |
| 1941 | + callerContext.connection, |
| 1942 | + QDBusServiceWatcher::WatchForUnregistration); |
| 1943 | + connect(watcher.get(), |
| 1944 | + &QDBusServiceWatcher::serviceUnregistered, |
| 1945 | + &loop, |
| 1946 | + [&taskRef, &loop, callerName]() { |
| 1947 | + LogW("caller {} disconnected", callerName.toStdString()); |
| 1948 | + taskRef.updateState(linglong::api::types::v1::State::Canceled, |
| 1949 | + "caller disconnected"); |
| 1950 | + loop.exit(1); |
| 1951 | + }); |
| 1952 | + } |
| 1953 | + } |
| 1954 | + |
| 1955 | + auto replyConn = |
| 1956 | + connect(this, |
| 1957 | + &PackageManager::ReplyReceived, |
| 1958 | + &loop, |
| 1959 | + [&taskRef, &loop, objectPath](const QDBusObjectPath &replyObjectPath, |
| 1960 | + const QVariantMap &reply) { |
| 1961 | + if (replyObjectPath.path() != objectPath.path()) { |
| 1962 | + return; |
| 1963 | + } |
| 1964 | + |
| 1965 | + auto interactionReply = |
| 1966 | + common::serialize::fromQVariantMap<api::types::v1::InteractionReply>(reply); |
| 1967 | + if (!interactionReply || interactionReply->action != "yes") { |
| 1968 | + taskRef.updateState(linglong::api::types::v1::State::Canceled, "canceled"); |
| 1969 | + } |
| 1970 | + loop.exit(0); |
| 1971 | + }); |
| 1972 | + |
| 1973 | + auto timeoutConn = connect(&timeoutTimer, &QTimer::timeout, &loop, [&taskRef, &loop]() { |
| 1974 | + auto msg = fmt::format("task {} confirm timeout", taskRef.taskID()); |
| 1975 | + LogW(msg); |
| 1976 | + taskRef.updateState(linglong::api::types::v1::State::Canceled, msg); |
| 1977 | + loop.exit(1); |
| 1978 | + }); |
| 1979 | + |
| 1980 | + Q_EMIT RequestInteraction(objectPath, |
| 1981 | + static_cast<int>(msgType), |
| 1982 | + common::serialize::toQVariantMap(additionalMessage)); |
| 1983 | + |
| 1984 | + timeoutTimer.start(std::chrono::milliseconds{ 180000 }); |
| 1985 | + loop.exec(); |
| 1986 | + timeoutTimer.stop(); |
| 1987 | + |
| 1988 | + disconnect(replyConn); |
| 1989 | + disconnect(timeoutConn); |
| 1990 | + disconnect(callerDisconnectedConn); |
| 1991 | + |
| 1992 | + if (callerContext.isPeerMode()) { |
| 1993 | + callerContext.connection.disconnect("", |
| 1994 | + "/org/freedesktop/DBus/Local", |
| 1995 | + "org.freedesktop.DBus.Local", |
| 1996 | + "Disconnected", |
| 1997 | + this, |
| 1998 | + SLOT(onPeerDisconnected())); |
| 1999 | + } |
| 2000 | + |
| 2001 | + return !taskRef.isTaskDone(); |
| 2002 | +} |
| 2003 | + |
1890 | 2004 | // no-op for now |
1891 | 2005 | utils::error::Result<void> PackageManager::tryGenerateCache(const package::Reference &ref) noexcept |
1892 | 2006 | { |
|
0 commit comments