diff options
Diffstat (limited to 'browser/base/content/test/webrtc/browser_webrtc_hooks.js')
-rw-r--r-- | browser/base/content/test/webrtc/browser_webrtc_hooks.js | 373 |
1 files changed, 373 insertions, 0 deletions
diff --git a/browser/base/content/test/webrtc/browser_webrtc_hooks.js b/browser/base/content/test/webrtc/browser_webrtc_hooks.js new file mode 100644 index 0000000000..0fe02d40da --- /dev/null +++ b/browser/base/content/test/webrtc/browser_webrtc_hooks.js @@ -0,0 +1,373 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const { webrtcUI } = ChromeUtils.import("resource:///modules/webrtcUI.jsm"); + +const ORIGIN = "https://example.com"; + +async function tryPeerConnection(browser, expectedError = null) { + let errtype = await SpecialPowers.spawn(browser, [], async function() { + let pc = new content.RTCPeerConnection(); + try { + await pc.createOffer({ offerToReceiveAudio: true }); + return null; + } catch (err) { + return err.name; + } + }); + + let detail = expectedError + ? `createOffer() threw a ${expectedError}` + : "createOffer() succeeded"; + is(errtype, expectedError, detail); +} + +// Helper for tests that use the peer-request-allowed and -blocked events. +// A test that expects some of those events does the following: +// - call Events.on() before the test to setup event handlers +// - call Events.expect(name) after a specific event is expected to have +// occured. This will fail if the event didn't occur, and will return +// the details passed to the handler for furhter checking. +// - call Events.off() at the end of the test to clean up. At this point, if +// any events were triggered that the test did not expect, the test fails. +const Events = { + events: ["peer-request-allowed", "peer-request-blocked"], + details: new Map(), + handlers: new Map(), + on() { + for (let event of this.events) { + let handler = data => { + if (this.details.has(event)) { + ok(false, `Got multiple ${event} events`); + } + this.details.set(event, data); + }; + webrtcUI.on(event, handler); + this.handlers.set(event, handler); + } + }, + expect(event) { + let result = this.details.get(event); + isnot(result, undefined, `${event} event was triggered`); + this.details.delete(event); + + // All events should have a good origin + is(result.origin, ORIGIN, `${event} event has correct origin`); + + return result; + }, + off() { + for (let event of this.events) { + webrtcUI.off(event, this.handlers.get(event)); + this.handlers.delete(event); + } + for (let [event] of this.details) { + ok(false, `Got unexpected event ${event}`); + } + }, +}; + +var gTests = [ + { + desc: "Basic peer-request-allowed event", + run: async function testPeerRequestEvent(browser) { + Events.on(); + + await tryPeerConnection(browser); + + let details = Events.expect("peer-request-allowed"); + isnot( + details.callID, + undefined, + "peer-request-allowed event includes callID" + ); + isnot( + details.windowID, + undefined, + "peer-request-allowed event includes windowID" + ); + + Events.off(); + }, + }, + + { + desc: "Immediate peer connection blocker can allow", + run: async function testBlocker(browser) { + Events.on(); + + let blockerCalled = false; + let blocker = params => { + is( + params.origin, + ORIGIN, + "Peer connection blocker origin parameter is correct" + ); + blockerCalled = true; + return "allow"; + }; + + webrtcUI.addPeerConnectionBlocker(blocker); + + await tryPeerConnection(browser); + is(blockerCalled, true, "Blocker was called"); + Events.expect("peer-request-allowed"); + + webrtcUI.removePeerConnectionBlocker(blocker); + Events.off(); + }, + }, + + { + desc: "Deferred peer connection blocker can allow", + run: async function testDeferredBlocker(browser) { + Events.on(); + + let blocker = params => Promise.resolve("allow"); + webrtcUI.addPeerConnectionBlocker(blocker); + + await tryPeerConnection(browser); + Events.expect("peer-request-allowed"); + + webrtcUI.removePeerConnectionBlocker(blocker); + Events.off(); + }, + }, + + { + desc: "Immediate peer connection blocker can deny", + run: async function testBlockerDeny(browser) { + Events.on(); + + let blocker = params => "deny"; + webrtcUI.addPeerConnectionBlocker(blocker); + + await tryPeerConnection(browser, "NotAllowedError"); + + Events.expect("peer-request-blocked"); + + webrtcUI.removePeerConnectionBlocker(blocker); + Events.off(); + }, + }, + + { + desc: "Multiple blockers work (both allow)", + run: async function testMultipleAllowBlockers(browser) { + Events.on(); + + let blocker1Called = false, + blocker1 = params => { + blocker1Called = true; + return "allow"; + }; + webrtcUI.addPeerConnectionBlocker(blocker1); + + let blocker2Called = false, + blocker2 = params => { + blocker2Called = true; + return "allow"; + }; + webrtcUI.addPeerConnectionBlocker(blocker2); + + await tryPeerConnection(browser); + + Events.expect("peer-request-allowed"); + ok(blocker1Called, "First blocker was called"); + ok(blocker2Called, "Second blocker was called"); + + webrtcUI.removePeerConnectionBlocker(blocker1); + webrtcUI.removePeerConnectionBlocker(blocker2); + Events.off(); + }, + }, + + { + desc: "Multiple blockers work (allow then deny)", + run: async function testAllowDenyBlockers(browser) { + Events.on(); + + let blocker1Called = false, + blocker1 = params => { + blocker1Called = true; + return "allow"; + }; + webrtcUI.addPeerConnectionBlocker(blocker1); + + let blocker2Called = false, + blocker2 = params => { + blocker2Called = true; + return "deny"; + }; + webrtcUI.addPeerConnectionBlocker(blocker2); + + await tryPeerConnection(browser, "NotAllowedError"); + + Events.expect("peer-request-blocked"); + ok(blocker1Called, "First blocker was called"); + ok(blocker2Called, "Second blocker was called"); + + webrtcUI.removePeerConnectionBlocker(blocker1); + webrtcUI.removePeerConnectionBlocker(blocker2); + Events.off(); + }, + }, + + { + desc: "Multiple blockers work (deny first)", + run: async function testDenyAllowBlockers(browser) { + Events.on(); + + let blocker1Called = false, + blocker1 = params => { + blocker1Called = true; + return "deny"; + }; + webrtcUI.addPeerConnectionBlocker(blocker1); + + let blocker2Called = false, + blocker2 = params => { + blocker2Called = true; + return "allow"; + }; + webrtcUI.addPeerConnectionBlocker(blocker2); + + await tryPeerConnection(browser, "NotAllowedError"); + + Events.expect("peer-request-blocked"); + ok(blocker1Called, "First blocker was called"); + ok( + !blocker2Called, + "Peer connection blocker after a deny is not invoked" + ); + + webrtcUI.removePeerConnectionBlocker(blocker1); + webrtcUI.removePeerConnectionBlocker(blocker2); + Events.off(); + }, + }, + + { + desc: "Blockers may be removed", + run: async function testRemoveBlocker(browser) { + Events.on(); + + let blocker1Called = false, + blocker1 = params => { + blocker1Called = true; + return "allow"; + }; + webrtcUI.addPeerConnectionBlocker(blocker1); + + let blocker2Called = false, + blocker2 = params => { + blocker2Called = true; + return "allow"; + }; + webrtcUI.addPeerConnectionBlocker(blocker2); + webrtcUI.removePeerConnectionBlocker(blocker1); + + await tryPeerConnection(browser); + + Events.expect("peer-request-allowed"); + + ok(!blocker1Called, "Removed peer connection blocker is not invoked"); + ok(blocker2Called, "Second peer connection blocker was invoked"); + + webrtcUI.removePeerConnectionBlocker(blocker2); + Events.off(); + }, + }, + + { + desc: "Blocker that throws is ignored", + run: async function testBlockerThrows(browser) { + Events.on(); + let blocker1Called = false, + blocker1 = params => { + blocker1Called = true; + throw new Error("kaboom"); + }; + webrtcUI.addPeerConnectionBlocker(blocker1); + + let blocker2Called = false, + blocker2 = params => { + blocker2Called = true; + return "allow"; + }; + webrtcUI.addPeerConnectionBlocker(blocker2); + + await tryPeerConnection(browser); + + Events.expect("peer-request-allowed"); + ok(blocker1Called, "First blocker was invoked"); + ok(blocker2Called, "Second blocker was invoked"); + + webrtcUI.removePeerConnectionBlocker(blocker1); + webrtcUI.removePeerConnectionBlocker(blocker2); + Events.off(); + }, + }, + + { + desc: "Cancel peer request", + run: async function testBlockerCancel(browser) { + let blocker, + blockerPromise = new Promise(resolve => { + blocker = params => { + resolve(); + // defer indefinitely + return new Promise(innerResolve => {}); + }; + }); + webrtcUI.addPeerConnectionBlocker(blocker); + + await SpecialPowers.spawn(browser, [], async function() { + new content.RTCPeerConnection().createOffer({ + offerToReceiveAudio: true, + }); + }); + + await blockerPromise; + + let eventPromise = new Promise(resolve => { + webrtcUI.on("peer-request-cancel", function listener(details) { + resolve(details); + webrtcUI.off("peer-request-cancel", listener); + }); + }); + + await SpecialPowers.spawn(browser, [], async function() { + content.location.reload(); + }); + + let details = await eventPromise; + isnot( + details.callID, + undefined, + "peer-request-cancel event includes callID" + ); + is( + details.origin, + ORIGIN, + "peer-request-cancel event has correct origin" + ); + + webrtcUI.removePeerConnectionBlocker(blocker); + }, + }, +]; + +add_task(async function test() { + await runTests(gTests, { + skipObserverVerification: true, + cleanup() { + is( + webrtcUI.peerConnectionBlockers.size, + 0, + "Peer connection blockers list is empty" + ); + }, + }); +}); |