diff --git a/src/developermodesettings.cpp b/src/developermodesettings.cpp index 5767eb7..8f12194 100644 --- a/src/developermodesettings.cpp +++ b/src/developermodesettings.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2013 – 2019 Jolla Ltd. - * Copyright (c) 2019 Open Mobile Platform LLC. + * Copyright (c) 2019 – 2020 Open Mobile Platform LLC. * Contact: Thomas Perl * Contact: Raine Makelainen * @@ -68,6 +68,9 @@ #define USB_MODED_CONFIG_IP "ip" #define USB_MODED_CONFIG_INTERFACE "interface" +/* Package which will move debug folder to /home/.system/usr/lib */ +#define DEBUG_HOME_PACKAGE "jolla-developer-mode-home-debug-location" + static QMap enumerate_network_interfaces() { QMap result; @@ -94,6 +97,17 @@ static QString get_cached_package(const QString &version) return dir.absoluteFilePath(preloaded.last()); } +namespace { + bool debugHomeFolderExists() + { + QDir pathDir("/home/.system/usr/lib/debug"); + if (pathDir.exists()) { + return true; + } + return false; + } +} + DeveloperModeSettings::DeveloperModeSettings(QObject *parent) : QObject(parent) , m_usbModeDaemon(USB_MODED_SERVICE, USB_MODED_PATH, USB_MODED_INTERFACE, QDBusConnection::systemBus()) @@ -109,6 +123,8 @@ DeveloperModeSettings::DeveloperModeSettings(QObject *parent) , m_refreshedForInstall(false) , m_localInstallFailed(false) , m_localDeveloperModePackagePath(get_cached_package(QStringLiteral("*"))) // Initialized to possibly incompatible package + , m_debugHomeEnabled(debugHomeFolderExists()) + , m_installationType(None) { // Resolve and update local package path if (!m_localDeveloperModePackagePath.isEmpty()) { @@ -173,6 +189,35 @@ bool DeveloperModeSettings::repositoryAccessRequired() const return m_localInstallFailed || m_localDeveloperModePackagePath.isEmpty(); } +bool DeveloperModeSettings::debugHomeEnabled() const +{ + return m_debugHomeEnabled; +} + +enum DeveloperModeSettings::InstallationType DeveloperModeSettings::installationType() const +{ + return m_installationType; +} + +QString DeveloperModeSettings::packageName() +{ + if (m_installationType == DeveloperMode) { + return DEVELOPER_MODE_PACKAGE; + } else if (m_installationType == DebugHome) { + return DEBUG_HOME_PACKAGE; + } else { + return QString(); + } +} + +void DeveloperModeSettings::setInstallationType(InstallationType type) +{ + if (m_installationType != type) { + m_installationType = type; + emit installationTypeChanged(); + } +} + void DeveloperModeSettings::setDeveloperMode(bool enabled) { if (m_developerModeEnabled != enabled) { @@ -182,6 +227,25 @@ void DeveloperModeSettings::setDeveloperMode(bool enabled) } m_refreshedForInstall = false; + setInstallationType(DeveloperMode); + if (enabled) { + resolveAndExecute(InstallCommand); + } else { + resolveAndExecute(RemoveCommand); + } + } +} + +void DeveloperModeSettings::moveDebugToHome(bool enabled) +{ + if (m_debugHomeEnabled != enabled) { + if (m_workStatus != Idle) { + qCWarning(lcDeveloperModeLog) << "Debug home state change requested during activity, ignored."; + return; + } + + m_refreshedForInstall = false; + setInstallationType(DebugHome); if (enabled) { resolveAndExecute(InstallCommand); } else { @@ -261,9 +325,9 @@ void DeveloperModeSettings::resolveAndExecute(Command command) { setWorkStatus(Preparing); m_workProgress = 0; - m_developerModePackageId.clear(); // might differ between installed/available + m_packageId.clear(); // might differ between installed/available - if (command == InstallCommand && !m_localInstallFailed && !m_localDeveloperModePackagePath.isEmpty()) { + if (command == InstallCommand && !m_localInstallFailed && !m_localDeveloperModePackagePath.isEmpty() && m_installationType == DeveloperMode) { // Resolve which version of developer mode package is expected PackageKit::Transaction *resolvePackage = PackageKit::Daemon::resolve(DEVELOPER_MODE_PACKAGE"-preload", PackageKit::Transaction::FilterInstalled); connect(resolvePackage, &PackageKit::Transaction::errorCode, this, &DeveloperModeSettings::reportTransactionErrorCode); @@ -303,71 +367,86 @@ void DeveloperModeSettings::resolveAndExecute(Command command) }); } else { - PackageKit::Transaction::Filters filters; - if (command == RemoveCommand) { - filters = PackageKit::Transaction::FilterInstalled; - } else { - filters = PackageKit::Transaction::FilterNewest; - } - PackageKit::Transaction *resolvePackage = PackageKit::Daemon::resolve(DEVELOPER_MODE_PACKAGE, filters); + // Install package form repos + installAndRemove(command); + } +} - connect(resolvePackage, &PackageKit::Transaction::errorCode, this, &DeveloperModeSettings::reportTransactionErrorCode); - connect(resolvePackage, &PackageKit::Transaction::package, - this, [this](PackageKit::Transaction::Info info, const QString &packageId, const QString &summary) { - qCDebug(lcDeveloperModeLog) << "Package transaction:" << info << packageId << "summary:" << summary; - m_developerModePackageId = packageId; - }); +bool DeveloperModeSettings::installAndRemove(Command command) +{ + if (packageName().isEmpty()) { + qCWarning(lcDeveloperModeLog) << "No installation package name set. Shouldn't happen."; + resetState(); + return false; + } - connect(resolvePackage, &PackageKit::Transaction::finished, - this, [this, command](PackageKit::Transaction::Exit status, uint runtime) { - Q_UNUSED(runtime) + PackageKit::Transaction::Filters filters; + if (command == RemoveCommand) { + filters = PackageKit::Transaction::FilterInstalled; + } else { + filters = PackageKit::Transaction::FilterNewest; + } - if (status != PackageKit::Transaction::ExitSuccess || m_developerModePackageId.isEmpty()) { - if (command == InstallCommand) { - if (m_refreshedForInstall) { - qCWarning(lcDeveloperModeLog) << "Failed to install developer mode, package didn't resolve."; - resetState(); - } else { - refreshPackageCacheAndInstall(); // try once if it helps - } - } else if (command == RemoveCommand) { - qCWarning(lcDeveloperModeLog) << "Removing developer mode but package didn't resolve into anything. Shouldn't happen."; - resetState(); - } + PackageKit::Transaction *resolvePackage = PackageKit::Daemon::resolve(packageName(), filters); - } else if (command == InstallCommand) { - PackageKit::Transaction *tx = PackageKit::Daemon::installPackage(m_developerModePackageId); - connectCommandSignals(tx); + connect(resolvePackage, &PackageKit::Transaction::errorCode, this, &DeveloperModeSettings::reportTransactionErrorCode); + connect(resolvePackage, &PackageKit::Transaction::package, + this, [this](PackageKit::Transaction::Info info, const QString &packageId, const QString &summary) { + qCDebug(lcDeveloperModeLog) << "Package transaction:" << info << packageId << "summary:" << summary; + m_packageId = packageId; + }); + connect(resolvePackage, &PackageKit::Transaction::finished, + this, [this, command](PackageKit::Transaction::Exit status, uint runtime) { + Q_UNUSED(runtime) + + if (status != PackageKit::Transaction::ExitSuccess || m_packageId.isEmpty()) { + if (command == InstallCommand) { if (m_refreshedForInstall) { - connect(tx, &PackageKit::Transaction::finished, - this, [this](PackageKit::Transaction::Exit status, uint runtime) { - qCDebug(lcDeveloperModeLog) << "Developer mode installation transaction done (with refresh):" << status << runtime; - resetState(); - }); + qCWarning(lcDeveloperModeLog) << "Failed to install, package didn't resolve."; + resetState(); } else { - connect(tx, &PackageKit::Transaction::finished, - this, [this](PackageKit::Transaction::Exit status, uint runtime) { - if (status == PackageKit::Transaction::ExitSuccess) { - qCDebug(lcDeveloperModeLog) << "Developer mode installation transaction done:" << status << runtime; - resetState(); - } else { - qCDebug(lcDeveloperModeLog) << "Developer mode installation failed, trying again after refresh"; - refreshPackageCacheAndInstall(); - } - }); + refreshPackageCacheAndInstall(); // try once if it helps } - } else { - PackageKit::Transaction *tx = PackageKit::Daemon::removePackage(m_developerModePackageId, true, true); - connectCommandSignals(tx); + } else if (command == RemoveCommand) { + qCWarning(lcDeveloperModeLog) << "Removing package but package didn't resolve into anything. Shouldn't happen."; + resetState(); + } + + } else if (command == InstallCommand) { + PackageKit::Transaction *tx = PackageKit::Daemon::installPackage(m_packageId); + connectCommandSignals(tx); + + if (m_refreshedForInstall) { connect(tx, &PackageKit::Transaction::finished, this, [this](PackageKit::Transaction::Exit status, uint runtime) { - qCDebug(lcDeveloperModeLog) << "Developer mode removal transaction done:" << status << runtime; + qCDebug(lcDeveloperModeLog) << "Installation transaction done (with refresh):" << status << runtime; resetState(); }); + } else { + connect(tx, &PackageKit::Transaction::finished, + this, [this](PackageKit::Transaction::Exit status, uint runtime) { + if (status == PackageKit::Transaction::ExitSuccess) { + qCDebug(lcDeveloperModeLog) << "Installation transaction done:" << status << runtime; + resetState(); + } else { + qCDebug(lcDeveloperModeLog) << "Installation failed, trying again after refresh"; + refreshPackageCacheAndInstall(); + } + }); } - }); - } + + } else { + PackageKit::Transaction *tx = PackageKit::Daemon::removePackage(m_packageId, true, true); + connectCommandSignals(tx); + connect(tx, &PackageKit::Transaction::finished, + this, [this](PackageKit::Transaction::Exit status, uint runtime) { + qCDebug(lcDeveloperModeLog) << "Package removal transaction done:" << status << runtime; + resetState(); + }); + } + }); + return true; } void DeveloperModeSettings::connectCommandSignals(PackageKit::Transaction *transaction) @@ -478,13 +557,21 @@ void DeveloperModeSettings::updateState(int percentage, PackageKit::Transaction: void DeveloperModeSettings::resetState() { - bool enabled = QFile::exists(DEVELOPER_MODE_PROVIDED_FILE); - if (m_developerModeEnabled != enabled) { - m_developerModeEnabled = enabled; - emit developerModeEnabledChanged(); + if (m_installationType == DeveloperMode) { + bool enabled = QFile::exists(DEVELOPER_MODE_PROVIDED_FILE); + if (m_developerModeEnabled != enabled) { + m_developerModeEnabled = enabled; + emit developerModeEnabledChanged(); + } + } else if (m_installationType == DebugHome) { + if (m_debugHomeEnabled != debugHomeFolderExists()) { + m_debugHomeEnabled = debugHomeFolderExists(); + emit debugHomeEnabledChanged(); + } } setWorkStatus(Idle); + setInstallationType(None); if (m_workProgress != PROGRESS_INDETERMINATE) { m_workProgress = PROGRESS_INDETERMINATE; diff --git a/src/developermodesettings.h b/src/developermodesettings.h index d5473f7..9acd635 100644 --- a/src/developermodesettings.h +++ b/src/developermodesettings.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2013 – 2019 Jolla Ltd. - * Copyright (c) 2019 Open Mobile Platform LLC. + * Copyright (c) 2019 – 2020 Open Mobile Platform LLC. * Contact: Thomas Perl * * You may use this file under the terms of the BSD license as follows: @@ -49,6 +49,7 @@ class SYSTEMSETTINGS_EXPORT DeveloperModeSettings : public QObject { Q_OBJECT Q_ENUMS(Status) + Q_ENUMS(InstallationType) Q_PROPERTY(QString wlanIpAddress READ wlanIpAddress NOTIFY wlanIpAddressChanged) Q_PROPERTY(QString usbIpAddress READ usbIpAddress NOTIFY usbIpAddressChanged) @@ -57,6 +58,8 @@ class SYSTEMSETTINGS_EXPORT DeveloperModeSettings : public QObject Q_PROPERTY(enum DeveloperModeSettings::Status workStatus READ workStatus NOTIFY workStatusChanged) Q_PROPERTY(int workProgress READ workProgress NOTIFY workProgressChanged) Q_PROPERTY(bool repositoryAccessRequired READ repositoryAccessRequired NOTIFY repositoryAccessRequiredChanged) + Q_PROPERTY(bool debugHomeEnabled READ debugHomeEnabled NOTIFY debugHomeEnabledChanged) + Q_PROPERTY(enum DeveloperModeSettings::InstallationType installationType READ installationType NOTIFY installationTypeChanged) public: explicit DeveloperModeSettings(QObject *parent = NULL); @@ -68,6 +71,11 @@ class SYSTEMSETTINGS_EXPORT DeveloperModeSettings : public QObject DownloadingPackages, InstallingPackages, RemovingPackages + }; + enum InstallationType { + None, + DeveloperMode, + DebugHome }; QString wlanIpAddress() const; @@ -77,10 +85,14 @@ class SYSTEMSETTINGS_EXPORT DeveloperModeSettings : public QObject enum DeveloperModeSettings::Status workStatus() const; int workProgress() const; bool repositoryAccessRequired() const; + bool debugHomeEnabled() const; + QString packageName(); + enum DeveloperModeSettings::InstallationType installationType() const; Q_INVOKABLE void setDeveloperMode(bool enabled); Q_INVOKABLE void setUsbIpAddress(const QString &usbIpAddress); Q_INVOKABLE void refresh(); + Q_INVOKABLE void moveDebugToHome(bool enabled); signals: void wlanIpAddressChanged(); @@ -89,6 +101,8 @@ class SYSTEMSETTINGS_EXPORT DeveloperModeSettings : public QObject void workStatusChanged(); void workProgressChanged(); void repositoryAccessRequiredChanged(); + void debugHomeEnabledChanged(); + void installationTypeChanged(); private slots: void reportTransactionErrorCode(PackageKit::Transaction::Error code, const QString &details); @@ -104,7 +118,9 @@ private slots: void setWorkStatus(Status status); void refreshPackageCacheAndInstall(); void resolveAndExecute(Command command); + bool installAndRemove(Command command); void connectCommandSignals(PackageKit::Transaction *transaction); + void setInstallationType(InstallationType type); QString usbModedGetConfig(const QString &key, const QString &fallback); void usbModedSetConfig(const QString &key, const QString &value); @@ -114,7 +130,7 @@ private slots: QString m_usbInterface; QString m_usbIpAddress; QString m_username; - QString m_developerModePackageId; + QString m_packageId; bool m_developerModeEnabled; DeveloperModeSettings::Status m_workStatus; int m_workProgress; @@ -123,8 +139,11 @@ private slots: bool m_refreshedForInstall; bool m_localInstallFailed; QString m_localDeveloperModePackagePath; + bool m_debugHomeEnabled; + DeveloperModeSettings::InstallationType m_installationType; }; Q_DECLARE_METATYPE(DeveloperModeSettings::Status) +Q_DECLARE_METATYPE(DeveloperModeSettings::InstallationType) #endif /* DEVELOPERMODESETTINGS_H */