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