2017-12-11 14:45:29 +00:00
|
|
|
/*
|
|
|
|
This file is part of Telegram Desktop,
|
2018-01-03 10:23:14 +00:00
|
|
|
the official desktop application for the Telegram messaging service.
|
2017-12-11 14:45:29 +00:00
|
|
|
|
2018-01-03 10:23:14 +00:00
|
|
|
For license and copyright information please follow this link:
|
|
|
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
2017-12-11 14:45:29 +00:00
|
|
|
*/
|
|
|
|
#include "core/launcher.h"
|
|
|
|
|
|
|
|
#include "platform/platform_launcher.h"
|
|
|
|
#include "platform/platform_specific.h"
|
|
|
|
#include "core/crash_reports.h"
|
2017-12-17 18:41:34 +00:00
|
|
|
#include "core/main_queue_processor.h"
|
2018-07-11 22:14:44 +00:00
|
|
|
#include "core/update_checker.h"
|
2017-12-11 14:45:29 +00:00
|
|
|
#include "application.h"
|
|
|
|
|
|
|
|
namespace Core {
|
|
|
|
|
|
|
|
std::unique_ptr<Launcher> Launcher::Create(int argc, char *argv[]) {
|
|
|
|
return std::make_unique<Platform::Launcher>(argc, argv);
|
|
|
|
}
|
|
|
|
|
2018-06-03 19:52:23 +00:00
|
|
|
Launcher::Launcher(
|
|
|
|
int argc,
|
|
|
|
char *argv[],
|
|
|
|
const QString &deviceModel,
|
|
|
|
const QString &systemVersion)
|
2017-12-11 14:45:29 +00:00
|
|
|
: _argc(argc)
|
2018-06-03 19:52:23 +00:00
|
|
|
, _argv(argv)
|
|
|
|
, _deviceModel(deviceModel)
|
|
|
|
, _systemVersion(systemVersion) {
|
2017-12-11 14:45:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Launcher::init() {
|
2017-12-12 08:15:33 +00:00
|
|
|
_arguments = readArguments(_argc, _argv);
|
|
|
|
|
|
|
|
prepareSettings();
|
|
|
|
|
2017-12-11 14:45:29 +00:00
|
|
|
QCoreApplication::setApplicationName(qsl("TelegramDesktop"));
|
|
|
|
|
|
|
|
#ifndef OS_MAC_OLD
|
|
|
|
QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling, true);
|
|
|
|
#endif // OS_MAC_OLD
|
|
|
|
|
|
|
|
initHook();
|
|
|
|
}
|
|
|
|
|
|
|
|
int Launcher::exec() {
|
|
|
|
init();
|
|
|
|
|
|
|
|
if (cLaunchMode() == LaunchModeFixPrevious) {
|
|
|
|
return psFixPrevious();
|
|
|
|
} else if (cLaunchMode() == LaunchModeCleanup) {
|
|
|
|
return psCleanup();
|
|
|
|
}
|
|
|
|
|
|
|
|
// both are finished in Application::closeApplication
|
|
|
|
Logs::start(this); // must be started before Platform is started
|
|
|
|
Platform::start(); // must be started before QApplication is created
|
|
|
|
|
2017-12-17 18:41:34 +00:00
|
|
|
auto result = executeApplication();
|
2017-12-11 14:45:29 +00:00
|
|
|
|
|
|
|
DEBUG_LOG(("Telegram finished, result: %1").arg(result));
|
|
|
|
|
2018-07-11 22:14:44 +00:00
|
|
|
if (!UpdaterDisabled() && cRestartingUpdate()) {
|
2017-12-11 14:45:29 +00:00
|
|
|
DEBUG_LOG(("Application Info: executing updater to install update..."));
|
2017-12-12 07:52:53 +00:00
|
|
|
if (!launchUpdater(UpdaterLaunch::PerformUpdate)) {
|
|
|
|
psDeleteDir(cWorkingDir() + qsl("tupdates/temp"));
|
|
|
|
}
|
2018-07-11 22:14:44 +00:00
|
|
|
} else if (cRestarting()) {
|
2017-12-11 14:45:29 +00:00
|
|
|
DEBUG_LOG(("Application Info: executing Telegram, because of restart..."));
|
2017-12-12 07:52:53 +00:00
|
|
|
launchUpdater(UpdaterLaunch::JustRelaunch);
|
2017-12-11 14:45:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CrashReports::Finish();
|
|
|
|
Platform::finish();
|
|
|
|
Logs::finish();
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-12-12 08:15:33 +00:00
|
|
|
QStringList Launcher::readArguments(int argc, char *argv[]) const {
|
|
|
|
Expects(argc >= 0);
|
|
|
|
|
|
|
|
if (const auto native = readArgumentsHook(argc, argv)) {
|
|
|
|
return *native;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto result = QStringList();
|
|
|
|
result.reserve(argc);
|
|
|
|
for (auto i = 0; i != argc; ++i) {
|
|
|
|
result.push_back(fromUtf8Safe(argv[i]));
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-12-11 14:45:29 +00:00
|
|
|
QString Launcher::argumentsString() const {
|
|
|
|
return _arguments.join(' ');
|
|
|
|
}
|
|
|
|
|
2018-06-03 19:52:23 +00:00
|
|
|
bool Launcher::customWorkingDir() const {
|
|
|
|
return _customWorkingDir;
|
|
|
|
}
|
|
|
|
|
2017-12-12 07:52:53 +00:00
|
|
|
void Launcher::prepareSettings() {
|
|
|
|
#ifdef Q_OS_MAC
|
|
|
|
#ifndef OS_MAC_OLD
|
|
|
|
if (QSysInfo::macVersion() >= QSysInfo::MV_10_11) {
|
|
|
|
gIsElCapitan = true;
|
|
|
|
}
|
|
|
|
#else // OS_MAC_OLD
|
|
|
|
if (QSysInfo::macVersion() < QSysInfo::MV_10_7) {
|
|
|
|
gIsSnowLeopard = true;
|
|
|
|
}
|
|
|
|
#endif // OS_MAC_OLD
|
|
|
|
#endif // Q_OS_MAC
|
|
|
|
|
|
|
|
switch (cPlatform()) {
|
|
|
|
case dbipWindows:
|
|
|
|
#ifndef OS_WIN_STORE
|
|
|
|
gPlatformString = qsl("Windows");
|
|
|
|
#else // OS_WIN_STORE
|
|
|
|
gPlatformString = qsl("WinStore");
|
|
|
|
#endif // OS_WIN_STORE
|
|
|
|
break;
|
|
|
|
case dbipMac:
|
|
|
|
#ifndef OS_MAC_STORE
|
|
|
|
gPlatformString = qsl("MacOS");
|
|
|
|
#else // OS_MAC_STORE
|
|
|
|
gPlatformString = qsl("MacAppStore");
|
|
|
|
#endif // OS_MAC_STORE
|
|
|
|
break;
|
|
|
|
case dbipMacOld:
|
|
|
|
gPlatformString = qsl("MacOSold");
|
|
|
|
break;
|
|
|
|
case dbipLinux64:
|
|
|
|
gPlatformString = qsl("Linux64bit");
|
|
|
|
break;
|
|
|
|
case dbipLinux32:
|
|
|
|
gPlatformString = qsl("Linux32bit");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto path = Platform::CurrentExecutablePath(_argc, _argv);
|
|
|
|
LOG(("Executable path before check: %1").arg(path));
|
|
|
|
if (!path.isEmpty()) {
|
|
|
|
auto info = QFileInfo(path);
|
|
|
|
if (info.isSymLink()) {
|
|
|
|
info = info.symLinkTarget();
|
|
|
|
}
|
|
|
|
if (info.exists()) {
|
2018-06-20 18:12:47 +00:00
|
|
|
const auto dir = info.absoluteDir().absolutePath();
|
|
|
|
gExeDir = (dir.endsWith('/') ? dir : (dir + '/'));
|
2017-12-12 07:52:53 +00:00
|
|
|
gExeName = info.fileName();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cExeName().isEmpty()) {
|
|
|
|
LOG(("WARNING: Could not compute executable path, some features will be disabled."));
|
|
|
|
}
|
|
|
|
|
|
|
|
processArguments();
|
|
|
|
}
|
|
|
|
|
2018-06-03 19:52:23 +00:00
|
|
|
QString Launcher::deviceModel() const {
|
|
|
|
return _deviceModel;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Launcher::systemVersion() const {
|
|
|
|
return _systemVersion;
|
|
|
|
}
|
|
|
|
|
2017-12-12 07:52:53 +00:00
|
|
|
void Launcher::processArguments() {
|
|
|
|
enum class KeyFormat {
|
|
|
|
NoValues,
|
|
|
|
OneValue,
|
|
|
|
AllLeftValues,
|
|
|
|
};
|
|
|
|
auto parseMap = std::map<QByteArray, KeyFormat> {
|
2018-07-11 22:14:44 +00:00
|
|
|
{ "-testmode" , KeyFormat::NoValues },
|
|
|
|
{ "-debug" , KeyFormat::NoValues },
|
|
|
|
{ "-many" , KeyFormat::NoValues },
|
|
|
|
{ "-key" , KeyFormat::OneValue },
|
|
|
|
{ "-autostart" , KeyFormat::NoValues },
|
|
|
|
{ "-fixprevious" , KeyFormat::NoValues },
|
|
|
|
{ "-cleanup" , KeyFormat::NoValues },
|
|
|
|
{ "-noupdate" , KeyFormat::NoValues },
|
|
|
|
{ "-externalupdater", KeyFormat::NoValues },
|
|
|
|
{ "-tosettings" , KeyFormat::NoValues },
|
|
|
|
{ "-startintray" , KeyFormat::NoValues },
|
|
|
|
{ "-sendpath" , KeyFormat::AllLeftValues },
|
|
|
|
{ "-workdir" , KeyFormat::OneValue },
|
|
|
|
{ "--" , KeyFormat::OneValue },
|
2017-12-12 07:52:53 +00:00
|
|
|
};
|
|
|
|
auto parseResult = QMap<QByteArray, QStringList>();
|
|
|
|
auto parsingKey = QByteArray();
|
|
|
|
auto parsingFormat = KeyFormat::NoValues;
|
|
|
|
for (const auto &argument : _arguments) {
|
|
|
|
switch (parsingFormat) {
|
|
|
|
case KeyFormat::OneValue: {
|
|
|
|
parseResult[parsingKey] = QStringList(argument.mid(0, 8192));
|
|
|
|
parsingFormat = KeyFormat::NoValues;
|
|
|
|
} break;
|
|
|
|
case KeyFormat::AllLeftValues: {
|
|
|
|
parseResult[parsingKey].push_back(argument.mid(0, 8192));
|
|
|
|
} break;
|
|
|
|
case KeyFormat::NoValues: {
|
|
|
|
parsingKey = argument.toLatin1();
|
|
|
|
auto it = parseMap.find(parsingKey);
|
|
|
|
if (it != parseMap.end()) {
|
|
|
|
parsingFormat = it->second;
|
|
|
|
parseResult[parsingKey] = QStringList();
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-11 22:14:44 +00:00
|
|
|
if (parseResult.contains("-externalupdater")) {
|
|
|
|
SetUpdaterDisabledAtStartup();
|
|
|
|
}
|
2017-12-12 07:52:53 +00:00
|
|
|
gTestMode = parseResult.contains("-testmode");
|
2018-06-05 13:32:26 +00:00
|
|
|
Logs::SetDebugEnabled(parseResult.contains("-debug"));
|
2017-12-12 07:52:53 +00:00
|
|
|
gManyInstance = parseResult.contains("-many");
|
|
|
|
gKeyFile = parseResult.value("-key", QStringList()).join(QString());
|
|
|
|
gLaunchMode = parseResult.contains("-autostart") ? LaunchModeAutoStart
|
|
|
|
: parseResult.contains("-fixprevious") ? LaunchModeFixPrevious
|
|
|
|
: parseResult.contains("-cleanup") ? LaunchModeCleanup
|
|
|
|
: LaunchModeNormal;
|
|
|
|
gNoStartUpdate = parseResult.contains("-noupdate");
|
|
|
|
gStartToSettings = parseResult.contains("-tosettings");
|
|
|
|
gStartInTray = parseResult.contains("-startintray");
|
|
|
|
gSendPaths = parseResult.value("-sendpath", QStringList());
|
|
|
|
gWorkingDir = parseResult.value("-workdir", QStringList()).join(QString());
|
|
|
|
if (!gWorkingDir.isEmpty()) {
|
|
|
|
if (QDir().exists(gWorkingDir)) {
|
|
|
|
_customWorkingDir = true;
|
|
|
|
} else {
|
|
|
|
gWorkingDir = QString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gStartUrl = parseResult.value("--", QStringList()).join(QString());
|
|
|
|
}
|
|
|
|
|
2017-12-17 18:41:34 +00:00
|
|
|
int Launcher::executeApplication() {
|
|
|
|
MainQueueProcessor processor;
|
|
|
|
Application app(this, _argc, _argv);
|
|
|
|
return app.exec();
|
|
|
|
}
|
|
|
|
|
2017-12-11 14:45:29 +00:00
|
|
|
} // namespace Core
|