refactor: more refactors, fixed previously introduced SingleApplication bug

This commit is contained in:
QxQ 2020-10-14 22:59:39 +08:00
parent 4cd00df503
commit 6dbf9968e1
10 changed files with 91 additions and 98 deletions

View File

@ -1 +1 @@
6001 6002

View File

@ -21,9 +21,8 @@ namespace Qv2ray
EXIT_NORMAL = 0, EXIT_NORMAL = 0,
EXIT_NEW_VERSION_TRIGGER = EXIT_NORMAL, EXIT_NEW_VERSION_TRIGGER = EXIT_NORMAL,
EXIT_SECONDARY_INSTANCE = EXIT_NORMAL, EXIT_SECONDARY_INSTANCE = EXIT_NORMAL,
EXIT_PREINITIALIZATION_FAILED = -1, EXIT_INITIALIZATION_FAILED = -1,
EXIT_PRECONDITION_FAILED = -2, EXIT_PRECONDITION_FAILED = -2,
EXIT_CRASHED = -9,
}; };
struct Qv2rayStartupArguments struct Qv2rayStartupArguments
@ -58,7 +57,6 @@ namespace Qv2ray
public: public:
Qv2ray::base::config::Qv2rayConfigObject *ConfigObject; Qv2ray::base::config::Qv2rayConfigObject *ConfigObject;
QString ConfigPath; QString ConfigPath;
Qv2rayExitReason ExitReason;
Qv2rayStartupArguments StartupArguments; Qv2rayStartupArguments StartupArguments;
public: public:
@ -68,9 +66,6 @@ namespace Qv2ray
public: public:
virtual QStringList GetAssetsPaths(const QString &dirName) const final; virtual QStringList GetAssetsPaths(const QString &dirName) const final;
// //
virtual bool Initialize() = 0;
virtual Qv2rayExitReason RunQv2ray() = 0;
//
virtual void MessageBoxWarn(QWidget *parent, const QString &title, const QString &text, MessageOpt button) = 0; virtual void MessageBoxWarn(QWidget *parent, const QString &title, const QString &text, MessageOpt button) = 0;
virtual void MessageBoxInfo(QWidget *parent, const QString &title, const QString &text, MessageOpt button) = 0; virtual void MessageBoxInfo(QWidget *parent, const QString &title, const QString &text, MessageOpt button) = 0;
virtual MessageOpt MessageBoxAsk(QWidget *parent, const QString &title, const QString &text, const QList<MessageOpt> &buttons) = 0; virtual MessageOpt MessageBoxAsk(QWidget *parent, const QString &title, const QString &text, const QList<MessageOpt> &buttons) = 0;

View File

@ -212,8 +212,8 @@ namespace Qv2ray::core::config
return false; return false;
} }
GlobalConfig.kernelConfig.KernelPath(QString(QV2RAY_DEFAULT_VCORE_PATH)); GlobalConfig.kernelConfig.KernelPath(QV2RAY_DEFAULT_VCORE_PATH);
GlobalConfig.kernelConfig.AssetsPath(QString(QV2RAY_DEFAULT_VASSETS_PATH)); GlobalConfig.kernelConfig.AssetsPath(QV2RAY_DEFAULT_VASSETS_PATH);
GlobalConfig.logLevel = 3; GlobalConfig.logLevel = 3;
GlobalConfig.uiConfig.language = QLocale::system().name(); GlobalConfig.uiConfig.language = QLocale::system().name();
GlobalConfig.defaultRouteConfig.dnsConfig.servers.append({ "1.1.1.1" }); GlobalConfig.defaultRouteConfig.dnsConfig.servers.append({ "1.1.1.1" });

View File

@ -15,7 +15,6 @@
#include "utils/QvHelpers.hpp" #include "utils/QvHelpers.hpp"
#include <QSslSocket>
#include <csignal> #include <csignal>
#ifndef Q_OS_WIN #ifndef Q_OS_WIN
@ -180,30 +179,6 @@ LONG WINAPI TopLevelExceptionHandler(PEXCEPTION_POINTERS)
} }
#endif #endif
void ProcessExitReason(Qv2rayExitReason reason)
{ // app.MessageBoxWarn(nullptr, app.tr("Cannot start Qv2ray"), app.tr("Qv2ray early initialization failed."));
// return QVEXIT_EARLY_SETUP_FAIL;
switch (reason)
{
case EXIT_CRASHED:
{
break;
}
case EXIT_NORMAL:
{
break;
}
case EXIT_PREINITIALIZATION_FAILED:
{
break;
}
case EXIT_PRECONDITION_FAILED:
{
break;
}
}
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
globalArgc = argc; globalArgc = argc;
@ -258,31 +233,22 @@ int main(int argc, char *argv[])
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true);
#endif #endif
// Check OpenSSL version for auto-update and subscriptions Qv2rayApplication app(argc, argv);
auto osslReqVersion = QSslSocket::sslLibraryBuildVersionString(); if (const auto list = app.CheckPrerequisites(); !list.isEmpty())
auto osslCurVersion = QSslSocket::sslLibraryVersionString();
LOG("Current OpenSSL version: " + osslCurVersion);
if (!QSslSocket::supportsSsl())
{ {
LOG("Required OpenSSL version: " + osslReqVersion); BootstrapMessageBox("Qv2ray Prerequisites Check Failed", list.join(NEWLINE));
LOG("OpenSSL library MISSING, Quitting."); return Qv2rayExitReason::EXIT_PRECONDITION_FAILED;
BootstrapMessageBox(QObject::tr("Dependency Missing"),
QObject::tr("Cannot find openssl libs") + NEWLINE +
QObject::tr("This could be caused by a missing of `openssl` package in your system.") + NEWLINE +
QObject::tr("If you are using an AppImage from Github Action, please report a bug.") + NEWLINE + //
NEWLINE + QObject::tr("Technical Details") + NEWLINE + //
"OSsl.Rq.V=" + osslReqVersion + NEWLINE + //
"OSsl.Cr.V=" + osslCurVersion);
BootstrapMessageBox(QObject::tr("Cannot start Qv2ray"), QObject::tr("Cannot start Qv2ray without OpenSSL"));
return -1;
} }
Qv2rayApplication app(argc, argv);
if (!app.Initialize()) if (!app.Initialize())
{ {
LOG("Qv2ray initialization failed:", app.ExitReason); const auto reason = app.GetExitReason();
ProcessExitReason(app.ExitReason); if (reason == EXIT_INITIALIZATION_FAILED)
{
BootstrapMessageBox("Qv2ray Initialization Failed", "PreInitialization Failed." NEWLINE "For more information, please see the log.");
LOG("Qv2ray initialization failed:", reason);
}
return reason;
} }
#ifndef Q_OS_WIN #ifndef Q_OS_WIN
@ -291,10 +257,11 @@ int main(int argc, char *argv[])
#endif #endif
app.RunQv2ray(); app.RunQv2ray();
if (app.ExitReason == EXIT_NEW_VERSION_TRIGGER) const auto reason = app.GetExitReason();
if (reason == EXIT_NEW_VERSION_TRIGGER)
{ {
LOG("Starting new version of Qv2ray: " + app.StartupArguments._qvNewVersionPath); LOG("Starting new version of Qv2ray: " + app.StartupArguments._qvNewVersionPath);
QProcess::startDetached(app.StartupArguments._qvNewVersionPath, {}); QProcess::startDetached(app.StartupArguments._qvNewVersionPath, {});
} }
return app.ExitReason; return reason;
} }

View File

@ -1,6 +1,8 @@
#include "Qv2rayPlatformApplication.hpp" #include "Qv2rayPlatformApplication.hpp"
#include "core/settings/SettingsBackend.hpp" #include "core/settings/SettingsBackend.hpp"
#include <QSslSocket>
#define QV_MODULE_NAME "PlatformApplication" #define QV_MODULE_NAME "PlatformApplication"
#ifdef QT_DEBUG #ifdef QT_DEBUG
@ -9,13 +11,42 @@ const static inline QString QV2RAY_URL_SCHEME = "qv2ray-debug";
const static inline QString QV2RAY_URL_SCHEME = "qv2ray"; const static inline QString QV2RAY_URL_SCHEME = "qv2ray";
#endif #endif
bool Qv2rayPlatformApplication::initializeInternal() QStringList Qv2rayPlatformApplication::CheckPrerequisites()
{
QStringList errors;
if (!QSslSocket::supportsSsl())
{
// Check OpenSSL version for auto-update and subscriptions
const auto osslReqVersion = QSslSocket::sslLibraryBuildVersionString();
const auto osslCurVersion = QSslSocket::sslLibraryVersionString();
LOG("Current OpenSSL version: " + osslCurVersion);
LOG("Required OpenSSL version: " + osslReqVersion);
errors << "Qv2ray cannot run without OpenSSL.";
errors << "This is usually caused by using the wrong version of OpenSSL";
errors << "Required=" + osslReqVersion + "Current=" + osslCurVersion;
}
return errors + checkPrerequisitesInternal();
}
bool Qv2rayPlatformApplication::Initialize()
{ {
QString errorMessage; QString errorMessage;
bool canContinue; bool canContinue;
auto hasError = parseCommandLine(&errorMessage, &canContinue); const auto hasError = parseCommandLine(&errorMessage, &canContinue);
if (hasError && !canContinue) if (hasError)
return false; {
LOG("Command line:" A(errorMessage));
if (!canContinue)
{
LOG("Fatal, Qv2ray cannot continue.");
return false;
}
else
{
LOG("Non-fatal error, continue starting up.");
}
}
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
const auto appPath = QDir::toNativeSeparators(applicationFilePath()); const auto appPath = QDir::toNativeSeparators(applicationFilePath());
const auto regPath = "HKEY_CURRENT_USER\\Software\\Classes\\" + QV2RAY_URL_SCHEME; const auto regPath = "HKEY_CURRENT_USER\\Software\\Classes\\" + QV2RAY_URL_SCHEME;
@ -37,15 +68,18 @@ bool Qv2rayPlatformApplication::initializeInternal()
if (isSecondary()) if (isSecondary())
{ {
StartupArguments.version = QV2RAY_VERSION_STRING; StartupArguments.version = QV2RAY_VERSION_STRING;
StartupArguments.buildVersion = QV2RAY_VERSION_BUILD;
StartupArguments.fullArgs = arguments(); StartupArguments.fullArgs = arguments();
if (StartupArguments.arguments.isEmpty()) if (StartupArguments.arguments.isEmpty())
StartupArguments.arguments << Qv2rayStartupArguments::NORMAL; StartupArguments.arguments << Qv2rayStartupArguments::NORMAL;
bool status = sendMessage(JsonToString(StartupArguments.toJson(), QJsonDocument::Compact).toUtf8()); bool status = sendMessage(JsonToString(StartupArguments.toJson(), QJsonDocument::Compact).toUtf8());
if (!status) if (!status)
LOG("Cannot send message."); LOG("Cannot send message.");
return true; SetExitReason(EXIT_SECONDARY_INSTANCE);
return false;
} }
#endif #endif
#ifdef QV2RAY_GUI #ifdef QV2RAY_GUI
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
@ -58,6 +92,7 @@ bool Qv2rayPlatformApplication::initializeInternal()
SaveGlobalSettings(); SaveGlobalSettings();
}); });
#endif #endif
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
SetCurrentDirectory(applicationDirPath().toStdWString().c_str()); SetCurrentDirectory(applicationDirPath().toStdWString().c_str());
// Set special font in Windows // Set special font in Windows
@ -71,12 +106,10 @@ bool Qv2rayPlatformApplication::initializeInternal()
// Install a default translater. From the OS/DE // Install a default translater. From the OS/DE
Qv2rayTranslator = std::make_unique<QvTranslator>(); Qv2rayTranslator = std::make_unique<QvTranslator>();
Qv2rayTranslator->InstallTranslation(QLocale::system().name()); Qv2rayTranslator->InstallTranslation(QLocale::system().name());
//
//
LocateConfiguration();
//
const auto allTranslations = Qv2rayTranslator->GetAvailableLanguages(); const auto allTranslations = Qv2rayTranslator->GetAvailableLanguages();
const auto osLanguage = QLocale::system().name(); const auto osLanguage = QLocale::system().name();
//
LocateConfiguration();
if (!allTranslations.contains(GlobalConfig.uiConfig.language)) if (!allTranslations.contains(GlobalConfig.uiConfig.language))
{ {
// If we need to reset the language. // If we need to reset the language.
@ -102,12 +135,12 @@ bool Qv2rayPlatformApplication::initializeInternal()
return true; return true;
} }
bool Qv2rayPlatformApplication::runInternal() Qv2rayExitReason Qv2rayPlatformApplication::RunQv2ray()
{ {
PluginHost = new QvPluginHost(); PluginHost = new QvPluginHost();
RouteManager = new RouteHandler(); RouteManager = new RouteHandler();
ConnectionManager = new QvConfigHandler(); ConnectionManager = new QvConfigHandler();
return true; return runQv2rayInternal();
} }
void Qv2rayPlatformApplication::quitInternal() void Qv2rayPlatformApplication::quitInternal()
@ -118,7 +151,7 @@ void Qv2rayPlatformApplication::quitInternal()
ConnectionManager->SaveConnectionConfig(); ConnectionManager->SaveConnectionConfig();
PluginHost->SavePluginSettings(); PluginHost->SavePluginSettings();
SaveGlobalSettings(); SaveGlobalSettings();
TerminateUI(); terminateUIInternal();
delete ConnectionManager; delete ConnectionManager;
delete RouteManager; delete RouteManager;
delete PluginHost; delete PluginHost;

View File

@ -51,21 +51,30 @@ class Qv2rayPlatformApplication
public: public:
Qv2rayPlatformApplication(int &argc, char *argv[]) : QVBASEAPPLICATION(QVBASEAPPLICATION_CTORARGS), Qv2rayApplicationInterface(){}; Qv2rayPlatformApplication(int &argc, char *argv[]) : QVBASEAPPLICATION(QVBASEAPPLICATION_CTORARGS), Qv2rayApplicationInterface(){};
virtual ~Qv2rayPlatformApplication(){}; virtual ~Qv2rayPlatformApplication(){};
inline void QuitApplication(int retCode = 0) virtual Qv2rayExitReason GetExitReason() const final
{ {
QCoreApplication::exit(retCode); return _exitReason;
} }
virtual QStringList CheckPrerequisites() final;
virtual bool Initialize() final;
virtual Qv2rayExitReason RunQv2ray() final;
protected: protected:
bool initializeInternal(); virtual QStringList checkPrerequisitesInternal() = 0;
bool runInternal(); virtual Qv2rayExitReason runQv2rayInternal() = 0;
void quitInternal(); virtual void terminateUIInternal() = 0;
virtual void TerminateUI() = 0; virtual void SetExitReason(Qv2rayExitReason r) final
{
_exitReason = r;
}
#ifndef QV2RAY_NO_SINGLEAPPLICATON #ifndef QV2RAY_NO_SINGLEAPPLICATON
virtual void onMessageReceived(quint32 clientId, QByteArray msg) = 0; virtual void onMessageReceived(quint32 clientId, QByteArray msg) = 0;
#endif #endif
private: private:
void quitInternal();
Qv2rayExitReason _exitReason;
bool parseCommandLine(QString *errorMessage, bool *canContinue); bool parseCommandLine(QString *errorMessage, bool *canContinue);
}; };

View File

@ -25,17 +25,12 @@ Qv2rayWidgetApplication::Qv2rayWidgetApplication(int &argc, char *argv[]) : Qv2r
{ {
} }
bool Qv2rayWidgetApplication::Initialize() QStringList Qv2rayWidgetApplication::checkPrerequisitesInternal()
{ {
const auto result = initializeInternal(); return {};
if (!result)
return false;
setQuitOnLastWindowClosed(false);
hTray = new QSystemTrayIcon();
return true;
} }
void Qv2rayWidgetApplication::TerminateUI() void Qv2rayWidgetApplication::terminateUIInternal()
{ {
delete mainWindow; delete mainWindow;
delete hTray; delete hTray;
@ -73,7 +68,7 @@ void Qv2rayWidgetApplication::onMessageReceived(quint32 clientId, QByteArray _ms
if (result == Yes) if (result == Yes)
{ {
StartupArguments._qvNewVersionPath = newPath; StartupArguments._qvNewVersionPath = newPath;
QuitApplication(EXIT_NEW_VERSION_TRIGGER); SetExitReason(EXIT_NEW_VERSION_TRIGGER);
} }
} }
@ -83,7 +78,8 @@ void Qv2rayWidgetApplication::onMessageReceived(quint32 clientId, QByteArray _ms
{ {
case Qv2rayStartupArguments::EXIT: case Qv2rayStartupArguments::EXIT:
{ {
QuitApplication(); SetExitReason(EXIT_NORMAL);
quit();
break; break;
} }
case Qv2rayStartupArguments::NORMAL: case Qv2rayStartupArguments::NORMAL:
@ -128,9 +124,10 @@ void Qv2rayWidgetApplication::onMessageReceived(quint32 clientId, QByteArray _ms
} }
#endif #endif
Qv2rayExitReason Qv2rayWidgetApplication::RunQv2ray() Qv2rayExitReason Qv2rayWidgetApplication::runQv2rayInternal()
{ {
runInternal(); setQuitOnLastWindowClosed(false);
hTray = new QSystemTrayIcon();
StyleManager = new QvStyleManager(); StyleManager = new QvStyleManager();
StyleManager->ApplyStyle(GlobalConfig.uiConfig.theme); StyleManager->ApplyStyle(GlobalConfig.uiConfig.theme);
// Show MainWindow // Show MainWindow

View File

@ -13,8 +13,6 @@ namespace Qv2ray
Q_OBJECT Q_OBJECT
public: public:
explicit Qv2rayWidgetApplication(int &argc, char *argv[]); explicit Qv2rayWidgetApplication(int &argc, char *argv[]);
bool Initialize() override;
Qv2rayExitReason RunQv2ray() override;
QJsonObject UIStates; QJsonObject UIStates;
public: public:
@ -31,8 +29,10 @@ namespace Qv2ray
} }
private: private:
QStringList checkPrerequisitesInternal() override;
Qv2rayExitReason runQv2rayInternal() override;
bool isInitialized; bool isInitialized;
void TerminateUI() override; void terminateUIInternal() override;
#ifndef QV2RAY_NO_SINGLEAPPLICATON #ifndef QV2RAY_NO_SINGLEAPPLICATON
void onMessageReceived(quint32 clientID, QByteArray msg) override; void onMessageReceived(quint32 clientID, QByteArray msg) override;
#endif #endif

View File

@ -484,7 +484,7 @@ void MainWindow::on_activatedTray(QSystemTrayIcon::ActivationReason reason)
void MainWindow::Action_Exit() void MainWindow::Action_Exit()
{ {
ConnectionManager->StopConnection(); ConnectionManager->StopConnection();
QvWidgetApplication->QuitApplication(); QvWidgetApplication->quit();
} }
void MainWindow::on_preferencesBtn_clicked() void MainWindow::on_preferencesBtn_clicked()

View File

@ -12,14 +12,6 @@ class QvTestApplication
{ {
public: public:
explicit QvTestApplication() : QCoreApplication(fakeArgc, fakeArgv), Qv2rayApplicationInterface(){}; explicit QvTestApplication() : QCoreApplication(fakeArgc, fakeArgv), Qv2rayApplicationInterface(){};
virtual bool Initialize() override
{
return true;
};
virtual Qv2rayExitReason RunQv2ray() override
{
return {};
};
virtual void MessageBoxWarn(QWidget *, const QString &, const QString &, MessageOpt) override{}; virtual void MessageBoxWarn(QWidget *, const QString &, const QString &, MessageOpt) override{};
virtual void MessageBoxInfo(QWidget *, const QString &, const QString &, MessageOpt) override{}; virtual void MessageBoxInfo(QWidget *, const QString &, const QString &, MessageOpt) override{};
virtual MessageOpt MessageBoxAsk(QWidget *, const QString &, const QString &, const QList<MessageOpt> &) override virtual MessageOpt MessageBoxAsk(QWidget *, const QString &, const QString &, const QList<MessageOpt> &) override