Line | Branch | Exec | Source |
---|---|---|---|
1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- | ||
2 | * | ||
3 | * Copyright (C) 2010-2012 Richard Hughes <richard@hughsie.com> | ||
4 | * Copyright (C) 2012 Thomas Bechtold <thomasbechtold@jpberlin.de> | ||
5 | * Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org> | ||
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 of the License, or | ||
10 | * (at your option) 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, see <http://www.gnu.org/licenses/>. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <config.h> | ||
23 | #include <stdlib.h> | ||
24 | |||
25 | #include "shell/cc-object-storage.h" | ||
26 | |||
27 | #include "cc-network-panel.h" | ||
28 | #include "cc-network-resources.h" | ||
29 | |||
30 | #include <NetworkManager.h> | ||
31 | |||
32 | #include "cc-list-row.h" | ||
33 | #include "cc-net-proxy-page.h" | ||
34 | #include "net-device-bluetooth.h" | ||
35 | #include "net-device-ethernet.h" | ||
36 | #include "net-device-mobile.h" | ||
37 | #include "net-device-wifi.h" | ||
38 | #include "net-vpn.h" | ||
39 | |||
40 | #include "panel-common.h" | ||
41 | |||
42 | #include "network-dialogs.h" | ||
43 | #include "connection-editor/net-connection-editor.h" | ||
44 | |||
45 | #include <libmm-glib.h> | ||
46 | |||
47 | typedef enum { | ||
48 | OPERATION_NULL, | ||
49 | OPERATION_SHOW_DEVICE, | ||
50 | OPERATION_CONNECT_MOBILE | ||
51 | } CmdlineOperation; | ||
52 | |||
53 | struct _CcNetworkPanel | ||
54 | { | ||
55 | CcPanel parent; | ||
56 | |||
57 | GPtrArray *bluetooth_devices; | ||
58 | GPtrArray *ethernet_devices; | ||
59 | GPtrArray *mobile_devices; | ||
60 | GPtrArray *vpns; | ||
61 | GHashTable *nm_device_to_device; | ||
62 | |||
63 | NMClient *client; | ||
64 | MMManager *modem_manager; | ||
65 | gboolean updating_device; | ||
66 | |||
67 | /* widgets */ | ||
68 | AdwViewStack *stack; | ||
69 | GtkWidget *box_bluetooth; | ||
70 | GtkWidget *box_vpn; | ||
71 | GtkWidget *box_wired; | ||
72 | GtkWidget *container_bluetooth; | ||
73 | GtkWidget *proxy_row; | ||
74 | GtkWidget *save_button; | ||
75 | |||
76 | /* wireless dialog stuff */ | ||
77 | CmdlineOperation arg_operation; | ||
78 | gchar *arg_device; | ||
79 | gchar *arg_access_point; | ||
80 | gboolean operation_done; | ||
81 | }; | ||
82 | |||
83 | enum { | ||
84 | PROP_0, | ||
85 | PROP_PARAMETERS | ||
86 | }; | ||
87 | |||
88 | static void handle_argv (CcNetworkPanel *self); | ||
89 | static void device_managed_cb (CcNetworkPanel *self, GParamSpec *pspec, NMDevice *device); | ||
90 | |||
91 |
6/7✓ Branch 0 taken 1 times.
✓ Branch 1 taken 43 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 43 times.
|
92 | CC_PANEL_REGISTER (CcNetworkPanel, cc_network_panel) |
92 | |||
93 | static void | ||
94 | ✗ | cc_network_panel_get_property (GObject *object, | |
95 | guint property_id, | ||
96 | GValue *value, | ||
97 | GParamSpec *pspec) | ||
98 | { | ||
99 | switch (property_id) { | ||
100 | default: | ||
101 | ✗ | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); | |
102 | } | ||
103 | ✗ | } | |
104 | |||
105 | static CmdlineOperation | ||
106 | ✗ | cmdline_operation_from_string (const gchar *string) | |
107 | { | ||
108 | ✗ | if (g_strcmp0 (string, "connect-3g") == 0) | |
109 | ✗ | return OPERATION_CONNECT_MOBILE; | |
110 | ✗ | if (g_strcmp0 (string, "show-device") == 0) | |
111 | ✗ | return OPERATION_SHOW_DEVICE; | |
112 | |||
113 | ✗ | g_warning ("Invalid additional argument %s", string); | |
114 | ✗ | return OPERATION_NULL; | |
115 | } | ||
116 | |||
117 | static void | ||
118 | 11 | reset_command_line_args (CcNetworkPanel *self) | |
119 | { | ||
120 | 11 | self->arg_operation = OPERATION_NULL; | |
121 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | g_clear_pointer (&self->arg_device, g_free); |
122 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | g_clear_pointer (&self->arg_access_point, g_free); |
123 | 11 | } | |
124 | |||
125 | static gboolean | ||
126 | ✗ | verify_argv (CcNetworkPanel *self, | |
127 | const char **args) | ||
128 | { | ||
129 | ✗ | switch (self->arg_operation) { | |
130 | ✗ | case OPERATION_CONNECT_MOBILE: | |
131 | case OPERATION_SHOW_DEVICE: | ||
132 | ✗ | if (self->arg_device == NULL) { | |
133 | ✗ | g_warning ("Operation %s requires an object path", args[0]); | |
134 | ✗ | return FALSE; | |
135 | } | ||
136 | default: | ||
137 | ✗ | return TRUE; | |
138 | } | ||
139 | } | ||
140 | |||
141 | static GPtrArray * | ||
142 | ✗ | variant_av_to_string_array (GVariant *array) | |
143 | { | ||
144 | GVariantIter iter; | ||
145 | GVariant *v; | ||
146 | GPtrArray *strv; | ||
147 | gsize count; | ||
148 | ✗ | count = g_variant_iter_init (&iter, array); | |
149 | ✗ | strv = g_ptr_array_sized_new (count + 1); | |
150 | ✗ | while (g_variant_iter_next (&iter, "v", &v)) { | |
151 | ✗ | g_ptr_array_add (strv, (gpointer)g_variant_get_string (v, NULL)); | |
152 | ✗ | g_variant_unref (v); | |
153 | } | ||
154 | ✗ | g_ptr_array_add (strv, NULL); /* NULL-terminate the strv data array */ | |
155 | ✗ | return strv; | |
156 | } | ||
157 | |||
158 | static void | ||
159 | ✗ | cc_network_panel_set_property (GObject *object, | |
160 | guint property_id, | ||
161 | const GValue *value, | ||
162 | GParamSpec *pspec) | ||
163 | { | ||
164 | ✗ | CcNetworkPanel *self = CC_NETWORK_PANEL (object); | |
165 | |||
166 | ✗ | switch (property_id) { | |
167 | ✗ | case PROP_PARAMETERS: { | |
168 | GVariant *parameters; | ||
169 | |||
170 | ✗ | reset_command_line_args (self); | |
171 | |||
172 | ✗ | parameters = g_value_get_variant (value); | |
173 | ✗ | if (parameters) { | |
174 | ✗ | g_autoptr(GPtrArray) array = NULL; | |
175 | const gchar **args; | ||
176 | ✗ | array = variant_av_to_string_array (parameters); | |
177 | ✗ | args = (const gchar **) array->pdata; | |
178 | |||
179 | ✗ | g_debug ("Invoked with operation %s", args[0]); | |
180 | |||
181 | ✗ | if (args[0]) | |
182 | ✗ | self->arg_operation = cmdline_operation_from_string (args[0]); | |
183 | ✗ | if (args[0] && args[1]) | |
184 | ✗ | self->arg_device = g_strdup (args[1]); | |
185 | ✗ | if (args[0] && args[1] && args[2]) | |
186 | ✗ | self->arg_access_point = g_strdup (args[2]); | |
187 | |||
188 | ✗ | if (verify_argv (self, (const char **) args) == FALSE) { | |
189 | ✗ | reset_command_line_args (self); | |
190 | ✗ | return; | |
191 | } | ||
192 | ✗ | g_debug ("Calling handle_argv() after setting property"); | |
193 | ✗ | handle_argv (self); | |
194 | } | ||
195 | ✗ | break; | |
196 | } | ||
197 | ✗ | default: | |
198 | ✗ | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); | |
199 | } | ||
200 | } | ||
201 | |||
202 | static void | ||
203 | 11 | cc_network_panel_dispose (GObject *object) | |
204 | { | ||
205 | 11 | CcNetworkPanel *self = CC_NETWORK_PANEL (object); | |
206 | |||
207 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | g_clear_object (&self->client); |
208 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | g_clear_object (&self->modem_manager); |
209 | |||
210 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | g_clear_pointer (&self->bluetooth_devices, g_ptr_array_unref); |
211 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | g_clear_pointer (&self->ethernet_devices, g_ptr_array_unref); |
212 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | g_clear_pointer (&self->mobile_devices, g_ptr_array_unref); |
213 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | g_clear_pointer (&self->vpns, g_ptr_array_unref); |
214 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | g_clear_pointer (&self->nm_device_to_device, g_hash_table_destroy); |
215 | |||
216 | 11 | G_OBJECT_CLASS (cc_network_panel_parent_class)->dispose (object); | |
217 | 11 | } | |
218 | |||
219 | static void | ||
220 | 11 | cc_network_panel_finalize (GObject *object) | |
221 | { | ||
222 | 11 | CcNetworkPanel *self = CC_NETWORK_PANEL (object); | |
223 | |||
224 | 11 | reset_command_line_args (self); | |
225 | |||
226 | 11 | G_OBJECT_CLASS (cc_network_panel_parent_class)->finalize (object); | |
227 | 11 | } | |
228 | |||
229 | static const char * | ||
230 | ✗ | cc_network_panel_get_help_uri (CcPanel *panel) | |
231 | { | ||
232 | ✗ | return "help:gnome-help/net"; | |
233 | } | ||
234 | |||
235 | static void | ||
236 | 29 | panel_refresh_device_titles (CcNetworkPanel *self) | |
237 | { | ||
238 |
2/2✓ Branch 1 taken 18 times.
✓ Branch 2 taken 11 times.
|
29 | g_autoptr(GPtrArray) ndarray = NULL; |
239 |
2/2✓ Branch 1 taken 18 times.
✓ Branch 2 taken 11 times.
|
29 | g_autoptr(GPtrArray) nmdarray = NULL; |
240 | GtkWidget **devices; | ||
241 | NMDevice **nm_devices; | ||
242 |
2/2✓ Branch 1 taken 18 times.
✓ Branch 2 taken 11 times.
|
29 | g_auto(GStrv) titles = NULL; |
243 | guint i, num_devices; | ||
244 | |||
245 | 29 | ndarray = g_ptr_array_new (); | |
246 | 29 | nmdarray = g_ptr_array_new (); | |
247 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
|
29 | for (i = 0; i < self->bluetooth_devices->len; i++) { |
248 | ✗ | NetDeviceBluetooth *device = g_ptr_array_index (self->bluetooth_devices, i); | |
249 | ✗ | g_ptr_array_add (ndarray, device); | |
250 | ✗ | g_ptr_array_add (nmdarray, net_device_bluetooth_get_device (device)); | |
251 | } | ||
252 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 29 times.
|
53 | for (i = 0; i < self->ethernet_devices->len; i++) { |
253 | 24 | NetDeviceEthernet *device = g_ptr_array_index (self->ethernet_devices, i); | |
254 | 24 | g_ptr_array_add (ndarray, device); | |
255 | 24 | g_ptr_array_add (nmdarray, net_device_ethernet_get_device (device)); | |
256 | } | ||
257 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
|
29 | for (i = 0; i < self->mobile_devices->len; i++) { |
258 | ✗ | NetDeviceMobile *device = g_ptr_array_index (self->mobile_devices, i); | |
259 | ✗ | g_ptr_array_add (ndarray, device); | |
260 | ✗ | g_ptr_array_add (nmdarray, net_device_mobile_get_device (device)); | |
261 | } | ||
262 | |||
263 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 18 times.
|
29 | if (ndarray->len == 0) |
264 | 11 | return; | |
265 | |||
266 | 18 | devices = (GtkWidget **)ndarray->pdata; | |
267 | 18 | nm_devices = (NMDevice **)nmdarray->pdata; | |
268 | 18 | num_devices = ndarray->len; | |
269 | |||
270 | 18 | titles = nm_device_disambiguate_names (nm_devices, num_devices); | |
271 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 18 times.
|
42 | for (i = 0; i < num_devices; i++) { |
272 |
4/8✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 24 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 24 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 24 times.
|
24 | if (NM_IS_DEVICE_BT (nm_devices[i])) |
273 | ✗ | adw_preferences_row_set_title (ADW_PREFERENCES_ROW (devices[i]), nm_device_bt_get_name (NM_DEVICE_BT (nm_devices[i]))); | |
274 |
1/2✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
|
24 | else if (NET_IS_DEVICE_ETHERNET (devices[i])) |
275 | 24 | adw_preferences_group_set_title (ADW_PREFERENCES_GROUP (devices[i]), titles[i]); | |
276 | ✗ | else if (NET_IS_DEVICE_MOBILE (devices[i])) | |
277 | ✗ | net_device_mobile_set_title (NET_DEVICE_MOBILE (devices[i]), titles[i]); | |
278 | } | ||
279 | } | ||
280 | |||
281 | static gboolean | ||
282 | ✗ | handle_argv_for_device (CcNetworkPanel *self, | |
283 | NMDevice *device) | ||
284 | { | ||
285 | ✗ | GtkWidget *toplevel = cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (self))); | |
286 | |||
287 | ✗ | if (self->arg_operation == OPERATION_NULL) | |
288 | ✗ | return TRUE; | |
289 | |||
290 | ✗ | if (g_strcmp0 (nm_object_get_path (NM_OBJECT (device)), self->arg_device) == 0) { | |
291 | ✗ | if (self->arg_operation == OPERATION_CONNECT_MOBILE) { | |
292 | ✗ | cc_network_panel_connect_to_3g_network (toplevel, self->client, device); | |
293 | |||
294 | ✗ | reset_command_line_args (self); /* done */ | |
295 | ✗ | return TRUE; | |
296 | ✗ | } else if (self->arg_operation == OPERATION_SHOW_DEVICE) { | |
297 | ✗ | reset_command_line_args (self); /* done */ | |
298 | ✗ | return TRUE; | |
299 | } | ||
300 | } | ||
301 | |||
302 | ✗ | return FALSE; | |
303 | } | ||
304 | |||
305 | static gboolean | ||
306 | ✗ | handle_argv_for_connection (CcNetworkPanel *self, | |
307 | NMConnection *connection) | ||
308 | { | ||
309 | ✗ | if (self->arg_operation == OPERATION_NULL) | |
310 | ✗ | return TRUE; | |
311 | ✗ | if (self->arg_operation != OPERATION_SHOW_DEVICE) | |
312 | ✗ | return FALSE; | |
313 | |||
314 | ✗ | if (g_strcmp0 (nm_connection_get_path (connection), self->arg_device) == 0) { | |
315 | ✗ | reset_command_line_args (self); | |
316 | ✗ | return TRUE; | |
317 | } | ||
318 | |||
319 | ✗ | return FALSE; | |
320 | } | ||
321 | |||
322 | |||
323 | static void | ||
324 | 22 | handle_argv (CcNetworkPanel *self) | |
325 | { | ||
326 | gint i; | ||
327 | |||
328 |
1/2✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
|
22 | if (self->arg_operation == OPERATION_NULL) |
329 | 22 | return; | |
330 | |||
331 | ✗ | for (i = 0; i < self->bluetooth_devices->len; i++) { | |
332 | ✗ | NetDeviceBluetooth *device = g_ptr_array_index (self->bluetooth_devices, i); | |
333 | ✗ | if (handle_argv_for_device (self, net_device_bluetooth_get_device (device))) | |
334 | ✗ | return; | |
335 | } | ||
336 | ✗ | for (i = 0; i < self->ethernet_devices->len; i++) { | |
337 | ✗ | NetDeviceEthernet *device = g_ptr_array_index (self->ethernet_devices, i); | |
338 | ✗ | if (handle_argv_for_device (self, net_device_ethernet_get_device (device))) | |
339 | ✗ | return; | |
340 | } | ||
341 | ✗ | for (i = 0; i < self->mobile_devices->len; i++) { | |
342 | ✗ | NetDeviceMobile *device = g_ptr_array_index (self->mobile_devices, i); | |
343 | ✗ | if (handle_argv_for_device (self, net_device_mobile_get_device (device))) | |
344 | ✗ | return; | |
345 | } | ||
346 | ✗ | for (i = 0; i < self->vpns->len; i++) { | |
347 | ✗ | NetVpn *vpn = g_ptr_array_index (self->vpns, i); | |
348 | ✗ | if (handle_argv_for_connection (self, net_vpn_get_connection (vpn))) | |
349 | ✗ | return; | |
350 | } | ||
351 | |||
352 | ✗ | g_debug ("Could not handle argv operation, no matching device yet?"); | |
353 | } | ||
354 | |||
355 | static void | ||
356 | 5 | update_bluetooth_section (CcNetworkPanel *self) | |
357 | { | ||
358 | 5 | gtk_widget_set_visible (self->container_bluetooth, self->bluetooth_devices->len > 0); | |
359 | 5 | } | |
360 | |||
361 | static gboolean | ||
362 | ✗ | wwan_panel_supports_modem (GDBusObject *object) | |
363 | { | ||
364 | MMObject *mm_object; | ||
365 | MMModem *modem; | ||
366 | MMModemCapability capability, supported_capabilities; | ||
367 | |||
368 | ✗ | g_assert (G_IS_DBUS_OBJECT (object)); | |
369 | |||
370 | ✗ | supported_capabilities = MM_MODEM_CAPABILITY_GSM_UMTS | MM_MODEM_CAPABILITY_LTE; | |
371 | #if MM_CHECK_VERSION (1,14,0) | ||
372 | ✗ | supported_capabilities |= MM_MODEM_CAPABILITY_5GNR; | |
373 | #endif | ||
374 | |||
375 | ✗ | mm_object = MM_OBJECT (object); | |
376 | ✗ | modem = mm_object_get_modem (mm_object); | |
377 | ✗ | capability = mm_modem_get_current_capabilities (modem); | |
378 | |||
379 | ✗ | return capability & supported_capabilities; | |
380 | } | ||
381 | |||
382 | static void | ||
383 | 13 | panel_add_device (CcNetworkPanel *self, NMDevice *device) | |
384 | { | ||
385 | NMDeviceType type; | ||
386 | NetDeviceEthernet *device_ethernet; | ||
387 | NetDeviceMobile *device_mobile; | ||
388 | NetDeviceBluetooth *device_bluetooth; | ||
389 |
1/2✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
|
13 | g_autoptr(GDBusObject) modem_object = NULL; |
390 | |||
391 | /* does already exist */ | ||
392 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
|
13 | if (g_hash_table_lookup (self->nm_device_to_device, device) != NULL) |
393 | ✗ | return; | |
394 | |||
395 | 13 | type = nm_device_get_device_type (device); | |
396 | |||
397 | 13 | g_debug ("device %s type %i path %s", | |
398 | nm_device_get_udi (device), type, nm_object_get_path (NM_OBJECT (device))); | ||
399 | |||
400 | /* map the NMDeviceType to the GType, or ignore */ | ||
401 |
1/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
13 | switch (type) { |
402 | 13 | case NM_DEVICE_TYPE_ETHERNET: | |
403 | case NM_DEVICE_TYPE_INFINIBAND: | ||
404 | 13 | device_ethernet = net_device_ethernet_new (self->client, device); | |
405 | 13 | gtk_box_append (GTK_BOX (self->box_wired), GTK_WIDGET (device_ethernet)); | |
406 | 13 | g_ptr_array_add (self->ethernet_devices, device_ethernet); | |
407 | 13 | g_hash_table_insert (self->nm_device_to_device, device, device_ethernet); | |
408 | 13 | break; | |
409 | ✗ | case NM_DEVICE_TYPE_MODEM: | |
410 | ✗ | if (g_str_has_prefix (nm_device_get_udi (device), "/org/freedesktop/ModemManager1/Modem/")) { | |
411 | ✗ | if (self->modem_manager == NULL) { | |
412 | ✗ | g_warning ("Cannot grab information for modem at %s: No ModemManager support", | |
413 | nm_device_get_udi (device)); | ||
414 | ✗ | return; | |
415 | } | ||
416 | |||
417 | ✗ | modem_object = g_dbus_object_manager_get_object (G_DBUS_OBJECT_MANAGER (self->modem_manager), | |
418 | ✗ | nm_device_get_udi (device)); | |
419 | ✗ | if (modem_object == NULL) { | |
420 | ✗ | g_warning ("Cannot grab information for modem at %s: Not found", | |
421 | nm_device_get_udi (device)); | ||
422 | ✗ | return; | |
423 | } | ||
424 | |||
425 | /* This will be handled by cellular panel */ | ||
426 | ✗ | if (wwan_panel_supports_modem (modem_object)) | |
427 | ✗ | return; | |
428 | } | ||
429 | |||
430 | ✗ | device_mobile = net_device_mobile_new (self->client, device, modem_object); | |
431 | ✗ | gtk_box_append (GTK_BOX (self->box_wired), GTK_WIDGET (device_mobile)); | |
432 | ✗ | g_ptr_array_add (self->mobile_devices, device_mobile); | |
433 | ✗ | g_hash_table_insert (self->nm_device_to_device, device, device_mobile); | |
434 | ✗ | break; | |
435 | ✗ | case NM_DEVICE_TYPE_BT: | |
436 | ✗ | device_bluetooth = net_device_bluetooth_new (self->client, device); | |
437 | ✗ | gtk_list_box_append (GTK_LIST_BOX (self->box_bluetooth), GTK_WIDGET (device_bluetooth)); | |
438 | ✗ | g_ptr_array_add (self->bluetooth_devices, device_bluetooth); | |
439 | ✗ | g_hash_table_insert (self->nm_device_to_device, device, device_bluetooth); | |
440 | |||
441 | /* Update the device_bluetooth section if we're adding a bluetooth | ||
442 | * device. This is a temporary solution though, for these will | ||
443 | * be handled by the future Mobile Broadband panel */ | ||
444 | ✗ | update_bluetooth_section (self); | |
445 | ✗ | break; | |
446 | |||
447 | /* For Wi-Fi and VPN we handle connections separately; we correctly manage | ||
448 | * them, but not here. | ||
449 | */ | ||
450 | ✗ | case NM_DEVICE_TYPE_WIFI: | |
451 | case NM_DEVICE_TYPE_TUN: | ||
452 | /* And the rest we simply cannot deal with currently. */ | ||
453 | default: | ||
454 | ✗ | return; | |
455 | } | ||
456 | } | ||
457 | |||
458 | static void | ||
459 | 5 | panel_remove_device (CcNetworkPanel *self, NMDevice *device) | |
460 | { | ||
461 | GtkWidget *net_device; | ||
462 | |||
463 | 5 | net_device = g_hash_table_lookup (self->nm_device_to_device, device); | |
464 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (net_device == NULL) |
465 | ✗ | return; | |
466 | |||
467 | 5 | g_ptr_array_remove (self->bluetooth_devices, net_device); | |
468 | 5 | g_ptr_array_remove (self->ethernet_devices, net_device); | |
469 | 5 | g_ptr_array_remove (self->mobile_devices, net_device); | |
470 | 5 | g_hash_table_remove (self->nm_device_to_device, device); | |
471 | |||
472 | 5 | gtk_box_remove (GTK_BOX (gtk_widget_get_parent (net_device)), net_device); | |
473 | |||
474 | /* update device_bluetooth widgets */ | ||
475 | 5 | update_bluetooth_section (self); | |
476 | } | ||
477 | |||
478 | static void | ||
479 | ✗ | connection_state_changed (CcNetworkPanel *self) | |
480 | { | ||
481 | ✗ | } | |
482 | |||
483 | static void | ||
484 | 2 | active_connections_changed (CcNetworkPanel *self) | |
485 | { | ||
486 | const GPtrArray *connections; | ||
487 | int i, j; | ||
488 | |||
489 | 2 | g_debug ("Active connections changed:"); | |
490 | 2 | connections = nm_client_get_active_connections (self->client); | |
491 |
3/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
|
4 | for (i = 0; connections && (i < connections->len); i++) { |
492 | NMActiveConnection *connection; | ||
493 | const GPtrArray *devices; | ||
494 | |||
495 | 2 | connection = g_ptr_array_index (connections, i); | |
496 | 2 | g_debug (" %s", nm_object_get_path (NM_OBJECT (connection))); | |
497 | 2 | devices = nm_active_connection_get_devices (connection); | |
498 |
3/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
|
4 | for (j = 0; devices && j < devices->len; j++) |
499 | 2 | g_debug (" %s", nm_device_get_udi (g_ptr_array_index (devices, j))); | |
500 | |||
501 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if (nm_is_wireguard_connection (connection)) |
502 | ✗ | g_debug (" WireGuard connection: %s", nm_active_connection_get_id(connection)); | |
503 | |||
504 |
4/8✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
|
2 | if (NM_IS_VPN_CONNECTION (connection)) |
505 | ✗ | g_debug (" VPN base connection: %s", nm_active_connection_get_specific_object_path (connection)); | |
506 | |||
507 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | if (g_object_get_data (G_OBJECT (connection), "has-state-changed-handler") == NULL) { |
508 | 2 | g_signal_connect_object (connection, "notify::state", | |
509 | G_CALLBACK (connection_state_changed), self, G_CONNECT_SWAPPED); | ||
510 | 2 | g_object_set_data (G_OBJECT (connection), "has-state-changed-handler", GINT_TO_POINTER (TRUE)); | |
511 | } | ||
512 | } | ||
513 | 2 | } | |
514 | |||
515 | static void | ||
516 | 13 | device_managed_cb (CcNetworkPanel *self, GParamSpec *pspec, NMDevice *device) | |
517 | { | ||
518 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
|
13 | if (!nm_device_get_managed (device)) |
519 | ✗ | return; | |
520 | |||
521 | 13 | panel_add_device (self, device); | |
522 | 13 | panel_refresh_device_titles (self); | |
523 | } | ||
524 | |||
525 | static void | ||
526 | 13 | device_added_cb (CcNetworkPanel *self, NMDevice *device) | |
527 | { | ||
528 | 13 | g_debug ("New device added"); | |
529 | |||
530 |
1/2✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
|
13 | if (nm_device_get_managed (device)) |
531 | 13 | device_managed_cb (self, NULL, device); | |
532 | else | ||
533 | ✗ | g_signal_connect_object (device, "notify::managed", G_CALLBACK (device_managed_cb), self, G_CONNECT_SWAPPED); | |
534 | 13 | } | |
535 | |||
536 | static void | ||
537 | 5 | device_removed_cb (CcNetworkPanel *self, NMDevice *device) | |
538 | { | ||
539 | 5 | g_debug ("Device removed"); | |
540 | 5 | panel_remove_device (self, device); | |
541 | 5 | panel_refresh_device_titles (self); | |
542 | |||
543 | 5 | g_signal_handlers_disconnect_by_func (device, | |
544 | G_CALLBACK (device_managed_cb), | ||
545 | self); | ||
546 | 5 | } | |
547 | |||
548 | static void | ||
549 | 11 | manager_running (CcNetworkPanel *self) | |
550 | { | ||
551 | const GPtrArray *devices; | ||
552 | int i; | ||
553 | |||
554 | /* clear all devices we added */ | ||
555 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
|
11 | if (!nm_client_get_nm_running (self->client)) { |
556 | ✗ | g_debug ("NM disappeared"); | |
557 | ✗ | goto out; | |
558 | } | ||
559 | |||
560 | 11 | g_debug ("coldplugging devices"); | |
561 | 11 | devices = nm_client_get_devices (self->client); | |
562 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if (devices == NULL) { |
563 | ✗ | g_debug ("No devices to add"); | |
564 | ✗ | return; | |
565 | } | ||
566 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | for (i = 0; i < devices->len; i++) { |
567 | ✗ | NMDevice *device = g_ptr_array_index (devices, i); | |
568 | ✗ | device_added_cb (self, device); | |
569 | } | ||
570 | 11 | out: | |
571 | 11 | panel_refresh_device_titles (self); | |
572 | |||
573 | 11 | g_debug ("Calling handle_argv() after cold-plugging devices"); | |
574 | 11 | handle_argv (self); | |
575 | } | ||
576 | |||
577 | static void | ||
578 | 3 | panel_add_vpn_device (CcNetworkPanel *self, NMConnection *connection) | |
579 | { | ||
580 | NetVpn *net_vpn; | ||
581 | guint i; | ||
582 | |||
583 | /* does already exist */ | ||
584 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | for (i = 0; i < self->vpns->len; i++) { |
585 | ✗ | net_vpn = g_ptr_array_index (self->vpns, i); | |
586 | ✗ | if (net_vpn_get_connection (net_vpn) == connection) | |
587 | ✗ | return; | |
588 | } | ||
589 | |||
590 | 3 | net_vpn = net_vpn_new (self->client, connection); | |
591 | 3 | gtk_list_box_append (GTK_LIST_BOX (self->box_vpn), GTK_WIDGET (net_vpn)); | |
592 | |||
593 | /* store in the devices array */ | ||
594 | 3 | g_ptr_array_add (self->vpns, net_vpn); | |
595 | } | ||
596 | |||
597 | static void | ||
598 | 7 | add_connection (CcNetworkPanel *self, NMConnection *connection) | |
599 | { | ||
600 | NMSettingConnection *s_con; | ||
601 | const gchar *type; | ||
602 | |||
603 | 7 | s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, | |
604 | NM_TYPE_SETTING_CONNECTION)); | ||
605 | 7 | type = nm_setting_connection_get_connection_type (s_con); | |
606 |
3/4✓ Branch 1 taken 4 times.
✓ Branch 2 taken 3 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
7 | if (g_strcmp0 (type, "vpn") != 0 && g_strcmp0 (type, "wireguard") != 0) |
607 | 4 | return; | |
608 | |||
609 | /* Don't add the libvirtd bridge to the UI */ | ||
610 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | if (g_strcmp0 (nm_setting_connection_get_interface_name (s_con), "virbr0") == 0) |
611 | ✗ | return; | |
612 | |||
613 | 3 | g_debug ("add %s/%s remote connection: %s", | |
614 | type, g_type_name_from_instance ((GTypeInstance*)connection), | ||
615 | nm_connection_get_path (connection)); | ||
616 | 3 | panel_add_vpn_device (self, connection); | |
617 | } | ||
618 | |||
619 | static void | ||
620 | 1 | client_connection_removed_cb (CcNetworkPanel *self, NMConnection *connection) | |
621 | { | ||
622 | guint i; | ||
623 | |||
624 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | for (i = 0; i < self->vpns->len; i++) { |
625 | 1 | NetVpn *vpn = g_ptr_array_index (self->vpns, i); | |
626 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | if (net_vpn_get_connection (vpn) == connection) { |
627 | 1 | g_ptr_array_remove (self->vpns, vpn); | |
628 | 1 | gtk_list_box_remove (GTK_LIST_BOX (self->box_vpn), GTK_WIDGET (vpn)); | |
629 | 1 | return; | |
630 | } | ||
631 | } | ||
632 | } | ||
633 | |||
634 | static void | ||
635 | 11 | panel_check_network_manager_version (CcNetworkPanel *self) | |
636 | { | ||
637 | const gchar *version; | ||
638 | |||
639 | /* parse running version */ | ||
640 | 11 | version = nm_client_get_version (self->client); | |
641 | |||
642 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if (version == NULL) { |
643 | ✗ | adw_view_stack_set_visible_child_name (ADW_VIEW_STACK (self->stack), "nm-error-page"); | |
644 | } else { | ||
645 | 11 | adw_view_stack_set_visible_child_name (ADW_VIEW_STACK (self->stack), "network-page"); | |
646 | 11 | manager_running (self); | |
647 | } | ||
648 | 11 | } | |
649 | |||
650 | static void | ||
651 | ✗ | create_connection_cb (CcNetworkPanel *self) | |
652 | { | ||
653 | NetConnectionEditor *editor; | ||
654 | |||
655 | ✗ | editor = net_connection_editor_new (NULL, NULL, NULL, self->client); | |
656 | ✗ | gtk_window_set_transient_for (GTK_WINDOW (editor), | |
657 | ✗ | GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self)))); | |
658 | ✗ | gtk_window_present (GTK_WINDOW (editor)); | |
659 | ✗ | } | |
660 | |||
661 | static void | ||
662 | 11 | cc_network_panel_map (GtkWidget *widget) | |
663 | { | ||
664 | 11 | GTK_WIDGET_CLASS (cc_network_panel_parent_class)->map (widget); | |
665 | |||
666 | /* is the user compiling against a new version, but not running | ||
667 | * the daemon? */ | ||
668 | 11 | panel_check_network_manager_version (CC_NETWORK_PANEL (widget)); | |
669 | 11 | } | |
670 | |||
671 | |||
672 | static void | ||
673 | 1 | cc_network_panel_class_init (CcNetworkPanelClass *klass) | |
674 | { | ||
675 | 1 | GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); | |
676 | 1 | GObjectClass *object_class = G_OBJECT_CLASS (klass); | |
677 | 1 | CcPanelClass *panel_class = CC_PANEL_CLASS (klass); | |
678 | |||
679 | 1 | panel_class->get_help_uri = cc_network_panel_get_help_uri; | |
680 | |||
681 | 1 | widget_class->map = cc_network_panel_map; | |
682 | |||
683 | 1 | object_class->get_property = cc_network_panel_get_property; | |
684 | 1 | object_class->set_property = cc_network_panel_set_property; | |
685 | 1 | object_class->dispose = cc_network_panel_dispose; | |
686 | 1 | object_class->finalize = cc_network_panel_finalize; | |
687 | |||
688 | 1 | g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters"); | |
689 | |||
690 | 1 | gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/cc-network-panel.ui"); | |
691 | |||
692 | 1 | gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, stack); | |
693 | 1 | gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, box_bluetooth); | |
694 | 1 | gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, box_vpn); | |
695 | 1 | gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, box_wired); | |
696 | 1 | gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, container_bluetooth); | |
697 | 1 | gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, proxy_row); | |
698 | |||
699 | 1 | gtk_widget_class_bind_template_callback (widget_class, create_connection_cb); | |
700 | |||
701 | 1 | g_type_ensure (CC_TYPE_LIST_ROW); | |
702 | 1 | g_type_ensure (CC_TYPE_NET_PROXY_PAGE); | |
703 | 1 | } | |
704 | |||
705 | static void | ||
706 | 11 | cc_network_panel_init (CcNetworkPanel *self) | |
707 | { | ||
708 | 11 | g_autoptr(GDBusConnection) system_bus = NULL; | |
709 | 11 | g_autoptr(GError) error = NULL; | |
710 | const GPtrArray *connections; | ||
711 | guint i; | ||
712 | |||
713 | 11 | g_resources_register (cc_network_get_resource ()); | |
714 | |||
715 | 11 | gtk_widget_init_template (GTK_WIDGET (self)); | |
716 | |||
717 | 11 | self->bluetooth_devices = g_ptr_array_new (); | |
718 | 11 | self->ethernet_devices = g_ptr_array_new (); | |
719 | 11 | self->mobile_devices = g_ptr_array_new (); | |
720 | 11 | self->vpns = g_ptr_array_new (); | |
721 | 11 | self->nm_device_to_device = g_hash_table_new (g_direct_hash, g_direct_equal); | |
722 | |||
723 | /* Create and store a NMClient instance if it doesn't exist yet */ | ||
724 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
|
11 | if (!cc_object_storage_has_object (CC_OBJECT_NMCLIENT)) { |
725 | ✗ | g_autoptr(NMClient) client = nm_client_new (NULL, NULL); | |
726 | ✗ | cc_object_storage_add_object (CC_OBJECT_NMCLIENT, client); | |
727 | } | ||
728 | |||
729 | /* use NetworkManager client */ | ||
730 | 11 | self->client = cc_object_storage_get_object (CC_OBJECT_NMCLIENT); | |
731 | |||
732 | 11 | g_signal_connect_object (self->client, "notify::nm-running" , | |
733 | G_CALLBACK (manager_running), self, G_CONNECT_SWAPPED); | ||
734 | 11 | g_signal_connect_object (self->client, "notify::active-connections", | |
735 | G_CALLBACK (active_connections_changed), self, G_CONNECT_SWAPPED); | ||
736 | 11 | g_signal_connect_object (self->client, "device-added", | |
737 | G_CALLBACK (device_added_cb), self, G_CONNECT_SWAPPED); | ||
738 | 11 | g_signal_connect_object (self->client, "device-removed", | |
739 | G_CALLBACK (device_removed_cb), self, G_CONNECT_SWAPPED); | ||
740 | |||
741 | /* Setup ModemManager client */ | ||
742 | 11 | system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); | |
743 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if (system_bus == NULL) { |
744 | ✗ | g_warning ("Error connecting to system D-Bus: %s", | |
745 | error->message); | ||
746 | } else { | ||
747 | 11 | self->modem_manager = mm_manager_new_sync (system_bus, | |
748 | G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, | ||
749 | NULL, | ||
750 | &error); | ||
751 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if (self->modem_manager == NULL) |
752 | ✗ | g_warning ("Error connecting to ModemManager: %s", | |
753 | error->message); | ||
754 | } | ||
755 | |||
756 | /* add remote settings such as VPN settings as virtual devices */ | ||
757 | 11 | g_signal_connect_object (self->client, NM_CLIENT_CONNECTION_ADDED, | |
758 | G_CALLBACK (add_connection), self, G_CONNECT_SWAPPED); | ||
759 | 11 | g_signal_connect_object (self->client, NM_CLIENT_CONNECTION_REMOVED, | |
760 | G_CALLBACK (client_connection_removed_cb), self, G_CONNECT_SWAPPED); | ||
761 | |||
762 | /* Cold-plug existing connections */ | ||
763 | 11 | connections = nm_client_get_connections (self->client); | |
764 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | if (connections) { |
765 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | for (i = 0; i < connections->len; i++) |
766 | ✗ | add_connection (self, connections->pdata[i]); | |
767 | } | ||
768 | |||
769 | 11 | g_debug ("Calling handle_argv() after cold-plugging connections"); | |
770 | 11 | handle_argv (self); | |
771 | 11 | } | |
772 |