aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorMichael Albinus2020-01-22 16:54:55 +0100
committerMichael Albinus2020-01-22 16:54:55 +0100
commit2d9d62bb24c662890c943f16750f4a852aa6dc8b (patch)
tree46b0b60bed2bf49444f24ad5b04da55b133cf165 /lisp
parent1a2a5a17a75d77961b94d88989353bd07cfd3ef5 (diff)
downloademacs-2d9d62bb24c662890c943f16750f4a852aa6dc8b.tar.gz
emacs-2d9d62bb24c662890c943f16750f4a852aa6dc8b.zip
Add new Tramp method "media"
* doc/misc/tramp.texi (Quick Start Guide, GVFS-based methods): Add media devices. * etc/NEWS: Mention new Tramp method "media". * lisp/net/tramp-gvfs.el (tramp-gvfs-methods): Add "media" method. (tramp-goa-methods): Add tramp-autoload cookie. (tramp-media-methods): New defvar. (tramp-gvfs-service-volumemonitor): New defsubst. (top): Remove media methods if not supported. Add defaults for `tramp-default-host-alist'. (tramp-goa-account): Rename from `tramp-goa-name'. Adapt all callees. (tramp-gvfs-service-afc-volumemonitor) (tramp-gvfs-service-goa-volumemonitor) (tramp-gvfs-service-gphoto2-volumemonitor) (tramp-gvfs-service-mtp-volumemonitor) (tramp-gvfs-path-remotevolumemonitor) (tramp-gvfs-interface-remotevolumemonitor): New defconsts. (tramp-media-device): New defstruct. (tramp-gvfs-activation-uri): New defun. (tramp-gvfs-url-file-name): Use it. (tramp-gvfs-handler-mounted-unmounted) (tramp-gvfs-connection-mounted-p, tramp-gvfs-mount-spec): Handle "media" method. (tramp-get-goa-account): Rename from `tramp-make-goa-name'. Adapt all callees. (tramp-get-goa-accounts): Adapt docstring. Cache with nil key. (tramp-parse-goa-accounts, tramp-get-media-device) (tramp-get-media-devices) (tramp-parse-media-names): New defuns. (top): Rework completion function registration. * lisp/net/tramp.el (tramp-dns-sd-service-regexp): New defconst. (tramp-set-completion-function): Use it.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/net/tramp-gvfs.el529
-rw-r--r--lisp/net/tramp.el7
2 files changed, 446 insertions, 90 deletions
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index 67135e30d64..3811c6767ac 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -49,11 +49,15 @@
49 49
50;; The user option `tramp-gvfs-methods' contains the list of supported 50;; The user option `tramp-gvfs-methods' contains the list of supported
51;; connection methods. Per default, these are "afp", "dav", "davs", 51;; connection methods. Per default, these are "afp", "dav", "davs",
52;; "gdrive", "nextcloud" and "sftp". 52;; "gdrive", "media", "nextcloud" and "sftp".
53 53
54;; "gdrive" and "nextcloud" connection methods require a respective 54;; "gdrive" and "nextcloud" connection methods require a respective
55;; account in GNOME Online Accounts, with enabled "Files" service. 55;; account in GNOME Online Accounts, with enabled "Files" service.
56 56
57;; The "media" connection method is responsible for media devices,
58;; like cell phones, tablets, cameras etc. The device must already be
59;; connected via USB, before accessing it.
60
57;; Other possible connection methods are "ftp", "http", "https" and 61;; Other possible connection methods are "ftp", "http", "https" and
58;; "smb". When one of these methods is added to the list, the remote 62;; "smb". When one of these methods is added to the list, the remote
59;; access for that method is performed via GVFS instead of the native 63;; access for that method is performed via GVFS instead of the native
@@ -127,10 +131,10 @@
127 131
128;;;###tramp-autoload 132;;;###tramp-autoload
129(defcustom tramp-gvfs-methods 133(defcustom tramp-gvfs-methods
130 '("afp" "dav" "davs" "gdrive" "nextcloud" "sftp") 134 '("afp" "dav" "davs" "gdrive" "media" "nextcloud" "sftp")
131 "List of methods for remote files, accessed with GVFS." 135 "List of methods for remote files, accessed with GVFS."
132 :group 'tramp 136 :group 'tramp
133 :version "27.1" 137 :version "28.1"
134 :type '(repeat (choice (const "afp") 138 :type '(repeat (choice (const "afp")
135 (const "dav") 139 (const "dav")
136 (const "davs") 140 (const "davs")
@@ -138,10 +142,12 @@
138 (const "gdrive") 142 (const "gdrive")
139 (const "http") 143 (const "http")
140 (const "https") 144 (const "https")
145 (const "media")
141 (const "nextcloud") 146 (const "nextcloud")
142 (const "sftp") 147 (const "sftp")
143 (const "smb")))) 148 (const "smb"))))
144 149
150;;;###tramp-autoload
145(defconst tramp-goa-methods '("gdrive" "nextcloud") 151(defconst tramp-goa-methods '("gdrive" "nextcloud")
146 "List of methods which require registration at GNOME Online Accounts.") 152 "List of methods which require registration at GNOME Online Accounts.")
147 153
@@ -151,15 +157,23 @@
151 (dolist (method tramp-goa-methods) 157 (dolist (method tramp-goa-methods)
152 (setq tramp-gvfs-methods (delete method tramp-gvfs-methods)))) 158 (setq tramp-gvfs-methods (delete method tramp-gvfs-methods))))
153 159
154;; Add defaults for `tramp-default-user-alist' and `tramp-default-host-alist'.
155;;;###tramp-autoload 160;;;###tramp-autoload
156(tramp--with-startup 161(defvar tramp-media-methods '("afc" "gphoto2" "mtp")
157 (when (string-match "\\(.+\\)@\\(\\(?:gmail\\|googlemail\\)\\.com\\)" 162 "List of GVFS methods which are covered by the \"media\" method.
158 user-mail-address) 163They are checked during start up via
159 (add-to-list 'tramp-default-user-alist 164`tramp-gvfs-interface-remotevolumemonitor'.")
160 `("\\`gdrive\\'" nil ,(match-string 1 user-mail-address))) 165
161 (add-to-list 'tramp-default-host-alist 166(defsubst tramp-gvfs-service-volumemonitor (method)
162 '("\\`gdrive\\'" nil ,(match-string 2 user-mail-address))))) 167 "Return the well known name of the volume monitor responsible for METHOD."
168 (symbol-value
169 (intern-soft (format "tramp-gvfs-service-%s-volumemonitor" method))))
170
171;; Remove media methods if not supported.
172(when tramp-gvfs-enabled
173 (dolist (method tramp-media-methods)
174 (unless (member (tramp-gvfs-service-volumemonitor method)
175 (dbus-list-known-names :session))
176 (setq tramp-media-methods (delete method tramp-media-methods)))))
163 177
164;;;###tramp-autoload 178;;;###tramp-autoload
165(defcustom tramp-gvfs-zeroconf-domain "local" 179(defcustom tramp-gvfs-zeroconf-domain "local"
@@ -169,13 +183,15 @@
169 :type 'string) 183 :type 'string)
170 184
171;; Add the methods to `tramp-methods', in order to allow minibuffer 185;; Add the methods to `tramp-methods', in order to allow minibuffer
172;; completion. 186;; completion. Add defaults for `tramp-default-host-alist'.
173;;;###tramp-autoload 187;;;###tramp-autoload
174(when (featurep 'dbusbind) 188(when (featurep 'dbusbind)
175 (tramp--with-startup 189 (tramp--with-startup
176 (dolist (elt tramp-gvfs-methods) 190 (dolist (method tramp-gvfs-methods)
177 (unless (assoc elt tramp-methods) 191 (unless (assoc method tramp-methods)
178 (add-to-list 'tramp-methods (cons elt nil)))))) 192 (add-to-list 'tramp-methods `(,method)))
193 (when (member method (cons "media" tramp-goa-methods))
194 (add-to-list 'tramp-default-host-alist `(,method nil ""))))))
179 195
180(defconst tramp-gvfs-path-tramp (concat dbus-path-emacs "/Tramp") 196(defconst tramp-gvfs-path-tramp (concat dbus-path-emacs "/Tramp")
181 "The preceding object path for own objects.") 197 "The preceding object path for own objects.")
@@ -458,7 +474,208 @@ It has been changed in GVFS 1.14.")
458 474
459;; The basic structure for GNOME Online Accounts. We use a list :type, 475;; The basic structure for GNOME Online Accounts. We use a list :type,
460;; in order to be compatible with Emacs 25. 476;; in order to be compatible with Emacs 25.
461(cl-defstruct (tramp-goa-name (:type list) :named) method user host port) 477(cl-defstruct (tramp-goa-account (:type list) :named) method user host port)
478
479;;;###tramp-autoload
480(defconst tramp-gvfs-service-afc-volumemonitor "org.gtk.vfs.AfcVolumeMonitor"
481 "The well known name of the AFC volume monitor.")
482
483;; This one is not needed yet.
484(defconst tramp-gvfs-service-goa-volumemonitor "org.gtk.vfs.GoaVolumeMonitor"
485 "The well known name of the GOA volume monitor.")
486
487;;;###tramp-autoload
488(defconst tramp-gvfs-service-gphoto2-volumemonitor
489 "org.gtk.vfs.GPhoto2VolumeMonitor"
490 "The well known name of the GPhoto2 volume monitor.")
491
492;;;###tramp-autoload
493(defconst tramp-gvfs-service-mtp-volumemonitor "org.gtk.vfs.MTPVolumeMonitor"
494 "The well known name of the MTP volume monitor.")
495
496(defconst tramp-gvfs-path-remotevolumemonitor
497 "/org/gtk/Private/RemoteVolumeMonitor"
498 "The object path of the remote volume monitor.")
499
500(defconst tramp-gvfs-interface-remotevolumemonitor
501 "org.gtk.Private.RemoteVolumeMonitor"
502 "The volume monitor interface.")
503
504;; <interface name='org.gtk.Private.RemoteVolumeMonitor'>
505;; <method name="IsSupported">
506;; <arg type='b' name='is_supported' direction='out'/>
507;; </method>
508;; <method name="List">
509;; <arg type='a(ssssbbbbbbbbuasa{ss}sa{sv})' name='drives' direction='out'/>
510;; <arg type='a(ssssssbbssa{ss}sa{sv})' name='volumes' direction='out'/>
511;; <arg type='a(ssssssbsassa{sv})' name='mounts' direction='out'/>
512;; </method>
513;; <method name="CancelOperation">
514;; <arg type='s' name='cancellation_id' direction='in'/>
515;; <arg type='b' name='was_cancelled' direction='out'/>
516;; </method>
517;; <method name="MountUnmount">
518;; <arg type='s' name='id' direction='in'/>
519;; <arg type='s' name='cancellation_id' direction='in'/>
520;; <arg type='u' name='unmount_flags' direction='in'/>
521;; <arg type='s' name='mount_op_id' direction='in'/>
522;; </method>
523;; <method name="VolumeMount">
524;; <arg type='s' name='id' direction='in'/>
525;; <arg type='s' name='cancellation_id' direction='in'/>
526;; <arg type='u' name='mount_flags' direction='in'/>
527;; <arg type='s' name='mount_op_id' direction='in'/>
528;; </method>
529;; <method name="DriveEject">
530;; <arg type='s' name='id' direction='in'/>
531;; <arg type='s' name='cancellation_id' direction='in'/>
532;; <arg type='u' name='unmount_flags' direction='in'/>
533;; <arg type='s' name='mount_op_id' direction='in'/>
534;; </method>
535;; <method name="DrivePollForMedia">
536;; <arg type='s' name='id' direction='in'/>
537;; <arg type='s' name='cancellation_id' direction='in'/>
538;; </method>
539;; <method name="DriveStart">
540;; <arg type='s' name='id' direction='in'/>
541;; <arg type='s' name='cancellation_id' direction='in'/>
542;; <arg type='u' name='flags' direction='in'/>
543;; <arg type='s' name='mount_op_id' direction='in'/>
544;; </method>
545;; <method name="DriveStop">
546;; <arg type='s' name='id' direction='in'/>
547;; <arg type='s' name='cancellation_id' direction='in'/>
548;; <arg type='u' name='unmount_flags' direction='in'/>
549;; <arg type='s' name='mount_op_id' direction='in'/>
550;; </method>
551;; <method name="MountOpReply">
552;; <arg type='s' name='mount_op_id' direction='in'/>
553;; <arg type='i' name='result' direction='in'/>
554;; <arg type='s' name='user_name' direction='in'/>
555;; <arg type='s' name='domain' direction='in'/>
556;; <arg type='s' name='encoded_password' direction='in'/>
557;; <arg type='i' name='password_save' direction='in'/>
558;; <arg type='i' name='choice' direction='in'/>
559;; <arg type='b' name='anonymous' direction='in'/>
560;; </method>
561;; <signal name="DriveChanged">
562;; <arg type='s' name='dbus_name'/>
563;; <arg type='s' name='id'/>
564;; <arg type='(ssssbbbbbbbbuasa{ss}sa{sv})' name='drive'/>
565;; </signal>
566;; <signal name="DriveConnected">
567;; <arg type='s' name='dbus_name'/>
568;; <arg type='s' name='id'/>
569;; <arg type='(ssssbbbbbbbbuasa{ss}sa{sv})' name='drive'/>
570;; </signal>
571;; <signal name="DriveDisconnected">
572;; <arg type='s' name='dbus_name'/>
573;; <arg type='s' name='id'/>
574;; <arg type='(ssssbbbbbbbbuasa{ss}sa{sv})' name='drive'/>
575;; </signal>
576;; <signal name="DriveEjectButton">
577;; <arg type='s' name='dbus_name'/>
578;; <arg type='s' name='id'/>
579;; <arg type='(ssssbbbbbbbbuasa{ss}sa{sv})' name='drive'/>
580;; </signal>
581;; <signal name="DriveStopButton">
582;; <arg type='s' name='dbus_name'/>
583;; <arg type='s' name='id'/>
584;; <arg type='(ssssbbbbbbbbuasa{ss}sa{sv})' name='drive'/>
585;; </signal>
586;; <signal name="VolumeChanged">
587;; <arg type='s' name='dbus_name'/>
588;; <arg type='s' name='id'/>
589;; <arg type='(ssssssbbssa{ss}sa{sv})' name='volume'/>
590;; </signal>
591;; <signal name="VolumeAdded">
592;; <arg type='s' name='dbus_name'/>
593;; <arg type='s' name='id'/>
594;; <arg type='(ssssssbbssa{ss}sa{sv})' name='volume'/>
595;; </signal>
596;; <signal name="VolumeRemoved">
597;; <arg type='s' name='dbus_name'/>
598;; <arg type='s' name='id'/>
599;; <arg type='(ssssssbbssa{ss}sa{sv})' name='volume'/>
600;; </signal>
601;; <signal name="MountChanged">
602;; <arg type='s' name='dbus_name'/>
603;; <arg type='s' name='id'/>
604;; <arg type='(ssssssbsassa{sv})' name='mount'/>
605;; </signal>
606;; <signal name="MountAdded">
607;; <arg type='s' name='dbus_name'/>
608;; <arg type='s' name='id'/>
609;; <arg type='(ssssssbsassa{sv})' name='mount'/>
610;; </signal>
611;; <signal name="MountPreUnmount">
612;; <arg type='s' name='dbus_name'/>
613;; <arg type='s' name='id'/>
614;; <arg type='(ssssssbsassa{sv})' name='mount'/>
615;; </signal>
616;; <signal name="MountRemoved">
617;; <arg type='s' name='dbus_name'/>
618;; <arg type='s' name='id'/>
619;; <arg type='(ssssssbsassa{sv})' name='mount'/>
620;; </signal>
621;; <signal name="MountOpAskPassword">
622;; <arg type='s' name='dbus_name'/>
623;; <arg type='s' name='id'/>
624;; <arg type='s' name='message_to_show'/>
625;; <arg type='s' name='default_user'/>
626;; <arg type='s' name='default_domain'/>
627;; <arg type='u' name='flags'/>
628;; </signal>
629;; <signal name="MountOpAskQuestion">
630;; <arg type='s' name='dbus_name'/>
631;; <arg type='s' name='id'/>
632;; <arg type='s' name='message_to_show'/>
633;; <arg type='as' name='choices'/>
634;; </signal>
635;; <signal name="MountOpShowProcesses">
636;; <arg type='s' name='dbus_name'/>
637;; <arg type='s' name='id'/>
638;; <arg type='s' name='message_to_show'/>
639;; <arg type='ai' name='pid'/>
640;; <arg type='as' name='choices'/>
641;; </signal>
642;; <signal name="MountOpShowUnmountProgress">
643;; <arg type='s' name='dbus_name'/>
644;; <arg type='s' name='id'/>
645;; <arg type='s' name='message_to_show'/>
646;; <arg type='x' name='time_left'/>
647;; <arg type='x' name='bytes_left'/>
648;; </signal>
649;; <signal name="MountOpAborted">
650;; <arg type='s' name='dbus_name'/>
651;; <arg type='s' name='id'/>
652;; </signal>
653;; </interface>
654
655;; STRUCT volume
656;; STRING id
657;; STRING name
658;; STRING gicon_data
659;; STRING symbolic_gicon_data
660;; STRING uuid
661;; STRING activation_uri
662;; BOOLEAN can-mount
663;; BOOLEAN should-automount
664;; STRING drive-id
665;; STRING mount-id
666;; ARRAY identifiers
667;; DICT
668;; STRING key (unix-device, class, uuid, ...)
669;; STRING value
670;; STRING sort_key
671;; ARRAY expansion
672;; DICT
673;; STRING key (always-call-mount, is-removable, ...)
674;; VARIANT value (boolean?)
675
676;; The basic structure for media devices. We use a list :type, in
677;; order to be compatible with Emacs 25.
678(cl-defstruct (tramp-media-device (:type list) :named) method host port)
462 679
463;; "gvfs-<command>" utilities have been deprecated in GVFS 1.31.1. We 680;; "gvfs-<command>" utilities have been deprecated in GVFS 1.31.1. We
464;; must use "gio <command>" tool instead. 681;; must use "gio <command>" tool instead.
@@ -1381,36 +1598,45 @@ If FILE-SYSTEM is non-nil, return file system attributes."
1381 1598
1382;; File name conversions. 1599;; File name conversions.
1383 1600
1601(defun tramp-gvfs-activation-uri (filename)
1602 "Return activation URI to be used in gio commands."
1603 (if (tramp-tramp-file-p filename)
1604 (with-parsed-tramp-file-name filename nil
1605 ;; Ensure that media devices are cached.
1606 (when (string-equal method "media")
1607 (tramp-get-media-device v))
1608 (with-tramp-connection-property v "activation-uri"
1609 (setq localname "/")
1610 (when (string-equal "gdrive" method)
1611 (setq method "google-drive"))
1612 (when (string-equal "nextcloud" method)
1613 (setq method "davs"
1614 localname
1615 (concat (tramp-gvfs-get-remote-prefix v) localname)))
1616 (when (and user domain)
1617 (setq user (concat domain ";" user)))
1618 (url-recreate-url
1619 (url-parse-make-urlobj
1620 method (and user (url-hexify-string user))
1621 nil (and host (url-hexify-string host))
1622 (if (stringp port) (string-to-number port) port)
1623 localname nil nil t))))
1624 ;; Local URI.
1625 (url-recreate-url
1626 (url-parse-make-urlobj "file" nil nil nil nil nil nil nil t))))
1627
1384(defun tramp-gvfs-url-file-name (filename) 1628(defun tramp-gvfs-url-file-name (filename)
1385 "Return FILENAME in URL syntax." 1629 "Return FILENAME in URL syntax."
1386 ;; "/" must NOT be hexified.
1387 (setq filename (tramp-compat-file-name-unquote filename)) 1630 (setq filename (tramp-compat-file-name-unquote filename))
1388 (let ((url-unreserved-chars (cons ?/ url-unreserved-chars)) 1631 (let* (;; "/" must NOT be hexified.
1389 result) 1632 (url-unreserved-chars (cons ?/ url-unreserved-chars))
1390 (setq 1633 (result
1391 result 1634 (concat (substring (tramp-gvfs-activation-uri filename) 0 -1)
1392 (url-recreate-url 1635 (url-hexify-string (tramp-file-local-name filename)))))
1393 (if (tramp-tramp-file-p filename)
1394 (with-parsed-tramp-file-name filename nil
1395 (when (string-equal "gdrive" method)
1396 (setq method "google-drive"))
1397 (when (string-equal "nextcloud" method)
1398 (setq method "davs"
1399 localname
1400 (concat (tramp-gvfs-get-remote-prefix v) localname)))
1401 (when (and user domain)
1402 (setq user (concat domain ";" user)))
1403 (url-parse-make-urlobj
1404 method (and user (url-hexify-string user))
1405 nil (and host (url-hexify-string host))
1406 (if (stringp port) (string-to-number port) port)
1407 (and localname (url-hexify-string localname)) nil nil t))
1408 (url-parse-make-urlobj
1409 "file" nil nil nil nil
1410 (url-hexify-string (file-truename filename)) nil nil t))))
1411 (when (tramp-tramp-file-p filename) 1636 (when (tramp-tramp-file-p filename)
1412 (with-parsed-tramp-file-name filename nil 1637 (tramp-message
1413 (tramp-message v 10 "remote file `%s' is URL `%s'" filename result))) 1638 (tramp-dissect-file-name filename) 10
1639 "remote file `%s' is URL `%s'" filename result))
1414 result)) 1640 result))
1415 1641
1416(defun tramp-gvfs-object-path (filename) 1642(defun tramp-gvfs-object-path (filename)
@@ -1567,6 +1793,17 @@ If FILE-SYSTEM is non-nil, return file system attributes."
1567 user (url-user uri) 1793 user (url-user uri)
1568 host (url-host uri) 1794 host (url-host uri)
1569 port (url-portspec uri))) 1795 port (url-portspec uri)))
1796 (when (member method tramp-media-methods)
1797 ;; Ensure that media devices are cached.
1798 (tramp-get-media-devices nil)
1799 (let ((v (tramp-get-connection-property
1800 (make-tramp-media-device
1801 :method method :host (downcase host) :port port)
1802 "vector" nil)))
1803 (when v
1804 (setq method (tramp-file-name-method v)
1805 host (tramp-file-name-host v)
1806 port (tramp-file-name-port v)))))
1570 (when (member method tramp-gvfs-methods) 1807 (when (member method tramp-gvfs-methods)
1571 (with-parsed-tramp-file-name 1808 (with-parsed-tramp-file-name
1572 (tramp-make-tramp-file-name method user domain host port "") nil 1809 (tramp-make-tramp-file-name method user domain host port "") nil
@@ -1657,6 +1894,17 @@ If FILE-SYSTEM is non-nil, return file system attributes."
1657 user (url-user uri) 1894 user (url-user uri)
1658 host (url-host uri) 1895 host (url-host uri)
1659 port (url-portspec uri))) 1896 port (url-portspec uri)))
1897 (when (member method tramp-media-methods)
1898 ;; Ensure that media devices are cached.
1899 (tramp-get-media-devices vec)
1900 (let ((v (tramp-get-connection-property
1901 (make-tramp-media-device
1902 :method method :host (downcase host) :port port)
1903 "vector" nil)))
1904 (when v
1905 (setq method (tramp-file-name-method v)
1906 host (tramp-file-name-host v)
1907 port (tramp-file-name-port v)))))
1660 (when (and 1908 (when (and
1661 (string-equal method (tramp-file-name-method vec)) 1909 (string-equal method (tramp-file-name-method vec))
1662 (string-equal user (tramp-file-name-user vec)) 1910 (string-equal user (tramp-file-name-user vec))
@@ -1694,11 +1942,16 @@ It was \"a(say)\", but has changed to \"a{sv})\"."
1694 1942
1695(defun tramp-gvfs-mount-spec (vec) 1943(defun tramp-gvfs-mount-spec (vec)
1696 "Return a mount-spec for \"org.gtk.vfs.MountTracker.mountLocation\"." 1944 "Return a mount-spec for \"org.gtk.vfs.MountTracker.mountLocation\"."
1697 (let* ((method (tramp-file-name-method vec)) 1945 (let* ((media (tramp-get-media-device vec))
1946 (method (if media
1947 (tramp-media-device-method media)
1948 (tramp-file-name-method vec)))
1698 (user (tramp-file-name-user vec)) 1949 (user (tramp-file-name-user vec))
1699 (domain (tramp-file-name-domain vec)) 1950 (domain (tramp-file-name-domain vec))
1700 (host (tramp-file-name-host vec)) 1951 (host (if media
1701 (port (tramp-file-name-port vec)) 1952 (tramp-media-device-host media) (tramp-file-name-host vec)))
1953 (port (if media
1954 (tramp-media-device-port media) (tramp-file-name-port vec)))
1702 (localname (tramp-file-name-unquote-localname vec)) 1955 (localname (tramp-file-name-unquote-localname vec))
1703 (share (when (string-match "^/?\\([^/]+\\)" localname) 1956 (share (when (string-match "^/?\\([^/]+\\)" localname)
1704 (match-string 1 localname))) 1957 (match-string 1 localname)))
@@ -1792,7 +2045,7 @@ This is relevant for GNOME Online Accounts."
1792 ;; Ensure that GNOME Online Accounts are cached. 2045 ;; Ensure that GNOME Online Accounts are cached.
1793 (when (member (tramp-file-name-method vec) tramp-goa-methods) 2046 (when (member (tramp-file-name-method vec) tramp-goa-methods)
1794 (tramp-get-goa-accounts vec)) 2047 (tramp-get-goa-accounts vec))
1795 (tramp-get-connection-property (tramp-make-goa-name vec) "prefix" "/"))) 2048 (tramp-get-connection-property (tramp-get-goa-account vec) "prefix" "/")))
1796 2049
1797(defun tramp-gvfs-maybe-open-connection (vec) 2050(defun tramp-gvfs-maybe-open-connection (vec)
1798 "Maybe open a connection VEC. 2051 "Maybe open a connection VEC.
@@ -1841,7 +2094,7 @@ connection if a previous connection has died for some reason."
1841 ;; Ensure that GNOME Online Accounts are cached. 2094 ;; Ensure that GNOME Online Accounts are cached.
1842 (tramp-get-goa-accounts vec) 2095 (tramp-get-goa-accounts vec)
1843 (when (tramp-get-connection-property 2096 (when (tramp-get-connection-property
1844 (tramp-make-goa-name vec) "FilesDisabled" t) 2097 (tramp-get-goa-account vec) "FilesDisabled" t)
1845 (tramp-user-error 2098 (tramp-user-error
1846 vec "There is no Online Account `%s'" 2099 vec "There is no Online Account `%s'"
1847 (tramp-make-tramp-file-name vec 'noloc)))) 2100 (tramp-make-tramp-file-name vec 'noloc))))
@@ -1966,12 +2219,12 @@ is applied, and it returns t if the return code is zero."
1966 (and (tramp-flush-file-properties vec "/") nil))))) 2219 (and (tramp-flush-file-properties vec "/") nil)))))
1967 2220
1968 2221
1969;; D-Bus GNOME Online Accounts functions. 2222;; GNOME Online Accounts functions.
1970 2223
1971(defun tramp-make-goa-name (vec) 2224(defun tramp-get-goa-account (vec)
1972 "Transform VEC into a `tramp-goa-name' structure." 2225 "Transform VEC into a `tramp-goa-account' structure."
1973 (when (tramp-file-name-p vec) 2226 (when (tramp-file-name-p vec)
1974 (make-tramp-goa-name 2227 (make-tramp-goa-account
1975 :method (tramp-file-name-method vec) 2228 :method (tramp-file-name-method vec)
1976 :user (tramp-file-name-user vec) 2229 :user (tramp-file-name-user vec)
1977 :host (tramp-file-name-host vec) 2230 :host (tramp-file-name-host vec)
@@ -1979,12 +2232,12 @@ is applied, and it returns t if the return code is zero."
1979 2232
1980(defun tramp-get-goa-accounts (vec) 2233(defun tramp-get-goa-accounts (vec)
1981 "Retrieve GNOME Online Accounts, and cache them. 2234 "Retrieve GNOME Online Accounts, and cache them.
1982The hash key is a `tramp-goa-name' structure. The value is an 2235The hash key is a `tramp-goa-account' structure. The value is an
1983alist of the properties of `tramp-goa-interface-account' and 2236alist of the properties of `tramp-goa-interface-account' and
1984`tramp-goa-interface-files' of the corresponding GNOME online 2237`tramp-goa-interface-files' of the corresponding GNOME Online
1985account. Additionally, a property \"prefix\" is added. 2238Account. Additionally, a property \"prefix\" is added.
1986VEC is used only for traces." 2239VEC is used only for traces."
1987 (with-tramp-connection-property (tramp-make-goa-name vec) "goa-accounts" 2240 (with-tramp-connection-property nil "goa-accounts"
1988 (dolist 2241 (dolist
1989 (object-path 2242 (object-path
1990 (mapcar 2243 (mapcar
@@ -2010,15 +2263,15 @@ VEC is used only for traces."
2010 (cdr (assoc "ProviderType" account-properties)) 2263 (cdr (assoc "ProviderType" account-properties))
2011 '("google" "owncloud")) 2264 '("google" "owncloud"))
2012 (string-match tramp-goa-identity-regexp identity)) 2265 (string-match tramp-goa-identity-regexp identity))
2013 (setq key (make-tramp-goa-name 2266 (setq key (make-tramp-goa-account
2014 :method (cdr (assoc "ProviderType" account-properties)) 2267 :method (cdr (assoc "ProviderType" account-properties))
2015 :user (match-string 1 identity) 2268 :user (match-string 1 identity)
2016 :host (match-string 2 identity) 2269 :host (match-string 2 identity)
2017 :port (match-string 3 identity))) 2270 :port (match-string 3 identity)))
2018 (when (string-equal (tramp-goa-name-method key) "google") 2271 (when (string-equal (tramp-goa-account-method key) "google")
2019 (setf (tramp-goa-name-method key) "gdrive")) 2272 (setf (tramp-goa-account-method key) "gdrive"))
2020 (when (string-equal (tramp-goa-name-method key) "owncloud") 2273 (when (string-equal (tramp-goa-account-method key) "owncloud")
2021 (setf (tramp-goa-name-method key) "nextcloud")) 2274 (setf (tramp-goa-account-method key) "nextcloud"))
2022 ;; Cache all properties. 2275 ;; Cache all properties.
2023 (dolist (prop (nconc account-properties files-properties)) 2276 (dolist (prop (nconc account-properties files-properties))
2024 (tramp-set-connection-property key (car prop) (cdr prop))) 2277 (tramp-set-connection-property key (car prop) (cdr prop)))
@@ -2034,6 +2287,80 @@ VEC is used only for traces."
2034 ;; Mark, that goa accounts have been cached. 2287 ;; Mark, that goa accounts have been cached.
2035 "cached")) 2288 "cached"))
2036 2289
2290(defun tramp-parse-goa-accounts (service)
2291 "Return a list of (user host) tuples allowed to access.
2292It checks for registered GNOME Online Accounts."
2293 ;; SERVICE might be encoded as a DNS-SD service.
2294 (and (string-match tramp-dns-sd-service-regexp service)
2295 (setq service (match-string 1 service)))
2296 (let (result)
2297 (maphash
2298 (lambda (key _value)
2299 (if (and (tramp-goa-account-p key)
2300 (string-equal service (tramp-goa-account-method key)))
2301 (push (list (tramp-goa-account-user key)
2302 (tramp-goa-account-host key))
2303 result)))
2304 tramp-cache-data)
2305 result))
2306
2307
2308;; Media devices functions.
2309
2310(defun tramp-get-media-device (vec)
2311 "Transform VEC into a `tramp-media-device' structure.
2312Check, that respective cache values do exist."
2313 (if-let* ((media (tramp-get-connection-property vec "media-device" nil))
2314 (prop (tramp-get-connection-property media "vector" nil)))
2315 media
2316 (tramp-get-media-devices vec)
2317 (tramp-get-connection-property vec "media-device" nil)))
2318
2319(defun tramp-get-media-devices (vec)
2320 "Retrieve media devices, and cache them.
2321The hash key is a `tramp-media-device' structure.
2322VEC is used only for traces."
2323; (with-tramp-connection-property nil "media-devices"
2324 (dolist (method tramp-media-methods)
2325 (dolist (volume (cadr (with-tramp-dbus-call-method vec t
2326 :session (tramp-gvfs-service-volumemonitor method)
2327 tramp-gvfs-path-remotevolumemonitor
2328 tramp-gvfs-interface-remotevolumemonitor "List")))
2329 (let* ((uri (url-generic-parse-url (nth 5 volume)))
2330 (vec (make-tramp-file-name
2331 :method "media"
2332 ;; A host name cannot contain spaces.
2333 :host (replace-regexp-in-string " " "_" (nth 1 volume))))
2334 (media (make-tramp-media-device
2335 :method method
2336 :host (url-host uri)
2337 :port (and (url-portspec uri)
2338 (number-to-string (url-portspec uri))))))
2339 (tramp-set-connection-property vec "activation-uri" (nth 5 volume))
2340 (tramp-set-connection-property vec "media-device" media)
2341 (tramp-set-connection-property media "vector" vec))))
2342 ;; Mark, that media devices have been cached.
2343); "cached"))
2344
2345(defun tramp-parse-media-names (service)
2346 "Return a list of (user host) tuples allowed to access.
2347It checks for mounted media devices."
2348 ;; SERVICE might be encoded as a DNS-SD service.
2349 (and (string-match tramp-dns-sd-service-regexp service)
2350 (setq service (match-string 1 service)))
2351 (let (result)
2352 (maphash
2353 (lambda (key _value)
2354 (if (and (tramp-media-device-p key)
2355 (string-equal service (tramp-media-device-method key))
2356 (tramp-get-connection-property key "vector" nil))
2357 (push
2358 (list nil (tramp-file-name-host
2359 (tramp-get-connection-property key "vector" nil)))
2360 result)))
2361 tramp-cache-data)
2362 result))
2363
2037 2364
2038;; D-Bus zeroconf functions. 2365;; D-Bus zeroconf functions.
2039 2366
@@ -2078,39 +2405,61 @@ This uses \"avahi-browse\" in case D-Bus is not enabled in Avahi."
2078 (list user host))) 2405 (list user host)))
2079 result)))) 2406 result))))
2080 2407
2081;; Add completion functions for AFP, DAV, DAVS, SFTP and SMB methods.
2082(when tramp-gvfs-enabled 2408(when tramp-gvfs-enabled
2083 ;; Suppress D-Bus error messages. 2409 ;; Suppress D-Bus error messages and Tramp traces.
2084 (let (tramp-gvfs-dbus-event-vector) 2410 (let (tramp-gvfs-dbus-event-vector tramp-verbose fun)
2411 ;; Add completion functions for services announced by DNS-SD.
2412 ;; See <http://www.dns-sd.org/ServiceTypes.html> for valid service types.
2085 (zeroconf-init tramp-gvfs-zeroconf-domain) 2413 (zeroconf-init tramp-gvfs-zeroconf-domain)
2086 (if (zeroconf-list-service-types) 2414 (when (setq fun (or (and (zeroconf-list-service-types)
2087 (progn 2415 #'tramp-zeroconf-parse-device-names)
2088 (tramp-set-completion-function 2416 (and (executable-find "avahi-browse")
2089 "afp" '((tramp-zeroconf-parse-device-names "_afpovertcp._tcp"))) 2417 #'tramp-gvfs-parse-device-names)))
2090 (tramp-set-completion-function 2418 (when (member "afp" tramp-gvfs-methods)
2091 "dav" '((tramp-zeroconf-parse-device-names "_webdav._tcp"))) 2419 (tramp-set-completion-function
2092 (tramp-set-completion-function 2420 "afp" `((,fun "_afpovertcp._tcp"))))
2093 "davs" '((tramp-zeroconf-parse-device-names "_webdav._tcp"))) 2421 (when (member "dav" tramp-gvfs-methods)
2094 (tramp-set-completion-function 2422 (tramp-set-completion-function
2095 "sftp" '((tramp-zeroconf-parse-device-names "_ssh._tcp") 2423 "dav" `((,fun "_webdav._tcp")
2096 (tramp-zeroconf-parse-device-names "_workstation._tcp"))) 2424 (,fun "_webdavs._tcp"))))
2097 (when (member "smb" tramp-gvfs-methods) 2425 (when (member "davs" tramp-gvfs-methods)
2098 (tramp-set-completion-function
2099 "smb" '((tramp-zeroconf-parse-device-names "_smb._tcp")))))
2100
2101 (when (executable-find "avahi-browse")
2102 (tramp-set-completion-function 2426 (tramp-set-completion-function
2103 "afp" '((tramp-gvfs-parse-device-names "_afpovertcp._tcp"))) 2427 "davs" `((,fun "_webdav._tcp")
2428 (,fun "_webdavs._tcp"))))
2429 (when (member "ftp" tramp-gvfs-methods)
2104 (tramp-set-completion-function 2430 (tramp-set-completion-function
2105 "dav" '((tramp-gvfs-parse-device-names "_webdav._tcp"))) 2431 "ftp" `((,fun "_ftp._tcp"))))
2432 (when (member "http" tramp-gvfs-methods)
2106 (tramp-set-completion-function 2433 (tramp-set-completion-function
2107 "davs" '((tramp-gvfs-parse-device-names "_webdav._tcp"))) 2434 "http" `((,fun "_http._tcp")
2435 (,fun "_https._tcp"))))
2436 (when (member "https" tramp-gvfs-methods)
2108 (tramp-set-completion-function 2437 (tramp-set-completion-function
2109 "sftp" '((tramp-gvfs-parse-device-names "_ssh._tcp") 2438 "https" `((,fun "_http._tcp")
2110 (tramp-gvfs-parse-device-names "_workstation._tcp"))) 2439 (,fun "_https._tcp"))))
2111 (when (member "smb" tramp-gvfs-methods) 2440 (when (member "sftp" tramp-gvfs-methods)
2112 (tramp-set-completion-function 2441 (tramp-set-completion-function
2113 "smb" '((tramp-gvfs-parse-device-names "_smb._tcp")))))))) 2442 "sftp" `((,fun "_sftp-ssh._tcp")
2443 (,fun "_ssh._tcp")
2444 (,fun "_workstation._tcp"))))
2445 (when (member "smb" tramp-gvfs-methods)
2446 (tramp-set-completion-function
2447 "smb" `((,fun "_smb._tcp")))))
2448
2449 ;; Add completion functions for GNOME Online Accounts.
2450 (tramp-get-goa-accounts nil)
2451 (dolist (method tramp-goa-methods)
2452 (when (member method tramp-gvfs-methods)
2453 (tramp-set-completion-function
2454 method `((tramp-parse-goa-accounts ,(format "_%s._tcp" method))))))
2455
2456 ;; Add completion functions for media devices.
2457 (tramp-get-media-devices nil)
2458 (tramp-set-completion-function
2459 "media"
2460 (mapcar
2461 (lambda (method) `(tramp-parse-media-names ,(format "_%s._tcp" method)))
2462 tramp-media-methods))))
2114 2463
2115(add-hook 'tramp-unload-hook 2464(add-hook 'tramp-unload-hook
2116 (lambda () 2465 (lambda ()
@@ -2120,10 +2469,14 @@ This uses \"avahi-browse\" in case D-Bus is not enabled in Avahi."
2120 2469
2121;;; TODO: 2470;;; TODO:
2122 2471
2472;; * Support /media::.
2473;;
2474;; * React on media mount/unmount.
2475;;
2123;; * (Customizable) unmount when exiting Emacs. See tramp-archive.el. 2476;; * (Customizable) unmount when exiting Emacs. See tramp-archive.el.
2124;; 2477;;
2125;; * Host name completion for existing mount points (afp-server, 2478;; * Host name completion for existing mount points (afp-server,
2126;; smb-server, google-drive, nextcloud) or via smb-network or network. 2479;; smb-server) or via smb-network or network.
2127;; 2480;;
2128;; * Check, how two shares of the same SMB server can be mounted in 2481;; * Check, how two shares of the same SMB server can be mounted in
2129;; parallel. 2482;; parallel.
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 900c15ffae9..324b2a24b80 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -2059,6 +2059,9 @@ letter into the file name. This function removes it."
2059 2059
2060;;; Config Manipulation Functions: 2060;;; Config Manipulation Functions:
2061 2061
2062(defconst tramp-dns-sd-service-regexp "^_[-[:alnum:]]+\\._tcp$"
2063 "DNS-SD service regexp.")
2064
2062(defun tramp-set-completion-function (method function-list) 2065(defun tramp-set-completion-function (method function-list)
2063 "Set the list of completion functions for METHOD. 2066 "Set the list of completion functions for METHOD.
2064FUNCTION-LIST is a list of entries of the form (FUNCTION FILE). 2067FUNCTION-LIST is a list of entries of the form (FUNCTION FILE).
@@ -2091,9 +2094,9 @@ Example:
2091 (zerop 2094 (zerop
2092 (tramp-call-process 2095 (tramp-call-process
2093 v "reg" nil nil nil "query" (nth 1 (car v)))))) 2096 v "reg" nil nil nil "query" (nth 1 (car v))))))
2094 ;; Zeroconf service type. 2097 ;; DNS-SD service type.
2095 ((string-match-p 2098 ((string-match-p
2096 "^_[[:alpha:]]+\\._[[:alpha:]]+$" (nth 1 (car v)))) 2099 tramp-dns-sd-service-regexp (nth 1 (car v))))
2097 ;; Configuration file or empty string. 2100 ;; Configuration file or empty string.
2098 (t (file-exists-p (nth 1 (car v)))))) 2101 (t (file-exists-p (nth 1 (car v))))))
2099 (setq r (delete (car v) r))) 2102 (setq r (delete (car v) r)))