~ubuntu-core-dev/update-notifier/ubuntu

« back to all changes in this revision

Viewing changes to src/crash.c

  • Committer: Michael Terry
  • Date: 2013-02-01 15:13:06 UTC
  • mto: This revision was merged to the branch mainline in revision 780.
  • Revision ID: michael.terry@canonical.com-20130201151306-famyx1w1k3o5xg1j
Install a policykit policy file to replace last gksu use for
cddistupgrader.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifdef HAVE_CONFIG_H
 
2
#include "config.h"
 
3
#endif
 
4
 
 
5
#include <sys/types.h>
 
6
#include <sys/stat.h>
 
7
#include <unistd.h>
 
8
 
 
9
#include <libnotify/notify.h>
 
10
 
 
11
#include "update-notifier.h"
 
12
#include "update.h"
 
13
#include "trayappletui.h"
 
14
 
 
15
static gboolean
 
16
check_system_crashes(void)
 
17
{
 
18
   int exitcode;
 
19
 
 
20
   if(!in_admin_group())
 
21
      return FALSE;
 
22
 
 
23
   // check for system crashes
 
24
   gchar *argv[] = { CRASHREPORT_HELPER, "--system", NULL };
 
25
   if(!g_spawn_sync(NULL,
 
26
                    argv,
 
27
                    NULL,
 
28
                    G_SPAWN_STDOUT_TO_DEV_NULL|G_SPAWN_STDERR_TO_DEV_NULL,
 
29
                    NULL,
 
30
                    NULL,
 
31
                    NULL,
 
32
                    NULL,
 
33
                    &exitcode,
 
34
                    NULL)) {
 
35
      g_warning("Can not run %s\n", CRASHREPORT_HELPER);
 
36
      return FALSE;
 
37
   }
 
38
 
 
39
   return exitcode == 0;
 
40
}
 
41
 
 
42
static gboolean
 
43
ask_invoke_apport_with_pkexec(void)
 
44
{
 
45
   GtkDialog *dialog;
 
46
   gchar *msg = _("System program problem detected");
 
47
   gchar *descr = _("Do you want to report the problem "
 
48
                    "now?");
 
49
   dialog = (GtkDialog*)gtk_message_dialog_new (NULL,
 
50
                                    GTK_DIALOG_DESTROY_WITH_PARENT,
 
51
                                    GTK_MESSAGE_QUESTION,
 
52
                                    GTK_BUTTONS_NONE,
 
53
                                    "%s", msg);
 
54
   gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
 
55
                                            "%s", descr);
 
56
   gtk_dialog_add_button(dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
 
57
   gtk_dialog_add_button(dialog, _("Report problem…"), GTK_RESPONSE_ACCEPT);
 
58
   int res = gtk_dialog_run(dialog);
 
59
   gtk_widget_destroy(GTK_WIDGET(dialog));
 
60
   if (res == GTK_RESPONSE_ACCEPT)
 
61
      return TRUE;
 
62
   return FALSE;
 
63
}
 
64
 
 
65
static gboolean 
 
66
run_apport(TrayApplet *ta)
 
67
{
 
68
   g_debug("fire up the crashreport tool\n");
 
69
   // be nice and always ask first before firing up pkexec
 
70
   if (check_system_crashes() && ask_invoke_apport_with_pkexec()) {
 
71
      invoke_with_pkexec(CRASHREPORT_REPORT_APP);
 
72
   } else {
 
73
      return g_spawn_command_line_async(CRASHREPORT_REPORT_APP, NULL);
 
74
   }
 
75
   return TRUE;
 
76
}
 
77
 
 
78
static gboolean
 
79
show_notification (TrayApplet *ta)
 
80
{
 
81
   NotifyNotification *n;
 
82
 
 
83
   // check if the update-icon is still visible (in the delay time a 
 
84
   // update may already have been performed)
 
85
   if(!tray_applet_ui_get_visible(ta))
 
86
      return FALSE;
 
87
 
 
88
   n = tray_applet_ui_get_data (ta, "notification");
 
89
   if (n)
 
90
      g_object_unref (n);
 
91
   tray_applet_ui_set_data (ta, "notification", NULL);
 
92
 
 
93
   // now show a notification handle 
 
94
   n = notify_notification_new(
 
95
                                     _("Crash report detected"),
 
96
                                     _("An application has crashed on your "
 
97
                                       "system (now or in the past). "
 
98
                                       "Click on the notification icon to "
 
99
                                       "display details. "
 
100
                                       ),
 
101
                                     GTK_STOCK_DIALOG_INFO);
 
102
   notify_notification_set_timeout (n, 60000);
 
103
   notify_notification_show (n, NULL);
 
104
   tray_applet_ui_set_data (ta, "notification", n);
 
105
 
 
106
   return FALSE;
 
107
}
 
108
 
 
109
static void 
 
110
hide_crash_applet(TrayApplet *ta)
 
111
{
 
112
   NotifyNotification *n;
 
113
 
 
114
   tray_applet_ui_set_visible(ta, FALSE);
 
115
   
 
116
   /* Hide any notification popup */
 
117
   n = tray_applet_ui_get_data (ta, "notification");
 
118
   if (n) {
 
119
      notify_notification_close (n, NULL);
 
120
      g_object_unref (n);
 
121
   }
 
122
   tray_applet_ui_set_data (ta, "notification", NULL);
 
123
}
 
124
 
 
125
gboolean
 
126
crashreport_check (TrayApplet *ta)
 
127
{
 
128
   int crashreports_found = 0;
 
129
   gboolean system_crashes;
 
130
   g_debug("crashreport_check\n");
 
131
 
 
132
   // don't do anything if no apport-gtk is installed
 
133
   if(!g_file_test(CRASHREPORT_REPORT_APP, G_FILE_TEST_IS_EXECUTABLE))
 
134
      return FALSE;
 
135
 
 
136
   // Check whether the user doesn't want notifications
 
137
   if (!g_settings_get_boolean (ta->un->settings,
 
138
                                SETTINGS_KEY_APPORT_NOTIFICATIONS)) {
 
139
      g_debug("apport notifications disabled, not displaying crashes");
 
140
      return FALSE;
 
141
   }
 
142
 
 
143
   // check for (new) reports by calling CRASHREPORT_HELPER
 
144
   // and checking the return code
 
145
   int exitcode;
 
146
   gchar *argv[] = { CRASHREPORT_HELPER, NULL };
 
147
   if(!g_spawn_sync(NULL,
 
148
                    argv,
 
149
                    NULL,
 
150
                    G_SPAWN_STDOUT_TO_DEV_NULL|G_SPAWN_STDERR_TO_DEV_NULL,
 
151
                    NULL,
 
152
                    NULL,
 
153
                    NULL,
 
154
                    NULL,
 
155
                    &exitcode,
 
156
                    NULL)) {
 
157
      g_warning("Can not run %s\n", CRASHREPORT_HELPER);
 
158
      return FALSE;
 
159
   }
 
160
   // exitcode == 0: reports found, else no reports
 
161
   system_crashes = check_system_crashes();
 
162
   crashreports_found = !exitcode || system_crashes;
 
163
 
 
164
   // in autolaunch mode, just open windows, 
 
165
   gboolean autolaunch = g_settings_get_boolean(ta->un->settings,
 
166
                                                SETTINGS_KEY_AUTO_LAUNCH); 
 
167
   if (autolaunch) {
 
168
      if (crashreports_found > 0) {
 
169
         g_debug("autolaunch mode, just running apport now");
 
170
         crashreports_found=0;
 
171
         run_apport(ta);
 
172
         return TRUE;
 
173
      } else
 
174
         return FALSE;
 
175
   }
 
176
 
 
177
   // non-autolaunch will always use the notification area
 
178
   gboolean visible = tray_applet_ui_get_visible(ta);
 
179
 
 
180
   // crashreport found 
 
181
   if(crashreports_found > 0 && !visible) {
 
182
      tray_applet_ui_set_visible(ta, TRUE);
 
183
      /* Show the notification, after a delay so it doesn't look ugly
 
184
       * if we've just logged in */
 
185
      g_timeout_add(5000, (GSourceFunc)(show_notification), ta);
 
186
   }
 
187
 
 
188
   // no crashreports, but visible
 
189
   if((crashreports_found == 0) && visible) {
 
190
      hide_crash_applet(ta);
 
191
   }
 
192
 
 
193
   return TRUE;
 
194
}
 
195
 
 
196
static gboolean
 
197
button_release_cb (GtkWidget *widget,
 
198
                   TrayApplet *ta)
 
199
{
 
200
   run_apport(ta);
 
201
   hide_crash_applet(ta);
 
202
   return TRUE;
 
203
}
 
204
 
 
205
static gboolean
 
206
crashreport_check_initially(TrayApplet *ta)
 
207
{
 
208
   crashreport_check(ta);
 
209
   // stop timeout handler
 
210
   return FALSE;
 
211
}
 
212
 
 
213
void
 
214
crashreport_tray_icon_init (TrayApplet *ta)
 
215
{
 
216
        tray_applet_ui_set_single_action(ta,
 
217
                                         _("Crash report detected"),
 
218
                                         G_CALLBACK(button_release_cb),
 
219
                                         ta);
 
220
 
 
221
        /* Check for crashes for the first time */
 
222
        g_timeout_add_seconds(1, (GSourceFunc)crashreport_check_initially, ta);
 
223
}