From owner-svn-ports-head@freebsd.org Wed Nov 22 06:25:12 2017 Return-Path: Delivered-To: svn-ports-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 7BA81DE1FEB; Wed, 22 Nov 2017 06:25:12 +0000 (UTC) (envelope-from jbeich@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 24B7D6E735; Wed, 22 Nov 2017 06:25:12 +0000 (UTC) (envelope-from jbeich@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id vAM6PBTU014952; Wed, 22 Nov 2017 06:25:11 GMT (envelope-from jbeich@FreeBSD.org) Received: (from jbeich@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id vAM6PA5P014946; Wed, 22 Nov 2017 06:25:10 GMT (envelope-from jbeich@FreeBSD.org) Message-Id: <201711220625.vAM6PA5P014946@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jbeich set sender to jbeich@FreeBSD.org using -f From: Jan Beich Date: Wed, 22 Nov 2017 06:25:10 +0000 (UTC) To: ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org Subject: svn commit: r454670 - in head: Mk www/firefox www/libxul www/libxul/files X-SVN-Group: ports-head X-SVN-Commit-Author: jbeich X-SVN-Commit-Paths: in head: Mk www/firefox www/libxul www/libxul/files X-SVN-Commit-Revision: 454670 X-SVN-Commit-Repository: ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-ports-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the ports tree for head List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 22 Nov 2017 06:25:12 -0000 Author: jbeich Date: Wed Nov 22 06:25:10 2017 New Revision: 454670 URL: https://svnweb.freebsd.org/changeset/ports/454670 Log: gecko: drop GNOMEUI option Added: head/www/libxul/files/patch-bug694570 (contents, props changed) Modified: head/Mk/bsd.gecko.mk (contents, props changed) head/www/firefox/Makefile (contents, props changed) head/www/firefox/Makefile.options (contents, props changed) head/www/libxul/Makefile (contents, props changed) Modified: head/Mk/bsd.gecko.mk ============================================================================== --- head/Mk/bsd.gecko.mk Wed Nov 22 06:24:59 2017 (r454669) +++ head/Mk/bsd.gecko.mk Wed Nov 22 06:25:10 2017 (r454670) @@ -333,16 +333,6 @@ MOZ_OPTIONS+= --enable-gconf MOZ_OPTIONS+= --disable-gconf .endif -.if ${MOZILLA_VER:R:R} < 55 -.if ${PORT_OPTIONS:MGNOMEUI} -BUILD_DEPENDS+= ${libgnomeui_DETECT}:${libgnomeui_LIB_DEPENDS:C/.*://} -USE_GNOME+= libgnomeui:build -MOZ_OPTIONS+= --enable-gnomeui -.else -MOZ_OPTIONS+= --disable-gnomeui -.endif -.endif # Mozilla < 55 - .if ${PORT_OPTIONS:MLIBPROXY} LIB_DEPENDS+= libproxy.so:net/libproxy MOZ_OPTIONS+= --enable-libproxy Modified: head/www/firefox/Makefile ============================================================================== --- head/www/firefox/Makefile Wed Nov 22 06:24:59 2017 (r454669) +++ head/www/firefox/Makefile Wed Nov 22 06:25:10 2017 (r454670) @@ -46,7 +46,6 @@ MOZ_OPTIONS= --enable-application=browser \ --enable-official-branding OPTIONS_DEFAULT= BUNDLED_CAIRO -OPTIONS_EXCLUDE= GNOMEUI .include "${.CURDIR}/../../www/firefox/Makefile.options" Modified: head/www/firefox/Makefile.options ============================================================================== --- head/www/firefox/Makefile.options Wed Nov 22 06:24:59 2017 (r454669) +++ head/www/firefox/Makefile.options Wed Nov 22 06:25:10 2017 (r454670) @@ -1,7 +1,7 @@ # -*- makefile-bsdmake -*- OPTIONS_DEFINE+= BUNDLED_CAIRO CANBERRA DBUS DEBUG DTRACE FFMPEG GCONF \ - GNOMEUI INTEGER_SAMPLES LIBPROXY \ + INTEGER_SAMPLES LIBPROXY \ OPTIMIZED_CFLAGS PROFILE TEST OPTIONS_DEFAULT+= DBUS DTRACE FFMPEG OPTIMIZED_CFLAGS PROFILE \ @@ -26,7 +26,6 @@ OPTIONS_EXCLUDE_aarch64= DTRACE BUNDLED_CAIRO_DESC?= Use bundled fork of cairo-1.9.5 CANBERRA_DESC?= Sound theme alerts -GNOMEUI_DESC?= libgnomeui support module INTEGER_SAMPLES_DESC?= Integer audio sample format LIBPROXY_DESC?= Proxy support via libproxy LIGHTNING_DESC?= Calendar extension Modified: head/www/libxul/Makefile ============================================================================== --- head/www/libxul/Makefile Wed Nov 22 06:24:59 2017 (r454669) +++ head/www/libxul/Makefile Wed Nov 22 06:25:10 2017 (r454670) @@ -3,7 +3,7 @@ PORTNAME= libxul DISTVERSION= 45.9.0 -PORTREVISION= 7 +PORTREVISION= 8 CATEGORIES?= www devel MASTER_SITES= MOZILLA/firefox/releases/${DISTVERSION}esr/source \ MOZILLA/firefox/candidates/${DISTVERSION}esr-candidates/build3/source Added: head/www/libxul/files/patch-bug694570 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/libxul/files/patch-bug694570 Wed Nov 22 06:25:10 2017 (r454670) @@ -0,0 +1,794 @@ +diff --git toolkit/xre/nsAppRunner.cpp toolkit/xre/nsAppRunner.cpp +index b4077bc883f1..d088dcb3fa46 100644 +--- toolkit/xre/nsAppRunner.cpp ++++ toolkit/xre/nsAppRunner.cpp +@@ -275,6 +275,7 @@ SaveToEnv(const char *putenv) + if (expr) + PR_SetEnv(expr); + // We intentionally leak |expr| here since it is required by PR_SetEnv. ++ MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(expr); + } + + // Tests that an environment variable exists and has a value +diff --git toolkit/xre/nsNativeAppSupportUnix.cpp toolkit/xre/nsNativeAppSupportUnix.cpp +index 96ee13034f77..75652e38f5db 100644 +--- toolkit/xre/nsNativeAppSupportUnix.cpp ++++ toolkit/xre/nsNativeAppSupportUnix.cpp +@@ -1,4 +1,5 @@ +-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* vim: set ts=8 sts=2 et sw=2 tw=80: */ + /* 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/. */ +@@ -33,7 +34,12 @@ + + #ifdef MOZ_X11 + #include +-#include ++#include ++#include ++#include ++#include "nsThreadUtils.h" ++ ++#include + #endif + + #ifdef MOZ_ENABLE_DBUS +@@ -46,94 +52,398 @@ + You have GTK+ %d.%d.\nThis application requires GTK+ %d.%d or newer.\n\n\ + Please upgrade your GTK+ library if you wish to use this application." + +-typedef struct _GnomeProgram GnomeProgram; +-typedef struct _GnomeModuleInfo GnomeModuleInfo; +-typedef struct _GnomeClient GnomeClient; +- +-typedef enum { +- GNOME_SAVE_GLOBAL, +- GNOME_SAVE_LOCAL, +- GNOME_SAVE_BOTH +-} GnomeSaveStyle; +- +-typedef enum { +- GNOME_INTERACT_NONE, +- GNOME_INTERACT_ERRORS, +- GNOME_INTERACT_ANY +-} GnomeInteractStyle; +- +-typedef enum { +- GNOME_DIALOG_ERROR, +- GNOME_DIALOG_NORMAL +-} GnomeDialogType; +- +-#if defined(MOZ_X11) && (MOZ_WIDGET_GTK == 2) +-typedef GnomeProgram * (*_gnome_program_init_fn)(const char *, const char *, +- const GnomeModuleInfo *, int, +- char **, const char *, ...); +-typedef GnomeProgram * (*_gnome_program_get_fn)(void); +-typedef const GnomeModuleInfo * (*_libgnomeui_module_info_get_fn)(); +-typedef GnomeClient * (*_gnome_master_client_fn)(void); +-typedef void (*_gnome_client_set_restart_command_fn)(GnomeClient*, gint, gchar*[]); +- +-static _gnome_client_set_restart_command_fn gnome_client_set_restart_command; ++#if MOZ_X11 ++#undef IceSetIOErrorHandler ++#undef IceAddConnectionWatch ++#undef IceConnectionNumber ++#undef IceProcessMessages ++#undef IceGetConnectionContext ++#undef SmcInteractDone ++#undef SmcSaveYourselfDone ++#undef SmcInteractRequest ++#undef SmcCloseConnection ++#undef SmcOpenConnection ++#undef SmcSetProperties ++ ++typedef IceIOErrorHandler (*IceSetIOErrorHandlerFn) (IceIOErrorHandler); ++typedef int (*IceAddConnectionWatchFn) (IceWatchProc, IcePointer); ++typedef int (*IceConnectionNumberFn) (IceConn); ++typedef IceProcessMessagesStatus (*IceProcessMessagesFn) (IceConn, IceReplyWaitInfo*, Bool*); ++typedef IcePointer (*IceGetConnectionContextFn) (IceConn); ++ ++typedef void (*SmcInteractDoneFn) (SmcConn, Bool); ++typedef void (*SmcSaveYourselfDoneFn) (SmcConn, Bool); ++typedef int (*SmcInteractRequestFn) (SmcConn, int, SmcInteractProc, SmPointer); ++typedef SmcCloseStatus (*SmcCloseConnectionFn) (SmcConn, int, char**); ++typedef SmcConn (*SmcOpenConnectionFn) (char*, SmPointer, int, int, ++ unsigned long, SmcCallbacks*, ++ const char*, char**, int, char*); ++typedef void (*SmcSetPropertiesFn) (SmcConn, int, SmProp**); ++ ++static IceSetIOErrorHandlerFn IceSetIOErrorHandlerPtr; ++static IceAddConnectionWatchFn IceAddConnectionWatchPtr; ++static IceConnectionNumberFn IceConnectionNumberPtr; ++static IceProcessMessagesFn IceProcessMessagesPtr; ++static IceGetConnectionContextFn IceGetConnectionContextPtr; ++static SmcInteractDoneFn SmcInteractDonePtr; ++static SmcSaveYourselfDoneFn SmcSaveYourselfDonePtr; ++static SmcInteractRequestFn SmcInteractRequestPtr; ++static SmcCloseConnectionFn SmcCloseConnectionPtr; ++static SmcOpenConnectionFn SmcOpenConnectionPtr; ++static SmcSetPropertiesFn SmcSetPropertiesPtr; ++ ++#define IceSetIOErrorHandler IceSetIOErrorHandlerPtr ++#define IceAddConnectionWatch IceAddConnectionWatchPtr ++#define IceConnectionNumber IceConnectionNumberPtr ++#define IceProcessMessages IceProcessMessagesPtr ++#define IceGetConnectionContext IceGetConnectionContextPtr ++#define SmcInteractDone SmcInteractDonePtr ++#define SmcSaveYourselfDone SmcSaveYourselfDonePtr ++#define SmcInteractRequest SmcInteractRequestPtr ++#define SmcCloseConnection SmcCloseConnectionPtr ++#define SmcOpenConnection SmcOpenConnectionPtr ++#define SmcSetProperties SmcSetPropertiesPtr ++ ++enum ClientState { ++ STATE_DISCONNECTED, ++ STATE_REGISTERING, ++ STATE_IDLE, ++ STATE_INTERACTING, ++ STATE_SHUTDOWN_CANCELLED ++}; ++ ++static const char *gClientStateTable[] = { ++ "DISCONNECTED", ++ "REGISTERING", ++ "IDLE", ++ "INTERACTING", ++ "SHUTDOWN_CANCELLED" ++}; ++ ++static LazyLogModule sMozSMLog("MozSM"); ++#endif /* MOZ_X11 */ ++ ++class nsNativeAppSupportUnix : public nsNativeAppSupportBase ++{ ++public: ++#if MOZ_X11 ++ nsNativeAppSupportUnix(): mSessionConnection(nullptr), ++ mClientState(STATE_DISCONNECTED) {}; ++ ~nsNativeAppSupportUnix() ++ { ++ // this goes out of scope after "web-workers-shutdown" async shutdown phase ++ // so it's safe to disconnect here (i.e. the application won't lose data) ++ DisconnectFromSM(); ++ }; ++ ++ void DisconnectFromSM(); ++#endif ++ NS_IMETHOD Start(bool* aRetVal); ++ NS_IMETHOD Stop(bool *aResult); ++ NS_IMETHOD Enable(); ++ ++private: ++#if MOZ_X11 ++ static void SaveYourselfCB(SmcConn smc_conn, SmPointer client_data, ++ int save_style, Bool shutdown, int interact_style, ++ Bool fast); ++ static void DieCB(SmcConn smc_conn, SmPointer client_data); ++ static void InteractCB(SmcConn smc_conn, SmPointer client_data); ++ static void SaveCompleteCB(SmcConn smc_conn, SmPointer client_data) {}; ++ static void ShutdownCancelledCB(SmcConn smc_conn, SmPointer client_data); ++ void DoInteract(); ++ void SetClientState(ClientState aState) ++ { ++ mClientState = aState; ++ MOZ_LOG(sMozSMLog, LogLevel::Debug, ("New state = %s\n", gClientStateTable[aState])); ++ } ++ ++ SmcConn mSessionConnection; ++ ClientState mClientState; + #endif ++}; + +-gboolean save_yourself_cb(GnomeClient *client, gint phase, +- GnomeSaveStyle style, gboolean shutdown, +- GnomeInteractStyle interact, gboolean fast, +- gpointer user_data) ++#if MOZ_X11 ++static gboolean ++process_ice_messages(IceConn connection) ++{ ++ IceProcessMessagesStatus status; ++ ++ status = IceProcessMessages(connection, nullptr, nullptr); ++ ++ switch (status) { ++ case IceProcessMessagesSuccess: ++ return TRUE; ++ ++ case IceProcessMessagesIOError: { ++ nsNativeAppSupportUnix *native = ++ static_cast(IceGetConnectionContext(connection)); ++ native->DisconnectFromSM(); ++ } ++ return FALSE; ++ ++ case IceProcessMessagesConnectionClosed: ++ return FALSE; ++ ++ default: ++ g_assert_not_reached (); ++ } ++} ++ ++static gboolean ++ice_iochannel_watch(GIOChannel *channel, GIOCondition condition, ++ gpointer client_data) ++{ ++ return process_ice_messages(static_cast(client_data)); ++} ++ ++static void ++ice_connection_watch(IceConn connection, IcePointer client_data, ++ Bool opening, IcePointer *watch_data) ++{ ++ guint watch_id; ++ ++ if (opening) { ++ GIOChannel *channel; ++ int fd = IceConnectionNumber(connection); ++ ++ fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC); ++ channel = g_io_channel_unix_new(fd); ++ watch_id = g_io_add_watch(channel, ++ static_cast(G_IO_IN | G_IO_ERR), ++ ice_iochannel_watch, connection); ++ g_io_channel_unref(channel); ++ ++ *watch_data = GUINT_TO_POINTER(watch_id); ++ } else { ++ watch_id = GPOINTER_TO_UINT(*watch_data); ++ g_source_remove(watch_id); ++ } ++} ++ ++static void ++ice_io_error_handler(IceConn connection) ++{ ++ // override the default handler which would exit the application; ++ // do nothing and let ICELib handle the failure of the connection gracefully. ++} ++ ++static void ++ice_init(void) ++{ ++ static bool initted = false; ++ ++ if (!initted) { ++ IceSetIOErrorHandler(ice_io_error_handler); ++ IceAddConnectionWatch(ice_connection_watch, nullptr); ++ initted = true; ++ } ++} ++ ++void ++nsNativeAppSupportUnix::InteractCB(SmcConn smc_conn, SmPointer client_data) ++{ ++ nsNativeAppSupportUnix *self = ++ static_cast(client_data); ++ ++ self->SetClientState(STATE_INTERACTING); ++ ++ // We do this asynchronously, as we spin the event loop recursively if ++ // a dialog is displayed. If we do this synchronously, we don't finish ++ // processing the current ICE event whilst the dialog is displayed, which ++ // means we won't process any more. libsm hates us if we do the InteractDone ++ // with a pending ShutdownCancelled, and we would certainly like to handle Die ++ // whilst a dialog is displayed ++ NS_DispatchToCurrentThread(NS_NewRunnableMethod(self, &nsNativeAppSupportUnix::DoInteract)); ++} ++ ++void ++nsNativeAppSupportUnix::DoInteract() + { + nsCOMPtr obsServ = + mozilla::services::GetObserverService(); ++ if (!obsServ) { ++ SmcInteractDone(mSessionConnection, False); ++ SmcSaveYourselfDone(mSessionConnection, True); ++ SetClientState(STATE_IDLE); ++ return; ++ } + +- nsCOMPtr didSaveSession = ++ nsCOMPtr cancelQuit = + do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID); + +- if (!obsServ || !didSaveSession) +- return TRUE; // OOM ++ bool abortQuit = false; ++ if (cancelQuit) { ++ cancelQuit->SetData(false); ++ obsServ->NotifyObservers(cancelQuit, "quit-application-requested", nullptr); + +- // Notify observers to save the session state +- didSaveSession->SetData(false); +- obsServ->NotifyObservers(didSaveSession, "session-save", nullptr); ++ cancelQuit->GetData(&abortQuit); ++ } ++ ++ if (!abortQuit && mClientState == STATE_DISCONNECTED) { ++ // The session manager disappeared, whilst we were interacting, so ++ // quit now ++ nsCOMPtr appService = ++ do_GetService("@mozilla.org/toolkit/app-startup;1"); ++ ++ if (appService) { ++ appService->Quit(nsIAppStartup::eForceQuit); ++ } ++ } else { ++ if (mClientState != STATE_SHUTDOWN_CANCELLED) { ++ // Only do this if the shutdown wasn't cancelled ++ SmcInteractDone(mSessionConnection, !!abortQuit); ++ SmcSaveYourselfDone(mSessionConnection, !abortQuit); ++ } ++ ++ SetClientState(STATE_IDLE); ++ } ++} + +- bool status; +- didSaveSession->GetData(&status); ++void ++nsNativeAppSupportUnix::SaveYourselfCB(SmcConn smc_conn, SmPointer client_data, ++ int save_style, Bool shutdown, ++ int interact_style, Bool fast) ++{ ++ nsNativeAppSupportUnix *self = ++ static_cast(client_data); ++ ++ // Expect a SaveYourselfCB if we're registering a new client. ++ // All properties are already set in Start() so just reply with ++ // SmcSaveYourselfDone if the callback matches the expected signature. ++ // ++ // Ancient versions (?) of xsm do not follow such an early SaveYourself with ++ // SaveComplete. This is a problem if the application freezes interaction ++ // while waiting for a response to SmcSaveYourselfDone. So never freeze ++ // interaction when in STATE_REGISTERING. ++ // ++ // That aside, we could treat each combination of flags appropriately and not ++ // special-case this. ++ if (self->mClientState == STATE_REGISTERING) { ++ self->SetClientState(STATE_IDLE); ++ ++ if (save_style == SmSaveLocal && interact_style == SmInteractStyleNone && ++ !shutdown && !fast) { ++ SmcSaveYourselfDone(self->mSessionConnection, True); ++ return; ++ } ++ } ++ ++ if (self->mClientState == STATE_SHUTDOWN_CANCELLED) { ++ // The last shutdown request was cancelled whilst we were interacting, ++ // and we haven't finished interacting yet. Switch the state back again ++ self->SetClientState(STATE_INTERACTING); ++ } ++ ++ nsCOMPtr obsServ = ++ mozilla::services::GetObserverService(); ++ if (!obsServ) { ++ SmcSaveYourselfDone(smc_conn, True); ++ return; ++ } + +- // If there was no session saved and the save_yourself request is +- // caused by upcoming shutdown we like to prepare for it +- if (!status && shutdown) { +- nsCOMPtr cancelQuit = ++ bool status = false; ++ if (save_style != SmSaveGlobal) { ++ nsCOMPtr didSaveSession = + do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID); + +- cancelQuit->SetData(false); +- obsServ->NotifyObservers(cancelQuit, "quit-application-requested", nullptr); ++ if (!didSaveSession) { ++ SmcSaveYourselfDone(smc_conn, True); ++ return; ++ } + +- bool abortQuit; +- cancelQuit->GetData(&abortQuit); ++ // Notify observers to save the session state ++ didSaveSession->SetData(false); ++ obsServ->NotifyObservers(didSaveSession, "session-save", nullptr); ++ ++ didSaveSession->GetData(&status); + } + +- return TRUE; ++ // If the interact style permits us to, we are shutting down and we didn't ++ // manage to (or weren't asked to) save the local state, then notify the user ++ // in advance that we are doing to quit (assuming that we aren't already ++ // doing so) ++ if (!status && shutdown && interact_style != SmInteractStyleNone) { ++ if (self->mClientState != STATE_INTERACTING) { ++ SmcInteractRequest(smc_conn, SmDialogNormal, ++ nsNativeAppSupportUnix::InteractCB, client_data); ++ } ++ } else { ++ SmcSaveYourselfDone(smc_conn, True); ++ } + } + +-void die_cb(GnomeClient *client, gpointer user_data) ++void ++nsNativeAppSupportUnix::DieCB(SmcConn smc_conn, SmPointer client_data) + { + nsCOMPtr appService = + do_GetService("@mozilla.org/toolkit/app-startup;1"); + +- if (appService) ++ if (appService) { + appService->Quit(nsIAppStartup::eForceQuit); ++ } ++ // Quit causes the shutdown to begin but the shutdown process is asynchronous ++ // so we can't DisconnectFromSM() yet + } + +-class nsNativeAppSupportUnix : public nsNativeAppSupportBase ++void ++nsNativeAppSupportUnix::ShutdownCancelledCB(SmcConn smc_conn, ++ SmPointer client_data) + { +-public: +- NS_IMETHOD Start(bool* aRetVal); +- NS_IMETHOD Stop(bool *aResult); +- NS_IMETHOD Enable(); ++ nsNativeAppSupportUnix *self = ++ static_cast(client_data); ++ ++ // Interacting is the only time when we wouldn't already have called ++ // SmcSaveYourselfDone. Do that now, then set the state to make sure we ++ // don't send it again after finishing interacting ++ if (self->mClientState == STATE_INTERACTING) { ++ SmcSaveYourselfDone(smc_conn, False); ++ self->SetClientState(STATE_SHUTDOWN_CANCELLED); ++ } ++} + +-private: +-}; ++void ++nsNativeAppSupportUnix::DisconnectFromSM() ++{ ++ // the SM is free to exit any time after we disconnect, so callers must be ++ // sure to have reached a sufficiently advanced phase of shutdown that there ++ // is no risk of data loss: ++ // e.g. all async writes are complete by the end of "profile-before-change" ++ if (mSessionConnection) { ++ SetClientState(STATE_DISCONNECTED); ++ SmcCloseConnection(mSessionConnection, 0, nullptr); ++ mSessionConnection = nullptr; ++ gdk_x11_set_sm_client_id(nullptr); // follow gnome-client behaviour ++ } ++} ++ ++static void ++SetSMValue(SmPropValue& val, const nsCString& data) ++{ ++ val.value = static_cast(const_cast(data.get())); ++ val.length = data.Length(); ++} ++ ++static void ++SetSMProperty(SmProp& prop, const char* name, const char* type, int numVals, ++ SmPropValue vals[]) ++{ ++ prop.name = const_cast(name); ++ prop.type = const_cast(type); ++ prop.num_vals = numVals; ++ prop.vals = vals; ++} ++#endif /* MOZ_X11 */ ++ ++static void RemoveArg(char **argv) ++{ ++ do { ++ *argv = *(argv + 1); ++ ++argv; ++ } while (*argv); ++ ++ --gArgc; ++} + + NS_IMETHODIMP + nsNativeAppSupportUnix::Start(bool *aRetVal) +@@ -168,79 +478,132 @@ nsNativeAppSupportUnix::Start(bool *aRetVal) + + *aRetVal = true; + +-#if defined(MOZ_X11) && (MOZ_WIDGET_GTK == 2) ++#ifdef MOZ_X11 ++ gboolean sm_disable = FALSE; ++ if (!getenv("SESSION_MANAGER")) { ++ sm_disable = TRUE; ++ } + +- PRLibrary *gnomeuiLib = PR_LoadLibrary("libgnomeui-2.so.0"); +- if (!gnomeuiLib) +- return NS_OK; ++ nsAutoCString prev_client_id; ++ ++ char **curarg = gArgv + 1; ++ while (*curarg) { ++ char *arg = *curarg; ++ if (arg[0] == '-' && arg[1] == '-') { ++ arg += 2; ++ if (!strcmp(arg, "sm-disable")) { ++ RemoveArg(curarg); ++ sm_disable = TRUE; ++ continue; ++ } else if (!strcmp(arg, "sm-client-id")) { ++ RemoveArg(curarg); ++ if (*curarg[0] != '-') { ++ prev_client_id = *curarg; ++ RemoveArg(curarg); ++ } ++ continue; ++ } ++ } + +- PRLibrary *gnomeLib = PR_LoadLibrary("libgnome-2.so.0"); +- if (!gnomeLib) { +- PR_UnloadLibrary(gnomeuiLib); +- return NS_OK; ++ ++curarg; + } + +- _gnome_program_init_fn gnome_program_init = +- (_gnome_program_init_fn)PR_FindFunctionSymbol(gnomeLib, "gnome_program_init"); +- _gnome_program_get_fn gnome_program_get = +- (_gnome_program_get_fn)PR_FindFunctionSymbol(gnomeLib, "gnome_program_get"); +- _libgnomeui_module_info_get_fn libgnomeui_module_info_get = (_libgnomeui_module_info_get_fn)PR_FindFunctionSymbol(gnomeuiLib, "libgnomeui_module_info_get"); +- if (!gnome_program_init || !gnome_program_get || !libgnomeui_module_info_get) { +- PR_UnloadLibrary(gnomeuiLib); +- PR_UnloadLibrary(gnomeLib); +- return NS_OK; ++ if (prev_client_id.IsEmpty()) { ++ prev_client_id = getenv("DESKTOP_AUTOSTART_ID"); + } + +-#endif /* MOZ_X11 && (MOZ_WIDGET_GTK == 2) */ ++ // We don't want child processes to use the same ID ++ unsetenv("DESKTOP_AUTOSTART_ID"); + +-#ifdef ACCESSIBILITY +- // We will load gail, atk-bridge by ourself later +- // We can't run atk-bridge init here, because gail get the control +- // Set GNOME_ACCESSIBILITY to 0 can avoid this +- static const char *accEnv = "GNOME_ACCESSIBILITY"; +- const char *accOldValue = getenv(accEnv); +- setenv(accEnv, "0", 1); +-#endif ++ char *client_id = nullptr; ++ if (!sm_disable) { ++ PRLibrary *iceLib = PR_LoadLibrary("libICE.so.6"); ++ if (!iceLib) { ++ return NS_OK; ++ } + +-#if defined(MOZ_X11) && (MOZ_WIDGET_GTK == 2) +- if (!gnome_program_get()) { +- gnome_program_init("Gecko", "1.0", libgnomeui_module_info_get(), +- gArgc, gArgv, nullptr); +- } +-#endif /* MOZ_X11 && (MOZ_WIDGET_GTK == 2) */ ++ PRLibrary *smLib = PR_LoadLibrary("libSM.so.6"); ++ if (!smLib) { ++ PR_UnloadLibrary(iceLib); ++ return NS_OK; ++ } + +-#ifdef ACCESSIBILITY +- if (accOldValue) { +- setenv(accEnv, accOldValue, 1); +- } else { +- unsetenv(accEnv); ++ IceSetIOErrorHandler = (IceSetIOErrorHandlerFn)PR_FindFunctionSymbol(iceLib, "IceSetIOErrorHandler"); ++ IceAddConnectionWatch = (IceAddConnectionWatchFn)PR_FindFunctionSymbol(iceLib, "IceAddConnectionWatch"); ++ IceConnectionNumber = (IceConnectionNumberFn)PR_FindFunctionSymbol(iceLib, "IceConnectionNumber"); ++ IceProcessMessages = (IceProcessMessagesFn)PR_FindFunctionSymbol(iceLib, "IceProcessMessages"); ++ IceGetConnectionContext = (IceGetConnectionContextFn)PR_FindFunctionSymbol(iceLib, "IceGetConnectionContext"); ++ if (!IceSetIOErrorHandler || !IceAddConnectionWatch || ++ !IceConnectionNumber || !IceProcessMessages || !IceGetConnectionContext) { ++ PR_UnloadLibrary(iceLib); ++ PR_UnloadLibrary(smLib); ++ return NS_OK; ++ } ++ ++ SmcInteractDone = (SmcInteractDoneFn)PR_FindFunctionSymbol(smLib, "SmcInteractDone"); ++ SmcSaveYourselfDone = (SmcSaveYourselfDoneFn)PR_FindFunctionSymbol(smLib, "SmcSaveYourselfDone"); ++ SmcInteractRequest = (SmcInteractRequestFn)PR_FindFunctionSymbol(smLib, "SmcInteractRequest"); ++ SmcCloseConnection = (SmcCloseConnectionFn)PR_FindFunctionSymbol(smLib, "SmcCloseConnection"); ++ SmcOpenConnection = (SmcOpenConnectionFn)PR_FindFunctionSymbol(smLib, "SmcOpenConnection"); ++ SmcSetProperties = (SmcSetPropertiesFn)PR_FindFunctionSymbol(smLib, "SmcSetProperties"); ++ if (!SmcInteractDone || !SmcSaveYourselfDone || !SmcInteractRequest || ++ !SmcCloseConnection || !SmcOpenConnection || !SmcSetProperties) { ++ PR_UnloadLibrary(iceLib); ++ PR_UnloadLibrary(smLib); ++ return NS_OK; ++ } ++ ++ ice_init(); ++ ++ // all callbacks are mandatory in libSM 1.0, so listen even if we don't care. ++ unsigned long mask = SmcSaveYourselfProcMask | SmcDieProcMask | ++ SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask; ++ ++ SmcCallbacks callbacks; ++ callbacks.save_yourself.callback = nsNativeAppSupportUnix::SaveYourselfCB; ++ callbacks.save_yourself.client_data = static_cast(this); ++ ++ callbacks.die.callback = nsNativeAppSupportUnix::DieCB; ++ callbacks.die.client_data = static_cast(this); ++ ++ callbacks.save_complete.callback = nsNativeAppSupportUnix::SaveCompleteCB; ++ callbacks.save_complete.client_data = nullptr; ++ ++ callbacks.shutdown_cancelled.callback = ++ nsNativeAppSupportUnix::ShutdownCancelledCB; ++ callbacks.shutdown_cancelled.client_data = static_cast(this); ++ ++ char errbuf[256]; ++ mSessionConnection = SmcOpenConnection(nullptr, this, SmProtoMajor, ++ SmProtoMinor, mask, &callbacks, ++ prev_client_id.get(), &client_id, ++ sizeof(errbuf), errbuf); + } +-#endif + +- // Careful! These libraries cannot be unloaded after this point because +- // gnome_program_init causes atexit handlers to be registered. Strange +- // crashes will occur if these libraries are unloaded. ++ if (!mSessionConnection) { ++ return NS_OK; ++ } + +- // TODO GTK3 - see Bug 694570 - Stop using libgnome and libgnomeui on Linux +-#if defined(MOZ_X11) && (MOZ_WIDGET_GTK == 2) +- gnome_client_set_restart_command = (_gnome_client_set_restart_command_fn) +- PR_FindFunctionSymbol(gnomeuiLib, "gnome_client_set_restart_command"); ++ LogModule::Init(); // need to make sure initialized before SetClientState ++ if (prev_client_id.IsEmpty() || ++ (client_id && !prev_client_id.Equals(client_id))) { ++ SetClientState(STATE_REGISTERING); ++ } else { ++ SetClientState(STATE_IDLE); ++ } + +- _gnome_master_client_fn gnome_master_client = (_gnome_master_client_fn) +- PR_FindFunctionSymbol(gnomeuiLib, "gnome_master_client"); ++ gdk_x11_set_sm_client_id(client_id); + +- GnomeClient *client = gnome_master_client(); +- g_signal_connect(client, "save-yourself", G_CALLBACK(save_yourself_cb), nullptr); +- g_signal_connect(client, "die", G_CALLBACK(die_cb), nullptr); ++ // Set SM Properties ++ // SmCloneCommand, SmProgram, SmRestartCommand, SmUserID are required ++ // properties so must be set, and must have a sensible fallback value. + +- // Set the correct/requested restart command in any case. ++ // Determine executable path to use for XSMP session restore + + // Is there a request to suppress default binary launcher? +- nsAutoCString path; +- char* argv1 = getenv("MOZ_APP_LAUNCHER"); ++ nsAutoCString path(getenv("MOZ_APP_LAUNCHER")); + +- if(!argv1) { +- // Tell the desktop the command for restarting us so that we can be part of XSMP session restore ++ if (path.IsEmpty()) { + NS_ASSERTION(gDirServiceProvider, "gDirServiceProvider is NULL! This shouldn't happen!"); + nsCOMPtr executablePath; + nsresult rv; +@@ -258,14 +621,60 @@ nsNativeAppSupportUnix::Start(bool *aRetVal) + } + + executablePath->GetNativePath(path); +- argv1 = (char*)(path.get()); + } + } + +- if (argv1) { +- gnome_client_set_restart_command(client, 1, &argv1); ++ if (path.IsEmpty()) { ++ // can't determine executable path. Best fallback is name from ++ // application.ini but it might not resolve to the same executable at ++ // launch time. ++ path = gAppData->name; // will always be set ++ ToLowerCase(path); ++ MOZ_LOG(sMozSMLog, LogLevel::Warning, ++ ("Could not determine executable path. Falling back to %s.", path.get())); + } +-#endif /* MOZ_X11 && (MOZ_WIDGET_GTK == 2) */ ++ ++ SmProp propRestart, propClone, propProgram, propUser, *props[4]; ++ SmPropValue valsRestart[3], valsClone[1], valsProgram[1], valsUser[1]; ++ int n = 0; ++ ++ NS_NAMED_LITERAL_CSTRING(kClientIDParam, "--sm-client-id"); ++ ++ SetSMValue(valsRestart[0], path); ++ SetSMValue(valsRestart[1], kClientIDParam); ++ SetSMValue(valsRestart[2], nsDependentCString(client_id)); ++ SetSMProperty(propRestart, SmRestartCommand, SmLISTofARRAY8, 3, valsRestart); ++ props[n++] = &propRestart; ++ ++ SetSMValue(valsClone[0], path); ++ SetSMProperty(propClone, SmCloneCommand, SmLISTofARRAY8, 1, valsClone); ++ props[n++] = &propClone; ++ ++ nsAutoCString appName(gAppData->name); // will always be set ++ ToLowerCase(appName); ++ ++ SetSMValue(valsProgram[0], appName); ++ SetSMProperty(propProgram, SmProgram, SmARRAY8, 1, valsProgram); ++ props[n++] = &propProgram; ++ ++ nsAutoCString userName; // username that started the program ++ struct passwd* pw = getpwuid(getuid()); ++ if (pw && pw->pw_name) { ++ userName = pw->pw_name; ++ } else { ++ userName = NS_LITERAL_CSTRING("nobody"); ++ MOZ_LOG(sMozSMLog, LogLevel::Warning, ++ ("Could not determine user-name. Falling back to %s.", userName.get())); ++ } ++ ++ SetSMValue(valsUser[0], userName); ++ SetSMProperty(propUser, SmUserID, SmARRAY8, 1, valsUser); ++ props[n++] = &propUser; ++ ++ SmcSetProperties(mSessionConnection, n, props); ++ ++ g_free(client_id); ++#endif /* MOZ_X11 */ + + return NS_OK; + } +diff --git widget/gtk/compat/gdk/gdkx.h widget/gtk/compat/gdk/gdkx.h +index 5d59720d2f91..240c12e3013a 100644 +--- widget/gtk/compat/gdk/gdkx.h ++++ widget/gtk/compat/gdk/gdkx.h +@@ -5,9 +5,14 @@ + #ifndef GDKX_WRAPPER_H + #define GDKX_WRAPPER_H + ++#include ++ + #define gdk_x11_window_foreign_new_for_display gdk_x11_window_foreign_new_for_display_ + #define gdk_x11_window_lookup_for_display gdk_x11_window_lookup_for_display_ + #define gdk_x11_window_get_xid gdk_x11_window_get_xid_ ++#if !GTK_CHECK_VERSION(2,24,0) ++#define gdk_x11_set_sm_client_id gdk_x11_set_sm_client_id_ ++#endif + #include_next + #undef gdk_x11_window_foreign_new_for_display + #undef gdk_x11_window_lookup_for_display +@@ -35,4 +40,12 @@ gdk_x11_window_get_xid(GdkWindow *window) + #define GDK_IS_X11_DISPLAY(a) (true) + #endif + ++#if !GTK_CHECK_VERSION(2,24,0) ++#undef gdk_x11_set_sm_client_id ++static inline void ++gdk_x11_set_sm_client_id (const gchar *sm_client_id) ++{ ++ gdk_set_sm_client_id(sm_client_id); ++} ++#endif + #endif /* GDKX_WRAPPER_H */ +diff --git widget/gtk/mozgtk/mozgtk.c widget/gtk/mozgtk/mozgtk.c +index 0bb4dfd04144..17c98fe3dd61 100644 +--- widget/gtk/mozgtk/mozgtk.c ++++ widget/gtk/mozgtk/mozgtk.c +@@ -132,6 +132,7 @@ STUB(gdk_x11_window_foreign_new_for_display) + STUB(gdk_x11_window_lookup_for_display) + STUB(gdk_x11_window_set_user_time) + STUB(gdk_x11_xatom_to_atom) ++STUB(gdk_x11_set_sm_client_id) + STUB(gtk_accel_label_new) + STUB(gtk_alignment_get_type) + STUB(gtk_alignment_new)