Bug 843971: Add MediaManager function to report what a window is capturing r=smaug
authorRandell Jesup <rjesup@jesup.org>
Wed, 27 Feb 2013 15:36:06 -0500
changeset 123206 3c22e7998e22325b6a2111da7c9c965595e5e18c
parent 123205 e125dce45cb734475fff25e1823202b3494ccc87
child 123207 58c7e618c860b6d37e8c55178b60c74e0c879eba
push id24373
push userryanvm@gmail.com
push dateThu, 28 Feb 2013 01:36:21 +0000
treeherdermozilla-central@8cb9d6981978 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs843971
milestone22.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 843971: Add MediaManager function to report what a window is capturing r=smaug
dom/media/MediaManager.cpp
dom/media/MediaManager.h
dom/media/nsIMediaManager.idl
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -8,16 +8,17 @@
 #include "nsIDOMFile.h"
 #include "nsIEventTarget.h"
 #include "nsIUUIDGenerator.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIPopupWindowManager.h"
 #include "nsISupportsArray.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
+#include "nsIDocShell.h"
 
 // For PR_snprintf
 #include "prprf.h"
 
 #include "nsJSUtils.h"
 #include "nsDOMFile.h"
 #include "nsGlobalWindow.h"
 
@@ -1294,16 +1295,91 @@ MediaManager::GetActiveMediaCaptureWindo
     return rv;
 
   mActiveWindows.EnumerateRead(WindowsHashToArrayFunc, array);
 
   *aArray = array;
   return NS_OK;
 }
 
+NS_IMETHODIMP
+MediaManager::MediaCaptureWindowState(nsIDOMWindow* aWindow, bool* aVideo,
+                                      bool* aAudio)
+{
+  *aVideo = false;
+  *aAudio = false;
+
+  nsresult rv = MediaCaptureWindowStateInternal(aWindow, aVideo, aAudio);
+#ifdef DEBUG
+  nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(aWindow);
+  LOG(("%s: window %lld capturing %s %s", __FUNCTION__, piWin ? piWin->WindowID() : -1,
+       *aVideo ? "video" : "", *aAudio ? "audio" : ""));
+#endif
+  return rv;
+}
+
+nsresult
+MediaManager::MediaCaptureWindowStateInternal(nsIDOMWindow* aWindow, bool* aVideo,
+                                              bool* aAudio)
+{
+  // We need to return the union of all streams in all innerwindows that
+  // correspond to that outerwindow.
+
+  // Iterate the docshell tree to find all the child windows, find
+  // all the listeners for each one, get the booleans, and merge the
+  // results.
+  nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(aWindow);
+  if (piWin) {
+    if (piWin->GetCurrentInnerWindow() || piWin->IsInnerWindow()) {
+      uint64_t windowID;
+      if (piWin->GetCurrentInnerWindow()) {
+        windowID = piWin->GetCurrentInnerWindow()->WindowID();
+      } else {
+        windowID = piWin->WindowID();
+      }
+      StreamListeners* listeners = GetActiveWindows()->Get(windowID);
+      if (listeners) {
+        uint32_t length = listeners->Length();
+        for (uint32_t i = 0; i < length; ++i) {
+          nsRefPtr<GetUserMediaCallbackMediaStreamListener> listener =
+            listeners->ElementAt(i);
+          if (listener->CapturingVideo()) {
+            *aVideo = true;
+          }
+          if (listener->CapturingAudio()) {
+            *aAudio = true;
+          }
+          if (*aAudio && *aVideo) {
+            return NS_OK; // no need to continue iterating
+          }
+        }
+      }
+    }
+
+    // iterate any children of *this* window (iframes, etc)
+    nsCOMPtr<nsIDocShellTreeNode> node =
+      do_QueryInterface(piWin->GetDocShell());
+    if (node) {
+      int32_t i, count;
+      node->GetChildCount(&count);
+      for (i = 0; i < count; ++i) {
+        nsCOMPtr<nsIDocShellTreeItem> item;
+        node->GetChildAt(i, getter_AddRefs(item));
+        nsCOMPtr<nsPIDOMWindow> win = do_GetInterface(item);
+
+        MediaCaptureWindowStateInternal(win, aVideo, aAudio);
+        if (*aAudio && *aVideo) {
+          return NS_OK; // no need to continue iterating
+        }
+      }
+    }
+  }
+  return NS_OK;
+}
+
 // Can be invoked from EITHER MainThread or MSG thread
 void
 GetUserMediaCallbackMediaStreamListener::Invalidate()
 {
 
   nsRefPtr<MediaOperationRunnable> runnable;
   // We can't take a chance on blocking here, so proxy this to another
   // thread.
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -123,16 +123,25 @@ public:
   {
     NS_ASSERTION(mStream,"Getting stream from never-activated GUMCMSListener");
     if (!mStream) {
       return nullptr;
     }
     return mStream->AsSourceStream();
   }
 
+  bool CapturingVideo()
+  {
+    return mVideoSource && mLastEndTimeVideo > 0 && !mFinished;
+  }
+  bool CapturingAudio()
+  {
+    return mAudioSource && mLastEndTimeAudio > 0 && !mFinished;
+  }
+
   // implement in .cpp to avoid circular dependency with MediaOperationRunnable
   // Can be invoked from EITHER MainThread or MSG thread
   void Invalidate();
 
   void
   AudioConfig(bool aEchoOn, uint32_t aEcho,
               bool aAgcOn, uint32_t aAGC,
               bool aNoiseOn, uint32_t aNoise)
@@ -420,16 +429,19 @@ private:
     mActiveWindows.Init();
     mActiveCallbacks.Init();
   }
 
   ~MediaManager() {
     delete mBackend;
   }
 
+  nsresult MediaCaptureWindowStateInternal(nsIDOMWindow* aWindow, bool* aVideo,
+                                           bool* aAudio);
+
   // ONLY access from MainThread so we don't need to lock
   WindowTable mActiveWindows;
   nsRefPtrHashtable<nsStringHashKey, nsRunnable> mActiveCallbacks;
   // Always exists
   nsCOMPtr<nsIThread> mMediaThread;
 
   Mutex mMutex;
   // protected with mMutex:
--- a/dom/media/nsIMediaManager.idl
+++ b/dom/media/nsIMediaManager.idl
@@ -1,18 +1,23 @@
 /* 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/. */
 
 #include "nsISupports.idl"
 
 interface nsISupportsArray;
+interface nsIDOMWindow;
 
 %{C++
 #define NS_MEDIAMANAGERSERVICE_CID {0xabc622ea, 0x9655, 0x4123, {0x80, 0xd9, 0x22, 0x62, 0x1b, 0xdd, 0x54, 0x65}}
 #define MEDIAMANAGERSERVICE_CONTRACTID "@mozilla.org/mediaManagerService;1"
 %}
 
-[scriptable, builtinclass, uuid(afe82ff1-2caa-4304-85da-0158a5dee56b)]
+[scriptable, builtinclass, uuid(2efff6ab-0e3e-4cc4-8f9b-4aaca59a1140)]
 interface nsIMediaManagerService : nsISupports
 {
+  /* return a array of inner windows that have active captures */
   readonly attribute nsISupportsArray activeMediaCaptureWindows;
+
+  /* Get the capture state for the given window and all descendant windows (iframes, etc) */
+  void mediaCaptureWindowState(in nsIDOMWindow aWindow, out boolean aVideo, out boolean aAudio);
 };