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

« back to all changes in this revision

Viewing changes to src/crash.c

  • Committer: Jeremy Bicha
  • Date: 2019-02-09 14:25:07 UTC
  • Revision ID: jbicha@ubuntu.com-20190209142507-45fc0sqnn4uqdl7j
Try adding gnome-shell as alternate dependency of notification-daemon

as part of an effort to drop notification-daemon to universe

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
 
11
11
#include "update-notifier.h"
12
12
#include "update.h"
13
 
 
14
 
 
15
 
 
 
13
#include "trayappletui.h"
16
14
 
17
15
static gboolean
18
 
check_system_crashes() {
 
16
check_system_crashes(void)
 
17
{
19
18
   int exitcode;
20
19
 
21
20
   if(!in_admin_group())
22
21
      return FALSE;
23
22
 
24
23
   // check for system crashes
25
 
   if(!g_spawn_command_line_sync(CRASHREPORT_HELPER " --system", NULL, NULL, 
26
 
                                 &exitcode, NULL)) {
27
 
      g_warning("Can not run %s\n", CRASHREPORT_HELPER);
 
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", CRASHREPORT_HELPER);
28
36
      return FALSE;
29
37
   }
30
38
 
31
39
   return exitcode == 0;
32
40
}
33
41
 
34
 
static gboolean 
 
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
35
66
run_apport(TrayApplet *ta)
36
67
{
37
 
   g_debug("fire up the crashreport tool\n");
 
68
   g_debug("fire up the crashreport tool");
 
69
   // be nice and always ask first before firing up pkexec
38
70
   if (check_system_crashes()) {
39
 
       invoke_with_gksu(CRASHREPORT_REPORT_APP, 
40
 
        _("<span weight=\"bold\" size=\"larger\">Please enter your password to access problem reports of system programs</span>"),
41
 
        TRUE);
42
 
       return TRUE;
43
 
   } else
44
 
       return g_spawn_command_line_async(CRASHREPORT_REPORT_APP, NULL);
 
71
      // workaround, wayland doesn't allow pkexec use
 
72
      if (g_strcmp0 (g_getenv ("XDG_SESSION_TYPE"), "wayland") == 0)
 
73
         g_debug ("no pkexec for system reports under wayland");
 
74
      else if (ask_invoke_apport_with_pkexec())
 
75
         invoke_with_pkexec(CRASHREPORT_REPORT_APP);
 
76
   } else {
 
77
      return g_spawn_command_line_async(CRASHREPORT_REPORT_APP, NULL);
 
78
   }
 
79
   return TRUE;
45
80
}
46
81
 
47
82
static gboolean
49
84
{
50
85
   NotifyNotification *n;
51
86
 
52
 
   // check if the update-icon is still visible (in the delay time a 
 
87
   // check if the update-icon is still visible (in the delay time a
53
88
   // update may already have been performed)
54
 
   if(!gtk_status_icon_get_visible(ta->tray_icon))
 
89
   if(!tray_applet_ui_get_visible(ta))
55
90
      return FALSE;
56
91
 
57
 
   GdkRectangle area;
58
 
   gtk_status_icon_get_geometry(ta->tray_icon, NULL, &area, NULL);
59
 
 
60
 
   // no usefull coordiante yet, do another timeout
61
 
   if(area.x <= 0 || area.y <= 0 || area.width <= 0 || area.height <= 0)
62
 
      return TRUE;
63
 
 
64
 
   // now show a notification handle 
65
 
   n = notify_notification_new_with_status_icon(
 
92
   n = tray_applet_ui_get_data (ta, "notification");
 
93
   if (n)
 
94
      g_object_unref (n);
 
95
   tray_applet_ui_set_data (ta, "notification", NULL);
 
96
 
 
97
   // now show a notification handle
 
98
   n = notify_notification_new(
66
99
                                     _("Crash report detected"),
67
100
                                     _("An application has crashed on your "
68
101
                                       "system (now or in the past). "
69
102
                                       "Click on the notification icon to "
70
103
                                       "display details. "
71
104
                                       ),
72
 
                                     GTK_STOCK_DIALOG_INFO,
73
 
                                     ta->tray_icon);
74
 
        notify_notification_set_timeout (n, 60000);
75
 
        notify_notification_show (n, NULL);
76
 
        g_object_set_data (G_OBJECT(ta->tray_icon), "notification", n);
 
105
                                     GTK_STOCK_DIALOG_INFO);
 
106
   notify_notification_set_timeout (n, 60000);
 
107
   notify_notification_show (n, NULL);
 
108
   tray_applet_ui_set_data (ta, "notification", n);
77
109
 
78
 
        return FALSE;
 
110
   return FALSE;
79
111
}
80
112
 
81
 
static void 
 
113
static void
82
114
hide_crash_applet(TrayApplet *ta)
83
115
{
84
116
   NotifyNotification *n;
85
 
 
86
 
   gtk_status_icon_set_visible(ta->tray_icon, FALSE);
87
 
   
 
117
 
88
118
   /* Hide any notification popup */
89
 
   n = g_object_get_data (G_OBJECT(ta->tray_icon), "notification");
90
 
   if (n)
 
119
   n = tray_applet_ui_get_data (ta, "notification");
 
120
   if (n) {
91
121
      notify_notification_close (n, NULL);
92
 
   g_object_set_data (G_OBJECT(ta->tray_icon), "notification", NULL);
 
122
      g_object_unref (n);
 
123
   }
 
124
   tray_applet_ui_destroy (ta);
 
125
}
 
126
 
 
127
static gboolean
 
128
button_release_cb (GtkWidget *widget,
 
129
                   TrayApplet *ta)
 
130
{
 
131
   run_apport(ta);
 
132
   hide_crash_applet(ta);
 
133
   return TRUE;
93
134
}
94
135
 
95
136
gboolean
96
137
crashreport_check (TrayApplet *ta)
97
138
{
98
139
   int crashreports_found = 0;
99
 
   static gboolean first_run = TRUE;
100
140
   gboolean system_crashes;
101
 
 
102
 
   //   g_debug("crashreport_check\n");
 
141
   g_debug("crashreport_check");
103
142
 
104
143
   // don't do anything if no apport-gtk is installed
105
144
   if(!g_file_test(CRASHREPORT_REPORT_APP, G_FILE_TEST_IS_EXECUTABLE))
106
145
      return FALSE;
107
146
 
 
147
   // don't do anything if autoreport is enabled
 
148
   if (g_file_test(CRASHREPORT_AUTOREPORT, G_FILE_TEST_EXISTS))
 
149
      return FALSE;
 
150
   
 
151
   // if whoopsie is installed, but disabled, don't do anything
 
152
   if (g_file_test(CRASHREPORT_WHOOPSIE_EXEC, G_FILE_TEST_IS_EXECUTABLE)) {
 
153
      int exitcode;
 
154
      gchar *argv[] = { "/bin/systemctl", "is-enabled", "-q", CRASHREPORT_WHOOPSIE_SERVICE, NULL };
 
155
      if (g_spawn_sync(NULL, argv, NULL, G_SPAWN_STDOUT_TO_DEV_NULL|G_SPAWN_STDERR_TO_DEV_NULL,
 
156
                      NULL, NULL, NULL, NULL, &exitcode, NULL)) {
 
157
         if (exitcode != 0) {
 
158
            g_debug("whoopsie disabled, not displaying crashes");
 
159
            return FALSE;
 
160
         }
 
161
      }
 
162
   }
 
163
 
108
164
   // Check whether the user doesn't want notifications
109
 
   if (!gconf_client_get_bool ((GConfClient*) ta->user_data,
110
 
       GCONF_KEY_APPORT_NOTIFICATIONS, NULL)) {
111
 
       g_debug("apport notifications disabled in gconf, not displaying crashes");
112
 
       return FALSE;
 
165
   if (!g_settings_get_boolean (ta->un->settings,
 
166
                                SETTINGS_KEY_APPORT_NOTIFICATIONS)) {
 
167
      g_debug("apport notifications disabled, not displaying crashes");
 
168
      return FALSE;
113
169
   }
114
170
 
115
171
   // check for (new) reports by calling CRASHREPORT_HELPER
116
172
   // and checking the return code
117
173
   int exitcode;
118
 
   if(!g_spawn_command_line_sync(CRASHREPORT_HELPER, NULL, NULL, 
119
 
                                 &exitcode, NULL)) {
120
 
      g_warning("Can not run %s\n", CRASHREPORT_HELPER);
 
174
   gchar *argv[] = { CRASHREPORT_HELPER, NULL };
 
175
   if(!g_spawn_sync(NULL,
 
176
                    argv,
 
177
                    NULL,
 
178
                    G_SPAWN_STDOUT_TO_DEV_NULL|G_SPAWN_STDERR_TO_DEV_NULL,
 
179
                    NULL,
 
180
                    NULL,
 
181
                    NULL,
 
182
                    NULL,
 
183
                    &exitcode,
 
184
                    NULL)) {
 
185
      g_warning("Can not run %s", CRASHREPORT_HELPER);
121
186
      return FALSE;
122
187
   }
123
 
   // exitcode == 0: repots found, else no reports
 
188
   // exitcode == 0: reports found, else no reports
124
189
   system_crashes = check_system_crashes();
125
190
   crashreports_found = !exitcode || system_crashes;
126
191
 
127
 
   // crashreport found and first run: show notification bubble and
128
 
   // return
129
 
   gboolean visible = gtk_status_icon_get_visible(ta->tray_icon);
130
 
 
131
 
   //   g_print("reports: %i, visible: %i\n",crashreports_found,visible);
132
 
 
133
 
   if((crashreports_found > 0) && (system_crashes || first_run)) {
134
 
      gtk_status_icon_set_tooltip(ta->tray_icon,
135
 
                                  _("Crash report detected"));
136
 
      gtk_status_icon_set_visible(ta->tray_icon, TRUE);
 
192
   if (crashreports_found > 0) {
 
193
      g_debug("crashreport found running apport now");
 
194
      crashreports_found=0;
 
195
      run_apport(ta);
 
196
      return TRUE;
 
197
   } else
 
198
      return FALSE;
 
199
 
 
200
   // non-autolaunch will always use the notification area
 
201
   gboolean visible = tray_applet_ui_get_visible(ta);
 
202
 
 
203
   // crashreport found
 
204
   if(crashreports_found > 0 && !visible) {
 
205
      tray_applet_ui_ensure(ta);
 
206
      tray_applet_ui_set_single_action(ta, _("Crash report detected"),
 
207
                                       G_CALLBACK(button_release_cb), ta);
 
208
      tray_applet_ui_set_visible(ta, TRUE);
137
209
      /* Show the notification, after a delay so it doesn't look ugly
138
210
       * if we've just logged in */
139
 
      g_timeout_add(5000, (GSourceFunc)(show_notification), ta);
140
 
   }
141
 
   // crashreport found and already visible
142
 
   else if((crashreports_found > 0) && !(system_crashes || first_run)) {
143
 
      run_apport(ta);
144
 
      // if apport was run, we don't care anymore and hide the icon
145
 
      crashreports_found=0;
 
211
      g_timeout_add_seconds(5, (GSourceFunc)(show_notification), ta);
146
212
   }
147
213
 
148
214
   // no crashreports, but visible
150
216
      hide_crash_applet(ta);
151
217
   }
152
218
 
153
 
   first_run = FALSE;
154
219
   return TRUE;
155
220
}
156
221
 
157
222
static gboolean
158
 
button_release_cb (GtkWidget *widget,
159
 
                   TrayApplet *ta)
 
223
crashreport_check_initially(TrayApplet *ta)
160
224
{
161
 
run_apport(ta);
162
 
hide_crash_applet(ta);
163
 
        return TRUE;
 
225
   crashreport_check(ta);
 
226
   // stop timeout handler
 
227
   return FALSE;
164
228
}
165
229
 
166
 
 
167
230
void
168
231
crashreport_tray_icon_init (TrayApplet *ta)
169
232
{
170
 
 
171
 
        ta->user_data = gconf_client_get_default();
172
 
        g_signal_connect (G_OBJECT(ta->tray_icon),
173
 
                          "activate",
174
 
                          G_CALLBACK (button_release_cb),
175
 
                          ta);
176
 
 
177
233
        /* Check for crashes for the first time */
178
 
        crashreport_check (ta);
 
234
        g_timeout_add_seconds(1, (GSourceFunc)crashreport_check_initially, ta);
179
235
}