toolkit/xre/nsNativeAppSupportUnix.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nsNativeAppSupportBase.h"
michael@0 7 #include "nsCOMPtr.h"
michael@0 8 #include "nsXPCOM.h"
michael@0 9 #include "nsISupportsPrimitives.h"
michael@0 10 #include "nsIObserverService.h"
michael@0 11 #include "nsIAppStartup.h"
michael@0 12 #include "nsServiceManagerUtils.h"
michael@0 13 #include "prlink.h"
michael@0 14 #include "nsXREDirProvider.h"
michael@0 15 #include "nsReadableUtils.h"
michael@0 16
michael@0 17 #include "nsIFile.h"
michael@0 18 #include "nsDirectoryServiceDefs.h"
michael@0 19 #include "nsICommandLineRunner.h"
michael@0 20 #include "nsIWindowMediator.h"
michael@0 21 #include "nsPIDOMWindow.h"
michael@0 22 #include "nsIDocShell.h"
michael@0 23 #include "nsIBaseWindow.h"
michael@0 24 #include "nsIWidget.h"
michael@0 25 #include "nsIWritablePropertyBag2.h"
michael@0 26 #include "nsIPrefService.h"
michael@0 27 #include "mozilla/Services.h"
michael@0 28
michael@0 29 #include <stdlib.h>
michael@0 30 #include <glib.h>
michael@0 31 #include <glib-object.h>
michael@0 32 #include <gtk/gtk.h>
michael@0 33
michael@0 34 #ifdef MOZ_X11
michael@0 35 #include <gdk/gdkx.h>
michael@0 36 #include <X11/Xatom.h>
michael@0 37 #endif
michael@0 38
michael@0 39 #ifdef MOZ_ENABLE_DBUS
michael@0 40 #include <dbus/dbus.h>
michael@0 41 #endif
michael@0 42
michael@0 43 #define MIN_GTK_MAJOR_VERSION 2
michael@0 44 #define MIN_GTK_MINOR_VERSION 10
michael@0 45 #define UNSUPPORTED_GTK_MSG "We're sorry, this application requires a version of the GTK+ library that is not installed on your computer.\n\n\
michael@0 46 You have GTK+ %d.%d.\nThis application requires GTK+ %d.%d or newer.\n\n\
michael@0 47 Please upgrade your GTK+ library if you wish to use this application."
michael@0 48
michael@0 49 typedef struct _GnomeProgram GnomeProgram;
michael@0 50 typedef struct _GnomeModuleInfo GnomeModuleInfo;
michael@0 51 typedef struct _GnomeClient GnomeClient;
michael@0 52
michael@0 53 typedef enum {
michael@0 54 GNOME_SAVE_GLOBAL,
michael@0 55 GNOME_SAVE_LOCAL,
michael@0 56 GNOME_SAVE_BOTH
michael@0 57 } GnomeSaveStyle;
michael@0 58
michael@0 59 typedef enum {
michael@0 60 GNOME_INTERACT_NONE,
michael@0 61 GNOME_INTERACT_ERRORS,
michael@0 62 GNOME_INTERACT_ANY
michael@0 63 } GnomeInteractStyle;
michael@0 64
michael@0 65 typedef enum {
michael@0 66 GNOME_DIALOG_ERROR,
michael@0 67 GNOME_DIALOG_NORMAL
michael@0 68 } GnomeDialogType;
michael@0 69
michael@0 70 typedef GnomeProgram * (*_gnome_program_init_fn)(const char *, const char *,
michael@0 71 const GnomeModuleInfo *, int,
michael@0 72 char **, const char *, ...);
michael@0 73 typedef GnomeProgram * (*_gnome_program_get_fn)(void);
michael@0 74 typedef const GnomeModuleInfo * (*_libgnomeui_module_info_get_fn)();
michael@0 75 typedef GnomeClient * (*_gnome_master_client_fn)(void);
michael@0 76 typedef void (*_gnome_client_set_restart_command_fn)(GnomeClient*, gint, gchar*[]);
michael@0 77
michael@0 78 static _gnome_client_set_restart_command_fn gnome_client_set_restart_command;
michael@0 79
michael@0 80 gboolean save_yourself_cb(GnomeClient *client, gint phase,
michael@0 81 GnomeSaveStyle style, gboolean shutdown,
michael@0 82 GnomeInteractStyle interact, gboolean fast,
michael@0 83 gpointer user_data)
michael@0 84 {
michael@0 85 nsCOMPtr<nsIObserverService> obsServ =
michael@0 86 mozilla::services::GetObserverService();
michael@0 87
michael@0 88 nsCOMPtr<nsISupportsPRBool> didSaveSession =
michael@0 89 do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID);
michael@0 90
michael@0 91 if (!obsServ || !didSaveSession)
michael@0 92 return TRUE; // OOM
michael@0 93
michael@0 94 // Notify observers to save the session state
michael@0 95 didSaveSession->SetData(false);
michael@0 96 obsServ->NotifyObservers(didSaveSession, "session-save", nullptr);
michael@0 97
michael@0 98 bool status;
michael@0 99 didSaveSession->GetData(&status);
michael@0 100
michael@0 101 // If there was no session saved and the save_yourself request is
michael@0 102 // caused by upcoming shutdown we like to prepare for it
michael@0 103 if (!status && shutdown) {
michael@0 104 nsCOMPtr<nsISupportsPRBool> cancelQuit =
michael@0 105 do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID);
michael@0 106
michael@0 107 cancelQuit->SetData(false);
michael@0 108 obsServ->NotifyObservers(cancelQuit, "quit-application-requested", nullptr);
michael@0 109
michael@0 110 bool abortQuit;
michael@0 111 cancelQuit->GetData(&abortQuit);
michael@0 112 }
michael@0 113
michael@0 114 return TRUE;
michael@0 115 }
michael@0 116
michael@0 117 void die_cb(GnomeClient *client, gpointer user_data)
michael@0 118 {
michael@0 119 nsCOMPtr<nsIAppStartup> appService =
michael@0 120 do_GetService("@mozilla.org/toolkit/app-startup;1");
michael@0 121
michael@0 122 if (appService)
michael@0 123 appService->Quit(nsIAppStartup::eForceQuit);
michael@0 124 }
michael@0 125
michael@0 126 class nsNativeAppSupportUnix : public nsNativeAppSupportBase
michael@0 127 {
michael@0 128 public:
michael@0 129 NS_IMETHOD Start(bool* aRetVal);
michael@0 130 NS_IMETHOD Stop(bool *aResult);
michael@0 131 NS_IMETHOD Enable();
michael@0 132
michael@0 133 private:
michael@0 134 };
michael@0 135
michael@0 136 NS_IMETHODIMP
michael@0 137 nsNativeAppSupportUnix::Start(bool *aRetVal)
michael@0 138 {
michael@0 139 NS_ASSERTION(gAppData, "gAppData must not be null.");
michael@0 140
michael@0 141 // The dbus library is used by both nsWifiScannerDBus and BluetoothDBusService,
michael@0 142 // from diffrent threads. This could lead to race conditions if the dbus is not
michael@0 143 // initialized before making any other library calls.
michael@0 144 #ifdef MOZ_ENABLE_DBUS
michael@0 145 dbus_threads_init_default();
michael@0 146 #endif
michael@0 147
michael@0 148 #if (MOZ_WIDGET_GTK == 2)
michael@0 149 if (gtk_major_version < MIN_GTK_MAJOR_VERSION ||
michael@0 150 (gtk_major_version == MIN_GTK_MAJOR_VERSION && gtk_minor_version < MIN_GTK_MINOR_VERSION)) {
michael@0 151 GtkWidget* versionErrDialog = gtk_message_dialog_new(nullptr,
michael@0 152 GtkDialogFlags(GTK_DIALOG_MODAL |
michael@0 153 GTK_DIALOG_DESTROY_WITH_PARENT),
michael@0 154 GTK_MESSAGE_ERROR,
michael@0 155 GTK_BUTTONS_OK,
michael@0 156 UNSUPPORTED_GTK_MSG,
michael@0 157 gtk_major_version,
michael@0 158 gtk_minor_version,
michael@0 159 MIN_GTK_MAJOR_VERSION,
michael@0 160 MIN_GTK_MINOR_VERSION);
michael@0 161 gtk_dialog_run(GTK_DIALOG(versionErrDialog));
michael@0 162 gtk_widget_destroy(versionErrDialog);
michael@0 163 exit(0);
michael@0 164 }
michael@0 165 #endif
michael@0 166
michael@0 167 *aRetVal = true;
michael@0 168
michael@0 169 #if defined(MOZ_X11) && (MOZ_WIDGET_GTK == 2)
michael@0 170
michael@0 171 PRLibrary *gnomeuiLib = PR_LoadLibrary("libgnomeui-2.so.0");
michael@0 172 if (!gnomeuiLib)
michael@0 173 return NS_OK;
michael@0 174
michael@0 175 PRLibrary *gnomeLib = PR_LoadLibrary("libgnome-2.so.0");
michael@0 176 if (!gnomeLib) {
michael@0 177 PR_UnloadLibrary(gnomeuiLib);
michael@0 178 return NS_OK;
michael@0 179 }
michael@0 180
michael@0 181 _gnome_program_init_fn gnome_program_init =
michael@0 182 (_gnome_program_init_fn)PR_FindFunctionSymbol(gnomeLib, "gnome_program_init");
michael@0 183 _gnome_program_get_fn gnome_program_get =
michael@0 184 (_gnome_program_get_fn)PR_FindFunctionSymbol(gnomeLib, "gnome_program_get");
michael@0 185 _libgnomeui_module_info_get_fn libgnomeui_module_info_get = (_libgnomeui_module_info_get_fn)PR_FindFunctionSymbol(gnomeuiLib, "libgnomeui_module_info_get");
michael@0 186 if (!gnome_program_init || !gnome_program_get || !libgnomeui_module_info_get) {
michael@0 187 PR_UnloadLibrary(gnomeuiLib);
michael@0 188 PR_UnloadLibrary(gnomeLib);
michael@0 189 return NS_OK;
michael@0 190 }
michael@0 191
michael@0 192 #endif /* MOZ_X11 && (MOZ_WIDGET_GTK == 2) */
michael@0 193
michael@0 194 #ifdef ACCESSIBILITY
michael@0 195 // We will load gail, atk-bridge by ourself later
michael@0 196 // We can't run atk-bridge init here, because gail get the control
michael@0 197 // Set GNOME_ACCESSIBILITY to 0 can avoid this
michael@0 198 static const char *accEnv = "GNOME_ACCESSIBILITY";
michael@0 199 const char *accOldValue = getenv(accEnv);
michael@0 200 setenv(accEnv, "0", 1);
michael@0 201 #endif
michael@0 202
michael@0 203 #if defined(MOZ_X11) && (MOZ_WIDGET_GTK == 2)
michael@0 204 if (!gnome_program_get()) {
michael@0 205 gnome_program_init("Gecko", "1.0", libgnomeui_module_info_get(),
michael@0 206 gArgc, gArgv, nullptr);
michael@0 207 }
michael@0 208 #endif /* MOZ_X11 && (MOZ_WIDGET_GTK == 2) */
michael@0 209
michael@0 210 #ifdef ACCESSIBILITY
michael@0 211 if (accOldValue) {
michael@0 212 setenv(accEnv, accOldValue, 1);
michael@0 213 } else {
michael@0 214 unsetenv(accEnv);
michael@0 215 }
michael@0 216 #endif
michael@0 217
michael@0 218 // Careful! These libraries cannot be unloaded after this point because
michael@0 219 // gnome_program_init causes atexit handlers to be registered. Strange
michael@0 220 // crashes will occur if these libraries are unloaded.
michael@0 221
michael@0 222 // TODO GTK3 - see Bug 694570 - Stop using libgnome and libgnomeui on Linux
michael@0 223 #if defined(MOZ_X11) && (MOZ_WIDGET_GTK == 2)
michael@0 224 gnome_client_set_restart_command = (_gnome_client_set_restart_command_fn)
michael@0 225 PR_FindFunctionSymbol(gnomeuiLib, "gnome_client_set_restart_command");
michael@0 226
michael@0 227 _gnome_master_client_fn gnome_master_client = (_gnome_master_client_fn)
michael@0 228 PR_FindFunctionSymbol(gnomeuiLib, "gnome_master_client");
michael@0 229
michael@0 230 GnomeClient *client = gnome_master_client();
michael@0 231 g_signal_connect(client, "save-yourself", G_CALLBACK(save_yourself_cb), nullptr);
michael@0 232 g_signal_connect(client, "die", G_CALLBACK(die_cb), nullptr);
michael@0 233
michael@0 234 // Set the correct/requested restart command in any case.
michael@0 235
michael@0 236 // Is there a request to suppress default binary launcher?
michael@0 237 nsAutoCString path;
michael@0 238 char* argv1 = getenv("MOZ_APP_LAUNCHER");
michael@0 239
michael@0 240 if(!argv1) {
michael@0 241 // Tell the desktop the command for restarting us so that we can be part of XSMP session restore
michael@0 242 NS_ASSERTION(gDirServiceProvider, "gDirServiceProvider is NULL! This shouldn't happen!");
michael@0 243 nsCOMPtr<nsIFile> executablePath;
michael@0 244 nsresult rv;
michael@0 245
michael@0 246 bool dummy;
michael@0 247 rv = gDirServiceProvider->GetFile(XRE_EXECUTABLE_FILE, &dummy, getter_AddRefs(executablePath));
michael@0 248
michael@0 249 if (NS_SUCCEEDED(rv)) {
michael@0 250 // Strip off the -bin suffix to get the shell script we should run; this is what Breakpad does
michael@0 251 nsAutoCString leafName;
michael@0 252 rv = executablePath->GetNativeLeafName(leafName);
michael@0 253 if (NS_SUCCEEDED(rv) && StringEndsWith(leafName, NS_LITERAL_CSTRING("-bin"))) {
michael@0 254 leafName.SetLength(leafName.Length() - strlen("-bin"));
michael@0 255 executablePath->SetNativeLeafName(leafName);
michael@0 256 }
michael@0 257
michael@0 258 executablePath->GetNativePath(path);
michael@0 259 argv1 = (char*)(path.get());
michael@0 260 }
michael@0 261 }
michael@0 262
michael@0 263 if (argv1) {
michael@0 264 gnome_client_set_restart_command(client, 1, &argv1);
michael@0 265 }
michael@0 266 #endif /* MOZ_X11 && (MOZ_WIDGET_GTK == 2) */
michael@0 267
michael@0 268 return NS_OK;
michael@0 269 }
michael@0 270
michael@0 271 NS_IMETHODIMP
michael@0 272 nsNativeAppSupportUnix::Stop(bool *aResult)
michael@0 273 {
michael@0 274 NS_ENSURE_ARG(aResult);
michael@0 275 *aResult = true;
michael@0 276 return NS_OK;
michael@0 277 }
michael@0 278
michael@0 279 NS_IMETHODIMP
michael@0 280 nsNativeAppSupportUnix::Enable()
michael@0 281 {
michael@0 282 return NS_OK;
michael@0 283 }
michael@0 284
michael@0 285 nsresult
michael@0 286 NS_CreateNativeAppSupport(nsINativeAppSupport **aResult)
michael@0 287 {
michael@0 288 nsNativeAppSupportBase* native = new nsNativeAppSupportUnix();
michael@0 289 if (!native)
michael@0 290 return NS_ERROR_OUT_OF_MEMORY;
michael@0 291
michael@0 292 *aResult = native;
michael@0 293 NS_ADDREF(*aResult);
michael@0 294
michael@0 295 return NS_OK;
michael@0 296 }

mercurial