mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-04-21 21:52:03 +02:00
updater: add sparkle
- add sparkle submodule - add an option to enable sparkle - modify entitlements - cleanup Info.plist Gitlab: #578 Change-Id: I7f562112a72a33e008ab316479fbaa68dc0e07f1
This commit is contained in:
parent
6b7c25054d
commit
298493169c
16 changed files with 505 additions and 193 deletions
4
.gitmodules
vendored
4
.gitmodules
vendored
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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()
|
|
@ -2,39 +2,39 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.13</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
|
||||
<key>CSResourcesFileMapped</key>
|
||||
<true/>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.social-networking</string>
|
||||
<key>LSRequiresCarbon</key>
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>True</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Jami requires to access your camera to make calls and record video</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Jami requires to access your microphone to make calls and record audio</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>Jami requires to access your photo library to show image on profile and send via chat</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.13</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.social-networking</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
|
||||
<key>SUPublicDSAKeyFile</key>
|
||||
<string>dsa_pub.pem</string>
|
||||
<key>SUFeedURL</key>
|
||||
<string>${SPARKLE_URL}</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Jami requires to access your camera to make calls and record video</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Jami requires to access your microphone to make calls and record audio</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>Jami requires to access your photo library to show image on profile and send via chat</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.device.camera</key>
|
||||
<true/>
|
||||
<key>com.apple.security.device.microphone</key>
|
||||
<key>com.apple.security.device.audio-input</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
1
sparkle/Sparkle
Submodule
1
sparkle/Sparkle
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 2195ee0883efc92828a0cf33b830f43f9bd7e01b
|
36
sparkle/dsa_pub.pem
Normal file
36
sparkle/dsa_pub.pem
Normal file
|
@ -0,0 +1,36 @@
|
|||
-----BEGIN PUBLIC KEY-----
|
||||
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
|
||||
ZnO5P9x/rPIJLCXY4xQYBryQCMu6JC5ibWzP
|
||||
-----END PUBLIC KEY-----
|
11
sparkle/sign_update.sh
Executable file
11
sparkle/sign_update.sh
Executable file
|
@ -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
|
||||
|
46
sparkle/sparkle-xml-updater.sh
Executable file
46
sparkle/sparkle-xml-updater.sh
Executable file
|
@ -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>/,/<\/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}
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<channel>
|
||||
<title>${CHANNEL_NAME}</title>
|
||||
<link>${REPO_URL}/${SPARKLE_FILE}</link>
|
||||
<description>Most recent changes with links to updates.</description>
|
||||
<language>en</language>
|
||||
<item>
|
||||
<title>"${CHANNEL_NAME}-${BUILD}"</title>
|
||||
<pubDate>$DATE_RFC2822</pubDate>
|
||||
<sparkle:version>${BUILD}</sparkle:version>
|
||||
<sparkle:shortVersionString>${VERSION}</sparkle:shortVersionString>
|
||||
<sparkle:minimumSystemVersion>10.13</sparkle:minimumSystemVersion>
|
||||
<enclosure url="${REPO_URL}/$(basename ${PACKAGE})" length="$PACKAGE_SIZE" type="application/octet-stream" sparkle:dsaSignature="$(./sign_update.sh ${PACKAGE} ${DSA_KEY})" />
|
||||
</item>
|
||||
$(echo -e "${ITEMS}")
|
||||
</channel>
|
||||
</rss>
|
||||
EOFILE
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
132
src/os/macos/updatemanager.mm
Normal file
132
src/os/macos/updatemanager.mm
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Copyright (C) 2021-2022 Savoir-faire Linux Inc.
|
||||
* Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "updatemanager.h"
|
||||
|
||||
#ifdef ENABLE_SPARKLE
|
||||
#include <Sparkle/Sparkle.h>
|
||||
#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<Impl>())
|
||||
{}
|
||||
|
||||
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();
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*!
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Savoir-faire Linux Inc.
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
*
|
||||
|
@ -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<Impl>(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;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*!
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Savoir-faire Linux Inc.
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
*
|
||||
|
@ -20,25 +20,29 @@
|
|||
|
||||
#include "networkmanager.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
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<Impl> pimpl_;
|
||||
};
|
||||
Q_DECLARE_METATYPE(UpdateManager*)
|
||||
|
|
Loading…
Add table
Reference in a new issue