Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Nov 2017 06:25:10 +0000 (UTC)
From:      Jan Beich <jbeich@FreeBSD.org>
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
Message-ID:  <201711220625.vAM6PA5P014946@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <gdk/gdkx.h>
+-#include <X11/Xatom.h>
++#include <X11/ICE/ICElib.h>
++#include <X11/SM/SMlib.h>
++#include <fcntl.h>
++#include "nsThreadUtils.h"
++
++#include <pwd.h>
+ #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<nsNativeAppSupportUnix *>(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<IceConn>(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<GIOCondition>(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<nsNativeAppSupportUnix *>(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<nsIObserverService> obsServ =
+     mozilla::services::GetObserverService();
++  if (!obsServ) {
++    SmcInteractDone(mSessionConnection, False);
++    SmcSaveYourselfDone(mSessionConnection, True);
++    SetClientState(STATE_IDLE);
++    return;
++  }
+ 
+-  nsCOMPtr<nsISupportsPRBool> didSaveSession =
++  nsCOMPtr<nsISupportsPRBool> 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<nsIAppStartup> 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<nsNativeAppSupportUnix *>(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<nsIObserverService> 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<nsISupportsPRBool> cancelQuit =
++  bool status = false;
++  if (save_style != SmSaveGlobal) {
++    nsCOMPtr<nsISupportsPRBool> 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<nsIAppStartup> 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<nsNativeAppSupportUnix *>(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<SmPointer>(const_cast<char*>(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<char*>(name);
++  prop.type = const_cast<char*>(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<SmPointer>(this);
++
++    callbacks.die.callback = nsNativeAppSupportUnix::DieCB;
++    callbacks.die.client_data = static_cast<SmPointer>(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<SmPointer>(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<nsIFile> 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 <gtk/gtkversion.h>
++
+ #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 <gdk/gdkx.h>
+ #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)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201711220625.vAM6PA5P014946>