feat: modify API to use useSystemPicker option

This commit is contained in:
Keeley Hammond 2024-08-28 15:05:20 -04:00
Родитель ea905b2e04
Коммит 5a7b61ffcd
Не найден ключ, соответствующий данной подписи
8 изменённых файлов: 59 добавлений и 48 удалений

Просмотреть файл

@ -16,19 +16,12 @@ app.whenReady().then(() => {
const mainWindow = new BrowserWindow()
session.defaultSession.setDisplayMediaRequestHandler((request, callback) => {
// If we should use the system picker
// Note: this is currently experimental
if (desktopCapturer.isDisplayMediaSystemPickerAvailable()) {
desktopCapturer.getNativePickerSource().then((source) => {
callback({ video: source })
return
})
}
desktopCapturer.getSources({ types: ['screen'] }).then((sources) => {
// Grant access to the first screen found.
// Your app shows some UI, but in this exampe
// grant access to the first screen found.
callback({ video: sources[0], audio: 'loopback' })
})
})
}, { useSystemPicker: true })
mainWindow.loadFile('index.html')
})
@ -46,7 +39,8 @@ startButton.addEventListener('click', () => {
video: {
width: 320,
height: 240,
frameRate: 30
frameRate: 30,
displaySurface: 'monitor'
}
}).then(stream => {
video.srcObject = stream
@ -102,7 +96,7 @@ which can detected by [`systemPreferences.getMediaAccessStatus`][].
[`navigator.mediaDevices.getUserMedia`]: https://developer.mozilla.org/en/docs/Web/API/MediaDevices/getUserMedia
[`systemPreferences.getMediaAccessStatus`]: system-preferences.md#systempreferencesgetmediaaccessstatusmediatype-windows-macos
### `desktopCapturer.isDisplayMediaSystemPickerAvailable()` _Experimental_ _MacOS_
### `desktopCapturer.isDisplayMediaSystemPickerAvailable()` _Experimental_ _macOS_
Returns `Boolean`, whether or not requesting desktop content via
the system picker is supported on this platform.
@ -112,12 +106,6 @@ true, use the `getNativePickerSource` method to return the system picker's
selected media stream. Not doing so may cause a warning dialog to your users
on macOS 15 and higher.
### `desktopCapturer.getNativePickerSource` _Experimental_ _Readonly_ _MacOS_
A `DesktopCapturerSource` property that should be used in conjunction with
[`session.setDisplayMediaRequestHandler`](./session.md#sessetdisplaymediarequesthandlerhandler) to use the system picker instead
of providing a specific video source from `getSources`.
## Caveats
`navigator.mediaDevices.getUserMedia` does not work on macOS for audio capture due to a fundamental limitation whereby apps that want to access the system's audio require a [signed kernel extension](https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/KernelExtensions/KernelExtensions.html). Chromium, and by extension Electron, does not provide this.

Просмотреть файл

@ -953,7 +953,7 @@ session.fromPartition('some-partition').setPermissionCheckHandler((webContents,
})
```
#### `ses.setDisplayMediaRequestHandler(handler)`
#### `ses.setDisplayMediaRequestHandler(handler[, opts])`
* `handler` Function | null
* `request` Object
@ -980,6 +980,8 @@ session.fromPartition('some-partition').setPermissionCheckHandler((webContents,
and this is set to `true`, then local playback of audio will not be muted (e.g. using `MediaRecorder`
to record `WebFrameMain` with this flag set to `true` will allow audio to pass through to the speakers
while recording). Default is `false`.
* `opts` Object (optional)
* `useSystemPicker` Boolean - true if a user wants to use the native system picker
This handler will be called when web content requests access to display media
via the `navigator.mediaDevices.getDisplayMedia` API. Use the

Просмотреть файл

@ -15,27 +15,6 @@ function isValid (options: Electron.SourcesOptions) {
export { isDisplayMediaSystemPickerAvailable };
export async function getNativePickerSource () {
if (process.platform !== 'darwin') {
throw new Error('Native system picker option is currently only supported on MacOS');
}
if (!isDisplayMediaSystemPickerAvailable) {
throw new Error(`Native system picker unavailable.
Note: This is an experimental API; please check the API documentation for updated restrictions`);
}
// Pass in the needed options for a more native experience
// screen & windows by default, no thumbnails, since the native picker doesn't return them
const options: Electron.SourcesOptions = {
types: ['screen', 'window'],
thumbnailSize: { width: 0, height: 0 },
fetchWindowIcons: false
};
return await getSources(options);
}
export async function getSources (args: Electron.SourcesOptions) {
if (!isValid(args)) throw new Error('Invalid options');

Просмотреть файл

@ -1,11 +1,46 @@
import { fetchWithSession } from '@electron/internal/browser/api/net-fetch';
import { net } from 'electron/main';
import { desktopCapturer, net } from 'electron/main';
const { fromPartition, fromPath, Session } = process._linkedBinding('electron_browser_session');
const { isDisplayMediaSystemPickerAvailable } = process._linkedBinding('electron_browser_desktop_capturer');
async function getNativePickerSource () {
if (process.platform !== 'darwin') {
throw new Error('Native system picker option is currently only supported on MacOS');
}
if (!isDisplayMediaSystemPickerAvailable) {
throw new Error(`Native system picker unavailable.
Note: This is an experimental API; please check the API documentation for updated restrictions`);
}
// Pass in the needed options for a more native experience
// screen & windows by default, no thumbnails, since the native picker doesn't return them
const options: Electron.SourcesOptions = {
types: ['screen', 'window'],
thumbnailSize: { width: 0, height: 0 },
fetchWindowIcons: false
};
const mediaStreams = await desktopCapturer.getSources(options);
return mediaStreams[0];
}
Session.prototype.fetch = function (input: RequestInfo, init?: RequestInit) {
return fetchWithSession(input, init, this, net.request);
};
Session.prototype.setDisplayMediaRequestHandler = function (handler, opts) {
if (!handler) return this._setDisplayMediaRequestHandler(handler, opts);
this._setDisplayMediaRequestHandler(async (req, callback) => {
if (opts && opts.useSystemPicker && isDisplayMediaSystemPickerAvailable()) {
return callback({ video: await getNativePickerSource() });
}
return handler(req, callback);
}, opts);
};
export default {
fromPartition,
fromPath,

Просмотреть файл

@ -110,10 +110,10 @@ index 2215bf4589342fa4619fb58ec3e21ff5ef3ed3b4..3e52ce331b80cf97fd7b9bcbf7dd4311
// There was a bug in ScreenCaptureKit that was fixed in 14.4,
// see b/40076027.
diff --git a/content/browser/media/capture/native_screen_capture_picker_mac.mm b/content/browser/media/capture/native_screen_capture_picker_mac.mm
index b5a776f37b4bb667bc1aa62a08102b67a12f5b64..36b1508f0a8bd17bec0e49bf797a64c2fcc38bc2 100644
index b34d8402c213329620683e41588c0411d45124fb..1b8e95f476a032f60ea7e578fac480344924ab50 100644
--- a/content/browser/media/capture/native_screen_capture_picker_mac.mm
+++ b/content/browser/media/capture/native_screen_capture_picker_mac.mm
@@ -117,8 +117,11 @@ void Open(DesktopMediaID::Type type,
@@ -132,8 +132,11 @@ void Open(DesktopMediaID::Type type,
base::OnceCallback<void()> cancel_callback,
base::OnceCallback<void()> error_callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@ -126,14 +126,13 @@ index b5a776f37b4bb667bc1aa62a08102b67a12f5b64..36b1508f0a8bd17bec0e49bf797a64c2
if (@available(macOS 14.0, *)) {
NSNumber* source_id = @(next_id_);
auto picker_observer = [[PickerObserver alloc]
@@ -135,20 +138,14 @@ void Open(DesktopMediaID::Type type,
@@ -150,19 +153,13 @@ void Open(DesktopMediaID::Type type,
// TODO(https://crbug.com/360781940): Add support for changing selected
// content. The problem to solve is how this should interact with stream
// restart.
- config.allowsChangingSelectedContent = false;
+ config.allowsChangingSelectedContent = true;
// Limits the maximum number of screen/window capture to 5.
NSNumber* max_stream_count = @5;
NSNumber* max_stream_count = @(kMaxContentShareCountValue.Get());
- if (type == DesktopMediaID::Type::TYPE_SCREEN) {
- config.allowedPickerModes = SCContentSharingPickerModeSingleDisplay;
- picker.defaultConfiguration = config;

Просмотреть файл

@ -14,4 +14,4 @@ bool DesktopCapturer::IsDisplayMediaSystemPickerAvailable() {
return false;
}
} // namespace electron::api
} // namespace electron::api

Просмотреть файл

@ -1607,7 +1607,7 @@ void Session::FillObjectTemplate(v8::Isolate* isolate,
&Session::SetPermissionRequestHandler)
.SetMethod("setPermissionCheckHandler",
&Session::SetPermissionCheckHandler)
.SetMethod("setDisplayMediaRequestHandler",
.SetMethod("_setDisplayMediaRequestHandler",
&Session::SetDisplayMediaRequestHandler)
.SetMethod("setDevicePermissionHandler",
&Session::SetDevicePermissionHandler)

8
typings/internal-electron.d.ts поставляемый
Просмотреть файл

@ -127,6 +127,14 @@ declare namespace Electron {
type?: 'backgroundPage' | 'window' | 'browserView' | 'remote' | 'webview' | 'offscreen';
}
interface Session {
_setDisplayMediaRequestHandler: Electron.Session['setDisplayMediaRequestHandler'];
}
interface DisplayMediaRequestHandlerOpts {
userSystemPicker: boolean,
}
type CreateWindowFunction = (options: BrowserWindowConstructorOptions) => WebContents;
interface Menu {