Repository: electron/electron (language: cpp)

Issue:
[Bug]: desktopCapturer fails to generate thumbnails after a PipeWire stream is cancelled externally
### Preflight Checklist

- [X] I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/main/CONTRIBUTING.md) for this project.
- [X] I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) that this project adheres to.
- [X] I have searched the [issue tracker](https://www.github.com/electron/electron/issues) for a bug report that matches the one I want to file, without success.

### Electron Version

25.3.0

### What operating system are you using?

Other Linux

### Operating System Version

Fedora 38

### What arch are you using?

x64

### Last Known Working Electron version

_No response_

### Expected Behavior

1. Get screencast sources using `desktopCapturer.getSources()` on Wayland
2. Select a source on the permission popup
3. Start a screencast stream using `navigator.mediaDevices.getUserMedia()`
4. Interrupt the stream by cancelling screen sharing using OS controls, like on the top bar of GNOME shell
5. Try to fetch screencast sources again using `desktopCapturer.getSources()`, with thumbnails
6. Select a source on the permission popup
7. Sources and thumbnails should be returned by  `desktopCapturer.getSources()`

### Actual Behavior

The second call to `desktopCapturer.getSources()` does not complete.

### Testcase Gist URL

https://gist.github.com/aiddya/d368bc2cb7f72a9b030b918ee1332299

### Additional Information

Filing this as a known issue. This issue is not reproducible with Chromium, so it's related to how `DesktopCapturer` and `NativeDesktopMediaList` objects are handled in Electron.


Discussion / hints:

Fix patch:
diff --git a/patches/webrtc/.patches b/patches/webrtc/.patches
index 495c94465691c..0cf4d364bb504 100644
--- a/patches/webrtc/.patches
+++ b/patches/webrtc/.patches
@@ -1,1 +1,2 @@
 fix_fallback_to_x11_capturer_on_wayland.patch
+fix_mark_pipewire_capturer_as_failed_after_session_is_closed.patch
diff --git a/patches/webrtc/fix_mark_pipewire_capturer_as_failed_after_session_is_closed.patch b/patches/webrtc/fix_mark_pipewire_capturer_as_failed_after_session_is_closed.patch
new file mode 100644
index 0000000000000..30327062058b8
--- /dev/null
+++ b/patches/webrtc/fix_mark_pipewire_capturer_as_failed_after_session_is_closed.patch
@@ -0,0 +1,26 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Athul Iddya <athul@iddya.com>
+Date: Sat, 22 Jul 2023 11:11:01 -0700
+Subject: fix: mark PipeWire capturer as failed after session is closed
+
+After a PipeWire screencast session is successfully started, the
+consumer is expected to keep calling CaptureFrame() from the
+DesktopCapturer interface in a loop to pull frames. A PipeWire
+screencast session can be closed by the server on user action. Once the
+session is closed, there's no point in calling CaptureFrame() again as
+the capture has to be restarted. Inform the caller of the failure by
+returning Result::ERROR_PERMANENT on the next invocation of
+CaptureFrame().
+
+diff --git a/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc b/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc
+index 4ef00e68ab58333648b8acaf4256f4b57a42734d..5a67c18c1d1f62aa5e3162d9778ca665bac4a1bb 100644
+--- a/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc
++++ b/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc
+@@ -109,6 +109,7 @@ void BaseCapturerPipeWire::OnScreenCastRequestResult(RequestResponse result,
+ void BaseCapturerPipeWire::OnScreenCastSessionClosed() {
+   if (!capturer_failed_) {
+     options_.screencast_stream()->StopScreenCastStream();
++    capturer_failed_ = true;
+   }
+ }
+ 
diff --git a/shell/browser/api/electron_api_desktop_capturer.cc b/shell/browser/api/electron_api_desktop_capturer.cc
index 5cfe0fedb9ef3..74530402e906d 100644
--- a/shell/browser/api/electron_api_desktop_capturer.cc
+++ b/shell/browser/api/electron_api_desktop_capturer.cc
@@ -399,6 +399,9 @@ void DesktopCapturer::UpdateSourcesList(DesktopMediaList* list) {
     v8::HandleScope scope(isolate);
     gin_helper::CallMethod(this, "_onfinished", captured_sources_);
 
+    screen_capturer_.reset();
+    window_capturer_.reset();
+
     Unpin();
   }
 }
@@ -408,6 +411,9 @@ void DesktopCapturer::HandleFailure() {
   v8::HandleScope scope(isolate);
   gin_helper::CallMethod(this, "_onerror", "Failed to get sources.");
 
+  screen_capturer_.reset();
+  window_capturer_.reset();
+
   Unpin();
 }
 


Test patch: