Bug 1254102 - Add "blackout" mode. If the window is not legal, output a black square. r?jesup draft
authorGian-Carlo Pascutto <gcp@mozilla.com>
Wed, 16 Mar 2016 19:21:17 +0100
changeset 341179 1a464ab9077a79de45cd415bc7483f24574a15c4
parent 341107 bf5e6511a8c3c201a0a4bb658b21b949f902a709
child 516362 709154dddc4c0e83895c364db518bb5a9fb03d24
push id13166
push usergpascutto@mozilla.com
push dateWed, 16 Mar 2016 18:22:07 +0000
reviewersjesup
bugs1254102
milestone48.0a1
Bug 1254102 - Add "blackout" mode. If the window is not legal, output a black square. r?jesup MozReview-Commit-ID: GlBy8fUZwIE
dom/media/webrtc/MediaEngineTabVideoSource.cpp
dom/media/webrtc/MediaEngineTabVideoSource.h
--- a/dom/media/webrtc/MediaEngineTabVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineTabVideoSource.cpp
@@ -37,16 +37,17 @@ MediaEngineTabVideoSource::MediaEngineTa
   , mWindowId(0)
   , mScrollWithPage(false)
   , mViewportOffsetX(0)
   , mViewportOffsetY(0)
   , mViewportWidth(0)
   , mViewportHeight(0)
   , mTimePerFrame(0)
   , mDataSize(0)
+  , mBlackedoutWindow(false)
   , mMonitor("MediaEngineTabVideoSource") {}
 
 nsresult
 MediaEngineTabVideoSource::StartRunnable::Run()
 {
   mVideoSource->Draw();
   mVideoSource->mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
   mVideoSource->mTimer->InitWithCallback(mVideoSource, mVideoSource->mTimePerFrame, nsITimer:: TYPE_REPEATING_SLACK);
@@ -75,40 +76,48 @@ MediaEngineTabVideoSource::HandleEvent(n
   return NS_OK;
 }
 
 NS_IMETHODIMP
 MediaEngineTabVideoSource::Notify(nsITimer*) {
   Draw();
   return NS_OK;
 }
-#define LOGTAG "TabVideo"
 
 nsresult
 MediaEngineTabVideoSource::InitRunnable::Run()
 {
   if (mVideoSource->mWindowId != -1) {
-    nsCOMPtr<nsPIDOMWindowOuter> window =
-      nsGlobalWindow::GetOuterWindowWithId(mVideoSource->mWindowId)->AsOuter();
-    if (window) {
-      mVideoSource->mWindow = window;
+    nsGlobalWindow* globalWindow =
+      nsGlobalWindow::GetOuterWindowWithId(mVideoSource->mWindowId);
+    if (!globalWindow) {
+      // We can't access the window, just send a blacked out screen.
+      mVideoSource->mWindow = nullptr;
+      mVideoSource->mBlackedoutWindow = true;
+    } else {
+      nsCOMPtr<nsPIDOMWindowOuter> window = globalWindow->AsOuter();
+      if (window) {
+        mVideoSource->mWindow = window;
+        mVideoSource->mBlackedoutWindow = false;
+      }
     }
   }
-  if (!mVideoSource->mWindow) {
+  if (!mVideoSource->mWindow && !mVideoSource->mBlackedoutWindow) {
     nsresult rv;
     mVideoSource->mTabSource = do_GetService(NS_TABSOURCESERVICE_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<mozIDOMWindowProxy> win;
     rv = mVideoSource->mTabSource->GetTabToStream(getter_AddRefs(win));
     NS_ENSURE_SUCCESS(rv, rv);
     if (!win)
       return NS_OK;
 
     mVideoSource->mWindow = nsPIDOMWindowOuter::From(win);
+    MOZ_ASSERT(mVideoSource->mWindow);
   }
   nsCOMPtr<nsIRunnable> start(new StartRunnable(mVideoSource));
   start->Run();
   return NS_OK;
 }
 
 void
 MediaEngineTabVideoSource::GetName(nsAString_internal& aName)
@@ -206,34 +215,43 @@ MediaEngineTabVideoSource::NotifyPull(Me
     // This can fail if either a) we haven't added the track yet, or b)
     // we've removed or finished the track.
     aSource->AppendToTrack(aID, &(segment));
   }
 }
 
 void
 MediaEngineTabVideoSource::Draw() {
-  if (!mWindow) {
+  if (!mWindow && !mBlackedoutWindow) {
     return;
   }
 
-  if (mScrollWithPage || mViewportWidth == INT32_MAX) {
-    mWindow->GetInnerWidth(&mViewportWidth);
-  }
-  if (mScrollWithPage || mViewportHeight == INT32_MAX) {
-    mWindow->GetInnerHeight(&mViewportHeight);
-  }
-  if (!mViewportWidth || !mViewportHeight) {
-    return;
+  if (mWindow) {
+    if (mScrollWithPage || mViewportWidth == INT32_MAX) {
+      mWindow->GetInnerWidth(&mViewportWidth);
+    }
+    if (mScrollWithPage || mViewportHeight == INT32_MAX) {
+      mWindow->GetInnerHeight(&mViewportHeight);
+    }
+    if (!mViewportWidth || !mViewportHeight) {
+      return;
+    }
+  } else {
+    mViewportWidth = 640;
+    mViewportHeight = 480;
   }
 
   IntSize size;
   {
     float pixelRatio;
-    mWindow->GetDevicePixelRatio(&pixelRatio);
+    if (mWindow) {
+      mWindow->GetDevicePixelRatio(&pixelRatio);
+    } else {
+      pixelRatio = 1.0f;
+    }
     const int32_t deviceWidth = (int32_t)(pixelRatio * mViewportWidth);
     const int32_t deviceHeight = (int32_t)(pixelRatio * mViewportHeight);
 
     if ((deviceWidth <= mBufWidthMax) && (deviceHeight <= mBufHeightMax)) {
       size = IntSize(deviceWidth, deviceHeight);
     } else {
       const float scaleWidth = (float)mBufWidthMax / (float)deviceWidth;
       const float scaleHeight = (float)mBufHeightMax / (float)deviceHeight;
@@ -250,69 +268,73 @@ MediaEngineTabVideoSource::Draw() {
     mDataSize = stride * size.height;
     mData = MakeUniqueFallible<unsigned char[]>(mDataSize);
   }
   if (!mData) {
     return;
   }
 
   nsCOMPtr<nsIPresShell> presShell;
-  {
+  if (mWindow) {
     RefPtr<nsPresContext> presContext;
     nsIDocShell* docshell = mWindow->GetDocShell();
     if (docshell) {
       docshell->GetPresContext(getter_AddRefs(presContext));
     }
     if (!presContext) {
       return;
     }
     presShell = presContext->PresShell();
   }
 
-  nscolor bgColor = NS_RGB(255, 255, 255);
-  uint32_t renderDocFlags = mScrollWithPage? 0 :
-      (nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING |
-       nsIPresShell::RENDER_DOCUMENT_RELATIVE);
-  nsRect r(nsPresContext::CSSPixelsToAppUnits((float)mViewportOffsetX),
-           nsPresContext::CSSPixelsToAppUnits((float)mViewportOffsetY),
-           nsPresContext::CSSPixelsToAppUnits((float)mViewportWidth),
-           nsPresContext::CSSPixelsToAppUnits((float)mViewportHeight));
-
   RefPtr<layers::ImageContainer> container = layers::LayerManager::CreateImageContainer();
   RefPtr<DrawTarget> dt =
     Factory::CreateDrawTargetForData(BackendType::CAIRO,
                                      mData.get(),
                                      size,
                                      stride,
                                      SurfaceFormat::B8G8R8X8);
   if (!dt) {
     return;
   }
   RefPtr<gfxContext> context = new gfxContext(dt);
   context->SetMatrix(context->CurrentMatrix().Scale((((float) size.width)/mViewportWidth),
                                                     (((float) size.height)/mViewportHeight)));
 
-  NS_ENSURE_SUCCESS_VOID(presShell->RenderDocument(r, renderDocFlags, bgColor, context));
+  if (mWindow) {
+    nscolor bgColor = NS_RGB(255, 255, 255);
+    uint32_t renderDocFlags = mScrollWithPage? 0 :
+      (nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING |
+       nsIPresShell::RENDER_DOCUMENT_RELATIVE);
+    nsRect r(nsPresContext::CSSPixelsToAppUnits((float)mViewportOffsetX),
+             nsPresContext::CSSPixelsToAppUnits((float)mViewportOffsetY),
+             nsPresContext::CSSPixelsToAppUnits((float)mViewportWidth),
+             nsPresContext::CSSPixelsToAppUnits((float)mViewportHeight));
+    NS_ENSURE_SUCCESS_VOID(presShell->RenderDocument(r, renderDocFlags, bgColor, context));
+  }
 
   RefPtr<SourceSurface> surface = dt->Snapshot();
   if (!surface) {
     return;
   }
 
   RefPtr<layers::SourceSurfaceImage> image = new layers::SourceSurfaceImage(size, surface);
 
   MonitorAutoLock mon(mMonitor);
   mImage = image;
 }
 
 nsresult
 MediaEngineTabVideoSource::Stop(mozilla::SourceMediaStream*, mozilla::TrackID)
 {
-  if (!mWindow)
+  // If mBlackedoutWindow is true, we may be running
+  // despite mWindow == nullptr.
+  if (!mWindow && !mBlackedoutWindow) {
     return NS_OK;
+  }
 
   NS_DispatchToMainThread(new StopRunnable(this));
   return NS_OK;
 }
 
 bool
 MediaEngineTabVideoSource::IsFake()
 {
--- a/dom/media/webrtc/MediaEngineTabVideoSource.h
+++ b/dom/media/webrtc/MediaEngineTabVideoSource.h
@@ -84,14 +84,16 @@ private:
     int32_t mViewportOffsetX;
     int32_t mViewportOffsetY;
     int32_t mViewportWidth;
     int32_t mViewportHeight;
     int32_t mTimePerFrame;
     UniquePtr<unsigned char[]> mData;
     size_t mDataSize;
     nsCOMPtr<nsPIDOMWindowOuter> mWindow;
+    // If this is set, we will run despite mWindow == nullptr.
+    bool mBlackedoutWindow;
     RefPtr<layers::SourceSurfaceImage> mImage;
     nsCOMPtr<nsITimer> mTimer;
     Monitor mMonitor;
     nsCOMPtr<nsITabSource> mTabSource;
   };
 }