Files
amnezia-client/deploy/installer/qif/controlscript.js
Yaroslav Gurov 009ca981d5 feat: initial conan support and build process refactoring (#2260)
* feat: initial conan support

* feat: add awg-go and awg-apple recipes

* feat: macos full feature conan build, except ss and cloak

* feat: conan android initial support

* fix: android libssh fixes

* conan: android additional recipes and fixes

* feat: openvpn add support android

* fix: awg android connection establish

* conan: apple full-featured support

* chore: bump min macos version

* chore: get rid of manual deploy recursive copying

* conan: beautify makefile-based recipes

* conan: add geosite.dat and geoip.dat

* conan: use lib linking instead of QT_EXTRA_LIBS for OVPN

* conan: address lack of SONAME of libck-ovpn-plugin.so correctly

* conan: windows initial support

* conan: make awg-windows and wintun be interpret as exes

* conan: fix version for v2ray-rules-dat

* feat: conan and platform bootstrap rework in cmake

* feat: 16kb support for Android

* chore(conan): recipes cleanup

* feat: support of drivers for windows

* feat: support full-featured cmake install

* chore: exclude qtkeychain from the target build

* fix: install for apple systems

* fix: provide flags for cloak plugin for openvpn-pt-android

* chore: bump android deps for 16kb support

* feat(conan): patch cloak to properly provide env for golang

* chore: remove redundant hint from conan find

* feat: linux <-> conan features

* feat: linux initial packaging support

* feat: linux cpack support

* feat: cpack windows full-featured build

* feat: productbuild cpack support

* feat: rework CI/CD for macos

* feat: rework CI/CD for Linux

* fix: libncap automake args

* fix: CI/CD correct QT paths

* fix: windows rework CI/CD

* fix: windows artifact upload

* chore: remove MacOS-old from build targets

* feat: add conan to all mobile and NE builds

* feat: support default amnezia conan remote

* fix: use Release instead of release on Android

* feat: get rid of 3rd-prebuilt

* feat: conan CI/CD upload

* fix: CI/CD change windows toolset versions

* fix: remove MSVC version from CI/CD

* feat: conan CI/CD add Release and Debug build types

* feat: add multiple xcode versions for conan CI/CD

* fix: correct conan CI/CD clang versions

* feat: separate prebuilt baking, and add some for NE

* feat: rework keychain on ios/macos even more

* fix: add desktop Qt for iOS

* feat: add QT_HOST_PATH to build.sh

* fix: add deploy definition to cmake

* fix: android adjustments for toolchains and CI/CD

* fix: add needs for Android CI/CD

* fix: Android CI/CD use android-28

* fix: modernize translations, and CI/CD fixes

* fix: gradle min sdk compilation error

* fix: CI/CD add installers to all jobs

* fix: parse android platform more precisely

* fix: adjust aab path in CI/CD

* feat: CI/CD do not execute artifact build if there is nothing changed

* fix: CI/CD use common jobs even if previous were failed

* fix: Apple CI/CD use set-key-partition-list for keychains

* fix: Apple CI/CD do not specify any keychain (use default)

* fix: build aab as a different step in build script

* chore: beautify build.sh script

* feat: CI/CD build separate APKs per ABI

* fix: Android CI/CD upload artifact in separate steps

* chore: recipes cleanup

* feat: add hints for conan on MacOS

* fix: add main.cpp and tests back to CMakeLists.txt

* chore: xrayProtocol codestyle changes

* fix: openssl set proper X509 request version

* fix: make openvpn protocol rely only on client while configuring

* chore: get rid of old scripts

* chore: readme update describing build process more precisely

* feat: windows build script add multiprocessing capabilities

* chore: bump Qt version in README

* feat: add generator option and use Ninja by default in CI/CD for linux/macos

---------

Co-authored-by: NickVs2015 <nv@amnezia.org>
2026-05-04 22:59:24 +08:00

344 lines
11 KiB
JavaScript

var requestToQuitFromApp = false;
var updaterCompleted = 0;
var desktopAppProcessRunning = false;
var appInstalledUninstallerPath;
var appInstalledUninstallerPath_x86;
function appName()
{
return installer.value("Name");
}
function appExecutableFileName()
{
if (runningOnWindows()) {
return appName() + ".exe";
} else {
return appName();
}
}
function appInstalled()
{
if (runningOnWindows()) {
appInstalledUninstallerPath = installer.value("RootDir") + "Program Files/AmneziaVPN/maintenancetool.exe";
appInstalledUninstallerPath_x86 = installer.value("RootDir") + "Program Files (x86)/AmneziaVPN/maintenancetool.exe";
} else if (runningOnMacOS()){
appInstalledUninstallerPath = "/Applications/" + appName() + ".app/maintenancetool.app/Contents/MacOS/maintenancetool";
} else if (runningOnLinux()){
appInstalledUninstallerPath = "/opt/" + appName() + "/maintenancetool";
}
return installer.fileExists(appInstalledUninstallerPath) || installer.fileExists(appInstalledUninstallerPath_x86);
}
function endsWith(str, suffix)
{
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
function runningOnWindows()
{
return (installer.value("os") === "win");
}
function runningOnMacOS()
{
return (installer.value("os") === "mac");
}
function runningOnLinux()
{
return ((installer.value("os") === "linux") || (installer.value("os") === "x11"));
}
function sleep(milliseconds) {
var currentTime = new Date().getTime();
while (currentTime + milliseconds >= new Date().getTime()) {}
}
function raiseInstallerWindow()
{
if (!runningOnMacOS()) {
return;
}
var result = installer.execute("/bin/bash", ["-c", "ps -A | grep -m1 '" + appName() + "' | awk '{print $1}'"]);
if (Number(result[0]) > 0) {
var arg = 'tell application \"System Events\" ' +
'\n set frontmost of the first process whose unix id is ' + Number(result[0]) + ' to true ' +
'\n end tell' +
'\n ';
installer.execute("osascript", ["-e", arg]);
}
}
function appProcessIsRunning()
{
if (runningOnWindows()) {
var result = installer.execute("tasklist");
if ( Number(result[1]) === 0 ) {
if (result[0].indexOf(appExecutableFileName()) !== -1) {
return true;
}
}
} else {
return checkProcessIsRunning("pgrep -x '" + appName() + "'")
}
return false;
}
function checkProcessIsRunning(arg)
{
var cmdArgs = ["-c", arg];
var result = installer.execute("/bin/bash", cmdArgs);
var lines = result[0].trim().split(/\n+/);
var resultArg1 = Number(lines[0])
if (resultArg1 >= 2) {
return true;
}
return false;
}
function requestToQuit(installer,gui)
{
requestToQuitFromApp = true;
installer.setDefaultPageVisible(QInstaller.IntroductionPage, false);
installer.setDefaultPageVisible(QInstaller.TargetDirectory, false);
installer.setDefaultPageVisible(QInstaller.ComponentSelection, false);
installer.setDefaultPageVisible(QInstaller.LicenseCheck, false);
installer.setDefaultPageVisible(QInstaller.StartMenuSelection, false);
installer.setDefaultPageVisible(QInstaller.ReadyForInstallation, false);
installer.setDefaultPageVisible(QInstaller.PerformInstallation, false);
installer.setDefaultPageVisible(QInstaller.FinishedPage, false);
gui.clickButton(buttons.NextButton);
gui.clickButton(buttons.FinishButton);
gui.clickButton(buttons.CancelButton);
if (runningOnWindows()) {
installer.setCancelled();
}
}
Controller.prototype.PerformInstallationPageCallback = function()
{
gui.clickButton(buttons.NextButton);
}
Controller.prototype.LicenseAgreementPageCallback = function()
{
gui.clickButton(buttons.NextButton);
}
Controller.prototype.FinishedPageCallback = function ()
{
if (desktopAppProcessRunning) {
gui.clickButton(buttons.FinishButton);
} else if (installer.isUpdater()) {
installer.autoAcceptMessageBoxes();
gui.clickButton(buttons.FinishButton);
}
}
Controller.prototype.RestartPageCallback = function ()
{
updaterCompleted = 1;
gui.clickButton(buttons.FinishButton);
}
Controller.prototype.StartMenuDirectoryPageCallback = function()
{
gui.clickButton(buttons.NextButton);
}
Controller.prototype.ComponentSelectionPageCallback = function()
{
gui.clickButton(buttons.NextButton);
}
Controller.prototype.ReadyForInstallationPageCallback = function()
{
if (installer.isUpdater()) {
gui.clickButton(buttons.CommitButton);
}
}
Controller.prototype.TargetDirectoryPageCallback = function ()
{
var widget = gui.pageById(QInstaller.TargetDirectory);
if (widget !== null) {
widget.BrowseDirectoryButton.clicked.disconnect(onBrowseButtonClicked);
widget.BrowseDirectoryButton.clicked.connect(onBrowseButtonClicked);
gui.clickButton(buttons.NextButton);
}
}
Controller.prototype.IntroductionPageCallback = function ()
{
var widget = gui.currentPageWidget();
if (installer.isUpdater() && updaterCompleted === 1) {
gui.clickButton(buttons.FinishButton);
gui.clickButton(buttons.CancelButton);
return;
}
if (installer.isUninstaller()) {
if (widget !== null) {
widget.findChild("PackageManagerRadioButton").visible = false;
widget.findChild("UpdaterRadioButton").visible = false;
}
}
if (installer.isUpdater()) {
gui.clickButton(buttons.NextButton);
}
}
onBrowseButtonClicked = function()
{
var widget = gui.pageById(QInstaller.TargetDirectory);
if (widget !== null) {
if (runningOnWindows()) {
// On Windows we are appending \<APP_NAME> if selected path don't ends with <APP_NAME>
var targetDir = widget.TargetDirectoryLineEdit.text;
if (! endsWith(targetDir, appName())) {
targetDir = targetDir + "\\" + appName();
}
installer.setValue("TargetDir", targetDir);
widget.TargetDirectoryLineEdit.setText(installer.value("TargetDir"));
}
}
}
onNextButtonClicked = function()
{
var widget = gui.pageById(QInstaller.TargetDirectory);
if (widget !== null) {
installer.setValue("APP_BUNDLE_TARGET_DIR", widget.TargetDirectoryLineEdit.text);
}
}
function Controller () {
console.log("OS: %1, architecture: %2".arg(systemInfo.prettyProductName).arg(systemInfo.currentCpuArchitecture));
if (installer.isInstaller() || installer.isUpdater()) {
console.log("Check if app already installed: " + appInstalled());
}
if (runningOnWindows()) {
installer.setValue("AllUsers", "true");
}
if (installer.isInstaller()) {
installer.setDefaultPageVisible(QInstaller.ComponentSelection, false);
installer.setDefaultPageVisible(QInstaller.TargetDirectory, false);
installer.setDefaultPageVisible(QInstaller.StartMenuDirectoryPage, false);
installer.setDefaultPageVisible(QInstaller.LicenseCheck, false);
isDesktopAppProcessRunningMessageLoop();
if (requestToQuitFromApp === true) {
requestToQuit(installer, gui);
return;
}
if (runningOnMacOS()) {
installer.setMessageBoxAutomaticAnswer("OverwriteTargetDirectory", QMessageBox.Yes);
}
if (appInstalled()) {
if (QMessageBox.Ok === QMessageBox.information("os.information", appName(),
qsTr("The application is already installed.") + " " +
qsTr("We need to remove the old installation first. Do you wish to proceed?"),
QMessageBox.Ok | QMessageBox.Cancel)) {
if (appInstalled()) {
var resultArray = [];
if (installer.fileExists(appInstalledUninstallerPath_x86)) {
console.log("Starting uninstallation " + appInstalledUninstallerPath_x86);
resultArray = installer.execute(appInstalledUninstallerPath_x86);
}
if (installer.fileExists(appInstalledUninstallerPath)) {
console.log("Starting uninstallation " + appInstalledUninstallerPath);
resultArray = installer.execute(appInstalledUninstallerPath);
}
console.log("Uninstaller finished with code: " + resultArray[1])
if (Number(resultArray[1]) !== 0) {
console.log("Uninstallation aborted by user");
installer.setCancelled();
return;
} else {
for (var i = 0; i < 300; i++) {
sleep(100);
if (!installer.fileExists(appInstalledUninstallerPath)) {
break;
}
}
}
}
raiseInstallerWindow();
} else {
console.log("Request to quit from user");
installer.setCancelled();
return;
}
}
} else if (installer.isUninstaller()) {
isDesktopAppProcessRunningMessageLoop();
if (requestToQuitFromApp === true) {
requestToQuit(installer, gui);
return;
}
} else if (installer.isUpdater()) {
installer.setMessageBoxAutomaticAnswer("cancelInstallation", QMessageBox.No);
installer.installationFinished.connect(function() {
gui.clickButton(buttons.NextButton);
});
}
}
isDesktopAppProcessRunningMessageLoop = function ()
{
if (requestToQuitFromApp === true) {
return;
}
if (installer.isUpdater()) {
for (var i = 0; i < 400; i++) {
desktopAppProcessRunning = appProcessIsRunning();
if (!desktopAppProcessRunning) {
break;
}
}
}
desktopAppProcessRunning = appProcessIsRunning();
if (desktopAppProcessRunning) {
var result = QMessageBox.warning("QMessageBox", appName() + " installer",
appName() + " is active. Close the app and press \"Retry\" button to continue installation. Press \"Abort\" button to abort the installer and exit.",
QMessageBox.Retry | QMessageBox.Abort);
if (result === QMessageBox.Retry) {
isDesktopAppProcessRunningMessageLoop();
} else {
requestToQuitFromApp = true;
return;
}
}
}