diff options
Diffstat (limited to 'lib/ephy-file-helpers.c')
-rw-r--r-- | lib/ephy-file-helpers.c | 708 |
1 files changed, 111 insertions, 597 deletions
diff --git a/lib/ephy-file-helpers.c b/lib/ephy-file-helpers.c index 8fb7b4970..65b74db8b 100644 --- a/lib/ephy-file-helpers.c +++ b/lib/ephy-file-helpers.c @@ -27,26 +27,22 @@ #include "ephy-prefs.h" #include "eel-gconf-extensions.h" +#include "eel-app-launch-context.h" #include "ephy-debug.h" +#include "ephy-string.h" #include <glib.h> #include <glib/gi18n.h> +#include <gio/gio.h> +#include <gio/gdesktopappinfo.h> #include <libgnome/gnome-init.h> -#include <libgnomevfs/gnome-vfs-utils.h> -#include <libgnomevfs/gnome-vfs-file-info.h> -#include <libgnomevfs/gnome-vfs-ops.h> -#include <libgnomevfs/gnome-vfs-directory.h> -#include <libgnomevfs/gnome-vfs-xfer.h> #include <libxml/xmlreader.h> /* bug http://bugzilla.gnome.org/show_bug.cgi?id=156687 */ #undef GNOME_DISABLE_DEPRECATED #include <libgnome/gnome-desktop-item.h> -#define SN_API_NOT_YET_FROZEN -#include <libsn/sn.h> #include <gdk/gdk.h> -#include <gdk/gdkx.h> #include <gtk/gtkrecentmanager.h> #include <string.h> @@ -162,7 +158,7 @@ ephy_file_get_downloads_dir (void) g_return_val_if_fail (download_dir != NULL, NULL); - expanded = gnome_vfs_expand_initial_tilde (download_dir); + expanded = ephy_string_expand_initial_tilde (download_dir); g_free (download_dir); return expanded; @@ -433,35 +429,46 @@ ephy_file_find (const char *path, } gboolean -ephy_file_switch_temp_file (const char *filename, - const char *filename_temp) +ephy_file_switch_temp_file (GFile *file, + GFile *file_temp) { - char *old_file; + char *file_path, *file_temp_path; + char *old_file_path; gboolean old_exist; gboolean retval = TRUE; + GFile *old_file; - old_file = g_strconcat (filename, ".old", NULL); + file_path = g_file_get_path (file); + file_temp_path = g_file_get_path (file_temp); + old_file_path = g_strconcat (file_path, ".old", NULL); - old_exist = g_file_test (filename, G_FILE_TEST_EXISTS); + old_file = g_file_new_for_path (old_file_path); + old_exist = g_file_test (file_path, G_FILE_TEST_EXISTS); if (old_exist) { - if (rename (filename, old_file) < 0) + if (g_file_move (file, old_file, + G_FILE_COPY_OVERWRITE, + NULL, NULL, NULL, NULL) == FALSE) { - g_warning ("Failed to rename %s to %s", filename, old_file); + g_warning ("Failed to rename %s to %s", file_path, old_file_path); retval = FALSE; goto failed; } } - if (rename (filename_temp, filename) < 0) + if (g_file_move (file_temp, file, + G_FILE_COPY_OVERWRITE, + NULL, NULL, NULL, NULL) == FALSE) { - g_warning ("Failed to rename %s to %s", filename_temp, filename); + g_warning ("Failed to rename %s to %s", file_temp_path, file_path); - if (rename (old_file, filename) < 0) + if (g_file_move (old_file, file, + G_FILE_COPY_OVERWRITE, + NULL, NULL, NULL, NULL) == FALSE) { g_warning ("Failed to restore %s from %s", - filename, filename_temp); + file_path, file_temp_path); } retval = FALSE; goto failed; @@ -469,20 +476,24 @@ ephy_file_switch_temp_file (const char *filename, if (old_exist) { - if (unlink (old_file) < 0) + if (g_file_delete (old_file, + NULL, NULL) == FALSE) { - g_warning ("Failed to delete old file %s", old_file); + g_warning ("Failed to delete old file %s", old_file_path); } } failed: - g_free (old_file); + g_free (old_file_path); + g_free (file_path); + g_free (file_temp_path); + g_object_unref (old_file); return retval; } void -ephy_file_delete_on_exit (const char *path) +ephy_file_delete_on_exit (GFile *file) { /* does nothing now */ } @@ -583,441 +594,110 @@ ephy_file_check_mime (const char *mime_type) return permission; } -/* Copied from nautilus-program-choosing.c */ - -extern char **environ; - -/* Cut and paste from gdkspawn-x11.c */ -static gchar ** -my_gdk_spawn_make_environment_for_screen (GdkScreen *screen, - gchar **envp) -{ - gchar **retval = NULL; - gchar *display_name; - gint i, j = 0, env_len; - - g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); - - if (envp == NULL) - envp = environ; - - env_len = g_strv_length (envp); - retval = g_new (char *, env_len + 3); - - display_name = gdk_screen_make_display_name (screen); - - for (i = 0; envp[i] != NULL; i++) - if (!g_str_has_prefix (envp[i], "DISPLAY=") && - !g_str_has_prefix (envp[i], EPHY_UUID_ENVVAR "=")) - retval[j++] = g_strdup (envp[i]); - - retval[j++] = g_strconcat ("DISPLAY=", display_name, NULL); - retval[j++] = g_strdup (EPHY_UUID_ENVSTRING); - retval[j] = NULL; - - g_free (display_name); - - return retval; -} - -static void -sn_error_trap_push (SnDisplay *display, - Display *xdisplay) -{ - gdk_error_trap_push (); -} - -static void -sn_error_trap_pop (SnDisplay *display, - Display *xdisplay) -{ - gdk_error_trap_pop (); -} - -static char ** -make_spawn_environment_for_sn_context (SnLauncherContext *sn_context, - char **envp) -{ - char **retval; - int i, j, len; - - retval = NULL; - - if (envp == NULL) { - envp = environ; - } - - len = g_strv_length (envp); - retval = g_new (char *, len + 3); - - for (i = 0, j = 0; envp[i] != NULL; i++) { - if (!g_str_has_prefix (envp[i], "DESKTOP_STARTUP_ID=") && - !g_str_has_prefix (envp[i], EPHY_UUID_ENVVAR "=")) { - retval[j++] = g_strdup (envp[i]); - } - } - - retval[j++] = g_strdup_printf ("DESKTOP_STARTUP_ID=%s", - sn_launcher_context_get_startup_id (sn_context)); - retval[j++] = g_strdup (EPHY_UUID_ENVSTRING); - retval[j] = NULL; - - return retval; -} - -/* This should be fairly long, as it's confusing to users if a startup - * ends when it shouldn't (it appears that the startup failed, and - * they have to relaunch the app). Also the timeout only matters when - * there are bugs and apps don't end their own startup sequence. - * - * This timeout is a "last resort" timeout that ignores whether the - * startup sequence has shown activity or not. Metacity and the - * tasklist have smarter, and correspondingly able-to-be-shorter - * timeouts. The reason our timeout is dumb is that we don't monitor - * the sequence (don't use an SnMonitorContext) - */ -#define STARTUP_TIMEOUT_LENGTH (30 /* seconds */ * 1000) - -typedef struct -{ - GdkScreen *screen; - GSList *contexts; - guint timeout_id; -} StartupTimeoutData; - -static void -free_startup_timeout (void *data) -{ - StartupTimeoutData *std; - - std = data; - - g_slist_foreach (std->contexts, - (GFunc) sn_launcher_context_unref, - NULL); - g_slist_free (std->contexts); - - if (std->timeout_id != 0) { - g_source_remove (std->timeout_id); - std->timeout_id = 0; - } - - g_free (std); -} - -static gboolean -startup_timeout (void *data) -{ - StartupTimeoutData *std; - GSList *tmp; - GTimeVal now; - int min_timeout; - - std = data; - - min_timeout = STARTUP_TIMEOUT_LENGTH; - - g_get_current_time (&now); - - tmp = std->contexts; - while (tmp != NULL) { - SnLauncherContext *sn_context; - GSList *next; - long tv_sec, tv_usec; - double elapsed; - - sn_context = tmp->data; - next = tmp->next; - - sn_launcher_context_get_last_active_time (sn_context, - &tv_sec, &tv_usec); - - elapsed = - ((((double)now.tv_sec - tv_sec) * G_USEC_PER_SEC + - (now.tv_usec - tv_usec))) / 1000.0; - - if (elapsed >= STARTUP_TIMEOUT_LENGTH) { - std->contexts = g_slist_remove (std->contexts, - sn_context); - sn_launcher_context_complete (sn_context); - sn_launcher_context_unref (sn_context); - } else { - min_timeout = MIN (min_timeout, (STARTUP_TIMEOUT_LENGTH - elapsed)); - } - - tmp = next; - } - - if (std->contexts == NULL) { - std->timeout_id = 0; - } else { - std->timeout_id = g_timeout_add (min_timeout, - startup_timeout, - std); - } - - /* always remove this one, but we may have reinstalled another one. */ - return FALSE; -} - -static void -add_startup_timeout (GdkScreen *screen, - SnLauncherContext *sn_context) -{ - StartupTimeoutData *data; - - data = g_object_get_data (G_OBJECT (screen), "nautilus-startup-data"); - if (data == NULL) { - data = g_new (StartupTimeoutData, 1); - data->screen = screen; - data->contexts = NULL; - data->timeout_id = 0; - - g_object_set_data_full (G_OBJECT (screen), "nautilus-startup-data", - data, free_startup_timeout); - } - - sn_launcher_context_ref (sn_context); - data->contexts = g_slist_prepend (data->contexts, sn_context); - - if (data->timeout_id == 0) { - data->timeout_id = g_timeout_add (STARTUP_TIMEOUT_LENGTH, - startup_timeout, - data); - } -} - gboolean -ephy_file_launch_application (GnomeVFSMimeApplication *application, - const char *parameter, - guint32 user_time) +ephy_file_launch_application (GAppInfo *app, + GList *files, + guint32 user_time, + GtkWidget *widget) { - GdkScreen *screen; - GList *uris = NULL; - char *uri; - char **envp; - GnomeVFSResult result; - SnLauncherContext *sn_context; - SnDisplay *sn_display; - - g_return_val_if_fail (application != NULL, FALSE); - g_return_val_if_fail (parameter != NULL, FALSE); - - uri = gnome_vfs_make_uri_canonical (parameter); - if (uri == NULL) return FALSE; - - uris = g_list_prepend (NULL, uri); - - /* FIXME multihead! */ - screen = gdk_screen_get_default (); - envp = my_gdk_spawn_make_environment_for_screen (screen, NULL); - - sn_display = sn_display_new (gdk_display, - sn_error_trap_push, - sn_error_trap_pop); - + GAppLaunchContext *context; + GdkDisplay *display; + GdkScreen *screen; - /* Only initiate notification if application supports it. */ - if (gnome_vfs_mime_application_supports_startup_notification (application)) + context = G_APP_LAUNCH_CONTEXT (eel_app_launch_context_new ()); + if (widget) { - char *name; - - sn_context = sn_launcher_context_new (sn_display, - screen ? gdk_screen_get_number (screen) : - DefaultScreen (gdk_display)); - - name = g_filename_display_basename (uri); - if (name != NULL) { - char *description; - - sn_launcher_context_set_name (sn_context, name); - - /* FIXME: i18n after string freeze! */ - description = g_strdup_printf ("Opening %s", name); - - sn_launcher_context_set_description (sn_context, description); - - g_free (name); - g_free (description); - } - - if (!sn_launcher_context_get_initiated (sn_context)) { - const char *binary_name; - char **old_envp; - - binary_name = gnome_vfs_mime_application_get_binary_name (application); - - sn_launcher_context_set_binary_name (sn_context, - binary_name); - - sn_launcher_context_initiate (sn_context, - g_get_prgname () ? g_get_prgname () : "unknown", - binary_name, - (Time) user_time); - - old_envp = envp; - envp = make_spawn_environment_for_sn_context (sn_context, envp); - g_strfreev (old_envp); - } - } else { - sn_context = NULL; - } - - result = gnome_vfs_mime_application_launch_with_env (application, uris, envp); - - if (sn_context != NULL) { - if (result != GNOME_VFS_OK) { - sn_launcher_context_complete (sn_context); /* end sequence */ - } else { - add_startup_timeout (screen ? screen : - gdk_display_get_default_screen (gdk_display_get_default ()), - sn_context); - } - sn_launcher_context_unref (sn_context); + display = gtk_widget_get_display (widget); + screen = gtk_widget_get_screen (widget); } - - sn_display_unref (sn_display); - - g_strfreev (envp); - g_list_foreach (uris, (GFunc) g_free,NULL); - g_list_free (uris); - - if (result != GNOME_VFS_OK) + else { - g_warning ("Cannot launch application '%s'\n", - gnome_vfs_mime_application_get_name (application)); + display = gdk_display_get_default (); + screen = gdk_screen_get_default (); } - - return result == GNOME_VFS_OK; -} - -/* End cut-paste-adapt from nautilus */ - -static int -launch_desktop_item (const char *desktop_file, - const char *parameter, - guint32 user_time, - GError **error) -{ - GnomeDesktopItem *item = NULL; - GdkScreen *screen; - GList *uris = NULL; - char *canonical; - int ret = -1; - char **envp; - /* FIXME multihead! */ - screen = gdk_screen_get_default (); - envp = my_gdk_spawn_make_environment_for_screen (screen, NULL); - - item = gnome_desktop_item_new_from_file (desktop_file, 0, NULL); - if (item == NULL) return FALSE; - - if (parameter != NULL) - { - canonical = gnome_vfs_make_uri_canonical (parameter); - uris = g_list_append (uris, canonical); - } - - gnome_desktop_item_set_launch_time (item, user_time); - ret = gnome_desktop_item_launch_with_env (item, uris, 0, envp, error); - - g_list_foreach (uris, (GFunc) g_free, NULL); - g_list_free (uris); - g_strfreev (envp); - gnome_desktop_item_unref (item); - - return ret; + eel_app_launch_context_set_display (EEL_APP_LAUNCH_CONTEXT (context), + display); + eel_app_launch_context_set_screen (EEL_APP_LAUNCH_CONTEXT (context), + screen); + eel_app_launch_context_set_timestamp (EEL_APP_LAUNCH_CONTEXT (context), + user_time); + + return g_app_info_launch (app, files, context, NULL); } gboolean ephy_file_launch_desktop_file (const char *filename, const char *parameter, - guint32 user_time) + guint32 user_time, + GtkWidget *widget) { - GError *error = NULL; - const char * const *dirs; - char *path = NULL; - int i, ret = -1; - - dirs = g_get_system_data_dirs (); - if (dirs == NULL) return FALSE; - - for (i = 0; dirs[i] != NULL; i++) - { - path = g_build_filename (dirs[i], "applications", filename, NULL); - - if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) break; - - g_free (path); - path = NULL; - } - - if (path != NULL) - { - ret = launch_desktop_item (path, parameter, user_time, &error); - - if (ret == -1 || error != NULL) - { - g_warning ("Cannot launch desktop item '%s': %s\n", - path, error ? error->message : "(unknown error)"); - g_clear_error (&error); - } - - g_free (path); - } + GDesktopAppInfo *app; + GFile *file; + GList *list = NULL; + gboolean ret; - return ret >= 0; + app = g_desktop_app_info_new (filename); + file = g_file_new_for_path (parameter); + list = g_list_append (list, file); + + ret = ephy_file_launch_application (G_APP_INFO (app), list, user_time, widget); + g_list_free (list); + g_object_unref (file); + return ret; } gboolean ephy_file_launch_handler (const char *mime_type, - const char *address, + GFile *file, guint32 user_time) { - GnomeVFSMimeApplication *app = NULL; - GnomeVFSFileInfo *info = NULL; - char *canonical; + GAppInfo *app = NULL; gboolean ret = FALSE; - g_return_val_if_fail (address != NULL, FALSE); - - canonical = gnome_vfs_make_uri_canonical (address); - if (canonical == NULL) return FALSE; + g_return_val_if_fail (file != NULL, FALSE); if (mime_type != NULL) { - app = gnome_vfs_mime_get_default_application (mime_type); + app = g_app_info_get_default_for_type (mime_type, + FALSE); } else { + GFileInfo *file_info; + char *type; + /* Sniff mime type and check if it's safe to open */ - info = gnome_vfs_file_info_new (); - if (gnome_vfs_get_file_info (canonical, info, - GNOME_VFS_FILE_INFO_GET_MIME_TYPE | - GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE) == GNOME_VFS_OK && - (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE) && - info->mime_type != NULL && - info->mime_type[0] != '\0' && - ephy_file_check_mime (info->mime_type) == EPHY_MIME_PERMISSION_SAFE) + file_info = g_file_query_info (file, + G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, + 0, NULL, NULL); + if (file_info == NULL) { + return FALSE; + } + type = g_strdup (g_file_info_get_content_type (file_info)); + + g_object_unref (file_info); + + if (type != NULL && type[0] != '\0' && + ephy_file_check_mime (type) == EPHY_MIME_PERMISSION_SAFE) { /* FIXME rename tmp file to right extension ? */ - app = gnome_vfs_mime_get_default_application (info->mime_type); + app = g_app_info_get_default_for_type (type, FALSE); } - gnome_vfs_file_info_unref (info); + g_free (type); } if (app != NULL) { - ret = ephy_file_launch_application (app, address, user_time); - - gnome_vfs_mime_application_free (app); + GList *list = NULL; + + list = g_list_append (list, file); + ret = ephy_file_launch_application (app, list, user_time, NULL); + g_list_free (list); } else ret = FALSE; - g_free (canonical); - return ret; } @@ -1025,197 +705,34 @@ gboolean ephy_file_browse_to (const char *parameter, guint32 user_time) { - GnomeVFSURI *uri, *parent_uri, *desktop; + GFile *file, *parent, *desktop; char *desktop_dir; gboolean ret; - uri = gnome_vfs_uri_new (parameter); - parent_uri = gnome_vfs_uri_get_parent (uri); - + file = g_file_new_for_path (parameter); desktop_dir = ephy_file_desktop_dir (); - desktop = gnome_vfs_uri_new (desktop_dir); + desktop = g_file_new_for_path (desktop_dir); /* Don't do anything if destination is the desktop */ - if (gnome_vfs_uri_equal (desktop, parent_uri)) + if (g_file_contains_file (desktop, file)) { ret = FALSE; } else { + parent = g_file_get_parent (file); /* TODO find a way to make nautilus scroll to the actual file */ ret = ephy_file_launch_handler ("x-directory/normal", - gnome_vfs_uri_get_path (parent_uri), + parent, user_time); } g_free (desktop_dir); - gnome_vfs_uri_unref (uri); - gnome_vfs_uri_unref (parent_uri); - gnome_vfs_uri_unref (desktop); + g_object_unref (file); return ret; } -struct _EphyFileMonitor -{ - GnomeVFSMonitorHandle *handle; - EphyFileMonitorFunc callback; - EphyFileMonitorDelayFunc delay_func; - gpointer user_data; - char *uri; - guint delay; - guint timeout_id; - guint ticks; - GnomeVFSMonitorEventType type; -}; - -static gboolean -ephy_file_monitor_timeout_cb (EphyFileMonitor *monitor) -{ - if (monitor->ticks > 0) - { - monitor->ticks--; - - /* Run again */ - return TRUE; - } - - if (monitor->delay_func && - monitor->delay_func (monitor, monitor->user_data)) - { - monitor->ticks = DELAY_MAX_TICKS / 2; - - /* Run again */ - return TRUE; - } - - monitor->timeout_id = 0; - - monitor->callback (monitor, monitor->uri, monitor->type, monitor->user_data); - - /* don't run again */ - return FALSE; -} - -static void -ephy_file_monitor_cb (GnomeVFSMonitorHandle *handle, - const char *monitor_uri, - const char *info_uri, - GnomeVFSMonitorEventType event_type, - EphyFileMonitor *monitor) -{ - LOG ("File '%s' has changed, scheduling reload", monitor_uri); - - switch (event_type) - { - case GNOME_VFS_MONITOR_EVENT_CHANGED: - monitor->ticks = INITIAL_TICKS; - /* fall-through */ - case GNOME_VFS_MONITOR_EVENT_CREATED: - /* We make a lot of assumptions here, but basically we know - * that we just have to reload, by construction. - * Delay the reload a little bit so we don't endlessly - * reload while a file is written. - */ - monitor->type = event_type; - - if (monitor->ticks == 0) - { - monitor->ticks = 1; - } - else - { - /* Exponential backoff */ - monitor->ticks = MIN (monitor->ticks * 2, - DELAY_MAX_TICKS); - } - - if (monitor->timeout_id == 0) - { - monitor->timeout_id = - g_timeout_add (monitor->delay, - (GSourceFunc) ephy_file_monitor_timeout_cb, - monitor); - } - - break; - - case GNOME_VFS_MONITOR_EVENT_DELETED: - if (monitor->timeout_id != 0) - { - g_source_remove (monitor->timeout_id); - monitor->timeout_id = 0; - } - monitor->ticks = 0; - - monitor->callback (monitor, monitor->uri, event_type, monitor->user_data); - break; - case GNOME_VFS_MONITOR_EVENT_STARTEXECUTING: - case GNOME_VFS_MONITOR_EVENT_STOPEXECUTING: - case GNOME_VFS_MONITOR_EVENT_METADATA_CHANGED: - default: - break; - } -} - -EphyFileMonitor * -ephy_file_monitor_add (const char *uri, - GnomeVFSMonitorType monitor_type, - guint delay, - EphyFileMonitorFunc callback, - EphyFileMonitorDelayFunc delay_func, - gpointer user_data) -{ - EphyFileMonitor *monitor; - - g_return_val_if_fail (uri != NULL, NULL); - g_return_val_if_fail (callback, NULL); - - monitor = g_new (EphyFileMonitor, 1); - monitor->callback = callback; - monitor->delay_func = delay_func; - monitor->user_data = user_data; - monitor->uri = g_strdup (uri); - monitor->delay = delay; - monitor->ticks = 0; - monitor->timeout_id = 0; - - if (gnome_vfs_monitor_add (&monitor->handle, uri, monitor_type, - (GnomeVFSMonitorCallback) ephy_file_monitor_cb, - monitor) != GNOME_VFS_OK) - { - LOG ("Failed to add file monitor for '%s'", uri); - - g_free (monitor->uri); - g_free (monitor); - return NULL; - } - - LOG ("File monitor for '%s' added", uri); - - return monitor; -} - -void -ephy_file_monitor_cancel (EphyFileMonitor *monitor) -{ - g_return_if_fail (monitor != NULL); - g_return_if_fail (monitor->handle != NULL); - g_return_if_fail (monitor->uri != NULL); - - LOG ("Cancelling file monitor for '%s'", monitor->uri); - - gnome_vfs_monitor_cancel (monitor->handle); - - if (monitor->timeout_id != 0) - { - g_source_remove (monitor->timeout_id); - } - - g_free (monitor->uri); - g_free (monitor); -} - /** * ephy_file_delete_directory: * @path: the path to remove @@ -1226,18 +743,14 @@ ephy_file_monitor_cancel (EphyFileMonitor *monitor) void ephy_file_delete_directory (const char *path) { - GList *list; - GnomeVFSResult ret; - - list = g_list_append (NULL, gnome_vfs_uri_new (path)); + GFile *file; + gboolean ret; - ret = gnome_vfs_xfer_delete_list (list, GNOME_VFS_XFER_ERROR_MODE_ABORT, - GNOME_VFS_XFER_EMPTY_DIRECTORIES, - NULL, NULL); + file = g_file_new_for_path (path); - gnome_vfs_uri_list_free (list); + ret = g_file_delete (file, NULL, NULL); - if (ret == GNOME_VFS_OK) + if (ret == TRUE) { LOG ("Deleted the profile dir '%s'", path); } @@ -1245,4 +758,5 @@ ephy_file_delete_directory (const char *path) { LOG ("Couldn't delete profile dir '%s'", path); } + g_object_unref (file); } |