forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			121 lines
		
	
	
	
		
			4.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
	
		
			4.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* vim: set ts=2 sw=2 sts=2 et tw=80: */
 | |
| /* 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/. */
 | |
| 
 | |
| /**
 | |
|  * GlobalCaptureListener is a class that listens for changes to the global
 | |
|  * capture state of windows and screens. It uses this information to notify
 | |
|  * observers if it's possible that media is being shared by these captures.
 | |
|  * You probably only want one instance of this class per content process.
 | |
|  */
 | |
| class GlobalCaptureListener {
 | |
|   constructor() {
 | |
|     Services.cpmm.sharedData.addEventListener("change", this);
 | |
|     // Tracks if screen capture is taking place based on shared data. Default
 | |
|     // to true for safety.
 | |
|     this._isScreenCaptured = true;
 | |
|     // Tracks if any windows are being captured. Default to true for safety.
 | |
|     this._isAnyWindowCaptured = true;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Updates the capture state and forces that the state is notified to
 | |
|    * observers even if it hasn't changed since the last update.
 | |
|    */
 | |
|   requestUpdateAndNotify() {
 | |
|     this._updateCaptureState({ forceNotify: true });
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Handle changes in shared data that may alter the capture state.
 | |
|    * @param event a notification that sharedData has changed. If this includes
 | |
|    * changes to screen or window sharing state then we'll update the capture
 | |
|    * state.
 | |
|    */
 | |
|   handleEvent(event) {
 | |
|     if (
 | |
|       event.changedKeys.includes("webrtcUI:isSharingScreen") ||
 | |
|       event.changedKeys.includes("webrtcUI:sharedTopInnerWindowIds")
 | |
|     ) {
 | |
|       this._updateCaptureState();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Updates the capture state and notifies the state to observers if the
 | |
|    * state has changed since last update, or if forced.
 | |
|    * @param forceNotify if true then the capture state will be sent to
 | |
|    * observers even if it didn't change since the last update.
 | |
|    */
 | |
|   _updateCaptureState({ forceNotify = false } = {}) {
 | |
|     const previousCaptureState =
 | |
|       this._isScreenCaptured || this._isAnyWindowCaptured;
 | |
| 
 | |
|     this._isScreenCaptured = Boolean(
 | |
|       Services.cpmm.sharedData.get("webrtcUI:isSharingScreen")
 | |
|     );
 | |
| 
 | |
|     const capturedTopInnerWindowIds = Services.cpmm.sharedData.get(
 | |
|       "webrtcUI:sharedTopInnerWindowIds"
 | |
|     );
 | |
|     if (capturedTopInnerWindowIds && capturedTopInnerWindowIds.size > 0) {
 | |
|       this._isAnyWindowCaptured = true;
 | |
|     } else {
 | |
|       this._isAnyWindowCaptured = false;
 | |
|     }
 | |
|     const newCaptureState = this._isScreenCaptured || this._isAnyWindowCaptured;
 | |
| 
 | |
|     const captureStateChanged = previousCaptureState != newCaptureState;
 | |
| 
 | |
|     if (forceNotify || captureStateChanged) {
 | |
|       // Notify the state if the caller forces it, or if the state changed.
 | |
|       this._notifyCaptureState();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Notifies observers of the current capture state. Notifies observers
 | |
|    * with a null subject, "mediakeys-response" topic, and data that is either
 | |
|    * "capture-possible" or "capture-not-possible", depending on if capture is
 | |
|    * possible or not.
 | |
|    */
 | |
|   _notifyCaptureState() {
 | |
|     const isCapturePossible =
 | |
|       this._isScreenCaptured || this._isAnyWindowCaptured;
 | |
|     const isCapturePossibleString = isCapturePossible
 | |
|       ? "capture-possible"
 | |
|       : "capture-not-possible";
 | |
|     Services.obs.notifyObservers(
 | |
|       null,
 | |
|       "mediakeys-response",
 | |
|       isCapturePossibleString
 | |
|     );
 | |
|   }
 | |
| }
 | |
| 
 | |
| const gGlobalCaptureListener = new GlobalCaptureListener();
 | |
| 
 | |
| export class EncryptedMediaChild extends JSWindowActorChild {
 | |
|   // Expected to observe 'mediakeys-request' as notified from MediaKeySystemAccess.
 | |
|   // @param aSubject the nsPIDOMWindowInner associated with the notifying MediaKeySystemAccess.
 | |
|   // @param aTopic should be "mediakeys-request".
 | |
|   // @param aData json containing a `status` and a `keysystem`.
 | |
|   observe(aSubject, aTopic, aData) {
 | |
|     let parsedData;
 | |
|     try {
 | |
|       parsedData = JSON.parse(aData);
 | |
|     } catch (ex) {
 | |
|       console.error("Malformed EME video message with data: ", aData);
 | |
|       return;
 | |
|     }
 | |
|     const { status } = parsedData;
 | |
|     if (status == "is-capture-possible") {
 | |
|       // We handle this status in process -- don't send a message to the parent.
 | |
|       gGlobalCaptureListener.requestUpdateAndNotify();
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     this.sendAsyncMessage("EMEVideo:ContentMediaKeysRequest", aData);
 | |
|   }
 | |
| }
 | 
