From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- toolkit/components/remote/nsDBusRemoteServer.cpp | 214 +++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 toolkit/components/remote/nsDBusRemoteServer.cpp (limited to 'toolkit/components/remote/nsDBusRemoteServer.cpp') diff --git a/toolkit/components/remote/nsDBusRemoteServer.cpp b/toolkit/components/remote/nsDBusRemoteServer.cpp new file mode 100644 index 0000000000..34167177d9 --- /dev/null +++ b/toolkit/components/remote/nsDBusRemoteServer.cpp @@ -0,0 +1,214 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:expandtab:shiftwidth=2:tabstop=2: + */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsDBusRemoteServer.h" + +#include "nsCOMPtr.h" +#include "mozilla/XREAppData.h" +#include "mozilla/Base64.h" +#include "mozilla/ScopeExit.h" +#include "nsPrintfCString.h" + +#include "nsGTKToolkit.h" + +#include +#include + +#include + +static const char* introspect_template = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + +DBusHandlerResult nsDBusRemoteServer::Introspect(DBusMessage* msg) { + DBusMessage* reply = dbus_message_new_method_return(msg); + if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; + + nsAutoCString introspect_xml; + introspect_xml = nsPrintfCString(introspect_template, mAppName.get()); + + const char* message = introspect_xml.get(); + dbus_message_append_args(reply, DBUS_TYPE_STRING, &message, + DBUS_TYPE_INVALID); + + dbus_connection_send(mConnection, reply, nullptr); + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +DBusHandlerResult nsDBusRemoteServer::OpenURL(DBusMessage* msg) { + DBusMessage* reply = nullptr; + const char* commandLine; + int length; + + if (!dbus_message_get_args(msg, nullptr, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &commandLine, &length, DBUS_TYPE_INVALID) || + length == 0) { + nsAutoCString errorMsg; + errorMsg = nsPrintfCString("org.mozilla.%s.Error", mAppName.get()); + reply = dbus_message_new_error(msg, errorMsg.get(), "Wrong argument"); + } else { + guint32 timestamp = gtk_get_current_event_time(); + if (timestamp == GDK_CURRENT_TIME) { + timestamp = guint32(g_get_monotonic_time() / 1000); + } + HandleCommandLine(commandLine, timestamp); + reply = dbus_message_new_method_return(msg); + } + + dbus_connection_send(mConnection, reply, nullptr); + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +DBusHandlerResult nsDBusRemoteServer::HandleDBusMessage( + DBusConnection* aConnection, DBusMessage* msg) { + NS_ASSERTION(mConnection == aConnection, "Wrong D-Bus connection."); + + const char* method = dbus_message_get_member(msg); + const char* iface = dbus_message_get_interface(msg); + + if ((strcmp("Introspect", method) == 0) && + (strcmp("org.freedesktop.DBus.Introspectable", iface) == 0)) { + return Introspect(msg); + } + + nsAutoCString ourInterfaceName; + ourInterfaceName = nsPrintfCString("org.mozilla.%s", mAppName.get()); + + if ((strcmp("OpenURL", method) == 0) && + (strcmp(ourInterfaceName.get(), iface) == 0)) { + return OpenURL(msg); + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +void nsDBusRemoteServer::UnregisterDBusInterface(DBusConnection* aConnection) { + NS_ASSERTION(mConnection == aConnection, "Wrong D-Bus connection."); + // Not implemented +} + +static DBusHandlerResult message_handler(DBusConnection* conn, DBusMessage* msg, + void* user_data) { + auto interface = static_cast(user_data); + return interface->HandleDBusMessage(conn, msg); +} + +static void unregister(DBusConnection* conn, void* user_data) { + auto interface = static_cast(user_data); + interface->UnregisterDBusInterface(conn); +} + +static DBusObjectPathVTable remoteHandlersTable = { + .unregister_function = unregister, + .message_function = message_handler, +}; + +nsresult nsDBusRemoteServer::Startup(const char* aAppName, + const char* aProfileName) { + if (mConnection && dbus_connection_get_is_connected(mConnection)) { + // We're already connected so we don't need to reconnect + return NS_ERROR_ALREADY_INITIALIZED; + } + + // Don't even try to start without any application/profile name + if (!aAppName || aAppName[0] == '\0' || !aProfileName || + aProfileName[0] == '\0') + return NS_ERROR_INVALID_ARG; + + mConnection = dont_AddRef(dbus_bus_get(DBUS_BUS_SESSION, nullptr)); + if (!mConnection) { + return NS_ERROR_FAILURE; + } + auto releaseDBusConnection = + mozilla::MakeScopeExit([&] { mConnection = nullptr; }); + dbus_connection_set_exit_on_disconnect(mConnection, false); + dbus_connection_setup_with_g_main(mConnection, nullptr); + + mAppName = aAppName; + mozilla::XREAppData::SanitizeNameForDBus(mAppName); + + nsAutoCString profileName; + MOZ_TRY( + mozilla::Base64Encode(aProfileName, strlen(aProfileName), profileName)); + + mozilla::XREAppData::SanitizeNameForDBus(profileName); + + nsPrintfCString busName("org.mozilla.%s.%s", mAppName.get(), + profileName.get()); + if (busName.Length() > DBUS_MAXIMUM_NAME_LENGTH) + busName.Truncate(DBUS_MAXIMUM_NAME_LENGTH); + + static auto sDBusValidateBusName = (bool (*)(const char*, DBusError*))dlsym( + RTLD_DEFAULT, "dbus_validate_bus_name"); + if (!sDBusValidateBusName) { + return NS_ERROR_FAILURE; + } + + // We don't have a valid busName yet - try to create a default one. + if (!sDBusValidateBusName(busName.get(), nullptr)) { + busName = nsPrintfCString("org.mozilla.%s.%s", mAppName.get(), "default"); + if (!sDBusValidateBusName(busName.get(), nullptr)) { + // We failed completelly to get a valid bus name - just quit + // to prevent crash at dbus_bus_request_name(). + return NS_ERROR_FAILURE; + } + } + + DBusError err; + dbus_error_init(&err); + dbus_bus_request_name(mConnection, busName.get(), DBUS_NAME_FLAG_DO_NOT_QUEUE, + &err); + // The interface is already owned - there is another application/profile + // instance already running. + if (dbus_error_is_set(&err)) { + dbus_error_free(&err); + return NS_ERROR_FAILURE; + } + + mPathName = nsPrintfCString("/org/mozilla/%s/Remote", mAppName.get()); + static auto sDBusValidatePathName = (bool (*)(const char*, DBusError*))dlsym( + RTLD_DEFAULT, "dbus_validate_path"); + if (!sDBusValidatePathName || + !sDBusValidatePathName(mPathName.get(), nullptr)) { + return NS_ERROR_FAILURE; + } + if (!dbus_connection_register_object_path(mConnection, mPathName.get(), + &remoteHandlersTable, this)) { + return NS_ERROR_FAILURE; + } + + releaseDBusConnection.release(); + return NS_OK; +} + +void nsDBusRemoteServer::Shutdown() { + if (!mConnection) { + return; + } + + dbus_connection_unregister_object_path(mConnection, mPathName.get()); + + // dbus_connection_unref() will be called by RefPtr here. + mConnection = nullptr; +} -- cgit v1.2.3