1 /* nautilus-mime-actions.c - uri-specific versions of mime action functions
2 *
3 * Copyright (C) 2000, 2001 Eazel, Inc.
4 *
5 * The Gnome Library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * The Gnome Library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with the Gnome Library; see the file COPYING.LIB. If not,
17 * see <http://www.gnu.org/licenses/>.
18 *
19 * Authors: Maciej Stachowiak <mjs@eazel.com>
20 */
21
22 #include "nautilus-mime-actions.h"
23
24 #include <eel/eel-stock-dialogs.h>
25 #include <eel/eel-string.h>
26 #include <glib.h>
27 #include <glib/gi18n.h>
28 #include <glib/gstdio.h>
29 #include <string.h>
30
31 #define DEBUG_FLAG NAUTILUS_DEBUG_MIME
32 #include "nautilus-debug.h"
33
34 #include "nautilus-application.h"
35 #include "nautilus-enums.h"
36 #include "nautilus-file.h"
37 #include "nautilus-file-utilities.h"
38 #include "nautilus-file-operations.h"
39 #include "nautilus-global-preferences.h"
40 #include "nautilus-metadata.h"
41 #include "nautilus-program-choosing.h"
42 #include "nautilus-signaller.h"
43 #include "nautilus-ui-utilities.h"
44 #include "nautilus-window.h"
45 #include "nautilus-window-slot.h"
46
47 typedef enum
48 {
49 ACTIVATION_ACTION_LAUNCH,
50 ACTIVATION_ACTION_LAUNCH_IN_TERMINAL,
51 ACTIVATION_ACTION_OPEN_IN_VIEW,
52 ACTIVATION_ACTION_OPEN_IN_APPLICATION,
53 ACTIVATION_ACTION_EXTRACT,
54 ACTIVATION_ACTION_DO_NOTHING,
55 } ActivationAction;
56
57 typedef struct
58 {
59 NautilusFile *file;
60 char *uri;
61 } LaunchLocation;
62
63 typedef struct
64 {
65 GAppInfo *application;
66 GList *uris;
67 } ApplicationLaunchParameters;
68
69 typedef struct
70 {
71 NautilusWindowSlot *slot;
72 gpointer window;
73 GtkWindow *parent_window;
74 GCancellable *cancellable;
75 GList *locations;
76 GList *mountables;
77 GList *start_mountables;
78 GList *not_mounted;
79 NautilusWindowOpenFlags flags;
80 char *timed_wait_prompt;
81 gboolean timed_wait_active;
82 NautilusFileListHandle *files_handle;
83 gboolean tried_mounting;
84 char *activation_directory;
85 gboolean user_confirmation;
86 } ActivateParameters;
87
88 typedef struct
89 {
90 ActivateParameters *activation_params;
91 GQueue *uris;
92 } ApplicationLaunchAsyncParameters;
93
94 /* Microsoft mime types at https://blogs.msdn.microsoft.com/vsofficedeveloper/2008/05/08/office-2007-file-format-mime-types-for-http-content-streaming-2/ */
95 struct
96 {
97 char *name;
98 char *mimetypes[20];
99 } mimetype_groups[] =
100 {
101 {
102 N_("Anything"),
103 { NULL }
104 },
105 {
106 N_("Files"),
107 { "application/octet-stream",
108 "text/plain",
109 NULL}
110 },
111 {
112 N_("Folders"),
113 { "inode/directory",
114 NULL}
115 },
116 { N_("Documents"),
117 { "application/rtf",
118 "application/msword",
119 "application/vnd.sun.xml.writer",
120 "application/vnd.sun.xml.writer.global",
121 "application/vnd.sun.xml.writer.template",
122 "application/vnd.oasis.opendocument.text",
123 "application/vnd.oasis.opendocument.text-template",
124 "application/x-abiword",
125 "application/x-applix-word",
126 "application/x-mswrite",
127 "application/docbook+xml",
128 "application/x-kword",
129 "application/x-kword-crypt",
130 "application/x-lyx",
131 "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
132 NULL}},
133 { N_("Illustration"),
134 { "application/illustrator",
135 "application/vnd.corel-draw",
136 "application/vnd.stardivision.draw",
137 "application/vnd.oasis.opendocument.graphics",
138 "application/x-dia-diagram",
139 "application/x-karbon",
140 "application/x-killustrator",
141 "application/x-kivio",
142 "application/x-kontour",
143 "application/x-wpg",
144 NULL}},
145 { N_("Music"),
146 { "application/ogg",
147 "audio/x-vorbis+ogg",
148 "audio/ac3",
149 "audio/basic",
150 "audio/midi",
151 "audio/x-flac",
152 "audio/mp4",
153 "audio/mpeg",
154 "audio/x-mpeg",
155 "audio/x-ms-asx",
156 "audio/x-pn-realaudio",
157 NULL}},
158 { N_("PDF / PostScript"),
159 { "application/pdf",
160 "application/postscript",
161 "application/x-dvi",
162 "image/x-eps",
163 "image/vnd.djvu+multipage",
164 NULL}},
165 { N_("Picture"),
166 { "application/vnd.oasis.opendocument.image",
167 "application/x-krita",
168 "image/bmp",
169 "image/cgm",
170 "image/gif",
171 "image/jpeg",
172 "image/jpeg2000",
173 "image/png",
174 "image/svg+xml",
175 "image/tiff",
176 "image/x-compressed-xcf",
177 "image/x-pcx",
178 "image/x-photo-cd",
179 "image/x-psd",
180 "image/x-tga",
181 "image/x-xcf",
182 NULL}},
183 { N_("Presentation"),
184 { "application/vnd.ms-powerpoint",
185 "application/vnd.sun.xml.impress",
186 "application/vnd.oasis.opendocument.presentation",
187 "application/x-magicpoint",
188 "application/x-kpresenter",
189 "application/vnd.openxmlformats-officedocument.presentationml.presentation",
190 NULL}},
191 { N_("Spreadsheet"),
192 { "application/vnd.lotus-1-2-3",
193 "application/vnd.ms-excel",
194 "application/vnd.stardivision.calc",
195 "application/vnd.sun.xml.calc",
196 "application/vnd.oasis.opendocument.spreadsheet",
197 "application/x-applix-spreadsheet",
198 "application/x-gnumeric",
199 "application/x-kspread",
200 "application/x-kspread-crypt",
201 "application/x-quattropro",
202 "application/x-sc",
203 "application/x-siag",
204 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
205 NULL}},
206 { N_("Text File"),
207 { "text/plain",
208 NULL}},
209 { N_("Video"),
210 { "video/mp4",
211 "video/3gpp",
212 "video/mpeg",
213 "video/quicktime",
214 "video/vivo",
215 "video/x-avi",
216 "video/x-mng",
217 "video/x-ms-asf",
218 "video/x-ms-wmv",
219 "video/x-msvideo",
220 "video/x-nsv",
221 "video/x-real-video",
222 NULL}}
223 };
224
225 /* Number of seconds until cancel dialog shows up */
226 #define DELAY_UNTIL_CANCEL_MSECS 5000
227
228 #define SILENT_WINDOW_OPEN_LIMIT 5
229 #define SILENT_OPEN_LIMIT 5
230
231 /* This number controls a maximum character count for a URL that is
232 * displayed as part of a dialog. It's fairly arbitrary -- big enough
233 * to allow most "normal" URIs to display in full, but small enough to
234 * prevent the dialog from getting insanely wide.
235 */
236 #define MAX_URI_IN_DIALOG_LENGTH 60
237
238 static void cancel_activate_callback (gpointer callback_data);
239 static void activate_activation_uris_ready_callback (GList *files,
240 gpointer callback_data);
241 static void activation_mount_mountables (ActivateParameters *parameters);
242 static void activation_start_mountables (ActivateParameters *parameters);
243 static void activate_callback (GList *files,
244 gpointer callback_data);
245 static void activation_mount_not_mounted (ActivateParameters *parameters);
246
247 static gboolean
is_sandboxed(void)248 is_sandboxed (void)
249 {
250 static gboolean ret;
251
252 static gsize init = 0;
253 if (g_once_init_enter (&init))
254 {
255 ret = g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS);
256 g_once_init_leave (&init, 1);
257 }
258
259 return ret;
260 }
261
262 static void
launch_location_free(LaunchLocation * location)263 launch_location_free (LaunchLocation *location)
264 {
265 nautilus_file_unref (location->file);
266 g_free (location->uri);
267 g_free (location);
268 }
269
270 static void
launch_location_list_free(GList * list)271 launch_location_list_free (GList *list)
272 {
273 g_list_foreach (list, (GFunc) launch_location_free, NULL);
274 g_list_free (list);
275 }
276
277 static GList *
get_file_list_for_launch_locations(GList * locations)278 get_file_list_for_launch_locations (GList *locations)
279 {
280 GList *files, *l;
281 LaunchLocation *location;
282
283 files = NULL;
284 for (l = locations; l != NULL; l = l->next)
285 {
286 location = l->data;
287
288 files = g_list_prepend (files,
289 nautilus_file_ref (location->file));
290 }
291 return g_list_reverse (files);
292 }
293
294
295 static LaunchLocation *
launch_location_from_file(NautilusFile * file)296 launch_location_from_file (NautilusFile *file)
297 {
298 LaunchLocation *location;
299 location = g_new (LaunchLocation, 1);
300 location->file = nautilus_file_ref (file);
301 location->uri = nautilus_file_get_uri (file);
302
303 return location;
304 }
305
306 static void
launch_location_update_from_file(LaunchLocation * location,NautilusFile * file)307 launch_location_update_from_file (LaunchLocation *location,
308 NautilusFile *file)
309 {
310 nautilus_file_unref (location->file);
311 g_free (location->uri);
312 location->file = nautilus_file_ref (file);
313 location->uri = nautilus_file_get_uri (file);
314 }
315
316 static void
launch_location_update_from_uri(LaunchLocation * location,const char * uri)317 launch_location_update_from_uri (LaunchLocation *location,
318 const char *uri)
319 {
320 nautilus_file_unref (location->file);
321 g_free (location->uri);
322 location->file = nautilus_file_get_by_uri (uri);
323 location->uri = g_strdup (uri);
324 }
325
326 static LaunchLocation *
find_launch_location_for_file(GList * list,NautilusFile * file)327 find_launch_location_for_file (GList *list,
328 NautilusFile *file)
329 {
330 LaunchLocation *location;
331 GList *l;
332
333 for (l = list; l != NULL; l = l->next)
334 {
335 location = l->data;
336
337 if (location->file == file)
338 {
339 return location;
340 }
341 }
342 return NULL;
343 }
344
345 static GList *
launch_locations_from_file_list(GList * list)346 launch_locations_from_file_list (GList *list)
347 {
348 GList *new;
349
350 new = NULL;
351 while (list)
352 {
353 new = g_list_prepend (new,
354 launch_location_from_file (list->data));
355 list = list->next;
356 }
357 new = g_list_reverse (new);
358 return new;
359 }
360
361 static ApplicationLaunchParameters *
application_launch_parameters_new(GAppInfo * application,GList * uris)362 application_launch_parameters_new (GAppInfo *application,
363 GList *uris)
364 {
365 ApplicationLaunchParameters *result;
366
367 result = g_new0 (ApplicationLaunchParameters, 1);
368 result->application = g_object_ref (application);
369 result->uris = g_list_copy_deep (uris, (GCopyFunc) g_strdup, NULL);
370
371 return result;
372 }
373
374 static void
application_launch_parameters_free(ApplicationLaunchParameters * parameters)375 application_launch_parameters_free (ApplicationLaunchParameters *parameters)
376 {
377 g_object_unref (parameters->application);
378 g_list_free_full (parameters->uris, g_free);
379
380 g_free (parameters);
381 }
382
383 static gboolean
nautilus_mime_actions_check_if_required_attributes_ready(NautilusFile * file)384 nautilus_mime_actions_check_if_required_attributes_ready (NautilusFile *file)
385 {
386 NautilusFileAttributes attributes;
387 gboolean ready;
388
389 attributes = nautilus_mime_actions_get_required_file_attributes ();
390 ready = nautilus_file_check_if_ready (file, attributes);
391
392 return ready;
393 }
394
395 NautilusFileAttributes
nautilus_mime_actions_get_required_file_attributes(void)396 nautilus_mime_actions_get_required_file_attributes (void)
397 {
398 return NAUTILUS_FILE_ATTRIBUTE_INFO;
399 }
400
401 GAppInfo *
nautilus_mime_get_default_application_for_file(NautilusFile * file)402 nautilus_mime_get_default_application_for_file (NautilusFile *file)
403 {
404 GAppInfo *app;
405 char *mime_type;
406 char *uri_scheme;
407
408 if (!nautilus_mime_actions_check_if_required_attributes_ready (file))
409 {
410 return NULL;
411 }
412
413 mime_type = nautilus_file_get_mime_type (file);
414 app = g_app_info_get_default_for_type (mime_type,
415 !nautilus_file_has_local_path (file));
416 g_free (mime_type);
417
418 if (app == NULL)
419 {
420 uri_scheme = nautilus_file_get_uri_scheme (file);
421 if (uri_scheme != NULL)
422 {
423 app = g_app_info_get_default_for_uri_scheme (uri_scheme);
424 g_free (uri_scheme);
425 }
426 }
427
428 return app;
429 }
430
431 static int
file_compare_by_mime_type(NautilusFile * file_a,NautilusFile * file_b)432 file_compare_by_mime_type (NautilusFile *file_a,
433 NautilusFile *file_b)
434 {
435 char *mime_type_a, *mime_type_b;
436 int ret;
437
438 mime_type_a = nautilus_file_get_mime_type (file_a);
439 mime_type_b = nautilus_file_get_mime_type (file_b);
440
441 ret = strcmp (mime_type_a, mime_type_b);
442
443 g_free (mime_type_a);
444 g_free (mime_type_b);
445
446 return ret;
447 }
448
449 static int
file_compare_by_parent_uri(NautilusFile * file_a,NautilusFile * file_b)450 file_compare_by_parent_uri (NautilusFile *file_a,
451 NautilusFile *file_b)
452 {
453 char *parent_uri_a, *parent_uri_b;
454 int ret;
455
456 parent_uri_a = nautilus_file_get_parent_uri (file_a);
457 parent_uri_b = nautilus_file_get_parent_uri (file_b);
458
459 ret = strcmp (parent_uri_a, parent_uri_b);
460
461 g_free (parent_uri_a);
462 g_free (parent_uri_b);
463
464 return ret;
465 }
466
467 GAppInfo *
nautilus_mime_get_default_application_for_files(GList * files)468 nautilus_mime_get_default_application_for_files (GList *files)
469 {
470 GList *l, *sorted_files;
471 NautilusFile *file;
472 GAppInfo *app, *one_app;
473
474 g_assert (files != NULL);
475
476 sorted_files = g_list_sort (g_list_copy (files), (GCompareFunc) file_compare_by_mime_type);
477
478 app = NULL;
479 for (l = sorted_files; l != NULL; l = l->next)
480 {
481 file = l->data;
482
483 if (l->prev &&
484 file_compare_by_mime_type (file, l->prev->data) == 0 &&
485 file_compare_by_parent_uri (file, l->prev->data) == 0)
486 {
487 continue;
488 }
489
490 one_app = nautilus_mime_get_default_application_for_file (file);
491 if (one_app == NULL || (app != NULL && !g_app_info_equal (app, one_app)))
492 {
493 if (app)
494 {
495 g_object_unref (app);
496 }
497 if (one_app)
498 {
499 g_object_unref (one_app);
500 }
501 app = NULL;
502 break;
503 }
504
505 if (app == NULL)
506 {
507 app = one_app;
508 }
509 else
510 {
511 g_object_unref (one_app);
512 }
513 }
514
515 g_list_free (sorted_files);
516
517 return app;
518 }
519
520 static void
trash_or_delete_files(GtkWindow * parent_window,const GList * files,gboolean delete_if_all_already_in_trash)521 trash_or_delete_files (GtkWindow *parent_window,
522 const GList *files,
523 gboolean delete_if_all_already_in_trash)
524 {
525 GList *locations;
526 const GList *node;
527
528 locations = NULL;
529 for (node = files; node != NULL; node = node->next)
530 {
531 locations = g_list_prepend (locations,
532 nautilus_file_get_location ((NautilusFile *) node->data));
533 }
534
535 locations = g_list_reverse (locations);
536
537 nautilus_file_operations_trash_or_delete_async (locations,
538 parent_window,
539 NULL,
540 NULL, NULL);
541 g_list_free_full (locations, g_object_unref);
542 }
543
544 static void
report_broken_symbolic_link(GtkWindow * parent_window,NautilusFile * file)545 report_broken_symbolic_link (GtkWindow *parent_window,
546 NautilusFile *file)
547 {
548 char *target_path;
549 char *display_name;
550 char *prompt;
551 char *detail;
552 GtkDialog *dialog;
553 GList file_as_list;
554 int response;
555 gboolean can_trash;
556
557 g_assert (nautilus_file_is_broken_symbolic_link (file));
558
559 display_name = nautilus_file_get_display_name (file);
560 can_trash = nautilus_file_can_trash (file) && !nautilus_file_is_in_trash (file);
561
562 if (can_trash)
563 {
564 prompt = g_strdup_printf (_("The link “%s” is broken. Move it to Trash?"), display_name);
565 }
566 else
567 {
568 prompt = g_strdup_printf (_("The link “%s” is broken."), display_name);
569 }
570 g_free (display_name);
571
572 target_path = nautilus_file_get_symbolic_link_target_path (file);
573 if (target_path == NULL)
574 {
575 detail = g_strdup (_("This link cannot be used because it has no target."));
576 }
577 else
578 {
579 detail = g_strdup_printf (_("This link cannot be used because its target "
580 "“%s” doesn’t exist."), target_path);
581 }
582
583 if (!can_trash)
584 {
585 eel_run_simple_dialog (GTK_WIDGET (parent_window), FALSE, GTK_MESSAGE_WARNING,
586 prompt, detail, _("_Cancel"), NULL);
587 goto out;
588 }
589
590 dialog = eel_show_yes_no_dialog (prompt, detail, _("Mo_ve to Trash"), _("_Cancel"),
591 parent_window);
592
593 gtk_dialog_set_default_response (dialog, GTK_RESPONSE_CANCEL);
594
595 /* Make this modal to avoid problems with reffing the view & file
596 * to keep them around in case the view changes, which would then
597 * cause the old view not to be destroyed, which would cause its
598 * merged Bonobo items not to be un-merged. Maybe we need to unmerge
599 * explicitly when disconnecting views instead of relying on the
600 * unmerge in Destroy. But since BonoboUIHandler is probably going
601 * to change wildly, I don't want to mess with this now.
602 */
603
604 response = gtk_dialog_run (dialog);
605 gtk_widget_destroy (GTK_WIDGET (dialog));
606
607 if (response == GTK_RESPONSE_YES)
608 {
609 file_as_list.data = file;
610 file_as_list.next = NULL;
611 file_as_list.prev = NULL;
612 trash_or_delete_files (parent_window, &file_as_list, TRUE);
613 }
614
615 out:
616 g_free (prompt);
617 g_free (target_path);
618 g_free (detail);
619 }
620
621 static ActivationAction
get_default_executable_text_file_action(void)622 get_default_executable_text_file_action (void)
623 {
624 return ACTIVATION_ACTION_OPEN_IN_APPLICATION;
625 }
626
627 static ActivationAction
get_activation_action(NautilusFile * file)628 get_activation_action (NautilusFile *file)
629 {
630 ActivationAction action;
631 char *activation_uri;
632 gboolean handles_extract = FALSE;
633 g_autoptr (GAppInfo) app_info = NULL;
634 const gchar *app_id;
635
636 app_info = nautilus_mime_get_default_application_for_file (file);
637 if (app_info != NULL)
638 {
639 app_id = g_app_info_get_id (app_info);
640 handles_extract = g_strcmp0 (app_id, NAUTILUS_DESKTOP_ID) == 0;
641 }
642 if (handles_extract && nautilus_file_is_archive (file))
643 {
644 return ACTIVATION_ACTION_EXTRACT;
645 }
646
647 activation_uri = nautilus_file_get_activation_uri (file);
648 if (activation_uri == NULL)
649 {
650 activation_uri = nautilus_file_get_uri (file);
651 }
652
653 action = ACTIVATION_ACTION_DO_NOTHING;
654 if (nautilus_file_is_launchable (file))
655 {
656 char *executable_path;
657
658 action = ACTIVATION_ACTION_LAUNCH;
659
660 executable_path = g_filename_from_uri (activation_uri, NULL, NULL);
661 if (!executable_path)
662 {
663 action = ACTIVATION_ACTION_DO_NOTHING;
664 }
665 else if (nautilus_file_contains_text (file))
666 {
667 action = get_default_executable_text_file_action ();
668 }
669 g_free (executable_path);
670 }
671
672 if (action == ACTIVATION_ACTION_DO_NOTHING)
673 {
674 if (nautilus_file_opens_in_view (file))
675 {
676 action = ACTIVATION_ACTION_OPEN_IN_VIEW;
677 }
678 else
679 {
680 action = ACTIVATION_ACTION_OPEN_IN_APPLICATION;
681 }
682 }
683 g_free (activation_uri);
684
685 return action;
686 }
687
688 gboolean
nautilus_mime_file_extracts(NautilusFile * file)689 nautilus_mime_file_extracts (NautilusFile *file)
690 {
691 return get_activation_action (file) == ACTIVATION_ACTION_EXTRACT;
692 }
693
694 gboolean
nautilus_mime_file_launches(NautilusFile * file)695 nautilus_mime_file_launches (NautilusFile *file)
696 {
697 ActivationAction activation_action;
698
699 activation_action = get_activation_action (file);
700
701 return (activation_action == ACTIVATION_ACTION_LAUNCH);
702 }
703
704 gboolean
nautilus_mime_file_opens_in_external_app(NautilusFile * file)705 nautilus_mime_file_opens_in_external_app (NautilusFile *file)
706 {
707 ActivationAction activation_action;
708
709 activation_action = get_activation_action (file);
710
711 return (activation_action == ACTIVATION_ACTION_OPEN_IN_APPLICATION);
712 }
713
714
715 static unsigned int
mime_application_hash(GAppInfo * app)716 mime_application_hash (GAppInfo *app)
717 {
718 const char *id;
719
720 id = g_app_info_get_id (app);
721
722 if (id == NULL)
723 {
724 return GPOINTER_TO_UINT (app);
725 }
726
727 return g_str_hash (id);
728 }
729
730 static void
list_to_parameters_foreach(GAppInfo * application,GList * uris,GList ** ret)731 list_to_parameters_foreach (GAppInfo *application,
732 GList *uris,
733 GList **ret)
734 {
735 ApplicationLaunchParameters *parameters;
736
737 uris = g_list_reverse (uris);
738
739 parameters = application_launch_parameters_new
740 (application, uris);
741 *ret = g_list_prepend (*ret, parameters);
742 }
743
744
745 /**
746 * make_activation_parameters
747 *
748 * Construct a list of ApplicationLaunchParameters from a list of NautilusFiles,
749 * where files that have the same default application are put into the same
750 * launch parameter, and others are put into the unhandled_files list.
751 *
752 * @files: Files to use for construction.
753 * @unhandled_files: Files without any default application will be put here.
754 *
755 * Return value: Newly allocated list of ApplicationLaunchParameters.
756 **/
757 static GList *
make_activation_parameters(GList * uris,GList ** unhandled_uris)758 make_activation_parameters (GList *uris,
759 GList **unhandled_uris)
760 {
761 GList *ret, *l, *app_uris;
762 NautilusFile *file;
763 GAppInfo *app, *old_app;
764 GHashTable *app_table;
765 char *uri;
766
767 ret = NULL;
768 *unhandled_uris = NULL;
769
770 app_table = g_hash_table_new_full
771 ((GHashFunc) mime_application_hash,
772 (GEqualFunc) g_app_info_equal,
773 (GDestroyNotify) g_object_unref,
774 (GDestroyNotify) g_list_free);
775
776 for (l = uris; l != NULL; l = l->next)
777 {
778 uri = l->data;
779 file = nautilus_file_get_by_uri (uri);
780
781 app = nautilus_mime_get_default_application_for_file (file);
782 if (app != NULL)
783 {
784 app_uris = NULL;
785
786 if (g_hash_table_lookup_extended (app_table, app,
787 (gpointer *) &old_app,
788 (gpointer *) &app_uris))
789 {
790 g_hash_table_steal (app_table, old_app);
791
792 app_uris = g_list_prepend (app_uris, uri);
793
794 g_object_unref (app);
795 app = old_app;
796 }
797 else
798 {
799 app_uris = g_list_prepend (NULL, uri);
800 }
801
802 g_hash_table_insert (app_table, app, app_uris);
803 }
804 else
805 {
806 *unhandled_uris = g_list_prepend (*unhandled_uris, uri);
807 }
808 nautilus_file_unref (file);
809 }
810
811 g_hash_table_foreach (app_table,
812 (GHFunc) list_to_parameters_foreach,
813 &ret);
814
815 g_hash_table_destroy (app_table);
816
817 *unhandled_uris = g_list_reverse (*unhandled_uris);
818
819 return g_list_reverse (ret);
820 }
821
822 static gboolean
file_was_cancelled(NautilusFile * file)823 file_was_cancelled (NautilusFile *file)
824 {
825 GError *error;
826
827 error = nautilus_file_get_file_info_error (file);
828 return
829 error != NULL &&
830 error->domain == G_IO_ERROR &&
831 error->code == G_IO_ERROR_CANCELLED;
832 }
833
834 static gboolean
file_was_not_mounted(NautilusFile * file)835 file_was_not_mounted (NautilusFile *file)
836 {
837 GError *error;
838
839 error = nautilus_file_get_file_info_error (file);
840 return
841 error != NULL &&
842 error->domain == G_IO_ERROR &&
843 error->code == G_IO_ERROR_NOT_MOUNTED;
844 }
845
846 static void
activation_parameters_free(ActivateParameters * parameters)847 activation_parameters_free (ActivateParameters *parameters)
848 {
849 if (parameters->timed_wait_active)
850 {
851 eel_timed_wait_stop (cancel_activate_callback, parameters);
852 }
853
854 if (parameters->slot)
855 {
856 g_object_remove_weak_pointer (G_OBJECT (parameters->slot), (gpointer *) ¶meters->slot);
857 }
858 if (parameters->parent_window)
859 {
860 g_object_remove_weak_pointer (G_OBJECT (parameters->parent_window), (gpointer *) ¶meters->parent_window);
861 }
862 g_object_unref (parameters->cancellable);
863 launch_location_list_free (parameters->locations);
864 nautilus_file_list_free (parameters->mountables);
865 nautilus_file_list_free (parameters->start_mountables);
866 nautilus_file_list_free (parameters->not_mounted);
867 g_free (parameters->activation_directory);
868 g_free (parameters->timed_wait_prompt);
869 g_assert (parameters->files_handle == NULL);
870 g_free (parameters);
871 }
872
873 static void
application_launch_async_parameters_free(ApplicationLaunchAsyncParameters * parameters)874 application_launch_async_parameters_free (ApplicationLaunchAsyncParameters *parameters)
875 {
876 g_queue_free (parameters->uris);
877 activation_parameters_free (parameters->activation_params);
878
879 g_free (parameters);
880 }
881
882 static void
cancel_activate_callback(gpointer callback_data)883 cancel_activate_callback (gpointer callback_data)
884 {
885 ActivateParameters *parameters = callback_data;
886
887 parameters->timed_wait_active = FALSE;
888
889 g_cancellable_cancel (parameters->cancellable);
890
891 if (parameters->files_handle)
892 {
893 nautilus_file_list_cancel_call_when_ready (parameters->files_handle);
894 parameters->files_handle = NULL;
895 activation_parameters_free (parameters);
896 }
897 }
898
899 static void
activation_start_timed_cancel(ActivateParameters * parameters)900 activation_start_timed_cancel (ActivateParameters *parameters)
901 {
902 parameters->timed_wait_active = TRUE;
903 eel_timed_wait_start_with_duration
904 (DELAY_UNTIL_CANCEL_MSECS,
905 cancel_activate_callback,
906 parameters,
907 parameters->timed_wait_prompt,
908 parameters->parent_window);
909 }
910
911 static void
pause_activation_timed_cancel(ActivateParameters * parameters)912 pause_activation_timed_cancel (ActivateParameters *parameters)
913 {
914 if (parameters->timed_wait_active)
915 {
916 eel_timed_wait_stop (cancel_activate_callback, parameters);
917 parameters->timed_wait_active = FALSE;
918 }
919 }
920
921 static void
unpause_activation_timed_cancel(ActivateParameters * parameters)922 unpause_activation_timed_cancel (ActivateParameters *parameters)
923 {
924 if (!parameters->timed_wait_active)
925 {
926 activation_start_timed_cancel (parameters);
927 }
928 }
929
930
931 static void
activate_mount_op_active(GtkMountOperation * operation,GParamSpec * pspec,ActivateParameters * parameters)932 activate_mount_op_active (GtkMountOperation *operation,
933 GParamSpec *pspec,
934 ActivateParameters *parameters)
935 {
936 gboolean is_active;
937
938 g_object_get (operation, "is-showing", &is_active, NULL);
939
940 if (is_active)
941 {
942 pause_activation_timed_cancel (parameters);
943 }
944 else
945 {
946 unpause_activation_timed_cancel (parameters);
947 }
948 }
949
950 static gboolean
confirm_multiple_windows(GtkWindow * parent_window,int count,gboolean use_tabs)951 confirm_multiple_windows (GtkWindow *parent_window,
952 int count,
953 gboolean use_tabs)
954 {
955 GtkDialog *dialog;
956 char *prompt;
957 char *detail;
958 int response;
959
960 if (count <= SILENT_WINDOW_OPEN_LIMIT)
961 {
962 return TRUE;
963 }
964
965 prompt = _("Are you sure you want to open all files?");
966 if (use_tabs)
967 {
968 detail = g_strdup_printf (ngettext ("This will open %d separate tab.",
969 "This will open %d separate tabs.", count), count);
970 }
971 else
972 {
973 detail = g_strdup_printf (ngettext ("This will open %d separate window.",
974 "This will open %d separate windows.", count), count);
975 }
976 dialog = eel_show_yes_no_dialog (prompt, detail,
977 _("_OK"), _("_Cancel"),
978 parent_window);
979 g_free (detail);
980
981 response = gtk_dialog_run (dialog);
982 gtk_widget_destroy (GTK_WIDGET (dialog));
983
984 return response == GTK_RESPONSE_YES;
985 }
986
987 typedef struct
988 {
989 NautilusWindowSlot *slot;
990 GtkWindow *parent_window;
991 NautilusFile *file;
992 GList *files;
993 NautilusWindowOpenFlags flags;
994 char *activation_directory;
995 gboolean user_confirmation;
996 char *uri;
997 GDBusProxy *proxy;
998 GtkWidget *dialog;
999 } ActivateParametersInstall;
1000
1001 static void
activate_parameters_install_free(ActivateParametersInstall * parameters_install)1002 activate_parameters_install_free (ActivateParametersInstall *parameters_install)
1003 {
1004 if (parameters_install->slot)
1005 {
1006 g_object_remove_weak_pointer (G_OBJECT (parameters_install->slot), (gpointer *) ¶meters_install->slot);
1007 }
1008 if (parameters_install->parent_window)
1009 {
1010 g_object_remove_weak_pointer (G_OBJECT (parameters_install->parent_window), (gpointer *) ¶meters_install->parent_window);
1011 }
1012
1013 if (parameters_install->proxy != NULL)
1014 {
1015 g_object_unref (parameters_install->proxy);
1016 }
1017
1018 nautilus_file_unref (parameters_install->file);
1019 nautilus_file_list_free (parameters_install->files);
1020 g_free (parameters_install->activation_directory);
1021 g_free (parameters_install->uri);
1022 g_free (parameters_install);
1023 }
1024
1025 static char *
get_application_no_mime_type_handler_message(NautilusFile * file,char * uri)1026 get_application_no_mime_type_handler_message (NautilusFile *file,
1027 char *uri)
1028 {
1029 char *uri_for_display;
1030 char *name;
1031 char *error_message;
1032
1033 name = nautilus_file_get_display_name (file);
1034
1035 /* Truncate the URI so it doesn't get insanely wide. Note that even
1036 * though the dialog uses wrapped text, if the URI doesn't contain
1037 * white space then the text-wrapping code is too stupid to wrap it.
1038 */
1039 uri_for_display = eel_str_middle_truncate (name, MAX_URI_IN_DIALOG_LENGTH);
1040 error_message = g_strdup_printf (_("Could Not Display “%s”"), uri_for_display);
1041 g_free (uri_for_display);
1042 g_free (name);
1043
1044 return error_message;
1045 }
1046
1047 static void
open_with_response_cb(GtkDialog * dialog,gint response_id,gpointer user_data)1048 open_with_response_cb (GtkDialog *dialog,
1049 gint response_id,
1050 gpointer user_data)
1051 {
1052 GtkWindow *parent_window;
1053 NautilusFile *file;
1054 GList files;
1055 GAppInfo *info;
1056 ActivateParametersInstall *parameters = user_data;
1057
1058 if (response_id != GTK_RESPONSE_OK)
1059 {
1060 gtk_widget_destroy (GTK_WIDGET (dialog));
1061 return;
1062 }
1063
1064 parent_window = parameters->parent_window;
1065 file = g_object_get_data (G_OBJECT (dialog), "mime-action:file");
1066 info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (dialog));
1067
1068 gtk_widget_destroy (GTK_WIDGET (dialog));
1069
1070 g_signal_emit_by_name (nautilus_signaller_get_current (), "mime-data-changed");
1071
1072 files.next = NULL;
1073 files.prev = NULL;
1074 files.data = file;
1075 nautilus_launch_application (info, &files, parent_window);
1076
1077 g_object_unref (info);
1078
1079 activate_parameters_install_free (parameters);
1080 }
1081
1082 static void
choose_program(GtkDialog * message_dialog,int response,gpointer callback_data)1083 choose_program (GtkDialog *message_dialog,
1084 int response,
1085 gpointer callback_data)
1086 {
1087 GtkWidget *dialog;
1088 NautilusFile *file;
1089 GFile *location;
1090 ActivateParametersInstall *parameters = callback_data;
1091
1092 if (response != GTK_RESPONSE_ACCEPT)
1093 {
1094 gtk_widget_destroy (GTK_WIDGET (message_dialog));
1095 activate_parameters_install_free (parameters);
1096 return;
1097 }
1098
1099 file = g_object_get_data (G_OBJECT (message_dialog), "mime-action:file");
1100
1101 g_assert (NAUTILUS_IS_FILE (file));
1102
1103 location = nautilus_file_get_location (file);
1104 nautilus_file_ref (file);
1105
1106 /* Destroy the message dialog after ref:ing the file */
1107 gtk_widget_destroy (GTK_WIDGET (message_dialog));
1108
1109 dialog = gtk_app_chooser_dialog_new (parameters->parent_window,
1110 GTK_DIALOG_MODAL,
1111 location);
1112 g_object_set_data_full (G_OBJECT (dialog),
1113 "mime-action:file",
1114 nautilus_file_ref (file),
1115 (GDestroyNotify) nautilus_file_unref);
1116
1117 gtk_widget_show (dialog);
1118
1119 g_signal_connect (dialog,
1120 "response",
1121 G_CALLBACK (open_with_response_cb),
1122 parameters);
1123
1124 g_object_unref (location);
1125 nautilus_file_unref (file);
1126 }
1127
1128 static void
show_unhandled_type_error(ActivateParametersInstall * parameters)1129 show_unhandled_type_error (ActivateParametersInstall *parameters)
1130 {
1131 GtkWidget *dialog;
1132
1133 char *mime_type = nautilus_file_get_mime_type (parameters->file);
1134 char *error_message = get_application_no_mime_type_handler_message (parameters->file, parameters->uri);
1135 if (g_content_type_is_unknown (mime_type))
1136 {
1137 dialog = gtk_message_dialog_new (parameters->parent_window,
1138 GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
1139 GTK_MESSAGE_ERROR,
1140 0,
1141 "%s", error_message);
1142 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
1143 _("The file is of an unknown type"));
1144 }
1145 else
1146 {
1147 char *text;
1148 text = g_strdup_printf (_("There is no application installed for “%s” files"), g_content_type_get_description (mime_type));
1149
1150 dialog = gtk_message_dialog_new (parameters->parent_window,
1151 GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
1152 GTK_MESSAGE_ERROR,
1153 0,
1154 "%s", error_message);
1155 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
1156 "%s", text);
1157
1158 g_free (text);
1159 }
1160
1161 gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Select Application"), GTK_RESPONSE_ACCEPT);
1162
1163 gtk_dialog_add_button (GTK_DIALOG (dialog), _("_OK"), GTK_RESPONSE_OK);
1164
1165 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
1166
1167 g_object_set_data_full (G_OBJECT (dialog),
1168 "mime-action:file",
1169 nautilus_file_ref (parameters->file),
1170 (GDestroyNotify) nautilus_file_unref);
1171
1172 gtk_widget_show (GTK_WIDGET (dialog));
1173
1174 g_signal_connect (dialog, "response",
1175 G_CALLBACK (choose_program), parameters);
1176
1177 g_free (error_message);
1178 g_free (mime_type);
1179 }
1180
1181 static void
search_for_application_dbus_call_notify_cb(GDBusProxy * proxy,GAsyncResult * result,gpointer user_data)1182 search_for_application_dbus_call_notify_cb (GDBusProxy *proxy,
1183 GAsyncResult *result,
1184 gpointer user_data)
1185 {
1186 ActivateParametersInstall *parameters_install = user_data;
1187 GVariant *variant;
1188 GError *error = NULL;
1189
1190 variant = g_dbus_proxy_call_finish (proxy, result, &error);
1191 if (variant == NULL)
1192 {
1193 if (!g_dbus_error_is_remote_error (error) ||
1194 g_strcmp0 (g_dbus_error_get_remote_error (error), "org.freedesktop.PackageKit.Modify.Failed") == 0)
1195 {
1196 char *message;
1197
1198 message = g_strdup_printf ("%s\n%s",
1199 _("There was an internal error trying to search for applications:"),
1200 error->message);
1201 show_dialog (_("Unable to search for application"),
1202 message,
1203 parameters_install->parent_window,
1204 GTK_MESSAGE_ERROR);
1205 g_free (message);
1206 }
1207 else
1208 {
1209 g_warning ("Error while trying to search for applications: %s",
1210 error->message);
1211 }
1212
1213 g_error_free (error);
1214 activate_parameters_install_free (parameters_install);
1215 return;
1216 }
1217
1218 g_variant_unref (variant);
1219
1220 activate_parameters_install_free (parameters_install);
1221 }
1222
1223 static void
search_for_application_mime_type(ActivateParametersInstall * parameters_install,const gchar * mime_type)1224 search_for_application_mime_type (ActivateParametersInstall *parameters_install,
1225 const gchar *mime_type)
1226 {
1227 gchar *desktop_startup_id;
1228
1229 g_assert (parameters_install->proxy != NULL);
1230
1231 desktop_startup_id = g_strdup_printf ("_TIME%i", gtk_get_current_event_time ());
1232
1233 g_dbus_proxy_call (parameters_install->proxy,
1234 "InstallMimeTypes",
1235 g_variant_new_parsed ("([%s], %s, %s, [{%s, %v}])",
1236 mime_type,
1237 "hide-confirm-search",
1238 APPLICATION_ID,
1239 "desktop-startup-id",
1240 g_variant_new_take_string (desktop_startup_id)),
1241 G_DBUS_CALL_FLAGS_NONE,
1242 G_MAXINT /* no timeout */,
1243 NULL /* cancellable */,
1244 (GAsyncReadyCallback) search_for_application_dbus_call_notify_cb,
1245 parameters_install);
1246
1247 DEBUG ("InstallMimeType method invoked for %s", mime_type);
1248 }
1249
1250 static void
application_unhandled_file_install(GtkDialog * dialog,gint response_id,ActivateParametersInstall * parameters_install)1251 application_unhandled_file_install (GtkDialog *dialog,
1252 gint response_id,
1253 ActivateParametersInstall *parameters_install)
1254 {
1255 char *mime_type;
1256
1257 gtk_widget_destroy (GTK_WIDGET (dialog));
1258 parameters_install->dialog = NULL;
1259
1260 if (response_id == GTK_RESPONSE_YES)
1261 {
1262 mime_type = nautilus_file_get_mime_type (parameters_install->file);
1263 search_for_application_mime_type (parameters_install, mime_type);
1264 g_free (mime_type);
1265 }
1266 else
1267 {
1268 /* free as we're not going to get the async dbus callback */
1269 activate_parameters_install_free (parameters_install);
1270 }
1271 }
1272
1273 static void
pk_proxy_appeared_cb(GObject * source,GAsyncResult * res,gpointer user_data)1274 pk_proxy_appeared_cb (GObject *source,
1275 GAsyncResult *res,
1276 gpointer user_data)
1277 {
1278 ActivateParametersInstall *parameters_install = user_data;
1279 char *mime_type, *name_owner;
1280 char *error_message;
1281 GtkWidget *dialog;
1282 GDBusProxy *proxy;
1283 GError *error = NULL;
1284
1285 proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
1286 name_owner = g_dbus_proxy_get_name_owner (proxy);
1287
1288 if (error != NULL || name_owner == NULL)
1289 {
1290 g_warning ("Couldn't call Modify on the PackageKit interface: %s",
1291 error != NULL ? error->message : "no owner for PackageKit");
1292 g_clear_error (&error);
1293
1294 /* show an unhelpful dialog */
1295 show_unhandled_type_error (parameters_install);
1296
1297 return;
1298 }
1299
1300 g_free (name_owner);
1301
1302 mime_type = nautilus_file_get_mime_type (parameters_install->file);
1303 error_message = get_application_no_mime_type_handler_message (parameters_install->file,
1304 parameters_install->uri);
1305 /* use a custom dialog to prompt the user to install new software */
1306 dialog = gtk_message_dialog_new (parameters_install->parent_window,
1307 GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
1308 GTK_MESSAGE_ERROR,
1309 GTK_BUTTONS_NONE,
1310 "%s", error_message);
1311 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
1312 _("There is no application installed for “%s” files. "
1313 "Do you want to search for an application to open this file?"),
1314 g_content_type_get_description (mime_type));
1315 gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
1316
1317 gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Cancel"), GTK_RESPONSE_CANCEL);
1318 gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Search in Software"), GTK_RESPONSE_YES);
1319
1320 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES);
1321
1322 parameters_install->dialog = dialog;
1323 parameters_install->proxy = proxy;
1324
1325 g_signal_connect (dialog, "response",
1326 G_CALLBACK (application_unhandled_file_install),
1327 parameters_install);
1328 gtk_widget_show_all (dialog);
1329 g_free (mime_type);
1330 }
1331
1332 static void
application_unhandled_uri(ActivateParameters * parameters,char * uri)1333 application_unhandled_uri (ActivateParameters *parameters,
1334 char *uri)
1335 {
1336 gboolean show_install_mime;
1337 char *mime_type;
1338 NautilusFile *file;
1339 ActivateParametersInstall *parameters_install;
1340
1341 file = nautilus_file_get_by_uri (uri);
1342
1343 mime_type = nautilus_file_get_mime_type (file);
1344
1345 /* copy the parts of parameters we are interested in as the orignal will be unref'd */
1346 parameters_install = g_new0 (ActivateParametersInstall, 1);
1347 parameters_install->slot = parameters->slot;
1348 g_object_add_weak_pointer (G_OBJECT (parameters_install->slot), (gpointer *) ¶meters_install->slot);
1349 if (parameters->parent_window)
1350 {
1351 parameters_install->parent_window = parameters->parent_window;
1352 g_object_add_weak_pointer (G_OBJECT (parameters_install->parent_window), (gpointer *) ¶meters_install->parent_window);
1353 }
1354 parameters_install->activation_directory = g_strdup (parameters->activation_directory);
1355 parameters_install->file = file;
1356 parameters_install->files = get_file_list_for_launch_locations (parameters->locations);
1357 parameters_install->flags = parameters->flags;
1358 parameters_install->user_confirmation = parameters->user_confirmation;
1359 parameters_install->uri = g_strdup (uri);
1360
1361 #ifdef ENABLE_PACKAGEKIT
1362 /* allow an admin to disable the PackageKit search functionality */
1363 show_install_mime = g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_INSTALL_MIME_ACTIVATION);
1364 #else
1365 /* we have no install functionality */
1366 show_install_mime = FALSE;
1367 #endif
1368 /* There is no use trying to look for handlers of application/octet-stream */
1369 if (g_content_type_is_unknown (mime_type))
1370 {
1371 show_install_mime = FALSE;
1372 }
1373
1374 g_free (mime_type);
1375
1376 if (!show_install_mime)
1377 {
1378 goto out;
1379 }
1380
1381 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
1382 G_DBUS_PROXY_FLAGS_NONE,
1383 NULL,
1384 "org.freedesktop.PackageKit",
1385 "/org/freedesktop/PackageKit",
1386 "org.freedesktop.PackageKit.Modify2",
1387 NULL,
1388 pk_proxy_appeared_cb,
1389 parameters_install);
1390
1391 return;
1392
1393 out:
1394 /* show an unhelpful dialog */
1395 show_unhandled_type_error (parameters_install);
1396 }
1397
1398 static void
launch_default_for_uris_callback(GObject * source_object,GAsyncResult * res,gpointer user_data)1399 launch_default_for_uris_callback (GObject *source_object,
1400 GAsyncResult *res,
1401 gpointer user_data)
1402 {
1403 ApplicationLaunchAsyncParameters *params;
1404 ActivateParameters *activation_params;
1405 char *uri;
1406 g_autoptr (GError) error = NULL;
1407
1408 params = user_data;
1409 activation_params = params->activation_params;
1410 uri = g_queue_pop_head (params->uris);
1411
1412 nautilus_launch_default_for_uri_finish (res, &error);
1413 if (error == NULL)
1414 {
1415 gtk_recent_manager_add_item (gtk_recent_manager_get_default (), uri);
1416 }
1417
1418 if (!g_queue_is_empty (params->uris))
1419 {
1420 nautilus_launch_default_for_uri_async (g_queue_peek_head (params->uris),
1421 activation_params->parent_window,
1422 activation_params->cancellable,
1423 launch_default_for_uris_callback,
1424 params);
1425 }
1426 else
1427 {
1428 application_launch_async_parameters_free (params);
1429 }
1430 }
1431
1432 static void
activate_files(ActivateParameters * parameters)1433 activate_files (ActivateParameters *parameters)
1434 {
1435 NautilusFile *file;
1436 NautilusWindowOpenFlags flags;
1437 g_autoptr (GList) open_in_app_parameters = NULL;
1438 g_autoptr (GList) unhandled_open_in_app_uris = NULL;
1439 ApplicationLaunchParameters *one_parameters;
1440 int count;
1441 g_autofree char *old_working_dir = NULL;
1442 GdkScreen *screen;
1443 gint num_apps;
1444 gint num_unhandled;
1445 gint num_files;
1446 gboolean open_files;
1447 g_autoptr (GQueue) launch_files = NULL;
1448 g_autoptr (GQueue) launch_in_terminal_files = NULL;
1449 g_autoptr (GQueue) open_in_app_uris = NULL;
1450 g_autoptr (GQueue) open_in_view_files = NULL;
1451 GList *l;
1452 ActivationAction action;
1453
1454 launch_files = g_queue_new ();
1455 launch_in_terminal_files = g_queue_new ();
1456 open_in_view_files = g_queue_new ();
1457 open_in_app_uris = g_queue_new ();
1458
1459 for (l = parameters->locations; l != NULL; l = l->next)
1460 {
1461 LaunchLocation *location;
1462
1463 location = l->data;
1464 file = location->file;
1465
1466 if (file_was_cancelled (file))
1467 {
1468 continue;
1469 }
1470
1471 action = get_activation_action (file);
1472
1473 switch (action)
1474 {
1475 case ACTIVATION_ACTION_LAUNCH:
1476 {
1477 g_queue_push_tail (launch_files, file);
1478 }
1479 break;
1480
1481 case ACTIVATION_ACTION_LAUNCH_IN_TERMINAL:
1482 {
1483 g_queue_push_tail (launch_in_terminal_files, file);
1484 }
1485 break;
1486
1487 case ACTIVATION_ACTION_OPEN_IN_VIEW:
1488 {
1489 g_queue_push_tail (open_in_view_files, file);
1490 }
1491 break;
1492
1493 case ACTIVATION_ACTION_OPEN_IN_APPLICATION:
1494 {
1495 g_queue_push_tail (open_in_app_uris, location->uri);
1496 }
1497 break;
1498
1499 case ACTIVATION_ACTION_DO_NOTHING:
1500 {
1501 }
1502 break;
1503
1504 case ACTIVATION_ACTION_EXTRACT:
1505 {
1506 /* Extraction of files should be handled in the view */
1507 g_assert_not_reached ();
1508 }
1509 break;
1510 }
1511 }
1512
1513 if (parameters->activation_directory &&
1514 (!g_queue_is_empty (launch_files) ||
1515 !g_queue_is_empty (launch_in_terminal_files)))
1516 {
1517 old_working_dir = g_get_current_dir ();
1518 g_chdir (parameters->activation_directory);
1519 }
1520
1521 screen = gtk_widget_get_screen (GTK_WIDGET (parameters->parent_window));
1522 for (l = g_queue_peek_head_link (launch_files); l != NULL; l = l->next)
1523 {
1524 g_autofree char *uri = NULL;
1525 g_autofree char *executable_path = NULL;
1526 g_autofree char *quoted_path = NULL;
1527
1528 file = NAUTILUS_FILE (l->data);
1529
1530 uri = nautilus_file_get_activation_uri (file);
1531 executable_path = g_filename_from_uri (uri, NULL, NULL);
1532 quoted_path = g_shell_quote (executable_path);
1533
1534 DEBUG ("Launching file path %s", quoted_path);
1535
1536 nautilus_launch_application_from_command (screen, quoted_path, FALSE, NULL);
1537 }
1538
1539 for (l = g_queue_peek_head_link (launch_in_terminal_files); l != NULL; l = l->next)
1540 {
1541 g_autofree char *uri = NULL;
1542 g_autofree char *executable_path = NULL;
1543 g_autofree char *quoted_path = NULL;
1544
1545 file = NAUTILUS_FILE (l->data);
1546
1547 uri = nautilus_file_get_activation_uri (file);
1548 executable_path = g_filename_from_uri (uri, NULL, NULL);
1549 quoted_path = g_shell_quote (executable_path);
1550
1551 DEBUG ("Launching in terminal file quoted path %s", quoted_path);
1552
1553 nautilus_launch_application_from_command (screen, quoted_path, TRUE, NULL);
1554 }
1555
1556 if (old_working_dir != NULL)
1557 {
1558 g_chdir (old_working_dir);
1559 }
1560
1561 count = g_queue_get_length (open_in_view_files);
1562
1563 flags = parameters->flags;
1564 if (count > 1)
1565 {
1566 if ((parameters->flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW) == 0)
1567 {
1568 flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB;
1569 }
1570 else
1571 {
1572 flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW;
1573 }
1574 }
1575
1576 if (parameters->slot != NULL &&
1577 (!parameters->user_confirmation ||
1578 confirm_multiple_windows (parameters->parent_window, count,
1579 (flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB) != 0)))
1580 {
1581 if ((flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB) != 0 &&
1582 g_settings_get_enum (nautilus_preferences, NAUTILUS_PREFERENCES_NEW_TAB_POSITION) ==
1583 NAUTILUS_NEW_TAB_POSITION_AFTER_CURRENT_TAB)
1584 {
1585 /* When inserting N tabs after the current one,
1586 * we first open tab N, then tab N-1, ..., then tab 0.
1587 * Each of them is appended to the current tab, i.e.
1588 * prepended to the list of tabs to open.
1589 */
1590 g_queue_reverse (open_in_view_files);
1591 }
1592
1593 for (l = g_queue_peek_head_link (open_in_view_files); l != NULL; l = l->next)
1594 {
1595 g_autofree char *uri = NULL;
1596 g_autoptr (GFile) location = NULL;
1597 g_autoptr (GFile) location_with_permissions = NULL;
1598 /* The ui should ask for navigation or object windows
1599 * depending on what the current one is */
1600 file = NAUTILUS_FILE (l->data);
1601 uri = nautilus_file_get_activation_uri (file);
1602 location = g_file_new_for_uri (uri);
1603 if (g_file_is_native (location) &&
1604 (nautilus_file_is_in_admin (file) ||
1605 !nautilus_file_can_read (file) ||
1606 !nautilus_file_can_execute (file)))
1607 {
1608 g_autofree gchar *file_path = NULL;
1609
1610 g_free (uri);
1611
1612 file_path = g_file_get_path (location);
1613 uri = g_strconcat ("admin://", file_path, NULL);
1614 }
1615
1616 location_with_permissions = g_file_new_for_uri (uri);
1617 /* FIXME: we need to pass the parent_window, but we only use it for the current active window,
1618 * which nautilus-application should take care of. However is not working and creating regressions
1619 * in some cases. Until we figure out what's going on, continue to use the parameters->slot
1620 * to make splicit the window we want to use for activating the files */
1621 nautilus_application_open_location_full (NAUTILUS_APPLICATION (g_application_get_default ()),
1622 location_with_permissions, flags, NULL, NULL, parameters->slot);
1623 }
1624 }
1625
1626 if (!g_queue_is_empty (open_in_app_uris) && is_sandboxed ())
1627 {
1628 const char *uri;
1629 ApplicationLaunchAsyncParameters *async_params;
1630
1631 uri = g_queue_peek_head (open_in_app_uris);
1632
1633 async_params = g_new0 (ApplicationLaunchAsyncParameters, 1);
1634 async_params->activation_params = parameters;
1635 async_params->uris = g_steal_pointer (&open_in_app_uris);
1636
1637 nautilus_launch_default_for_uri_async (uri,
1638 parameters->parent_window,
1639 parameters->cancellable,
1640 launch_default_for_uris_callback,
1641 async_params);
1642 return;
1643 }
1644
1645 if (open_in_app_uris != NULL)
1646 {
1647 open_in_app_parameters = make_activation_parameters (g_queue_peek_head_link (open_in_app_uris),
1648 &unhandled_open_in_app_uris);
1649 }
1650
1651 num_apps = g_list_length (open_in_app_parameters);
1652 num_unhandled = g_list_length (unhandled_open_in_app_uris);
1653 num_files = g_queue_get_length (open_in_app_uris);
1654 open_files = TRUE;
1655
1656 if (!g_queue_is_empty (open_in_app_uris) &&
1657 (!parameters->user_confirmation ||
1658 num_files + num_unhandled > SILENT_OPEN_LIMIT) &&
1659 num_apps > 1)
1660 {
1661 GtkDialog *dialog;
1662 char *prompt;
1663 g_autofree char *detail = NULL;
1664 int response;
1665
1666 pause_activation_timed_cancel (parameters);
1667
1668 prompt = _("Are you sure you want to open all files?");
1669 /* TODO: Replace 'window' with 'application' after string freeze. */
1670 detail = g_strdup_printf (ngettext ("This will open %d separate window.",
1671 "This will open %d separate windows.", num_apps), num_apps);
1672 dialog = eel_show_yes_no_dialog (prompt, detail,
1673 _("_OK"), _("_Cancel"),
1674 parameters->parent_window);
1675 response = gtk_dialog_run (dialog);
1676 gtk_widget_destroy (GTK_WIDGET (dialog));
1677
1678 unpause_activation_timed_cancel (parameters);
1679
1680 if (response != GTK_RESPONSE_YES)
1681 {
1682 open_files = FALSE;
1683 }
1684 }
1685
1686 if (open_files)
1687 {
1688 for (l = open_in_app_parameters; l != NULL; l = l->next)
1689 {
1690 one_parameters = l->data;
1691
1692 nautilus_launch_application_by_uri (one_parameters->application,
1693 one_parameters->uris,
1694 parameters->parent_window);
1695 application_launch_parameters_free (one_parameters);
1696 }
1697
1698 for (l = unhandled_open_in_app_uris; l != NULL; l = l->next)
1699 {
1700 char *uri = l->data;
1701
1702 /* this does not block */
1703 application_unhandled_uri (parameters, uri);
1704 }
1705 }
1706
1707 activation_parameters_free (parameters);
1708 }
1709
1710 static void
activation_mount_not_mounted_callback(GObject * source_object,GAsyncResult * res,gpointer user_data)1711 activation_mount_not_mounted_callback (GObject *source_object,
1712 GAsyncResult *res,
1713 gpointer user_data)
1714 {
1715 ActivateParameters *parameters = user_data;
1716 GError *error;
1717 NautilusFile *file;
1718 LaunchLocation *loc;
1719
1720 file = parameters->not_mounted->data;
1721
1722 error = NULL;
1723 if (!g_file_mount_enclosing_volume_finish (G_FILE (source_object), res, &error))
1724 {
1725 if (error->domain != G_IO_ERROR ||
1726 (error->code != G_IO_ERROR_CANCELLED &&
1727 error->code != G_IO_ERROR_FAILED_HANDLED &&
1728 error->code != G_IO_ERROR_ALREADY_MOUNTED))
1729 {
1730 show_dialog (_("Unable to access location"),
1731 error->message,
1732 parameters->parent_window,
1733 GTK_MESSAGE_ERROR);
1734 }
1735
1736 if (error->domain != G_IO_ERROR ||
1737 error->code != G_IO_ERROR_ALREADY_MOUNTED)
1738 {
1739 loc = find_launch_location_for_file (parameters->locations,
1740 file);
1741 if (loc)
1742 {
1743 parameters->locations =
1744 g_list_remove (parameters->locations, loc);
1745 launch_location_free (loc);
1746 }
1747 }
1748
1749 g_error_free (error);
1750 }
1751
1752 parameters->not_mounted = g_list_delete_link (parameters->not_mounted,
1753 parameters->not_mounted);
1754 nautilus_file_unref (file);
1755
1756 activation_mount_not_mounted (parameters);
1757 }
1758
1759 static void
activation_mount_not_mounted(ActivateParameters * parameters)1760 activation_mount_not_mounted (ActivateParameters *parameters)
1761 {
1762 NautilusFile *file;
1763 GFile *location;
1764 LaunchLocation *loc;
1765 GMountOperation *mount_op;
1766 GList *l, *next, *files;
1767
1768 if (parameters->not_mounted != NULL)
1769 {
1770 file = parameters->not_mounted->data;
1771 mount_op = gtk_mount_operation_new (parameters->parent_window);
1772 g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
1773 g_signal_connect (mount_op, "notify::is-showing",
1774 G_CALLBACK (activate_mount_op_active), parameters);
1775 location = nautilus_file_get_location (file);
1776 g_file_mount_enclosing_volume (location, 0, mount_op, parameters->cancellable,
1777 activation_mount_not_mounted_callback, parameters);
1778 g_object_unref (location);
1779 /* unref mount_op here - g_file_mount_enclosing_volume() does ref for itself */
1780 g_object_unref (mount_op);
1781 return;
1782 }
1783
1784 parameters->tried_mounting = TRUE;
1785
1786 if (parameters->locations == NULL)
1787 {
1788 activation_parameters_free (parameters);
1789 return;
1790 }
1791
1792 /* once the mount is finished, refresh all attributes
1793 * - fixes new windows not appearing after successful mount
1794 */
1795 for (l = parameters->locations; l != NULL; l = next)
1796 {
1797 loc = l->data;
1798 next = l->next;
1799 nautilus_file_invalidate_all_attributes (loc->file);
1800 }
1801
1802 files = get_file_list_for_launch_locations (parameters->locations);
1803 nautilus_file_list_call_when_ready
1804 (files,
1805 nautilus_mime_actions_get_required_file_attributes (),
1806 ¶meters->files_handle,
1807 activate_callback, parameters);
1808 nautilus_file_list_free (files);
1809 }
1810
1811
1812 static void
activate_callback(GList * files,gpointer callback_data)1813 activate_callback (GList *files,
1814 gpointer callback_data)
1815 {
1816 ActivateParameters *parameters = callback_data;
1817 GList *l, *next;
1818 NautilusFile *file;
1819 LaunchLocation *location;
1820
1821 parameters->files_handle = NULL;
1822
1823 for (l = parameters->locations; l != NULL; l = next)
1824 {
1825 location = l->data;
1826 file = location->file;
1827 next = l->next;
1828
1829 if (file_was_cancelled (file))
1830 {
1831 launch_location_free (location);
1832 parameters->locations = g_list_delete_link (parameters->locations, l);
1833 continue;
1834 }
1835
1836 if (file_was_not_mounted (file))
1837 {
1838 if (parameters->tried_mounting)
1839 {
1840 launch_location_free (location);
1841 parameters->locations = g_list_delete_link (parameters->locations, l);
1842 }
1843 else
1844 {
1845 parameters->not_mounted = g_list_prepend (parameters->not_mounted,
1846 nautilus_file_ref (file));
1847 }
1848 continue;
1849 }
1850 }
1851
1852
1853 if (parameters->not_mounted != NULL)
1854 {
1855 activation_mount_not_mounted (parameters);
1856 }
1857 else
1858 {
1859 activate_files (parameters);
1860 }
1861 }
1862
1863 static void
activate_activation_uris_ready_callback(GList * files_ignore,gpointer callback_data)1864 activate_activation_uris_ready_callback (GList *files_ignore,
1865 gpointer callback_data)
1866 {
1867 ActivateParameters *parameters = callback_data;
1868 GList *l, *next, *files;
1869 NautilusFile *file;
1870 LaunchLocation *location;
1871
1872 parameters->files_handle = NULL;
1873
1874 for (l = parameters->locations; l != NULL; l = next)
1875 {
1876 location = l->data;
1877 file = location->file;
1878 next = l->next;
1879
1880 if (file_was_cancelled (file))
1881 {
1882 launch_location_free (location);
1883 parameters->locations = g_list_delete_link (parameters->locations, l);
1884 continue;
1885 }
1886
1887 if (nautilus_file_is_broken_symbolic_link (file))
1888 {
1889 launch_location_free (location);
1890 parameters->locations = g_list_delete_link (parameters->locations, l);
1891 pause_activation_timed_cancel (parameters);
1892 report_broken_symbolic_link (parameters->parent_window, file);
1893 unpause_activation_timed_cancel (parameters);
1894 continue;
1895 }
1896
1897 if (nautilus_file_get_file_type (file) == G_FILE_TYPE_MOUNTABLE &&
1898 !nautilus_file_has_activation_uri (file))
1899 {
1900 /* Don't launch these... There is nothing we
1901 * can do */
1902 launch_location_free (location);
1903 parameters->locations = g_list_delete_link (parameters->locations, l);
1904 continue;
1905 }
1906 }
1907
1908 if (parameters->locations == NULL)
1909 {
1910 activation_parameters_free (parameters);
1911 return;
1912 }
1913
1914 /* Convert the files to the actual activation uri files */
1915 for (l = parameters->locations; l != NULL; l = l->next)
1916 {
1917 char *uri;
1918 location = l->data;
1919
1920 /* We want the file for the activation URI since we care
1921 * about the attributes for that, not for the original file.
1922 */
1923 uri = nautilus_file_get_activation_uri (location->file);
1924 if (uri != NULL)
1925 {
1926 launch_location_update_from_uri (location, uri);
1927 }
1928 g_free (uri);
1929 }
1930
1931
1932 /* get the parameters for the actual files */
1933 files = get_file_list_for_launch_locations (parameters->locations);
1934 nautilus_file_list_call_when_ready
1935 (files,
1936 nautilus_mime_actions_get_required_file_attributes (),
1937 ¶meters->files_handle,
1938 activate_callback, parameters);
1939 nautilus_file_list_free (files);
1940 }
1941
1942 static void
activate_regular_files(ActivateParameters * parameters)1943 activate_regular_files (ActivateParameters *parameters)
1944 {
1945 GList *l, *files;
1946 NautilusFile *file;
1947 LaunchLocation *location;
1948
1949 /* link target info might be stale, re-read it */
1950 for (l = parameters->locations; l != NULL; l = l->next)
1951 {
1952 location = l->data;
1953 file = location->file;
1954
1955 if (file_was_cancelled (file))
1956 {
1957 launch_location_free (location);
1958 parameters->locations = g_list_delete_link (parameters->locations, l);
1959 continue;
1960 }
1961 }
1962
1963 if (parameters->locations == NULL)
1964 {
1965 activation_parameters_free (parameters);
1966 return;
1967 }
1968
1969 files = get_file_list_for_launch_locations (parameters->locations);
1970 nautilus_file_list_call_when_ready
1971 (files, nautilus_mime_actions_get_required_file_attributes (),
1972 ¶meters->files_handle,
1973 activate_activation_uris_ready_callback, parameters);
1974 nautilus_file_list_free (files);
1975 }
1976
1977 static void
activation_mountable_mounted(NautilusFile * file,GFile * result_location,GError * error,gpointer callback_data)1978 activation_mountable_mounted (NautilusFile *file,
1979 GFile *result_location,
1980 GError *error,
1981 gpointer callback_data)
1982 {
1983 ActivateParameters *parameters = callback_data;
1984 NautilusFile *target_file;
1985 LaunchLocation *location;
1986
1987 /* Remove from list of files that have to be mounted */
1988 parameters->mountables = g_list_remove (parameters->mountables, file);
1989 nautilus_file_unref (file);
1990
1991
1992 if (error == NULL)
1993 {
1994 /* Replace file with the result of the mount */
1995 target_file = nautilus_file_get (result_location);
1996
1997 location = find_launch_location_for_file (parameters->locations,
1998 file);
1999 if (location)
2000 {
2001 launch_location_update_from_file (location, target_file);
2002 }
2003 nautilus_file_unref (target_file);
2004 }
2005 else
2006 {
2007 /* Remove failed file */
2008
2009 if (error->domain != G_IO_ERROR ||
2010 (error->code != G_IO_ERROR_FAILED_HANDLED &&
2011 error->code != G_IO_ERROR_ALREADY_MOUNTED))
2012 {
2013 location = find_launch_location_for_file (parameters->locations,
2014 file);
2015 if (location)
2016 {
2017 parameters->locations =
2018 g_list_remove (parameters->locations,
2019 location);
2020 launch_location_free (location);
2021 }
2022 }
2023
2024 if (error->domain != G_IO_ERROR ||
2025 (error->code != G_IO_ERROR_CANCELLED &&
2026 error->code != G_IO_ERROR_FAILED_HANDLED &&
2027 error->code != G_IO_ERROR_ALREADY_MOUNTED))
2028 {
2029 show_dialog (_("Unable to access location"),
2030 error->message,
2031 parameters->parent_window,
2032 GTK_MESSAGE_ERROR);
2033 }
2034
2035 if (error->code == G_IO_ERROR_CANCELLED)
2036 {
2037 activation_parameters_free (parameters);
2038 return;
2039 }
2040 }
2041
2042 /* Mount more mountables */
2043 activation_mount_mountables (parameters);
2044 }
2045
2046
2047 static void
activation_mount_mountables(ActivateParameters * parameters)2048 activation_mount_mountables (ActivateParameters *parameters)
2049 {
2050 NautilusFile *file;
2051 GMountOperation *mount_op;
2052
2053 if (parameters->mountables != NULL)
2054 {
2055 file = parameters->mountables->data;
2056 mount_op = gtk_mount_operation_new (parameters->parent_window);
2057 g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
2058 g_signal_connect (mount_op, "notify::is-showing",
2059 G_CALLBACK (activate_mount_op_active), parameters);
2060 nautilus_file_mount (file,
2061 mount_op,
2062 parameters->cancellable,
2063 activation_mountable_mounted,
2064 parameters);
2065 g_object_unref (mount_op);
2066 return;
2067 }
2068
2069 if (parameters->mountables == NULL && parameters->start_mountables == NULL)
2070 {
2071 activate_regular_files (parameters);
2072 }
2073 }
2074
2075
2076 static void
activation_mountable_started(NautilusFile * file,GFile * gfile_of_file,GError * error,gpointer callback_data)2077 activation_mountable_started (NautilusFile *file,
2078 GFile *gfile_of_file,
2079 GError *error,
2080 gpointer callback_data)
2081 {
2082 ActivateParameters *parameters = callback_data;
2083 LaunchLocation *location;
2084
2085 /* Remove from list of files that have to be mounted */
2086 parameters->start_mountables = g_list_remove (parameters->start_mountables, file);
2087 nautilus_file_unref (file);
2088
2089 if (error == NULL)
2090 {
2091 /* Remove file */
2092 location = find_launch_location_for_file (parameters->locations, file);
2093 if (location != NULL)
2094 {
2095 parameters->locations = g_list_remove (parameters->locations, location);
2096 launch_location_free (location);
2097 }
2098 }
2099 else
2100 {
2101 /* Remove failed file */
2102 if (error->domain != G_IO_ERROR ||
2103 (error->code != G_IO_ERROR_FAILED_HANDLED))
2104 {
2105 location = find_launch_location_for_file (parameters->locations,
2106 file);
2107 if (location)
2108 {
2109 parameters->locations =
2110 g_list_remove (parameters->locations,
2111 location);
2112 launch_location_free (location);
2113 }
2114 }
2115
2116 if (error->domain != G_IO_ERROR ||
2117 (error->code != G_IO_ERROR_CANCELLED &&
2118 error->code != G_IO_ERROR_FAILED_HANDLED))
2119 {
2120 show_dialog (_("Unable to start location"),
2121 error->message,
2122 parameters->parent_window,
2123 GTK_MESSAGE_ERROR);
2124 }
2125
2126 if (error->code == G_IO_ERROR_CANCELLED)
2127 {
2128 activation_parameters_free (parameters);
2129 return;
2130 }
2131 }
2132
2133 /* Start more mountables */
2134 activation_start_mountables (parameters);
2135 }
2136
2137 static void
activation_start_mountables(ActivateParameters * parameters)2138 activation_start_mountables (ActivateParameters *parameters)
2139 {
2140 NautilusFile *file;
2141 GMountOperation *start_op;
2142
2143 if (parameters->start_mountables != NULL)
2144 {
2145 file = parameters->start_mountables->data;
2146 start_op = gtk_mount_operation_new (parameters->parent_window);
2147 g_signal_connect (start_op, "notify::is-showing",
2148 G_CALLBACK (activate_mount_op_active), parameters);
2149 nautilus_file_start (file,
2150 start_op,
2151 parameters->cancellable,
2152 activation_mountable_started,
2153 parameters);
2154 g_object_unref (start_op);
2155 return;
2156 }
2157
2158 if (parameters->mountables == NULL && parameters->start_mountables == NULL)
2159 {
2160 activate_regular_files (parameters);
2161 }
2162 }
2163
2164 /**
2165 * nautilus_mime_activate_files:
2166 *
2167 * Activate a list of files. Each one might launch with an application or
2168 * with a component. This is normally called only by subclasses.
2169 * @view: FMDirectoryView in question.
2170 * @files: A GList of NautilusFiles to activate.
2171 *
2172 **/
2173 void
nautilus_mime_activate_files(GtkWindow * parent_window,NautilusWindowSlot * slot,GList * files,const char * launch_directory,NautilusWindowOpenFlags flags,gboolean user_confirmation)2174 nautilus_mime_activate_files (GtkWindow *parent_window,
2175 NautilusWindowSlot *slot,
2176 GList *files,
2177 const char *launch_directory,
2178 NautilusWindowOpenFlags flags,
2179 gboolean user_confirmation)
2180 {
2181 ActivateParameters *parameters;
2182 char *file_name;
2183 int file_count;
2184 GList *l, *next;
2185 NautilusFile *file;
2186 LaunchLocation *location;
2187
2188 if (files == NULL)
2189 {
2190 return;
2191 }
2192
2193 DEBUG_FILES (files, "Calling activate_files() with files:");
2194
2195 parameters = g_new0 (ActivateParameters, 1);
2196 parameters->slot = slot;
2197 g_object_add_weak_pointer (G_OBJECT (parameters->slot), (gpointer *) ¶meters->slot);
2198 if (parent_window)
2199 {
2200 parameters->parent_window = parent_window;
2201 g_object_add_weak_pointer (G_OBJECT (parameters->parent_window), (gpointer *) ¶meters->parent_window);
2202 }
2203 parameters->cancellable = g_cancellable_new ();
2204 parameters->activation_directory = g_strdup (launch_directory);
2205 parameters->locations = launch_locations_from_file_list (files);
2206 parameters->flags = flags;
2207 parameters->user_confirmation = user_confirmation;
2208
2209 file_count = g_list_length (files);
2210 if (file_count == 1)
2211 {
2212 file_name = nautilus_file_get_display_name (files->data);
2213 parameters->timed_wait_prompt = g_strdup_printf (_("Opening “%s”."), file_name);
2214 g_free (file_name);
2215 }
2216 else
2217 {
2218 parameters->timed_wait_prompt = g_strdup_printf (ngettext ("Opening %d item.",
2219 "Opening %d items.",
2220 file_count),
2221 file_count);
2222 }
2223
2224
2225 for (l = parameters->locations; l != NULL; l = next)
2226 {
2227 location = l->data;
2228 file = location->file;
2229 next = l->next;
2230
2231 if (nautilus_file_can_mount (file))
2232 {
2233 parameters->mountables = g_list_prepend (parameters->mountables,
2234 nautilus_file_ref (file));
2235 }
2236
2237 if (nautilus_file_can_start (file))
2238 {
2239 parameters->start_mountables = g_list_prepend (parameters->start_mountables,
2240 nautilus_file_ref (file));
2241 }
2242 }
2243
2244 activation_start_timed_cancel (parameters);
2245 if (parameters->mountables != NULL)
2246 {
2247 activation_mount_mountables (parameters);
2248 }
2249 if (parameters->start_mountables != NULL)
2250 {
2251 activation_start_mountables (parameters);
2252 }
2253 if (parameters->mountables == NULL && parameters->start_mountables == NULL)
2254 {
2255 activate_regular_files (parameters);
2256 }
2257 }
2258
2259 /**
2260 * nautilus_mime_activate_file:
2261 *
2262 * Activate a file in this view. This might involve switching the displayed
2263 * location for the current window, or launching an application.
2264 * @view: FMDirectoryView in question.
2265 * @file: A NautilusFile representing the file in this view to activate.
2266 * @use_new_window: Should this item be opened in a new window?
2267 *
2268 **/
2269
2270 void
nautilus_mime_activate_file(GtkWindow * parent_window,NautilusWindowSlot * slot,NautilusFile * file,const char * launch_directory,NautilusWindowOpenFlags flags)2271 nautilus_mime_activate_file (GtkWindow *parent_window,
2272 NautilusWindowSlot *slot,
2273 NautilusFile *file,
2274 const char *launch_directory,
2275 NautilusWindowOpenFlags flags)
2276 {
2277 GList *files;
2278
2279 g_return_if_fail (NAUTILUS_IS_FILE (file));
2280
2281 files = g_list_prepend (NULL, file);
2282 nautilus_mime_activate_files (parent_window, slot, files, launch_directory, flags, FALSE);
2283 g_list_free (files);
2284 }
2285
2286 gint
nautilus_mime_types_get_number_of_groups(void)2287 nautilus_mime_types_get_number_of_groups (void)
2288 {
2289 return G_N_ELEMENTS (mimetype_groups);
2290 }
2291
2292 const gchar *
nautilus_mime_types_group_get_name(gint group_index)2293 nautilus_mime_types_group_get_name (gint group_index)
2294 {
2295 g_return_val_if_fail (group_index < G_N_ELEMENTS (mimetype_groups), NULL);
2296
2297 return gettext (mimetype_groups[group_index].name);
2298 }
2299
2300 GPtrArray *
nautilus_mime_types_group_get_mimetypes(gint group_index)2301 nautilus_mime_types_group_get_mimetypes (gint group_index)
2302 {
2303 GStrv group;
2304 GPtrArray *mimetypes;
2305
2306 g_return_val_if_fail (group_index < G_N_ELEMENTS (mimetype_groups), NULL);
2307
2308 group = mimetype_groups[group_index].mimetypes;
2309 mimetypes = g_ptr_array_new_full (g_strv_length (group), g_free);
2310
2311 /* Setup the new mimetypes set */
2312 for (gint i = 0; group[i] != NULL; i++)
2313 {
2314 g_ptr_array_add (mimetypes, g_strdup (group[i]));
2315 }
2316
2317 return mimetypes;
2318 }
2319