1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsNativeAppSupportBase.h"
9 #include "nsISupportsPrimitives.h"
10 #include "nsIObserverService.h"
11 #include "nsIAppStartup.h"
12 #include "nsServiceManagerUtils.h"
14 #include "nsXREDirProvider.h"
15 #include "nsReadableUtils.h"
18 #include "nsDirectoryServiceDefs.h"
19 #include "nsICommandLineRunner.h"
20 #include "nsIWindowMediator.h"
21 #include "nsPIDOMWindow.h"
22 #include "nsIDocShell.h"
23 #include "nsIBaseWindow.h"
24 #include "nsIWidget.h"
25 #include "nsIWritablePropertyBag2.h"
26 #include "nsIPrefService.h"
27 #include "mozilla/Services.h"
31 #include <glib-object.h>
36 #include <X11/Xatom.h>
39 #ifdef MOZ_ENABLE_DBUS
40 #include <dbus/dbus.h>
43 #define MIN_GTK_MAJOR_VERSION 2
44 #define MIN_GTK_MINOR_VERSION 10
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\
46 You have GTK+ %d.%d.\nThis application requires GTK+ %d.%d or newer.\n\n\
47 Please upgrade your GTK+ library if you wish to use this application."
49 typedef struct _GnomeProgram GnomeProgram
;
50 typedef struct _GnomeModuleInfo GnomeModuleInfo
;
51 typedef struct _GnomeClient GnomeClient
;
61 GNOME_INTERACT_ERRORS
,
70 typedef GnomeProgram
* (*_gnome_program_init_fn
)(const char *, const char *,
71 const GnomeModuleInfo
*, int,
72 char **, const char *, ...);
73 typedef GnomeProgram
* (*_gnome_program_get_fn
)(void);
74 typedef const GnomeModuleInfo
* (*_libgnomeui_module_info_get_fn
)();
75 typedef GnomeClient
* (*_gnome_master_client_fn
)(void);
76 typedef void (*_gnome_client_set_restart_command_fn
)(GnomeClient
*, gint
, gchar
*[]);
78 static _gnome_client_set_restart_command_fn gnome_client_set_restart_command
;
80 gboolean
save_yourself_cb(GnomeClient
*client
, gint phase
,
81 GnomeSaveStyle style
, gboolean shutdown
,
82 GnomeInteractStyle interact
, gboolean fast
,
85 nsCOMPtr
<nsIObserverService
> obsServ
=
86 mozilla::services::GetObserverService();
88 nsCOMPtr
<nsISupportsPRBool
> didSaveSession
=
89 do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID
);
91 if (!obsServ
|| !didSaveSession
)
94 // Notify observers to save the session state
95 didSaveSession
->SetData(false);
96 obsServ
->NotifyObservers(didSaveSession
, "session-save", nullptr);
99 didSaveSession
->GetData(&status
);
101 // If there was no session saved and the save_yourself request is
102 // caused by upcoming shutdown we like to prepare for it
103 if (!status
&& shutdown
) {
104 nsCOMPtr
<nsISupportsPRBool
> cancelQuit
=
105 do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID
);
107 cancelQuit
->SetData(false);
108 obsServ
->NotifyObservers(cancelQuit
, "quit-application-requested", nullptr);
111 cancelQuit
->GetData(&abortQuit
);
117 void die_cb(GnomeClient
*client
, gpointer user_data
)
119 nsCOMPtr
<nsIAppStartup
> appService
=
120 do_GetService("@mozilla.org/toolkit/app-startup;1");
123 appService
->Quit(nsIAppStartup::eForceQuit
);
126 class nsNativeAppSupportUnix
: public nsNativeAppSupportBase
129 NS_IMETHOD
Start(bool* aRetVal
);
130 NS_IMETHOD
Stop(bool *aResult
);
137 nsNativeAppSupportUnix::Start(bool *aRetVal
)
139 NS_ASSERTION(gAppData
, "gAppData must not be null.");
141 // The dbus library is used by both nsWifiScannerDBus and BluetoothDBusService,
142 // from diffrent threads. This could lead to race conditions if the dbus is not
143 // initialized before making any other library calls.
144 #ifdef MOZ_ENABLE_DBUS
145 dbus_threads_init_default();
148 #if (MOZ_WIDGET_GTK == 2)
149 if (gtk_major_version
< MIN_GTK_MAJOR_VERSION
||
150 (gtk_major_version
== MIN_GTK_MAJOR_VERSION
&& gtk_minor_version
< MIN_GTK_MINOR_VERSION
)) {
151 GtkWidget
* versionErrDialog
= gtk_message_dialog_new(nullptr,
152 GtkDialogFlags(GTK_DIALOG_MODAL
|
153 GTK_DIALOG_DESTROY_WITH_PARENT
),
159 MIN_GTK_MAJOR_VERSION
,
160 MIN_GTK_MINOR_VERSION
);
161 gtk_dialog_run(GTK_DIALOG(versionErrDialog
));
162 gtk_widget_destroy(versionErrDialog
);
169 #if defined(MOZ_X11) && (MOZ_WIDGET_GTK == 2)
171 PRLibrary
*gnomeuiLib
= PR_LoadLibrary("libgnomeui-2.so.0");
175 PRLibrary
*gnomeLib
= PR_LoadLibrary("libgnome-2.so.0");
177 PR_UnloadLibrary(gnomeuiLib
);
181 _gnome_program_init_fn gnome_program_init
=
182 (_gnome_program_init_fn
)PR_FindFunctionSymbol(gnomeLib
, "gnome_program_init");
183 _gnome_program_get_fn gnome_program_get
=
184 (_gnome_program_get_fn
)PR_FindFunctionSymbol(gnomeLib
, "gnome_program_get");
185 _libgnomeui_module_info_get_fn libgnomeui_module_info_get
= (_libgnomeui_module_info_get_fn
)PR_FindFunctionSymbol(gnomeuiLib
, "libgnomeui_module_info_get");
186 if (!gnome_program_init
|| !gnome_program_get
|| !libgnomeui_module_info_get
) {
187 PR_UnloadLibrary(gnomeuiLib
);
188 PR_UnloadLibrary(gnomeLib
);
192 #endif /* MOZ_X11 && (MOZ_WIDGET_GTK == 2) */
195 // We will load gail, atk-bridge by ourself later
196 // We can't run atk-bridge init here, because gail get the control
197 // Set GNOME_ACCESSIBILITY to 0 can avoid this
198 static const char *accEnv
= "GNOME_ACCESSIBILITY";
199 const char *accOldValue
= getenv(accEnv
);
200 setenv(accEnv
, "0", 1);
203 #if defined(MOZ_X11) && (MOZ_WIDGET_GTK == 2)
204 if (!gnome_program_get()) {
205 gnome_program_init("Gecko", "1.0", libgnomeui_module_info_get(),
206 gArgc
, gArgv
, nullptr);
208 #endif /* MOZ_X11 && (MOZ_WIDGET_GTK == 2) */
212 setenv(accEnv
, accOldValue
, 1);
218 // Careful! These libraries cannot be unloaded after this point because
219 // gnome_program_init causes atexit handlers to be registered. Strange
220 // crashes will occur if these libraries are unloaded.
222 // TODO GTK3 - see Bug 694570 - Stop using libgnome and libgnomeui on Linux
223 #if defined(MOZ_X11) && (MOZ_WIDGET_GTK == 2)
224 gnome_client_set_restart_command
= (_gnome_client_set_restart_command_fn
)
225 PR_FindFunctionSymbol(gnomeuiLib
, "gnome_client_set_restart_command");
227 _gnome_master_client_fn gnome_master_client
= (_gnome_master_client_fn
)
228 PR_FindFunctionSymbol(gnomeuiLib
, "gnome_master_client");
230 GnomeClient
*client
= gnome_master_client();
231 g_signal_connect(client
, "save-yourself", G_CALLBACK(save_yourself_cb
), nullptr);
232 g_signal_connect(client
, "die", G_CALLBACK(die_cb
), nullptr);
234 // Set the correct/requested restart command in any case.
236 // Is there a request to suppress default binary launcher?
238 char* argv1
= getenv("MOZ_APP_LAUNCHER");
241 // Tell the desktop the command for restarting us so that we can be part of XSMP session restore
242 NS_ASSERTION(gDirServiceProvider
, "gDirServiceProvider is NULL! This shouldn't happen!");
243 nsCOMPtr
<nsIFile
> executablePath
;
247 rv
= gDirServiceProvider
->GetFile(XRE_EXECUTABLE_FILE
, &dummy
, getter_AddRefs(executablePath
));
249 if (NS_SUCCEEDED(rv
)) {
250 // Strip off the -bin suffix to get the shell script we should run; this is what Breakpad does
251 nsAutoCString leafName
;
252 rv
= executablePath
->GetNativeLeafName(leafName
);
253 if (NS_SUCCEEDED(rv
) && StringEndsWith(leafName
, NS_LITERAL_CSTRING("-bin"))) {
254 leafName
.SetLength(leafName
.Length() - strlen("-bin"));
255 executablePath
->SetNativeLeafName(leafName
);
258 executablePath
->GetNativePath(path
);
259 argv1
= (char*)(path
.get());
264 gnome_client_set_restart_command(client
, 1, &argv1
);
266 #endif /* MOZ_X11 && (MOZ_WIDGET_GTK == 2) */
272 nsNativeAppSupportUnix::Stop(bool *aResult
)
274 NS_ENSURE_ARG(aResult
);
280 nsNativeAppSupportUnix::Enable()
286 NS_CreateNativeAppSupport(nsINativeAppSupport
**aResult
)
288 nsNativeAppSupportBase
* native
= new nsNativeAppSupportUnix();
290 return NS_ERROR_OUT_OF_MEMORY
;