Use RegisterUrlScheme from lib_base
This commit is contained in:
		
							parent
							
								
									9b1d967967
								
							
						
					
					
						commit
						49fed41dfa
					
				
					 7 changed files with 18 additions and 191 deletions
				
			
		|  | @ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL | ||||||
| #include "core/ui_integration.h" | #include "core/ui_integration.h" | ||||||
| #include "chat_helpers/emoji_keywords.h" | #include "chat_helpers/emoji_keywords.h" | ||||||
| #include "chat_helpers/stickers_emoji_image_loader.h" | #include "chat_helpers/stickers_emoji_image_loader.h" | ||||||
|  | #include "base/platform/base_platform_url_scheme.h" | ||||||
| #include "base/platform/base_platform_last_input.h" | #include "base/platform/base_platform_last_input.h" | ||||||
| #include "base/platform/base_platform_info.h" | #include "base/platform/base_platform_info.h" | ||||||
| #include "platform/platform_specific.h" | #include "platform/platform_specific.h" | ||||||
|  | @ -197,6 +198,7 @@ void Application::run() { | ||||||
| 	ValidateScale(); | 	ValidateScale(); | ||||||
| 
 | 
 | ||||||
| 	if (Local::oldSettingsVersion() < AppVersion) { | 	if (Local::oldSettingsVersion() < AppVersion) { | ||||||
|  | 		RegisterUrlScheme(); | ||||||
| 		psNewVersion(); | 		psNewVersion(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -1130,6 +1132,19 @@ void Application::startShortcuts() { | ||||||
| 	}, _lifetime); | 	}, _lifetime); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void Application::RegisterUrlScheme() { | ||||||
|  | 	base::Platform::RegisterUrlScheme(base::Platform::UrlSchemeDescriptor{ | ||||||
|  | 		.executable = cExeDir() + cExeName(), | ||||||
|  | 		.arguments = qsl("-workdir \"%1\"").arg(cWorkingDir()), | ||||||
|  | 		.protocol = qsl("tg"), | ||||||
|  | 		.protocolName = qsl("Telegram Link"), | ||||||
|  | 		.shortAppName = qsl("tdesktop"), | ||||||
|  | 		.longAppName = QCoreApplication::applicationName(), | ||||||
|  | 		.displayAppName = AppName.utf16(), | ||||||
|  | 		.displayAppDescription = AppName.utf16(), | ||||||
|  | 	}); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool IsAppLaunched() { | bool IsAppLaunched() { | ||||||
| 	return (Application::Instance != nullptr); | 	return (Application::Instance != nullptr); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -277,6 +277,8 @@ public: | ||||||
| 	void setScreenIsLocked(bool locked); | 	void setScreenIsLocked(bool locked); | ||||||
| 	bool screenIsLocked() const; | 	bool screenIsLocked() const; | ||||||
| 
 | 
 | ||||||
|  | 	static void RegisterUrlScheme(); | ||||||
|  | 
 | ||||||
| protected: | protected: | ||||||
| 	bool eventFilter(QObject *object, QEvent *event) override; | 	bool eventFilter(QObject *object, QEvent *event) override; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -43,8 +43,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL | ||||||
| #include <QtGui/QWindow> | #include <QtGui/QWindow> | ||||||
| 
 | 
 | ||||||
| #include <private/qguiapplication_p.h> | #include <private/qguiapplication_p.h> | ||||||
| #include <glib.h> |  | ||||||
| #include <gio/gio.h> |  | ||||||
| #include <glibmm.h> | #include <glibmm.h> | ||||||
| #include <giomm.h> | #include <giomm.h> | ||||||
| #include <jemalloc/jemalloc.h> | #include <jemalloc/jemalloc.h> | ||||||
|  | @ -71,17 +69,12 @@ namespace { | ||||||
| 
 | 
 | ||||||
| constexpr auto kDesktopFile = ":/misc/telegramdesktop.desktop"_cs; | constexpr auto kDesktopFile = ":/misc/telegramdesktop.desktop"_cs; | ||||||
| constexpr auto kIconName = "telegram"_cs; | constexpr auto kIconName = "telegram"_cs; | ||||||
| constexpr auto kHandlerTypeName = "x-scheme-handler/tg"_cs; |  | ||||||
| constexpr auto kDarkColorLimit = 192; | constexpr auto kDarkColorLimit = 192; | ||||||
| 
 | 
 | ||||||
| constexpr auto kXDGDesktopPortalService = "org.freedesktop.portal.Desktop"_cs; | constexpr auto kXDGDesktopPortalService = "org.freedesktop.portal.Desktop"_cs; | ||||||
| constexpr auto kXDGDesktopPortalObjectPath = "/org/freedesktop/portal/desktop"_cs; | constexpr auto kXDGDesktopPortalObjectPath = "/org/freedesktop/portal/desktop"_cs; | ||||||
| constexpr auto kIBusPortalService = "org.freedesktop.portal.IBus"_cs; | constexpr auto kIBusPortalService = "org.freedesktop.portal.IBus"_cs; | ||||||
| 
 | 
 | ||||||
| constexpr auto kSnapcraftSettingsService = "io.snapcraft.Settings"_cs; |  | ||||||
| constexpr auto kSnapcraftSettingsObjectPath = "/io/snapcraft/Settings"_cs; |  | ||||||
| constexpr auto kSnapcraftSettingsInterface = kSnapcraftSettingsService; |  | ||||||
| 
 |  | ||||||
| #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION | #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION | ||||||
| void PortalAutostart(bool start, bool silent) { | void PortalAutostart(bool start, bool silent) { | ||||||
| 	if (cExeName().isEmpty()) { | 	if (cExeName().isEmpty()) { | ||||||
|  | @ -210,67 +203,6 @@ void PortalAutostart(bool start, bool silent) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SnapDefaultHandler(const QString &protocol) { |  | ||||||
| 	try { |  | ||||||
| 		const auto connection = Gio::DBus::Connection::get_sync( |  | ||||||
| 			Gio::DBus::BusType::BUS_TYPE_SESSION); |  | ||||||
| 
 |  | ||||||
| 		auto reply = connection->call_sync( |  | ||||||
| 			std::string(kSnapcraftSettingsObjectPath), |  | ||||||
| 			std::string(kSnapcraftSettingsInterface), |  | ||||||
| 			"GetSub", |  | ||||||
| 			base::Platform::MakeGlibVariant(std::tuple{ |  | ||||||
| 				Glib::ustring("default-url-scheme-handler"), |  | ||||||
| 				Glib::ustring(protocol.toStdString()), |  | ||||||
| 			}), |  | ||||||
| 			std::string(kSnapcraftSettingsService)); |  | ||||||
| 
 |  | ||||||
| 		const auto currentHandler = base::Platform::GlibVariantCast< |  | ||||||
| 			Glib::ustring>(reply.get_child(0)); |  | ||||||
| 
 |  | ||||||
| 		const auto expectedHandler = qEnvironmentVariable("SNAP_NAME") |  | ||||||
| 			+ qsl(".desktop"); |  | ||||||
| 
 |  | ||||||
| 		if (currentHandler == expectedHandler.toStdString()) { |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		const auto context = Glib::MainContext::create(); |  | ||||||
| 		const auto loop = Glib::MainLoop::create(context); |  | ||||||
| 		g_main_context_push_thread_default(context->gobj()); |  | ||||||
| 
 |  | ||||||
| 		connection->call( |  | ||||||
| 			std::string(kSnapcraftSettingsObjectPath), |  | ||||||
| 			std::string(kSnapcraftSettingsInterface), |  | ||||||
| 			"SetSub", |  | ||||||
| 			base::Platform::MakeGlibVariant(std::tuple{ |  | ||||||
| 				Glib::ustring("default-url-scheme-handler"), |  | ||||||
| 				Glib::ustring(protocol.toStdString()), |  | ||||||
| 				Glib::ustring(expectedHandler.toStdString()), |  | ||||||
| 			}), |  | ||||||
| 			[&](const Glib::RefPtr<Gio::AsyncResult> &result) { |  | ||||||
| 				try { |  | ||||||
| 					connection->call_finish(result); |  | ||||||
| 				} catch (const Glib::Error &e) { |  | ||||||
| 					LOG(("Snap Default Handler Error: %1").arg( |  | ||||||
| 						QString::fromStdString(e.what()))); |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				loop->quit(); |  | ||||||
| 			}, |  | ||||||
| 			std::string(kSnapcraftSettingsService)); |  | ||||||
| 
 |  | ||||||
| 		QWindow window; |  | ||||||
| 		QGuiApplicationPrivate::showModalWindow(&window); |  | ||||||
| 		loop->run(); |  | ||||||
| 		g_main_context_pop_thread_default(context->gobj()); |  | ||||||
| 		QGuiApplicationPrivate::hideModalWindow(&window); |  | ||||||
| 	} catch (const Glib::Error &e) { |  | ||||||
| 		LOG(("Snap Default Handler Error: %1").arg( |  | ||||||
| 			QString::fromStdString(e.what()))); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool IsIBusPortalPresent() { | bool IsIBusPortalPresent() { | ||||||
| 	static const auto Result = [&] { | 	static const auto Result = [&] { | ||||||
| 		try { | 		try { | ||||||
|  | @ -816,76 +748,6 @@ void InstallLauncher(bool force) { | ||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RegisterCustomScheme(bool force) { |  | ||||||
| 	try { |  | ||||||
| #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION |  | ||||||
| 		if (InSnap()) { |  | ||||||
| 			SnapDefaultHandler(qsl("tg")); |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| #endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
 |  | ||||||
| 
 |  | ||||||
| 		if (cExeName().isEmpty()) { |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		const auto neededCommandlineBuilder = qsl("%1 -workdir %2 --").arg( |  | ||||||
| 			QString(EscapeShell(QFile::encodeName(cExeDir() + cExeName()))), |  | ||||||
| 			QString(EscapeShell(QFile::encodeName(cWorkingDir())))); |  | ||||||
| 
 |  | ||||||
| 		const auto neededCommandline = qsl("%1 %u") |  | ||||||
| 			.arg(neededCommandlineBuilder); |  | ||||||
| 
 |  | ||||||
| 		const auto currentAppInfo = Gio::AppInfo::get_default_for_type( |  | ||||||
| 			std::string(kHandlerTypeName), |  | ||||||
| 			true); |  | ||||||
| 
 |  | ||||||
| 		if (currentAppInfo) { |  | ||||||
| 			const auto currentCommandline = QString::fromStdString( |  | ||||||
| 				currentAppInfo->get_commandline()); |  | ||||||
| 
 |  | ||||||
| 			if (currentCommandline == neededCommandline) { |  | ||||||
| 				return; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		auto registeredAppInfoList = g_app_info_get_recommended_for_type( |  | ||||||
| 			kHandlerTypeName.utf8().constData()); |  | ||||||
| 
 |  | ||||||
| 		for (auto l = registeredAppInfoList; l != nullptr; l = l->next) { |  | ||||||
| 			const auto currentRegisteredAppInfo = reinterpret_cast<GAppInfo*>( |  | ||||||
| 				l->data); |  | ||||||
| 
 |  | ||||||
| 			const auto currentAppInfoId = QString( |  | ||||||
| 				g_app_info_get_id(currentRegisteredAppInfo)); |  | ||||||
| 
 |  | ||||||
| 			const auto currentCommandline = QString( |  | ||||||
| 				g_app_info_get_commandline(currentRegisteredAppInfo)); |  | ||||||
| 
 |  | ||||||
| 			if (currentCommandline == neededCommandline |  | ||||||
| 				&& currentAppInfoId.startsWith(qsl("userapp-"))) { |  | ||||||
| 				g_app_info_delete(currentRegisteredAppInfo); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if (registeredAppInfoList) { |  | ||||||
| 			g_list_free_full(registeredAppInfoList, g_object_unref); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		const auto newAppInfo = Gio::AppInfo::create_from_commandline( |  | ||||||
| 			neededCommandlineBuilder.toStdString(), |  | ||||||
| 			std::string(AppName), |  | ||||||
| 			Gio::AppInfoCreateFlags::APP_INFO_CREATE_SUPPORTS_URIS); |  | ||||||
| 
 |  | ||||||
| 		if (newAppInfo) { |  | ||||||
| 			newAppInfo->set_as_default_for_type( |  | ||||||
| 				std::string(kHandlerTypeName)); |  | ||||||
| 		} |  | ||||||
| 	} catch (const Glib::Error &e) { |  | ||||||
| 		LOG(("App Error: %1").arg(QString::fromStdString(e.what()))); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| PermissionStatus GetPermissionStatus(PermissionType type) { | PermissionStatus GetPermissionStatus(PermissionType type) { | ||||||
| 	return PermissionStatus::Granted; | 	return PermissionStatus::Granted; | ||||||
| } | } | ||||||
|  | @ -976,7 +838,6 @@ void psNewVersion() { | ||||||
| #ifndef __HAIKU__ | #ifndef __HAIKU__ | ||||||
| 	Platform::InstallLauncher(); | 	Platform::InstallLauncher(); | ||||||
| #endif // __HAIKU__
 | #endif // __HAIKU__
 | ||||||
| 	Platform::RegisterCustomScheme(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void psAutoStart(bool start, bool silent) { | void psAutoStart(bool start, bool silent) { | ||||||
|  |  | ||||||
|  | @ -112,11 +112,6 @@ void WriteCrashDumpDetails() { | ||||||
| #endif // DESKTOP_APP_DISABLE_CRASH_REPORTS | #endif // DESKTOP_APP_DISABLE_CRASH_REPORTS | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RegisterCustomScheme(bool force) { |  | ||||||
| 	OSStatus result = LSSetDefaultHandlerForURLScheme(CFSTR("tg"), (CFStringRef)[[NSBundle mainBundle] bundleIdentifier]); |  | ||||||
| 	DEBUG_LOG(("App Info: set default handler for 'tg' scheme result: %1").arg(result)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // I do check for availability, just not in the exact way clang is content with | // I do check for availability, just not in the exact way clang is content with | ||||||
| #pragma clang diagnostic push | #pragma clang diagnostic push | ||||||
| #pragma clang diagnostic ignored "-Wunguarded-availability" | #pragma clang diagnostic ignored "-Wunguarded-availability" | ||||||
|  | @ -196,7 +191,6 @@ void IgnoreApplicationActivationRightNow() { | ||||||
| } // namespace Platform | } // namespace Platform | ||||||
| 
 | 
 | ||||||
| void psNewVersion() { | void psNewVersion() { | ||||||
| 	Platform::RegisterCustomScheme(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void psAutoStart(bool start, bool silent) { | void psAutoStart(bool start, bool silent) { | ||||||
|  |  | ||||||
|  | @ -30,7 +30,6 @@ enum class SystemSettingsType { | ||||||
| void SetWatchingMediaKeys(bool watching); | void SetWatchingMediaKeys(bool watching); | ||||||
| void SetApplicationIcon(const QIcon &icon); | void SetApplicationIcon(const QIcon &icon); | ||||||
| QString SingleInstanceLocalServerName(const QString &hash); | QString SingleInstanceLocalServerName(const QString &hash); | ||||||
| void RegisterCustomScheme(bool force = false); |  | ||||||
| PermissionStatus GetPermissionStatus(PermissionType type); | PermissionStatus GetPermissionStatus(PermissionType type); | ||||||
| void RequestPermission(PermissionType type, Fn<void(PermissionStatus)> resultCallback); | void RequestPermission(PermissionType type, Fn<void(PermissionStatus)> resultCallback); | ||||||
| void OpenSystemSettingsForPermission(PermissionType type); | void OpenSystemSettingsForPermission(PermissionType type); | ||||||
|  |  | ||||||
|  | @ -372,49 +372,6 @@ namespace { | ||||||
| 
 | 
 | ||||||
| namespace Platform { | namespace Platform { | ||||||
| 
 | 
 | ||||||
| void RegisterCustomScheme(bool force) { |  | ||||||
| 	if (cExeName().isEmpty()) { |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 	DEBUG_LOG(("App Info: Checking custom scheme 'tg'...")); |  | ||||||
| 
 |  | ||||||
| 	HKEY rkey; |  | ||||||
| 	QString exe = QDir::toNativeSeparators(cExeDir() + cExeName()); |  | ||||||
| 
 |  | ||||||
| 	// Legacy URI scheme registration
 |  | ||||||
| 	if (!_psOpenRegKey(L"Software\\Classes\\tg", &rkey)) return; |  | ||||||
| 	if (!_psSetKeyValue(rkey, L"URL Protocol", QString())) return; |  | ||||||
| 	if (!_psSetKeyValue(rkey, 0, qsl("URL:Telegram Link"))) return; |  | ||||||
| 
 |  | ||||||
| 	if (!_psOpenRegKey(L"Software\\Classes\\tg\\DefaultIcon", &rkey)) return; |  | ||||||
| 	if (!_psSetKeyValue(rkey, 0, '"' + exe + qsl(",1\""))) return; |  | ||||||
| 
 |  | ||||||
| 	if (!_psOpenRegKey(L"Software\\Classes\\tg\\shell", &rkey)) return; |  | ||||||
| 	if (!_psOpenRegKey(L"Software\\Classes\\tg\\shell\\open", &rkey)) return; |  | ||||||
| 	if (!_psOpenRegKey(L"Software\\Classes\\tg\\shell\\open\\command", &rkey)) return; |  | ||||||
| 	if (!_psSetKeyValue(rkey, 0, '"' + exe + qsl("\" -workdir \"") + cWorkingDir() + qsl("\" -- \"%1\""))) return; |  | ||||||
| 
 |  | ||||||
| 	// URI scheme registration as Default Program - Windows Vista and above
 |  | ||||||
| 	if (!_psOpenRegKey(L"Software\\Classes\\tdesktop.tg", &rkey)) return; |  | ||||||
| 	if (!_psOpenRegKey(L"Software\\Classes\\tdesktop.tg\\DefaultIcon", &rkey)) return; |  | ||||||
| 	if (!_psSetKeyValue(rkey, 0, '"' + exe + qsl(",1\""))) return; |  | ||||||
| 
 |  | ||||||
| 	if (!_psOpenRegKey(L"Software\\Classes\\tdesktop.tg\\shell", &rkey)) return; |  | ||||||
| 	if (!_psOpenRegKey(L"Software\\Classes\\tdesktop.tg\\shell\\open", &rkey)) return; |  | ||||||
| 	if (!_psOpenRegKey(L"Software\\Classes\\tdesktop.tg\\shell\\open\\command", &rkey)) return; |  | ||||||
| 	if (!_psSetKeyValue(rkey, 0, '"' + exe + qsl("\" -workdir \"") + cWorkingDir() + qsl("\" -- \"%1\""))) return; |  | ||||||
| 
 |  | ||||||
| 	if (!_psOpenRegKey(L"Software\\TelegramDesktop", &rkey)) return; |  | ||||||
| 	if (!_psOpenRegKey(L"Software\\TelegramDesktop\\Capabilities", &rkey)) return; |  | ||||||
| 	if (!_psSetKeyValue(rkey, L"ApplicationName", qsl("Telegram Desktop"))) return; |  | ||||||
| 	if (!_psSetKeyValue(rkey, L"ApplicationDescription", qsl("Telegram Desktop"))) return; |  | ||||||
| 	if (!_psOpenRegKey(L"Software\\TelegramDesktop\\Capabilities\\UrlAssociations", &rkey)) return; |  | ||||||
| 	if (!_psSetKeyValue(rkey, L"tg", qsl("tdesktop.tg"))) return; |  | ||||||
| 
 |  | ||||||
| 	if (!_psOpenRegKey(L"Software\\RegisteredApplications", &rkey)) return; |  | ||||||
| 	if (!_psSetKeyValue(rkey, L"Telegram Desktop", qsl("SOFTWARE\\TelegramDesktop\\Capabilities"))) return; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| PermissionStatus GetPermissionStatus(PermissionType type) { | PermissionStatus GetPermissionStatus(PermissionType type) { | ||||||
| 	if (type==PermissionType::Microphone) { | 	if (type==PermissionType::Microphone) { | ||||||
| 		PermissionStatus result=PermissionStatus::Granted; | 		PermissionStatus result=PermissionStatus::Granted; | ||||||
|  | @ -467,7 +424,6 @@ bool OpenSystemSettings(SystemSettingsType type) { | ||||||
| } // namespace Platform
 | } // namespace Platform
 | ||||||
| 
 | 
 | ||||||
| void psNewVersion() { | void psNewVersion() { | ||||||
| 	Platform::RegisterCustomScheme(); |  | ||||||
| 	if (Local::oldSettingsVersion() < 8051) { | 	if (Local::oldSettingsVersion() < 8051) { | ||||||
| 		AppUserModelId::checkPinned(); | 		AppUserModelId::checkPinned(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -137,7 +137,7 @@ auto GenerateCodes() { | ||||||
| 		} | 		} | ||||||
| 	}); | 	}); | ||||||
| 	codes.emplace(qsl("registertg"), [](SessionController *window) { | 	codes.emplace(qsl("registertg"), [](SessionController *window) { | ||||||
| 		Platform::RegisterCustomScheme(true); | 		Core::Application::RegisterUrlScheme(); | ||||||
| 		Ui::Toast::Show("Forced custom scheme register."); | 		Ui::Toast::Show("Forced custom scheme register."); | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Ilya Fedin
						Ilya Fedin