diff options
author | Ondrej Holy <oholy@redhat.com> | 2021-02-01 14:28:45 +0100 |
---|---|---|
committer | Ondrej Holy <oholy@redhat.com> | 2021-02-12 14:48:02 +0100 |
commit | 5fa777ddc6dafc71e72f499fd699f508a711924c (patch) | |
tree | 6ef1e079da320b2c3957616bca3858ed5605fcda | |
parent | c01cc21c3b3a1f2223dd70ca0633580728d3bcf3 (diff) | |
download | gvfs-5fa777ddc6dafc71e72f499fd699f508a711924c.tar.gz |
google: Add Shared drives folder
Currently, it is not possible to browse files available over Shared drives
(formerly Team drives). Let's add Shared drives folder to the root to make
them available.
Fixes: https://gitlab.gnome.org/GNOME/gvfs/-/issues/377
-rw-r--r-- | daemon/gvfsbackendgoogle.c | 159 |
1 files changed, 146 insertions, 13 deletions
diff --git a/daemon/gvfsbackendgoogle.c b/daemon/gvfsbackendgoogle.c index 8a5cf415..27c95f27 100644 --- a/daemon/gvfsbackendgoogle.c +++ b/daemon/gvfsbackendgoogle.c @@ -58,11 +58,13 @@ struct _GVfsBackendGoogle GDataEntry *root; GDataEntry *home; GDataEntry *shared_with_me_dir; + GDataEntry *shared_drives_dir; GHashTable *entries; /* gchar *entry_id -> GDataEntry */ GHashTable *dir_entries; /* DirEntriesKey -> GDataEntry */ GHashTable *dir_timestamps; /* gchar *entry_id -> gint64 *timestamp */ GHashTable *monitors; GList *dir_collisions; + GList *shared_drives; GRecMutex mutex; /* guards cache */ GoaClient *client; gchar *account_identity; @@ -91,6 +93,7 @@ G_DEFINE_TYPE(GVfsBackendGoogle, g_vfs_backend_google, G_VFS_TYPE_BACKEND) #define ROOT_ID "GVfsRoot" #define SHARED_WITH_ME_ID "GVfsSharedWithMe" +#define SHARED_DRIVES_ID "GVfsSharedDrives" /* ---------------------------------------------------------------------------------------------------- */ typedef struct @@ -931,6 +934,48 @@ is_dir_listing_valid (GVfsBackendGoogle *self, GDataEntry *parent) } static void +rebuild_shared_drives_dir (GVfsBackendGoogle *self, + GCancellable *cancellable, + GError **error) + +{ + GDataAuthorizationDomain *auth_domain; + GList *l; + gint64 *timestamp; + + auth_domain = gdata_documents_service_get_primary_authorization_domain (); + + remove_dir (self, self->shared_drives_dir); + + for (l = self->shared_drives; l != NULL; l = l->next) + { + GDataDocumentsDrive *drive = GDATA_DOCUMENTS_DRIVE (l->data); + GDataEntry *entry = NULL; + + entry = gdata_service_query_single_entry (GDATA_SERVICE (self->service), + auth_domain, + gdata_entry_get_id (GDATA_ENTRY (drive)), + NULL, + GDATA_TYPE_DOCUMENTS_FOLDER, + cancellable, + error); + if (entry == NULL) + return; + + /* Replace "My Drive" title by the real name of the Drive. */ + gdata_entry_set_title (entry, gdata_documents_drive_get_name (drive)); + + insert_custom_entry (self, entry, SHARED_DRIVES_ID); + + g_object_unref (entry); + } + + timestamp = g_new (gint64, 1); + *timestamp = g_get_real_time (); + g_hash_table_insert (self->dir_timestamps, SHARED_DRIVES_ID, timestamp); +} + +static void rebuild_dir (GVfsBackendGoogle *self, GDataEntry *parent, GCancellable *cancellable, @@ -942,6 +987,12 @@ rebuild_dir (GVfsBackendGoogle *self, gchar *search; gchar *parent_id; + if (parent == self->shared_drives_dir) + { + rebuild_shared_drives_dir (self, cancellable, error); + return; + } + /* g_strdup() is necessary to prevent segfault because gdata_entry_get_id() calls g_free() */ parent_id = g_strdup (gdata_entry_get_id (parent)); @@ -1285,6 +1336,7 @@ build_file_info (GVfsBackendGoogle *self, gsize i; gboolean is_shared_with_me_dir = (entry == self->shared_with_me_dir); gboolean is_home = (entry == self->home); + gboolean is_shared_drives_dir = (entry == self->shared_drives_dir); gboolean can_edit; if (GDATA_IS_DOCUMENTS_FOLDER (entry)) @@ -1302,7 +1354,8 @@ build_file_info (GVfsBackendGoogle *self, /* TODO: It is not always possible to rename, delete, or list children. * However, the proper implementation of gdata_documents_entry_can_rename/ * _delete/_list_children would require port to Google Drive API v3. */ - g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME, !is_root && !is_home && !is_shared_with_me_dir); + g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME, + !is_root && !is_home && !is_shared_with_me_dir && !is_shared_drives_dir); g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE, is_folder); @@ -1310,10 +1363,12 @@ build_file_info (GVfsBackendGoogle *self, g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_STANDARD_IS_VOLATILE, is_symlink); g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE); - g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, !is_root && !is_home && !is_shared_with_me_dir); + g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, + !is_root && !is_home && !is_shared_with_me_dir && !is_shared_drives_dir); can_edit = gdata_documents_entry_can_edit (GDATA_DOCUMENTS_ENTRY (entry)); - g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, !is_root && !is_shared_with_me_dir && can_edit); + g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, + !is_root && !is_shared_with_me_dir && !is_shared_drives_dir && can_edit); g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ, TRUE); if (is_folder) @@ -1376,6 +1431,11 @@ build_file_info (GVfsBackendGoogle *self, icon = g_themed_icon_new_with_default_fallbacks ("folder-publicshare"); symbolic_icon = g_themed_icon_new_with_default_fallbacks ("folder-publicshare-symbolic"); } + else if (is_shared_drives_dir) + { + icon = g_themed_icon_new_with_default_fallbacks ("folder-remote"); + symbolic_icon = g_themed_icon_new_with_default_fallbacks ("folder-remote-symbolic"); + } else { icon = g_content_type_get_icon (content_type); @@ -1407,7 +1467,7 @@ build_file_info (GVfsBackendGoogle *self, g_file_info_set_display_name (info, title); g_file_info_set_edit_name (info, title); - if (is_root || is_home || is_shared_with_me_dir) + if (is_root || is_home || is_shared_with_me_dir || is_shared_drives_dir) goto out; copy_name = generate_copy_name (self, entry, entry_path); @@ -1556,8 +1616,9 @@ g_vfs_backend_google_copy (GVfsBackend *_self, goto out; } - if (source_entry == self->root || source_parent == self->root || - destination_parent == self->root || destination_parent == self->shared_with_me_dir) + if (source_entry == self->root || source_parent == self->root || source_parent == self->shared_drives_dir || + destination_parent == self->root || destination_parent == self->shared_with_me_dir || + destination_parent == self->shared_drives_dir) { g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("Operation not supported")); goto out; @@ -1977,8 +2038,9 @@ g_vfs_backend_google_move (GVfsBackend *_self, goto out; } - if (source_entry == self->root || source_parent == self->root || - destination_parent == self->root || destination_parent == self->shared_with_me_dir) + if (source_entry == self->root || source_parent == self->root || source_parent == self->shared_drives_dir || + destination_parent == self->root || destination_parent == self->shared_with_me_dir || + destination_parent == self->shared_drives_dir) { g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("Operation not supported")); goto out; @@ -2440,7 +2502,8 @@ g_vfs_backend_google_delete (GVfsBackend *_self, g_debug (" entry path: %s\n", entry_path); - if (entry == self->root || entry == self->home || entry == self->shared_with_me_dir) + if (entry == self->root || entry == self->home || entry == self->shared_with_me_dir || + entry == self->shared_drives_dir || parent == self->shared_drives_dir) { g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("Operation not supported")); goto out; @@ -2773,6 +2836,48 @@ g_vfs_backend_google_make_directory (GVfsBackend *_self, /* ---------------------------------------------------------------------------------------------------- */ +static GList * +query_shared_drives (GVfsBackendGoogle *self, + GCancellable *cancellable, + GError **error) +{ + GDataDocumentsDriveQuery *query; + GList *shared_drives = NULL; + + query = gdata_documents_drive_query_new (NULL); + while (TRUE) + { + GDataDocumentsFeed *feed; + GList *entries; + + feed = gdata_documents_service_query_drives (self->service, + query, + cancellable, + NULL, + NULL, + error); + if (feed == NULL) + break; + + entries = gdata_feed_get_entries (GDATA_FEED (feed)); + if (entries == NULL) + { + g_object_unref (feed); + break; + } + + shared_drives = g_list_concat (shared_drives, + g_list_copy_deep (entries, (GCopyFunc) g_object_ref, NULL)); + + gdata_query_next_page (GDATA_QUERY (query)); + g_object_unref (feed); + } + + g_clear_object (&query); + + return shared_drives; +} + static void g_vfs_backend_google_mount (GVfsBackend *_self, GVfsJobMount *job, @@ -2866,6 +2971,23 @@ g_vfs_backend_google_mount (GVfsBackend *_self, gdata_entry_set_title (self->shared_with_me_dir, _("Shared with me")); insert_custom_entry (self, self->shared_with_me_dir, ROOT_ID); + self->shared_drives = query_shared_drives (self, cancellable, &error); + if (error != NULL) + { + sanitize_error (&error); + g_vfs_job_failed_from_error (G_VFS_JOB (job), error); + g_error_free (error); + goto out; + } + + if (self->shared_drives) + { + self->shared_drives_dir = GDATA_ENTRY (gdata_documents_folder_new (SHARED_DRIVES_ID)); + /* Translators: This is the "Shared drives" folder on https://drive.google.com. */ + gdata_entry_set_title (self->shared_drives_dir, _("Shared drives")); + insert_custom_entry (self, self->shared_drives_dir, ROOT_ID); + } + /* TODO: Make it work with GOA volume monitor resp. shadow mounts. */ g_vfs_backend_set_default_location (_self, gdata_entry_get_id (self->home)); @@ -2987,7 +3109,7 @@ g_vfs_backend_google_push (GVfsBackend *_self, goto out; } - if (destination_parent == self->root || destination_parent == self->shared_with_me_dir) + if (destination_parent == self->root || destination_parent == self->shared_with_me_dir || destination_parent == self->shared_drives_dir) { g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("Operation not supported")); goto out; @@ -3621,6 +3743,7 @@ g_vfs_backend_google_set_display_name (GVfsBackend *_self, GDataAuthorizationDomain *auth_domain; GDataEntry *entry; GDataEntry *new_entry = NULL; + GDataEntry *parent; GError *error; gchar *entry_path = NULL; @@ -3638,7 +3761,15 @@ g_vfs_backend_google_set_display_name (GVfsBackend *_self, g_debug (" entry path: %s\n", entry_path); - if (entry == self->root || entry == self->home || entry == self->shared_with_me_dir) + parent = resolve_dir (self, filename, cancellable, NULL, NULL, &error); + if (error != NULL) + { + g_vfs_job_failed_from_error (G_VFS_JOB (job), error); + g_error_free (error); + goto out; + } + + if (entry == self->root || entry == self->home || entry == self->shared_with_me_dir || parent == self->shared_drives_dir) { g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("Operation not supported")); goto out; @@ -3716,7 +3847,7 @@ g_vfs_backend_google_create (GVfsBackend *_self, g_debug (" parent path: %s\n", parent_path); - if (parent == self->root || parent == self->shared_with_me_dir) + if (parent == self->root || parent == self->shared_with_me_dir || parent == self->shared_drives_dir) { g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("Operation not supported")); goto out; @@ -3831,7 +3962,7 @@ g_vfs_backend_google_replace (GVfsBackend *_self, g_debug (" parent path: %s\n", parent_path); - if (parent == self->root || parent == self->shared_with_me_dir) + if (parent == self->root || parent == self->shared_with_me_dir || parent == self->shared_drives_dir) { g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("Operation not supported")); goto out; @@ -4069,6 +4200,8 @@ g_vfs_backend_google_dispose (GObject *_self) g_clear_object (&self->root); g_clear_object (&self->home); g_clear_object (&self->shared_with_me_dir); + g_clear_object (&self->shared_drives_dir); + g_clear_list (&self->shared_drives, g_object_unref); g_clear_object (&self->client); g_clear_pointer (&self->entries, g_hash_table_unref); g_clear_pointer (&self->dir_entries, g_hash_table_unref); |