xref: /aosp_15_r20/external/webrtc/modules/desktop_capture/linux/wayland/screencast_portal.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2022 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef MODULES_DESKTOP_CAPTURE_LINUX_WAYLAND_SCREENCAST_PORTAL_H_
12 #define MODULES_DESKTOP_CAPTURE_LINUX_WAYLAND_SCREENCAST_PORTAL_H_
13 
14 #include <gio/gio.h>
15 
16 #include <string>
17 
18 #include "modules/desktop_capture/desktop_capture_types.h"
19 #include "modules/desktop_capture/linux/wayland/screen_capture_portal_interface.h"
20 #include "modules/portal/portal_request_response.h"
21 #include "modules/portal/xdg_desktop_portal_utils.h"
22 #include "modules/portal/xdg_session_details.h"
23 
24 namespace webrtc {
25 
26 class ScreenCastPortal : public xdg_portal::ScreenCapturePortalInterface {
27  public:
28   using ProxyRequestResponseHandler = void (*)(GObject* object,
29                                                GAsyncResult* result,
30                                                gpointer user_data);
31 
32   using SourcesRequestResponseSignalHandler =
33       void (*)(GDBusConnection* connection,
34                const char* sender_name,
35                const char* object_path,
36                const char* interface_name,
37                const char* signal_name,
38                GVariant* parameters,
39                gpointer user_data);
40 
41   // Values are set based on cursor mode property in
42   // xdg-desktop-portal/screencast
43   // https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.ScreenCast.xml
44   enum class CursorMode : uint32_t {
45     // Mouse cursor will not be included in any form
46     kHidden = 0b01,
47     // Mouse cursor will be part of the screen content
48     kEmbedded = 0b10,
49     // Mouse cursor information will be send separately in form of metadata
50     kMetadata = 0b100
51   };
52 
53   // Values are set based on persist mode property in
54   // xdg-desktop-portal/screencast
55   // https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.ScreenCast.xml
56   enum class PersistMode : uint32_t {
57     // Do not allow to restore stream
58     kDoNotPersist = 0b00,
59     // The restore token is valid as long as the application is alive. It's
60     // stored in memory and revoked when the application closes its DBus
61     // connection
62     kTransient = 0b01,
63     // The restore token is stored in disk and is valid until the user manually
64     // revokes it
65     kPersistent = 0b10
66   };
67 
68   // Interface that must be implemented by the ScreenCastPortal consumers.
69   class PortalNotifier {
70    public:
71     virtual void OnScreenCastRequestResult(xdg_portal::RequestResponse result,
72                                            uint32_t stream_node_id,
73                                            int fd) = 0;
74     virtual void OnScreenCastSessionClosed() = 0;
75 
76    protected:
77     PortalNotifier() = default;
78     virtual ~PortalNotifier() = default;
79   };
80 
81   ScreenCastPortal(CaptureType type, PortalNotifier* notifier);
82   ScreenCastPortal(CaptureType type,
83                    PortalNotifier* notifier,
84                    ProxyRequestResponseHandler proxy_request_response_handler,
85                    SourcesRequestResponseSignalHandler
86                        sources_request_response_signal_handler,
87                    gpointer user_data,
88                    // TODO(chromium:1291247): Remove the default option once
89                    // downstream has been adjusted.
90                    bool prefer_cursor_embedded = false);
91 
92   ~ScreenCastPortal();
93 
94   // Initialize ScreenCastPortal with series of DBus calls where we try to
95   // obtain all the required information, like PipeWire file descriptor and
96   // PipeWire stream node ID.
97   //
98   // The observer will return whether the communication with xdg-desktop-portal
99   // was successful and only then you will be able to get all the required
100   // information in order to continue working with PipeWire.
101   void Start() override;
102   void Stop() override;
103   xdg_portal::SessionDetails GetSessionDetails() override;
104 
105   // Method to notify the reason for failure of a portal request.
106   void OnPortalDone(xdg_portal::RequestResponse result) override;
107 
108   // Sends a create session request to the portal.
109   void RequestSession(GDBusProxy* proxy) override;
110 
111   // Set of methods leveraged by remote desktop portal to setup a common session
112   // with screen cast portal.
113   void SetSessionDetails(const xdg_portal::SessionDetails& session_details);
114   uint32_t pipewire_stream_node_id();
115   void SourcesRequest();
116   void OpenPipeWireRemote();
117 
118   // ScreenCast specific methods for stream restoration
119   void SetPersistMode(ScreenCastPortal::PersistMode mode);
120   void SetRestoreToken(const std::string& token);
121   std::string RestoreToken() const;
122 
123  private:
124   // Values are set based on source type property in
125   // xdg-desktop-portal/screencast
126   // https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.ScreenCast.xml
127   enum class CaptureSourceType : uint32_t {
128     kScreen = 0b01,
129     kWindow = 0b10,
130     kAnyScreenContent = kScreen | kWindow
131   };
132   static CaptureSourceType ToCaptureSourceType(CaptureType type);
133 
134   PortalNotifier* notifier_;
135 
136   // A PipeWire stream ID of stream we will be connecting to
137   uint32_t pw_stream_node_id_ = 0;
138   // A file descriptor of PipeWire socket
139   int pw_fd_ = -1;
140   // Restore token that can be used to restore previous session
141   std::string restore_token_;
142 
143   CaptureSourceType capture_source_type_ =
144       ScreenCastPortal::CaptureSourceType::kScreen;
145 
146   CursorMode cursor_mode_ = CursorMode::kMetadata;
147 
148   PersistMode persist_mode_ = ScreenCastPortal::PersistMode::kDoNotPersist;
149 
150   ProxyRequestResponseHandler proxy_request_response_handler_;
151   SourcesRequestResponseSignalHandler sources_request_response_signal_handler_;
152   gpointer user_data_;
153 
154   GDBusConnection* connection_ = nullptr;
155   GDBusProxy* proxy_ = nullptr;
156   GCancellable* cancellable_ = nullptr;
157   std::string portal_handle_;
158   std::string session_handle_;
159   std::string sources_handle_;
160   std::string start_handle_;
161   guint session_request_signal_id_ = 0;
162   guint sources_request_signal_id_ = 0;
163   guint start_request_signal_id_ = 0;
164   guint session_closed_signal_id_ = 0;
165 
166   void UnsubscribeSignalHandlers();
167   static void OnProxyRequested(GObject* object,
168                                GAsyncResult* result,
169                                gpointer user_data);
170   static void OnSessionRequested(GDBusProxy* proxy,
171                                  GAsyncResult* result,
172                                  gpointer user_data);
173   static void OnSessionRequestResponseSignal(GDBusConnection* connection,
174                                              const char* sender_name,
175                                              const char* object_path,
176                                              const char* interface_name,
177                                              const char* signal_name,
178                                              GVariant* parameters,
179                                              gpointer user_data);
180   static void OnSessionClosedSignal(GDBusConnection* connection,
181                                     const char* sender_name,
182                                     const char* object_path,
183                                     const char* interface_name,
184                                     const char* signal_name,
185                                     GVariant* parameters,
186                                     gpointer user_data);
187   static void OnSourcesRequested(GDBusProxy* proxy,
188                                  GAsyncResult* result,
189                                  gpointer user_data);
190   static void OnSourcesRequestResponseSignal(GDBusConnection* connection,
191                                              const char* sender_name,
192                                              const char* object_path,
193                                              const char* interface_name,
194                                              const char* signal_name,
195                                              GVariant* parameters,
196                                              gpointer user_data);
197 
198   void StartRequest();
199   static void OnStartRequested(GDBusProxy* proxy,
200                                GAsyncResult* result,
201                                gpointer user_data);
202   static void OnStartRequestResponseSignal(GDBusConnection* connection,
203                                            const char* sender_name,
204                                            const char* object_path,
205                                            const char* interface_name,
206                                            const char* signal_name,
207                                            GVariant* parameters,
208                                            gpointer user_data);
209 
210   static void OnOpenPipeWireRemoteRequested(GDBusProxy* proxy,
211                                             GAsyncResult* result,
212                                             gpointer user_data);
213 };
214 
215 }  // namespace webrtc
216 
217 #endif  // MODULES_DESKTOP_CAPTURE_LINUX_WAYLAND_SCREENCAST_PORTAL_H_
218