mime-actions: use file metadata for trusting desktop files

Currently we only trust desktop files that have the executable bit
set, and don't replace the displayed icon or the displayed name until
it's trusted, which prevents for running random programs by a malicious
desktop file.

However, the executable permission is preserved if the desktop file
comes from a compressed file.

To prevent this, add a metadata::trusted metadata to the file once the
user acknowledges the file as trusted. This adds metadata to the file,
which cannot be added unless it has access to the computer.

Also remove the SHEBANG "trusted" content we were putting inside the
desktop file, since that doesn't add more security since it can come
with the file itself.

https://bugzilla.gnome.org/show_bug.cgi?id=777991
nautilus_directory_call_when_ready_internal (NautilusDirectory         *directory,
                                             NautilusFile              *file,
                                             NautilusFileAttributes     file_attributes,
                                             gboolean                   wait_for_file_list,
                                             NautilusDirectoryCallback  directory_callback,
                                             NautilusFileCallback       file_callback,
                                             gpointer                   callback_data)
{
    ReadyCallback callback;

    g_assert (directory == NULL || NAUTILUS_IS_DIRECTORY (directory));
    g_assert (file == NULL || NAUTILUS_IS_FILE (file));
    g_assert (file != NULL || directory_callback != NULL);

    /* Construct a callback object. */
    callback.active = TRUE;
    callback.file = file;
    if (file == NULL)
    {
        callback.callback.directory = directory_callback;
    }
    else
    {
        callback.callback.file = file_callback;
    }
    callback.callback_data = callback_data;
    callback.request = nautilus_directory_set_up_request (file_attributes);
    if (wait_for_file_list)
    {
        REQUEST_SET_TYPE (callback.request, REQUEST_FILE_LIST);
    }

    /* Handle the NULL case. */
    if (directory == NULL)
    {
        ready_callback_call (NULL, &callback);
        return;
    }

    /* Check if the callback is already there. */
    if (g_list_find_custom (directory->details->call_when_ready_list,
                            &callback,
                            ready_callback_key_compare_only_active) != NULL)
    {
        if (file_callback != NULL && directory_callback != NULL)
        {
            g_warning ("tried to add a new callback while an old one was pending");
        }
        /* NULL callback means, just read it. Conflicts are ok. */
        return;
    }

    /* Add the new callback to the list. */
    directory->details->call_when_ready_list = g_list_prepend
                                                   (directory->details->call_when_ready_list,
                                                   g_memdup (&callback, sizeof (callback)));
    request_counter_add_request (directory->details->call_when_ready_counters,
                                 callback.request);

    /* Put the callback file or all the files on the work queue. */
    if (file != NULL)
    {
        nautilus_directory_add_file_to_work_queue (directory, file);
    }
    else
    {
        add_all_files_to_work_queue (directory);
    }

    nautilus_directory_async_state_changed (directory);
}

nautilus_directory_call_when_ready_internal (NautilusDirectory         *directory,
                                             NautilusFile              *file,
                                             NautilusFileAttributes     file_attributes,
                                             gboolean                   wait_for_file_list,
                                             NautilusDirectoryCallback  directory_callback,
                                             NautilusFileCallback       file_callback,
                                             gpointer                   callback_data)
{
    ReadyCallback callback;

    g_assert (directory == NULL || NAUTILUS_IS_DIRECTORY (directory));
    g_assert (file == NULL || NAUTILUS_IS_FILE (file));
    g_assert (file != NULL || directory_callback != NULL);

    /* Construct a callback object. */
    callback.active = TRUE;
    callback.file = file;
    if (file == NULL)
    {
        callback.callback.directory = directory_callback;
    }
    else
    {
        callback.callback.file = file_callback;
    }
    callback.callback_data = callback_data;
    callback.request = nautilus_directory_set_up_request (file_attributes);
    if (wait_for_file_list)
    {
        REQUEST_SET_TYPE (callback.request, REQUEST_FILE_LIST);
    }

    /* Handle the NULL case. */
    if (directory == NULL)
    {
        ready_callback_call (NULL, &callback);
        return;
    }

    /* Check if the callback is already there. */
    if (g_list_find_custom (directory->details->call_when_ready_list,
                            &callback,
                            ready_callback_key_compare_only_active) != NULL)
    {
        if (file_callback != NULL && directory_callback != NULL)
        {
            g_warning ("tried to add a new callback while an old one was pending");
        }
        /* NULL callback means, just read it. Conflicts are ok. */
        return;
    }

    /* Add the new callback to the list. */
    directory->details->call_when_ready_list = g_list_prepend
                                                   (directory->details->call_when_ready_list,
                                                   g_memdup (&callback, sizeof (callback)));
    request_counter_add_request (directory->details->call_when_ready_counters,
                                 callback.request);

    /* Put the callback file or all the files on the work queue. */
    if (file != NULL)
    {
        nautilus_directory_add_file_to_work_queue (directory, file);
    }
    else
    {
        add_all_files_to_work_queue (directory);
    }

    nautilus_directory_async_state_changed (directory);
}
