2
* Copyright © 2000-2002 Marco Pesenti Gritti
3
* Copyright © 2006, 2008 Christian Persch
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2, or (at your option)
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23
#include "ephy-settings.h"
24
#include "ephy-shell.h"
25
#include "ephy-file-helpers.h"
26
#include "ephy-object-helpers.h"
27
#include "ephy-state.h"
28
#include "ephy-debug.h"
29
#include "ephy-stock-icons.h"
30
#include "ephy-dbus-client-bindings.h"
31
#include "ephy-activation.h"
32
#include "ephy-session.h"
33
#include "ephy-shell.h"
34
#include "ephy-prefs.h"
35
#include "ephy-profile-utils.h"
36
#include "ephy-debug.h"
37
#include "eggsmclient.h"
39
#include <libxml/xmlversion.h>
41
#include <glib/gi18n.h>
49
#ifdef ENABLE_INTROSPECTION
50
#include <girepository.h>
53
static GQuark startup_error_quark = 0;
54
#define STARTUP_ERROR_QUARK (startup_error_quark)
56
static gboolean open_in_new_tab = FALSE;
57
static gboolean open_in_new_window = FALSE;
58
static gboolean open_as_bookmarks_editor = FALSE;
59
/*static gboolean reload_plugins = FALSE;*/
61
static char *session_filename = NULL;
62
static char *bookmark_url = NULL;
63
static char *bookmarks_file = NULL;
64
static char **arguments = NULL;
66
/* Only set from options in debug builds */
67
static gboolean private_instance = FALSE;
68
static gboolean keep_temp_directory = FALSE;
69
static char *profile_directory = NULL;
72
option_version_cb (const gchar *option_name,
77
g_print ("%s %s\n", _("GNOME Web Browser"), VERSION);
83
static const GOptionEntry option_entries[] =
85
{ "new-tab", 'n', 0, G_OPTION_ARG_NONE, &open_in_new_tab,
86
N_("Open a new tab in an existing browser window"), NULL },
87
{ "new-window", 0, 0, G_OPTION_ARG_NONE, &open_in_new_window,
88
N_("Open a new browser window"), NULL },
89
{ "bookmarks-editor", 'b', 0, G_OPTION_ARG_NONE, &open_as_bookmarks_editor,
90
N_("Launch the bookmarks editor"), NULL },
91
{ "import-bookmarks", '\0', 0, G_OPTION_ARG_FILENAME, &bookmarks_file,
92
N_("Import bookmarks from the given file"), N_("FILE") },
93
{ "load-session", 'l', 0, G_OPTION_ARG_FILENAME, &session_filename,
94
N_("Load the given session file"), N_("FILE") },
95
{ "add-bookmark", 't', 0, G_OPTION_ARG_STRING, &bookmark_url,
96
N_("Add a bookmark"), N_("URL") },
97
{ "private-instance", 'p', 0, G_OPTION_ARG_NONE, &private_instance,
98
N_("Start a private instance"), NULL },
99
{ "profile", 0, 0, G_OPTION_ARG_STRING, &profile_directory,
100
N_("Profile directory to use in the private instance"), N_("DIR") },
101
{ G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &arguments,
103
{ "version", 0, G_OPTION_FLAG_NO_ARG | G_OPTION_FLAG_HIDDEN,
104
G_OPTION_ARG_CALLBACK, option_version_cb, NULL, NULL },
108
#ifdef GNOME_ENABLE_DEBUG
109
static GOptionEntry debug_option_entries[] =
111
{ "keep-tempdir", 0, 0, G_OPTION_ARG_NONE, &keep_temp_directory,
112
"Don't delete the temporary directory on exit", NULL },
115
#endif /* GNOME_ENABLE_DEBUG */
117
/* adapted from gtk+/gdk/x11/gdkdisplay-x11.c */
119
get_startup_id (void)
121
const char *startup_id, *time_str;
124
startup_id = g_getenv ("DESKTOP_STARTUP_ID");
125
if (startup_id == NULL) return 0;
127
/* Find the launch time from the startup_id, if it's there. Newer spec
128
* states that the startup_id is of the form <unique>_TIME<timestamp>
130
time_str = g_strrstr (startup_id, "_TIME");
131
if (time_str != NULL)
137
/* Skip past the "_TIME" part */
140
value = strtoul (time_str, &end, 0);
141
if (end != time_str && errno == 0)
143
retval = (guint32) value;
150
/* Copied from libnautilus/nautilus-program-choosing.c; Needed in case
151
* we have no DESKTOP_STARTUP_ID (with its accompanying timestamp).
154
slowly_and_stupidly_obtain_timestamp (Display *xdisplay)
160
XSetWindowAttributes attrs;
165
attrs.override_redirect = True;
166
attrs.event_mask = PropertyChangeMask | StructureNotifyMask;
169
XCreateWindow (xdisplay,
170
RootWindow (xdisplay, 0),
176
CWOverrideRedirect | CWEventMask,
179
atom_name = XInternAtom (xdisplay, "WM_NAME", TRUE);
180
g_assert (atom_name != None);
181
atom_type = XInternAtom (xdisplay, "STRING", TRUE);
182
g_assert (atom_type != None);
184
name = "Fake Window";
185
XChangeProperty (xdisplay,
188
8, PropModeReplace, (unsigned char *)name, strlen (name));
191
XWindowEvent (xdisplay,
196
XDestroyWindow(xdisplay, xwindow);
198
return event.xproperty.time;
202
unref_proxy_reply_cb (DBusGProxy *proxy,
208
g_warning ("An error occurred while calling remote method: %s", error->message);
209
g_error_free (error);
212
g_object_unref (proxy);
214
if (gtk_main_level ())
221
open_urls (DBusGProxy *proxy,
225
static const char *empty_arguments[] = { "", NULL };
229
options = g_string_sized_new (64);
231
if (open_in_new_window)
233
g_string_append (options, "new-window,");
237
g_string_append (options, "new-tab,");
240
if (arguments == NULL)
242
uris = (char **) empty_arguments;
246
uris = (char **) arguments;
249
org_gnome_Epiphany_load_ur_ilist_async
250
(proxy, (const char **) uris, options->str, user_time,
251
unref_proxy_reply_cb, NULL);
253
if (arguments != NULL)
255
g_strfreev (arguments);
259
g_string_free (options, TRUE);
265
call_dbus_proxy (DBusGProxy *proxy,
270
gboolean retval = TRUE;
272
shell = ephy_shell_get_default ();
274
if (open_as_bookmarks_editor)
276
org_gnome_Epiphany_open_bookmarks_editor_async
278
unref_proxy_reply_cb, shell);
280
else if (session_filename != NULL)
282
org_gnome_Epiphany_load_session_async
283
(proxy, session_filename, user_time,
284
unref_proxy_reply_cb, shell);
286
g_free (session_filename);
287
session_filename = NULL;
291
retval = open_urls (proxy, user_time, error);
295
dbus_g_connection_flush (ephy_dbus_get_bus (ephy_dbus_get_default (), EPHY_DBUS_SESSION));
301
queue_commands (guint32 user_time)
304
EphySession *session;
306
shell = ephy_shell_get_default ();
307
g_assert (shell != NULL);
309
session = EPHY_SESSION (ephy_shell_get_session (shell));
310
g_assert (session != NULL);
312
/* We only get here when starting a new instance, so we
313
* first need to autoresume!
315
ephy_session_queue_command (session,
316
EPHY_SESSION_CMD_RESUME_SESSION,
317
NULL, NULL, user_time, TRUE);
319
if (open_as_bookmarks_editor)
321
ephy_session_queue_command (session,
322
EPHY_SESSION_CMD_OPEN_BOOKMARKS_EDITOR,
323
NULL, NULL, user_time, FALSE);
325
else if (session_filename != NULL)
327
ephy_session_queue_command (session,
328
EPHY_SESSION_CMD_LOAD_SESSION,
329
session_filename, NULL,
332
g_free (session_filename);
333
session_filename = NULL;
335
/* Don't queue any window openings if no extra arguments given,
336
* since session autoresume will open one for us.
338
else if (arguments != NULL)
342
options = g_string_sized_new (64);
344
if (open_in_new_window)
346
g_string_append (options, "new-window,");
350
g_string_append (options, "new-tab,external,");
353
ephy_session_queue_command (session,
354
EPHY_SESSION_CMD_OPEN_URIS,
359
g_strfreev (arguments);
365
show_error_message (GError **error)
369
/* FIXME better texts!!! */
370
dialog = gtk_message_dialog_new (NULL,
374
_("Could not start GNOME Web Browser"));
375
gtk_message_dialog_format_secondary_text
376
(GTK_MESSAGE_DIALOG (dialog),
377
_("Startup failed because of the following error:\n%s"),
380
g_clear_error (error);
382
gtk_dialog_run (GTK_DIALOG (dialog));
386
get_accels_filename (void)
390
home = g_get_home_dir();
393
return g_build_filename (home, GNOME_DOT_GNOME, "accels", PACKAGE, NULL);
401
filename = get_accels_filename ();
405
gtk_accel_map_load (filename);
414
filename = get_accels_filename ();
418
gtk_accel_map_save (filename);
423
shell_quit_cb (EphyShell *shell, gpointer data)
432
GOptionContext *option_context;
433
GOptionGroup *option_group;
435
GError *error = NULL;
437
gboolean arbitrary_url;
440
/* Initialize the i18n stuff */
441
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
442
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
443
textdomain (GETTEXT_PACKAGE);
446
/* Threads have to be initialised before calling ANY glib function */
447
g_thread_init (NULL);
448
dbus_g_thread_init ();
450
/* check libxml2 API version epiphany was compiled with against the
451
* version we're running with.
455
/* sets name to help matching with the .desktop file */
456
g_set_prgname ("epiphany-browser");
458
/* If we're given -remote arguments, translate them */
460
strcmp (argv[1], "-remote") == 0)
462
const char *opening, *closing;
463
char *command, *argument;
468
g_print ("-remote allows exactly one argument\n");
472
opening = strchr (argv[2], '(');
473
closing = strchr (argv[2], ')');
475
if (opening == NULL ||
477
opening == argv[2] ||
478
opening + 1 >= closing)
480
g_print ("Invalid argument for -remote\n");
484
command = g_strstrip (g_strndup (argv[2], opening - argv[2]));
486
/* See http://lxr.mozilla.org/seamonkey/source/xpfe/components/xremote/src/XRemoteService.cpp
487
* for the commands that mozilla supports; we'll just support openURL here.
489
if (g_ascii_strcasecmp (command, "openURL") != 0)
491
g_print ("-remote command \"%s\" not supported\n", command);
498
argument = g_strstrip (g_strndup (opening + 1, closing - opening - 1));
499
arguments = g_strsplit (argument, ",", -1);
501
if (arguments == NULL)
503
g_print ("Invalid argument for -remote\n");
508
/* replace arguments */
509
argv[1] = g_strstrip (g_strdup (arguments[0]));
512
g_strfreev (arguments);
515
/* Initialise our debug helpers */
518
/* get this early, since gdk will unset the env var */
519
user_time = get_startup_id ();
521
option_context = g_option_context_new ("");
522
option_group = g_option_group_new ("epiphany-browser",
523
N_("GNOME Web Browser"),
524
N_("GNOME Web Browser options"),
527
g_option_group_set_translation_domain (option_group, GETTEXT_PACKAGE);
529
g_option_group_add_entries (option_group, option_entries);
531
g_option_context_set_main_group (option_context, option_group);
533
#ifdef ENABLE_INTROSPECTION
534
g_option_context_add_group (option_context, g_irepository_get_option_group ());
537
g_option_context_add_group (option_context, gtk_get_option_group (TRUE));
538
g_option_context_add_group (option_context, egg_sm_client_get_option_group ());
540
#ifdef GNOME_ENABLE_DEBUG
541
option_group = g_option_group_new ("debug",
542
"Epiphany debug options",
543
"Epiphany debug options",
545
g_option_group_add_entries (option_group, debug_option_entries);
546
g_option_context_add_group (option_context, option_group);
547
#endif /* GNOME_ENABLE_DEBUG */
549
if (!g_option_context_parse (option_context, &argc, &argv, &error))
551
g_print ("Failed to parse arguments: %s\n", error->message);
552
g_error_free (error);
553
g_option_context_free (option_context);
557
g_option_context_free (option_context);
559
/* Some argument sanity checks*/
560
if (arguments != NULL && (session_filename != NULL || open_as_bookmarks_editor))
562
g_print ("Cannot use --bookmarks-editor or --load-session with URL arguments\n");
566
if (profile_directory != NULL && private_instance == FALSE)
568
g_print ("--profile can only be used in combination with --private-instance\n");
572
arbitrary_url = g_settings_get_boolean (EPHY_SETTINGS_LOCKDOWN,
573
EPHY_PREFS_LOCKDOWN_ARBITRARY_URL);
575
if (arguments != NULL && arbitrary_url)
577
g_print ("URL loading is locked down\n");
581
/* Make URIs from arguments, to support filename args */
582
if (arguments != NULL)
586
for (i = 0; arguments[i] != NULL; ++i)
590
char rpath[PATH_MAX];
595
path = realpath (arguments[i], rpath);
598
uri = g_locale_to_utf8 (path, -1,
606
uri = g_locale_to_utf8 (arguments[i], -1,
612
g_free (arguments[i]);
614
/* If it's a file, use g_file_new_for_commandline_arg,
615
* so we get the right escaping.
620
file = g_file_new_for_commandline_arg (uri);
621
arguments[i] = g_file_get_uri (file);
622
g_object_unref (file);
632
g_print ("Could not convert '%s' to UTF-8: %s!\n",
633
arguments[i], error->message);
634
g_error_free (error);
640
/* Get a timestamp manually if need be */
643
user_time = slowly_and_stupidly_obtain_timestamp (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
646
/* sets the name to appear in the window list applet when grouping windows */
647
g_set_application_name (_("Web Browser"));
649
/* Set default window icon */
650
gtk_window_set_default_icon_name (EPHY_STOCK_EPHY);
652
/* sets WM_CLASS to help GNOME Shell windows matching */
653
gdk_set_program_class ("epiphany");
655
startup_error_quark = g_quark_from_static_string ("epiphany-startup-error");
657
if (!_ephy_dbus_startup (!private_instance, &error))
659
_ephy_dbus_release ();
661
show_error_message (&error);
666
/* If we're remoting, no need to start up any further services,
667
* just forward the call.
669
if (!private_instance &&
670
!_ephy_dbus_is_name_owner ())
672
/* Create DBUS proxy */
673
proxy = ephy_dbus_get_proxy (ephy_dbus_get_default (), EPHY_DBUS_SESSION);
676
error = g_error_new (STARTUP_ERROR_QUARK,
678
"Unable to get DBus proxy; aborting activation."); /* FIXME i18n */
680
_ephy_dbus_release ();
682
show_error_message (&error);
687
if (!call_dbus_proxy (proxy, user_time, &error))
689
_ephy_dbus_release ();
691
show_error_message (&error);
696
/* Wait for the response */
699
_ephy_dbus_release ();
701
gdk_notify_startup_complete ();
706
/* We're not remoting; start our services */
707
if (!ephy_file_helpers_init (profile_directory,
709
keep_temp_directory || profile_directory,
712
_ephy_dbus_release ();
714
show_error_message (&error);
719
/* Migrate profile if we are not running a private instance */
720
if (ephy_has_private_profile () == FALSE &&
721
ephy_profile_utils_get_migration_version () < EPHY_PROFILE_MIGRATION_VERSION)
723
GError *error = NULL;
724
char *argv[1] = { "ephy-profile-migrator" };
725
char *envp[1] = { "EPHY_LOG_MODULES=ephy-profile" };
727
g_spawn_sync (NULL, argv, envp, G_SPAWN_SEARCH_PATH,
728
NULL, NULL, NULL, NULL,
733
LOG ("Failed to run migrator: %s", error->message);
734
g_error_free (error);
738
ephy_stock_icons_init ();
741
/* Work-around Flash Player crash */
742
g_setenv ("XLIB_SKIP_ARGB_VISUALS", "1", FALSE);
744
/* Now create the shell */
745
_ephy_shell_create_instance ();
746
g_signal_connect (ephy_shell, "quit", G_CALLBACK (shell_quit_cb), NULL);
748
queue_commands (user_time);
753
g_object_unref (ephy_shell);
757
ephy_settings_shutdown ();
758
ephy_file_helpers_shutdown ();
761
_ephy_dbus_release ();