Files
amnezia-client/client/amnezia_application.cpp
T

365 lines
14 KiB
C++
Raw Normal View History

2022-08-25 12:47:02 +03:00
#include "amnezia_application.h"
#include <QClipboard>
2022-08-25 12:47:02 +03:00
#include <QFontDatabase>
#include <QMimeData>
#include <QQuickStyle>
#include <QResource>
#include <QStandardPaths>
#include <QTextDocument>
2022-08-25 12:47:02 +03:00
#include <QTimer>
#include <QTranslator>
2023-09-06 22:20:59 +05:00
#include <QQuickItem>
#include "logger.h"
2023-05-16 07:34:06 +07:00
#include "version.h"
2022-08-25 12:47:02 +03:00
#include "platforms/ios/QRCodeReaderBase.h"
#if defined(Q_OS_ANDROID)
#include "platforms/android/android_controller.h"
#endif
2022-08-25 12:47:02 +03:00
2023-07-15 14:19:48 -07:00
#include "protocols/qml_register_protocols.h"
2022-08-25 12:47:02 +03:00
2022-08-26 03:19:34 -07:00
#if defined(Q_OS_IOS)
2023-08-28 22:03:28 +03:00
#include "platforms/ios/ios_controller.h"
2022-08-26 03:19:34 -07:00
#endif
2022-08-25 12:47:02 +03:00
2022-08-26 00:35:03 +03:00
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
AmneziaApplication::AmneziaApplication(int &argc, char *argv[]) : AMNEZIA_BASE_CLASS(argc, argv)
2022-08-26 00:35:03 +03:00
#else
AmneziaApplication::AmneziaApplication(int &argc, char *argv[], bool allowSecondary, SingleApplication::Options options,
int timeout, const QString &userData)
: SingleApplication(argc, argv, allowSecondary, options, timeout, userData)
2022-08-26 00:35:03 +03:00
#endif
2022-08-25 12:47:02 +03:00
{
setQuitOnLastWindowClosed(false);
// Fix config file permissions
2023-08-16 08:08:08 -07:00
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
{
QSettings s(ORGANIZATION_NAME, APPLICATION_NAME);
s.setValue("permFixed", true);
}
QString configLoc1 = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).first() + "/"
+ ORGANIZATION_NAME + "/" + APPLICATION_NAME + ".conf";
QFile::setPermissions(configLoc1, QFileDevice::ReadOwner | QFileDevice::WriteOwner);
QString configLoc2 = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).first() + "/"
+ ORGANIZATION_NAME + "/" + APPLICATION_NAME + "/" + APPLICATION_NAME + ".conf";
QFile::setPermissions(configLoc2, QFileDevice::ReadOwner | QFileDevice::WriteOwner);
#endif
2022-08-25 12:47:02 +03:00
m_settings = std::shared_ptr<Settings>(new Settings);
}
AmneziaApplication::~AmneziaApplication()
{
m_vpnConnectionThread.quit();
m_vpnConnectionThread.wait(3000);
2023-08-09 18:17:29 +05:00
2022-08-31 16:54:46 +03:00
if (m_engine) {
QObject::disconnect(m_engine, 0, 0, 0);
2022-08-31 16:54:46 +03:00
delete m_engine;
}
2022-08-25 12:47:02 +03:00
}
void AmneziaApplication::init()
{
m_engine = new QQmlApplicationEngine;
const QUrl url(QStringLiteral("qrc:/ui/qml/main2.qml"));
QObject::connect(
m_engine, &QQmlApplicationEngine::objectCreated, this,
[url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
},
Qt::QueuedConnection);
2022-08-25 12:47:02 +03:00
2022-12-28 13:41:45 +03:00
m_engine->rootContext()->setContextProperty("Debug", &Logger::Instance());
2023-06-13 20:03:20 +09:00
m_configurator = std::shared_ptr<VpnConfigurator>(new VpnConfigurator(m_settings, this));
m_vpnConnection.reset(new VpnConnection(m_settings, m_configurator));
2023-08-09 18:17:29 +05:00
m_vpnConnection->moveToThread(&m_vpnConnectionThread);
m_vpnConnectionThread.start();
initModels();
loadTranslator();
initControllers();
#ifdef Q_OS_ANDROID
connect(AndroidController::instance(), &AndroidController::initialized, this,
[this](bool status, bool connected, const QDateTime &connectionDate) {
if (connected) {
m_connectionController->onConnectionStateChanged(Vpn::ConnectionState::Connected);
if (m_vpnConnection)
m_vpnConnection->restoreConnection();
}
});
if (!AndroidController::instance()->initialize()) {
qCritical() << QString("Init failed");
if (m_vpnConnection)
emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Error);
return;
}
connect(AndroidController::instance(), &AndroidController::importConfigFromOutside, [this](QString data) {
m_pageController->replaceStartPage();
m_importController->extractConfigFromData(data);
m_pageController->goToPageViewConfig();
});
2023-08-28 22:03:28 +03:00
#endif
#ifdef Q_OS_IOS
2023-08-27 10:46:41 -07:00
IosController::Instance()->initialize();
connect(IosController::Instance(), &IosController::importConfigFromOutside, [this](QString data) {
m_pageController->replaceStartPage();
m_importController->extractConfigFromData(data);
m_pageController->goToPageViewConfig();
});
connect(IosController::Instance(), &IosController::importBackupFromOutside, [this](QString filePath) {
m_pageController->replaceStartPage();
m_pageController->goToPageSettingsBackup();
m_settingsController->importBackupFromOutside(filePath);
});
#endif
2023-07-14 13:14:50 +09:00
m_notificationHandler.reset(NotificationHandler::create(nullptr));
connect(m_vpnConnection.get(), &VpnConnection::connectionStateChanged, m_notificationHandler.get(),
&NotificationHandler::setConnectionState);
connect(m_notificationHandler.get(), &NotificationHandler::raiseRequested, m_pageController.get(),
&PageController::raiseMainWindow);
2023-07-14 13:14:50 +09:00
connect(m_notificationHandler.get(), &NotificationHandler::connectRequested, m_connectionController.get(),
&ConnectionController::openConnection);
connect(m_notificationHandler.get(), &NotificationHandler::disconnectRequested, m_connectionController.get(),
&ConnectionController::closeConnection);
2023-10-06 13:43:32 +08:00
connect(this, &AmneziaApplication::translationsUpdated, m_notificationHandler.get(), &NotificationHandler::onTranslationsUpdated);
2023-07-14 13:14:50 +09:00
2022-08-25 12:47:02 +03:00
m_engine->load(url);
2023-09-06 22:20:59 +05:00
m_systemController->setQmlRoot(m_engine->rootObjects().value(0));
2022-08-25 12:47:02 +03:00
if (m_settings->isSaveLogs()) {
2022-12-28 13:41:45 +03:00
if (!Logger::init()) {
2022-08-25 12:47:02 +03:00
qWarning() << "Initialization of debug subsystem failed";
}
}
2023-08-24 14:53:52 +05:00
#ifdef Q_OS_WIN
if (m_parser.isSet("a"))
m_pageController->showOnStartup();
else
emit m_pageController->raiseMainWindow();
#else
m_pageController->showOnStartup();
#endif
// TODO - fix
2023-08-08 19:10:14 +05:00
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
if (isPrimary()) {
QObject::connect(this, &SingleApplication::instanceStarted, m_pageController.get(), [this]() {
qDebug() << "Secondary instance started, showing this window instead";
emit m_pageController->raiseMainWindow();
});
}
#endif
2022-08-29 01:32:42 +03:00
// Android TextField clipboard workaround
// https://bugreports.qt.io/browse/QTBUG-113461
#ifdef Q_OS_ANDROID
2023-08-31 16:00:41 +05:00
QObject::connect(qApp, &QGuiApplication::applicationStateChanged, [](Qt::ApplicationState state) {
if (state == Qt::ApplicationActive) {
if (qApp->clipboard()->mimeData()->formats().contains("text/html")) {
QTextDocument doc;
doc.setHtml(qApp->clipboard()->mimeData()->html());
qApp->clipboard()->setText(doc.toPlainText());
}
}
});
#endif
2022-08-25 12:47:02 +03:00
}
void AmneziaApplication::registerTypes()
{
qRegisterMetaType<ServerCredentials>("ServerCredentials");
qRegisterMetaType<DockerContainer>("DockerContainer");
qRegisterMetaType<TransportProto>("TransportProto");
qRegisterMetaType<Proto>("Proto");
qRegisterMetaType<ServiceType>("ServiceType");
declareQmlProtocolEnum();
declareQmlContainerEnum();
qmlRegisterType<QRCodeReader>("QRCodeReader", 1, 0, "QRCodeReader");
m_containerProps.reset(new ContainerProps());
qmlRegisterSingletonInstance("ContainerProps", 1, 0, "ContainerProps", m_containerProps.get());
2022-08-25 12:47:02 +03:00
m_protocolProps.reset(new ProtocolProps());
qmlRegisterSingletonInstance("ProtocolProps", 1, 0, "ProtocolProps", m_protocolProps.get());
2023-05-14 21:11:19 +08:00
qmlRegisterSingletonType(QUrl("qrc:/ui/qml/Filters/ContainersModelFilters.qml"), "ContainersModelFilters", 1, 0,
"ContainersModelFilters");
2023-05-14 21:11:19 +08:00
//
Vpn::declareQmlVpnConnectionStateEnum();
2023-05-15 13:38:17 +08:00
PageLoader::declareQmlPageEnum();
2022-08-25 12:47:02 +03:00
}
void AmneziaApplication::loadFonts()
{
2022-12-18 18:07:32 +03:00
QQuickStyle::setStyle("Basic");
QFontDatabase::addApplicationFont(":/fonts/pt-root-ui_vf.ttf");
2022-08-25 12:47:02 +03:00
}
void AmneziaApplication::loadTranslator()
{
auto locale = m_settings->getAppLanguage();
m_translator.reset(new QTranslator());
2023-09-28 23:21:13 +08:00
updateTranslator(locale);
2022-08-25 12:47:02 +03:00
}
2023-09-28 23:21:13 +08:00
void AmneziaApplication::updateTranslator(const QLocale &locale)
{
2023-09-28 23:21:13 +08:00
if (!m_translator->isEmpty()) {
QCoreApplication::removeTranslator(m_translator.get());
}
2023-09-30 17:36:06 +08:00
QString strFileName = QString(":/translations/amneziavpn")+QLatin1String("_")+locale.name()+".qm";
if (m_translator->load(strFileName)) {
if (QCoreApplication::installTranslator(m_translator.get())) {
m_settings->setAppLanguage(locale);
}
} else {
m_settings->setAppLanguage(QLocale::English);
}
m_engine->retranslate();
emit translationsUpdated();
}
2022-08-31 16:54:46 +03:00
bool AmneziaApplication::parseCommands()
2022-08-25 12:47:02 +03:00
{
m_parser.setApplicationDescription(APPLICATION_NAME);
m_parser.addHelpOption();
m_parser.addVersionOption();
QCommandLineOption c_autostart { { "a", "autostart" }, "System autostart" };
2022-08-25 12:47:02 +03:00
m_parser.addOption(c_autostart);
QCommandLineOption c_cleanup { { "c", "cleanup" }, "Cleanup logs" };
2022-08-25 12:47:02 +03:00
m_parser.addOption(c_cleanup);
m_parser.process(*this);
if (m_parser.isSet(c_cleanup)) {
2022-12-28 13:41:45 +03:00
Logger::cleanUp();
QTimer::singleShot(100, this, [this] { quit(); });
2022-08-25 12:47:02 +03:00
exec();
2022-08-31 16:54:46 +03:00
return false;
2022-08-25 12:47:02 +03:00
}
2022-08-31 16:54:46 +03:00
return true;
2022-08-25 12:47:02 +03:00
}
2022-08-29 01:32:42 +03:00
QQmlApplicationEngine *AmneziaApplication::qmlEngine() const
{
return m_engine;
}
void AmneziaApplication::initModels()
{
m_containersModel.reset(new ContainersModel(m_settings, this));
m_engine->rootContext()->setContextProperty("ContainersModel", m_containersModel.get());
m_serversModel.reset(new ServersModel(m_settings, this));
m_engine->rootContext()->setContextProperty("ServersModel", m_serversModel.get());
connect(m_serversModel.get(), &ServersModel::currentlyProcessedServerIndexChanged, m_containersModel.get(),
&ContainersModel::setCurrentlyProcessedServerIndex);
m_languageModel.reset(new LanguageModel(m_settings, this));
m_engine->rootContext()->setContextProperty("LanguageModel", m_languageModel.get());
connect(m_languageModel.get(), &LanguageModel::updateTranslations, this, &AmneziaApplication::updateTranslator);
connect(this, &AmneziaApplication::translationsUpdated, m_languageModel.get(), &LanguageModel::translationsUpdated);
2023-08-08 19:10:14 +05:00
m_sitesModel.reset(new SitesModel(m_settings, this));
m_engine->rootContext()->setContextProperty("SitesModel", m_sitesModel.get());
2023-08-24 14:53:52 +05:00
connect(m_containersModel.get(), &ContainersModel::defaultContainerChanged, this, [this]() {
if (m_containersModel->getDefaultContainer() == DockerContainer::WireGuard
&& m_sitesModel->getRouteMode() != Settings::RouteMode::VpnAllSites) {
m_sitesModel->setRouteMode(Settings::RouteMode::VpnAllSites);
emit m_pageController->showNotificationMessage(
tr("Split tunneling for WireGuard is not implemented, the option was disabled"));
}
});
2023-08-08 19:10:14 +05:00
m_protocolsModel.reset(new ProtocolsModel(m_settings, this));
m_engine->rootContext()->setContextProperty("ProtocolsModel", m_protocolsModel.get());
m_openVpnConfigModel.reset(new OpenVpnConfigModel(this));
m_engine->rootContext()->setContextProperty("OpenVpnConfigModel", m_openVpnConfigModel.get());
m_shadowSocksConfigModel.reset(new ShadowSocksConfigModel(this));
m_engine->rootContext()->setContextProperty("ShadowSocksConfigModel", m_shadowSocksConfigModel.get());
m_cloakConfigModel.reset(new CloakConfigModel(this));
m_engine->rootContext()->setContextProperty("CloakConfigModel", m_cloakConfigModel.get());
m_wireguardConfigModel.reset(new WireGuardConfigModel(this));
m_engine->rootContext()->setContextProperty("WireGuardConfigModel", m_wireguardConfigModel.get());
#ifdef Q_OS_WINDOWS
m_ikev2ConfigModel.reset(new Ikev2ConfigModel(this));
m_engine->rootContext()->setContextProperty("Ikev2ConfigModel", m_ikev2ConfigModel.get());
#endif
m_sftpConfigModel.reset(new SftpConfigModel(this));
m_engine->rootContext()->setContextProperty("SftpConfigModel", m_sftpConfigModel.get());
}
void AmneziaApplication::initControllers()
{
m_connectionController.reset(new ConnectionController(m_serversModel, m_containersModel, m_vpnConnection));
m_engine->rootContext()->setContextProperty("ConnectionController", m_connectionController.get());
connect(this, &AmneziaApplication::translationsUpdated, m_connectionController.get(), &ConnectionController::onTranslationsUpdated);
2023-08-24 14:53:52 +05:00
m_pageController.reset(new PageController(m_serversModel, m_settings));
m_engine->rootContext()->setContextProperty("PageController", m_pageController.get());
m_installController.reset(new InstallController(m_serversModel, m_containersModel, m_protocolsModel, m_settings));
m_engine->rootContext()->setContextProperty("InstallController", m_installController.get());
2023-08-02 20:37:43 +09:00
connect(m_installController.get(), &InstallController::passphraseRequestStarted, m_pageController.get(),
&PageController::showPassphraseRequestDrawer);
connect(m_pageController.get(), &PageController::passphraseRequestDrawerClosed, m_installController.get(),
&InstallController::setEncryptedPassphrase);
connect(m_installController.get(), &InstallController::currentContainerUpdated, m_connectionController.get(),
&ConnectionController::onCurrentContainerUpdated);
m_importController.reset(new ImportController(m_serversModel, m_containersModel, m_settings));
m_engine->rootContext()->setContextProperty("ImportController", m_importController.get());
m_exportController.reset(new ExportController(m_serversModel, m_containersModel, m_settings, m_configurator));
m_engine->rootContext()->setContextProperty("ExportController", m_exportController.get());
m_settingsController.reset(new SettingsController(m_serversModel, m_containersModel, m_languageModel, m_settings));
m_engine->rootContext()->setContextProperty("SettingsController", m_settingsController.get());
if (m_settingsController->isAutoStartEnabled() && m_serversModel->getDefaultServerIndex() >= 0) {
QTimer::singleShot(1000, this, [this]() { m_connectionController->openConnection(); });
}
2023-08-08 19:10:14 +05:00
m_sitesController.reset(new SitesController(m_settings, m_vpnConnection, m_sitesModel));
m_engine->rootContext()->setContextProperty("SitesController", m_sitesController.get());
2023-09-06 22:20:59 +05:00
m_systemController.reset(new SystemController(m_settings));
m_engine->rootContext()->setContextProperty("SystemController", m_systemController.get());
}