1 /* vim: set ts=2 sw=2 sts=2 et tw=80: */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 * GlobalCaptureListener is a class that listens for changes to the global
8 * capture state of windows and screens. It uses this information to notify
9 * observers if it's possible that media is being shared by these captures.
10 * You probably only want one instance of this class per content process.
12 class GlobalCaptureListener {
14 Services.cpmm.sharedData.addEventListener("change", this);
15 // Tracks if screen capture is taking place based on shared data. Default
16 // to true for safety.
17 this._isScreenCaptured = true;
18 // Tracks if any windows are being captured. Default to true for safety.
19 this._isAnyWindowCaptured = true;
23 * Updates the capture state and forces that the state is notified to
24 * observers even if it hasn't changed since the last update.
26 requestUpdateAndNotify() {
27 this._updateCaptureState({ forceNotify: true });
31 * Handle changes in shared data that may alter the capture state.
32 * @param event a notification that sharedData has changed. If this includes
33 * changes to screen or window sharing state then we'll update the capture
38 event.changedKeys.includes("webrtcUI:isSharingScreen") ||
39 event.changedKeys.includes("webrtcUI:sharedTopInnerWindowIds")
41 this._updateCaptureState();
46 * Updates the capture state and notifies the state to observers if the
47 * state has changed since last update, or if forced.
48 * @param forceNotify if true then the capture state will be sent to
49 * observers even if it didn't change since the last update.
51 _updateCaptureState({ forceNotify = false } = {}) {
52 const previousCaptureState =
53 this._isScreenCaptured || this._isAnyWindowCaptured;
55 this._isScreenCaptured = Boolean(
56 Services.cpmm.sharedData.get("webrtcUI:isSharingScreen")
59 const capturedTopInnerWindowIds = Services.cpmm.sharedData.get(
60 "webrtcUI:sharedTopInnerWindowIds"
62 if (capturedTopInnerWindowIds && capturedTopInnerWindowIds.size > 0) {
63 this._isAnyWindowCaptured = true;
65 this._isAnyWindowCaptured = false;
67 const newCaptureState = this._isScreenCaptured || this._isAnyWindowCaptured;
69 const captureStateChanged = previousCaptureState != newCaptureState;
71 if (forceNotify || captureStateChanged) {
72 // Notify the state if the caller forces it, or if the state changed.
73 this._notifyCaptureState();
78 * Notifies observers of the current capture state. Notifies observers
79 * with a null subject, "mediakeys-response" topic, and data that is either
80 * "capture-possible" or "capture-not-possible", depending on if capture is
83 _notifyCaptureState() {
84 const isCapturePossible =
85 this._isScreenCaptured || this._isAnyWindowCaptured;
86 const isCapturePossibleString = isCapturePossible
88 : "capture-not-possible";
89 Services.obs.notifyObservers(
92 isCapturePossibleString
97 const gGlobalCaptureListener = new GlobalCaptureListener();
99 export class EncryptedMediaChild extends JSWindowActorChild {
100 // Expected to observe 'mediakeys-request' as notified from MediaKeySystemAccess.
101 // @param aSubject the nsPIDOMWindowInner associated with the notifying MediaKeySystemAccess.
102 // @param aTopic should be "mediakeys-request".
103 // @param aData json containing a `status` and a `keysystem`.
104 observe(aSubject, aTopic, aData) {
107 parsedData = JSON.parse(aData);
109 console.error("Malformed EME video message with data: ", aData);
112 const { status } = parsedData;
113 if (status == "is-capture-possible") {
114 // We handle this status in process -- don't send a message to the parent.
115 gGlobalCaptureListener.requestUpdateAndNotify();
119 this.sendAsyncMessage("EMEVideo:ContentMediaKeysRequest", aData);