Bug 1845017 - Disable the TestPHCExhaustion test r=glandium
[gecko.git] / browser / actors / EncryptedMediaChild.sys.mjs
blob7db643df67f1736f707d88ef76bba77f8aacfc1e
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/. */
6 /**
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.
11  */
12 class GlobalCaptureListener {
13   constructor() {
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;
20   }
22   /**
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.
25    */
26   requestUpdateAndNotify() {
27     this._updateCaptureState({ forceNotify: true });
28   }
30   /**
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
34    * state.
35    */
36   handleEvent(event) {
37     if (
38       event.changedKeys.includes("webrtcUI:isSharingScreen") ||
39       event.changedKeys.includes("webrtcUI:sharedTopInnerWindowIds")
40     ) {
41       this._updateCaptureState();
42     }
43   }
45   /**
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.
50    */
51   _updateCaptureState({ forceNotify = false } = {}) {
52     const previousCaptureState =
53       this._isScreenCaptured || this._isAnyWindowCaptured;
55     this._isScreenCaptured = Boolean(
56       Services.cpmm.sharedData.get("webrtcUI:isSharingScreen")
57     );
59     const capturedTopInnerWindowIds = Services.cpmm.sharedData.get(
60       "webrtcUI:sharedTopInnerWindowIds"
61     );
62     if (capturedTopInnerWindowIds && capturedTopInnerWindowIds.size > 0) {
63       this._isAnyWindowCaptured = true;
64     } else {
65       this._isAnyWindowCaptured = false;
66     }
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();
74     }
75   }
77   /**
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
81    * possible or not.
82    */
83   _notifyCaptureState() {
84     const isCapturePossible =
85       this._isScreenCaptured || this._isAnyWindowCaptured;
86     const isCapturePossibleString = isCapturePossible
87       ? "capture-possible"
88       : "capture-not-possible";
89     Services.obs.notifyObservers(
90       null,
91       "mediakeys-response",
92       isCapturePossibleString
93     );
94   }
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) {
105     let parsedData;
106     try {
107       parsedData = JSON.parse(aData);
108     } catch (ex) {
109       console.error("Malformed EME video message with data: ", aData);
110       return;
111     }
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();
116       return;
117     }
119     this.sendAsyncMessage("EMEVideo:ContentMediaKeysRequest", aData);
120   }