diff --git a/.gitmodules b/.gitmodules
index 971ddabe0..2cb2b72ee 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -2,3 +2,7 @@
path = 3rdparty/qrencode-win32
url = https://github.com/BlueDragon747/qrencode-win32.git
ignore = dirty
+[submodule "sparkle/Sparkle"]
+ path = sparkle/Sparkle
+ url = https://github.com/sparkle-project/Sparkle.git
+ ignore = dirty
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b9d94f24b..ca3b06c7b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -98,7 +98,6 @@ set(COMMON_SOURCES
${SRC_DIR}/accountlistmodel.cpp
${SRC_DIR}/networkmanager.cpp
${SRC_DIR}/instancemanager.cpp
- ${SRC_DIR}/updatemanager.cpp
${SRC_DIR}/main.cpp
${SRC_DIR}/smartlistmodel.cpp
${SRC_DIR}/utils.cpp
@@ -214,7 +213,9 @@ if(MSVC)
)
list(APPEND COMMON_SOURCES
- ${SRC_DIR}/connectivitymonitor.cpp)
+ ${SRC_DIR}/connectivitymonitor.cpp
+ ${SRC_DIR}/updatemanager.cpp
+ )
# preprocessor defines
add_definitions(-DUNICODE -DQT_NO_DEBUG -DNDEBUG)
@@ -269,7 +270,8 @@ elseif (NOT APPLE)
list(APPEND COMMON_SOURCES
${SRC_DIR}/xrectsel.c
${SRC_DIR}/dbuserrorhandler.cpp
- ${SRC_DIR}/connectivitymonitor.cpp)
+ ${SRC_DIR}/connectivitymonitor.cpp
+ ${SRC_DIR}/updatemanager.cpp)
list(APPEND COMMON_HEADERS
${SRC_DIR}/dbuserrorhandler.h
${SRC_DIR}/xrectsel.h)
@@ -348,10 +350,10 @@ elseif (NOT APPLE)
find_library(ringclient ringclient ${LRCLIBDIR} NO_DEFAULT_PATH)
find_library(qrencode qrencode)
find_library(X11 X11)
-else()
+else() # APPLE
list(APPEND COMMON_SOURCES
- ${SRC_DIR}/connectivitymonitor.mm)
- find_package(PkgConfig REQUIRED)
+ ${SRC_DIR}/os/macos/updatemanager.mm
+ ${SRC_DIR}/os/macos/connectivitymonitor.mm)
if(NOT DEFINED LRC)
if(EXISTS ${PROJECT_SOURCE_DIR}/../install/lrc)
set(LRC ${PROJECT_SOURCE_DIR}/../install/lrc)
@@ -388,9 +390,24 @@ else()
find_library(ringclient ringclient ${LRCLIBDIR} NO_DEFAULT_PATH)
find_library(SYSTEM_CONFIGURATUION SystemConfiguration)
- SET(myApp_ICON ${CMAKE_CURRENT_SOURCE_DIR}/resources/images/jami.icns)
- SET_SOURCE_FILES_PROPERTIES(${myApp_ICON} PROPERTIES
+ set(myApp_ICON ${CMAKE_CURRENT_SOURCE_DIR}/resources/images/jami.icns)
+ set_source_files_properties(${myApp_ICON} PROPERTIES
MACOSX_PACKAGE_LOCATION Resources)
+ if(ENABLE_SPARKLE)
+ message("Sparkle auto-update enabled")
+ find_library(SPARKLE_FRAMEWORK
+ NAMES Sparkle
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/sparkle)
+ add_definitions(-DENABLE_SPARKLE)
+ message("Sparkle is here:" ${SPARKLE_FRAMEWORK})
+ set(PUBLIC_KEY_PATH "${CMAKE_CURRENT_SOURCE_DIR}/sparkle/dsa_pub.pem")
+ set_source_files_properties(${PUBLIC_KEY_PATH} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
+ set(PUBLIC_KEY ${PUBLIC_KEY_PATH})
+ endif()
+ if(BETA)
+ message(STATUS "Beta config enabled")
+ add_definitions(-DBETA)
+ endif()
endif()
# Qt find package
@@ -607,12 +624,14 @@ elseif (NOT APPLE)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
else()
- target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/resources/images/jami.icns)
- target_link_libraries(${PROJECT_NAME} PRIVATE
- ${QT_LIBS}
- ${LRC_LIB_NAME}
- ${SYSTEM_CONFIGURATUION}
- qrencode)
+ set(resources ${CMAKE_CURRENT_SOURCE_DIR}/resources/images/jami.icns)
+ set(libs ${QT_LIBS} ${LRC_LIB_NAME} ${SYSTEM_CONFIGURATUION} qrencode)
+ if(ENABLE_SPARKLE)
+ set(resources ${resources} ${PUBLIC_KEY} ${SPARKLE_FRAMEWORK})
+ set(libs ${libs} ${SPARKLE_FRAMEWORK})
+ endif(ENABLE_SPARKLE)
+ target_sources(${PROJECT_NAME} PRIVATE ${resources})
+ target_link_libraries(${PROJECT_NAME} PRIVATE ${libs})
# translations
if(Qt${QT_VERSION_MAJOR}LinguistTools_FOUND)
@@ -636,21 +655,23 @@ else()
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/libringclient/translations)
endif()
set_target_properties(${PROJECT_NAME} PROPERTIES
- MACOSX_BUNDLE TRUE
- MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/resources/Info.plist"
- MACOSX_BUNDLE_EXECUTABLE_NAME "${PROJ_NAME}"
- MACOSX_BUNDLE_ICON_FILE "jami.icns"
- MACOSX_BUNDLE_GUI_IDENTIFIER "${BUNDLE_ID}"
- MACOSX_BUNDLE_BUNDLE_NAME "${PROJ_NAME}"
- MACOSX_BUNDLE_SHORT_VERSION_STRING "${JAMI_VERSION}"
- MACOSX_BUNDLE_BUNDLE_VERSION "${JAMI_BUILD}"
- MACOSX_BUNDLE_COPYRIGHT "${PROJ_COPYRIGHT}"
- XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/resources/entitlements/Jami.entitlements"
- XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME TRUE)
+ MACOSX_BUNDLE TRUE
+ MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/resources/Info.plist"
+ MACOSX_BUNDLE_EXECUTABLE_NAME "${PROJ_NAME}"
+ MACOSX_BUNDLE_ICON_FILE "jami.icns"
+ MACOSX_BUNDLE_GUI_IDENTIFIER "${BUNDLE_ID}"
+ MACOSX_BUNDLE_SHORT_VERSION_STRING "${JAMI_VERSION}"
+ MACOSX_BUNDLE_BUNDLE_VERSION "${JAMI_BUILD}"
+ MACOSX_BUNDLE_COPYRIGHT "${PROJ_COPYRIGHT}"
+ SPARKLE_URL "${SPARKLE_URL}"
+ XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/resources/entitlements/Jami.entitlements"
+ XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME TRUE)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -DQML_SRC_DIR=${SRC_DIR}
-DMAC_DEPLOY_QT_PATH=${CMAKE_PREFIX_PATH}/bin
-DEXE_NAME="${CMAKE_BINARY_DIR}/${PROJECT_NAME}.app"
+ -DSPARKLE_PATH=${SPARKLE_FRAMEWORK}
+ -DENABLE_SPARKLE=${ENABLE_SPARKLE}
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos_qt_deploy.cmake)
endif()
diff --git a/cmake/macos_qt_deploy.cmake b/cmake/macos_qt_deploy.cmake
index 5af951040..cf12292a0 100644
--- a/cmake/macos_qt_deploy.cmake
+++ b/cmake/macos_qt_deploy.cmake
@@ -1,5 +1,7 @@
-
- message("Qt deploying in dir " ${QML_SRC_DIR})
- execute_process(COMMAND "${MAC_DEPLOY_QT_PATH}/macdeployqt"
+message("Qt deploying in dir " ${QML_SRC_DIR})
+execute_process(COMMAND "${MAC_DEPLOY_QT_PATH}/macdeployqt"
${EXE_NAME}
-qmldir=${QML_SRC_DIR})
+if(${ENABLE_SPARKLE} MATCHES true)
+ file(COPY ${SPARKLE_PATH} DESTINATION ${EXE_NAME}/Contents/Frameworks/)
+endif()
\ No newline at end of file
diff --git a/resources/Info.plist b/resources/Info.plist
index 9ae6f7a74..6bc475055 100644
--- a/resources/Info.plist
+++ b/resources/Info.plist
@@ -2,39 +2,39 @@
- CFBundleDevelopmentRegion
- English
- CFBundleExecutable
- ${MACOSX_BUNDLE_EXECUTABLE_NAME}
- CFBundleIconFile
- ${MACOSX_BUNDLE_ICON_FILE}
- CFBundleIdentifier
- ${MACOSX_BUNDLE_GUI_IDENTIFIER}
- CFBundleName
- ${MACOSX_BUNDLE_BUNDLE_NAME}
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- ${MACOSX_BUNDLE_SHORT_VERSION_STRING}
- LSMinimumSystemVersion
- 10.13
- CFBundleVersion
- ${MACOSX_BUNDLE_BUNDLE_VERSION}
- CSResourcesFileMapped
-
- LSApplicationCategoryType
- public.app-category.social-networking
- LSRequiresCarbon
-
- NSHumanReadableCopyright
- ${MACOSX_BUNDLE_COPYRIGHT}
- NSHighResolutionCapable
- True
- NSCameraUsageDescription
- Jami requires to access your camera to make calls and record video
- NSMicrophoneUsageDescription
- Jami requires to access your microphone to make calls and record audio
- NSPhotoLibraryUsageDescription
- Jami requires to access your photo library to show image on profile and send via chat
+ CFBundleDevelopmentRegion
+ English
+ CFBundleExecutable
+ ${MACOSX_BUNDLE_EXECUTABLE_NAME}
+ CFBundleIconFile
+ ${MACOSX_BUNDLE_ICON_FILE}
+ CFBundleIdentifier
+ ${MACOSX_BUNDLE_GUI_IDENTIFIER}
+ CFBundleName
+ ${MACOSX_BUNDLE_EXECUTABLE_NAME}
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ ${MACOSX_BUNDLE_SHORT_VERSION_STRING}
+ LSMinimumSystemVersion
+ 10.13
+ CFBundleVersion
+ ${MACOSX_BUNDLE_BUNDLE_VERSION}
+ LSApplicationCategoryType
+ public.app-category.social-networking
+ NSHumanReadableCopyright
+ ${MACOSX_BUNDLE_COPYRIGHT}
+ SUPublicDSAKeyFile
+ dsa_pub.pem
+ SUFeedURL
+ ${SPARKLE_URL}
+ NSPrincipalClass
+ NSApplication
+ NSCameraUsageDescription
+ Jami requires to access your camera to make calls and record video
+ NSMicrophoneUsageDescription
+ Jami requires to access your microphone to make calls and record audio
+ NSPhotoLibraryUsageDescription
+ Jami requires to access your photo library to show image on profile and send via chat
diff --git a/resources/entitlements/Jami.entitlements b/resources/entitlements/Jami.entitlements
index 725c1ee5f..80ca05b1f 100644
--- a/resources/entitlements/Jami.entitlements
+++ b/resources/entitlements/Jami.entitlements
@@ -2,13 +2,13 @@
- com.apple.security.app-sandbox
-
com.apple.security.device.camera
- com.apple.security.device.microphone
+ com.apple.security.device.audio-input
com.apple.security.files.user-selected.read-write
+ com.apple.security.cs.allow-jit
+
diff --git a/sparkle/Sparkle b/sparkle/Sparkle
new file mode 160000
index 000000000..2195ee088
--- /dev/null
+++ b/sparkle/Sparkle
@@ -0,0 +1 @@
+Subproject commit 2195ee0883efc92828a0cf33b830f43f9bd7e01b
diff --git a/sparkle/dsa_pub.pem b/sparkle/dsa_pub.pem
new file mode 100644
index 000000000..97455e2f2
--- /dev/null
+++ b/sparkle/dsa_pub.pem
@@ -0,0 +1,36 @@
+-----BEGIN PUBLIC KEY-----
+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
+ZnO5P9x/rPIJLCXY4xQYBryQCMu6JC5ibWzP
+-----END PUBLIC KEY-----
diff --git a/sparkle/sign_update.sh b/sparkle/sign_update.sh
new file mode 100755
index 000000000..bb2fbab5e
--- /dev/null
+++ b/sparkle/sign_update.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+set -e
+set -o pipefail
+if [ "$#" -ne 2 ]; then
+ echo "Usage: $0 update_archive private_key"
+ exit 1
+fi
+
+openssl=/usr/bin/openssl
+$openssl dgst -sha1 -binary < "$1" | $openssl dgst -dss1 -sign "$2" | base64 $BASE64_OPTS
+
diff --git a/sparkle/sparkle-xml-updater.sh b/sparkle/sparkle-xml-updater.sh
new file mode 100755
index 000000000..62ca00323
--- /dev/null
+++ b/sparkle/sparkle-xml-updater.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+# Take the package to add as argument ./sparkle-xml-updater.sh jami.dmg
+
+REPO_FOLDER=$1
+SPARKLE_FILE=$2
+REPO_URL=$3
+PACKAGE=$4
+DSA_KEY=$5
+CHANNEL_NAME=$6
+VERSION=$7
+BUILD=$8
+
+if [ ! -f ${PACKAGE} -o ! -f ${DSA_KEY} ]; then
+ echo "Can't find package or dsa key, aborting..."
+ exit 1
+fi
+
+if [ -f ${REPO_FOLDER}/${SPARKLE_FILE} ]; then
+ ITEMS=$(sed -n "/- /,/<\/item>/p" ${REPO_FOLDER}/${SPARKLE_FILE})
+fi
+
+PACKAGE_SIZE=`stat -f%z ${PACKAGE}`
+DATE_RFC2822=`date "+%a, %d %b %Y %T %z"`
+
+cat << EOFILE > ${REPO_FOLDER}/${SPARKLE_FILE}
+
+
+
+ ${CHANNEL_NAME}
+ ${REPO_URL}/${SPARKLE_FILE}
+ Most recent changes with links to updates.
+ en
+
-
+ "${CHANNEL_NAME}-${BUILD}"
+ $DATE_RFC2822
+ ${BUILD}
+ ${VERSION}
+ 10.13
+
+
+$(echo -e "${ITEMS}")
+
+
+EOFILE
+
diff --git a/src/MainApplicationWindow.qml b/src/MainApplicationWindow.qml
index fa337d5ee..d03d75d08 100644
--- a/src/MainApplicationWindow.qml
+++ b/src/MainApplicationWindow.qml
@@ -155,9 +155,11 @@ ApplicationWindow {
windowSettingsLoaded = true
// Quiet check for updates on start if set to.
- if (UtilsAdapter.getAppValue(Settings.AutoUpdate)) {
- UpdateManager.checkForUpdates(true)
- UpdateManager.setAutoUpdateCheck(true)
+ if (Qt.platform.os.toString() !== "osx") {
+ if (UtilsAdapter.getAppValue(Settings.AutoUpdate)) {
+ UpdateManager.checkForUpdates(true)
+ UpdateManager.setAutoUpdateCheck(true)
+ }
}
// Handle a start URI if set as start option.
@@ -190,7 +192,7 @@ ApplicationWindow {
Connections {
target: {
- if (Qt.platform.os !== "windows" && Qt.platform.os !== "macos")
+ if (Qt.platform.os.toString() !== "windows" && Qt.platform.os.toString() !== "osx")
return DBusErrorHandler
return null
}
@@ -220,7 +222,7 @@ ApplicationWindow {
JamiQmlUtils.mainApplicationScreen = root.screen
- if (Qt.platform.os !== "windows" && Qt.platform.os !== "macos")
+ if (Qt.platform.os.toString() !== "windows" && Qt.platform.os.toString() !== "osx")
DBusErrorHandler.setActive(true)
}
}
diff --git a/src/connectivitymonitor.mm b/src/os/macos/connectivitymonitor.mm
similarity index 100%
rename from src/connectivitymonitor.mm
rename to src/os/macos/connectivitymonitor.mm
diff --git a/src/os/macos/updatemanager.mm b/src/os/macos/updatemanager.mm
new file mode 100644
index 000000000..3ff7dfae6
--- /dev/null
+++ b/src/os/macos/updatemanager.mm
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2021-2022 Savoir-faire Linux Inc.
+ * Author: Kateryna Kostiuk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "updatemanager.h"
+
+#ifdef ENABLE_SPARKLE
+#include
+#endif
+
+#ifdef BETA
+static constexpr bool isBeta = true;
+#else
+static constexpr bool isBeta = false;
+#endif
+
+#ifdef ENABLE_SPARKLE
+ struct UpdateManager::Impl
+{
+
+ Impl()
+ {
+ updaterController_ = [[SPUStandardUpdaterController alloc] initWithStartingUpdater: true
+ updaterDelegate: nil
+ userDriverDelegate: nil];
+ };
+
+ void checkForUpdates()
+ {
+ [updaterController_ checkForUpdates: nil];
+ };
+
+ void setAutoUpdateCheck(bool state)
+ {
+ updaterController_.updater.automaticallyChecksForUpdates = state;
+ };
+
+ bool isAutoUpdaterEnabled()
+ {
+ return updaterController_.updater.automaticallyChecksForUpdates;
+ };
+
+ bool isUpdaterEnabled() {
+ return true;
+ };
+
+ SPUStandardUpdaterController* updaterController_;
+
+};
+#else
+struct UpdateManager::Impl
+{
+ void checkForUpdates() {};
+
+ void setAutoUpdateCheck(bool state) {};
+
+ bool isAutoUpdaterEnabled()
+ {
+ return false;
+ };
+ bool isUpdaterEnabled()
+ {
+ return false;
+ };
+};
+#endif
+
+UpdateManager::UpdateManager(const QString& url,
+ ConnectivityMonitor* cm,
+ LRCInstance* instance,
+ QObject* parent)
+ : NetWorkManager(cm, parent)
+ , pimpl_(std::make_unique())
+{}
+
+UpdateManager::~UpdateManager()
+{}
+
+void
+UpdateManager::checkForUpdates(bool quiet)
+{
+ Q_UNUSED(quiet)
+ pimpl_->checkForUpdates();
+}
+
+void
+UpdateManager::applyUpdates(bool beta)
+{
+ Q_UNUSED(beta)
+}
+
+void
+UpdateManager::cancelUpdate()
+{}
+
+void
+UpdateManager::setAutoUpdateCheck(bool state)
+{
+ pimpl_->setAutoUpdateCheck(state);
+}
+
+bool
+UpdateManager::isCurrentVersionBeta()
+{
+ return isBeta;
+}
+
+bool
+UpdateManager::isUpdaterEnabled()
+{
+ return pimpl_->isUpdaterEnabled();
+}
+
+bool
+UpdateManager::isAutoUpdaterEnabled()
+{
+ return pimpl_->isAutoUpdaterEnabled();
+}
diff --git a/src/settingsview/components/GeneralSettingsPage.qml b/src/settingsview/components/GeneralSettingsPage.qml
index 478fda3ca..82f7a93a4 100644
--- a/src/settingsview/components/GeneralSettingsPage.qml
+++ b/src/settingsview/components/GeneralSettingsPage.qml
@@ -23,6 +23,7 @@ import net.jami.Models 1.1
import net.jami.Adapters 1.1
import net.jami.Enums 1.1
import net.jami.Constants 1.1
+import net.jami.Helpers 1.1
import "../../commoncomponents"
@@ -99,7 +100,7 @@ Rectangle {
Layout.leftMargin: JamiTheme.preferredMarginSize
Layout.rightMargin: JamiTheme.preferredMarginSize
Layout.bottomMargin: JamiTheme.preferredMarginSize
- visible: Qt.platform.os == "windows" ? true : false
+ visible: UpdateManager.isUpdaterEnabled()
}
}
}
diff --git a/src/settingsview/components/UpdateSettings.qml b/src/settingsview/components/UpdateSettings.qml
index af3bb96a1..f56530bc1 100644
--- a/src/settingsview/components/UpdateSettings.qml
+++ b/src/settingsview/components/UpdateSettings.qml
@@ -50,7 +50,9 @@ ColumnLayout {
Layout.fillWidth: true
Layout.leftMargin: JamiTheme.preferredMarginSize
- checked: UtilsAdapter.getAppValue(Settings.Key.AutoUpdate)
+ checked: Qt.platform.os.toString() === "windows" ?
+ UtilsAdapter.getAppValue(Settings.Key.AutoUpdate) :
+ UpdateManager.isAutoUpdaterEnabled()
labelText: JamiStrings.update
tooltipText: JamiStrings.enableAutoUpdates
@@ -84,7 +86,7 @@ ColumnLayout {
MaterialButton {
id: installBetaButton
- visible: !UpdateManager.isCurrentVersionBeta()
+ visible: !UpdateManager.isCurrentVersionBeta() && Qt.platform.os.toString() === "windows"
Layout.alignment: Qt.AlignHCenter
diff --git a/src/updatemanager.cpp b/src/updatemanager.cpp
index 59c7f1092..b9af40444 100644
--- a/src/updatemanager.cpp
+++ b/src/updatemanager.cpp
@@ -1,4 +1,4 @@
-/*!
+/*
* Copyright (C) 2020-2022 Savoir-faire Linux Inc.
* Author: Andreas Traczyk
*
@@ -38,31 +38,172 @@ static constexpr char betaVersionSubUrl[] = "/beta/version";
static constexpr char msiSubUrl[] = "/jami.release.x64.msi";
static constexpr char betaMsiSubUrl[] = "/beta/jami.beta.x64.msi";
+struct UpdateManager::Impl : public QObject
+{
+ Impl(const QString& url, ConnectivityMonitor* cm, LRCInstance* instance, UpdateManager& parent)
+ : QObject(nullptr)
+ , parent_(parent)
+ , lrcInstance_(instance)
+ , baseUrlString_(url.isEmpty() ? downloadUrl : url)
+ , tempPath_(Utils::WinGetEnv("TEMP"))
+ , updateTimer_(new QTimer(this))
+ {
+ connect(updateTimer_, &QTimer::timeout, [this] {
+ // Quiet period update check.
+ parent_.checkForUpdates(true);
+ });
+ };
+ ~Impl() = default;
+
+ void checkForUpdates(bool quiet)
+ {
+ parent_.disconnect();
+ // Fail without UI if this is a programmatic check.
+ if (!quiet)
+ connect(&parent_,
+ &NetWorkManager::errorOccured,
+ &parent_,
+ &UpdateManager::updateCheckErrorOccurred);
+
+ cleanUpdateFiles();
+ QUrl versionUrl {isBeta ? QUrl::fromUserInput(baseUrlString_ + betaVersionSubUrl)
+ : QUrl::fromUserInput(baseUrlString_ + versionSubUrl)};
+ parent_.get(versionUrl, [this, quiet](const QString& latestVersionString) {
+ if (latestVersionString.isEmpty()) {
+ qWarning() << "Error checking version";
+ if (!quiet)
+ Q_EMIT parent_.updateCheckReplyReceived(false);
+ return;
+ }
+ auto currentVersion = QString(VERSION_STRING).toULongLong();
+ auto latestVersion = latestVersionString.toULongLong();
+ qDebug() << "latest: " << latestVersion << " current: " << currentVersion;
+ if (latestVersion > currentVersion) {
+ qDebug() << "New version found";
+ Q_EMIT parent_.updateCheckReplyReceived(true, true);
+ } else {
+ qDebug() << "No new version found";
+ if (!quiet)
+ Q_EMIT parent_.updateCheckReplyReceived(true, false);
+ }
+ });
+ };
+
+ void applyUpdates(bool beta = false)
+ {
+ parent_.disconnect();
+ connect(&parent_,
+ &NetWorkManager::errorOccured,
+ &parent_,
+ &UpdateManager::updateDownloadErrorOccurred);
+ connect(&parent_, &NetWorkManager::statusChanged, [this](GetStatus status) {
+ switch (status) {
+ case GetStatus::STARTED:
+ connect(&parent_,
+ &NetWorkManager::downloadProgressChanged,
+ &parent_,
+ &UpdateManager::updateDownloadProgressChanged);
+ Q_EMIT parent_.updateDownloadStarted();
+ break;
+ case GetStatus::FINISHED:
+ Q_EMIT parent_.updateDownloadFinished();
+ break;
+ default:
+ break;
+ }
+ });
+
+ QUrl downloadUrl {(beta || isBeta) ? QUrl::fromUserInput(baseUrlString_ + betaMsiSubUrl)
+ : QUrl::fromUserInput(baseUrlString_ + msiSubUrl)};
+
+ parent_.get(
+ downloadUrl,
+ [this, downloadUrl](const QString&) {
+ lrcInstance_->finish();
+ Q_EMIT lrcInstance_->quitEngineRequested();
+ auto args = QString(" /passive /norestart WIXNONUILAUNCH=1");
+ QProcess process;
+ process.start("powershell ",
+ QStringList() << tempPath_ + "\\" + downloadUrl.fileName() << "/L*V"
+ << tempPath_ + "\\jami_x64_install.log" + args);
+ process.waitForFinished();
+ },
+ tempPath_);
+ };
+
+ void cancelUpdate()
+ {
+ parent_.cancelRequest();
+ };
+
+ void setAutoUpdateCheck(bool state)
+ {
+ // Quiet check for updates periodically, if set to.
+ if (!state) {
+ updateTimer_->stop();
+ return;
+ }
+ updateTimer_->start(updatePeriod);
+ };
+
+ void cleanUpdateFiles()
+ {
+ // Delete all logs and msi in the %TEMP% directory before launching.
+ QString dir = QString(Utils::WinGetEnv("TEMP"));
+ QDir log_dir(dir, {"jami*.log"});
+ for (const QString& filename : log_dir.entryList()) {
+ log_dir.remove(filename);
+ }
+ QDir msi_dir(dir, {"jami*.msi"});
+ for (const QString& filename : msi_dir.entryList()) {
+ msi_dir.remove(filename);
+ }
+ QDir version_dir(dir, {"version"});
+ for (const QString& filename : version_dir.entryList()) {
+ version_dir.remove(filename);
+ }
+ };
+
+ UpdateManager& parent_;
+
+ LRCInstance* lrcInstance_ {nullptr};
+ QString baseUrlString_;
+ QString tempPath_;
+ QTimer* updateTimer_;
+};
+
UpdateManager::UpdateManager(const QString& url,
ConnectivityMonitor* cm,
LRCInstance* instance,
QObject* parent)
: NetWorkManager(cm, parent)
- , lrcInstance_(instance)
- , baseUrlString_(url.isEmpty() ? downloadUrl : url)
- , tempPath_(Utils::WinGetEnv("TEMP"))
- , updateTimer_(new QTimer(this))
+ , pimpl_(std::make_unique(url, cm, instance, *this))
+{}
+
+UpdateManager::~UpdateManager() {}
+
+void
+UpdateManager::checkForUpdates(bool quiet)
{
- connect(updateTimer_, &QTimer::timeout, [this] {
- // Quiet period update check.
- checkForUpdates(true);
- });
+ pimpl_->checkForUpdates(quiet);
+}
+
+void
+UpdateManager::applyUpdates(bool beta)
+{
+ pimpl_->applyUpdates(beta);
+}
+
+void
+UpdateManager::cancelUpdate()
+{
+ pimpl_->cancelUpdate();
}
void
UpdateManager::setAutoUpdateCheck(bool state)
{
- // Quiet check for updates periodically, if set to.
- if (!state) {
- updateTimer_->stop();
- return;
- }
- updateTimer_->start(updatePeriod);
+ pimpl_->setAutoUpdateCheck(state);
}
bool
@@ -71,102 +212,17 @@ UpdateManager::isCurrentVersionBeta()
return isBeta;
}
-void
-UpdateManager::checkForUpdates(bool quiet)
+bool
+UpdateManager::isUpdaterEnabled()
{
- disconnect();
-
- // Fail without UI if this is a programmatic check.
- if (!quiet)
- connect(this, &NetWorkManager::errorOccured, this, &UpdateManager::updateCheckErrorOccurred);
-
- cleanUpdateFiles();
- QUrl versionUrl {isBeta ? QUrl::fromUserInput(baseUrlString_ + betaVersionSubUrl)
- : QUrl::fromUserInput(baseUrlString_ + versionSubUrl)};
- get(versionUrl, [this, quiet](const QString& latestVersionString) {
- if (latestVersionString.isEmpty()) {
- qWarning() << "Error checking version";
- if (!quiet)
- Q_EMIT updateCheckReplyReceived(false);
- return;
- }
- auto currentVersion = QString(VERSION_STRING).toULongLong();
- auto latestVersion = latestVersionString.toULongLong();
- qDebug() << "latest: " << latestVersion << " current: " << currentVersion;
- if (latestVersion > currentVersion) {
- qDebug() << "New version found";
- Q_EMIT updateCheckReplyReceived(true, true);
- } else {
- qDebug() << "No new version found";
- if (!quiet)
- Q_EMIT updateCheckReplyReceived(true, false);
- }
- });
+#ifdef Q_OS_WIN
+ return true;
+#endif
+ return false;
}
-void
-UpdateManager::applyUpdates(bool beta)
+bool
+UpdateManager::isAutoUpdaterEnabled()
{
- disconnect();
- connect(this, &NetWorkManager::errorOccured, this, &UpdateManager::updateDownloadErrorOccurred);
- connect(this, &NetWorkManager::statusChanged, [this](GetStatus status) {
- switch (status) {
- case GetStatus::STARTED:
- connect(this,
- &NetWorkManager::downloadProgressChanged,
- this,
- &UpdateManager::updateDownloadProgressChanged);
- Q_EMIT updateDownloadStarted();
- break;
- case GetStatus::FINISHED:
- Q_EMIT updateDownloadFinished();
- break;
- default:
- break;
- }
- });
-
- QUrl downloadUrl {(beta || isBeta) ? QUrl::fromUserInput(baseUrlString_ + betaMsiSubUrl)
- : QUrl::fromUserInput(baseUrlString_ + msiSubUrl)};
-
- get(
- downloadUrl,
- [this, downloadUrl](const QString&) {
- lrcInstance_->finish();
- Q_EMIT lrcInstance_->quitEngineRequested();
- auto args = QString(" /passive /norestart WIXNONUILAUNCH=1");
- QProcess process;
- process.start("powershell ",
- QStringList() << tempPath_ + "\\" + downloadUrl.fileName() << "/L*V"
- << tempPath_ + "\\jami_x64_install.log" + args);
- process.waitForFinished();
- },
- tempPath_);
-}
-
-void
-UpdateManager::cancelUpdate()
-{
- cancelRequest();
-}
-
-void
-UpdateManager::cleanUpdateFiles()
-{
- /*
- * Delete all logs and msi in the %TEMP% directory before launching.
- */
- QString dir = QString(Utils::WinGetEnv("TEMP"));
- QDir log_dir(dir, {"jami*.log"});
- for (const QString& filename : log_dir.entryList()) {
- log_dir.remove(filename);
- }
- QDir msi_dir(dir, {"jami*.msi"});
- for (const QString& filename : msi_dir.entryList()) {
- msi_dir.remove(filename);
- }
- QDir version_dir(dir, {"version"});
- for (const QString& filename : version_dir.entryList()) {
- version_dir.remove(filename);
- }
+ return false;
}
diff --git a/src/updatemanager.h b/src/updatemanager.h
index d506a542c..cf8279c12 100644
--- a/src/updatemanager.h
+++ b/src/updatemanager.h
@@ -1,4 +1,4 @@
-/*!
+/*
* Copyright (C) 2020-2022 Savoir-faire Linux Inc.
* Author: Andreas Traczyk
*
@@ -20,25 +20,29 @@
#include "networkmanager.h"
+#include
+
class LRCInstance;
class ConnectivityMonitor;
-class QTimer;
class UpdateManager final : public NetWorkManager
{
Q_OBJECT
+ Q_DISABLE_COPY(UpdateManager)
public:
explicit UpdateManager(const QString& url,
ConnectivityMonitor* cm,
LRCInstance* instance = nullptr,
QObject* parent = nullptr);
- ~UpdateManager() = default;
+ ~UpdateManager();
Q_INVOKABLE void checkForUpdates(bool quiet = false);
Q_INVOKABLE void applyUpdates(bool beta = false);
Q_INVOKABLE void cancelUpdate();
Q_INVOKABLE void setAutoUpdateCheck(bool state);
Q_INVOKABLE bool isCurrentVersionBeta();
+ Q_INVOKABLE bool isUpdaterEnabled();
+ Q_INVOKABLE bool isAutoUpdaterEnabled();
Q_SIGNALS:
void updateCheckReplyReceived(bool ok, bool found = false);
@@ -50,13 +54,7 @@ Q_SIGNALS:
void appCloseRequested();
private:
- // LRCInstance pointer
- LRCInstance* lrcInstance_ {nullptr};
-
- QString baseUrlString_;
- QString tempPath_;
- QTimer* updateTimer_;
-
- void cleanUpdateFiles();
+ struct Impl;
+ std::unique_ptr pimpl_;
};
Q_DECLARE_METATYPE(UpdateManager*)