Bug 983504 - Modify constraints for screen sharing. r=bholley,jib
authorMatthew A. Miller <linuxwolf@outer-planes.net>
Tue, 08 Jul 2014 00:01:27 -0600
changeset 194415 49e5c7d46ea0cd9515d292131259ac539652ce2b
parent 194414 911234d51c81820df05b0b7222289a6543e316a4
child 194416 bef05df2ed8a61fe5d50f79b6e7d9fa915400ba4
push id27145
push userkwierso@gmail.com
push dateThu, 17 Jul 2014 00:08:55 +0000
treeherdermozilla-central@8e8f3ba64655 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley, jib
bugs983504
milestone33.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 983504 - Modify constraints for screen sharing. r=bholley,jib
content/media/webrtc/MediaTrackConstraints.h
dom/media/MediaManager.cpp
dom/media/MediaManager.h
dom/media/nsIDOMNavigatorUserMedia.idl
dom/webidl/Constraints.webidl
dom/webidl/MediaTrackConstraintSet.webidl
modules/libpref/src/init/all.js
--- a/content/media/webrtc/MediaTrackConstraints.h
+++ b/content/media/webrtc/MediaTrackConstraints.h
@@ -37,16 +37,29 @@ public:
         auto value = ToEnum(array[i]);
         if (value != Kind::Other) {
           mRequireN.AppendElement(value);
         } else {
           mUnsupportedRequirement = true;
         }
       }
     }
+
+    // treat MediaSource special because it's always required
+    mRequired.mMediaSource = mMediaSource;
+
+    if (mMediaSource != dom::MediaSourceEnum::Camera && mAdvanced.WasPassed()) {
+      // iterate through advanced, forcing mediaSource to match "root"
+      auto& array = mAdvanced.Value();
+      for (uint32_t i = 0; i < array.Length(); i++) {
+        if (array[i].mMediaSource == dom::MediaSourceEnum::Camera) {
+          array[i].mMediaSource = mMediaSource;
+        }
+      }
+    }
   }
 protected:
   MediaTrackConstraintSet& Triage(const Kind kind) {
     if (mRequireN.IndexOf(kind) != mRequireN.NoIndex) {
       return mRequired;
     } else {
       mNonrequired.AppendElement(MediaTrackConstraintSet());
       return mNonrequired[mNonrequired.Length()-1];
@@ -80,14 +93,17 @@ struct VideoTrackConstraintsN :
                            dom::SupportedVideoConstraintsValues::strings) {
     if (mFacingMode.WasPassed()) {
       Triage(Kind::FacingMode).mFacingMode.Construct(mFacingMode.Value());
     }
     // Reminder: add handling for new constraints both here & SatisfyConstraintSet
     Triage(Kind::Width).mWidth = mWidth;
     Triage(Kind::Height).mHeight = mHeight;
     Triage(Kind::FrameRate).mFrameRate = mFrameRate;
+
+    // treat MediaSource special because it's always required
+    mRequired.mMediaSource = mMediaSource;
   }
 };
 
 }
 
 #endif /* MEDIATRACKCONSTRAINTS_H_ */
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -305,16 +305,19 @@ VideoDevice::VideoDevice(MediaEngineVide
   }
 #endif // MOZ_B2G_CAMERA
 
   // Kludge to test user-facing cameras on OSX.
   if (mName.Find(NS_LITERAL_STRING("Face")) != -1) {
     mHasFacingMode = true;
     mFacingMode = dom::VideoFacingModeEnum::User;
   }
+
+  // dom::MediaSourceEnum::Camera;
+  mMediaSource = aSource->GetMediaSource();
 }
 
 AudioDevice::AudioDevice(MediaEngineAudioSource* aSource)
   : MediaDevice(aSource) {}
 
 NS_IMETHODIMP
 MediaDevice::GetName(nsAString& aName)
 {
@@ -356,16 +359,25 @@ MediaDevice::GetFacingMode(nsAString& aF
     aFacingMode.Assign(NS_ConvertUTF8toUTF16(
         dom::VideoFacingModeEnumValues::strings[uint32_t(mFacingMode)].value));
   } else {
     aFacingMode.Truncate(0);
   }
   return NS_OK;
 }
 
+NS_IMETHODIMP
+MediaDevice::GetMediaSource(nsAString& aMediaSource)
+{
+
+  aMediaSource.Assign(NS_ConvertUTF8toUTF16(
+    dom::MediaSourceEnumValues::strings[uint32_t(mMediaSource)].value));
+  return NS_OK;
+}
+
 MediaEngineVideoSource*
 VideoDevice::GetSource()
 {
   return static_cast<MediaEngineVideoSource*>(&*mSource);
 }
 
 MediaEngineAudioSource*
 AudioDevice::GetSource()
@@ -709,24 +721,29 @@ GetInvariant(const OwningBooleanOrMediaT
  */
 
 // Reminder: add handling for new constraints both here and in GetSources below!
 
 static bool SatisfyConstraintSet(const MediaEngineVideoSource *,
                                  const MediaTrackConstraintSet &aConstraints,
                                  nsIMediaDevice &aCandidate)
 {
+  nsString s;
   if (aConstraints.mFacingMode.WasPassed()) {
-    nsString s;
     aCandidate.GetFacingMode(s);
     if (!s.EqualsASCII(dom::VideoFacingModeEnumValues::strings[
         uint32_t(aConstraints.mFacingMode.Value())].value)) {
       return false;
     }
   }
+  aCandidate.GetMediaSource(s);
+  if (!s.EqualsASCII(dom::MediaSourceEnumValues::strings[
+      uint32_t(aConstraints.mMediaSource)].value)) {
+    return false;
+  }
   // TODO: Add more video-specific constraints
   return true;
 }
 
 static bool SatisfyConstraintSet(const MediaEngineAudioSource *,
                                  const MediaTrackConstraintSet &aConstraints,
                                  nsIMediaDevice &aCandidate)
 {
@@ -737,28 +754,28 @@ static bool SatisfyConstraintSet(const M
 typedef nsTArray<nsCOMPtr<nsIMediaDevice> > SourceSet;
 
 // Source getter that constrains list returned
 
 template<class SourceType, class ConstraintsType>
 static SourceSet *
   GetSources(MediaEngine *engine,
              ConstraintsType &aConstraints,
-             void (MediaEngine::* aEnumerate)(nsTArray<nsRefPtr<SourceType> >*),
+             void (MediaEngine::* aEnumerate)(dom::MediaSourceEnum, nsTArray<nsRefPtr<SourceType> >*),
              const char* media_device_name = nullptr)
 {
   ScopedDeletePtr<SourceSet> result(new SourceSet);
 
   const SourceType * const type = nullptr;
   nsString deviceName;
   // First collect sources
   SourceSet candidateSet;
   {
     nsTArray<nsRefPtr<SourceType> > sources;
-    (engine->*aEnumerate)(&sources);
+    (engine->*aEnumerate)(aConstraints.mMediaSource, &sources);
     /**
       * We're allowing multiple tabs to access the same camera for parity
       * with Chrome.  See bug 811757 for some of the issues surrounding
       * this decision.  To disallow, we'd filter by IsAvailable() as we used
       * to.
       */
     for (uint32_t len = sources.Length(), i = 0; i < len; i++) {
       sources[i]->GetName(deviceName);
@@ -1013,18 +1030,18 @@ public:
 
   nsresult
   SelectDevice(MediaEngine* backend)
   {
     MOZ_ASSERT(mSuccess);
     MOZ_ASSERT(mError);
     if (mConstraints.mPicture || IsOn(mConstraints.mVideo)) {
       VideoTrackConstraintsN constraints(GetInvariant(mConstraints.mVideo));
-      ScopedDeletePtr<SourceSet> sources (GetSources(backend, constraints,
-          &MediaEngine::EnumerateVideoDevices));
+      ScopedDeletePtr<SourceSet> sources(GetSources(backend, constraints,
+                               &MediaEngine::EnumerateVideoDevices));
 
       if (!sources->Length()) {
         Fail(NS_LITERAL_STRING("NO_DEVICES_FOUND"));
         return NS_ERROR_FAILURE;
       }
       // Pick the first available device.
       mVideoDevice = do_QueryObject((*sources)[0]);
       LOG(("Selected video device"));
@@ -1175,27 +1192,28 @@ public:
       backend = new MediaEngineDefault();
     else
       backend = mManager->GetBackend(mWindowId);
 
     ScopedDeletePtr<SourceSet> final(new SourceSet);
     if (IsOn(mConstraints.mVideo)) {
       VideoTrackConstraintsN constraints(GetInvariant(mConstraints.mVideo));
       ScopedDeletePtr<SourceSet> s(GetSources(backend, constraints,
-          &MediaEngine::EnumerateVideoDevices,
-          mLoopbackVideoDevice.get()));
+              &MediaEngine::EnumerateVideoDevices,
+              mLoopbackVideoDevice.get()));
       final->MoveElementsFrom(*s);
     }
     if (IsOn(mConstraints.mAudio)) {
       AudioTrackConstraintsN constraints(GetInvariant(mConstraints.mAudio));
       ScopedDeletePtr<SourceSet> s (GetSources(backend, constraints,
           &MediaEngine::EnumerateAudioDevices,
           mLoopbackAudioDevice.get()));
       final->MoveElementsFrom(*s);
     }
+
     NS_DispatchToMainThread(new DeviceSuccessCallbackRunnable(mWindowId,
                                                               mSuccess, mError,
                                                               final.forget()));
     // DeviceSuccessCallbackRunnable should have taken these.
     MOZ_ASSERT(!mSuccess && !mError);
     return NS_OK;
   }
 
@@ -1460,16 +1478,25 @@ MediaManager::GetUserMedia(bool aPrivile
     runnable = new GetUserMediaRunnable(c, onSuccess.forget(),
       onError.forget(), windowID, listener, mPrefs, new MediaEngineDefault());
   } else {
     // Stream from default device from WebRTC backend.
     runnable = new GetUserMediaRunnable(c, onSuccess.forget(),
       onError.forget(), windowID, listener, mPrefs);
   }
 
+  // deny screensharing request if support is disabled
+  if (c.mVideo.IsMediaTrackConstraints() &&
+      !Preferences::GetBool("media.getusermedia.screensharing.enabled", false)) {
+    auto& tc = c.mVideo.GetAsMediaTrackConstraints();
+    if (tc.mMediaSource != dom::MediaSourceEnum::Camera) {
+      return runnable->Denied(NS_LITERAL_STRING("PERMISSION_DENIED"));
+    }
+  }
+
 #ifdef MOZ_B2G_CAMERA
   if (mCameraManager == nullptr) {
     mCameraManager = nsDOMCameraManager::CreateInstance(aWindow);
   }
 #endif
 
 #if defined(ANDROID) && !defined(MOZ_WIDGET_GONK)
   if (c.mPicture) {
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -481,16 +481,17 @@ public:
 
 protected:
   virtual ~MediaDevice() {}
   MediaDevice(MediaEngineSource* aSource);
   nsString mName;
   nsString mID;
   bool mHasFacingMode;
   dom::VideoFacingModeEnum mFacingMode;
+  dom::MediaSourceEnum mMediaSource;
   nsRefPtr<MediaEngineSource> mSource;
 };
 
 class VideoDevice : public MediaDevice
 {
 public:
   VideoDevice(MediaEngineVideoSource* aSource);
   NS_IMETHOD GetType(nsAString& aType);
--- a/dom/media/nsIDOMNavigatorUserMedia.idl
+++ b/dom/media/nsIDOMNavigatorUserMedia.idl
@@ -8,16 +8,17 @@
 
 [scriptable, builtinclass, uuid(4af2bdb7-1547-4d10-8886-02a78c3c0b83)]
 interface nsIMediaDevice : nsISupports
 {
   readonly attribute DOMString type;
   readonly attribute DOMString name;
   readonly attribute DOMString id;
   readonly attribute DOMString facingMode;
+  readonly attribute DOMString mediaSource;
 };
 
 [scriptable, function, uuid(24544878-d35e-4962-8c5f-fb84e97bdfee)]
 interface nsIGetUserMediaDevicesSuccessCallback : nsISupports
 {
   void onSuccess(in nsIVariant devices);
 };
 
--- a/dom/webidl/Constraints.webidl
+++ b/dom/webidl/Constraints.webidl
@@ -9,16 +9,22 @@
 
 enum VideoFacingModeEnum {
     "user",
     "environment",
     "left",
     "right"
 };
 
+enum MediaSourceEnum {
+    "camera",
+    "screen",
+    "application"
+};
+
 dictionary ConstrainLongRange {
     long min = -2147483647; // +1 works around windows compiler bug
     long max = 2147483647;
 };
 
 dictionary ConstrainDoubleRange {
     unrestricted double min = -Infinity;
     unrestricted double max = Infinity;
--- a/dom/webidl/MediaTrackConstraintSet.webidl
+++ b/dom/webidl/MediaTrackConstraintSet.webidl
@@ -8,28 +8,34 @@
  */
 
 enum SupportedVideoConstraints {
     "other",
     "facingMode",
     "width",
     "height",
     "frameRate",
+    "mediaSource"
 };
 
 enum SupportedAudioConstraints {
     "other"
 };
 
+
 dictionary MediaTrackConstraintSet {
     ConstrainLongRange width;
     ConstrainLongRange height;
     ConstrainDoubleRange frameRate;
     ConstrainVideoFacingMode facingMode;
+    ConstrainMediaSource mediaSource = "camera";
 };
 
 // TODO: Bug 995352 can't nest unions
 //typedef (long or ConstrainLongRange) ConstrainLong;
 //typedef (double or ConstrainDoubleRange) ConstrainDouble;
 
 typedef VideoFacingModeEnum ConstrainVideoFacingMode;
+typedef MediaSourceEnum ConstrainMediaSource;
+
 // TODO: Bug 767924 sequences in unions
 //typedef (VideoFacingModeEnum or sequence<VideoFacingModeEnum>) ConstrainVideoFacingMode;
+//typedef (MediaSourceEnum or sequence<MediaSourceEnum>) ConstrainMediaSource;
\ No newline at end of file
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -352,16 +352,22 @@ pref("media.peerconnection.capture_delay
 pref("media.getusermedia.playout_delay", 50);
 #endif
 #else
 #ifdef ANDROID
 pref("media.navigator.enabled", true);
 #endif
 #endif
 
+// do not enable screensharing before addressing security concerns: Bug 1035577
+// do not enable screensharing before implementing app/window sharing: Bug 1036653
+// do not enable screensharing before source constraints are finalized: Bug 1033885
+// do not enable screensharing before UX is ready: Bug 1035577
+pref("media.getusermedia.screensharing.enabled", false);
+
 // TextTrack support
 pref("media.webvtt.enabled", true);
 pref("media.webvtt.regions.enabled", false);
 
 // AudioTrack and VideoTrack support
 pref("media.track.enabled", false);
 
 // Whether to enable MediaSource support