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