~ubuntu-branches/ubuntu/wily/epiphany-browser/wily

« back to all changes in this revision

Viewing changes to .pc/16_fix_missing_restore_option.patch/src/ephy-session.c

  • Committer: Bazaar Package Importer
  • Author(s): Gustavo Noronha Silva, Josselin Mouette, Gustavo Noronha Silva
  • Date: 2011-03-31 23:37:12 UTC
  • mfrom: (1.1.66 upstream)
  • Revision ID: james.westby@ubuntu.com-20110331233712-e43bgqbhjepgl8tv
Tags: 3.0.0-1
[ Josselin Mouette ]
* Make the -dev package depend on the gir package.

[ Gustavo Noronha Silva ]
* debian/control:
- bump WebKitGTK+ requirement to 1.3.13, following upstream
* debian/patches/16_fix_missing_restore_option.patch,
  debian/patches/17_do_not_include_removed_header.patch:
- removed; included in this upstream version
* debian/patches/04_allow_flash_with_npwrapper.patch:
- imported from upstream's bugzilla to allow flash when used through
  npwrapper; also bump build-dep on webkit to 1.3.13-2 that has a patch
  to support this

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
 
/*
3
 
 *  Copyright © 2002 Jorn Baayen
4
 
 *  Copyright © 2003, 2004 Marco Pesenti Gritti
5
 
 *  Copyright © 2003, 2004, 2005, 2006, 2008 Christian Persch
6
 
 *
7
 
 *  This program is free software; you can redistribute it and/or modify
8
 
 *  it under the terms of the GNU General Public License as published by
9
 
 *  the Free Software Foundation; either version 2, or (at your option)
10
 
 *  any later version.
11
 
 *
12
 
 *  This program is distributed in the hope that it will be useful,
13
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 *  GNU General Public License for more details.
16
 
 *
17
 
 *  You should have received a copy of the GNU General Public License
18
 
 *  along with this program; if not, write to the Free Software
19
 
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
 
 */
21
 
 
22
 
#include "config.h"
23
 
 
24
 
#include "ephy-session.h"
25
 
 
26
 
#include "eggdesktopfile.h"
27
 
#include "eggsmclient.h"
28
 
#include "ephy-bookmarks-editor.h"
29
 
#include "ephy-debug.h"
30
 
#include "ephy-embed.h"
31
 
#include "ephy-embed-utils.h"
32
 
#include "ephy-embed-container.h"
33
 
#include "ephy-extension.h"
34
 
#include "ephy-file-helpers.h"
35
 
#include "ephy-gui.h"
36
 
#include "ephy-history-window.h"
37
 
#include "ephy-notebook.h"
38
 
#include "ephy-prefs.h"
39
 
#include "ephy-settings.h"
40
 
#include "ephy-shell.h"
41
 
#include "ephy-stock-icons.h"
42
 
#include "ephy-window.h"
43
 
 
44
 
#include <glib/gi18n.h>
45
 
#include <gtk/gtk.h>
46
 
 
47
 
#include <libxml/tree.h>
48
 
#include <libxml/xmlwriter.h>
49
 
 
50
 
#include <errno.h>
51
 
#include <string.h>
52
 
#include <stdlib.h>
53
 
 
54
 
typedef struct
55
 
{
56
 
        EphySessionCommand command;
57
 
        char *arg;
58
 
        char **args;
59
 
        guint32 user_time;
60
 
} SessionCommand;
61
 
 
62
 
#define EPHY_SESSION_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_SESSION, EphySessionPrivate))
63
 
 
64
 
struct _EphySessionPrivate
65
 
{
66
 
        GList *windows;
67
 
        GList *tool_windows;
68
 
        GtkWidget *resume_infobar;
69
 
        GtkWidget *resume_window;
70
 
 
71
 
        GQueue *queue;
72
 
        guint queue_idle_id;
73
 
 
74
 
        GtkWidget *quit_interact_dialog;
75
 
 
76
 
        guint dont_save : 1;
77
 
        guint quit_while_resuming : 1;
78
 
        guint loading_homepage : 1;
79
 
};
80
 
 
81
 
#define BOOKMARKS_EDITOR_ID     "BookmarksEditor"
82
 
#define HISTORY_WINDOW_ID       "HistoryWindow"
83
 
#define SESSION_CRASHED         "type:session_crashed"
84
 
 
85
 
static void ephy_session_class_init     (EphySessionClass *klass);
86
 
static void ephy_session_iface_init     (EphyExtensionIface *iface);
87
 
static void ephy_session_init           (EphySession *session);
88
 
static void session_command_queue_next  (EphySession *session);
89
 
 
90
 
enum
91
 
{
92
 
        PROP_0,
93
 
        PROP_ACTIVE_WINDOW
94
 
};
95
 
 
96
 
G_DEFINE_TYPE_WITH_CODE (EphySession, ephy_session, G_TYPE_OBJECT,
97
 
                         G_IMPLEMENT_INTERFACE (EPHY_TYPE_EXTENSION,
98
 
                                                ephy_session_iface_init))
99
 
 
100
 
/* Gnome session client */
101
 
 
102
 
typedef struct
103
 
{
104
 
        EphySession *session;
105
 
        EggSMClient *sm_client;
106
 
        GtkWidget *dialog;
107
 
        GtkWidget *label;
108
 
        guint timeout_id;
109
 
        guint ticks;
110
 
        int response;
111
 
} InteractData;
112
 
 
113
 
static void
114
 
confirm_shutdown_dialog_update_timeout_label (InteractData *data)
115
 
{
116
 
        char *text;
117
 
 
118
 
        text = g_strdup_printf (ngettext ("Downloads will be aborted and logout proceed in %d second.",
119
 
                                          "Downloads will be aborted and logout proceed in %d seconds.",
120
 
                                          data->ticks),
121
 
                                data->ticks);
122
 
 
123
 
        gtk_label_set_text (GTK_LABEL (data->label), text);
124
 
        g_free (text);
125
 
}
126
 
                
127
 
static gboolean
128
 
confirm_shutdown_dialog_tick_cb (InteractData *data)
129
 
{
130
 
        if (data->ticks > 0)
131
 
        {
132
 
                --data->ticks;
133
 
                confirm_shutdown_dialog_update_timeout_label (data);
134
 
                return TRUE;
135
 
        }
136
 
 
137
 
        data->timeout_id = 0;
138
 
        gtk_dialog_response (GTK_DIALOG (data->dialog),
139
 
                             GTK_RESPONSE_ACCEPT);
140
 
        return FALSE;
141
 
}
142
 
 
143
 
static void
144
 
confirm_shutdown_dialog_response_cb (GtkWidget *dialog,
145
 
                                     int response,
146
 
                                     InteractData *data)
147
 
{
148
 
        LOG ("confirm_shutdown_dialog_response_cb response %d", response);
149
 
 
150
 
        data->response = response;
151
 
 
152
 
        gtk_widget_destroy (dialog);
153
 
}
154
 
 
155
 
static void
156
 
confirm_shutdown_dialog_accept_cb (InteractData *data,
157
 
                                   GObject *zombie)
158
 
{
159
 
        gtk_dialog_response (GTK_DIALOG (data->dialog),
160
 
                             GTK_RESPONSE_ACCEPT);
161
 
}
162
 
 
163
 
static void
164
 
confirm_shutdown_dialog_weak_ref_cb (InteractData *data,
165
 
                                     GObject *zombie)
166
 
{
167
 
        EphySessionPrivate *priv = data->session->priv;
168
 
        EggSMClient *sm_client = data->sm_client;
169
 
        EphyShell *shell;
170
 
        gboolean will_quit;
171
 
 
172
 
        LOG ("confirm_shutdown_dialog_weak_ref_cb response %d", data->response);
173
 
 
174
 
        priv->quit_interact_dialog = NULL;
175
 
 
176
 
        shell = ephy_shell_get_default ();
177
 
        if (shell != NULL)
178
 
        {
179
 
                g_object_weak_unref (G_OBJECT (shell),
180
 
                                     (GWeakNotify) confirm_shutdown_dialog_accept_cb,
181
 
                                     data);
182
 
        }
183
 
 
184
 
        if (data->timeout_id != 0)
185
 
        {
186
 
                g_source_remove (data->timeout_id);
187
 
        }
188
 
 
189
 
        will_quit = data->response == GTK_RESPONSE_ACCEPT;
190
 
 
191
 
        g_free (data);
192
 
 
193
 
        egg_sm_client_will_quit (sm_client, will_quit);
194
 
        g_object_unref (sm_client);
195
 
}
196
 
 
197
 
static void
198
 
client_quit_requested_cb (EggSMClient *sm_client,
199
 
                          EphySession *session)
200
 
{
201
 
        EphySessionPrivate *priv = session->priv;
202
 
        GtkWidget *dialog, *box;
203
 
        InteractData *data;
204
 
        GList *downloads;
205
 
 
206
 
        /* If we're shutting down, check if there are downloads
207
 
         * remaining, since they can't be restarted.
208
 
         */
209
 
 
210
 
        downloads = ephy_embed_shell_get_downloads (embed_shell);
211
 
        if (ephy_shell_get_default () == NULL || g_list_length (downloads) == 0)
212
 
        {
213
 
                egg_sm_client_will_quit (sm_client, TRUE);
214
 
                return;
215
 
        }
216
 
 
217
 
        dialog = gtk_message_dialog_new
218
 
                (NULL,
219
 
                 GTK_DIALOG_MODAL,
220
 
                 GTK_MESSAGE_WARNING,
221
 
                 GTK_BUTTONS_NONE,
222
 
                 _("Abort pending downloads?"));
223
 
        priv->quit_interact_dialog = dialog;
224
 
 
225
 
        gtk_message_dialog_format_secondary_text
226
 
                (GTK_MESSAGE_DIALOG (dialog),
227
 
                 _("There are still downloads pending. If you log out, "
228
 
                   "they will be aborted and lost."));
229
 
 
230
 
        gtk_dialog_add_button (GTK_DIALOG (dialog),
231
 
                               _("_Cancel Logout"), GTK_RESPONSE_REJECT);
232
 
        gtk_dialog_add_button (GTK_DIALOG (dialog),
233
 
                               _("_Abort Downloads"), GTK_RESPONSE_ACCEPT);
234
 
 
235
 
        gtk_window_set_title (GTK_WINDOW (dialog), "");
236
 
        gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
237
 
        gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
238
 
        gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_REJECT);
239
 
 
240
 
        data = g_new (InteractData, 1);
241
 
        data->sm_client = g_object_ref (sm_client);
242
 
        data->session = session;
243
 
        data->dialog = dialog;
244
 
        data->response = GTK_RESPONSE_REJECT;
245
 
 
246
 
        /* This isn't very exact, but it's good enough here */
247
 
        data->timeout_id = g_timeout_add_seconds (1,
248
 
                                          (GSourceFunc) confirm_shutdown_dialog_tick_cb,
249
 
                                          data);
250
 
        data->ticks = 60;
251
 
 
252
 
        /* Add timeout label */
253
 
        data->label = gtk_label_new (NULL);
254
 
        gtk_label_set_line_wrap (GTK_LABEL (data->label), TRUE);
255
 
        confirm_shutdown_dialog_update_timeout_label (data);
256
 
 
257
 
        box = ephy_gui_message_dialog_get_content_box (dialog);
258
 
        gtk_box_pack_end (GTK_BOX (box), data->label, FALSE, FALSE, 0);
259
 
        gtk_widget_show (data->label);
260
 
 
261
 
        /* When we're quitting, un-veto the shutdown  */
262
 
        g_object_weak_ref (G_OBJECT (ephy_shell_get_default ()),
263
 
                           (GWeakNotify) confirm_shutdown_dialog_accept_cb,
264
 
                           data);
265
 
 
266
 
        g_signal_connect (dialog, "response",
267
 
                          G_CALLBACK (confirm_shutdown_dialog_response_cb), data);
268
 
        g_object_weak_ref (G_OBJECT (dialog),
269
 
                           (GWeakNotify) confirm_shutdown_dialog_weak_ref_cb,
270
 
                           data);
271
 
 
272
 
        gtk_window_present (GTK_WINDOW (dialog));
273
 
}
274
 
 
275
 
static void
276
 
client_quit_cancelled_cb (EggSMClient *sm_client,
277
 
                          EphySession *session)
278
 
{
279
 
        EphySessionPrivate *priv = session->priv;
280
 
 
281
 
        if (priv->quit_interact_dialog)
282
 
        {
283
 
                gtk_dialog_response (GTK_DIALOG (priv->quit_interact_dialog),
284
 
                                     GTK_RESPONSE_DELETE_EVENT);
285
 
        }
286
 
}
287
 
 
288
 
static void
289
 
client_quit_cb (EggSMClient *sm_client,
290
 
                EphySession *session)
291
 
{
292
 
        LOG ("quit-cb");
293
 
 
294
 
        ephy_session_close (session);
295
 
}
296
 
 
297
 
static void
298
 
client_save_state_cb (EggSMClient *sm_client,
299
 
                      GKeyFile *keyfile,
300
 
                      EphySession *session)
301
 
{
302
 
        char *argv[] = { NULL, "--load-session", NULL };
303
 
        char *discard_argv[] = { "rm", "-f", NULL };
304
 
        char *tmp, *save_to;
305
 
 
306
 
        LOG ("save_yourself_cb");
307
 
 
308
 
        tmp = g_build_filename (ephy_dot_dir (),
309
 
                                "session_gnome-XXXXXX",
310
 
                                NULL);
311
 
        save_to = ephy_file_tmp_filename (tmp, "xml");
312
 
        g_free (tmp);
313
 
 
314
 
        argv[0] = g_get_prgname ();
315
 
        argv[2] = save_to;
316
 
        egg_sm_client_set_restart_command (sm_client, 3, (const char **) argv);
317
 
 
318
 
        discard_argv[2] = save_to;
319
 
        egg_sm_client_set_discard_command (sm_client, 3, (const char **) discard_argv);
320
 
 
321
 
        ephy_session_save (session, save_to);
322
 
 
323
 
        g_free (save_to);
324
 
}
325
 
 
326
 
/* Helper functions */
327
 
 
328
 
static GFile *
329
 
get_session_file (const char *filename)
330
 
{
331
 
        GFile *file;
332
 
        char *path;
333
 
 
334
 
        if (filename == NULL)
335
 
        {
336
 
                return NULL;
337
 
        }
338
 
 
339
 
        if (strcmp (filename, SESSION_CRASHED) == 0)
340
 
        {
341
 
                path = g_build_filename (ephy_dot_dir (),
342
 
                                         "session_crashed.xml",
343
 
                                         NULL);
344
 
        }
345
 
        else
346
 
        {
347
 
                path = g_strdup (filename);
348
 
        }
349
 
 
350
 
        file = g_file_new_for_path (path);
351
 
        g_free (path);
352
 
 
353
 
        return file;
354
 
}
355
 
 
356
 
static void
357
 
session_delete (EphySession *session,
358
 
                const char *filename)
359
 
{
360
 
        GFile *file;
361
 
 
362
 
        file = get_session_file (filename);
363
 
 
364
 
        g_file_delete (file, NULL, NULL);
365
 
        g_object_unref (file);
366
 
}
367
 
 
368
 
static void
369
 
load_status_notify_cb (EphyWebView *view,
370
 
                       GParamSpec *pspec,
371
 
                       EphySession *session)
372
 
{
373
 
        WebKitLoadStatus status = webkit_web_view_get_load_status (WEBKIT_WEB_VIEW (view));
374
 
 
375
 
        /* We won't know the URL we are loading in PROVISIONAL because
376
 
           of bug #593149, but save session anyway */
377
 
        if (status == WEBKIT_LOAD_PROVISIONAL ||
378
 
            status == WEBKIT_LOAD_COMMITTED || 
379
 
            status == WEBKIT_LOAD_FINISHED)
380
 
                ephy_session_save (session, SESSION_CRASHED);
381
 
}
382
 
 
383
 
static void
384
 
notebook_page_added_cb (GtkWidget *notebook,
385
 
                        EphyEmbed *embed,
386
 
                        guint position,
387
 
                        EphySession *session)
388
 
{
389
 
        g_signal_connect (ephy_embed_get_web_view (embed), "notify::load-status",
390
 
                          G_CALLBACK (load_status_notify_cb), session);
391
 
}
392
 
 
393
 
static void
394
 
notebook_page_removed_cb (GtkWidget *notebook,
395
 
                          EphyEmbed *embed,
396
 
                          guint position,
397
 
                          EphySession *session)
398
 
{
399
 
        ephy_session_save (session, SESSION_CRASHED);
400
 
 
401
 
        g_signal_handlers_disconnect_by_func
402
 
                (ephy_embed_get_web_view (embed), G_CALLBACK (load_status_notify_cb),
403
 
                 session);
404
 
}
405
 
 
406
 
static void
407
 
notebook_page_reordered_cb (GtkWidget *notebook,
408
 
                            GtkWidget *tab,
409
 
                            guint position,
410
 
                            EphySession *session)
411
 
{
412
 
        ephy_session_save (session, SESSION_CRASHED);
413
 
}
414
 
 
415
 
static gboolean
416
 
window_focus_in_event_cb (EphyWindow *window,
417
 
                          GdkEventFocus *event,
418
 
                          EphySession *session)
419
 
{
420
 
        LOG ("focus-in-event for window %p", window);
421
 
 
422
 
        g_return_val_if_fail (g_list_find (session->priv->windows, window) != NULL, FALSE);
423
 
 
424
 
        /* move the active window to the front of the list */
425
 
        session->priv->windows = g_list_remove (session->priv->windows, window);
426
 
        session->priv->windows = g_list_prepend (session->priv->windows, window);
427
 
 
428
 
        g_object_notify (G_OBJECT (session), "active-window");
429
 
 
430
 
        /* propagate event */
431
 
        return FALSE;
432
 
}
433
 
 
434
 
/* Queue worker */
435
 
 
436
 
static void
437
 
session_command_free (SessionCommand *cmd)
438
 
{
439
 
        g_assert (cmd != NULL);
440
 
 
441
 
        g_free (cmd->arg);
442
 
        if (cmd->args)
443
 
        {
444
 
                g_strfreev (cmd->args);
445
 
        }
446
 
 
447
 
        g_free (cmd);
448
 
 
449
 
        g_object_unref (ephy_shell_get_default ());
450
 
}
451
 
 
452
 
static int
453
 
session_command_find (const SessionCommand *cmd,
454
 
                      gpointer cmdptr)
455
 
{
456
 
        EphySessionCommand command = GPOINTER_TO_INT (cmdptr);
457
 
 
458
 
        return command != cmd->command;
459
 
}
460
 
 
461
 
static void
462
 
resume_infobar_response_cb (GtkWidget *info_bar,
463
 
                            int response,
464
 
                            EphySession *session)
465
 
{
466
 
        guint32 user_time;
467
 
        EphySessionPrivate *priv = session->priv;
468
 
 
469
 
        LOG ("resume_infobar_response_cb response:%d", response);
470
 
 
471
 
        gtk_widget_hide (info_bar);
472
 
 
473
 
        user_time = gtk_get_current_event_time ();
474
 
 
475
 
        priv->dont_save = FALSE;
476
 
 
477
 
        gtk_widget_destroy (info_bar);
478
 
        priv->resume_infobar = NULL;
479
 
 
480
 
        if (response == GTK_RESPONSE_YES)
481
 
        {
482
 
                ephy_session_queue_command (session,
483
 
                                            EPHY_SESSION_CMD_LOAD_SESSION,
484
 
                                            SESSION_CRASHED, NULL,
485
 
                                            user_time, TRUE);
486
 
        }
487
 
}
488
 
 
489
 
static void
490
 
resume_infobar_weak_ref_cb (EphySession *session,
491
 
                            GObject *zombie)
492
 
{
493
 
        EphySessionPrivate *priv = session->priv;
494
 
 
495
 
        LOG ("resume_window_infobar_weak_ref_cb");
496
 
 
497
 
        priv->dont_save = FALSE;
498
 
        session_command_queue_next (session);
499
 
}
500
 
 
501
 
static void
502
 
session_command_autoresume (EphySession *session,
503
 
                            guint32 user_time)
504
 
{
505
 
        EphySessionPrivate *priv = session->priv;
506
 
        GFile *saved_session_file;
507
 
        char *saved_session_file_path;
508
 
        gboolean crashed_session;
509
 
 
510
 
        LOG ("ephy_session_autoresume");
511
 
 
512
 
        saved_session_file = get_session_file (SESSION_CRASHED);
513
 
        saved_session_file_path = g_file_get_path (saved_session_file);
514
 
        g_object_unref (saved_session_file);
515
 
        crashed_session = g_file_test (saved_session_file_path, G_FILE_TEST_EXISTS);
516
 
        
517
 
        g_free (saved_session_file_path);
518
 
 
519
 
        if (crashed_session == FALSE ||
520
 
            priv->windows != NULL ||
521
 
            priv->tool_windows != NULL)
522
 
        {
523
 
                /* FIXME can this happen? */
524
 
                if (priv->resume_infobar != NULL)
525
 
                {
526
 
                        gtk_widget_hide (priv->resume_infobar);
527
 
                        gtk_widget_destroy (priv->resume_infobar);
528
 
                }
529
 
 
530
 
                ephy_session_queue_command (session,
531
 
                                            EPHY_SESSION_CMD_MAYBE_OPEN_WINDOW,
532
 
                                            NULL, NULL, user_time, FALSE);
533
 
 
534
 
                return;
535
 
        }
536
 
 
537
 
        if (priv->resume_window)
538
 
        {
539
 
                gtk_window_present_with_time (GTK_WINDOW (priv->resume_window),
540
 
                                              user_time);
541
 
 
542
 
                return;
543
 
        }
544
 
 
545
 
        ephy_session_queue_command (session,
546
 
                                    EPHY_SESSION_CMD_MAYBE_OPEN_WINDOW_RESTORE,
547
 
                                    NULL, NULL, user_time, FALSE);
548
 
}
549
 
 
550
 
static void
551
 
session_command_open_bookmarks_editor (EphySession *session,
552
 
                                       guint32 user_time)
553
 
{
554
 
        GtkWidget *editor;
555
 
 
556
 
        editor = ephy_shell_get_bookmarks_editor (ephy_shell_get_default ());
557
 
        
558
 
        gtk_window_present_with_time (GTK_WINDOW (editor), user_time);
559
 
}
560
 
 
561
 
static void
562
 
session_command_open_uris (EphySession *session,
563
 
                           char **uris,
564
 
                           const char *options,
565
 
                           guint32 user_time)
566
 
{
567
 
        EphyShell *shell;
568
 
        EphyWindow *window;
569
 
        EphyEmbed *embed;
570
 
        EphySessionPrivate *priv;
571
 
        EphyNewTabFlags flags = 0;
572
 
        guint i;
573
 
 
574
 
        priv = session->priv;
575
 
 
576
 
        shell = ephy_shell_get_default ();
577
 
 
578
 
        g_object_ref (shell);
579
 
 
580
 
        window = ephy_session_get_active_window (session);
581
 
 
582
 
        if (options != NULL && strstr (options, "external") != NULL)
583
 
        {
584
 
                flags |= EPHY_NEW_TAB_FROM_EXTERNAL;
585
 
        }
586
 
        if (options != NULL && strstr (options, "new-window") != NULL)
587
 
        {
588
 
                window = NULL;
589
 
                flags |= EPHY_NEW_TAB_IN_NEW_WINDOW;
590
 
        }
591
 
        else if (options != NULL && strstr (options, "new-tab") != NULL)
592
 
        {
593
 
                flags |= EPHY_NEW_TAB_IN_EXISTING_WINDOW |
594
 
                         EPHY_NEW_TAB_JUMP;
595
 
        }
596
 
 
597
 
        for (i = 0; uris[i] != NULL; ++i)
598
 
        {
599
 
                const char *url = uris[i];
600
 
                EphyNewTabFlags page_flags;
601
 
                WebKitNetworkRequest *request = NULL;
602
 
 
603
 
                if (url[0] == '\0')
604
 
                {
605
 
                        page_flags = EPHY_NEW_TAB_HOME_PAGE;
606
 
                }
607
 
                else
608
 
                {
609
 
                        page_flags = EPHY_NEW_TAB_OPEN_PAGE;
610
 
                        request = webkit_network_request_new (url);
611
 
                }
612
 
 
613
 
                /* For the first URI, if we have a valid recovery
614
 
                 * window, reuse the already existing embed instead of
615
 
                 * creating a new one */
616
 
                if (i == 0 && priv->resume_window != NULL)
617
 
                {
618
 
                        EphyWebView *web_view;
619
 
                        
620
 
                        embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (priv->resume_window));
621
 
                        web_view = ephy_embed_get_web_view (embed);
622
 
                        ephy_web_view_load_url (web_view, url);
623
 
                }
624
 
                else
625
 
                {
626
 
                        embed = ephy_shell_new_tab_full (shell, window,
627
 
                                                         NULL /* parent tab */,
628
 
                                                         request,
629
 
                                                         flags | page_flags,
630
 
                                                         EPHY_WEB_VIEW_CHROME_ALL,
631
 
                                                         FALSE /* is popup? */,
632
 
                                                         user_time);
633
 
                }
634
 
 
635
 
                if (request)
636
 
                        g_object_unref (request);
637
 
 
638
 
                window = EPHY_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (embed)));
639
 
        }
640
 
 
641
 
        g_object_unref (shell);
642
 
}
643
 
 
644
 
static void
645
 
send_no_response_cb (GtkButton *button, GtkInfoBar *info_bar)
646
 
{
647
 
        gtk_info_bar_response (info_bar, GTK_RESPONSE_NO);
648
 
}
649
 
 
650
 
static void
651
 
send_yes_response_cb (GtkButton *button, GtkInfoBar *info_bar)
652
 
{
653
 
        gtk_info_bar_response (info_bar, GTK_RESPONSE_YES);
654
 
}
655
 
 
656
 
static void
657
 
loading_homepage_cb (EphyWebView *view, EphySession *session)
658
 
{
659
 
        EphySessionPrivate *priv = session->priv;
660
 
 
661
 
        priv->loading_homepage = TRUE;
662
 
}
663
 
 
664
 
static void
665
 
new_document_now_cb (EphyWebView *view, const char *uri, EphySession *session)
666
 
{
667
 
        EphySessionPrivate *priv = session->priv;
668
 
 
669
 
        if (priv->loading_homepage)
670
 
        {
671
 
                priv->loading_homepage = FALSE;
672
 
                return;
673
 
        }
674
 
 
675
 
        if (priv->resume_infobar) 
676
 
        {
677
 
                EphyEmbed *embed = EPHY_GET_EMBED_FROM_EPHY_WEB_VIEW (view);
678
 
                ephy_embed_remove_top_widget (embed, priv->resume_infobar);
679
 
                priv->resume_infobar = NULL;
680
 
                priv->resume_window = NULL;
681
 
        }
682
 
}
683
 
 
684
 
static gboolean
685
 
session_command_dispatch (EphySession *session)
686
 
{
687
 
        EphySessionPrivate *priv = session->priv;
688
 
        SessionCommand *cmd;
689
 
        gboolean run_again = TRUE;
690
 
 
691
 
        cmd = g_queue_pop_head (priv->queue);
692
 
        g_assert (cmd != NULL);
693
 
 
694
 
        LOG ("dispatching queue cmd:%d", cmd->command);
695
 
 
696
 
        switch (cmd->command)
697
 
        {
698
 
                case EPHY_SESSION_CMD_RESUME_SESSION:
699
 
                        session_command_autoresume (session, cmd->user_time);
700
 
                        break;
701
 
                case EPHY_SESSION_CMD_LOAD_SESSION:
702
 
                        ephy_session_load (session, cmd->arg, cmd->user_time);
703
 
                        break;
704
 
                case EPHY_SESSION_CMD_OPEN_BOOKMARKS_EDITOR:
705
 
                        session_command_open_bookmarks_editor (session, cmd->user_time);
706
 
                        break;
707
 
                case EPHY_SESSION_CMD_OPEN_URIS:
708
 
                        session_command_open_uris (session, cmd->args, cmd->arg, cmd->user_time);
709
 
                        break;
710
 
                case EPHY_SESSION_CMD_MAYBE_OPEN_WINDOW:
711
 
                        /* FIXME: maybe just check for normal windows? */
712
 
                        if (priv->windows == NULL &&
713
 
                            priv->tool_windows == NULL)
714
 
                        {
715
 
                                ephy_shell_new_tab_full (ephy_shell_get_default (),
716
 
                                                         NULL /* window */, NULL /* tab */,
717
 
                                                         NULL /* NetworkRequest */,
718
 
                                                         EPHY_NEW_TAB_IN_NEW_WINDOW |
719
 
                                                         EPHY_NEW_TAB_HOME_PAGE,
720
 
                                                         EPHY_WEB_VIEW_CHROME_ALL,
721
 
                                                         FALSE /* is popup? */,
722
 
                                                         cmd->user_time);
723
 
                        }
724
 
                        break;
725
 
                case EPHY_SESSION_CMD_MAYBE_OPEN_WINDOW_RESTORE:
726
 
                        /* FIXME: maybe just check for normal windows? */
727
 
                        if (priv->windows == NULL &&
728
 
                            priv->tool_windows == NULL)
729
 
                        {
730
 
                                GtkWidget *info_bar;
731
 
                                GtkWidget *action_area;
732
 
                                GtkWidget *button_box;
733
 
                                GtkWidget *action_button;
734
 
                                GtkWidget *content_area;
735
 
                                GtkWidget *label;
736
 
                                EphyEmbed *embed;
737
 
                                EphyWebView *view;
738
 
 
739
 
                                session->priv->dont_save = TRUE;
740
 
 
741
 
                                embed = ephy_shell_new_tab_full (ephy_shell_get_default (),
742
 
                                                                 NULL /* window */, NULL /* tab */,
743
 
                                                                 NULL /* Networ kRequest */,
744
 
                                                                 EPHY_NEW_TAB_IN_NEW_WINDOW |
745
 
                                                                 EPHY_NEW_TAB_HOME_PAGE,
746
 
                                                                 EPHY_WEB_VIEW_CHROME_ALL,
747
 
                                                                 FALSE /* is popup? */,
748
 
                                                                 cmd->user_time);
749
 
 
750
 
                                info_bar = gtk_info_bar_new ();
751
 
 
752
 
                                session->priv->resume_infobar = info_bar;
753
 
                                session->priv->resume_window = gtk_widget_get_toplevel (GTK_WIDGET (embed));
754
 
 
755
 
                                action_area = gtk_info_bar_get_action_area (GTK_INFO_BAR (info_bar));
756
 
                                button_box = gtk_hbutton_box_new ();
757
 
                                gtk_container_add (GTK_CONTAINER (action_area), button_box);
758
 
 
759
 
                                action_button = gtk_button_new_with_label (_("Don't recover"));
760
 
                                g_signal_connect (action_button, "clicked",
761
 
                                                  G_CALLBACK (send_no_response_cb), info_bar);
762
 
                                gtk_box_pack_start (GTK_BOX (button_box), action_button, FALSE, FALSE, 0);
763
 
 
764
 
                                action_button = gtk_button_new_with_label (_("Recover session"));
765
 
                                g_signal_connect (action_button, "clicked",
766
 
                                                  G_CALLBACK (send_yes_response_cb), info_bar);
767
 
                                gtk_box_pack_start (GTK_BOX (button_box), action_button, FALSE, FALSE, 0);
768
 
 
769
 
                                label = gtk_label_new (_("Do you want to recover the previous browser windows and tabs?"));
770
 
                                content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (info_bar));
771
 
                                gtk_container_add (GTK_CONTAINER (content_area), label);
772
 
                                gtk_widget_show_all (info_bar);
773
 
 
774
 
                                g_signal_connect (info_bar, "response",
775
 
                                                  G_CALLBACK (resume_infobar_response_cb), session);
776
 
 
777
 
                                g_object_weak_ref (G_OBJECT (info_bar),
778
 
                                                   (GWeakNotify) resume_infobar_weak_ref_cb,
779
 
                                                   session);
780
 
                                
781
 
                                ephy_embed_add_top_widget (embed, info_bar, FALSE);
782
 
 
783
 
                                view = ephy_embed_get_web_view (embed);
784
 
 
785
 
                                g_signal_connect (view, "loading-homepage",
786
 
                                                  G_CALLBACK (loading_homepage_cb), session);
787
 
 
788
 
                                g_signal_connect (view, "new-document-now",
789
 
                                                  G_CALLBACK (new_document_now_cb), session);
790
 
                        }
791
 
                        break;
792
 
                default:
793
 
                        g_assert_not_reached ();
794
 
                        break;
795
 
        }
796
 
 
797
 
        /* Look if there's anything else to dispatch */
798
 
        if (g_queue_is_empty (priv->queue) ||
799
 
            priv->resume_window != NULL)
800
 
        {
801
 
                priv->queue_idle_id = 0;
802
 
                run_again = FALSE;
803
 
        }
804
 
 
805
 
        /* This unrefs the shell! */
806
 
        session_command_free (cmd);
807
 
 
808
 
        return run_again;
809
 
}
810
 
 
811
 
static void
812
 
session_command_queue_next (EphySession *session)
813
 
{
814
 
        EphySessionPrivate *priv = session->priv;
815
 
 
816
 
        LOG ("queue_next");
817
 
 
818
 
        if (!g_queue_is_empty (priv->queue) &&
819
 
            priv->resume_infobar == NULL &&
820
 
            priv->queue_idle_id == 0)
821
 
        {
822
 
                priv->queue_idle_id =
823
 
                        g_idle_add ((GSourceFunc) session_command_dispatch,
824
 
                                    session);
825
 
        }
826
 
}
827
 
 
828
 
static void
829
 
session_command_queue_clear (EphySession *session)
830
 
{
831
 
        EphySessionPrivate *priv = session->priv;
832
 
 
833
 
        if (priv->queue_idle_id != 0)
834
 
        {
835
 
                g_source_remove (priv->queue_idle_id);
836
 
                priv->queue_idle_id = 0;
837
 
        }
838
 
 
839
 
        if (priv->queue != NULL)
840
 
        {
841
 
                g_queue_foreach (priv->queue, (GFunc) session_command_free, NULL);
842
 
                g_queue_free (priv->queue);
843
 
                priv->queue = NULL;
844
 
        }
845
 
}
846
 
 
847
 
/* EphyExtensionIface implementation */
848
 
 
849
 
static void
850
 
impl_attach_window (EphyExtension *extension,
851
 
                    EphyWindow *window)
852
 
{
853
 
        EphySession *session = EPHY_SESSION (extension);
854
 
        GtkWidget *notebook;
855
 
 
856
 
        LOG ("impl_attach_window");
857
 
 
858
 
        session->priv->windows = g_list_append (session->priv->windows, window);
859
 
        ephy_session_save (session, SESSION_CRASHED);
860
 
 
861
 
        g_signal_connect (window, "focus-in-event",
862
 
                          G_CALLBACK (window_focus_in_event_cb), session);
863
 
 
864
 
        notebook = ephy_window_get_notebook (window);
865
 
        g_signal_connect (notebook, "page-added",
866
 
                          G_CALLBACK (notebook_page_added_cb), session);
867
 
        g_signal_connect (notebook, "page-removed",
868
 
                          G_CALLBACK (notebook_page_removed_cb), session);
869
 
        g_signal_connect (notebook, "page-reordered",
870
 
                          G_CALLBACK (notebook_page_reordered_cb), session);
871
 
 
872
 
        /* Set unique identifier as role, so that on restore, the WM can
873
 
         * place the window on the right workspace
874
 
         */
875
 
 
876
 
        if (gtk_window_get_role (GTK_WINDOW (window)) == NULL)
877
 
        {
878
 
                /* I guess rand() is unique enough, otherwise we could use
879
 
                 * time + pid or something
880
 
                 */
881
 
                char *role;
882
 
 
883
 
                role = g_strdup_printf ("epiphany-window-%x", rand());
884
 
                gtk_window_set_role (GTK_WINDOW (window), role);
885
 
                g_free (role);
886
 
        }
887
 
}
888
 
 
889
 
static void
890
 
impl_detach_window (EphyExtension *extension,
891
 
                    EphyWindow *window)
892
 
{
893
 
        EphySession *session = EPHY_SESSION (extension);
894
 
 
895
 
        LOG ("impl_detach_window");
896
 
 
897
 
        session->priv->windows = g_list_remove (session->priv->windows, window);
898
 
        ephy_session_save (session, SESSION_CRASHED);
899
 
 
900
 
        /* NOTE: since the window will be destroyed anyway, we don't need to
901
 
         * disconnect our signal handlers from its components.
902
 
         */
903
 
}
904
 
 
905
 
/* Class implementation */
906
 
 
907
 
static void
908
 
ephy_session_init (EphySession *session)
909
 
{
910
 
        EphySessionPrivate *priv;
911
 
        EggSMClient *sm_client;
912
 
 
913
 
        LOG ("EphySession initialising");
914
 
 
915
 
        priv = session->priv = EPHY_SESSION_GET_PRIVATE (session);
916
 
 
917
 
        priv->queue = g_queue_new ();
918
 
 
919
 
        sm_client = egg_sm_client_get ();
920
 
        g_signal_connect (sm_client, "save-state",
921
 
                          G_CALLBACK (client_save_state_cb), session);
922
 
        g_signal_connect (sm_client, "quit-requested",
923
 
                          G_CALLBACK (client_quit_requested_cb), session);
924
 
        g_signal_connect (sm_client, "quit-cancelled",
925
 
                          G_CALLBACK (client_quit_cancelled_cb), session);
926
 
        g_signal_connect (sm_client, "quit",
927
 
                          G_CALLBACK (client_quit_cb), session);
928
 
}
929
 
 
930
 
static void
931
 
ephy_session_dispose (GObject *object)
932
 
{
933
 
        EphySession *session = EPHY_SESSION (object);
934
 
        EphySessionPrivate *priv = session->priv;
935
 
        EggSMClient *sm_client;
936
 
 
937
 
        LOG ("EphySession disposing");
938
 
 
939
 
        /* Only remove the crashed session if we're not shutting down while
940
 
         * the session resume dialogue was still shown!
941
 
        */
942
 
        if (priv->quit_while_resuming == FALSE)
943
 
        {
944
 
                session_delete (session, SESSION_CRASHED);
945
 
        }
946
 
 
947
 
        session_command_queue_clear (session);
948
 
 
949
 
        sm_client = egg_sm_client_get ();
950
 
        g_signal_handlers_disconnect_matched (sm_client, G_SIGNAL_MATCH_DATA,
951
 
                                              0, 0, NULL, NULL, session);
952
 
 
953
 
        G_OBJECT_CLASS (ephy_session_parent_class)->dispose (object);
954
 
}
955
 
 
956
 
static void
957
 
ephy_session_finalize (GObject *object)
958
 
{
959
 
        EphySession *session = EPHY_SESSION (object);
960
 
 
961
 
        LOG ("EphySession finalising");
962
 
 
963
 
        /* FIXME: those should be NULL already!? */
964
 
        g_list_free (session->priv->windows);
965
 
        g_list_free (session->priv->tool_windows);
966
 
 
967
 
        G_OBJECT_CLASS (ephy_session_parent_class)->finalize (object);
968
 
}
969
 
 
970
 
static void
971
 
ephy_session_iface_init (EphyExtensionIface *iface)
972
 
{
973
 
        iface->attach_window = impl_attach_window;
974
 
        iface->detach_window = impl_detach_window;
975
 
}
976
 
 
977
 
static void
978
 
ephy_session_set_property (GObject *object,
979
 
                           guint prop_id,
980
 
                           const GValue *value,
981
 
                           GParamSpec *pspec)
982
 
{
983
 
        /* no writeable properties */
984
 
        g_return_if_reached ();
985
 
}
986
 
 
987
 
static void
988
 
ephy_session_get_property (GObject *object,
989
 
                           guint prop_id,
990
 
                           GValue *value,
991
 
                           GParamSpec *pspec)
992
 
{
993
 
        EphySession *session = EPHY_SESSION (object);
994
 
 
995
 
        switch (prop_id)
996
 
        {
997
 
                case PROP_ACTIVE_WINDOW:
998
 
                        g_value_set_object (value, ephy_session_get_active_window (session));
999
 
                        break;
1000
 
                default:
1001
 
                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1002
 
        }
1003
 
}
1004
 
 
1005
 
static void
1006
 
ephy_session_class_init (EphySessionClass *class)
1007
 
{
1008
 
        GObjectClass *object_class = G_OBJECT_CLASS (class);
1009
 
 
1010
 
        object_class->dispose = ephy_session_dispose;
1011
 
        object_class->finalize = ephy_session_finalize;
1012
 
        object_class->get_property = ephy_session_get_property;
1013
 
        object_class->set_property = ephy_session_set_property;
1014
 
 
1015
 
        g_object_class_install_property
1016
 
                (object_class,
1017
 
                 PROP_ACTIVE_WINDOW,
1018
 
                 g_param_spec_object ("active-window",
1019
 
                                      "Active Window",
1020
 
                                      "The active window",
1021
 
                                      EPHY_TYPE_WINDOW,
1022
 
                                      G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
1023
 
 
1024
 
        g_type_class_add_private (object_class, sizeof (EphySessionPrivate));
1025
 
}
1026
 
 
1027
 
/* Implementation */
1028
 
 
1029
 
static void
1030
 
close_dialog (GtkWidget *widget)
1031
 
{
1032
 
        if (GTK_IS_DIALOG (widget))
1033
 
        {
1034
 
                /* don't destroy them, someone might have a ref on them */
1035
 
                gtk_dialog_response (GTK_DIALOG (widget),
1036
 
                                     GTK_RESPONSE_DELETE_EVENT);
1037
 
        }
1038
 
}
1039
 
 
1040
 
void
1041
 
ephy_session_close (EphySession *session)
1042
 
{
1043
 
        EphySessionPrivate *priv = session->priv;
1044
 
        GList *windows;
1045
 
 
1046
 
        LOG ("ephy_session_close");
1047
 
 
1048
 
        /* we have to ref the shell or else we may get finalised between
1049
 
         * destroying the windows and destroying the tool windows
1050
 
         */
1051
 
        g_object_ref (ephy_shell_get_default ());
1052
 
 
1053
 
        priv->dont_save = TRUE;
1054
 
        /* need to set this up here while the dialogue hasn't been killed yet */
1055
 
        priv->quit_while_resuming = priv->resume_window != NULL;        
1056
 
 
1057
 
        /* Clear command queue */
1058
 
        session_command_queue_clear (session);
1059
 
 
1060
 
        ephy_embed_shell_prepare_close (embed_shell);
1061
 
 
1062
 
        /* there may still be windows open, like dialogues posed from
1063
 
        * web pages, etc. Try to kill them, but be sure NOT to destroy
1064
 
        * the gtkmozembed offscreen window!
1065
 
        * Here, we just check if it's a dialogue and close it if it is one.
1066
 
        */
1067
 
        windows = gtk_window_list_toplevels ();
1068
 
        g_list_foreach (windows, (GFunc) close_dialog, NULL);
1069
 
        g_list_free (windows);
1070
 
 
1071
 
        windows = ephy_session_get_windows (session);
1072
 
        g_list_foreach (windows, (GFunc) gtk_widget_destroy, NULL);
1073
 
        g_list_free (windows);
1074
 
 
1075
 
        windows = g_list_copy (session->priv->tool_windows);
1076
 
        g_list_foreach (windows, (GFunc) gtk_widget_destroy, NULL);
1077
 
        g_list_free (windows);  
1078
 
 
1079
 
        ephy_embed_shell_prepare_close (embed_shell);
1080
 
 
1081
 
        /* Just to be really sure, do it again: */
1082
 
        windows = gtk_window_list_toplevels ();
1083
 
        g_list_foreach (windows, (GFunc) close_dialog, NULL);
1084
 
        g_list_free (windows);
1085
 
 
1086
 
        session->priv->dont_save = FALSE;
1087
 
 
1088
 
        /* Clear command queue */
1089
 
        session_command_queue_clear (session);
1090
 
 
1091
 
        g_object_unref (ephy_shell_get_default ());
1092
 
}
1093
 
 
1094
 
static int
1095
 
write_tab (xmlTextWriterPtr writer,
1096
 
           EphyEmbed *embed)
1097
 
{
1098
 
        const char *address, *title;
1099
 
        int ret;
1100
 
 
1101
 
        ret = xmlTextWriterStartElement (writer, (xmlChar *) "embed");
1102
 
        if (ret < 0) return ret;
1103
 
 
1104
 
        address = ephy_web_view_get_address (ephy_embed_get_web_view (embed));
1105
 
        ret = xmlTextWriterWriteAttribute (writer, (xmlChar *) "url",
1106
 
                                           (const xmlChar *) address);
1107
 
        if (ret < 0) return ret;
1108
 
 
1109
 
        title = ephy_web_view_get_title (ephy_embed_get_web_view (embed));
1110
 
        ret = xmlTextWriterWriteAttribute (writer, (xmlChar *) "title",
1111
 
                                           (const xmlChar *) title);
1112
 
        if (ret < 0) return ret;
1113
 
 
1114
 
        if (ephy_web_view_is_loading (ephy_embed_get_web_view (embed)))
1115
 
        {
1116
 
                ret = xmlTextWriterWriteAttribute (writer,
1117
 
                                                   (const xmlChar *) "loading",
1118
 
                                                   (const xmlChar *) "true");
1119
 
                if (ret < 0) return ret;
1120
 
        }
1121
 
 
1122
 
        ret = xmlTextWriterEndElement (writer); /* embed */
1123
 
        return ret;
1124
 
}
1125
 
 
1126
 
static int
1127
 
write_active_tab (xmlTextWriterPtr writer,
1128
 
                  GtkWidget *notebook)
1129
 
{
1130
 
        int ret;
1131
 
        int current;
1132
 
 
1133
 
        current = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook));
1134
 
    
1135
 
        ret = xmlTextWriterWriteFormatAttribute (writer, (const xmlChar *) "active-tab", "%d", current);
1136
 
        return ret;
1137
 
}
1138
 
    
1139
 
 
1140
 
static int
1141
 
write_window_geometry (xmlTextWriterPtr writer,
1142
 
                       GtkWindow *window)
1143
 
{
1144
 
        int x = 0, y = 0, width = -1, height = -1;
1145
 
        int ret;
1146
 
 
1147
 
        /* get window geometry */
1148
 
        gtk_window_get_size (window, &width, &height);
1149
 
        gtk_window_get_position (window, &x, &y);
1150
 
 
1151
 
        /* set window properties */
1152
 
        ret = xmlTextWriterWriteFormatAttribute (writer, (const xmlChar *) "x", "%d", x);
1153
 
        if (ret < 0) return ret;
1154
 
 
1155
 
        ret = xmlTextWriterWriteFormatAttribute (writer, (const xmlChar *) "y", "%d", y);
1156
 
        if (ret < 0) return ret;
1157
 
 
1158
 
        ret = xmlTextWriterWriteFormatAttribute (writer, (const xmlChar *) "width", "%d", width);
1159
 
        if (ret < 0) return ret;
1160
 
 
1161
 
        ret = xmlTextWriterWriteFormatAttribute (writer, (const xmlChar *) "height", "%d", height);
1162
 
        return ret;
1163
 
}
1164
 
 
1165
 
static int
1166
 
write_tool_window (xmlTextWriterPtr writer,
1167
 
                   GtkWindow *window)
1168
 
{
1169
 
        const xmlChar *id;
1170
 
        int ret;
1171
 
 
1172
 
        if (EPHY_IS_BOOKMARKS_EDITOR (window))
1173
 
        {
1174
 
                id = (const xmlChar *) BOOKMARKS_EDITOR_ID;
1175
 
        }
1176
 
        else if (EPHY_IS_HISTORY_WINDOW (window))
1177
 
        {
1178
 
                id = (const xmlChar *) HISTORY_WINDOW_ID;
1179
 
        }
1180
 
        else
1181
 
        {
1182
 
                g_return_val_if_reached (-1);
1183
 
        }
1184
 
 
1185
 
        ret = xmlTextWriterStartElement (writer, (const xmlChar *) "toolwindow");
1186
 
        if (ret < 0) return ret;
1187
 
 
1188
 
        ret = xmlTextWriterWriteAttribute (writer, (const xmlChar *) "id", id);
1189
 
        if (ret < 0) return ret;
1190
 
 
1191
 
        ret = write_window_geometry (writer, window);
1192
 
        if (ret < 0) return ret;
1193
 
 
1194
 
        ret = xmlTextWriterEndElement (writer); /* toolwindow */
1195
 
        return ret;
1196
 
}
1197
 
 
1198
 
static int
1199
 
write_ephy_window (xmlTextWriterPtr writer,
1200
 
                   EphyWindow *window)
1201
 
{
1202
 
        GList *tabs, *l;
1203
 
        GtkWidget *notebook;
1204
 
        const char *role;
1205
 
        int ret;
1206
 
 
1207
 
        tabs = ephy_embed_container_get_children (EPHY_EMBED_CONTAINER (window));
1208
 
        notebook = ephy_window_get_notebook (window);
1209
 
 
1210
 
        /* Do not save an empty EphyWindow.
1211
 
         * This only happens when the window was newly opened.
1212
 
         */
1213
 
        if (tabs == NULL) return 0;
1214
 
 
1215
 
        ret = xmlTextWriterStartElement (writer, (xmlChar *) "window");
1216
 
        if (ret < 0) return ret;
1217
 
 
1218
 
        ret = write_window_geometry (writer, GTK_WINDOW (window));
1219
 
        if (ret < 0) return ret;
1220
 
 
1221
 
        ret = write_active_tab (writer, notebook);
1222
 
        if (ret < 0) return ret;
1223
 
 
1224
 
        role = gtk_window_get_role (GTK_WINDOW (window));
1225
 
        if (role != NULL)
1226
 
        {
1227
 
                ret = xmlTextWriterWriteAttribute (writer, 
1228
 
                                                   (const xmlChar *)"role", 
1229
 
                                                   (const xmlChar *)role);
1230
 
                if (ret < 0) return ret;
1231
 
        }
1232
 
 
1233
 
        for (l = tabs; l != NULL; l = l->next)
1234
 
        {
1235
 
                EphyEmbed *embed = EPHY_EMBED (l->data);
1236
 
                ret = write_tab (writer, embed);
1237
 
                if (ret < 0) break;
1238
 
        }
1239
 
        g_list_free (tabs);
1240
 
        if (ret < 0) return ret;
1241
 
 
1242
 
        ret = xmlTextWriterEndElement (writer); /* window */
1243
 
        return ret;
1244
 
}
1245
 
 
1246
 
gboolean
1247
 
ephy_session_save (EphySession *session,
1248
 
                   const char *filename)
1249
 
{
1250
 
        EphySessionPrivate *priv;
1251
 
        xmlTextWriterPtr writer;
1252
 
        GList *w;
1253
 
        GFile *save_to_file, *tmp_file;
1254
 
        char *tmp_file_path, *save_to_file_path;
1255
 
        int ret;
1256
 
 
1257
 
        g_return_val_if_fail (EPHY_IS_SESSION (session), FALSE);
1258
 
 
1259
 
        priv = session->priv;
1260
 
 
1261
 
        if (priv->dont_save)
1262
 
        {
1263
 
                return TRUE;
1264
 
        }
1265
 
 
1266
 
        LOG ("ephy_sesion_save %s", filename);
1267
 
 
1268
 
        if (priv->windows == NULL && priv->tool_windows == NULL)
1269
 
        {
1270
 
                session_delete (session, filename);
1271
 
                return TRUE;
1272
 
        }
1273
 
 
1274
 
        save_to_file = get_session_file (filename);
1275
 
        save_to_file_path = g_file_get_path (save_to_file);
1276
 
        tmp_file_path = g_strconcat (save_to_file_path, ".tmp", NULL);
1277
 
        g_free (save_to_file_path);
1278
 
        tmp_file = g_file_new_for_path (tmp_file_path);
1279
 
 
1280
 
        /* FIXME: do we want to turn on compression? */
1281
 
        writer = xmlNewTextWriterFilename (tmp_file_path, 0);
1282
 
        if (writer == NULL)
1283
 
        {
1284
 
                g_free (tmp_file_path);
1285
 
 
1286
 
                return FALSE;
1287
 
        }
1288
 
 
1289
 
        ret = xmlTextWriterSetIndent (writer, 1);
1290
 
        if (ret < 0) goto out;
1291
 
 
1292
 
        ret = xmlTextWriterSetIndentString (writer, (const xmlChar *) "  ");
1293
 
        if (ret < 0) goto out;
1294
 
 
1295
 
        START_PROFILER ("Saving session")
1296
 
 
1297
 
        ret = xmlTextWriterStartDocument (writer, "1.0", NULL, NULL);
1298
 
        if (ret < 0) goto out;
1299
 
 
1300
 
        /* create and set the root node for the session */
1301
 
        ret = xmlTextWriterStartElement (writer, (const xmlChar *) "session");
1302
 
        if (ret < 0) goto out;
1303
 
 
1304
 
        /* iterate through all the windows */   
1305
 
        for (w = session->priv->windows; w != NULL && ret >= 0; w = w->next)
1306
 
        {
1307
 
                ret = write_ephy_window (writer, EPHY_WINDOW (w->data));
1308
 
        }
1309
 
        if (ret < 0) goto out;
1310
 
 
1311
 
        for (w = session->priv->tool_windows; w != NULL && ret >= 0; w = w->next)
1312
 
        {
1313
 
                ret = write_tool_window (writer, GTK_WINDOW (w->data));
1314
 
        }
1315
 
        if (ret < 0) goto out;
1316
 
 
1317
 
        ret = xmlTextWriterEndElement (writer); /* session */
1318
 
        if (ret < 0) goto out;
1319
 
 
1320
 
        ret = xmlTextWriterEndDocument (writer);
1321
 
 
1322
 
out:
1323
 
        xmlFreeTextWriter (writer);
1324
 
 
1325
 
        if (ret >= 0)
1326
 
        {
1327
 
                if (ephy_file_switch_temp_file (save_to_file, tmp_file) == FALSE)
1328
 
                {
1329
 
                        ret = -1;
1330
 
                }
1331
 
        }
1332
 
 
1333
 
        g_free (tmp_file_path);
1334
 
        g_object_unref (save_to_file);
1335
 
        g_object_unref (tmp_file);
1336
 
 
1337
 
        STOP_PROFILER ("Saving session")
1338
 
 
1339
 
        return ret >= 0 ? TRUE : FALSE;
1340
 
}
1341
 
 
1342
 
static void
1343
 
confirm_before_recover (EphyWindow* window, char* url, char* title)
1344
 
{
1345
 
        EphyEmbed *embed;
1346
 
 
1347
 
        embed = ephy_shell_new_tab (ephy_shell, window, NULL, NULL,
1348
 
                                    EPHY_NEW_TAB_IN_EXISTING_WINDOW |
1349
 
                                    EPHY_NEW_TAB_APPEND_LAST);
1350
 
 
1351
 
        ephy_web_view_load_error_page (ephy_embed_get_web_view (embed), url,
1352
 
                                       EPHY_WEB_VIEW_ERROR_PAGE_CRASH, NULL);
1353
 
}
1354
 
 
1355
 
static void 
1356
 
parse_embed (xmlNodePtr child,
1357
 
             EphyWindow *window,
1358
 
             gboolean is_first_window,
1359
 
             EphySession *session)
1360
 
{
1361
 
        EphySessionPrivate *priv = session->priv;
1362
 
 
1363
 
        while (child != NULL)
1364
 
        {
1365
 
                if (strcmp ((char *) child->name, "embed") == 0)
1366
 
                {
1367
 
                        xmlChar *url, *attr;
1368
 
                        char *recover_url;
1369
 
                        gboolean was_loading;
1370
 
 
1371
 
                        g_return_if_fail (window != NULL);
1372
 
 
1373
 
                        /* Check if that tab wasn't fully loaded yet when the session crashed */
1374
 
                        attr = xmlGetProp (child, (const xmlChar *) "loading");
1375
 
                        was_loading = attr != NULL &&
1376
 
                                      xmlStrEqual (attr, (const xmlChar *) "true");
1377
 
                        xmlFree (attr);
1378
 
 
1379
 
                        url = xmlGetProp (child, (const xmlChar *) "url");
1380
 
                        if (url == NULL) 
1381
 
                                continue;
1382
 
 
1383
 
                        /* in the case that crash happens before we receive the URL from the server,
1384
 
                           this will open an about:blank tab. See http://bugzilla.gnome.org/show_bug.cgi?id=591294
1385
 
 
1386
 
                           Otherwise, if the web was fully loaded, it is reloaded again.
1387
 
                        
1388
 
                        */
1389
 
                        if (!was_loading ||
1390
 
                            strcmp ((const char *) url, "about:blank") == 0)
1391
 
                        {
1392
 
                                recover_url = (char *) url;
1393
 
                                
1394
 
                                /* Reuse the window holding the recovery infobar instead of creating a new one */
1395
 
                                if (is_first_window == TRUE && priv->resume_window != NULL)
1396
 
                                {
1397
 
                                        EphyWebView *web_view;
1398
 
                                        EphyEmbed *embed;
1399
 
 
1400
 
                                        embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (priv->resume_window));
1401
 
                                        web_view = ephy_embed_get_web_view (embed);
1402
 
                                        ephy_web_view_load_url(web_view, recover_url);
1403
 
 
1404
 
                                        is_first_window = FALSE;
1405
 
                                }
1406
 
                                else
1407
 
                                {
1408
 
                                        ephy_shell_new_tab (ephy_shell, window, NULL, recover_url,
1409
 
                                                            EPHY_NEW_TAB_IN_EXISTING_WINDOW |
1410
 
                                                            EPHY_NEW_TAB_OPEN_PAGE |
1411
 
                                                            EPHY_NEW_TAB_APPEND_LAST);
1412
 
                                }
1413
 
                        }
1414
 
                        else if (was_loading && url != NULL &&
1415
 
                                 strcmp ((const char *) url, "about:blank") != 0)
1416
 
                        {
1417
 
                                /* shows a message to the user that warns that this page was
1418
 
                                   loading during crash and make Epiphany crash again,
1419
 
                                   in this case we know the URL */
1420
 
 
1421
 
                                xmlChar* title = xmlGetProp (child, (const xmlChar *) "title");
1422
 
                        
1423
 
                                confirm_before_recover (window, (char*) url, (char*) title);
1424
 
                        }
1425
 
 
1426
 
                        xmlFree (url);
1427
 
                }
1428
 
 
1429
 
                child = child->next;
1430
 
        }
1431
 
}
1432
 
 
1433
 
static gboolean
1434
 
int_from_string (const char *string,
1435
 
                 int *retval)
1436
 
{
1437
 
        char *tail = NULL;
1438
 
        long int val;
1439
 
        gboolean success = FALSE;
1440
 
 
1441
 
        if (string == NULL) return FALSE;
1442
 
 
1443
 
        errno = 0;
1444
 
        val = strtol (string, &tail, 0);
1445
 
 
1446
 
        if (errno == 0 && tail != NULL && tail[0] == '\0')
1447
 
        {
1448
 
                *retval = (int) val;
1449
 
                success = TRUE;
1450
 
        }
1451
 
 
1452
 
        return success;
1453
 
}
1454
 
 
1455
 
static void
1456
 
restore_geometry (GtkWindow *window,
1457
 
                  xmlNodePtr node)
1458
 
{
1459
 
        xmlChar *tmp;
1460
 
        int x = 0, y = 0, width = -1, height = -1;
1461
 
        gboolean success = TRUE;
1462
 
 
1463
 
        g_return_if_fail (window != NULL);
1464
 
 
1465
 
        tmp = xmlGetProp (node, (xmlChar *) "x");
1466
 
        success &= int_from_string ((char *) tmp, &x);
1467
 
        xmlFree (tmp);
1468
 
        tmp = xmlGetProp (node, (xmlChar *) "y");
1469
 
        success &= int_from_string ((char *) tmp, &y);
1470
 
        xmlFree (tmp);
1471
 
        tmp = xmlGetProp (node, (xmlChar *) "width");
1472
 
        success &= int_from_string ((char *) tmp, &width);
1473
 
        xmlFree (tmp);
1474
 
        tmp = xmlGetProp (node, (xmlChar *) "height");
1475
 
        success &= int_from_string ((char *) tmp, &height);
1476
 
        xmlFree (tmp);
1477
 
 
1478
 
        if (success)
1479
 
        {
1480
 
                tmp = xmlGetProp (node, (xmlChar *)"role");
1481
 
                if (tmp != NULL)
1482
 
                {
1483
 
                        gtk_window_set_role (GTK_WINDOW (window), (const char *)tmp);
1484
 
                        xmlFree (tmp);
1485
 
                }
1486
 
 
1487
 
                gtk_window_move (window, x, y);
1488
 
                gtk_window_set_default_size (window, width, height);
1489
 
                
1490
 
        }
1491
 
}
1492
 
 
1493
 
/*
1494
 
 * ephy_session_load:
1495
 
 * @session: a #EphySession
1496
 
 * @filename: the path of the source file
1497
 
 * @user_time: a user_time, or 0
1498
 
 *
1499
 
 * Load a session from disk, restoring the windows and their state
1500
 
 *
1501
 
 * Return value: TRUE if at least a window has been opened
1502
 
 **/
1503
 
gboolean
1504
 
ephy_session_load (EphySession *session,
1505
 
                   const char *filename,
1506
 
                   guint32 user_time)
1507
 
{
1508
 
        EphySessionPrivate *priv = session->priv;
1509
 
        xmlDocPtr doc;
1510
 
        xmlNodePtr child;
1511
 
        EphyWindow *window;
1512
 
        GtkWidget *widget = NULL;
1513
 
        GFile *save_to_file;
1514
 
        char *save_to_path;
1515
 
        gboolean first_window_created = FALSE;
1516
 
 
1517
 
        LOG ("ephy_sesion_load %s", filename);
1518
 
 
1519
 
        save_to_file = get_session_file (filename);
1520
 
        save_to_path = g_file_get_path (save_to_file);
1521
 
        g_object_unref (save_to_file);
1522
 
 
1523
 
        doc = xmlParseFile (save_to_path);
1524
 
        g_free (save_to_path);
1525
 
 
1526
 
        if (doc == NULL)
1527
 
        {
1528
 
                return FALSE;
1529
 
        }
1530
 
 
1531
 
        g_object_ref (ephy_shell_get_default ());
1532
 
 
1533
 
        priv->dont_save = TRUE;
1534
 
 
1535
 
        child = xmlDocGetRootElement (doc);
1536
 
 
1537
 
        /* skip the session node */
1538
 
        child = child->children;
1539
 
 
1540
 
        while (child != NULL)
1541
 
        {
1542
 
                if (xmlStrEqual (child->name, (const xmlChar *) "window"))
1543
 
                {
1544
 
                        xmlChar *tmp;
1545
 
                        EphyEmbed *active_child;
1546
 
                    
1547
 
                        if (first_window_created == FALSE && priv->resume_window != NULL)
1548
 
                        {
1549
 
                                window = EPHY_WINDOW (priv->resume_window);
1550
 
                                first_window_created = TRUE;
1551
 
                        }
1552
 
                        else
1553
 
                                window = ephy_window_new ();
1554
 
 
1555
 
                        widget = GTK_WIDGET (window);
1556
 
                        restore_geometry (GTK_WINDOW (widget), child);
1557
 
 
1558
 
                        ephy_gui_window_update_user_time (widget, user_time);
1559
 
 
1560
 
                        /* Now add the tabs */
1561
 
                        parse_embed (child->children, window,
1562
 
                                     window == EPHY_WINDOW (priv->resume_window), session);
1563
 
 
1564
 
                        /* Set focus to something sane */
1565
 
                        tmp = xmlGetProp (child, (xmlChar *) "active-tab");
1566
 
                        if (tmp != NULL)
1567
 
                        {
1568
 
                                gboolean success;
1569
 
                                int active_tab;
1570
 
 
1571
 
                                success = int_from_string ((char *) tmp, &active_tab);
1572
 
                                xmlFree (tmp);
1573
 
                                if (success)
1574
 
                                {
1575
 
                                        GtkWidget *notebook;
1576
 
                                        notebook = ephy_window_get_notebook (window);
1577
 
                                        gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), active_tab);
1578
 
                                }
1579
 
                        }
1580
 
 
1581
 
                        active_child = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
1582
 
                        gtk_widget_grab_focus (GTK_WIDGET (active_child));
1583
 
                        gtk_widget_show (widget);
1584
 
                }
1585
 
                else if (xmlStrEqual (child->name, (const xmlChar *) "toolwindow"))
1586
 
                {
1587
 
                        xmlChar *id;
1588
 
 
1589
 
                        id = xmlGetProp (child, (const xmlChar *) "id");
1590
 
 
1591
 
                        if (id && xmlStrEqual ((const xmlChar *) BOOKMARKS_EDITOR_ID, id))
1592
 
                        {
1593
 
                                if (!g_settings_get_boolean
1594
 
                                    (EPHY_SETTINGS_LOCKDOWN,
1595
 
                                     EPHY_PREFS_LOCKDOWN_BOOKMARK_EDITING))
1596
 
                                {
1597
 
                                        widget = ephy_shell_get_bookmarks_editor (ephy_shell);
1598
 
                                }
1599
 
                        }
1600
 
                        else if (id && xmlStrEqual ((const xmlChar *) HISTORY_WINDOW_ID, id))
1601
 
                        {
1602
 
                                if (!g_settings_get_boolean
1603
 
                                    (EPHY_SETTINGS_LOCKDOWN,
1604
 
                                     EPHY_PREFS_LOCKDOWN_HISTORY))
1605
 
                                {
1606
 
                                        widget = ephy_shell_get_history_window (ephy_shell);
1607
 
                                }
1608
 
                        }
1609
 
 
1610
 
                        restore_geometry (GTK_WINDOW (widget), child);
1611
 
 
1612
 
                        ephy_gui_window_update_user_time (widget, user_time);
1613
 
 
1614
 
                        gtk_widget_show (widget);
1615
 
                }
1616
 
 
1617
 
                child = child->next;
1618
 
        }
1619
 
 
1620
 
        xmlFreeDoc (doc);
1621
 
 
1622
 
        priv->dont_save = FALSE;
1623
 
        priv->resume_window = NULL;
1624
 
 
1625
 
        ephy_session_save (session, SESSION_CRASHED);
1626
 
 
1627
 
        g_object_unref (ephy_shell_get_default ());
1628
 
 
1629
 
        return (priv->windows != NULL || priv->tool_windows != NULL);
1630
 
}
1631
 
 
1632
 
/**
1633
 
 * ephy_session_get_windows:
1634
 
 * @session: the #EphySession
1635
 
 *
1636
 
 * Returns: (element-type EphyWindow) (transfer container): the list of
1637
 
 *          open #EphyWindow:s.
1638
 
 **/
1639
 
GList *
1640
 
ephy_session_get_windows (EphySession *session)
1641
 
{
1642
 
        g_return_val_if_fail (EPHY_IS_SESSION (session), NULL);
1643
 
 
1644
 
        return g_list_copy (session->priv->windows);
1645
 
}
1646
 
 
1647
 
/**
1648
 
 * ephy_session_add_window:
1649
 
 * @session: a #EphySession
1650
 
 * @window: a #EphyWindow
1651
 
 *
1652
 
 * Add a tool window to the session. #EphyWindow take care of adding
1653
 
 * itself to session.
1654
 
 **/
1655
 
void
1656
 
ephy_session_add_window (EphySession *session,
1657
 
                         GtkWindow *window)
1658
 
{
1659
 
        LOG ("ephy_session_add_window %p", window);
1660
 
 
1661
 
        session->priv->tool_windows =
1662
 
                g_list_append (session->priv->tool_windows, window);
1663
 
 
1664
 
        ephy_session_save (session, SESSION_CRASHED);
1665
 
}
1666
 
 
1667
 
/**
1668
 
 * ephy_session_remove_window:
1669
 
 * @session: a #EphySession.
1670
 
 * @window: a #GtkWindow, which must be either the bookmarks editor or the
1671
 
 * history window.
1672
 
 *
1673
 
 * Remove a tool window from the session.
1674
 
 **/
1675
 
void
1676
 
ephy_session_remove_window (EphySession *session,
1677
 
                            GtkWindow *window)
1678
 
{
1679
 
        LOG ("ephy_session_remove_window %p", window);
1680
 
 
1681
 
        session->priv->tool_windows =
1682
 
                g_list_remove (session->priv->tool_windows, window);
1683
 
 
1684
 
        ephy_session_save (session, SESSION_CRASHED);
1685
 
}
1686
 
 
1687
 
/**
1688
 
 * ephy_session_get_active_window:
1689
 
 * @session: a #EphySession
1690
 
 *
1691
 
 * Get the current active browser window. Use it when you
1692
 
 * need to take an action (like opening an url) on
1693
 
 * a window but you dont have a target window.
1694
 
 *
1695
 
 * Return value: (transfer none): the current active non-popup browser
1696
 
 *               window, or NULL of there is none.
1697
 
 **/
1698
 
EphyWindow *
1699
 
ephy_session_get_active_window (EphySession *session)
1700
 
{
1701
 
        EphyWindow *window = NULL;
1702
 
        EphyEmbedContainer *w;
1703
 
        GList *l;
1704
 
 
1705
 
        g_return_val_if_fail (EPHY_IS_SESSION (session), NULL);
1706
 
 
1707
 
        for (l = session->priv->windows; l != NULL; l = l->next)
1708
 
        {
1709
 
                w = EPHY_EMBED_CONTAINER (l->data);
1710
 
 
1711
 
                if (ephy_embed_container_get_is_popup (w) == FALSE)
1712
 
                {
1713
 
                        window = EPHY_WINDOW (w);
1714
 
                        break;
1715
 
                }
1716
 
        }
1717
 
 
1718
 
        return window;
1719
 
}
1720
 
 
1721
 
/**
1722
 
 * ephy_session_queue_command:
1723
 
 * @session: a #EphySession
1724
 
 **/
1725
 
void
1726
 
ephy_session_queue_command (EphySession *session,
1727
 
                            EphySessionCommand command,
1728
 
                            const char *arg,
1729
 
                            char **args,
1730
 
                            guint32 user_time,
1731
 
                            gboolean priority)
1732
 
{
1733
 
        EphySessionPrivate *priv;
1734
 
        GList *element;
1735
 
        SessionCommand *cmd;
1736
 
 
1737
 
        LOG ("queue_command command:%d", command);
1738
 
 
1739
 
        g_return_if_fail (EPHY_IS_SESSION (session));
1740
 
        g_return_if_fail (command != EPHY_SESSION_CMD_OPEN_URIS || args != NULL);
1741
 
 
1742
 
        priv = session->priv;
1743
 
 
1744
 
        /* First look if the same command is already queued */
1745
 
        if (command > EPHY_SESSION_CMD_RESUME_SESSION &&
1746
 
            command < EPHY_SESSION_CMD_OPEN_URIS)
1747
 
        {
1748
 
                element = g_queue_find_custom (priv->queue,
1749
 
                                               GINT_TO_POINTER (command),
1750
 
                                               (GCompareFunc) session_command_find);
1751
 
                if (element != NULL)
1752
 
                {
1753
 
                        cmd = (SessionCommand *) element->data;
1754
 
 
1755
 
                        if ((command == EPHY_SESSION_CMD_LOAD_SESSION &&
1756
 
                             strcmp (cmd->arg, arg) == 0) ||
1757
 
                            command == EPHY_SESSION_CMD_OPEN_BOOKMARKS_EDITOR ||
1758
 
                            command == EPHY_SESSION_CMD_RESUME_SESSION)
1759
 
                        {
1760
 
                                cmd->user_time = user_time;
1761
 
                                g_queue_remove (priv->queue, cmd);
1762
 
                                g_queue_push_tail (priv->queue, cmd);
1763
 
 
1764
 
                                return;
1765
 
                        }
1766
 
                }
1767
 
        }
1768
 
 
1769
 
        /* FIXME: use g_slice_new */
1770
 
        cmd = g_new0 (SessionCommand, 1);
1771
 
        cmd->command = command;
1772
 
        cmd->arg = arg ? g_strdup (arg) : NULL;
1773
 
        cmd->args = args ? g_strdupv (args) : NULL;
1774
 
        cmd->user_time = user_time;
1775
 
        /* This ref is released in session_command_free */
1776
 
        g_object_ref (ephy_shell_get_default ());
1777
 
 
1778
 
        if (priority)
1779
 
        {
1780
 
                g_queue_push_head (priv->queue, cmd);
1781
 
        }
1782
 
        else
1783
 
        {
1784
 
                g_queue_push_tail (priv->queue, cmd);
1785
 
        }
1786
 
 
1787
 
        session_command_queue_next (session);
1788
 
 
1789
 
        if (priv->resume_window != NULL)
1790
 
        {
1791
 
                gtk_window_present_with_time (GTK_WINDOW (priv->resume_window),
1792
 
                                              user_time);
1793
 
        }
1794
 
}