Add additional checks in case of early portal error

In case ScreenCast portal fails right at the beginning, we need to check
the response before trying to get session handle to avoid accessing
non-existing portal data.

Also on early failure do not continue making source request if we failed
before and don't have session handle.

Bug: webrtc:13429
Change-Id: I2bfbd2c6e96e3cda1e62aa9dc07f66d4c7496b53
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/272400
Reviewed-by: Alexander Cooper <alcooper@chromium.org>
Reviewed-by: Mark Foltz <mfoltz@chromium.org>
Commit-Queue: Mark Foltz <mfoltz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#37872}
This commit is contained in:
Jan Grulich 2022-08-22 14:06:08 +02:00 committed by WebRTC LUCI CQ
parent cc9fce39fc
commit 65a9a515b5
4 changed files with 39 additions and 21 deletions

View file

@ -8,6 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/desktop_capture/linux/wayland/screen_capture_portal_interface.h"
#include "modules/desktop_capture/linux/wayland/xdg_desktop_portal_utils.h"
#include <string>
@ -67,18 +68,26 @@ void ScreenCapturePortalInterface::RegisterSessionClosedSignalHandler(
GDBusConnection* connection,
std::string& session_handle,
guint& session_closed_signal_id) {
uint32_t portal_response;
uint32_t portal_response = 2;
Scoped<GVariant> response_data;
g_variant_get(parameters, /*format_string=*/"(u@a{sv})", &portal_response,
response_data.receive());
if (RequestResponseFromPortalResponse(portal_response) !=
RequestResponse::kSuccess) {
RTC_LOG(LS_ERROR) << "Failed to request the session subscription.";
OnPortalDone(RequestResponse::kError);
return;
}
Scoped<GVariant> g_session_handle(
g_variant_lookup_value(response_data.get(), /*key=*/"session_handle",
/*expected_type=*/nullptr));
session_handle = g_variant_dup_string(
session_handle = g_variant_get_string(
/*value=*/g_session_handle.get(), /*length=*/nullptr);
if (session_handle.empty() || portal_response) {
RTC_LOG(LS_ERROR) << "Failed to request the session subscription.";
if (session_handle.empty()) {
RTC_LOG(LS_ERROR) << "Could not get session handle despite valid response";
OnPortalDone(RequestResponse::kError);
return;
}

View file

@ -29,21 +29,7 @@ using xdg_portal::SetupRequestResponseSignal;
using xdg_portal::SetupSessionRequestHandlers;
using xdg_portal::StartSessionRequest;
using xdg_portal::TearDownSession;
RequestResponse ToRequestResponseFromSignal(uint32_t signal_response) {
// See:
// https://docs.flatpak.org/en/latest/portal-api-reference.html#gdbus-signal-org-freedesktop-portal-Request.Response
switch (signal_response) {
case 0:
return RequestResponse::kSuccess;
case 1:
return RequestResponse::kUserCancelled;
case 2:
return RequestResponse::kError;
default:
return RequestResponse::kUnknown;
}
}
using xdg_portal::RequestResponseFromPortalResponse;
} // namespace
@ -176,7 +162,13 @@ void ScreenCastPortal::OnSessionRequestResponseSignal(
that->RegisterSessionClosedSignalHandler(
OnSessionClosedSignal, parameters, that->connection_,
that->session_handle_, that->session_closed_signal_id_);
// Do not continue if we don't get session_handle back. The call above will
// already notify the capturer there is a failure, but we would still continue
// to make following request and crash on that.
if (!that->session_handle_.empty()) {
that->SourcesRequest();
}
}
// static
@ -357,7 +349,7 @@ void ScreenCastPortal::OnStartRequestResponseSignal(GDBusConnection* connection,
response_data.receive());
if (portal_response || !response_data) {
RTC_LOG(LS_ERROR) << "Failed to start the screen cast session.";
that->OnPortalDone(ToRequestResponseFromSignal(portal_response));
that->OnPortalDone(RequestResponseFromPortalResponse(portal_response));
return;
}

View file

@ -33,6 +33,21 @@ std::string RequestResponseToString(RequestResponse request) {
}
}
RequestResponse RequestResponseFromPortalResponse(uint32_t portal_response) {
// See:
// https://docs.flatpak.org/en/latest/portal-api-reference.html#gdbus-signal-org-freedesktop-portal-Request.Response
switch (portal_response) {
case 0:
return RequestResponse::kSuccess;
case 1:
return RequestResponse::kUserCancelled;
case 2:
return RequestResponse::kError;
default:
return RequestResponse::kUnknown;
}
}
std::string PrepareSignalHandle(absl::string_view token,
GDBusConnection* connection) {
Scoped<char> sender(

View file

@ -57,6 +57,8 @@ using SessionStartRequestedHandler = void (*)(GDBusProxy*,
std::string RequestResponseToString(RequestResponse request);
RequestResponse RequestResponseFromPortalResponse(uint32_t portal_response);
// Returns a string path for signal handle based on the provided connection and
// token.
std::string PrepareSignalHandle(absl::string_view token,