UI: Options: Separate "Auto-run" and "Run as a Service" options.

This commit is contained in:
Nodir Temirkhodjaev 2021-05-16 11:29:40 +03:00
parent 8713b46a92
commit dafba58c22
6 changed files with 108 additions and 78 deletions

View File

@ -1060,7 +1060,7 @@ void ConfManager::saveExtFlags(const IniOptions &ini)
{ {
// Windows Explorer integration // Windows Explorer integration
if (ini.explorerIntegratedSet()) { if (ini.explorerIntegratedSet()) {
StartupUtil::integrateExplorer(ini.explorerIntegrated()); StartupUtil::setExplorerIntegrated(ini.explorerIntegrated());
} }
} }

View File

@ -28,33 +28,27 @@ namespace {
struct Startup struct Startup
{ {
Startup() : initialized(false), changed(false), wasServiceMode(false), mode(0) { } Startup() : initialized(false), isServiceChanged(false), wasService(false), isService(false) { }
void initialize()
{
if (!initialized) {
initialized = true;
mode = StartupUtil::getStartupMode();
}
}
quint8 initialized : 1; quint8 initialized : 1;
quint8 changed : 1; quint8 isServiceChanged : 1;
quint8 wasServiceMode : 1; quint8 wasService : 1;
quint8 mode : 4; quint8 isService : 1;
} g_startup; } g_startup;
} }
OptionsPage::OptionsPage(OptionsController *ctrl, QWidget *parent) : BasePage(ctrl, parent) OptionsPage::OptionsPage(OptionsController *ctrl, QWidget *parent) : BasePage(ctrl, parent)
{ {
setupStartup();
setupUi(); setupUi();
} }
void OptionsPage::onAboutToSave() void OptionsPage::onAboutToSave()
{ {
// Startup Mode // Startup
saveStartupMode(m_comboStartMode->currentIndex()); saveAutoRunMode(m_comboAutoRun->currentIndex());
saveService(m_cbService->isChecked());
// Password // Password
if (!settings()->hasPassword() && ini()->hasPassword() && ini()->password().isEmpty()) { if (!settings()->hasPassword() && ini()->hasPassword() && ini()->password().isEmpty()) {
@ -62,30 +56,41 @@ void OptionsPage::onAboutToSave()
} }
} }
void OptionsPage::saveStartupMode(int mode) void OptionsPage::saveAutoRunMode(int mode)
{ {
if (g_startup.mode == mode) if (m_currentAutoRunMode == mode)
return; return;
if (!g_startup.changed) { m_currentAutoRunMode = mode;
g_startup.changed = true;
g_startup.wasServiceMode = StartupUtil::isServiceMode(g_startup.mode); StartupUtil::setAutoRunMode(mode, settings()->defaultLanguage());
}
void OptionsPage::saveService(bool isService)
{
if (g_startup.isService == isService)
return;
g_startup.isService = isService;
if (!g_startup.isServiceChanged) {
g_startup.isServiceChanged = true;
const QString defaultLanguage = settings()->defaultLanguage(); const QString defaultLanguage = settings()->defaultLanguage();
connect(fortManager(), &QObject::destroyed, [defaultLanguage] { connect(fortManager(), &QObject::destroyed, [defaultLanguage] {
StartupUtil::setStartupMode(g_startup.mode, defaultLanguage); if (g_startup.wasService == g_startup.isService)
if (StartupUtil::isServiceMode(g_startup.mode)) { return;
StartupUtil::setServiceInstalled(g_startup.isService, defaultLanguage);
if (g_startup.isService) {
StartupUtil::startService(); // Try to start the (maybe installed) service StartupUtil::startService(); // Try to start the (maybe installed) service
} }
}); });
} }
g_startup.mode = mode;
if (g_startup.wasServiceMode != StartupUtil::isServiceMode(g_startup.mode)) {
QMetaObject::invokeMethod( QMetaObject::invokeMethod(
fortManager(), &FortManager::processRestartRequired, Qt::QueuedConnection); fortManager(), &FortManager::processRestartRequired, Qt::QueuedConnection);
}
} }
void OptionsPage::onCancelChanges(IniOptions *oldIni) void OptionsPage::onCancelChanges(IniOptions *oldIni)
@ -112,10 +117,12 @@ void OptionsPage::onRetranslateUi()
m_gbDriver->setTitle(tr("Driver")); m_gbDriver->setTitle(tr("Driver"));
m_gbNewVersion->setTitle(tr("New Version")); m_gbNewVersion->setTitle(tr("New Version"));
m_labelStartMode->setText(tr("Startup mode:")); m_labelStartMode->setText(tr("Auto-run:"));
retranslateComboStartMode(); retranslateComboStartMode();
m_cbService->setText(tr("Run Fort Firewall as a Service in background"));
m_cbProvBoot->setText(tr("Stop traffic when Fort Firewall is not running")); m_cbProvBoot->setText(tr("Stop traffic when Fort Firewall is not running"));
m_cbFilterEnabled->setText(tr("Filter Enabled")); m_cbFilterEnabled->setText(tr("Filter Enabled"));
m_cbFilterLocals->setText(tr("Filter Local Addresses")); m_cbFilterLocals->setText(tr("Filter Local Addresses"));
m_cbFilterLocals->setToolTip( m_cbFilterLocals->setToolTip(
@ -147,30 +154,29 @@ void OptionsPage::onRetranslateUi()
void OptionsPage::retranslateComboStartMode() void OptionsPage::retranslateComboStartMode()
{ {
const QStringList list = { tr("Disabled"), tr("For current user"), tr("For all users"), const QStringList list = { tr("Disabled"), tr("For current user"), tr("For all users") };
tr("For all users in background") };
int currentIndex = m_comboStartMode->currentIndex(); int currentIndex = m_comboAutoRun->currentIndex();
if (m_comboStartMode->currentIndex() < 0) { if (m_comboAutoRun->currentIndex() < 0) {
g_startup.initialize(); currentIndex = m_currentAutoRunMode;
currentIndex = g_startup.mode;
} }
m_comboStartMode->clear(); m_comboAutoRun->clear();
m_comboStartMode->addItems(list); m_comboAutoRun->addItems(list);
m_comboStartMode->setCurrentIndex(currentIndex); m_comboAutoRun->setCurrentIndex(currentIndex);
// Disable some items if user is not an administrator // Disable some items if user is not an administrator
if (OsUtil::isUserAdmin()) if (OsUtil::isUserAdmin())
return; return;
if (StartupUtil::isServiceMode(currentIndex)) { if (currentIndex >= StartupUtil::StartupAllUsers) {
m_comboStartMode->setEnabled(false); m_comboAutoRun->setEnabled(false);
m_cbService->setEnabled(false);
return; return;
} }
auto comboModel = qobject_cast<QStandardItemModel *>(m_comboStartMode->model()); auto comboModel = qobject_cast<QStandardItemModel *>(m_comboAutoRun->model());
if (!comboModel) if (!comboModel)
return; return;
@ -198,6 +204,17 @@ void OptionsPage::retranslateDriverMessage()
m_labelDriverMessage->setText(text); m_labelDriverMessage->setText(text);
} }
void OptionsPage::setupStartup()
{
m_currentAutoRunMode = StartupUtil::autoRunMode();
if (g_startup.initialized)
return;
g_startup.initialized = true;
g_startup.wasService = g_startup.isService = settings()->hasService();
}
void OptionsPage::setupUi() void OptionsPage::setupUi()
{ {
// Column #1 // Column #1
@ -246,6 +263,9 @@ void OptionsPage::setupStartupBox()
{ {
auto startModeLayout = setupStartModeLayout(); auto startModeLayout = setupStartModeLayout();
m_cbService = ControlUtil::createCheckBox(
g_startup.isService, [&](bool /*checked*/) { ctrl()->emitEdited(); });
m_cbProvBoot = ControlUtil::createCheckBox(conf()->provBoot(), [&](bool checked) { m_cbProvBoot = ControlUtil::createCheckBox(conf()->provBoot(), [&](bool checked) {
conf()->setProvBoot(checked); conf()->setProvBoot(checked);
ctrl()->setFlagsEdited(); ctrl()->setFlagsEdited();
@ -253,6 +273,7 @@ void OptionsPage::setupStartupBox()
auto layout = new QVBoxLayout(); auto layout = new QVBoxLayout();
layout->addLayout(startModeLayout); layout->addLayout(startModeLayout);
layout->addWidget(m_cbService);
layout->addWidget(m_cbProvBoot); layout->addWidget(m_cbProvBoot);
m_gbStartup = new QGroupBox(this); m_gbStartup = new QGroupBox(this);
@ -263,14 +284,14 @@ QLayout *OptionsPage::setupStartModeLayout()
{ {
m_labelStartMode = ControlUtil::createLabel(); m_labelStartMode = ControlUtil::createLabel();
m_comboStartMode = ControlUtil::createComboBox(QStringList(), [&](int index) { m_comboAutoRun = ControlUtil::createComboBox(QStringList(), [&](int index) {
if (g_startup.mode != index) { if (m_currentAutoRunMode != index) {
ctrl()->emitEdited(); ctrl()->emitEdited();
} }
}); });
m_comboStartMode->setFixedWidth(200); m_comboAutoRun->setFixedWidth(200);
return ControlUtil::createRowLayout(m_labelStartMode, m_comboStartMode); return ControlUtil::createRowLayout(m_labelStartMode, m_comboAutoRun);
} }
void OptionsPage::setupTrafficBox() void OptionsPage::setupTrafficBox()

View File

@ -19,12 +19,15 @@ protected slots:
void onRetranslateUi() override; void onRetranslateUi() override;
private: private:
void saveStartupMode(int mode); void saveAutoRunMode(int mode);
void saveService(bool isService);
void retranslateComboStartMode(); void retranslateComboStartMode();
void retranslateEditPassword(); void retranslateEditPassword();
void retranslateDriverMessage(); void retranslateDriverMessage();
void setupStartup();
void setupUi(); void setupUi();
QLayout *setupColumn1(); QLayout *setupColumn1();
void setupStartupBox(); void setupStartupBox();
@ -44,6 +47,8 @@ private:
void setupNewVersionUpdate(); void setupNewVersionUpdate();
private: private:
qint8 m_currentAutoRunMode = 0;
QGroupBox *m_gbStartup = nullptr; QGroupBox *m_gbStartup = nullptr;
QGroupBox *m_gbTraffic = nullptr; QGroupBox *m_gbTraffic = nullptr;
QGroupBox *m_gbGlobal = nullptr; QGroupBox *m_gbGlobal = nullptr;
@ -51,7 +56,8 @@ private:
QGroupBox *m_gbDriver = nullptr; QGroupBox *m_gbDriver = nullptr;
QGroupBox *m_gbNewVersion = nullptr; QGroupBox *m_gbNewVersion = nullptr;
QLabel *m_labelStartMode = nullptr; QLabel *m_labelStartMode = nullptr;
QComboBox *m_comboStartMode = nullptr; QComboBox *m_comboAutoRun = nullptr;
QCheckBox *m_cbService = nullptr;
QCheckBox *m_cbProvBoot = nullptr; QCheckBox *m_cbProvBoot = nullptr;
QCheckBox *m_cbFilterEnabled = nullptr; QCheckBox *m_cbFilterEnabled = nullptr;
QCheckBox *m_cbFilterLocals = nullptr; QCheckBox *m_cbFilterLocals = nullptr;

View File

@ -39,6 +39,12 @@ QString wrappedAppFilePath()
return QString("\"%1\"").arg(filePath); return QString("\"%1\"").arg(filePath);
} }
QString autoRunCommand(const QString &defaultLanguage)
{
return wrappedAppFilePath()
+ (defaultLanguage.isEmpty() ? QString() : " --lang " + defaultLanguage);
}
bool isAutorunForUser(RegKey::Root root, const char *key) bool isAutorunForUser(RegKey::Root root, const char *key)
{ {
const RegKey reg(root, key, RegKey::DefaultReadOnly); const RegKey reg(root, key, RegKey::DefaultReadOnly);
@ -153,6 +159,18 @@ bool StartupUtil::isServiceInstalled()
return res; return res;
} }
void StartupUtil::setServiceInstalled(bool install, const QString &defaultLanguage)
{
uninstallService(serviceNameStr);
if (!install)
return;
const QString command = autoRunCommand(defaultLanguage) + " --service";
installService(serviceNameStr, serviceDisplayStr, serviceDescriptionStr, command);
}
bool StartupUtil::startService() bool StartupUtil::startService()
{ {
bool res = false; bool res = false;
@ -168,15 +186,13 @@ bool StartupUtil::startService()
return res; return res;
} }
StartupUtil::StartupMode StartupUtil::getStartupMode() StartupUtil::AutoRunMode StartupUtil::autoRunMode()
{ {
const bool isForAllUsers = isAutorunForAllUsers(); return isAutorunForCurrentUser() ? StartupCurrentUser
return (isForAllUsers || isServiceInstalled()) : (isAutorunForAllUsers() ? StartupAllUsers : StartupDisabled);
? (isForAllUsers ? StartupAllUsers : StartupAllUsersBackground)
: (isAutorunForCurrentUser() ? StartupCurrentUser : StartupDisabled);
} }
void StartupUtil::setStartupMode(int mode, const QString &defaultLanguage) void StartupUtil::setAutoRunMode(int mode, const QString &defaultLanguage)
{ {
// Remove link from Programs -> Startup // Remove link from Programs -> Startup
// TODO: COMPAT: Remove after v4.1.0 (via v4.0.0) // TODO: COMPAT: Remove after v4.1.0 (via v4.0.0)
@ -184,13 +200,11 @@ void StartupUtil::setStartupMode(int mode, const QString &defaultLanguage)
removeAutorunForCurrentUser(); removeAutorunForCurrentUser();
removeAutorunForAllUsers(); removeAutorunForAllUsers();
uninstallService(serviceNameStr);
if (mode == StartupDisabled) if (mode == StartupDisabled)
return; return;
const QString command = wrappedAppFilePath() const QString command = autoRunCommand(defaultLanguage);
+ (defaultLanguage.isEmpty() ? QString() : " --lang " + defaultLanguage);
switch (mode) { switch (mode) {
case StartupCurrentUser: case StartupCurrentUser:
@ -198,19 +212,12 @@ void StartupUtil::setStartupMode(int mode, const QString &defaultLanguage)
break; break;
case StartupAllUsers: case StartupAllUsers:
setAutorunForAllUsers(command); setAutorunForAllUsers(command);
Q_FALLTHROUGH();
case StartupAllUsersBackground:
installService(
serviceNameStr, serviceDisplayStr, serviceDescriptionStr, command + " --service");
break; break;
default:
Q_UNREACHABLE();
} }
} }
bool StartupUtil::isServiceMode(int mode)
{
return mode == StartupAllUsers || mode == StartupAllUsersBackground;
}
bool StartupUtil::isExplorerIntegrated() bool StartupUtil::isExplorerIntegrated()
{ {
const RegKey regShell(regShellRoot, regShellMenu, RegKey::DefaultReadOnly); const RegKey regShell(regShellRoot, regShellMenu, RegKey::DefaultReadOnly);
@ -218,7 +225,7 @@ bool StartupUtil::isExplorerIntegrated()
return !reg.isNull(); return !reg.isNull();
} }
void StartupUtil::integrateExplorer(bool integrate) void StartupUtil::setExplorerIntegrated(bool integrate)
{ {
RegKey regShell(regShellRoot, regShellMenu, RegKey::DefaultReadWrite); RegKey regShell(regShellRoot, regShellMenu, RegKey::DefaultReadWrite);
if (integrate) { if (integrate) {

View File

@ -6,25 +6,20 @@
class StartupUtil class StartupUtil
{ {
public: public:
enum StartupMode : qint8 { enum AutoRunMode : qint8 { StartupDisabled = 0, StartupCurrentUser, StartupAllUsers };
StartupDisabled = 0,
StartupCurrentUser,
StartupAllUsers,
StartupAllUsersBackground
};
static const wchar_t *serviceName(); static const wchar_t *serviceName();
static bool isServiceInstalled(); static bool isServiceInstalled();
static void setServiceInstalled(bool install, const QString &defaultLanguage = QString());
static bool startService(); static bool startService();
static StartupMode getStartupMode(); static AutoRunMode autoRunMode();
static void setStartupMode(int mode, const QString &defaultLanguage = QString()); static void setAutoRunMode(int mode, const QString &defaultLanguage = QString());
static bool isServiceMode(int mode);
static bool isExplorerIntegrated(); static bool isExplorerIntegrated();
static void integrateExplorer(bool integrate); static void setExplorerIntegrated(bool integrate);
}; };
#endif // STARTUPUTIL_H #endif // STARTUPUTIL_H

View File

@ -23,8 +23,9 @@
static void uninstall() static void uninstall()
{ {
StartupUtil::setStartupMode(StartupUtil::StartupDisabled); // Remove auto-run and service StartupUtil::setAutoRunMode(StartupUtil::StartupDisabled); // Remove auto-run
StartupUtil::integrateExplorer(false); // Remove Windows Explorer integration StartupUtil::setServiceInstalled(false); // Uninstall service
StartupUtil::setExplorerIntegrated(false); // Remove Windows Explorer integration
DriverCommon::provUnregister(); // Unregister booted provider DriverCommon::provUnregister(); // Unregister booted provider
} }