e36bb4e
diff -up firefox-83.0/browser/actors/WebRTCParent.jsm.pw6 firefox-83.0/browser/actors/WebRTCParent.jsm
e36bb4e
--- firefox-83.0/browser/actors/WebRTCParent.jsm.pw6	2020-11-12 19:04:30.000000000 +0100
e36bb4e
+++ firefox-83.0/browser/actors/WebRTCParent.jsm	2020-11-25 10:28:32.492865982 +0100
e36bb4e
@@ -45,6 +45,9 @@ XPCOMUtils.defineLazyServiceGetter(
d675653
   "nsIOSPermissionRequest"
d675653
 );
d675653
 
d675653
+const PIPEWIRE_PORTAL_NAME = "####_PIPEWIRE_PORTAL_####";
d675653
+const PIPEWIRE_ID = 0xaffffff;
d675653
+
d675653
 class WebRTCParent extends JSWindowActorParent {
d675653
   didDestroy() {
d675653
     webrtcUI.forgetStreamsFromBrowserContext(this.browsingContext);
e36bb4e
@@ -753,6 +756,8 @@ function prompt(aActor, aBrowser, aReque
e36bb4e
         );
e36bb4e
         menupopup.appendChild(doc.createXULElement("menuseparator"));
e36bb4e
 
e36bb4e
+        let isPipeWire = false;
e36bb4e
+
e36bb4e
         // Build the list of 'devices'.
e36bb4e
         let monitorIndex = 1;
e36bb4e
         for (let i = 0; i < devices.length; ++i) {
e36bb4e
@@ -774,6 +779,29 @@ function prompt(aActor, aBrowser, aReque
d675653
             }
d675653
           } else {
d675653
             name = device.name;
d675653
+            // When we share content by PipeWire add only one item to the device
d675653
+            // list. When it's selected PipeWire portal dialog is opened and
d675653
+            // user confirms actual window/screen sharing there.
d675653
+            // Don't mark it as scary as there's an extra confirmation step by
d675653
+            // PipeWire portal dialog.
d675653
+            if (name == PIPEWIRE_PORTAL_NAME && device.id == PIPEWIRE_ID) {
e36bb4e
+              isPipeWire = true;
e36bb4e
+              let name;
e36bb4e
+              try {
e36bb4e
+                name = stringBundle.getString("getUserMedia.sharePipeWirePortal.label");
e36bb4e
+              } catch (err) {
e36bb4e
+                name = "Use operating system settings"
e36bb4e
+              }
d675653
+              let item = addDeviceToList(
d675653
+                menupopup,
e36bb4e
+                name,
d675653
+                i,
d675653
+                type
d675653
+              );
d675653
+              item.deviceId = device.id;
d675653
+              item.mediaSource = type;
d675653
+              break;
d675653
+            }
d675653
             if (type == "application") {
d675653
               // The application names returned by the platform are of the form:
d675653
               // <window count>\x1e<application name>
e36bb4e
@@ -888,39 +916,41 @@ function prompt(aActor, aBrowser, aReque
e36bb4e
             perms.EXPIRE_SESSION
e36bb4e
           );
e36bb4e
 
e36bb4e
-          video.deviceId = deviceId;
e36bb4e
-          let constraints = {
e36bb4e
-            video: { mediaSource: type, deviceId: { exact: deviceId } },
e36bb4e
-          };
e36bb4e
-          chromeWin.navigator.mediaDevices.getUserMedia(constraints).then(
e36bb4e
-            stream => {
e36bb4e
-              if (video.deviceId != deviceId) {
e36bb4e
-                // The user has selected a different device or closed the panel
e36bb4e
-                // before getUserMedia finished.
e36bb4e
-                stream.getTracks().forEach(t => t.stop());
e36bb4e
-                return;
e36bb4e
-              }
e36bb4e
-              video.srcObject = stream;
e36bb4e
-              video.stream = stream;
e36bb4e
-              doc.getElementById("webRTC-preview").hidden = false;
e36bb4e
-              video.onloadedmetadata = function(e) {
e36bb4e
-                video.play();
e36bb4e
-              };
e36bb4e
-            },
e36bb4e
-            err => {
e36bb4e
-              if (
e36bb4e
-                err.name == "OverconstrainedError" &&
e36bb4e
-                err.constraint == "deviceId"
e36bb4e
-              ) {
e36bb4e
-                // Window has disappeared since enumeration, which can happen.
e36bb4e
-                // No preview for you.
e36bb4e
-                return;
e36bb4e
+          if (!isPipeWire) {
e36bb4e
+            video.deviceId = deviceId;
e36bb4e
+            let constraints = {
e36bb4e
+              video: { mediaSource: type, deviceId: { exact: deviceId } },
e36bb4e
+            };
e36bb4e
+            chromeWin.navigator.mediaDevices.getUserMedia(constraints).then(
e36bb4e
+              stream => {
e36bb4e
+                if (video.deviceId != deviceId) {
e36bb4e
+                  // The user has selected a different device or closed the panel
e36bb4e
+                  // before getUserMedia finished.
e36bb4e
+                  stream.getTracks().forEach(t => t.stop());
e36bb4e
+                  return;
e36bb4e
+                }
e36bb4e
+                video.srcObject = stream;
e36bb4e
+                video.stream = stream;
e36bb4e
+                doc.getElementById("webRTC-preview").hidden = false;
e36bb4e
+                video.onloadedmetadata = function(e) {
e36bb4e
+                  video.play();
e36bb4e
+                };
e36bb4e
+              },
e36bb4e
+              err => {
e36bb4e
+                if (
e36bb4e
+                  err.name == "OverconstrainedError" &&
e36bb4e
+                  err.constraint == "deviceId"
e36bb4e
+                ) {
e36bb4e
+                  // Window has disappeared since enumeration, which can happen.
e36bb4e
+                  // No preview for you.
e36bb4e
+                  return;
e36bb4e
+                }
e36bb4e
+                Cu.reportError(
e36bb4e
+                  `error in preview: ${err.message} ${err.constraint}`
e36bb4e
+                );
e36bb4e
               }
e36bb4e
-              Cu.reportError(
e36bb4e
-                `error in preview: ${err.message} ${err.constraint}`
e36bb4e
-              );
e36bb4e
-            }
e36bb4e
-          );
e36bb4e
+            );
e36bb4e
+          }
e36bb4e
         };
e36bb4e
         menupopup.addEventListener("command", menupopup._commandEventListener);
e36bb4e
       }
e36bb4e
diff -up firefox-83.0/browser/locales/en-US/chrome/browser/browser.properties.pw6 firefox-83.0/browser/locales/en-US/chrome/browser/browser.properties
e36bb4e
--- firefox-83.0/browser/locales/en-US/chrome/browser/browser.properties.pw6	2020-11-12 19:04:30.000000000 +0100
e36bb4e
+++ firefox-83.0/browser/locales/en-US/chrome/browser/browser.properties	2020-11-25 09:24:26.378857626 +0100
e36bb4e
@@ -764,6 +764,7 @@ getUserMedia.selectWindowOrScreen.label=
d675653
 getUserMedia.selectWindowOrScreen.accesskey=W
d675653
 getUserMedia.pickWindowOrScreen.label = Select Window or Screen
d675653
 getUserMedia.shareEntireScreen.label = Entire screen
d675653
+getUserMedia.sharePipeWirePortal.label = Use operating system settings
d675653
 # LOCALIZATION NOTE (getUserMedia.shareMonitor.label):
d675653
 # %S is screen number (digits 1, 2, etc)
d675653
 # Example: Screen 1, Screen 2,..
e36bb4e
diff -up firefox-83.0/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc.pw6 firefox-83.0/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc
e36bb4e
--- firefox-83.0/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc.pw6	2020-11-25 09:24:26.358857788 +0100
e36bb4e
+++ firefox-83.0/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc	2020-11-25 09:24:26.378857626 +0100
e36bb4e
@@ -879,17 +879,17 @@ void BaseCapturerPipeWire::CaptureFrame(
d675653
   callback_->OnCaptureResult(Result::SUCCESS, std::move(result));
d675653
 }
d675653
 
d675653
+#define PIPEWIRE_ID   0xaffffff
d675653
+#define PIPEWIRE_NAME "####_PIPEWIRE_PORTAL_####"
d675653
+
d675653
 bool BaseCapturerPipeWire::GetSourceList(SourceList* sources) {
d675653
-  RTC_DCHECK(sources->size() == 0);
d675653
-  // List of available screens is already presented by the xdg-desktop-portal.
d675653
-  // But we have to add an empty source as the code expects it.
d675653
-  sources->push_back({0});
d675653
+  sources->push_back({PIPEWIRE_ID, 0, PIPEWIRE_NAME});
d675653
   return true;
d675653
 }
d675653
 
d675653
 bool BaseCapturerPipeWire::SelectSource(SourceId id) {
d675653
   // Screen selection is handled by the xdg-desktop-portal.
d675653
-  return true;
d675653
+  return id == PIPEWIRE_ID;
d675653
 }
d675653
 
d675653
 // static