mirror of
https://github.com/electron/electron.git
synced 2026-05-02 03:00:22 -04:00
test: add tab source ID tests for media handler (#51095)
* test: add getMediaSourceId tab source coverage Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: move captureWithTabSourceId() to a shared helper Co-authored-by: Charles Kerr <charles@charleskerr.com> * test: improve "webContents module getMediaSourceId()" testing Co-authored-by: Charles Kerr <charles@charleskerr.com> --------- Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: Charles Kerr <charles@charleskerr.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import { expect } from 'chai';
|
||||
|
||||
import * as http from 'node:http';
|
||||
|
||||
import { captureWithTabSourceId } from './lib/media-helpers';
|
||||
import { ifit, listen } from './lib/spec-helpers';
|
||||
import { closeAllWindows } from './lib/window-helpers';
|
||||
|
||||
@@ -417,6 +418,37 @@ describe('setDisplayMediaRequestHandler', () => {
|
||||
expect(message).to.equal('Invalid state');
|
||||
});
|
||||
|
||||
it('works when mediaDevices.getUserMedia uses a tab source id from webContents.getMediaSourceId', async () => {
|
||||
const sourceWindow = new BrowserWindow({ show: false });
|
||||
const requestingWindow = new BrowserWindow({ show: false });
|
||||
await Promise.all([sourceWindow.loadURL(serverUrl), requestingWindow.loadURL(serverUrl)]);
|
||||
|
||||
const sourceId = sourceWindow.webContents.getMediaSourceId(requestingWindow.webContents);
|
||||
const { ok, message, origin, videoTrackCount } = await captureWithTabSourceId(requestingWindow, sourceId);
|
||||
|
||||
expect(ok).to.be.true(message);
|
||||
expect(origin).to.equal(new URL(serverUrl).origin);
|
||||
expect(videoTrackCount).to.equal(1);
|
||||
});
|
||||
|
||||
it('rejects a tab source id when used from a different requesting webContents', async () => {
|
||||
const sourceWindow = new BrowserWindow({ show: false });
|
||||
const registeredRequesterWindow = new BrowserWindow({ show: false });
|
||||
const otherRequesterWindow = new BrowserWindow({ show: false });
|
||||
await Promise.all([
|
||||
sourceWindow.loadURL(serverUrl),
|
||||
registeredRequesterWindow.loadURL(serverUrl),
|
||||
otherRequesterWindow.loadURL(serverUrl)
|
||||
]);
|
||||
|
||||
const sourceId = sourceWindow.webContents.getMediaSourceId(registeredRequesterWindow.webContents);
|
||||
const { ok, message, origin } = await captureWithTabSourceId(otherRequesterWindow, sourceId);
|
||||
|
||||
expect(ok).to.be.false();
|
||||
expect(message).to.match(/Invalid state|Error starting tab capture/);
|
||||
expect(origin).to.equal(new URL(serverUrl).origin);
|
||||
});
|
||||
|
||||
it('can remove a displayMediaRequestHandler', async () => {
|
||||
const ses = session.fromPartition('' + Math.random());
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import * as path from 'node:path';
|
||||
import { setTimeout } from 'node:timers/promises';
|
||||
import * as url from 'node:url';
|
||||
|
||||
import { captureWithTabSourceId } from './lib/media-helpers';
|
||||
import { ifdescribe, defer, waitUntil, listen, ifit } from './lib/spec-helpers';
|
||||
import { cleanupWebContents, closeAllWindows } from './lib/window-helpers';
|
||||
|
||||
@@ -1797,9 +1798,33 @@ describe('webContents module', () => {
|
||||
|
||||
describe('getMediaSourceId()', () => {
|
||||
afterEach(closeAllWindows);
|
||||
it('returns a valid stream id', () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
expect(w.webContents.getMediaSourceId(w.webContents)).to.be.a('string').that.is.not.empty();
|
||||
let server: http.Server;
|
||||
let serverUrl: string;
|
||||
|
||||
before(async () => {
|
||||
server = http.createServer((req, res) => {
|
||||
res.setHeader('Content-Type', 'text/html');
|
||||
res.end('');
|
||||
});
|
||||
serverUrl = (await listen(server)).url;
|
||||
});
|
||||
|
||||
after(() => {
|
||||
server.close();
|
||||
});
|
||||
|
||||
it('returns a stream id that can be used by the registered requester', async () => {
|
||||
const sourceWindow = new BrowserWindow({ show: false });
|
||||
const requesterWindow = new BrowserWindow({ show: false });
|
||||
await Promise.all([sourceWindow.loadURL(serverUrl), requesterWindow.loadURL(serverUrl)]);
|
||||
|
||||
const streamId = sourceWindow.webContents.getMediaSourceId(requesterWindow.webContents);
|
||||
const { ok, message, origin, videoTrackCount } = await captureWithTabSourceId(requesterWindow, streamId);
|
||||
|
||||
expect(streamId).to.be.a('string').that.is.not.empty();
|
||||
expect(ok, message).to.equal(true);
|
||||
expect(origin).to.equal(new url.URL(serverUrl).origin);
|
||||
expect(videoTrackCount).to.equal(1);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
39
spec/lib/media-helpers.ts
Normal file
39
spec/lib/media-helpers.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { BrowserWindow } from 'electron/main';
|
||||
|
||||
export interface TabSourceCaptureResult {
|
||||
ok: boolean;
|
||||
href: string;
|
||||
message?: string;
|
||||
origin: string;
|
||||
videoTrackCount?: number;
|
||||
}
|
||||
|
||||
export const captureWithTabSourceId = async (
|
||||
requestingWindow: BrowserWindow,
|
||||
streamId: string
|
||||
): Promise<TabSourceCaptureResult> => {
|
||||
return requestingWindow.webContents.executeJavaScript(`
|
||||
navigator.mediaDevices.getUserMedia({
|
||||
video: {
|
||||
mandatory: {
|
||||
chromeMediaSource: 'tab',
|
||||
chromeMediaSourceId: ${JSON.stringify(streamId)},
|
||||
},
|
||||
},
|
||||
}).then((stream) => {
|
||||
const result = {
|
||||
ok: stream instanceof MediaStream,
|
||||
href: location.href,
|
||||
origin: location.origin,
|
||||
videoTrackCount: stream.getVideoTracks().length,
|
||||
};
|
||||
stream.getTracks().forEach((track) => track.stop());
|
||||
return result;
|
||||
}, (error) => ({
|
||||
ok: false,
|
||||
href: location.href,
|
||||
message: error.message,
|
||||
origin: location.origin,
|
||||
}));
|
||||
`);
|
||||
};
|
||||
Reference in New Issue
Block a user